[UDFS] Explicitly mention the license (GPLv2).
[reactos.git] / reactos / drivers / filesystems / udfs / udf_info / mount.cpp
1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*
7 Module name:
8
9 mount.cpp
10
11 Abstract:
12
13 This file contains filesystem-specific routines
14 responsible for Mount/Umount
15
16 */
17
18 #include "udf.h"
19
20 /* FIXME*/
21 #define XCHG_DD(a,b) \
22 { \
23 ULONG _temp_; \
24 PULONG _from_, _to_; \
25 _from_ = ((PULONG)&(b)); \
26 _to_ = ((PULONG)&(a)); \
27 _temp_ = *_from_; \
28 *_from_ = *_to_; \
29 *_to_ = _temp_; \
30 }
31
32 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_MOUNT
33
34 OSSTATUS
35 __fastcall
36 UDFSetDstring(
37 IN PUNICODE_STRING UName,
38 IN dstring* Dest,
39 IN uint32 Length
40 );
41
42 #ifndef UDF_READ_ONLY_BUILD
43 /*
44 This routine loads specified bitmap.
45 It is also allocate space if the bitmap is not allocated.
46 */
47 OSSTATUS
48 UDFPrepareXSpaceBitmap(
49 IN PVCB Vcb,
50 IN OUT PSHORT_AD XSpaceBitmap,
51 IN OUT PEXTENT_INFO XSBMExtInfo,
52 IN OUT int8** XSBM,
53 IN OUT uint32* XSl
54 )
55 {
56 uint32 BS, j, LBS;
57 uint32 plen;
58 OSSTATUS status;
59 EXTENT_MAP TmpExt;
60 lb_addr locAddr;
61 int8* _XSBM;
62 uint16 Ident;
63 uint32 ReadBytes;
64 uint32 PartNum;
65
66 if(!(XSpaceBitmap->extLength)) {
67 *XSl = 0;
68 *XSBM = NULL;
69 return STATUS_SUCCESS;
70 }
71
72 PartNum = UDFGetPartNumByPartNdx(Vcb, Vcb->PartitionMaps-1);
73 locAddr.partitionReferenceNum = (uint16)PartNum;
74 plen = UDFPartStart(Vcb, PartNum) + UDFPartLen(Vcb, PartNum);
75
76 BS = Vcb->BlockSize;
77 LBS = Vcb->LBlockSize;
78
79 *XSl = sizeof(SPACE_BITMAP_DESC) + ((plen+7)>>3);
80 _XSBM = (int8*)DbgAllocatePool(NonPagedPool, (*XSl + BS - 1) & ~(BS-1) );
81 *XSBM = _XSBM;
82
83 switch (XSpaceBitmap->extLength >> 30) {
84 case EXTENT_RECORDED_ALLOCATED: {
85 locAddr.logicalBlockNum = XSpaceBitmap->extPosition;
86 *XSl = min(XSpaceBitmap->extLength, *XSl);
87 TmpExt.extLength = XSpaceBitmap->extLength = *XSl;
88 TmpExt.extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
89 if(TmpExt.extLocation == LBA_OUT_OF_EXTENT) {
90 BrutePoint();
91 }
92 XSBMExtInfo->Mapping = UDFExtentToMapping(&TmpExt);
93 XSBMExtInfo->Offset = 0;
94 XSBMExtInfo->Length = *XSl;
95 break;
96 }
97 case EXTENT_NEXT_EXTENT_ALLOCDESC:
98 case EXTENT_NOT_RECORDED_NOT_ALLOCATED: {
99 // allocate space for bitmap
100 if(!OS_SUCCESS(status = UDFAllocFreeExtent(Vcb, *XSl,
101 UDFPartStart(Vcb, PartNum), UDFPartEnd(Vcb, PartNum), XSBMExtInfo, EXTENT_FLAG_ALLOC_SEQUENTIAL) ))
102 return status;
103 if(XSBMExtInfo->Mapping[1].extLength) {
104 KdPrint(("Can't allocate space for Freed Space bitmap\n"));
105 *XSl = 0;
106 } else {
107 *XSl = (uint32)(XSBMExtInfo->Length);
108 XSpaceBitmap->extPosition = UDFPhysLbaToPart(Vcb, PartNum, XSBMExtInfo->Mapping[0].extLocation);
109 }
110 break;
111 }
112 case EXTENT_NOT_RECORDED_ALLOCATED: {
113 // record Alloc-Not-Rec
114 locAddr.logicalBlockNum = XSpaceBitmap->extPosition;
115 *XSl = min((XSpaceBitmap->extLength & UDF_EXTENT_LENGTH_MASK), *XSl);
116 TmpExt.extLength = XSpaceBitmap->extLength = *XSl;
117 TmpExt.extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
118 if(TmpExt.extLocation == LBA_OUT_OF_EXTENT) {
119 BrutePoint();
120 }
121 XSBMExtInfo->Mapping = UDFExtentToMapping(&TmpExt);
122 XSBMExtInfo->Offset = 0;
123 XSBMExtInfo->Length = *XSl;
124 break;
125 }
126 }
127
128 if(!_XSBM) {
129 BrutePoint();
130 return STATUS_INSUFFICIENT_RESOURCES;
131 }
132
133 switch (XSpaceBitmap->extLength >> 30) {
134 case EXTENT_RECORDED_ALLOCATED: {
135 // read descriptor & bitmap
136 if((!OS_SUCCESS(status = UDFReadTagged(Vcb, *XSBM, (j = TmpExt.extLocation),
137 locAddr.logicalBlockNum, &Ident))) ||
138 (Ident != TID_SPACE_BITMAP_DESC) ||
139 (!OS_SUCCESS(status = UDFReadExtent(Vcb, XSBMExtInfo, 0, *XSl, FALSE, *XSBM, &ReadBytes))) ) {
140 if(OS_SUCCESS(status)) {
141 BrutePoint();
142 status = STATUS_FILE_CORRUPT_ERROR;
143 }
144 if(XSBMExtInfo->Mapping) {
145 MyFreePool__(XSBMExtInfo->Mapping);
146 XSBMExtInfo->Mapping = NULL;
147 }
148 DbgFreePool(*XSBM);
149 *XSl = 0;
150 *XSBM = NULL;
151 return status;
152 } else {
153 // BrutePoint();
154 }
155 return STATUS_SUCCESS;
156 }
157 #if 0
158 case EXTENT_NEXT_EXTENT_ALLOCDESC:
159 case EXTENT_NOT_RECORDED_NOT_ALLOCATED:
160 case EXTENT_NOT_RECORDED_ALLOCATED: {
161 break;
162 }
163 #endif
164 }
165
166 PSPACE_BITMAP_DESC XSDesc = (PSPACE_BITMAP_DESC)(*XSBM);
167
168 XSpaceBitmap->extLength = (*XSl + LBS -1) & ~(LBS-1);
169 RtlZeroMemory(*XSBM, *XSl);
170 XSDesc->descTag.tagIdent = TID_SPACE_BITMAP_DESC;
171 UDFSetUpTag(Vcb, &(XSDesc->descTag), 0, XSpaceBitmap->extPosition);
172 XSDesc->numOfBits = plen;
173 XSDesc->numOfBytes = (*XSl)-sizeof(SPACE_BITMAP_DESC);
174
175 return STATUS_SUCCESS;
176 } // end UDFPrepareXSpaceBitmap()
177
178 /*
179 This routine updates Freed & Unallocated space bitmaps
180 */
181 OSSTATUS
182 UDFUpdateXSpaceBitmaps(
183 IN PVCB Vcb,
184 IN uint32 PartNum,
185 IN PPARTITION_HEADER_DESC phd // partition header pointing to Bitmaps
186 )
187 {
188 uint32 i,j,d;
189 uint32 plen, pstart, pend;
190 int8* bad_bm;
191 int8* old_bm;
192 int8* new_bm;
193 int8* fpart_bm;
194 int8* upart_bm;
195 OSSTATUS status, status2;
196 int8* USBM=NULL;
197 int8* FSBM=NULL;
198 uint32 USl, FSl;
199 EXTENT_INFO FSBMExtInfo, USBMExtInfo;
200 lb_addr locAddr;
201 uint32 WrittenBytes;
202
203 UDF_CHECK_BITMAP_RESOURCE(Vcb);
204
205 plen = UDFPartLen(Vcb, PartNum);
206 locAddr.partitionReferenceNum = (uint16)PartNum;
207 // prepare bitmaps for updating
208
209 status = UDFPrepareXSpaceBitmap(Vcb, &(phd->unallocatedSpaceBitmap), &USBMExtInfo, &USBM, &USl);
210 status2 = UDFPrepareXSpaceBitmap(Vcb, &(phd->freedSpaceBitmap), &FSBMExtInfo, &FSBM, &FSl);
211 if(!OS_SUCCESS(status) ||
212 !OS_SUCCESS(status2)) {
213 BrutePoint();
214 }
215
216 pstart = UDFPartStart(Vcb, PartNum);
217 new_bm = Vcb->FSBM_Bitmap;
218 old_bm = Vcb->FSBM_OldBitmap;
219 bad_bm = Vcb->BSBM_Bitmap;
220
221 if((status == STATUS_INSUFFICIENT_RESOURCES) ||
222 (status2 == STATUS_INSUFFICIENT_RESOURCES)) {
223 // try to recover insufficient resources
224 if(USl && USBMExtInfo.Mapping) {
225 USl -= sizeof(SPACE_BITMAP_DESC);
226 status = UDFWriteExtent(Vcb, &USBMExtInfo, sizeof(SPACE_BITMAP_DESC), USl, FALSE, new_bm, &WrittenBytes);
227 #ifdef UDF_DBG
228 } else {
229 KdPrint(("Can't update USBM\n"));
230 #endif // UDF_DBG
231 }
232 if(USBMExtInfo.Mapping) MyFreePool__(USBMExtInfo.Mapping);
233
234 if(FSl && FSBMExtInfo.Mapping) {
235 FSl -= sizeof(SPACE_BITMAP_DESC);
236 status2 = UDFWriteExtent(Vcb, &FSBMExtInfo, sizeof(SPACE_BITMAP_DESC), FSl, FALSE, new_bm, &WrittenBytes);
237 } else {
238 status2 = status;
239 KdPrint(("Can't update FSBM\n"));
240 }
241 if(FSBMExtInfo.Mapping) MyFreePool__(FSBMExtInfo.Mapping);
242 } else {
243 // normal way to record BitMaps
244 if(USBM) upart_bm = USBM + sizeof(SPACE_BITMAP_DESC);
245 if(FSBM) fpart_bm = FSBM + sizeof(SPACE_BITMAP_DESC);
246 pend = min(pstart + plen, Vcb->FSBM_BitCount);
247
248 d=1<<Vcb->LB2B_Bits;
249 // if we have some bad bits, mark corresponding area as BAD
250 if(bad_bm) {
251 for(i=pstart; i<pend; i++) {
252 if(UDFGetBadBit(bad_bm, i)) {
253 // TODO: would be nice to add these blocks to unallocatable space
254 UDFSetUsedBits(new_bm, i & ~(d-1), d);
255 }
256 }
257 }
258 j=0;
259 for(i=pstart; i<pend; i+=d) {
260 if(UDFGetUsedBit(old_bm, i) && UDFGetFreeBit(new_bm, i)) {
261 // sector was deallocated during last session
262 if(USBM) UDFSetFreeBit(upart_bm, j);
263 if(FSBM) UDFSetFreeBit(fpart_bm, j);
264 } else if(UDFGetUsedBit(new_bm, i)) {
265 // allocated
266 if(USBM) UDFSetUsedBit(upart_bm, j);
267 if(FSBM) UDFSetUsedBit(fpart_bm, j);
268 }
269 j++;
270 }
271 // flush updates
272 if(USBM) {
273 status = UDFWriteExtent(Vcb, &USBMExtInfo, 0, USl, FALSE, USBM, &WrittenBytes);
274 DbgFreePool(USBM);
275 MyFreePool__(USBMExtInfo.Mapping);
276 }
277 if(FSBM) {
278 status2 = UDFWriteExtent(Vcb, &FSBMExtInfo, 0, FSl, FALSE, FSBM, &WrittenBytes);
279 DbgFreePool(FSBM);
280 MyFreePool__(FSBMExtInfo.Mapping);
281 } else {
282 status2 = status;
283 }
284 }
285
286 if(!OS_SUCCESS(status))
287 return status;
288 return status2;
289 } // end UDFUpdateXSpaceBitmaps()
290
291 /*
292 This routine updates Partition Desc & associated data structures
293 */
294 OSSTATUS
295 UDFUpdatePartDesc(
296 PVCB Vcb,
297 int8* Buf
298 )
299 {
300 PartitionDesc *p = (PartitionDesc *)Buf;
301 uint32 i; // PartNdx
302 tag* PTag;
303 uint32 WrittenBytes;
304
305 for(i=0; i<Vcb->PartitionMaps; i++)
306 {
307 if((UDFGetPartNumByPartNdx(Vcb,i) == p->partitionNumber) &&
308 (!strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR02) ||
309 !strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR03)))
310 {
311 PPARTITION_HEADER_DESC phd;
312
313 phd = (PPARTITION_HEADER_DESC)(p->partitionContentsUse);
314 #ifdef UDF_DBG
315 if(phd->unallocatedSpaceTable.extLength) {
316 // rebuild unallocatedSpaceTable
317 KdPrint(("unallocatedSpaceTable (part %d)\n", i));
318 }
319 if(phd->freedSpaceTable.extLength) {
320 // rebuild freedSpaceTable
321 KdPrint(("freedSpaceTable (part %d)\n", i));
322 }
323 #endif // UDF_DBG
324 UDFUpdateXSpaceBitmaps(Vcb, p->partitionNumber, phd);
325 PTag = (tag*)Buf;
326 UDFSetUpTag(Vcb, PTag, PTag->descCRCLength, PTag->tagLocation);
327 UDFWriteSectors(Vcb, TRUE, PTag->tagLocation, 1, FALSE, Buf, &WrittenBytes);
328 }
329 }
330 return STATUS_SUCCESS;
331 } // end UDFUpdatePartDesc()
332
333 /*
334 This routine blanks Unalloc Space Desc
335 *//*
336 OSSTATUS
337 UDFUpdateUSpaceDesc(
338 IN PVCB Vcb,
339 int8* Buf
340 )
341 {
342 PUNALLOC_SPACE_DESC usd;
343 uint32 WrittenBytes;
344
345 usd = (PUNALLOC_SPACE_DESC)Buf;
346 usd->numAllocDescs = 0;
347 RtlZeroMemory(Buf+sizeof(UNALLOC_SPACE_DESC), Vcb->BlockSize - sizeof(UNALLOC_SPACE_DESC));
348 UDFSetUpTag(Vcb, &(usd->descTag), 0, usd->descTag.tagLocation);
349 UDFWriteSectors(Vcb, TRUE, usd->descTag.tagLocation, 1, FALSE, Buf, &WrittenBytes);
350 return STATUS_SUCCESS;
351 }*/
352
353 /*
354 update Logical volume integrity descriptor
355 */
356 OSSTATUS
357 UDFUpdateLogicalVolInt(
358 PVCB Vcb,
359 BOOLEAN Close
360 )
361 {
362 OSSTATUS RC = STATUS_SUCCESS;
363 uint32 i, len;
364 uint32 WrittenBytes;
365 // uint32 lvid_count = 0;
366 uint32 pSize;
367 tag* PTag;
368 LogicalVolIntegrityDesc *lvid;
369 LogicalVolIntegrityDescImpUse* LVID_iUse;
370 LogicalVolHeaderDesc* LVID_hd;
371 uint32* partFreeSpace;
372 BOOLEAN equal = FALSE;
373
374 if(Vcb->CDR_Mode)
375 return STATUS_SUCCESS;
376 if(!Vcb->LVid) {
377 return STATUS_UNSUCCESSFUL;
378 }
379
380 KdPrint(("UDF: Updating LVID @%x (%x)\n", Vcb->LVid_loc.extLocation, Vcb->LVid_loc.extLength));
381 len = max(Vcb->LVid_loc.extLength, Vcb->BlockSize);
382 lvid = Vcb->LVid;
383 if(lvid->descTag.tagSerialNum > UDF_LVID_TTL) {
384 // TODO: allocate space for new LVID
385 }
386
387 LVID_iUse = UDFGetLVIDiUse(Vcb);
388
389 if((LVID_iUse->minUDFReadRev == Vcb->minUDFReadRev) &&
390 (LVID_iUse->minUDFReadRev == Vcb->minUDFReadRev) &&
391 (LVID_iUse->maxUDFWriteRev == Vcb->maxUDFWriteRev) &&
392 (LVID_iUse->numFiles == Vcb->numFiles) &&
393 (LVID_iUse->numDirs == Vcb->numDirs))
394 equal = TRUE;
395
396 LVID_iUse->minUDFReadRev = Vcb->minUDFReadRev;
397 LVID_iUse->minUDFWriteRev = Vcb->minUDFWriteRev;
398 LVID_iUse->maxUDFWriteRev = Vcb->maxUDFWriteRev;
399
400 LVID_iUse->numFiles = Vcb->numFiles;
401 LVID_iUse->numDirs = Vcb->numDirs;
402
403 #if 0
404 UDFSetEntityID_imp(&(LVID_iUse->impIdent), UDF_ID_DEVELOPER);
405 #endif
406
407 if(Close){
408 KdPrint(("UDF: Opening LVID\n"));
409 lvid->integrityType = INTEGRITY_TYPE_CLOSE;
410 } else {
411 KdPrint(("UDF: Closing LVID\n"));
412 lvid->integrityType = INTEGRITY_TYPE_OPEN;
413 }
414
415 equal = equal && (Vcb->IntegrityType == lvid->integrityType);
416
417 // update Free Space Table
418 partFreeSpace = (uint32*)(lvid+1);
419 for(i=0; i<lvid->numOfPartitions; i++) {
420 pSize = UDFGetPartFreeSpace(Vcb, i) >> Vcb->LB2B_Bits;
421 equal = equal && (partFreeSpace[i] == pSize);
422 partFreeSpace[i] = pSize;
423 }
424
425 // Update LVID Header Descriptor
426 LVID_hd = (LogicalVolHeaderDesc*)&(lvid->logicalVolContentsUse);
427 equal = equal && (LVID_hd->uniqueID == Vcb->NextUniqueId);
428 LVID_hd->uniqueID = Vcb->NextUniqueId;
429
430 if(equal) {
431 KdPrint(("UDF: equal Ids\n"));
432 return STATUS_SUCCESS;
433 }
434
435 PTag = &(lvid->descTag);
436 lvid->lengthOfImpUse =
437 sizeof(LogicalVolIntegrityDescImpUse);
438 UDFSetUpTag(Vcb, PTag,
439 sizeof(LogicalVolIntegrityDesc) +
440 sizeof(uint32)*2*lvid->numOfPartitions +
441 sizeof(LogicalVolIntegrityDescImpUse),
442 PTag->tagLocation);
443
444 Vcb->IntegrityType = INTEGRITY_TYPE_OPEN; // make happy auto-dirty
445 RC = UDFWriteSectors(Vcb, TRUE, PTag->tagLocation, len >> Vcb->BlockSizeBits, FALSE, (int8*)(lvid), &WrittenBytes);
446 WCacheFlushBlocks__(&(Vcb->FastCache), Vcb, PTag->tagLocation, len >> Vcb->BlockSizeBits);
447 // update it here to prevent recursion
448 Vcb->IntegrityType = lvid->integrityType;
449
450 return RC;
451 } // end UDFUpdateLogicalVolInt()
452
453 /*
454 This routine reads all sparing tables & stores them in contiguos memory
455 space
456 */
457 OSSTATUS
458 UDFUpdateSparingTable(
459 IN PVCB Vcb
460 )
461 {
462 PSPARING_MAP RelocMap;
463 // PSPARING_MAP NewRelocMap;
464 OSSTATUS status = STATUS_SUCCESS;
465 OSSTATUS status2 = STATUS_SUCCESS;
466 uint32 i=0, BC, BC2;
467 PSPARING_TABLE SparTable;
468 uint32 ReadBytes;
469 // uint32 n,m;
470 // BOOLEAN merged;
471 BOOLEAN sorted;
472
473 KdPrint(("UDF: Updating Sparable Part Map:\n"));
474 if(!Vcb->SparingTableModified) return STATUS_SUCCESS;
475 if(!Vcb->SparingTable) return STATUS_SUCCESS;
476
477 BC = (Vcb->SparingTableLength >> Vcb->BlockSizeBits) + 1;
478 SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->BlockSize);
479 if(!SparTable) return STATUS_INSUFFICIENT_RESOURCES;
480 // if a part of Sparing Table is already loaded,
481 // update it with data from another one
482 RelocMap = Vcb->SparingTable;
483 // sort sparing table
484 //merged = FALSE;
485 do {
486 sorted = FALSE;
487 for(i=1;i<Vcb->SparingCount;i++) {
488 if(RelocMap[i-1].origLocation > RelocMap[i].origLocation) {
489 XCHG_DD(RelocMap[i-1].origLocation, RelocMap[i].origLocation);
490 swp_loc:
491 XCHG_DD(RelocMap[i-1].mappedLocation, RelocMap[i].mappedLocation);
492 //merged = TRUE;
493 sorted = TRUE;
494 } else
495 if(RelocMap[i-1].origLocation == SPARING_LOC_AVAILABLE &&
496 RelocMap[i].origLocation == SPARING_LOC_AVAILABLE &&
497 RelocMap[i-1].mappedLocation > RelocMap[i].mappedLocation) {
498 goto swp_loc;
499 }
500 }
501 } while(sorted);
502
503 for(i=0;i<Vcb->SparingCount;i++) {
504 KdPrint((" @%x -> %x \n",
505 RelocMap[i].origLocation, RelocMap[i].mappedLocation));
506 }
507
508 Vcb->SparingTableModified = FALSE;
509 // if(!merged) {
510 // KdPrint((" sparing table unchanged\n"));
511 // MyFreePool__(SparTable);
512 // return STATUS_SUCCESS;
513 // }
514
515 // walk through all available Sparing Tables
516 for(i=0;i<Vcb->SparingTableCount;i++) {
517 // read (next) table
518 KdPrint((" sparing table @%x\n", Vcb->SparingTableLoc[i]));
519 status = UDFReadSectors(Vcb, FALSE, Vcb->SparingTableLoc[i], 1, FALSE, (int8*)SparTable, &ReadBytes);
520 // tag should be set to TID_UNUSED_DESC
521 if(OS_SUCCESS(status) && (SparTable->descTag.tagIdent == TID_UNUSED_DESC)) {
522
523 BC2 = ((sizeof(SPARING_TABLE) +
524 SparTable->reallocationTableLen*sizeof(SparingEntry) +
525 Vcb->BlockSize-1)
526 >> Vcb->BlockSizeBits);
527 if(BC2 > BC) {
528 KdPrint((" sizeSparingTable @%x too long: %x > %x\n",
529 Vcb->SparingTableLoc[i], BC2, BC
530 ));
531 continue;
532 }
533 status = UDFReadSectors(Vcb, FALSE, Vcb->SparingTableLoc[i],
534 BC2, FALSE, (int8*)SparTable, &ReadBytes);
535
536 if(!OS_SUCCESS(status)) {
537 KdPrint((" Error reading sizeSparingTable @%x (%x)\n",
538 Vcb->SparingTableLoc[i], BC2
539 ));
540 continue;
541 }
542
543 BC2 = ((sizeof(SPARING_TABLE) +
544 Vcb->SparingCount*sizeof(SparingEntry) +
545 Vcb->BlockSize-1)
546 >> Vcb->BlockSizeBits);
547 if(BC2 > BC) {
548 KdPrint((" new sizeSparingTable @%x too long: %x > %x\n",
549 Vcb->SparingTableLoc[i], BC2, BC
550 ));
551 continue;
552 }
553
554 SparTable->reallocationTableLen = (USHORT)Vcb->SparingCount;
555 RtlCopyMemory((SparTable+1), RelocMap, Vcb->SparingCount*sizeof(SparingEntry));
556 /*
557 merged = FALSE;
558 NewRelocMap = (PSPARING_MAP)(SparTable+1);
559 for(n=0; n<SparTable->reallocationTableLen; n++) {
560 for(m=0; m<Vcb->SparingCount; m++) {
561 if(RelocMap[m].mappedLocation == NewRelocMap[n].mappedLocation) {
562 if(RelocMap[m].origLocation != NewRelocMap[n].origLocation) {
563 KdPrint((" update @%x (%x) -> @%x (%x)\n",
564 NewRelocMap[m].origLocation, NewRelocMap[m].mappedLocation,
565 RelocMap[m].origLocation, RelocMap[m].mappedLocation));
566 merged = TRUE;
567 }
568 }
569 }
570 }
571 */
572 // if(merged) {
573 KdPrint(("UDF: record updated\n"));
574 status = UDFWriteSectors(Vcb, FALSE, Vcb->SparingTableLoc[i], BC2, FALSE, (int8*)SparTable, &ReadBytes);
575 if(!OS_SUCCESS(status)) {
576 if(!OS_SUCCESS(status2)) {
577 status2 = status;
578 }
579 // }
580 }
581 }
582 }
583 MyFreePool__(SparTable);
584 if(!OS_SUCCESS(status2)) {
585 status = status2;
586 }
587 return status;
588 } // end UDFUpdateSparingTable()
589
590 /*
591 update Logical volume descriptor
592 */
593 OSSTATUS
594 UDFUpdateLogicalVol(
595 IN PVCB Vcb,
596 IN UDF_VDS_RECORD Lba,
597 IN PUNICODE_STRING VolIdent
598 )
599 {
600 LogicalVolDesc* lvd = NULL;
601 #define CUR_IDENT_SZ (sizeof(lvd->logicalVolIdent))
602 dstring CS0[CUR_IDENT_SZ];
603 uint16 ident;
604 uint32 WrittenBytes;
605 OSSTATUS status = STATUS_SUCCESS;
606 // OSSTATUS status2 = STATUS_SUCCESS;
607
608 status = UDFUpdateSparingTable(Vcb);
609
610 if(!(Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_VLABEL)) {
611 goto Err_SetVI;
612 }
613
614 lvd = (LogicalVolDesc*)MyAllocatePool__(NonPagedPool, max(Vcb->BlockSize, sizeof(LogicalVolDesc)) );
615
616 if(!lvd) {
617 status = STATUS_INSUFFICIENT_RESOURCES;
618 goto Err_SetVI;
619 }
620
621 KdPrint(("UDF: Updating LVD @%x (%x)\n", Lba.block, Vcb->BlockSize));
622
623 status = UDFSetDstring(&(Vcb->VolIdent), (dstring*)&CS0, CUR_IDENT_SZ);
624 if(!OS_SUCCESS(status)) {
625 if(status == STATUS_INVALID_PARAMETER) {
626 status = STATUS_INVALID_VOLUME_LABEL;
627 }
628 goto Err_SetVI;
629 }
630
631 if(!Lba.block) {
632 status = STATUS_INVALID_PARAMETER;
633 goto Err_SetVI;
634 }
635 status = UDFReadTagged(Vcb, (int8*)lvd, Lba.block, Lba.block, &ident);
636 if(!OS_SUCCESS(status)) goto Err_SetVI;
637 if(ident != TID_LOGICAL_VOL_DESC) {
638 status = STATUS_FILE_CORRUPT_ERROR;
639 goto Err_SetVI;
640 }
641
642 if(RtlCompareMemory(lvd->logicalVolIdent, CS0, CUR_IDENT_SZ) == CUR_IDENT_SZ) {
643 // no changes
644 KdPrint(("UDF: equal VolIds\n"));
645 status = STATUS_SUCCESS;
646 goto Err_SetVI;
647 }
648 RtlCopyMemory(lvd->logicalVolIdent, CS0, CUR_IDENT_SZ);
649
650 lvd->descTag.tagSerialNum --;
651 UDFSetUpTag(Vcb, (tag*)lvd, lvd->descTag.descCRCLength, Lba.block);
652
653 status = UDFWriteSectors(Vcb, TRUE, Lba.block, 1, FALSE, (int8*)lvd, &WrittenBytes);
654
655 Err_SetVI:
656 if(lvd)
657 MyFreePool__(lvd);
658
659 #undef CUR_IDENT_SZ
660 //#endif //0
661
662 return status;
663 } // end UDFUpdateLogicalVol()
664
665 /*
666 This routine updates volume descriptor sequence
667 */
668 OSSTATUS
669 UDFUpdateVDS(
670 IN PVCB Vcb,
671 IN uint32 block,
672 IN uint32 lastblock,
673 IN uint32 flags
674 )
675 {
676 OSSTATUS status;
677 int8* Buf = (int8*)DbgAllocatePool(NonPagedPool,Vcb->LBlockSize);
678 UDF_VDS_RECORD vds[VDS_POS_LENGTH];
679 uint32 i,j;
680 uint16 ident;
681
682 if (!Buf) return STATUS_INSUFFICIENT_RESOURCES;
683 RtlZeroMemory(vds, sizeof(UDF_VDS_RECORD) * VDS_POS_LENGTH);
684 if(!OS_SUCCESS(status = UDFReadVDS(Vcb, block, lastblock, (PUDF_VDS_RECORD)&vds, Buf))) {
685 DbgFreePool(Buf);
686 return status;
687 }
688
689 /*
690 // update USD (if any)
691 for (i=0; i<VDS_POS_LENGTH; i++) {
692 if (vds[i].block) {
693 status = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident);
694 if(OS_SUCCESS(status) && (i == VDS_POS_PARTITION_DESC)) {
695 // load partition descriptor(s)
696 int8* Buf2 = (int8*)DbgAllocatePool(NonPagedPool,Vcb->BlockSize);
697 if (!Buf2) {
698 DbgFreePool(Buf);
699 return STATUS_INSUFFICIENT_RESOURCES;
700 }
701 for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++) {
702 UDFReadTagged(Vcb,Buf2, j, j, &ident);
703 if (ident == TID_UNALLOC_SPACE_DESC)
704 // This implememtation doesn't support USD ;) recording
705 // So, we'll make'em blank, but record all bitmaps
706 UDFUpdateUSpaceDesc(Vcb,Buf2);
707 }
708 DbgFreePool(Buf2);
709 break;
710 }
711 }
712 }*/
713 for (i=0; i<VDS_POS_LENGTH; i++) {
714 if (vds[i].block) {
715 status = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident);
716 if(!OS_SUCCESS(status))
717 continue;
718 // update XBMs
719 if(i == VDS_POS_PARTITION_DESC) {
720 if(!(flags & 1))
721 continue;
722 // update partition descriptor(s)
723 int8* Buf2 = (int8*)DbgAllocatePool(NonPagedPool,Vcb->BlockSize);
724 if (!Buf2) {
725 DbgFreePool(Buf);
726 return STATUS_INSUFFICIENT_RESOURCES;
727 }
728 UDFUpdatePartDesc(Vcb,Buf);
729 for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++) {
730 UDFReadTagged(Vcb,Buf2, j, j, &ident);
731 if (ident == TID_PARTITION_DESC)
732 UDFUpdatePartDesc(Vcb,Buf2);
733 }
734 DbgFreePool(Buf2);
735 // continue;
736 } else
737 // update Vol Ident Desc
738 if(i == VDS_POS_LOGICAL_VOL_DESC) {
739 status = UDFUpdateLogicalVol(Vcb, vds[VDS_POS_LOGICAL_VOL_DESC], &(Vcb->VolIdent));
740 if(!OS_SUCCESS(status))
741 continue;
742 }
743 }
744 }
745
746 DbgFreePool(Buf);
747 return status;
748 } // end UDFUpdateVDS()
749 #endif //UDF_READ_ONLY_BUILD
750
751 OSSTATUS
752 __fastcall
753 UDFSetDstring(
754 IN PUNICODE_STRING UName,
755 IN dstring* Dest,
756 IN uint32 Length
757 )
758 {
759 uint8* CS0;
760 uint32 len = Length-1;
761
762 UDFCompressUnicode(UName, &CS0, &len);
763 if(!CS0)
764 return STATUS_INSUFFICIENT_RESOURCES;
765 if(len > Length-1) {
766 MyFreePool__(CS0);
767 return STATUS_INVALID_PARAMETER;
768 }
769 RtlCopyMemory(Dest, CS0, len);
770 MyFreePool__(CS0);
771 if(len < Length-1)
772 RtlZeroMemory(Dest+len, Length-1-len);
773 Dest[Length-1] = (uint8)len;
774 return TRUE;
775 } // end UDFSetDstring()
776
777 void
778 __fastcall
779 UDFGetDstring(
780 IN OUT PUNICODE_STRING UName,
781 IN dstring* Dest,
782 IN uint32 Length
783 )
784 {
785 uint32 len = Dest[Length-1];
786
787 UDFDecompressUnicode(UName, Dest, len, NULL);
788 return;
789 } // end UDFGetDstring()
790
791 #ifndef UDF_READ_ONLY_BUILD
792 /*
793 This routine updates Volume Label & some other features stored in
794 VolIdentDesc
795 */
796 OSSTATUS
797 UDFUpdateVolIdent(
798 IN PVCB Vcb,
799 IN UDF_VDS_RECORD Lba,
800 IN PUNICODE_STRING VolIdent
801 )
802 {
803 #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent))
804 PrimaryVolDesc* pvoldesc = (PrimaryVolDesc*)MyAllocatePool__(NonPagedPool, max(Vcb->BlockSize, sizeof(PrimaryVolDesc)) );
805 OSSTATUS status;
806 dstring CS0[CUR_IDENT_SZ];
807 uint16 ident;
808 uint32 WrittenBytes;
809
810 if(!pvoldesc) return STATUS_INSUFFICIENT_RESOURCES;
811
812 KdPrint(("UDF: Updating PVD @%x (%x)\n", Lba.block, Vcb->BlockSize));
813
814 status = UDFSetDstring(&(Vcb->VolIdent), (dstring*)&CS0, CUR_IDENT_SZ);
815 if(!OS_SUCCESS(status)) {
816 if(status == STATUS_INVALID_PARAMETER) {
817 status = STATUS_INVALID_VOLUME_LABEL;
818 }
819 goto Err_SetVI;
820 }
821
822 if(!Lba.block) {
823 status = STATUS_INVALID_PARAMETER;
824 goto Err_SetVI;
825 }
826 status = UDFReadTagged(Vcb, (int8*)pvoldesc, Lba.block, Lba.block, &ident);
827 if(!OS_SUCCESS(status)) goto Err_SetVI;
828 if(ident != TID_PRIMARY_VOL_DESC) {
829 status = STATUS_FILE_CORRUPT_ERROR;
830 goto Err_SetVI;
831 }
832
833 if(RtlCompareMemory(pvoldesc->volIdent, CS0, CUR_IDENT_SZ) == CUR_IDENT_SZ) {
834 // no changes
835 status = STATUS_SUCCESS;
836 goto Err_SetVI;
837 }
838 RtlCopyMemory(pvoldesc->volIdent, CS0, CUR_IDENT_SZ);
839
840 pvoldesc->descTag.tagSerialNum --;
841 UDFSetUpTag(Vcb, (tag*)pvoldesc, pvoldesc->descTag.descCRCLength, Lba.block);
842
843 status = UDFWriteSectors(Vcb, TRUE, Lba.block, 1, FALSE, (int8*)pvoldesc, &WrittenBytes);
844 Err_SetVI:
845 MyFreePool__(pvoldesc);
846 return status;
847
848 #undef CUR_IDENT_SZ
849 } // end UDFUpdateVolIdent()
850 #endif //UDF_READ_ONLY_BUILD
851
852 OSSTATUS
853 UDFUpdateNonAllocated(
854 IN PVCB Vcb
855 )
856 {
857 uint32 PartNum;
858 uint32 i;
859 uint32 plen, pstart, pend;
860 int8* bad_bm;
861 EXTENT_AD Ext;
862 PEXTENT_MAP Map = NULL;
863 PEXTENT_INFO DataLoc;
864
865 KdPrint(("UDFUpdateNonAllocated:\n"));
866 if(!Vcb->NonAllocFileInfo) {
867 return STATUS_SUCCESS;
868 }
869 if(!(bad_bm = Vcb->BSBM_Bitmap)) {
870 return STATUS_SUCCESS;
871 }
872
873 DataLoc = &(Vcb->NonAllocFileInfo->Dloc->DataLoc);
874 ASSERT(!DataLoc->Offset);
875 if(Vcb->NonAllocFileInfo->Dloc->DataLoc.Offset) {
876 KdPrint(("NonAllocFileInfo in IN_ICB mode !!!\n"));
877 return STATUS_SUCCESS;
878 }
879 PartNum = UDFGetPartNumByPhysLba(Vcb, Vcb->NonAllocFileInfo->Dloc->FELoc.Mapping[0].extLocation);
880 pstart = UDFPartStart(Vcb, PartNum);
881 plen = UDFPartLen(Vcb, PartNum);
882 pend = min(pstart + plen, Vcb->FSBM_BitCount);
883
884 //BrutePoint();
885 for(i=pstart; i<pend; i++) {
886 if(!UDFGetBadBit(bad_bm, i))
887 continue;
888 // add BAD blocks to unallocatable space
889 // if the block is already in NonAllocatable, ignore it
890 if(UDFLocateLbaInExtent(Vcb, DataLoc->Mapping, i) != LBA_OUT_OF_EXTENT) {
891 KdPrint(("lba %#x is already in NonAllocFileInfo\n", i));
892 continue;
893 }
894 KdPrint(("add lba %#x to NonAllocFileInfo\n", i));
895 DataLoc->Modified = TRUE;
896 Ext.extLength = Vcb->LBlockSize;
897 // align lba on LogicalBlock boundary
898 Ext.extLocation = i & ~((1<<Vcb->LB2B_Bits) - 1);
899 Map = UDFExtentToMapping(&Ext);
900 DataLoc->Mapping = UDFMergeMappings(DataLoc->Mapping, Map);
901 }
902 UDFPackMapping(Vcb, DataLoc);
903 DataLoc->Length = UDFGetExtentLength(DataLoc->Mapping);
904 UDFFlushFile__(Vcb, Vcb->NonAllocFileInfo);
905
906 // ensure that BAD space is marked as USED
907 UDFMarkSpaceAsXXX(Vcb, 0, &(DataLoc->Mapping[0]), AS_USED); // mark as used
908
909 KdPrint(("UDFUpdateNonAllocated: done\n"));
910 return STATUS_SUCCESS;
911 } // end UDFUpdateNonAllocated()
912
913 /*
914 This routine rebuilds & flushes all system areas
915 */
916 OSSTATUS
917 UDFUmount__(
918 IN PVCB Vcb
919 )
920 {
921 #ifndef UDF_READ_ONLY_BUILD
922 uint32 flags = 0;
923
924 if(((Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) &&
925 !(UDFGlobalData.UDFFlags & UDF_DATA_FLAGS_UNREGISTERED))
926 || !Vcb->Modified)
927 return STATUS_SUCCESS;
928 // prevent discarding metadata
929 Vcb->VCBFlags |= UDF_VCB_ASSUME_ALL_USED;
930 if(Vcb->CDR_Mode) {
931 // flush internal cache
932 if(WCacheGetWriteBlockCount__(&(Vcb->FastCache)) >= (Vcb->WriteBlockSize >> Vcb->BlockSizeBits) )
933 WCacheFlushAll__(&(Vcb->FastCache), Vcb);
934 // record VAT
935 return UDFRecordVAT(Vcb);
936 }
937
938 UDFFlushAllCachedAllocations(Vcb, UDF_PREALLOC_CLASS_FE);
939 UDFFlushAllCachedAllocations(Vcb, UDF_PREALLOC_CLASS_DIR);
940
941 if(Vcb->VerifyOnWrite) {
942 KdPrint(("UDF: Flushing cache for verify\n"));
943 //WCacheFlushAll__(&(Vcb->FastCache), Vcb);
944 WCacheFlushBlocks__(&(Vcb->FastCache), Vcb, 0, Vcb->LastLBA);
945 UDFVFlush(Vcb);
946 }
947
948 // synchronize BAD Block bitmap and NonAllocatable
949 UDFUpdateNonAllocated(Vcb);
950
951 UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE);
952
953 // RAM mode
954 #ifdef UDF_DBG
955 if(!OS_SUCCESS(UDFUpdateVolIdent(Vcb, Vcb->PVolDescAddr, &(Vcb->VolIdent))))
956 KdPrint(("Error updating VolIdent (1)\n"));
957 if(!OS_SUCCESS(UDFUpdateVolIdent(Vcb, Vcb->PVolDescAddr2, &(Vcb->VolIdent))))
958 KdPrint(("Error updating VolIdent (2)\n"));
959 #else
960 UDFUpdateVolIdent(Vcb, Vcb->PVolDescAddr, &(Vcb->VolIdent));
961 UDFUpdateVolIdent(Vcb, Vcb->PVolDescAddr2, &(Vcb->VolIdent));
962 #endif // UDF_DBG
963
964 UDF_CHECK_BITMAP_RESOURCE(Vcb);
965 // check if we should update BM
966 if(Vcb->FSBM_ByteCount == RtlCompareMemory(Vcb->FSBM_Bitmap, Vcb->FSBM_OldBitmap, Vcb->FSBM_ByteCount)) {
967 flags &= ~1;
968 } else {
969 flags |= 1;
970 }
971
972 #ifdef UDF_DBG
973 if(!OS_SUCCESS(UDFUpdateVDS(Vcb, Vcb->VDS1, Vcb->VDS1 + Vcb->VDS1_Len, flags)))
974 KdPrint(("Error updating Main VDS\n"));
975 if(!OS_SUCCESS(UDFUpdateVDS(Vcb, Vcb->VDS2, Vcb->VDS2 + Vcb->VDS2_Len, flags)))
976 KdPrint(("Error updating Reserve VDS\n"));
977 #else
978 UDFUpdateVDS(Vcb, Vcb->VDS1, Vcb->VDS1 + Vcb->VDS1_Len, flags);
979 UDFUpdateVDS(Vcb, Vcb->VDS2, Vcb->VDS2 + Vcb->VDS2_Len, flags);
980 #endif // UDF_DBG
981
982 // Update Integrity Desc if any
983 if(Vcb->LVid && Vcb->origIntegrityType == INTEGRITY_TYPE_CLOSE) {
984 UDFUpdateLogicalVolInt(Vcb, TRUE);
985 }
986
987 if(flags & 1)
988 RtlCopyMemory(Vcb->FSBM_OldBitmap, Vcb->FSBM_Bitmap, Vcb->FSBM_ByteCount);
989
990 //skip_update_bitmap:
991
992 Vcb->VCBFlags &= ~UDF_VCB_ASSUME_ALL_USED;
993
994 UDFReleaseResource(&(Vcb->BitMapResource1));
995 #endif //UDF_READ_ONLY_BUILD
996
997 return STATUS_SUCCESS;
998 } // end UDFUmount__()
999
1000 /*************************************************************************
1001
1002 /*
1003 Find an anchor volume descriptor.
1004 The UDFGetDiskInfoAndVerify() will invoke this routine to find & check
1005 Anchor Volume Descriptors on the target device
1006 */
1007 lba_t
1008 UDFFindAnchor(
1009 PVCB Vcb // Volume control block
1010 )
1011 {
1012 // OSSTATUS RC = STATUS_SUCCESS;
1013
1014 uint16 ident;
1015 uint32 i;
1016 uint32 LastBlock;
1017 OSSTATUS status;
1018 int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
1019 BOOLEAN MRW_candidate;
1020 BOOLEAN IsMRW = (Vcb->MRWStatus != 0);
1021 if(!Buf)
1022 return 0;
1023
1024 KdPrint(("UDFFindAnchor\n"));
1025 // init probable locations...
1026 RtlZeroMemory(&(Vcb->Anchor), sizeof(Vcb->Anchor));
1027 Vcb->Anchor[0] = 256 + Vcb->FirstLBALastSes;
1028 Vcb->Anchor[1] = 512 + Vcb->FirstLBALastSes;
1029 Vcb->Anchor[2] = 256 + Vcb->TrackMap[Vcb->LastTrackNum].FirstLba;
1030 Vcb->Anchor[3] = 512 + Vcb->TrackMap[Vcb->LastTrackNum].FirstLba;
1031 Vcb->Anchor[4] = Vcb->LastLBA - 256;
1032 Vcb->Anchor[5] = Vcb->LastLBA - 256 + 1;
1033 Vcb->Anchor[6] = Vcb->LastLBA - 256 - 2;
1034 // vat locations
1035 Vcb->Anchor[7] = Vcb->LastLBA - 2;
1036 Vcb->Anchor[8] = Vcb->LastLBA;
1037 Vcb->Anchor[9] = Vcb->LastLBA - 512;
1038 // Vcb->Anchor[7] = Vcb->LastLBA - 256 - 7;
1039 // Vcb->Anchor[8] = Vcb->LastLBA - 512 - 2;
1040 // Vcb->Anchor[9] = Vcb->LastLBA - 512 - 7;
1041
1042 LastBlock = 0;
1043 // ... and check them
1044 for (i=0; i<sizeof(Vcb->Anchor)/sizeof(int); i++) {
1045 if(Vcb->Anchor[i] > Vcb->LastLBA)
1046 Vcb->Anchor[i] = 0;
1047 MRW_candidate = FALSE;
1048 if(Vcb->Anchor[i]) {
1049 KdPrint(("check Anchor %x\n", Vcb->Anchor[i]));
1050 if(!OS_SUCCESS(status = UDFReadTagged(Vcb,Buf,
1051 Vcb->Anchor[i], Vcb->Anchor[i], &ident))) {
1052
1053 // Fucking MRW...
1054 if(!IsMRW && (i<2) &&
1055 (Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM)) {
1056 if(OS_SUCCESS(status = UDFReadTagged(Vcb,Buf,
1057 Vcb->Anchor[i]+MRW_DMA_OFFSET, Vcb->Anchor[i], &ident))) {
1058 // do MRW workaround.....
1059 KdPrint(("UDF: looks like we have MRW....\n"));
1060 MRW_candidate = TRUE;
1061 goto MRW_workaround;
1062 }
1063 }
1064
1065 Vcb->Anchor[i] = 0;
1066 if(status == STATUS_NONEXISTENT_SECTOR) {
1067 KdPrint(("UDF: disk seems to be incomplete\n"));
1068 break;
1069 }
1070 } else {
1071 MRW_workaround:
1072 if((ident != TID_ANCHOR_VOL_DESC_PTR) && ((i<6) ||
1073 (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY))) {
1074 Vcb->Anchor[i] = 0;
1075 } else {
1076 KdPrint(("UDF: Found AVD at %x (point %d)\n",Vcb->Anchor[i], i));
1077 if(!LastBlock)
1078 LastBlock = Vcb->LastLBA;
1079 if(MRW_candidate) {
1080 KdPrint(("UDF: looks like we _*really*_ have MRW....\n"));
1081 IsMRW = TRUE;
1082 ASSERT(Vcb->LastReadTrack == 1);
1083 Vcb->TrackMap[Vcb->LastReadTrack].Flags |= TrackMap_FixMRWAddressing;
1084 WCachePurgeAll__(&(Vcb->FastCache), Vcb);
1085 KdPrint(("UDF: MRW on non-MRW drive => ReadOnly"));
1086 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
1087
1088 UDFRegisterFsStructure(Vcb, Vcb->Anchor[i], Vcb->BlockSize);
1089
1090 }
1091 }
1092 }
1093 }
1094 }
1095
1096 KdPrint(("UDF: -----------------\nUDF: Last block %x\n",LastBlock));
1097 MyFreePool__(Buf);
1098 return LastBlock;
1099 } // end UDFFindAnchor()
1100
1101 /*
1102 Look for Volume recognition sequence
1103 */
1104 uint32
1105 UDFFindVRS(
1106 PVCB Vcb
1107 )
1108 {
1109 VolStructDesc *vsd = NULL;
1110 uint32 offset;
1111 uint32 retStat = 0;
1112 uint32 BeginOffset = Vcb->FirstLBA;
1113 OSSTATUS RC;
1114 int8* buffer = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
1115 uint32 ReadBytes;
1116
1117 if(!buffer) return 0;
1118 // Relative to First LBA in Last Session
1119 offset = Vcb->FirstLBA + 0x10;
1120
1121 KdPrint(("UDFFindVRS:\n"));
1122
1123 // Process the sequence (if applicable)
1124 for (;(offset-BeginOffset <=0x20); offset ++) {
1125 // Read a block
1126 RC = UDFReadSectors(Vcb, FALSE, offset, 1, FALSE, buffer, &ReadBytes);
1127 if(!OS_SUCCESS(RC)) continue;
1128
1129 // Look for ISO descriptors
1130 vsd = (VolStructDesc *)(buffer);
1131
1132 if(vsd->stdIdent[0]) {
1133 if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_CD001, STD_ID_LEN))
1134 {
1135 retStat |= VRS_ISO9660_FOUND;
1136 switch (vsd->structType)
1137 {
1138 case 0:
1139 KdPrint(("UDF: ISO9660 Boot Record found\n"));
1140 break;
1141 case 1:
1142 KdPrint(("UDF: ISO9660 Primary Volume Descriptor found\n"));
1143 break;
1144 case 2:
1145 KdPrint(("UDF: ISO9660 Supplementary Volume Descriptor found\n"));
1146 break;
1147 case 3:
1148 KdPrint(("UDF: ISO9660 Volume Partition Descriptor found\n"));
1149 break;
1150 case 255:
1151 KdPrint(("UDF: ISO9660 Volume Descriptor Set Terminator found\n"));
1152 break;
1153 default:
1154 KdPrint(("UDF: ISO9660 VRS (%u) found\n", vsd->structType));
1155 break;
1156 }
1157 }
1158 else if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_BEA01, STD_ID_LEN))
1159 {
1160 KdPrint(("UDF: BEA01 Found\n"));
1161 }
1162 else if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_TEA01, STD_ID_LEN))
1163 {
1164 KdPrint(("UDF: TEA01 Found\n"));
1165 break;
1166 }
1167 else if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_NSR02, STD_ID_LEN))
1168 {
1169 retStat |= VRS_NSR02_FOUND;
1170 KdPrint(("UDF: NSR02 Found\n"));
1171 break;
1172 }
1173 else if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_NSR03, STD_ID_LEN))
1174 {
1175 retStat |= VRS_NSR03_FOUND;
1176 KdPrint(("UDF: NSR03 Found\n"));
1177 break;
1178 }
1179 }
1180 }
1181
1182 MyFreePool__(buffer);
1183
1184 return retStat;
1185 } // end UDFFindVRS()
1186
1187 /*
1188 process Primary volume descriptor
1189 */
1190 void
1191 UDFLoadPVolDesc(
1192 PVCB Vcb,
1193 int8* Buf // pointer to buffer containing PVD
1194 )
1195 {
1196 PrimaryVolDesc *pvoldesc;
1197 // OSSTATUS RC = STATUS_SUCCESS;
1198
1199 pvoldesc = (PrimaryVolDesc *)Buf;
1200 KdPrint(("UDF: PrimaryVolDesc:\n"));
1201 KdPrint(("volDescSeqNum = %d\n", pvoldesc->volDescSeqNum));
1202 KdPrint(("primaryVolDescNum = %d\n", pvoldesc->primaryVolDescNum));
1203 // remember recording time...
1204 Vcb->VolCreationTime = UDFTimeToNT(&(pvoldesc->recordingDateAndTime));
1205 // ...VolIdent...
1206 #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent))
1207 if (Vcb->VolIdent.Buffer) {
1208 MyFreePool__(Vcb->VolIdent.Buffer);
1209 }
1210 UDFGetDstring(&(Vcb->VolIdent), (dstring*)&(pvoldesc->volIdent), CUR_IDENT_SZ);
1211 #undef CUR_IDENT_SZ
1212 KdPrint(("volIdent[] = '%ws'\n", Vcb->VolIdent.Buffer));
1213 #ifdef UDF_DBG
1214 KdPrint(("volSeqNum = %d\n", pvoldesc->volSeqNum));
1215 KdPrint(("maxVolSeqNum = %d\n", pvoldesc->maxVolSeqNum));
1216 KdPrint(("interchangeLvl = %d\n", pvoldesc->interchangeLvl));
1217 KdPrint(("maxInterchangeLvl = %d\n", pvoldesc->maxInterchangeLvl));
1218 KdPrint(("charSetList = %d\n", pvoldesc->charSetList));
1219 KdPrint(("maxCharSetList = %d\n", pvoldesc->maxCharSetList));
1220 // ...& just print VolSetIdent
1221 UNICODE_STRING instr;
1222 #define CUR_IDENT_SZ (sizeof(pvoldesc->volSetIdent))
1223 UDFGetDstring(&instr, (dstring*)&(pvoldesc->volSetIdent), CUR_IDENT_SZ);
1224 #undef CUR_IDENT_SZ
1225 KdPrint(("volSetIdent[] = '%ws'\n", instr.Buffer));
1226 // KdPrint(("maxInterchangeLvl = %d\n", pvoldesc->maxInterchangeLvl));
1227 KdPrint(("flags = %x\n", pvoldesc->flags));
1228 if(instr.Buffer) MyFreePool__(instr.Buffer);
1229 #endif // UDF_DBG
1230 } // end UDFLoadPVolDesc()
1231
1232 /*
1233 load Logical volume integrity descriptor
1234 */
1235 OSSTATUS
1236 UDFLoadLogicalVolInt(
1237 PDEVICE_OBJECT DeviceObject,
1238 PVCB Vcb,
1239 extent_ad loc
1240 )
1241 {
1242 OSSTATUS RC = STATUS_SUCCESS;
1243 uint32 len;
1244 uint32 _ReadBytes;
1245 int8* Buf = NULL;
1246 uint16 ident;
1247 LogicalVolIntegrityDescImpUse* LVID_iUse;
1248 LogicalVolHeaderDesc* LVID_hd;
1249 extent_ad last_loc;
1250 BOOLEAN read_last = FALSE;
1251 uint32 lvid_count = 0;
1252
1253 ASSERT(!Vcb->LVid);
1254 if(Vcb->LVid) {
1255 MyFreePool__(Vcb->LVid);
1256 Vcb->LVid = NULL;
1257 }
1258 // walk through all sectors inside LogicalVolumeIntegrityDesc
1259 while(loc.extLength) {
1260 KdPrint(("UDF: Reading LVID @%x (%x)\n", loc.extLocation, loc.extLength));
1261 len = max(loc.extLength, Vcb->BlockSize);
1262 Buf = (int8*)MyAllocatePool__(NonPagedPool,len);
1263 if(!Buf)
1264 return STATUS_INSUFFICIENT_RESOURCES;
1265 RC = UDFReadTagged(Vcb,Buf, loc.extLocation, loc.extLocation, &ident);
1266 if(!OS_SUCCESS(RC)) {
1267 exit_with_err:
1268 KdPrint(("UDF: Reading LVID @%x (%x) failed.\n", loc.extLocation, loc.extLength));
1269 switch(Vcb->PartitialDamagedVolumeAction) {
1270 case UDF_PART_DAMAGED_RO:
1271 KdPrint(("UDF: Switch to r/o mode.\n"));
1272 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
1273 Vcb->UserFSFlags |= UDF_USER_FS_FLAGS_MEDIA_DEFECT_RO;
1274 RC = STATUS_SUCCESS;
1275 break;
1276 case UDF_PART_DAMAGED_NO:
1277 KdPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n"));
1278 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
1279 //RC = STATUS_WRONG_VOLUME;
1280 break;
1281 case UDF_PART_DAMAGED_RW:
1282 default:
1283 KdPrint(("UDF: Keep r/w mode for your own risk.\n"));
1284 RC = STATUS_SUCCESS;
1285 // asume we have INTEGRITY_TYPE_CLOSE
1286 Vcb->IntegrityType = INTEGRITY_TYPE_CLOSE;
1287 break;
1288 }
1289
1290 MyFreePool__(Buf);
1291 return RC;
1292 }
1293 UDFRegisterFsStructure(Vcb, loc.extLocation, len);
1294 // handle Terminal Entry
1295 if(ident == TID_TERMINAL_ENTRY) {
1296 read_last = TRUE;
1297 MyFreePool__(Buf);
1298 Vcb->LVid = NULL;
1299 loc = last_loc;
1300 continue;
1301 } else
1302 if(ident != TID_LOGICAL_VOL_INTEGRITY_DESC) {
1303 RC = STATUS_DISK_CORRUPT_ERROR;
1304 goto exit_with_err;
1305 }
1306
1307 Vcb->LVid = (LogicalVolIntegrityDesc *)Buf;
1308 RC = UDFReadData(Vcb, TRUE, ((uint64)(loc.extLocation)) << Vcb->BlockSizeBits, len, FALSE, Buf, &_ReadBytes);
1309 // update info
1310 if( !read_last &&
1311 Vcb->LVid->nextIntegrityExt.extLength) {
1312 // go to next LVID
1313 last_loc = loc;
1314 loc = Vcb->LVid->nextIntegrityExt;
1315 Vcb->LVid = NULL;
1316 MyFreePool__(Buf);
1317 lvid_count++;
1318 if(lvid_count > UDF_MAX_LVID_CHAIN_LENGTH) {
1319 RC = STATUS_DISK_CORRUPT_ERROR;
1320 goto exit_with_err;
1321 }
1322 continue;
1323 }
1324 // process last LVID
1325 Vcb->origIntegrityType =
1326 Vcb->IntegrityType = Vcb->LVid->integrityType;
1327 Vcb->LVid_loc = loc;
1328
1329 LVID_iUse = UDFGetLVIDiUse(Vcb);
1330
1331 KdPrint(("UDF: Last LVID:\n"));
1332 KdPrint((" minR: %x\n",LVID_iUse->minUDFReadRev ));
1333 KdPrint((" minW: %x\n",LVID_iUse->minUDFWriteRev));
1334 KdPrint((" maxW: %x\n",LVID_iUse->maxUDFWriteRev));
1335 KdPrint((" Type: %s\n",!Vcb->IntegrityType ? "Open" : "Close"));
1336
1337 Vcb->minUDFReadRev = LVID_iUse->minUDFReadRev;
1338 Vcb->minUDFWriteRev = LVID_iUse->minUDFWriteRev;
1339 Vcb->maxUDFWriteRev = LVID_iUse->maxUDFWriteRev;
1340
1341 Vcb->numFiles = LVID_iUse->numFiles;
1342 Vcb->numDirs = LVID_iUse->numDirs;
1343 KdPrint((" nFiles: %x\n",Vcb->numFiles ));
1344 KdPrint((" nDirs: %x\n",Vcb->numDirs ));
1345
1346 // Check if we can understand this format
1347 if(Vcb->minUDFReadRev > UDF_MAX_READ_REVISION)
1348 RC = STATUS_UNRECOGNIZED_VOLUME;
1349 // Check if we know how to write here
1350 if(Vcb->minUDFWriteRev > UDF_MAX_WRITE_REVISION) {
1351 KdPrint((" Target FS requires: %x Revision => ReadOnly\n",Vcb->minUDFWriteRev));
1352 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
1353 Vcb->UserFSFlags |= UDF_USER_FS_FLAGS_NEW_FS_RO;
1354 }
1355
1356 LVID_hd = (LogicalVolHeaderDesc*)&(Vcb->LVid->logicalVolContentsUse);
1357 Vcb->NextUniqueId = LVID_hd->uniqueID;
1358 KdPrint((" Next FID: %x\n",Vcb->NextUniqueId));
1359
1360 break;
1361 }
1362
1363 return RC;
1364 } // end UDFLoadLogicalVolInt()
1365
1366
1367 /*
1368 load Logical volume descriptor
1369 */
1370 OSSTATUS
1371 UDFLoadLogicalVol(
1372 PDEVICE_OBJECT DeviceObject,
1373 PVCB Vcb,
1374 int8* Buf,
1375 lb_addr *fileset
1376 )
1377 {
1378 LogicalVolDesc *lvd = (LogicalVolDesc *)Buf;
1379 uint16 i, offset;
1380 uint8 type;
1381 OSSTATUS status = STATUS_SUCCESS;
1382 KdPrint(("UDF: LogicalVolDesc\n"));
1383 // Validate partition map counter
1384 if(!(Vcb->Partitions)) {
1385 Vcb->PartitionMaps = lvd->numPartitionMaps;
1386 Vcb->Partitions = (PUDFPartMap)MyAllocatePool__(NonPagedPool, sizeof(UDFPartMap) * Vcb->PartitionMaps );
1387 if(!Vcb->Partitions)
1388 return STATUS_INSUFFICIENT_RESOURCES;
1389 } else {
1390 if(Vcb->PartitionMaps != lvd->numPartitionMaps)
1391 return STATUS_DISK_CORRUPT_ERROR;
1392 }
1393 KdPrint(("UDF: volDescSeqNum = %x\n", lvd->volDescSeqNum));
1394 // Get logical block size (may be different from physical)
1395 Vcb->LBlockSize = lvd->logicalBlockSize;
1396 // Get current UDF revision
1397 // Get Read-Only flags
1398 UDFReadEntityID_Domain(Vcb, &(lvd->domainIdent));
1399
1400 if(Vcb->LBlockSize < Vcb->BlockSize)
1401 return STATUS_DISK_CORRUPT_ERROR;
1402 switch(Vcb->LBlockSize) {
1403 case 512: Vcb->LBlockSizeBits = 9; break;
1404 case 1024: Vcb->LBlockSizeBits = 10; break;
1405 case 2048: Vcb->LBlockSizeBits = 11; break;
1406 case 4096: Vcb->LBlockSizeBits = 12; break;
1407 case 8192: Vcb->LBlockSizeBits = 13; break;
1408 case 16384: Vcb->LBlockSizeBits = 14; break;
1409 case 32768: Vcb->LBlockSizeBits = 15; break;
1410 case 65536: Vcb->LBlockSizeBits = 16; break;
1411 default:
1412 KdPrint(("UDF: Bad block size (%ld)\n", Vcb->LBlockSize));
1413 return STATUS_DISK_CORRUPT_ERROR;
1414 }
1415 KdPrint(("UDF: logical block size (%ld)\n", Vcb->LBlockSize));
1416 Vcb->LB2B_Bits = Vcb->LBlockSizeBits - Vcb->BlockSizeBits;
1417 KdPrint(("UDF: mapTableLength = %x\n", lvd->mapTableLength));
1418 KdPrint(("UDF: numPartitionMaps = %x\n", lvd->numPartitionMaps));
1419 // walk through all available part maps
1420 for (i=0,offset=0;
1421 i<Vcb->PartitionMaps && offset<lvd->mapTableLength;
1422 i++,offset+=((GenericPartitionMap *)( ((uint8*)(lvd+1))+offset) )->partitionMapLength)
1423 {
1424 GenericPartitionMap* gpm = (GenericPartitionMap *)(((uint8*)(lvd+1))+offset);
1425 type = gpm->partitionMapType;
1426 KdPrint(("Partition (%d) type %x, len %x\n", i, type, gpm->partitionMapLength));
1427 if(type == PARTITION_MAP_TYPE_1)
1428 {
1429 GenericPartitionMap1 *gpm1 = (GenericPartitionMap1 *)(((uint8*)(lvd+1))+offset);
1430
1431 Vcb->Partitions[i].PartitionType = UDF_TYPE1_MAP15;
1432 Vcb->Partitions[i].VolumeSeqNum = gpm1->volSeqNum;
1433 Vcb->Partitions[i].PartitionNum = gpm1->partitionNum;
1434 status = STATUS_SUCCESS;
1435 }
1436 else if(type == PARTITION_MAP_TYPE_2)
1437 {
1438 UdfPartitionMap2* upm2 = (UdfPartitionMap2 *)(((uint8*)(lvd+1))+offset);
1439 if(!strncmp((int8*)&(upm2->partIdent.ident), UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)))
1440 {
1441 UDFIdentSuffix* udfis =
1442 (UDFIdentSuffix*)&(upm2->partIdent.identSuffix);
1443
1444 if( (udfis->currentRev == 0x0150)/* ||
1445 (Vcb->CurrentUDFRev == 0x0150)*/ ) {
1446 KdPrint(("Found VAT 1.50\n"));
1447 Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP15;
1448 } else
1449 if( (udfis->currentRev == 0x0200) ||
1450 (udfis->currentRev == 0x0201) /*||
1451 (Vcb->CurrentUDFRev == 0x0200) ||
1452 (Vcb->CurrentUDFRev == 0x0201)*/ ) {
1453 KdPrint(("Found VAT 2.00\n"));
1454 Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP20;
1455 }
1456 status = STATUS_SUCCESS;
1457 }
1458 else if(!strncmp((int8*)&(upm2->partIdent.ident), UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE)))
1459 {
1460 KdPrint(("Load sparing table\n"));
1461 PSPARABLE_PARTITION_MAP spm = (PSPARABLE_PARTITION_MAP)(((uint8*)(lvd+1))+offset);
1462 Vcb->Partitions[i].PartitionType = UDF_SPARABLE_MAP15;
1463 status = UDFLoadSparingTable(Vcb, spm);
1464 }
1465 else if(!strncmp((int8*)&(upm2->partIdent.ident), UDF_ID_METADATA, strlen(UDF_ID_METADATA)))
1466 {
1467 KdPrint(("Found metadata partition\n"));
1468 // PMETADATA_PARTITION_MAP mpm = (PMETADATA_PARTITION_MAP)(((uint8*)(lvd+1))+offset);
1469 Vcb->Partitions[i].PartitionType = UDF_METADATA_MAP25;
1470 //status = UDFLoadSparingTable(Vcb, spm);
1471 }
1472 else
1473 {
1474 KdPrint(("Unknown ident: %s\n", upm2->partIdent.ident));
1475 continue;
1476 }
1477 Vcb->Partitions[i].VolumeSeqNum = upm2->volSeqNum;
1478 Vcb->Partitions[i].PartitionNum = upm2->partitionNum;
1479 }
1480 }
1481
1482 if(fileset) {
1483 // remember FileSet location
1484 long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]);
1485 *fileset = (la->extLocation);
1486 KdPrint(("FileSet found in LogicalVolDesc at block=%x, partition=%d\n",
1487 fileset->logicalBlockNum,
1488 fileset->partitionReferenceNum));
1489 }
1490 if(OS_SUCCESS(status)) {
1491 // load Integrity Desc if any
1492 if(lvd->integritySeqExt.extLength)
1493 status = UDFLoadLogicalVolInt(DeviceObject,Vcb,lvd->integritySeqExt);
1494 }
1495 return status;
1496 } // end UDFLoadLogicalVol()
1497
1498 OSSTATUS
1499 UDFLoadBogusLogicalVol(
1500 PDEVICE_OBJECT DeviceObject,
1501 PVCB Vcb,
1502 int8* Buf,
1503 lb_addr *fileset
1504 )
1505 {
1506 // LogicalVolDesc *lvd = (LogicalVolDesc *)Buf;
1507 KdPrint(("UDF: Bogus LogicalVolDesc\n"));
1508 // Validate partition map counter
1509 if(!(Vcb->Partitions)) {
1510 Vcb->PartitionMaps = 1;
1511 Vcb->Partitions = (PUDFPartMap)MyAllocatePool__(NonPagedPool, sizeof(UDFPartMap) * Vcb->PartitionMaps );
1512 if(!Vcb->Partitions)
1513 return STATUS_INSUFFICIENT_RESOURCES;
1514 } else {
1515 if(Vcb->PartitionMaps != 1)
1516 return STATUS_DISK_CORRUPT_ERROR;
1517 }
1518 KdPrint(("UDF: volDescSeqNum = %x\n", 0));
1519 // Get logical block size (may be different from physical)
1520 Vcb->LBlockSize = 2048;
1521 // Get current UDF revision
1522 // Get Read-Only flags
1523 // UDFReadEntityID_Domain(Vcb, &(lvd->domainIdent));
1524
1525 if(Vcb->LBlockSize < Vcb->BlockSize)
1526 return STATUS_DISK_CORRUPT_ERROR;
1527 Vcb->LBlockSizeBits = 11;
1528 KdPrint(("UDF: logical block size (%ld)\n", Vcb->LBlockSize));
1529 Vcb->LB2B_Bits = Vcb->LBlockSizeBits - Vcb->BlockSizeBits;
1530 KdPrint(("UDF: mapTableLength = %x\n", 0));
1531 KdPrint(("UDF: numPartitionMaps = %x\n", 0));
1532
1533 // if(CDRW) {
1534
1535 Vcb->Partitions[0].PartitionType = UDF_TYPE1_MAP15;
1536 Vcb->Partitions[0].VolumeSeqNum = 0;
1537 Vcb->Partitions[0].PartitionNum = 0;
1538
1539 /* } else if(CDR)
1540 if()
1541 KdPrint(("Found VAT 1.50\n"));
1542 Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP15;
1543 } else
1544 KdPrint(("Found VAT 2.00\n"));
1545 Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP20;
1546 }
1547 }
1548 }
1549 */
1550 if(fileset) {
1551 // remember FileSet location
1552 // long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]);
1553 fileset->logicalBlockNum = 0;
1554 fileset->partitionReferenceNum = 0;
1555 KdPrint(("FileSet found in LogicalVolDesc at block=%x, partition=%d\n",
1556 fileset->logicalBlockNum,
1557 fileset->partitionReferenceNum));
1558 }
1559 return STATUS_SUCCESS;
1560 } // end UDFLoadBogusLogicalVol()
1561
1562 /*
1563 This routine adds given Bitmap to existing one
1564 */
1565 OSSTATUS
1566 UDFAddXSpaceBitmap(
1567 IN PVCB Vcb,
1568 IN uint32 PartNum,
1569 IN PSHORT_AD bm,
1570 IN ULONG bm_type
1571 )
1572 {
1573 int8* tmp;
1574 int8* tmp_bm;
1575 uint32 i, lim, j, lba, l, lim2, l2, k;
1576 lb_addr locAddr;
1577 OSSTATUS status;
1578 uint16 Ident;
1579 uint32 flags;
1580 uint32 Length;
1581 uint32 ReadBytes;
1582 BOOLEAN bit_set;
1583
1584 UDF_CHECK_BITMAP_RESOURCE(Vcb);
1585 KdPrint(("UDFAddXSpaceBitmap: at block=%x, partition=%d\n",
1586 bm->extPosition,
1587 PartNum));
1588
1589 if(!(Length = (bm->extLength & UDF_EXTENT_LENGTH_MASK))) return STATUS_SUCCESS;
1590 i=UDFPartStart(Vcb, PartNum);
1591 flags = bm->extLength >> 30;
1592 if(!flags /*|| flags == EXTENT_NOT_RECORDED_ALLOCATED*/) {
1593 tmp = (int8*)DbgAllocatePool(NonPagedPool, max(Length, Vcb->BlockSize));
1594 if(!tmp) return STATUS_INSUFFICIENT_RESOURCES;
1595 locAddr.partitionReferenceNum = (uint16)PartNum;
1596 locAddr.logicalBlockNum = bm->extPosition;
1597 // read header of the Bitmap
1598 if(!OS_SUCCESS(status = UDFReadTagged(Vcb, tmp, lba = UDFPartLbaToPhys(Vcb, &(locAddr)),
1599 locAddr.logicalBlockNum, &Ident)) ) {
1600 err_addxsbm_1:
1601 DbgFreePool(tmp);
1602 return status;
1603 }
1604 if(Ident != TID_SPACE_BITMAP_DESC) {
1605 status = STATUS_DISK_CORRUPT_ERROR;
1606 goto err_addxsbm_1;
1607 }
1608 UDFRegisterFsStructure(Vcb, lba, Vcb->BlockSize);
1609 // read the whole Bitmap
1610 if(!OS_SUCCESS(status = UDFReadData(Vcb, FALSE, ((uint64)lba)<<Vcb->BlockSizeBits, Length, FALSE, tmp, &ReadBytes)))
1611 goto err_addxsbm_1;
1612 UDFRegisterFsStructure(Vcb, lba, Length);
1613 lim = min(i + ((lim2 = ((PSPACE_BITMAP_DESC)tmp)->numOfBits) << Vcb->LB2B_Bits), Vcb->FSBM_BitCount);
1614 tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1615 j = 0;
1616 for(;(l = UDFGetBitmapLen((uint32*)tmp_bm, j, lim2)) && (i<lim);) {
1617 // expand LBlocks to Sectors...
1618 l2 = l << Vcb->LB2B_Bits;
1619 // ...and mark them
1620 if(bm_type == UDF_FSPACE_BM) {
1621 bit_set = UDFGetFreeBit(tmp_bm, j);
1622 for(k=0;(k<l2) && (i<lim);k++) {
1623 if(bit_set) {
1624 // FREE block
1625 UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1626 UDFSetFreeBitOwner(Vcb, i);
1627 UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1628 } else {
1629 // USED block
1630 UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1631 }
1632 i++;
1633 }
1634 } else {
1635 bit_set = UDFGetZeroBit(tmp_bm, j);
1636 for(k=0;(k<l2) && (i<lim);k++) {
1637 if(bit_set) {
1638 // ZERO block
1639 UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1640 } else {
1641 // DATA block
1642 UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1643 }
1644 i++;
1645 }
1646 }
1647 j += l;
1648 }
1649 DbgFreePool(tmp);
1650 /* } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1651 i=Vcb->Partitions[PartNum].PartitionRoot;
1652 lim = i + Vcb->Partitions[PartNum].PartitionLen;
1653 for(;i<lim;i++) {
1654 UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1655 }*/
1656 }
1657 return STATUS_SUCCESS;
1658 } // end UDFAddXSpaceBitmap()
1659
1660 /*
1661 This routine adds given Bitmap to existing one
1662 */
1663 OSSTATUS
1664 UDFVerifyXSpaceBitmap(
1665 IN PVCB Vcb,
1666 IN uint32 PartNum,
1667 IN PSHORT_AD bm,
1668 IN ULONG bm_type
1669 )
1670 {
1671 int8* tmp;
1672 int8* tmp_bm;
1673 // uint32 i, lim, j, lba, l, lim2, l2, k;
1674 uint32 i, lim, j, lba, lim2;
1675 lb_addr locAddr;
1676 OSSTATUS status;
1677 uint16 Ident;
1678 uint32 flags;
1679 uint32 Length;
1680 uint32 ReadBytes;
1681 // BOOLEAN bit_set;
1682
1683 UDF_CHECK_BITMAP_RESOURCE(Vcb);
1684
1685 KdPrint((" UDFVerifyXSpaceBitmap: part %x\n", PartNum));
1686
1687 if(!(Length = (bm->extLength & UDF_EXTENT_LENGTH_MASK))) return STATUS_SUCCESS;
1688 i=UDFPartStart(Vcb, PartNum);
1689 flags = bm->extLength >> 30;
1690 if(!flags /*|| flags == EXTENT_NOT_RECORDED_ALLOCATED*/) {
1691 tmp = (int8*)DbgAllocatePool(NonPagedPool, max(Length, Vcb->BlockSize));
1692 if(!tmp) return STATUS_INSUFFICIENT_RESOURCES;
1693 locAddr.partitionReferenceNum = (uint16)PartNum;
1694 locAddr.logicalBlockNum = bm->extPosition;
1695 // read header of the Bitmap
1696 if(!OS_SUCCESS(status = UDFReadTagged(Vcb, tmp, lba = UDFPartLbaToPhys(Vcb, &(locAddr)),
1697 locAddr.logicalBlockNum, &Ident)) ) {
1698 err_vfyxsbm_1:
1699 DbgFreePool(tmp);
1700 return status;
1701 }
1702 KdPrint((" BM Lba %x\n", lba));
1703 if(Ident != TID_SPACE_BITMAP_DESC) {
1704 status = STATUS_DISK_CORRUPT_ERROR;
1705 goto err_vfyxsbm_1;
1706 }
1707 // read the whole Bitmap
1708 if(!OS_SUCCESS(status = UDFReadData(Vcb, FALSE, ((uint64)lba)<<Vcb->BlockSizeBits, Length, FALSE, tmp, &ReadBytes)))
1709 goto err_vfyxsbm_1;
1710 UDFRegisterFsStructure(Vcb, lba, Length);
1711 lim = min(i + ((lim2 = ((PSPACE_BITMAP_DESC)tmp)->numOfBits) << Vcb->LB2B_Bits), Vcb->FSBM_BitCount);
1712 tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1713 j = 0;
1714 /* for(;(l = UDFGetBitmapLen((uint32*)tmp_bm, j, lim2)) && (i<lim);) {
1715 // expand LBlocks to Sectors...
1716 l2 = l << Vcb->LB2B_Bits;
1717 // ...and mark them
1718 if(bm_type == UDF_FSPACE_BM) {
1719 bit_set = UDFGetFreeBit(tmp_bm, j);
1720 for(k=0;(k<l2) && (i<lim);k++) {
1721 if(bit_set) {
1722 // FREE block
1723 UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1724 UDFSetFreeBitOwner(Vcb, i);
1725 UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1726 } else {
1727 // USED block
1728 UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1729 }
1730 i++;
1731 }
1732 } else {
1733 bit_set = UDFGetZeroBit(tmp_bm, j);
1734 for(k=0;(k<l2) && (i<lim);k++) {
1735 if(bit_set) {
1736 // ZERO block
1737 UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1738 } else {
1739 // DATA block
1740 UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1741 }
1742 i++;
1743 }
1744 }
1745 j += l;
1746 }*/
1747 DbgFreePool(tmp);
1748 /* } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1749 i=Vcb->Partitions[PartNum].PartitionRoot;
1750 lim = i + Vcb->Partitions[PartNum].PartitionLen;
1751 for(;i<lim;i++) {
1752 UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1753 }*/
1754 }
1755 return STATUS_SUCCESS;
1756 } // end UDFVerifyXSpaceBitmap()
1757
1758 /*
1759 This routine subtracts given Bitmap to existing one
1760 */
1761 /*OSSTATUS
1762 UDFDelXSpaceBitmap(
1763 IN PVCB Vcb,
1764 IN uint32 PartNum,
1765 IN PSHORT_AD bm
1766 )
1767 {
1768 int8* tmp, tmp_bm;
1769 uint32 i, lim, j;
1770 lb_addr locAddr;
1771 OSSTATUS status;
1772 uint16 Ident;
1773 uint32 flags;
1774 uint32 Length;
1775 uint32 ReadBytes;
1776
1777 if(!(Length = (bm->extLength & UDF_EXTENT_LENGTH_MASK))) return STATUS_SUCCESS;
1778 i=0;
1779 flags = bm->extLength >> 30;
1780 if(!flags || flags == EXTENT_NOT_RECORDED_ALLOCATED) {
1781 tmp = (int8*)MyAllocatePool__(NonPagedPool, Length);
1782 if(!tmp) return STATUS_INSUFFICIENT_RESOURCES;
1783 locAddr.partitionReferenceNum = (uint16)PartNum;
1784 locAddr.logicalBlockNum = bm->extPosition;
1785 if((!OS_SUCCESS(status = UDFReadTagged(Vcb, tmp, (j = UDFPartLbaToPhys(Vcb, &(locAddr))),
1786 locAddr.logicalBlockNum, &Ident))) ||
1787 (Ident != TID_SPACE_BITMAP_DESC) ) {
1788 MyFreePool__(tmp);
1789 return status;
1790 }
1791 if(!OS_SUCCESS(status = UDFReadData(Vcb, FALSE, ((uint64)j)<<Vcb->BlockSizeBits, Length, FALSE, tmp, &ReadBytes))) {
1792 MyFreePool__(tmp);
1793 return status;
1794 }
1795 lim = i + ((PSPACE_BITMAP_DESC)tmp)->numOfBits;
1796 tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1797 j = 0;
1798 for(;i<lim;i++) {
1799 if(UDFGetUsedBit(tmp_bm, j)) UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1800 j++;
1801 }
1802 MyFreePool__(tmp);
1803 // } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1804 // i=Vcb->Partitions[PartNum].PartitionRoot;
1805 // lim = i + Vcb->Partitions[PartNum].PartitionLen;
1806 // for(;i<lim;i++) {
1807 // UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1808 // }
1809 }
1810 return STATUS_SUCCESS;
1811 } // end UDFDelXSpaceBitmap() */
1812
1813 /*
1814 This routine verifues FreeSpaceBitmap (internal) according to media
1815 parameters & input data
1816 */
1817 OSSTATUS
1818 UDFVerifyFreeSpaceBitmap(
1819 IN PVCB Vcb,
1820 IN uint32 PartNdx,
1821 IN PPARTITION_HEADER_DESC phd, // partition header pointing to Bitmaps
1822 IN uint32 Lba // UnallocSpaceDesc
1823 )
1824 {
1825 OSSTATUS status;
1826 uint32 i, l;
1827 uint16 Ident;
1828 int8* AllocDesc;
1829 PEXTENT_MAP Extent;
1830 lb_addr locAddr;
1831 uint32 PartNum;
1832
1833 PartNum = UDFGetPartNumByPartNdx(Vcb, PartNdx);
1834
1835 KdPrint(("UDFVerifyFreeSpaceBitmap:\n"));
1836 // read info for partition header (if any)
1837 if(phd) {
1838 // read unallocated Bitmap
1839 if(!OS_SUCCESS(status = UDFVerifyXSpaceBitmap(Vcb, PartNum, &(phd->unallocatedSpaceBitmap), UDF_FSPACE_BM)))
1840 return status;
1841 // read freed Bitmap
1842 if(!OS_SUCCESS(status = UDFVerifyXSpaceBitmap(Vcb, PartNum, &(phd->freedSpaceBitmap), UDF_ZSPACE_BM)))
1843 return status;
1844 }
1845 // read UnallocatedSpaceDesc & convert to Bitmap
1846 if(Lba) {
1847 KdPrint((" Lba @%x\n", Lba));
1848 if(!(AllocDesc = (int8*)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize + sizeof(EXTENT_AD) )))
1849 return STATUS_INSUFFICIENT_RESOURCES;
1850 RtlZeroMemory(((int8*)AllocDesc) + Vcb->LBlockSize, sizeof(EXTENT_AD));
1851 if(!OS_SUCCESS(status = UDFReadTagged(Vcb, AllocDesc, Lba, Lba, &Ident)) ||
1852 !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, l = (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) {
1853 MyFreePool__(AllocDesc);
1854 return status;
1855 }
1856 UDFRegisterFsStructure(Vcb, Lba, Vcb->BlockSize);
1857 RtlCopyMemory((int8*)Extent, AllocDesc+sizeof(UNALLOC_SPACE_DESC), (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) );
1858 locAddr.partitionReferenceNum = (uint16)PartNum;
1859 // read extent is recorded with relative addresses
1860 // so, we should convert it to suitable form
1861 for(i=0; Extent[i].extLength; i++) {
1862 locAddr.logicalBlockNum = Extent[i].extLocation;
1863 Extent[i].extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
1864 if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) {
1865 BrutePoint();
1866 MyFreePool__(AllocDesc);
1867 return STATUS_DISK_CORRUPT_ERROR;
1868 }
1869 if((Extent[i].extLocation >> 30) == EXTENT_NEXT_EXTENT_ALLOCDESC) {
1870 // load continuation
1871 Lba = Extent[i].extLocation & UDF_EXTENT_LENGTH_MASK;
1872 if(!OS_SUCCESS(status = UDFReadTagged(Vcb, AllocDesc, Lba, Lba, &Ident)) ||
1873 !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) {
1874 MyFreePool__(AllocDesc);
1875 return status;
1876 }
1877 if(Ident == TID_UNALLOC_SPACE_DESC) {
1878 UDFRegisterFsStructure(Vcb, Lba, Vcb->BlockSize);
1879 if(!(l = MyReallocPool__((int8*)Extent, l, (int8**)&Extent, i*sizeof(EXTENT_MAP)))) {
1880 MyFreePool__(Extent);
1881 MyFreePool__(AllocDesc);
1882 return STATUS_INSUFFICIENT_RESOURCES;
1883 }
1884 Extent[i].extLength =
1885 Extent[i].extLocation = 0;
1886 Extent = UDFMergeMappings(Extent, (PEXTENT_MAP)(AllocDesc+sizeof(UNALLOC_SPACE_DESC)) );
1887 #ifdef UDF_DBG
1888 } else {
1889 KdPrint(("Broken unallocated space descriptor sequence\n"));
1890 #endif // UDF_DBG
1891 }
1892 }
1893 }
1894 // UDFMarkSpaceAsXXX(Vcb, (-1), Extent, AS_USED); // mark as used
1895 MyFreePool__(Extent);
1896 MyFreePool__(AllocDesc);
1897 status = STATUS_SUCCESS;
1898 }
1899 return status;
1900 } // end UDFBuildFreeSpaceBitmap()
1901
1902 /*
1903 This routine builds FreeSpaceBitmap (internal) according to media
1904 parameters & input data
1905 */
1906 OSSTATUS
1907 UDFBuildFreeSpaceBitmap(
1908 IN PVCB Vcb,
1909 IN uint32 PartNdx,
1910 IN PPARTITION_HEADER_DESC phd, // partition header pointing to Bitmaps
1911 IN uint32 Lba // UnallocSpaceDesc
1912 )
1913 {
1914 OSSTATUS status;
1915 uint32 i, l;
1916 uint16 Ident;
1917 int8* AllocDesc;
1918 PEXTENT_MAP Extent;
1919 lb_addr locAddr;
1920 uint32 PartNum;
1921
1922 PartNum = UDFGetPartNumByPartNdx(Vcb, PartNdx);
1923 if(!(Vcb->FSBM_Bitmap)) {
1924 // init Bitmap buffer if necessary
1925 Vcb->FSBM_Bitmap = (int8*)DbgAllocatePool(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3) );
1926 if(!(Vcb->FSBM_Bitmap)) return STATUS_INSUFFICIENT_RESOURCES;
1927
1928 Vcb->ZSBM_Bitmap = (int8*)DbgAllocatePool(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3) );
1929 if(!(Vcb->ZSBM_Bitmap)) {
1930 #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1931 free_fsbm:
1932 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1933 MyFreePool__(Vcb->FSBM_Bitmap);
1934 Vcb->FSBM_Bitmap = NULL;
1935 return STATUS_INSUFFICIENT_RESOURCES;
1936 }
1937
1938 RtlZeroMemory(Vcb->FSBM_Bitmap, i);
1939 RtlZeroMemory(Vcb->ZSBM_Bitmap, i);
1940 #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1941 Vcb->FSBM_Bitmap_owners = (uint32*)DbgAllocatePool(NonPagedPool, (Vcb->LastPossibleLBA+1)*sizeof(uint32));
1942 if(!(Vcb->FSBM_Bitmap_owners)) {
1943 MyFreePool__(Vcb->ZSBM_Bitmap);
1944 Vcb->ZSBM_Bitmap = NULL;
1945 goto free_fsbm;
1946 }
1947 RtlFillMemory(Vcb->FSBM_Bitmap_owners, (Vcb->LastPossibleLBA+1)*sizeof(uint32), 0xff);
1948 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1949 Vcb->FSBM_ByteCount = i;
1950 Vcb->FSBM_BitCount = Vcb->LastPossibleLBA+1;
1951 }
1952 // read info for partition header (if any)
1953 if(phd) {
1954 // read unallocated Bitmap
1955 if(!OS_SUCCESS(status = UDFAddXSpaceBitmap(Vcb, PartNum, &(phd->unallocatedSpaceBitmap), UDF_FSPACE_BM)))
1956 return status;
1957 // read freed Bitmap
1958 if(!OS_SUCCESS(status = UDFAddXSpaceBitmap(Vcb, PartNum, &(phd->freedSpaceBitmap), UDF_ZSPACE_BM)))
1959 return status;
1960 }
1961 // read UnallocatedSpaceDesc & convert to Bitmap
1962 if(Lba) {
1963 if(!(AllocDesc = (int8*)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize + sizeof(EXTENT_AD) )))
1964 return STATUS_INSUFFICIENT_RESOURCES;
1965 RtlZeroMemory(((int8*)AllocDesc) + Vcb->LBlockSize, sizeof(EXTENT_AD));
1966 if(!OS_SUCCESS(status = UDFReadTagged(Vcb, AllocDesc, Lba, Lba, &Ident)) ||
1967 !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, l = (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) {
1968 MyFreePool__(AllocDesc);
1969 return status;
1970 }
1971 UDFRegisterFsStructure(Vcb, Lba, Vcb->BlockSize);
1972 RtlCopyMemory((int8*)Extent, AllocDesc+sizeof(UNALLOC_SPACE_DESC), (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) );
1973 locAddr.partitionReferenceNum = (uint16)PartNum;
1974 // read extent is recorded with relative addresses
1975 // so, we should convert it to suitable form
1976 for(i=0; Extent[i].extLength; i++) {
1977 locAddr.logicalBlockNum = Extent[i].extLocation;
1978 Extent[i].extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
1979 if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) {
1980 BrutePoint();
1981 MyFreePool__(AllocDesc);
1982 return STATUS_DISK_CORRUPT_ERROR;
1983 }
1984 if((Extent[i].extLocation >> 30) == EXTENT_NEXT_EXTENT_ALLOCDESC) {
1985 // load continuation
1986 Lba = Extent[i].extLocation & UDF_EXTENT_LENGTH_MASK;
1987 if(!OS_SUCCESS(status = UDFReadTagged(Vcb, AllocDesc, Lba, Lba, &Ident)) ||
1988 !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) {
1989 MyFreePool__(AllocDesc);
1990 return status;
1991 }
1992 if(Ident == TID_UNALLOC_SPACE_DESC) {
1993 UDFRegisterFsStructure(Vcb, Lba, Vcb->BlockSize);
1994 if(!(l = MyReallocPool__((int8*)Extent, l, (int8**)&Extent, i*sizeof(EXTENT_MAP)))) {
1995 MyFreePool__(Extent);
1996 MyFreePool__(AllocDesc);
1997 return STATUS_INSUFFICIENT_RESOURCES;
1998 }
1999 Extent[i].extLength =
2000 Extent[i].extLocation = 0;
2001 Extent = UDFMergeMappings(Extent, (PEXTENT_MAP)(AllocDesc+sizeof(UNALLOC_SPACE_DESC)) );
2002 #ifdef UDF_DBG
2003 } else {
2004 KdPrint(("Broken unallocated space descriptor sequence\n"));
2005 #endif // UDF_DBG
2006 }
2007 }
2008 }
2009 UDFMarkSpaceAsXXX(Vcb, (-1), Extent, AS_USED); // mark as used
2010 MyFreePool__(Extent);
2011 MyFreePool__(AllocDesc);
2012 }
2013 return status;
2014 } // end UDFVerifyFreeSpaceBitmap()
2015
2016 /*
2017 process Partition descriptor
2018 */
2019 OSSTATUS
2020 UDFLoadPartDesc(
2021 PVCB Vcb,
2022 int8* Buf
2023 )
2024 {
2025 PartitionDesc *p = (PartitionDesc *)Buf;
2026 uint32 i;
2027 OSSTATUS RC;
2028 BOOLEAN Found = FALSE;
2029 KdPrint(("UDF: Pard Descr:\n"));
2030 KdPrint((" volDescSeqNum = %x\n", p->volDescSeqNum));
2031 KdPrint((" partitionFlags = %x\n", p->partitionFlags));
2032 KdPrint((" partitionNumber = %x\n", p->partitionNumber));
2033 KdPrint((" accessType = %x\n", p->accessType));
2034 KdPrint((" partitionStartingLocation = %x\n", p->partitionStartingLocation));
2035 KdPrint((" partitionLength = %x\n", p->partitionLength));
2036 // There is nothing interesting to comment here
2037 // Just look at Names & Messages....
2038 for (i=0; i<Vcb->PartitionMaps; i++) {
2039 KdPrint(("Searching map: (%d == %d)\n",
2040 Vcb->Partitions[i].PartitionNum, (p->partitionNumber) ));
2041 if(Vcb->Partitions[i].PartitionNum == (p->partitionNumber)) {
2042 Found = TRUE;
2043 Vcb->Partitions[i].PartitionRoot = p->partitionStartingLocation + Vcb->FirstLBA;
2044 Vcb->Partitions[i].PartitionLen =
2045 min(p->partitionLength,
2046 Vcb->LastPossibleLBA - Vcb->Partitions[i].PartitionRoot); /* sectors */
2047 Vcb->Partitions[i].UspaceBitmap = 0xFFFFFFFF;
2048 Vcb->Partitions[i].FspaceBitmap = 0xFFFFFFFF;
2049 Vcb->Partitions[i].AccessType = p->accessType;
2050 KdPrint(("Access mode %x\n", p->accessType));
2051 if(p->accessType == PARTITION_ACCESS_WO) {
2052 Vcb->CDR_Mode = TRUE;
2053 // Vcb->Partitions[i].PartitionLen = Vcb->LastPossibleLBA - p->partitionStartingLocation;
2054 } else if(p->accessType < PARTITION_ACCESS_WO) {
2055 // Soft-read-only volume
2056 KdPrint(("Soft Read-only volume\n"));
2057 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2058 Vcb->UserFSFlags |= UDF_USER_FS_FLAGS_PART_RO;
2059 } else if(p->accessType > PARTITION_ACCESS_MAX_KNOWN) {
2060 return STATUS_UNRECOGNIZED_MEDIA;
2061 }
2062
2063 if(!strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR02) ||
2064 !strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR03))
2065 {
2066 PPARTITION_HEADER_DESC phd;
2067
2068 phd = (PPARTITION_HEADER_DESC)(p->partitionContentsUse);
2069 #ifdef UDF_DBG
2070 if(phd->unallocatedSpaceTable.extLength)
2071 KdPrint(("unallocatedSpaceTable (part %d)\n", i));
2072 #endif // UDF_DBG
2073 if(phd->unallocatedSpaceBitmap.extLength) {
2074 Vcb->Partitions[i].UspaceBitmap =
2075 phd->unallocatedSpaceBitmap.extPosition;
2076 KdPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2077 i, Vcb->Partitions[i].UspaceBitmap ));
2078 }
2079 #ifdef UDF_DBG
2080 if(phd->partitionIntegrityTable.extLength)
2081 KdPrint(("partitionIntegrityTable (part %d)\n", i));
2082 if(phd->freedSpaceTable.extLength)
2083 KdPrint(("freedSpaceTable (part %d)\n", i));
2084 #endif // UDF_DBG
2085 if(phd->freedSpaceBitmap.extLength) {
2086 Vcb->Partitions[i].FspaceBitmap =
2087 phd->freedSpaceBitmap.extPosition;
2088 KdPrint(("freedSpaceBitmap (part %d)\n", i));
2089 }
2090 RC = UDFBuildFreeSpaceBitmap(Vcb, i, phd, 0);
2091 //Vcb->Modified = FALSE;
2092 UDFPreClrModified(Vcb);
2093 UDFClrModified(Vcb);
2094 if(!OS_SUCCESS(RC))
2095 return RC;
2096
2097 if ((Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP15) ||
2098 (Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP20)) {
2099 RC = UDFLoadVAT(Vcb, i);
2100 if(!OS_SUCCESS(RC))
2101 return RC;
2102 WCacheFlushAll__(&(Vcb->FastCache), Vcb);
2103 WCacheSetMode__(&(Vcb->FastCache), WCACHE_MODE_R);
2104 Vcb->LastModifiedTrack = 0;
2105 }
2106 }
2107 }
2108 }
2109 #ifdef UDF_DBG
2110 if(!Found) {
2111 KdPrint(("Partition (%d) not found in partition map\n", (p->partitionNumber) ));
2112 } else {
2113 KdPrint(("Partition (%d:%d type %x) starts at physical %x, length %x\n",
2114 p->partitionNumber, i-1, Vcb->Partitions[i-1].PartitionType,
2115 Vcb->Partitions[i-1].PartitionRoot, Vcb->Partitions[i-1].PartitionLen));
2116 }
2117 #endif // UDF_DBG
2118 return STATUS_SUCCESS;
2119 } // end UDFLoadPartDesc()
2120
2121 /*
2122 process Partition descriptor
2123 */
2124 OSSTATUS
2125 UDFVerifyPartDesc(
2126 PVCB Vcb,
2127 int8* Buf
2128 )
2129 {
2130 PartitionDesc *p = (PartitionDesc *)Buf;
2131 uint32 i;
2132 OSSTATUS RC;
2133 BOOLEAN Found = FALSE;
2134 KdPrint(("UDF: Verify Part Descr:\n"));
2135 KdPrint((" volDescSeqNum = %x\n", p->volDescSeqNum));
2136 KdPrint((" partitionFlags = %x\n", p->partitionFlags));
2137 KdPrint((" partitionNumber = %x\n", p->partitionNumber));
2138 KdPrint((" accessType = %x\n", p->accessType));
2139 KdPrint((" partitionStartingLocation = %x\n", p->partitionStartingLocation));
2140 KdPrint((" partitionLength = %x\n", p->partitionLength));
2141 // There is nothing interesting to comment here
2142 // Just look at Names & Messages....
2143 for (i=0; i<Vcb->PartitionMaps; i++) {
2144 KdPrint(("Searching map: (%d == %d)\n",
2145 Vcb->Partitions[i].PartitionNum, (p->partitionNumber) ));
2146 if(Vcb->Partitions[i].PartitionNum == (p->partitionNumber)) {
2147 Found = TRUE;
2148 if(Vcb->Partitions[i].PartitionRoot != p->partitionStartingLocation + Vcb->FirstLBA)
2149 return STATUS_DISK_CORRUPT_ERROR;
2150 if(Vcb->Partitions[i].PartitionLen !=
2151 min(p->partitionLength,
2152 Vcb->LastPossibleLBA - Vcb->Partitions[i].PartitionRoot)) /* sectors */
2153 return STATUS_DISK_CORRUPT_ERROR;
2154 // Vcb->Partitions[i].UspaceBitmap = 0xFFFFFFFF;
2155 // Vcb->Partitions[i].FspaceBitmap = 0xFFFFFFFF;
2156 if(Vcb->Partitions[i].AccessType != p->accessType)
2157 return STATUS_DISK_CORRUPT_ERROR;
2158 KdPrint(("Access mode %x\n", p->accessType));
2159 if(p->accessType == PARTITION_ACCESS_WO) {
2160 if(Vcb->CDR_Mode != TRUE)
2161 return STATUS_DISK_CORRUPT_ERROR;
2162 // Vcb->Partitions[i].PartitionLen = Vcb->LastPossibleLBA - p->partitionStartingLocation;
2163 } else if(p->accessType < PARTITION_ACCESS_WO) {
2164 // Soft-read-only volume
2165 KdPrint(("Soft Read-only volume\n"));
2166 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY))
2167 return STATUS_DISK_CORRUPT_ERROR;
2168 } else if(p->accessType > PARTITION_ACCESS_MAX_KNOWN) {
2169 return STATUS_UNRECOGNIZED_MEDIA;
2170 }
2171
2172 if(!strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR02) ||
2173 !strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR03))
2174 {
2175 PPARTITION_HEADER_DESC phd;
2176
2177 phd = (PPARTITION_HEADER_DESC)(p->partitionContentsUse);
2178 #ifdef UDF_DBG
2179 if(phd->unallocatedSpaceTable.extLength)
2180 KdPrint(("unallocatedSpaceTable (part %d)\n", i));
2181 #endif // UDF_DBG
2182 if(phd->unallocatedSpaceBitmap.extLength) {
2183 if(Vcb->Partitions[i].UspaceBitmap ==
2184 phd->unallocatedSpaceBitmap.extPosition) {
2185 KdPrint(("Warning: both USpaceBitmaps have same location\n"));
2186 }
2187 KdPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2188 i, Vcb->Partitions[i].UspaceBitmap ));
2189 }
2190 #ifdef UDF_DBG
2191 if(phd->partitionIntegrityTable.extLength)
2192 KdPrint(("partitionIntegrityTable (part %d)\n", i));
2193 if(phd->freedSpaceTable.extLength)
2194 KdPrint(("freedSpaceTable (part %d)\n", i));
2195 #endif // UDF_DBG
2196 if(phd->freedSpaceBitmap.extLength) {
2197 if(Vcb->Partitions[i].FspaceBitmap ==
2198 phd->freedSpaceBitmap.extPosition) {
2199 KdPrint(("Warning: both FSpaceBitmaps have same location\n"));
2200 }
2201 KdPrint(("freedSpaceBitmap (part %d)\n", i));
2202 }
2203 RC = UDFVerifyFreeSpaceBitmap(Vcb, i, phd, 0);
2204 //Vcb->Modified = FALSE;
2205 //UDFPreClrModified(Vcb);
2206 //UDFClrModified(Vcb);
2207 if(!OS_SUCCESS(RC))
2208 return RC;
2209
2210 if ((Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP15) ||
2211 (Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP20)) {
2212 /* RC = UDFLoadVAT(Vcb, i);
2213 if(!OS_SUCCESS(RC))
2214 return RC;
2215 WCacheFlushAll__(&(Vcb->FastCache), Vcb);
2216 WCacheSetMode__(&(Vcb->FastCache), WCACHE_MODE_R);
2217 Vcb->LastModifiedTrack = 0;*/
2218 }
2219 }
2220 }
2221 }
2222 #ifdef UDF_DBG
2223 if(!Found) {
2224 KdPrint(("Partition (%d) not found in partition map\n", (p->partitionNumber) ));
2225 } else {
2226 KdPrint(("Partition (%d:%d type %x) starts at physical %x, length %x\n",
2227 p->partitionNumber, i-1, Vcb->Partitions[i-1].PartitionType,
2228 Vcb->Partitions[i-1].PartitionRoot, Vcb->Partitions[i-1].PartitionLen));
2229 }
2230 #endif // UDF_DBG
2231 return STATUS_SUCCESS;
2232 } // end UDFVerifyPartDesc()
2233
2234 /*
2235 This routine scans VDS & fills special array with Desc locations
2236 */
2237 OSSTATUS
2238 UDFReadVDS(
2239 IN PVCB Vcb,
2240 IN uint32 block,
2241 IN uint32 lastblock,
2242 IN PUDF_VDS_RECORD vds,
2243 IN int8* Buf
2244 )
2245 {
2246 OSSTATUS status;
2247 GenericDesc* gd;
2248 BOOLEAN done=FALSE;
2249 uint32 vdsn;
2250 uint16 ident;
2251
2252 KdPrint(("UDF: Read VDS (%x - %x)\n", block, lastblock ));
2253 // Read the main descriptor sequence
2254 for (;(!done && block <= lastblock); block++)
2255 {
2256 status = UDFReadTagged(Vcb, Buf, block, block, &ident);
2257 if(!OS_SUCCESS(status))
2258 return status;
2259 UDFRegisterFsStructure(Vcb, block, Vcb->BlockSize);
2260
2261 // Process each descriptor (ISO 13346 3/8.3-8.4)
2262 gd = (struct GenericDesc *)Buf;
2263 vdsn = gd->volDescSeqNum;
2264 KdPrint(("LBA %x, Ident = %x, vdsn = %x\n", block, ident, vdsn ));
2265 switch (ident)
2266 {
2267 case TID_PRIMARY_VOL_DESC: // ISO 13346 3/10.1
2268 if(vdsn >= vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum)
2269 {
2270 vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum = vdsn;
2271 vds[VDS_POS_PRIMARY_VOL_DESC].block = block;
2272 }
2273 break;
2274 case TID_VOL_DESC_PTR: // ISO 13346 3/10.3
2275 struct VolDescPtr* pVDP;
2276 if(vdsn >= vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum)
2277 {
2278 vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum = vdsn;
2279 vds[VDS_POS_VOL_DESC_PTR].block = block;
2280 vds[VDS_POS_RECURSION_COUNTER].volDescSeqNum++;
2281 if(vds[VDS_POS_RECURSION_COUNTER].volDescSeqNum > MAX_VDS_PARTS) {
2282 KdPrint(("too long multipart VDS -> abort\n"));
2283 return STATUS_DISK_CORRUPT_ERROR;
2284 }
2285 pVDP = (struct VolDescPtr*)Buf;
2286 KdPrint(("multipart VDS...\n"));
2287 return UDFReadVDS(Vcb, pVDP->nextVolDescSeqExt.extLocation,
2288 pVDP->nextVolDescSeqExt.extLocation + (pVDP->nextVolDescSeqExt.extLocation >> Vcb->BlockSizeBits),
2289 vds, Buf);
2290 }
2291 break;
2292 case TID_IMP_USE_VOL_DESC: // ISO 13346 3/10.4
2293 if(vdsn >= vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum)
2294 {
2295 vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum = vdsn;
2296 vds[VDS_POS_IMP_USE_VOL_DESC].block = block;
2297 }
2298 break;
2299 case TID_PARTITION_DESC: // ISO 13346 3/10.5
2300 if(!vds[VDS_POS_PARTITION_DESC].block)
2301 vds[VDS_POS_PARTITION_DESC].block = block;
2302 break;
2303 case TID_LOGICAL_VOL_DESC: // ISO 13346 3/10.6
2304 case TID_ADAPTEC_LOGICAL_VOL_DESC: // Adaptec Compressed UDF extesion
2305 if(vdsn >= vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum)
2306 {
2307 vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum = vdsn;
2308 vds[VDS_POS_LOGICAL_VOL_DESC].block = block;
2309 }
2310 break;
2311 case TID_UNALLOC_SPACE_DESC: // ISO 13346 3/10.8
2312 if(vdsn >= vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum)
2313 {
2314 vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum = vdsn;
2315 vds[VDS_POS_UNALLOC_SPACE_DESC].block = block;
2316 }
2317 break;
2318 case TID_TERMINATING_DESC: // ISO 13346 3/10.9
2319 vds[VDS_POS_TERMINATING_DESC].block = block;
2320 done = TRUE;
2321 break;
2322 }
2323 }
2324 return STATUS_SUCCESS;
2325 } // UDFReadVDS()
2326
2327 OSSTATUS
2328 UDFLoadImpUseVolDesc(
2329 IN PVCB Vcb,
2330 int8* Buf
2331 )
2332 {
2333 ImpUseVolDesc* iuvd = (ImpUseVolDesc*)Buf;
2334 ImpUseVolDescImpUse* iuvdiu = (ImpUseVolDescImpUse*)&(iuvd->impUse);
2335 KdPrint(("UDF: Imp Use Vol Desc:\n"));
2336 KdPrint((" volDescSeqNum = %x\n", iuvd->volDescSeqNum));
2337 KdPrint(("UDF: Imp Use Vol Desc Imp Use:\n"));
2338 KdDump(iuvdiu, sizeof(ImpUseVolDescImpUse));
2339 return STATUS_SUCCESS;
2340 } // UDFLoadImpUseVolDesc()
2341
2342 OSSTATUS
2343 UDFLoadUnallocatedSpaceDesc(
2344 IN PVCB Vcb,
2345 int8* Buf
2346 )
2347 {
2348 KdPrint(("UDF: Unallocated Space Desc:\n"));
2349 // UnallocatedSpaceDesc* usd = (UnallocatedSpaceDesc*)Buf;
2350 return STATUS_SUCCESS;
2351 } // UDFLoadImpUseVolDesc()
2352
2353 /*
2354 Process a main/reserve volume descriptor sequence.
2355 */
2356 OSSTATUS
2357 UDFProcessSequence(
2358 IN PDEVICE_OBJECT DeviceObject,
2359 IN PVCB Vcb,
2360 IN uint32 block,
2361 IN uint32 lastblock,
2362 OUT lb_addr *fileset
2363 )
2364 {
2365 OSSTATUS RC = STATUS_SUCCESS;
2366 int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2367 UDF_VDS_RECORD vds[VDS_POS_LENGTH];
2368 GenericDesc *gd;
2369 uint32 i,j;
2370 uint16 ident;
2371 int8* Buf2 = NULL;
2372
2373 _SEH2_TRY {
2374 if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2375 RtlZeroMemory(vds, sizeof(UDF_VDS_RECORD) * VDS_POS_LENGTH);
2376 if(!OS_SUCCESS(RC = UDFReadVDS(Vcb, block, lastblock, (PUDF_VDS_RECORD)&vds, Buf)))
2377 try_return(RC);
2378 // walk through Vol Desc Sequence according to locations gained by
2379 // UDFReadVDS() & do some procesing for each one
2380 // It is very simple dispath routine...
2381 for (i=0; i<VDS_POS_LENGTH; i++)
2382 {
2383 if(vds[i].block)
2384 {
2385 if(!OS_SUCCESS(RC = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident)))
2386 try_return(RC);
2387 UDFRegisterFsStructure(Vcb, vds[i].block, Vcb->BlockSize);
2388
2389 if(i == VDS_POS_PRIMARY_VOL_DESC) {
2390 UDFLoadPVolDesc(Vcb,Buf);
2391 if(!Vcb->PVolDescAddr.block) {
2392 Vcb->PVolDescAddr = vds[i];
2393 } else {
2394 Vcb->PVolDescAddr2 = vds[i];
2395 }
2396 } else
2397 if(i == VDS_POS_LOGICAL_VOL_DESC) {
2398 RC = UDFLoadLogicalVol(DeviceObject,Vcb, Buf, fileset);
2399 if(!OS_SUCCESS(RC)) try_return(RC);
2400 } else
2401
2402 if(i == VDS_POS_IMP_USE_VOL_DESC) {
2403 UDFLoadImpUseVolDesc(Vcb, Buf);
2404 } else
2405 if(i == VDS_POS_UNALLOC_SPACE_DESC) {
2406 UDFLoadUnallocatedSpaceDesc(Vcb, Buf);
2407 } else
2408
2409 if(i == VDS_POS_PARTITION_DESC)
2410 {
2411 Buf2 = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2412 if(!Buf2) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2413 RC = UDFLoadPartDesc(Vcb,Buf);
2414 if(!OS_SUCCESS(RC)) try_return(RC);
2415 for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++)
2416 {
2417 RC = UDFReadTagged(Vcb,Buf2, j, j, &ident);
2418 if(!OS_SUCCESS(RC)) try_return(RC);
2419 UDFRegisterFsStructure(Vcb, j, Vcb->BlockSize);
2420 gd = (struct GenericDesc *)Buf2;
2421 if(ident == TID_PARTITION_DESC) {
2422 RC = UDFLoadPartDesc(Vcb,Buf2);
2423 if(!OS_SUCCESS(RC)) try_return(RC);
2424 } else if(ident == TID_UNALLOC_SPACE_DESC) {
2425 RC = UDFBuildFreeSpaceBitmap(Vcb,0,NULL,j);
2426 //Vcb->Modified = FALSE;
2427 UDFPreClrModified(Vcb);
2428 UDFClrModified(Vcb);
2429 if(!OS_SUCCESS(RC))
2430 try_return(RC);
2431 }
2432 }
2433 MyFreePool__(Buf2);
2434 Buf2 = NULL;
2435 }
2436 } else {
2437 if(i == VDS_POS_LOGICAL_VOL_DESC) {
2438 RC = UDFLoadBogusLogicalVol(DeviceObject,Vcb, Buf, fileset);
2439 if(!OS_SUCCESS(RC)) try_return(RC);
2440 }
2441 }
2442 }
2443
2444 try_exit: NOTHING;
2445
2446 } _SEH2_FINALLY {
2447 if(Buf) MyFreePool__(Buf);
2448 if(Buf2) MyFreePool__(Buf2);
2449 } _SEH2_END;
2450
2451 return RC;
2452 } // end UDFProcessSequence()
2453
2454 /*
2455 Verifies a main/reserve volume descriptor sequence.
2456 */
2457 OSSTATUS
2458 UDFVerifySequence(
2459 IN PDEVICE_OBJECT DeviceObject,
2460 IN PVCB Vcb,
2461 IN uint32 block,
2462 IN uint32 lastblock,
2463 OUT lb_addr *fileset
2464 )
2465 {
2466 OSSTATUS RC = STATUS_SUCCESS;
2467 int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2468 UDF_VDS_RECORD vds[VDS_POS_LENGTH];
2469 GenericDesc *gd;
2470 uint32 i,j;
2471 uint16 ident;
2472 int8* Buf2 = NULL;
2473
2474 _SEH2_TRY {
2475 if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2476 if(!block) try_return (RC = STATUS_SUCCESS);
2477 RtlZeroMemory(vds, sizeof(UDF_VDS_RECORD) * VDS_POS_LENGTH);
2478 if(!OS_SUCCESS(RC = UDFReadVDS(Vcb, block, lastblock, (PUDF_VDS_RECORD)&vds, Buf)))
2479 try_return(RC);
2480
2481 for (i=0; i<VDS_POS_LENGTH; i++)
2482 {
2483 if(vds[i].block)
2484 {
2485 if(!OS_SUCCESS(RC = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident)))
2486 try_return(RC);
2487 UDFRegisterFsStructure(Vcb, vds[i].block, Vcb->BlockSize);
2488
2489 /* if(i == VDS_POS_PRIMARY_VOL_DESC)
2490 UDFLoadPVolDesc(Vcb,Buf);
2491 else if(i == VDS_POS_LOGICAL_VOL_DESC) {
2492 RC = UDFLoadLogicalVol(DeviceObject,Vcb, Buf, fileset);
2493 if(!OS_SUCCESS(RC)) try_return(RC);
2494 }
2495 else*/ if(i == VDS_POS_PARTITION_DESC)
2496 {
2497 Buf2 = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2498 if(!Buf2) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2499 RC = UDFVerifyPartDesc(Vcb,Buf);
2500 if(!OS_SUCCESS(RC)) try_return(RC);
2501 for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++)
2502 {
2503 RC = UDFReadTagged(Vcb,Buf2, j, j, &ident);
2504 if(!OS_SUCCESS(RC)) try_return(RC);
2505 UDFRegisterFsStructure(Vcb, j, Vcb->BlockSize);
2506 gd = (struct GenericDesc *)Buf2;
2507 if(ident == TID_PARTITION_DESC) {
2508 RC = UDFVerifyPartDesc(Vcb,Buf2);
2509 if(!OS_SUCCESS(RC)) try_return(RC);
2510 } else if(ident == TID_UNALLOC_SPACE_DESC) {
2511 RC = UDFVerifyFreeSpaceBitmap(Vcb,0,NULL,j);
2512 Vcb->Modified = FALSE;
2513 if(!OS_SUCCESS(RC))
2514 try_return(RC);
2515 }
2516 }
2517 MyFreePool__(Buf2);
2518 Buf2 = NULL;
2519 }
2520 }
2521 }
2522 try_exit: NOTHING;
2523
2524 } _SEH2_FINALLY {
2525 if(Buf) MyFreePool__(Buf);
2526 if(Buf2) MyFreePool__(Buf2);
2527 } _SEH2_END;
2528
2529 return RC;
2530 } // end UDFVerifySequence()
2531
2532 /*
2533 remember some useful info about FileSet & RootDir location
2534 */
2535 void
2536 UDFLoadFileset(
2537 IN PVCB Vcb,
2538 IN PFILE_SET_DESC fset,
2539 OUT lb_addr *root,
2540 OUT lb_addr *sysstream
2541 )
2542 {
2543 *root = fset->rootDirectoryICB.extLocation;
2544 Vcb->SerialNumber = fset->descTag.tagSerialNum;
2545 KdPrint(("Rootdir at block=%x, partition=%d\n",
2546 root->logicalBlockNum, root->partitionReferenceNum));
2547 if(sysstream) {
2548 *sysstream = fset->streamDirectoryICB.extLocation;
2549 KdPrint(("SysStream at block=%x, partition=%d\n",
2550 sysstream->logicalBlockNum, sysstream->partitionReferenceNum));
2551 }
2552 // Get current UDF revision
2553 // Get Read-Only flags
2554 UDFReadEntityID_Domain(Vcb, &(fset->domainIdent));
2555
2556 } // end UDFLoadFileset()
2557
2558 OSSTATUS
2559 UDFIsCachedBadSequence(
2560 IN PVCB Vcb,
2561 IN uint32 Lba
2562 )
2563 {
2564 ULONG j;
2565 OSSTATUS RC = STATUS_SUCCESS;
2566 // Check if it is known bad sequence
2567 for(j=0; j<Vcb->BadSeqLocIndex; j++) {
2568 if(Vcb->BadSeqLoc[j] == Lba) {
2569 RC = Vcb->BadSeqStatus[j];
2570 break;
2571 }
2572 }
2573 return RC;
2574 } // end UDFIsCachedBadSequence()
2575
2576 VOID
2577 UDFRememberBadSequence(
2578 IN PVCB Vcb,
2579 IN uint32 Lba,
2580 IN OSSTATUS RC
2581 )
2582 {
2583 int j;
2584 if(!OS_SUCCESS(UDFIsCachedBadSequence(Vcb, Lba)))
2585 return;
2586 // Remenber bad sequence
2587 j = Vcb->BadSeqLocIndex;
2588 Vcb->BadSeqLocIndex++;
2589 Vcb->BadSeqLoc[j] = Lba;
2590 Vcb->BadSeqStatus[j] = RC;
2591 } // end UDFRememberBadSequence()
2592
2593 /*
2594 load partition info
2595 */
2596 OSSTATUS
2597 UDFLoadPartition(
2598 IN PDEVICE_OBJECT DeviceObject,
2599 IN PVCB Vcb,
2600 OUT lb_addr *fileset
2601 )
2602 {
2603 OSSTATUS RC = STATUS_UNRECOGNIZED_VOLUME;
2604 OSSTATUS RC2 = STATUS_UNRECOGNIZED_VOLUME;
2605 AnchorVolDescPtr *anchor;
2606 uint16 ident;
2607 int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2608 uint32 main_s, main_e;
2609 uint32 reserve_s, reserve_e;
2610 int i;
2611
2612 if(!Buf) return STATUS_INSUFFICIENT_RESOURCES;
2613 // walk through all available Anchors & load data
2614 for (i=0; i<MAX_ANCHOR_LOCATIONS; i++)
2615 {
2616 if(Vcb->Anchor[i] && (OS_SUCCESS(UDFReadTagged(Vcb, Buf,
2617 Vcb->Anchor[i], Vcb->Anchor[i] - Vcb->FirstLBA, &ident))))
2618 {
2619 anchor = (AnchorVolDescPtr *)Buf;
2620
2621 // Locate the main sequence
2622 main_s = ( anchor->mainVolDescSeqExt.extLocation );
2623 main_e = ( anchor->mainVolDescSeqExt.extLength );
2624 main_e = main_e >> Vcb->BlockSizeBits;
2625 main_e += main_s;
2626
2627 // Locate the reserve sequence
2628 reserve_s = (anchor->reserveVolDescSeqExt.extLocation);
2629 reserve_e = (anchor->reserveVolDescSeqExt.extLength);
2630 reserve_e = reserve_e >> Vcb->BlockSizeBits;
2631 reserve_e += reserve_s;
2632
2633 // Check if it is known bad sequence
2634 RC = UDFIsCachedBadSequence(Vcb, main_s);
2635 if(OS_SUCCESS(RC)) {
2636 // Process the main & reserve sequences
2637 // responsible for finding the PartitionDesc(s)
2638 KdPrint(("-----------------------------------\n"));
2639 KdPrint(("UDF: Main sequence:\n"));
2640 RC = UDFProcessSequence(DeviceObject, Vcb, main_s, main_e, fileset);
2641 }
2642
2643 if(!OS_SUCCESS(RC)) {
2644 // Remenber bad sequence
2645 UDFRememberBadSequence(Vcb, main_s, RC);
2646
2647 KdPrint(("-----------------------------------\n"));
2648 KdPrint(("UDF: Main sequence failed.\n"));
2649 KdPrint(("UDF: Reserve sequence\n"));
2650 if(Vcb->LVid) MyFreePool__(Vcb->LVid);
2651 Vcb->LVid = NULL;
2652
2653 RC2 = UDFIsCachedBadSequence(Vcb, reserve_s);
2654 if(OS_SUCCESS(RC2)) {
2655 RC2 = UDFProcessSequence(DeviceObject, Vcb, reserve_s, reserve_e, fileset);
2656 }
2657
2658 if(OS_SUCCESS(RC2)) {
2659 KdPrint(("-----------------------------------\n"));
2660 Vcb->VDS2_Len = reserve_e - reserve_s;
2661 Vcb->VDS2 = reserve_s;
2662 RC = STATUS_SUCCESS;
2663 // Vcb is already Zero-filled
2664 // Vcb->VDS1_Len = 0;
2665 // Vcb->VDS1 = 0;
2666 break;
2667 } else {
2668 // This is also bad sequence. Remenber it too
2669 UDFRememberBadSequence(Vcb, reserve_s, RC);
2670 }
2671 } else {
2672 // remember these values for umount__
2673 Vcb->VDS1_Len = main_e - main_s;
2674 Vcb->VDS1 = main_s;
2675 /* if(Vcb->LVid) MyFreePool__(Vcb->LVid);
2676 Vcb->LVid = NULL;*/
2677 if(OS_SUCCESS(UDFVerifySequence(DeviceObject, Vcb, reserve_s, reserve_e, fileset)))
2678 {
2679 KdPrint(("-----------------------------------\n"));
2680 Vcb->VDS2_Len = reserve_e - reserve_s;
2681 Vcb->VDS2 = reserve_s;
2682 break;
2683 } else {
2684 KdPrint(("UDF: Reserve sequence verification failed.\n"));
2685 switch(Vcb->PartitialDamagedVolumeAction) {
2686 case UDF_PART_DAMAGED_RO:
2687 KdPrint(("UDF: Switch to r/o mode.\n"));
2688 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2689 break;
2690 case UDF_PART_DAMAGED_NO:
2691 KdPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n"));
2692 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
2693 RC = STATUS_WRONG_VOLUME;
2694 break;
2695 case UDF_PART_DAMAGED_RW:
2696 default:
2697 KdPrint(("UDF: Keep r/w mode for your own risk.\n"));
2698 break;
2699 }
2700 }
2701 break;
2702 }
2703 }
2704 }
2705
2706 if(Vcb->SparingCount &&
2707 (Vcb->NoFreeRelocationSpaceVolumeAction != UDF_PART_DAMAGED_RW)) {
2708 KdPrint(("UDF: No free Sparing Entries -> Switch to r/o mode.\n"));
2709 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2710 }
2711
2712 if(i == sizeof(Vcb->Anchor)/sizeof(int)) {
2713 KdPrint(("No Anchor block found\n"));
2714 RC = STATUS_UNRECOGNIZED_VOLUME;
2715 #ifdef UDF_DBG
2716 } else {
2717 KdPrint(("Using anchor in block %x\n", Vcb->Anchor[i]));
2718 #endif // UDF_DBG
2719 }
2720 MyFreePool__(Buf);
2721 return RC;
2722 } // end UDFLoadPartition()
2723
2724 /*
2725 This routine scans FileSet sequence & returns pointer to last valid
2726 FileSet
2727 */
2728 OSSTATUS
2729 UDFFindLastFileSet(
2730 IN PVCB Vcb,
2731 IN lb_addr *Addr, // Addr for the 1st FileSet
2732 IN OUT PFILE_SET_DESC FileSetDesc
2733 )
2734 {
2735 OSSTATUS status;
2736 uint32 relLocExt = Addr->logicalBlockNum;
2737 uint32 locExt = UDFPartLbaToPhys(Vcb, Addr);
2738 uint16 Ident;
2739 uint32 relPrevExt, prevExt;
2740
2741 relPrevExt, prevExt = NULL;
2742 FileSetDesc->nextExt.extLength = 1; // ;)
2743 // walk through FileSet chain
2744 // we've just pre-init'd extent length to read 1st FileSet
2745 while(FileSetDesc->nextExt.extLength) {
2746 status = UDFReadTagged(Vcb, (int8*)FileSetDesc, locExt, relLocExt, &Ident);
2747 if(!OS_SUCCESS(status)) {
2748 FileSetDesc->nextExt.extLength = 0;
2749 return status;
2750 }
2751 UDFRegisterFsStructure(Vcb, locExt, Vcb->BlockSize);
2752 if((locExt == LBA_OUT_OF_EXTENT) || (Ident != TID_FILE_SET_DESC)) {
2753 // try to read previous FileSet
2754 if(!prevExt) return STATUS_UNRECOGNIZED_VOLUME;
2755 status = UDFReadTagged(Vcb, (int8*)FileSetDesc, prevExt, relLocExt, &Ident);
2756 if(OS_SUCCESS(status)) {
2757 UDFRegisterFsStructure(Vcb, prevExt, Vcb->BlockSize);
2758 }
2759 return status;
2760 }
2761 prevExt = locExt;
2762 relPrevExt = relLocExt;
2763 locExt = UDFPartLbaToPhys(Vcb, &(FileSetDesc->nextExt.extLocation));
2764 }
2765 return STATUS_SUCCESS;
2766 } // end UDFFindLastFileSet()
2767
2768 /*
2769 This routine reads all sparing tables & stores them in contiguos memory
2770 space
2771 */
2772 OSSTATUS
2773 UDFLoadSparingTable(
2774 IN PVCB Vcb,
2775 IN PSPARABLE_PARTITION_MAP PartMap
2776 )
2777 {
2778 PSPARING_MAP RelocMap;
2779 PSPARING_MAP NewRelocMap;
2780 OSSTATUS status;
2781 uint32 i=0, BC, BC2;
2782 PSPARING_TABLE SparTable;
2783 uint32 TabSize, NewSize;
2784 uint32 ReadBytes;
2785 uint32 SparTableLoc;
2786 #ifdef UDF_TRACK_FS_STRUCTURES
2787 uint32 j;
2788 #endif //UDF_TRACK_FS_STRUCTURES
2789 uint32 n,m;
2790 BOOLEAN merged;
2791
2792 Vcb->SparingCountFree = -1;
2793
2794 KdPrint(("UDF: Sparable Part Map:\n"));
2795 Vcb->SparingTableLength = PartMap->sizeSparingTable;
2796 BC = (PartMap->sizeSparingTable >> Vcb->BlockSizeBits) + 1;
2797 KdPrint((" partitionMapType = %x\n", PartMap->partitionMapType));
2798 KdPrint((" partitionMapLength = %x\n", PartMap->partitionMapLength));
2799 KdPrint((" volSeqNum = %x\n", PartMap->volSeqNum));
2800 KdPrint((" partitionNum = %x\n", PartMap->partitionNum));
2801 KdPrint((" packetLength = %x\n", PartMap->packetLength));
2802 KdPrint((" numSparingTables = %x\n", PartMap->numSparingTables));
2803 KdPrint((" sizeSparingTable = %x\n", PartMap->sizeSparingTable));
2804 SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->BlockSize);
2805 if(!SparTable) return STATUS_INSUFFICIENT_RESOURCES;
2806 if(Vcb->SparingTable) {
2807 // if a part of Sparing Table is already loaded,
2808 // update it with data from another one
2809 RelocMap = Vcb->SparingTable;
2810 TabSize = Vcb->SparingCount * sizeof(SPARING_ENTRY);
2811 } else {
2812 // do some init to load first part of Sparing Table
2813 RelocMap = (PSPARING_MAP)MyAllocatePool__(NonPagedPool, RELOC_MAP_GRAN);
2814 if(!RelocMap) {
2815 MyFreePool__(SparTable);
2816 return STATUS_INSUFFICIENT_RESOURCES;
2817 }
2818 TabSize = RELOC_MAP_GRAN;
2819 Vcb->SparingBlockSize = PartMap->packetLength;
2820 }
2821 // walk through all available Sparing Tables
2822 for(i=0;i<PartMap->numSparingTables;i++) {
2823 // read (next) table
2824 SparTableLoc = ((uint32*)(PartMap+1))[i];
2825 for(n=0; n<Vcb->SparingTableCount; n++) {
2826 if(Vcb->SparingTableLoc[i] == SparTableLoc) {
2827 KdPrint((" already processed @%x\n",
2828 SparTableLoc
2829 ));
2830 continue;
2831 }
2832 }
2833 status = UDFReadSectors(Vcb, FALSE, SparTableLoc, 1, FALSE, (int8*)SparTable, &ReadBytes);
2834 // tag should be set to TID_UNUSED_DESC
2835 if(OS_SUCCESS(status) && (SparTable->descTag.tagIdent == TID_UNUSED_DESC)) {
2836
2837 UDFRegisterFsStructure(Vcb, SparTableLoc, Vcb->BlockSize);
2838 BC2 = ((sizeof(SPARING_TABLE) +
2839 SparTable->reallocationTableLen*sizeof(SparingEntry) +
2840 Vcb->BlockSize-1)
2841 >> Vcb->BlockSizeBits);
2842 if(BC2 > BC) {
2843 KdPrint((" sizeSparingTable @%x too long: %x > %x\n",
2844 SparTableLoc, BC2, BC
2845 ));
2846 continue;
2847 }
2848 status = UDFReadSectors(Vcb, FALSE, SparTableLoc,
2849 BC2, FALSE, (int8*)SparTable, &ReadBytes);
2850 UDFRegisterFsStructure(Vcb, SparTableLoc, BC2<<Vcb->BlockSizeBits);
2851
2852 if(!OS_SUCCESS(status)) {
2853 KdPrint((" Error reading sizeSparingTable @%x (%x)\n",
2854 SparTableLoc, BC2
2855 ));
2856 continue;
2857 }
2858 // process sparing table
2859 NewSize = sizeof(SparingEntry)*SparTable->reallocationTableLen;
2860 TabSize = MyReallocPool__((int8*)RelocMap, TabSize, (int8**)&RelocMap, TabSize+NewSize);
2861 if(!TabSize) {
2862 MyFreePool__(SparTable);
2863 return STATUS_INSUFFICIENT_RESOURCES;
2864 }
2865
2866 #ifdef UDF_TRACK_FS_STRUCTURES
2867 for(j=0; j<SparTable->reallocationTableLen; j++) {
2868 UDFRegisterFsStructure(Vcb, ((SparingEntry*)(SparTable+1))[j].mappedLocation, Vcb->WriteBlockSize);
2869 }
2870 #endif //UDF_TRACK_FS_STRUCTURES
2871
2872 Vcb->SparingTableLoc[Vcb->SparingTableCount] = SparTableLoc;
2873 Vcb->SparingTableCount++;
2874
2875 NewRelocMap = (PSPARING_MAP)(SparTable+1);
2876 for(n=0; n<SparTable->reallocationTableLen; n++) {
2877 merged = TRUE;
2878 for(m=0; m<Vcb->SparingCount; m++) {
2879 if(RelocMap[m].mappedLocation == NewRelocMap[n].mappedLocation) {
2880 KdPrint((" dup @%x (%x) vs @%x (%x)\n",
2881 RelocMap[m].origLocation, RelocMap[m].mappedLocation,
2882 NewRelocMap[m].origLocation, NewRelocMap[m].mappedLocation));
2883 merged = FALSE;
2884 }
2885 if((RelocMap[m].origLocation == NewRelocMap[n].origLocation) &&
2886 (RelocMap[m].mappedLocation != NewRelocMap[n].mappedLocation) &&
2887 (RelocMap[m].origLocation != SPARING_LOC_AVAILABLE) &&
2888 (RelocMap[m].origLocation != SPARING_LOC_CORRUPTED)) {
2889 KdPrint((" conflict @%x (%x) vs @%x (%x)\n",
2890 RelocMap[m].origLocation, RelocMap[m].mappedLocation,
2891 NewRelocMap[n].origLocation, NewRelocMap[n].mappedLocation));
2892 merged = FALSE;
2893 }
2894 }
2895 if(merged) {
2896 RelocMap[Vcb->SparingCount] = NewRelocMap[n];
2897 KdPrint((" reloc %x -> %x\n",
2898 RelocMap[Vcb->SparingCount].origLocation, RelocMap[Vcb->SparingCount].mappedLocation));
2899 Vcb->SparingCount++;
2900 if(RelocMap[Vcb->SparingCount].origLocation == SPARING_LOC_AVAILABLE) {
2901 Vcb->NoFreeRelocationSpaceVolumeAction = UDF_PART_DAMAGED_RW;
2902 }
2903 }
2904 }
2905
2906 /*
2907 RtlCopyMemory((int8*)(RelocMap+Vcb->SparingCount),
2908 (int8*)(SparTable+1), NewSize);
2909 Vcb->SparingCount += NewSize/sizeof(SPARING_ENTRY);
2910 */
2911 if(Vcb->SparingTableCount >= MAX_SPARING_TABLE_LOCATIONS) {
2912 KdPrint((" too many Sparing Tables\n"));
2913 break;
2914 }
2915 }
2916 }
2917 Vcb->SparingTable = RelocMap;
2918 MyFreePool__(SparTable);
2919 return STATUS_SUCCESS;
2920 } // end UDFLoadSparingTable()
2921
2922 /*
2923 This routine checks if buffer is ZERO-filled
2924 */
2925 BOOLEAN
2926 UDFCheckZeroBuf(
2927 IN int8* Buf,
2928 IN uint32 Length
2929 )
2930 {
2931 BOOLEAN RC = FALSE;
2932
2933 //#ifdef _X86_
2934 #ifdef _MSC_VER
2935
2936 uint32 len = Length;
2937 __asm push ecx
2938 __asm push edi
2939
2940 __asm mov ecx,len
2941 __asm mov edi,Buf
2942 __asm xor eax,eax
2943 __asm shr ecx,2
2944 __asm repe scasd
2945 __asm jne short not_all_zeros
2946 __asm mov RC,1
2947
2948 not_all_zeros:
2949
2950 __asm pop edi
2951 __asm pop ecx
2952
2953 return RC;
2954
2955 #else // _X86_
2956
2957 uint32* tmp = (uint32*)Buf;
2958 uint32 i;
2959
2960 for(i=0; i<Length/4; i++) {
2961 if(tmp[i]) return FALSE;
2962 }
2963 return TRUE;
2964
2965 #endif // _X86_
2966
2967 } // end UDFCheckZeroBuf()
2968
2969 /*
2970 check if this is an UDF-formatted disk
2971 */
2972 OSSTATUS
2973 UDFGetDiskInfoAndVerify(
2974 IN PDEVICE_OBJECT DeviceObject, // the target device object
2975 IN PVCB Vcb // Volume control block from this DevObj
2976 )
2977 {
2978 OSSTATUS RC = STATUS_UNRECOGNIZED_VOLUME;
2979 uint32 NSRDesc;
2980 lb_addr fileset;
2981 PFILE_SET_DESC FileSetDesc = NULL;
2982
2983 int8* Buf = NULL;
2984 uint32 ReadBytes;
2985
2986 KdPrint(("UDFGetDiskInfoAndVerify\n"));
2987 _SEH2_TRY {
2988
2989 if(!UDFFindAnchor(Vcb)) {
2990 if(Vcb->FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {
2991 // check if this disc is mountable for CDFS
2992 KdPrint((" FILE_DEVICE_CD_ROM_FILE_SYSTEM\n"));
2993 check_NSR:
2994 NSRDesc = UDFFindVRS(Vcb);
2995 if(!(NSRDesc & VRS_ISO9660_FOUND)) {
2996 // no CDFS VRS found
2997 KdPrint(("UDFGetDiskInfoAndVerify: no CDFS VRS found\n"));
2998 if(!Vcb->TrackMap[Vcb->LastTrackNum].LastLba &&
2999 !Vcb->TrackMap[Vcb->FirstTrackNum].LastLba) {
3000 // such a stupid method of Audio-CD detection...
3001 KdPrint(("UDFGetDiskInfoAndVerify: set UDF_VCB_FLAGS_RAW_DISK\n"));
3002 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
3003 }
3004 }
3005 Vcb->NSRDesc = NSRDesc;
3006
3007 Buf = (int8*)MyAllocatePool__(NonPagedPool, 0x10000);
3008 if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3009 RC = UDFReadData(Vcb, FALSE, 0, 0x10000, FALSE, Buf, &ReadBytes);
3010 if(!OS_SUCCESS(RC))
3011 try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
3012 RC = STATUS_UNRECOGNIZED_VOLUME;
3013 if(!UDFCheckZeroBuf(Buf,0x10000)) {
3014 KdPrint(("UDFGetDiskInfoAndVerify: possible FS detected, remove UDF_VCB_FLAGS_RAW_DISK\n"));
3015 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
3016 }
3017 MyFreePool__(Buf);
3018 Buf = NULL;
3019 }
3020 try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
3021 }
3022
3023 RC = UDFLoadPartition(DeviceObject,Vcb,&fileset);
3024 if(!OS_SUCCESS(RC)) {
3025 if(RC == STATUS_UNRECOGNIZED_VOLUME) {
3026 KdPrint(("UDFGetDiskInfoAndVerify: check NSR presence\n"));
3027 goto check_NSR;
3028 }
3029 try_return(RC);
3030 }
3031
3032 FileSetDesc = (PFILE_SET_DESC)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
3033 if(!FileSetDesc) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3034
3035 RC = UDFFindLastFileSet(Vcb,&fileset,FileSetDesc);
3036 if(!OS_SUCCESS(RC)) try_return(RC);
3037
3038 UDFLoadFileset(Vcb,FileSetDesc, &(Vcb->RootLbAddr), &(Vcb->SysStreamLbAddr));
3039
3040 Vcb->FSBM_OldBitmap = (int8*)DbgAllocatePool(NonPagedPool, Vcb->FSBM_ByteCount);
3041 if(!(Vcb->FSBM_OldBitmap)) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3042 RtlCopyMemory(Vcb->FSBM_OldBitmap, Vcb->FSBM_Bitmap, Vcb->FSBM_ByteCount);
3043
3044 try_exit: NOTHING;
3045 } _SEH2_FINALLY {
3046 if(FileSetDesc) MyFreePool__(FileSetDesc);
3047 if(Buf) MyFreePool__(Buf);
3048 } _SEH2_END;
3049
3050 return(RC);
3051
3052 } // end UDFGetDiskInfoAndVerify()
3053