1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
13 This file contains filesystem-specific routines
14 responsible for Mount/Umount
25 #define XCHG_DD(a,b) \
28 PULONG _from_, _to_; \
29 _from_ = ((PULONG)&(b)); \
30 _to_ = ((PULONG)&(a)); \
36 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_MOUNT
41 IN PUNICODE_STRING UName
,
46 #ifndef UDF_READ_ONLY_BUILD
48 This routine loads specified bitmap.
49 It is also allocate space if the bitmap is not allocated.
52 UDFPrepareXSpaceBitmap(
54 IN OUT PSHORT_AD XSpaceBitmap
,
55 IN OUT PEXTENT_INFO XSBMExtInfo
,
70 if(!(XSpaceBitmap
->extLength
)) {
73 return STATUS_SUCCESS
;
76 PartNum
= UDFGetPartNumByPartNdx(Vcb
, Vcb
->PartitionMaps
-1);
77 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
78 plen
= UDFPartStart(Vcb
, PartNum
) + UDFPartLen(Vcb
, PartNum
);
81 LBS
= Vcb
->LBlockSize
;
83 *XSl
= sizeof(SPACE_BITMAP_DESC
) + ((plen
+7)>>3);
84 _XSBM
= (int8
*)DbgAllocatePool(NonPagedPool
, (*XSl
+ BS
- 1) & ~(BS
-1) );
87 switch (XSpaceBitmap
->extLength
>> 30) {
88 case EXTENT_RECORDED_ALLOCATED
: {
89 locAddr
.logicalBlockNum
= XSpaceBitmap
->extPosition
;
90 *XSl
= min(XSpaceBitmap
->extLength
, *XSl
);
91 TmpExt
.extLength
= XSpaceBitmap
->extLength
= *XSl
;
92 TmpExt
.extLocation
= UDFPartLbaToPhys(Vcb
, &locAddr
);
93 if(TmpExt
.extLocation
== LBA_OUT_OF_EXTENT
) {
96 XSBMExtInfo
->Mapping
= UDFExtentToMapping(&TmpExt
);
97 XSBMExtInfo
->Offset
= 0;
98 XSBMExtInfo
->Length
= *XSl
;
101 case EXTENT_NEXT_EXTENT_ALLOCDESC
:
102 case EXTENT_NOT_RECORDED_NOT_ALLOCATED
: {
103 // allocate space for bitmap
104 if(!OS_SUCCESS(status
= UDFAllocFreeExtent(Vcb
, *XSl
,
105 UDFPartStart(Vcb
, PartNum
), UDFPartEnd(Vcb
, PartNum
), XSBMExtInfo
, EXTENT_FLAG_ALLOC_SEQUENTIAL
) ))
107 if(XSBMExtInfo
->Mapping
[1].extLength
) {
108 UDFPrint(("Can't allocate space for Freed Space bitmap\n"));
111 *XSl
= (uint32
)(XSBMExtInfo
->Length
);
112 XSpaceBitmap
->extPosition
= UDFPhysLbaToPart(Vcb
, PartNum
, XSBMExtInfo
->Mapping
[0].extLocation
);
116 case EXTENT_NOT_RECORDED_ALLOCATED
: {
117 // record Alloc-Not-Rec
118 locAddr
.logicalBlockNum
= XSpaceBitmap
->extPosition
;
119 *XSl
= min((XSpaceBitmap
->extLength
& UDF_EXTENT_LENGTH_MASK
), *XSl
);
120 TmpExt
.extLength
= XSpaceBitmap
->extLength
= *XSl
;
121 TmpExt
.extLocation
= UDFPartLbaToPhys(Vcb
, &locAddr
);
122 if(TmpExt
.extLocation
== LBA_OUT_OF_EXTENT
) {
125 XSBMExtInfo
->Mapping
= UDFExtentToMapping(&TmpExt
);
126 XSBMExtInfo
->Offset
= 0;
127 XSBMExtInfo
->Length
= *XSl
;
134 return STATUS_INSUFFICIENT_RESOURCES
;
137 switch (XSpaceBitmap
->extLength
>> 30) {
138 case EXTENT_RECORDED_ALLOCATED
: {
139 // read descriptor & bitmap
140 if((!OS_SUCCESS(status
= UDFReadTagged(Vcb
, *XSBM
, (j
= TmpExt
.extLocation
),
141 locAddr
.logicalBlockNum
, &Ident
))) ||
142 (Ident
!= TID_SPACE_BITMAP_DESC
) ||
143 (!OS_SUCCESS(status
= UDFReadExtent(Vcb
, XSBMExtInfo
, 0, *XSl
, FALSE
, *XSBM
, &ReadBytes
))) ) {
144 if(OS_SUCCESS(status
)) {
146 status
= STATUS_FILE_CORRUPT_ERROR
;
148 if(XSBMExtInfo
->Mapping
) {
149 MyFreePool__(XSBMExtInfo
->Mapping
);
150 XSBMExtInfo
->Mapping
= NULL
;
159 return STATUS_SUCCESS
;
162 case EXTENT_NEXT_EXTENT_ALLOCDESC
:
163 case EXTENT_NOT_RECORDED_NOT_ALLOCATED
:
164 case EXTENT_NOT_RECORDED_ALLOCATED
: {
170 PSPACE_BITMAP_DESC XSDesc
= (PSPACE_BITMAP_DESC
)(*XSBM
);
172 XSpaceBitmap
->extLength
= (*XSl
+ LBS
-1) & ~(LBS
-1);
173 RtlZeroMemory(*XSBM
, *XSl
);
174 XSDesc
->descTag
.tagIdent
= TID_SPACE_BITMAP_DESC
;
175 UDFSetUpTag(Vcb
, &(XSDesc
->descTag
), 0, XSpaceBitmap
->extPosition
);
176 XSDesc
->numOfBits
= plen
;
177 XSDesc
->numOfBytes
= (*XSl
)-sizeof(SPACE_BITMAP_DESC
);
179 return STATUS_SUCCESS
;
180 } // end UDFPrepareXSpaceBitmap()
183 This routine updates Freed & Unallocated space bitmaps
186 UDFUpdateXSpaceBitmaps(
189 IN PPARTITION_HEADER_DESC phd
// partition header pointing to Bitmaps
193 uint32 plen
, pstart
, pend
;
199 OSSTATUS status
, status2
;
203 EXTENT_INFO FSBMExtInfo
, USBMExtInfo
;
207 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
209 plen
= UDFPartLen(Vcb
, PartNum
);
210 // locAddr.partitionReferenceNum = (uint16)PartNum;
211 // prepare bitmaps for updating
213 status
= UDFPrepareXSpaceBitmap(Vcb
, &(phd
->unallocatedSpaceBitmap
), &USBMExtInfo
, &USBM
, &USl
);
214 status2
= UDFPrepareXSpaceBitmap(Vcb
, &(phd
->freedSpaceBitmap
), &FSBMExtInfo
, &FSBM
, &FSl
);
215 if(!OS_SUCCESS(status
) ||
216 !OS_SUCCESS(status2
)) {
220 pstart
= UDFPartStart(Vcb
, PartNum
);
221 new_bm
= Vcb
->FSBM_Bitmap
;
222 old_bm
= Vcb
->FSBM_OldBitmap
;
223 bad_bm
= Vcb
->BSBM_Bitmap
;
225 if((status
== STATUS_INSUFFICIENT_RESOURCES
) ||
226 (status2
== STATUS_INSUFFICIENT_RESOURCES
)) {
227 // try to recover insufficient resources
228 if(USl
&& USBMExtInfo
.Mapping
) {
229 USl
-= sizeof(SPACE_BITMAP_DESC
);
230 status
= UDFWriteExtent(Vcb
, &USBMExtInfo
, sizeof(SPACE_BITMAP_DESC
), USl
, FALSE
, new_bm
, &WrittenBytes
);
233 UDFPrint(("Can't update USBM\n"));
236 if(USBMExtInfo
.Mapping
) MyFreePool__(USBMExtInfo
.Mapping
);
238 if(FSl
&& FSBMExtInfo
.Mapping
) {
239 FSl
-= sizeof(SPACE_BITMAP_DESC
);
240 status2
= UDFWriteExtent(Vcb
, &FSBMExtInfo
, sizeof(SPACE_BITMAP_DESC
), FSl
, FALSE
, new_bm
, &WrittenBytes
);
243 UDFPrint(("Can't update FSBM\n"));
245 if(FSBMExtInfo
.Mapping
) MyFreePool__(FSBMExtInfo
.Mapping
);
247 // normal way to record BitMaps
248 if(USBM
) upart_bm
= USBM
+ sizeof(SPACE_BITMAP_DESC
);
249 if(FSBM
) fpart_bm
= FSBM
+ sizeof(SPACE_BITMAP_DESC
);
250 pend
= min(pstart
+ plen
, Vcb
->FSBM_BitCount
);
253 // if we have some bad bits, mark corresponding area as BAD
255 for(i
=pstart
; i
<pend
; i
++) {
256 if(UDFGetBadBit(bad_bm
, i
)) {
257 // TODO: would be nice to add these blocks to unallocatable space
258 UDFSetUsedBits(new_bm
, i
& ~(d
-1), d
);
263 for(i
=pstart
; i
<pend
; i
+=d
) {
264 if(UDFGetUsedBit(old_bm
, i
) && UDFGetFreeBit(new_bm
, i
)) {
265 // sector was deallocated during last session
266 if(USBM
) UDFSetFreeBit(upart_bm
, j
);
267 if(FSBM
) UDFSetFreeBit(fpart_bm
, j
);
268 } else if(UDFGetUsedBit(new_bm
, i
)) {
270 if(USBM
) UDFSetUsedBit(upart_bm
, j
);
271 if(FSBM
) UDFSetUsedBit(fpart_bm
, j
);
277 status
= UDFWriteExtent(Vcb
, &USBMExtInfo
, 0, USl
, FALSE
, USBM
, &WrittenBytes
);
279 MyFreePool__(USBMExtInfo
.Mapping
);
282 status2
= UDFWriteExtent(Vcb
, &FSBMExtInfo
, 0, FSl
, FALSE
, FSBM
, &WrittenBytes
);
284 MyFreePool__(FSBMExtInfo
.Mapping
);
290 if(!OS_SUCCESS(status
))
293 } // end UDFUpdateXSpaceBitmaps()
296 This routine updates Partition Desc & associated data structures
304 PartitionDesc
*p
= (PartitionDesc
*)Buf
;
309 for(i
=0; i
<Vcb
->PartitionMaps
; i
++)
311 if((UDFGetPartNumByPartNdx(Vcb
,i
) == p
->partitionNumber
) &&
312 (!strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR02
) ||
313 !strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR03
)))
315 PPARTITION_HEADER_DESC phd
;
317 phd
= (PPARTITION_HEADER_DESC
)(p
->partitionContentsUse
);
319 if(phd
->unallocatedSpaceTable
.extLength
) {
320 // rebuild unallocatedSpaceTable
321 UDFPrint(("unallocatedSpaceTable (part %d)\n", i
));
323 if(phd
->freedSpaceTable
.extLength
) {
324 // rebuild freedSpaceTable
325 UDFPrint(("freedSpaceTable (part %d)\n", i
));
328 UDFUpdateXSpaceBitmaps(Vcb
, p
->partitionNumber
, phd
);
330 UDFSetUpTag(Vcb
, PTag
, PTag
->descCRCLength
, PTag
->tagLocation
);
331 UDFWriteSectors(Vcb
, TRUE
, PTag
->tagLocation
, 1, FALSE
, Buf
, &WrittenBytes
);
334 return STATUS_SUCCESS
;
335 } // end UDFUpdatePartDesc()
338 This routine blanks Unalloc Space Desc
346 PUNALLOC_SPACE_DESC usd;
349 usd = (PUNALLOC_SPACE_DESC)Buf;
350 usd->numAllocDescs = 0;
351 RtlZeroMemory(Buf+sizeof(UNALLOC_SPACE_DESC), Vcb->BlockSize - sizeof(UNALLOC_SPACE_DESC));
352 UDFSetUpTag(Vcb, &(usd->descTag), 0, usd->descTag.tagLocation);
353 UDFWriteSectors(Vcb, TRUE, usd->descTag.tagLocation, 1, FALSE, Buf, &WrittenBytes);
354 return STATUS_SUCCESS;
358 update Logical volume integrity descriptor
361 UDFUpdateLogicalVolInt(
366 OSSTATUS RC
= STATUS_SUCCESS
;
369 // uint32 lvid_count = 0;
372 LogicalVolIntegrityDesc
*lvid
;
373 LogicalVolIntegrityDescImpUse
* LVID_iUse
;
374 LogicalVolHeaderDesc
* LVID_hd
;
375 uint32
* partFreeSpace
;
376 BOOLEAN equal
= FALSE
;
379 return STATUS_SUCCESS
;
381 return STATUS_UNSUCCESSFUL
;
384 UDFPrint(("UDF: Updating LVID @%x (%x)\n", Vcb
->LVid_loc
.extLocation
, Vcb
->LVid_loc
.extLength
));
385 len
= max(Vcb
->LVid_loc
.extLength
, Vcb
->BlockSize
);
387 if(lvid
->descTag
.tagSerialNum
> UDF_LVID_TTL
) {
388 // TODO: allocate space for new LVID
391 LVID_iUse
= UDFGetLVIDiUse(Vcb
);
393 if((LVID_iUse
->minUDFReadRev
== Vcb
->minUDFReadRev
) &&
394 (LVID_iUse
->minUDFReadRev
== Vcb
->minUDFReadRev
) &&
395 (LVID_iUse
->maxUDFWriteRev
== Vcb
->maxUDFWriteRev
) &&
396 (LVID_iUse
->numFiles
== Vcb
->numFiles
) &&
397 (LVID_iUse
->numDirs
== Vcb
->numDirs
))
400 LVID_iUse
->minUDFReadRev
= Vcb
->minUDFReadRev
;
401 LVID_iUse
->minUDFWriteRev
= Vcb
->minUDFWriteRev
;
402 LVID_iUse
->maxUDFWriteRev
= Vcb
->maxUDFWriteRev
;
404 LVID_iUse
->numFiles
= Vcb
->numFiles
;
405 LVID_iUse
->numDirs
= Vcb
->numDirs
;
408 UDFSetEntityID_imp(&(LVID_iUse
->impIdent
), UDF_ID_DEVELOPER
);
412 UDFPrint(("UDF: Opening LVID\n"));
413 lvid
->integrityType
= INTEGRITY_TYPE_CLOSE
;
415 UDFPrint(("UDF: Closing LVID\n"));
416 lvid
->integrityType
= INTEGRITY_TYPE_OPEN
;
419 equal
= equal
&& (Vcb
->IntegrityType
== lvid
->integrityType
);
421 // update Free Space Table
422 partFreeSpace
= (uint32
*)(lvid
+1);
423 for(i
=0; i
<lvid
->numOfPartitions
; i
++) {
424 pSize
= UDFGetPartFreeSpace(Vcb
, i
) >> Vcb
->LB2B_Bits
;
425 equal
= equal
&& (partFreeSpace
[i
] == pSize
);
426 partFreeSpace
[i
] = pSize
;
429 // Update LVID Header Descriptor
430 LVID_hd
= (LogicalVolHeaderDesc
*)&(lvid
->logicalVolContentsUse
);
431 equal
= equal
&& (LVID_hd
->uniqueID
== Vcb
->NextUniqueId
);
432 LVID_hd
->uniqueID
= Vcb
->NextUniqueId
;
435 UDFPrint(("UDF: equal Ids\n"));
436 return STATUS_SUCCESS
;
439 PTag
= &(lvid
->descTag
);
440 lvid
->lengthOfImpUse
=
441 sizeof(LogicalVolIntegrityDescImpUse
);
442 UDFSetUpTag(Vcb
, PTag
,
443 sizeof(LogicalVolIntegrityDesc
) +
444 sizeof(uint32
)*2*lvid
->numOfPartitions
+
445 sizeof(LogicalVolIntegrityDescImpUse
),
448 Vcb
->IntegrityType
= INTEGRITY_TYPE_OPEN
; // make happy auto-dirty
449 RC
= UDFWriteSectors(Vcb
, TRUE
, PTag
->tagLocation
, len
>> Vcb
->BlockSizeBits
, FALSE
, (int8
*)(lvid
), &WrittenBytes
);
450 WCacheFlushBlocks__(&(Vcb
->FastCache
), Vcb
, PTag
->tagLocation
, len
>> Vcb
->BlockSizeBits
);
451 // update it here to prevent recursion
452 Vcb
->IntegrityType
= lvid
->integrityType
;
455 } // end UDFUpdateLogicalVolInt()
458 This routine reads all sparing tables & stores them in contiguos memory
462 UDFUpdateSparingTable(
466 PSPARING_MAP RelocMap
;
467 // PSPARING_MAP NewRelocMap;
468 OSSTATUS status
= STATUS_SUCCESS
;
469 OSSTATUS status2
= STATUS_SUCCESS
;
471 PSPARING_TABLE SparTable
;
477 UDFPrint(("UDF: Updating Sparable Part Map:\n"));
478 if(!Vcb
->SparingTableModified
) return STATUS_SUCCESS
;
479 if(!Vcb
->SparingTable
) return STATUS_SUCCESS
;
481 BC
= (Vcb
->SparingTableLength
>> Vcb
->BlockSizeBits
) + 1;
482 SparTable
= (PSPARING_TABLE
)MyAllocatePool__(NonPagedPool
, BC
*Vcb
->BlockSize
);
483 if(!SparTable
) return STATUS_INSUFFICIENT_RESOURCES
;
484 // if a part of Sparing Table is already loaded,
485 // update it with data from another one
486 RelocMap
= Vcb
->SparingTable
;
487 // sort sparing table
491 for(i
=1;i
<Vcb
->SparingCount
;i
++) {
492 if(RelocMap
[i
-1].origLocation
> RelocMap
[i
].origLocation
) {
493 XCHG_DD(RelocMap
[i
-1].origLocation
, RelocMap
[i
].origLocation
);
495 XCHG_DD(RelocMap
[i
-1].mappedLocation
, RelocMap
[i
].mappedLocation
);
499 if(RelocMap
[i
-1].origLocation
== SPARING_LOC_AVAILABLE
&&
500 RelocMap
[i
].origLocation
== SPARING_LOC_AVAILABLE
&&
501 RelocMap
[i
-1].mappedLocation
> RelocMap
[i
].mappedLocation
) {
507 for(i
=0;i
<Vcb
->SparingCount
;i
++) {
508 UDFPrint((" @%x -> %x \n",
509 RelocMap
[i
].origLocation
, RelocMap
[i
].mappedLocation
));
512 Vcb
->SparingTableModified
= FALSE
;
514 // UDFPrint((" sparing table unchanged\n"));
515 // MyFreePool__(SparTable);
516 // return STATUS_SUCCESS;
519 // walk through all available Sparing Tables
520 for(i
=0;i
<Vcb
->SparingTableCount
;i
++) {
522 UDFPrint((" sparing table @%x\n", Vcb
->SparingTableLoc
[i
]));
523 status
= UDFReadSectors(Vcb
, FALSE
, Vcb
->SparingTableLoc
[i
], 1, FALSE
, (int8
*)SparTable
, &ReadBytes
);
524 // tag should be set to TID_UNUSED_DESC
525 if(OS_SUCCESS(status
) && (SparTable
->descTag
.tagIdent
== TID_UNUSED_DESC
)) {
527 BC2
= ((sizeof(SPARING_TABLE
) +
528 SparTable
->reallocationTableLen
*sizeof(SparingEntry
) +
530 >> Vcb
->BlockSizeBits
);
532 UDFPrint((" sizeSparingTable @%x too long: %x > %x\n",
533 Vcb
->SparingTableLoc
[i
], BC2
, BC
537 status
= UDFReadSectors(Vcb
, FALSE
, Vcb
->SparingTableLoc
[i
],
538 BC2
, FALSE
, (int8
*)SparTable
, &ReadBytes
);
540 if(!OS_SUCCESS(status
)) {
541 UDFPrint((" Error reading sizeSparingTable @%x (%x)\n",
542 Vcb
->SparingTableLoc
[i
], BC2
547 BC2
= ((sizeof(SPARING_TABLE
) +
548 Vcb
->SparingCount
*sizeof(SparingEntry
) +
550 >> Vcb
->BlockSizeBits
);
552 UDFPrint((" new sizeSparingTable @%x too long: %x > %x\n",
553 Vcb
->SparingTableLoc
[i
], BC2
, BC
558 SparTable
->reallocationTableLen
= (USHORT
)Vcb
->SparingCount
;
559 RtlCopyMemory((SparTable
+1), RelocMap
, Vcb
->SparingCount
*sizeof(SparingEntry
));
562 NewRelocMap = (PSPARING_MAP)(SparTable+1);
563 for(n=0; n<SparTable->reallocationTableLen; n++) {
564 for(m=0; m<Vcb->SparingCount; m++) {
565 if(RelocMap[m].mappedLocation == NewRelocMap[n].mappedLocation) {
566 if(RelocMap[m].origLocation != NewRelocMap[n].origLocation) {
567 UDFPrint((" update @%x (%x) -> @%x (%x)\n",
568 NewRelocMap[m].origLocation, NewRelocMap[m].mappedLocation,
569 RelocMap[m].origLocation, RelocMap[m].mappedLocation));
577 UDFPrint(("UDF: record updated\n"));
578 status
= UDFWriteSectors(Vcb
, FALSE
, Vcb
->SparingTableLoc
[i
], BC2
, FALSE
, (int8
*)SparTable
, &ReadBytes
);
579 if(!OS_SUCCESS(status
)) {
580 if(!OS_SUCCESS(status2
)) {
587 MyFreePool__(SparTable
);
588 if(!OS_SUCCESS(status2
)) {
592 } // end UDFUpdateSparingTable()
595 update Logical volume descriptor
600 IN UDF_VDS_RECORD Lba
,
601 IN PUNICODE_STRING VolIdent
604 LogicalVolDesc
* lvd
= NULL
;
605 #define CUR_IDENT_SZ (sizeof(lvd->logicalVolIdent))
606 dstring CS0
[CUR_IDENT_SZ
];
609 OSSTATUS status
= STATUS_SUCCESS
;
610 // OSSTATUS status2 = STATUS_SUCCESS;
612 status
= UDFUpdateSparingTable(Vcb
);
614 if(!(Vcb
->CompatFlags
& UDF_VCB_IC_W2K_COMPAT_VLABEL
)) {
618 lvd
= (LogicalVolDesc
*)MyAllocatePool__(NonPagedPool
, max(Vcb
->BlockSize
, sizeof(LogicalVolDesc
)) );
621 status
= STATUS_INSUFFICIENT_RESOURCES
;
625 UDFPrint(("UDF: Updating LVD @%x (%x)\n", Lba
.block
, Vcb
->BlockSize
));
627 status
= UDFSetDstring(&(Vcb
->VolIdent
), (dstring
*)&CS0
, CUR_IDENT_SZ
);
628 if(!OS_SUCCESS(status
)) {
629 if(status
== STATUS_INVALID_PARAMETER
) {
630 status
= STATUS_INVALID_VOLUME_LABEL
;
636 status
= STATUS_INVALID_PARAMETER
;
639 status
= UDFReadTagged(Vcb
, (int8
*)lvd
, Lba
.block
, Lba
.block
, &ident
);
640 if(!OS_SUCCESS(status
)) goto Err_SetVI
;
641 if(ident
!= TID_LOGICAL_VOL_DESC
) {
642 status
= STATUS_FILE_CORRUPT_ERROR
;
646 if(RtlCompareMemory(lvd
->logicalVolIdent
, CS0
, CUR_IDENT_SZ
) == CUR_IDENT_SZ
) {
648 UDFPrint(("UDF: equal VolIds\n"));
649 status
= STATUS_SUCCESS
;
652 RtlCopyMemory(lvd
->logicalVolIdent
, CS0
, CUR_IDENT_SZ
);
654 lvd
->descTag
.tagSerialNum
--;
655 UDFSetUpTag(Vcb
, (tag
*)lvd
, lvd
->descTag
.descCRCLength
, Lba
.block
);
657 status
= UDFWriteSectors(Vcb
, TRUE
, Lba
.block
, 1, FALSE
, (int8
*)lvd
, &WrittenBytes
);
667 } // end UDFUpdateLogicalVol()
670 This routine updates volume descriptor sequence
681 int8
* Buf
= (int8
*)DbgAllocatePool(NonPagedPool
,Vcb
->LBlockSize
);
682 UDF_VDS_RECORD vds
[VDS_POS_LENGTH
];
686 if (!Buf
) return STATUS_INSUFFICIENT_RESOURCES
;
687 RtlZeroMemory(vds
, sizeof(UDF_VDS_RECORD
) * VDS_POS_LENGTH
);
688 if(!OS_SUCCESS(status
= UDFReadVDS(Vcb
, block
, lastblock
, (PUDF_VDS_RECORD
)&vds
, Buf
))) {
694 // update USD (if any)
695 for (i=0; i<VDS_POS_LENGTH; i++) {
697 status = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident);
698 if(OS_SUCCESS(status) && (i == VDS_POS_PARTITION_DESC)) {
699 // load partition descriptor(s)
700 int8* Buf2 = (int8*)DbgAllocatePool(NonPagedPool,Vcb->BlockSize);
703 return STATUS_INSUFFICIENT_RESOURCES;
705 for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++) {
706 UDFReadTagged(Vcb,Buf2, j, j, &ident);
707 if (ident == TID_UNALLOC_SPACE_DESC)
708 // This implememtation doesn't support USD ;) recording
709 // So, we'll make'em blank, but record all bitmaps
710 UDFUpdateUSpaceDesc(Vcb,Buf2);
717 for (i
=0; i
<VDS_POS_LENGTH
; i
++) {
719 status
= UDFReadTagged(Vcb
, Buf
, vds
[i
].block
, vds
[i
].block
, &ident
);
720 if(!OS_SUCCESS(status
))
723 if(i
== VDS_POS_PARTITION_DESC
) {
726 // update partition descriptor(s)
727 int8
* Buf2
= (int8
*)DbgAllocatePool(NonPagedPool
,Vcb
->BlockSize
);
730 return STATUS_INSUFFICIENT_RESOURCES
;
732 UDFUpdatePartDesc(Vcb
,Buf
);
733 for (j
=vds
[i
].block
+1; j
<vds
[VDS_POS_TERMINATING_DESC
].block
; j
++) {
734 UDFReadTagged(Vcb
,Buf2
, j
, j
, &ident
);
735 if (ident
== TID_PARTITION_DESC
)
736 UDFUpdatePartDesc(Vcb
,Buf2
);
741 // update Vol Ident Desc
742 if(i
== VDS_POS_LOGICAL_VOL_DESC
) {
743 status
= UDFUpdateLogicalVol(Vcb
, vds
[VDS_POS_LOGICAL_VOL_DESC
], &(Vcb
->VolIdent
));
744 if(!OS_SUCCESS(status
))
752 } // end UDFUpdateVDS()
753 #endif //UDF_READ_ONLY_BUILD
758 IN PUNICODE_STRING UName
,
764 uint32 len
= Length
-1;
766 UDFCompressUnicode(UName
, &CS0
, &len
);
768 return STATUS_INSUFFICIENT_RESOURCES
;
771 return STATUS_INVALID_PARAMETER
;
773 RtlCopyMemory(Dest
, CS0
, len
);
776 RtlZeroMemory(Dest
+len
, Length
-1-len
);
777 Dest
[Length
-1] = (uint8
)len
;
779 } // end UDFSetDstring()
784 IN OUT PUNICODE_STRING UName
,
789 uint32 len
= Dest
[Length
-1];
791 UDFDecompressUnicode(UName
, Dest
, len
, NULL
);
793 } // end UDFGetDstring()
795 #ifndef UDF_READ_ONLY_BUILD
797 This routine updates Volume Label & some other features stored in
803 IN UDF_VDS_RECORD Lba
,
804 IN PUNICODE_STRING VolIdent
807 #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent))
808 PrimaryVolDesc
* pvoldesc
= (PrimaryVolDesc
*)MyAllocatePool__(NonPagedPool
, max(Vcb
->BlockSize
, sizeof(PrimaryVolDesc
)) );
810 dstring CS0
[CUR_IDENT_SZ
];
814 if(!pvoldesc
) return STATUS_INSUFFICIENT_RESOURCES
;
816 UDFPrint(("UDF: Updating PVD @%x (%x)\n", Lba
.block
, Vcb
->BlockSize
));
818 status
= UDFSetDstring(&(Vcb
->VolIdent
), (dstring
*)&CS0
, CUR_IDENT_SZ
);
819 if(!OS_SUCCESS(status
)) {
820 if(status
== STATUS_INVALID_PARAMETER
) {
821 status
= STATUS_INVALID_VOLUME_LABEL
;
827 status
= STATUS_INVALID_PARAMETER
;
830 status
= UDFReadTagged(Vcb
, (int8
*)pvoldesc
, Lba
.block
, Lba
.block
, &ident
);
831 if(!OS_SUCCESS(status
)) goto Err_SetVI
;
832 if(ident
!= TID_PRIMARY_VOL_DESC
) {
833 status
= STATUS_FILE_CORRUPT_ERROR
;
837 if(RtlCompareMemory(pvoldesc
->volIdent
, CS0
, CUR_IDENT_SZ
) == CUR_IDENT_SZ
) {
839 status
= STATUS_SUCCESS
;
842 RtlCopyMemory(pvoldesc
->volIdent
, CS0
, CUR_IDENT_SZ
);
844 pvoldesc
->descTag
.tagSerialNum
--;
845 UDFSetUpTag(Vcb
, (tag
*)pvoldesc
, pvoldesc
->descTag
.descCRCLength
, Lba
.block
);
847 status
= UDFWriteSectors(Vcb
, TRUE
, Lba
.block
, 1, FALSE
, (int8
*)pvoldesc
, &WrittenBytes
);
849 MyFreePool__(pvoldesc
);
853 } // end UDFUpdateVolIdent()
854 #endif //UDF_READ_ONLY_BUILD
857 UDFUpdateNonAllocated(
863 uint32 plen
, pstart
, pend
;
866 PEXTENT_MAP Map
= NULL
;
867 PEXTENT_INFO DataLoc
;
869 UDFPrint(("UDFUpdateNonAllocated:\n"));
870 if(!Vcb
->NonAllocFileInfo
) {
871 return STATUS_SUCCESS
;
873 if(!(bad_bm
= Vcb
->BSBM_Bitmap
)) {
874 return STATUS_SUCCESS
;
877 DataLoc
= &(Vcb
->NonAllocFileInfo
->Dloc
->DataLoc
);
878 ASSERT(!DataLoc
->Offset
);
879 if(Vcb
->NonAllocFileInfo
->Dloc
->DataLoc
.Offset
) {
880 UDFPrint(("NonAllocFileInfo in IN_ICB mode !!!\n"));
881 return STATUS_SUCCESS
;
883 PartNum
= UDFGetPartNumByPhysLba(Vcb
, Vcb
->NonAllocFileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
884 pstart
= UDFPartStart(Vcb
, PartNum
);
885 plen
= UDFPartLen(Vcb
, PartNum
);
886 pend
= min(pstart
+ plen
, Vcb
->FSBM_BitCount
);
889 for(i
=pstart
; i
<pend
; i
++) {
890 if(!UDFGetBadBit(bad_bm
, i
))
892 // add BAD blocks to unallocatable space
893 // if the block is already in NonAllocatable, ignore it
894 if(UDFLocateLbaInExtent(Vcb
, DataLoc
->Mapping
, i
) != LBA_OUT_OF_EXTENT
) {
895 UDFPrint(("lba %#x is already in NonAllocFileInfo\n", i
));
898 UDFPrint(("add lba %#x to NonAllocFileInfo\n", i
));
899 DataLoc
->Modified
= TRUE
;
900 Ext
.extLength
= Vcb
->LBlockSize
;
901 // align lba on LogicalBlock boundary
902 Ext
.extLocation
= i
& ~((1<<Vcb
->LB2B_Bits
) - 1);
903 Map
= UDFExtentToMapping(&Ext
);
904 DataLoc
->Mapping
= UDFMergeMappings(DataLoc
->Mapping
, Map
);
906 UDFPackMapping(Vcb
, DataLoc
);
907 DataLoc
->Length
= UDFGetExtentLength(DataLoc
->Mapping
);
908 UDFFlushFile__(Vcb
, Vcb
->NonAllocFileInfo
);
910 // ensure that BAD space is marked as USED
911 UDFMarkSpaceAsXXX(Vcb
, 0, &(DataLoc
->Mapping
[0]), AS_USED
); // mark as used
913 UDFPrint(("UDFUpdateNonAllocated: done\n"));
914 return STATUS_SUCCESS
;
915 } // end UDFUpdateNonAllocated()
918 This routine rebuilds & flushes all system areas
925 #ifndef UDF_READ_ONLY_BUILD
928 if((Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
)
930 return STATUS_SUCCESS
;
931 // prevent discarding metadata
932 Vcb
->VCBFlags
|= UDF_VCB_ASSUME_ALL_USED
;
934 // flush internal cache
935 if(WCacheGetWriteBlockCount__(&(Vcb
->FastCache
)) >= (Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
) )
936 WCacheFlushAll__(&(Vcb
->FastCache
), Vcb
);
938 return UDFRecordVAT(Vcb
);
941 UDFFlushAllCachedAllocations(Vcb
, UDF_PREALLOC_CLASS_FE
);
942 UDFFlushAllCachedAllocations(Vcb
, UDF_PREALLOC_CLASS_DIR
);
944 if(Vcb
->VerifyOnWrite
) {
945 UDFPrint(("UDF: Flushing cache for verify\n"));
946 //WCacheFlushAll__(&(Vcb->FastCache), Vcb);
947 WCacheFlushBlocks__(&(Vcb
->FastCache
), Vcb
, 0, Vcb
->LastLBA
);
951 // synchronize BAD Block bitmap and NonAllocatable
952 UDFUpdateNonAllocated(Vcb
);
954 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
958 if(!OS_SUCCESS(UDFUpdateVolIdent(Vcb
, Vcb
->PVolDescAddr
, &(Vcb
->VolIdent
))))
959 UDFPrint(("Error updating VolIdent (1)\n"));
960 if(!OS_SUCCESS(UDFUpdateVolIdent(Vcb
, Vcb
->PVolDescAddr2
, &(Vcb
->VolIdent
))))
961 UDFPrint(("Error updating VolIdent (2)\n"));
963 UDFUpdateVolIdent(Vcb
, Vcb
->PVolDescAddr
, &(Vcb
->VolIdent
));
964 UDFUpdateVolIdent(Vcb
, Vcb
->PVolDescAddr2
, &(Vcb
->VolIdent
));
967 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
968 // check if we should update BM
969 if(Vcb
->FSBM_ByteCount
== RtlCompareMemory(Vcb
->FSBM_Bitmap
, Vcb
->FSBM_OldBitmap
, Vcb
->FSBM_ByteCount
)) {
976 if(!OS_SUCCESS(UDFUpdateVDS(Vcb
, Vcb
->VDS1
, Vcb
->VDS1
+ Vcb
->VDS1_Len
, flags
)))
977 UDFPrint(("Error updating Main VDS\n"));
978 if(!OS_SUCCESS(UDFUpdateVDS(Vcb
, Vcb
->VDS2
, Vcb
->VDS2
+ Vcb
->VDS2_Len
, flags
)))
979 UDFPrint(("Error updating Reserve VDS\n"));
981 UDFUpdateVDS(Vcb
, Vcb
->VDS1
, Vcb
->VDS1
+ Vcb
->VDS1_Len
, flags
);
982 UDFUpdateVDS(Vcb
, Vcb
->VDS2
, Vcb
->VDS2
+ Vcb
->VDS2_Len
, flags
);
985 // Update Integrity Desc if any
986 if(Vcb
->LVid
&& Vcb
->origIntegrityType
== INTEGRITY_TYPE_CLOSE
) {
987 UDFUpdateLogicalVolInt(Vcb
, TRUE
);
991 RtlCopyMemory(Vcb
->FSBM_OldBitmap
, Vcb
->FSBM_Bitmap
, Vcb
->FSBM_ByteCount
);
993 //skip_update_bitmap:
995 Vcb
->VCBFlags
&= ~UDF_VCB_ASSUME_ALL_USED
;
997 UDFReleaseResource(&(Vcb
->BitMapResource1
));
998 #endif //UDF_READ_ONLY_BUILD
1000 return STATUS_SUCCESS
;
1001 } // end UDFUmount__()
1003 /*************************************************************************/
1006 Find an anchor volume descriptor.
1007 The UDFGetDiskInfoAndVerify() will invoke this routine to find & check
1008 Anchor Volume Descriptors on the target device
1012 PVCB Vcb
// Volume control block
1015 // OSSTATUS RC = STATUS_SUCCESS;
1021 int8
* Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
1022 BOOLEAN MRW_candidate
;
1023 BOOLEAN IsMRW
= (Vcb
->MRWStatus
!= 0);
1027 UDFPrint(("UDFFindAnchor\n"));
1028 // init probable locations...
1029 RtlZeroMemory(&(Vcb
->Anchor
), sizeof(Vcb
->Anchor
));
1030 Vcb
->Anchor
[0] = 256 + Vcb
->FirstLBALastSes
;
1031 Vcb
->Anchor
[1] = 512 + Vcb
->FirstLBALastSes
;
1032 Vcb
->Anchor
[2] = 256 + Vcb
->TrackMap
[Vcb
->LastTrackNum
].FirstLba
;
1033 Vcb
->Anchor
[3] = 512 + Vcb
->TrackMap
[Vcb
->LastTrackNum
].FirstLba
;
1034 Vcb
->Anchor
[4] = Vcb
->LastLBA
- 256;
1035 Vcb
->Anchor
[5] = Vcb
->LastLBA
- 256 + 1;
1036 Vcb
->Anchor
[6] = Vcb
->LastLBA
- 256 - 2;
1038 Vcb
->Anchor
[7] = Vcb
->LastLBA
- 2;
1039 Vcb
->Anchor
[8] = Vcb
->LastLBA
;
1040 Vcb
->Anchor
[9] = Vcb
->LastLBA
- 512;
1041 // Vcb->Anchor[7] = Vcb->LastLBA - 256 - 7;
1042 // Vcb->Anchor[8] = Vcb->LastLBA - 512 - 2;
1043 // Vcb->Anchor[9] = Vcb->LastLBA - 512 - 7;
1046 // ... and check them
1047 for (i
=0; i
<sizeof(Vcb
->Anchor
)/sizeof(int); i
++) {
1048 if(Vcb
->Anchor
[i
] > Vcb
->LastLBA
)
1050 MRW_candidate
= FALSE
;
1051 if(Vcb
->Anchor
[i
]) {
1052 UDFPrint(("check Anchor %x\n", Vcb
->Anchor
[i
]));
1053 if(!OS_SUCCESS(status
= UDFReadTagged(Vcb
,Buf
,
1054 Vcb
->Anchor
[i
], Vcb
->Anchor
[i
], &ident
))) {
1057 if(!IsMRW
&& (i
<2) &&
1058 (Vcb
->CompatFlags
& UDF_VCB_IC_MRW_ADDR_PROBLEM
)) {
1059 if(OS_SUCCESS(status
= UDFReadTagged(Vcb
,Buf
,
1060 Vcb
->Anchor
[i
]+MRW_DMA_OFFSET
, Vcb
->Anchor
[i
], &ident
))) {
1061 // do MRW workaround.....
1062 UDFPrint(("UDF: looks like we have MRW....\n"));
1063 MRW_candidate
= TRUE
;
1064 goto MRW_workaround
;
1069 if(status
== STATUS_NONEXISTENT_SECTOR
) {
1070 UDFPrint(("UDF: disk seems to be incomplete\n"));
1075 if((ident
!= TID_ANCHOR_VOL_DESC_PTR
) && ((i
<6) ||
1076 (ident
!= TID_FILE_ENTRY
&& ident
!= TID_EXTENDED_FILE_ENTRY
))) {
1079 UDFPrint(("UDF: Found AVD at %x (point %d)\n",Vcb
->Anchor
[i
], i
));
1081 LastBlock
= Vcb
->LastLBA
;
1083 UDFPrint(("UDF: looks like we _*really*_ have MRW....\n"));
1085 ASSERT(Vcb
->LastReadTrack
== 1);
1086 Vcb
->TrackMap
[Vcb
->LastReadTrack
].Flags
|= TrackMap_FixMRWAddressing
;
1087 WCachePurgeAll__(&(Vcb
->FastCache
), Vcb
);
1088 UDFPrint(("UDF: MRW on non-MRW drive => ReadOnly"));
1089 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
1091 UDFRegisterFsStructure(Vcb
, Vcb
->Anchor
[i
], Vcb
->BlockSize
);
1099 UDFPrint(("UDF: -----------------\nUDF: Last block %x\n",LastBlock
));
1102 } // end UDFFindAnchor()
1105 Look for Volume recognition sequence
1112 VolStructDesc
*vsd
= NULL
;
1115 uint32 BeginOffset
= Vcb
->FirstLBA
;
1117 int8
* buffer
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
1120 if(!buffer
) return 0;
1121 // Relative to First LBA in Last Session
1122 offset
= Vcb
->FirstLBA
+ 0x10;
1124 UDFPrint(("UDFFindVRS:\n"));
1126 // Process the sequence (if applicable)
1127 for (;(offset
-BeginOffset
<=0x20); offset
++) {
1129 RC
= UDFReadSectors(Vcb
, FALSE
, offset
, 1, FALSE
, buffer
, &ReadBytes
);
1130 if(!OS_SUCCESS(RC
)) continue;
1132 // Look for ISO descriptors
1133 vsd
= (VolStructDesc
*)(buffer
);
1135 if(vsd
->stdIdent
[0]) {
1136 if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_CD001
, STD_ID_LEN
))
1138 retStat
|= VRS_ISO9660_FOUND
;
1139 switch (vsd
->structType
)
1142 UDFPrint(("UDF: ISO9660 Boot Record found\n"));
1145 UDFPrint(("UDF: ISO9660 Primary Volume Descriptor found\n"));
1148 UDFPrint(("UDF: ISO9660 Supplementary Volume Descriptor found\n"));
1151 UDFPrint(("UDF: ISO9660 Volume Partition Descriptor found\n"));
1154 UDFPrint(("UDF: ISO9660 Volume Descriptor Set Terminator found\n"));
1157 UDFPrint(("UDF: ISO9660 VRS (%u) found\n", vsd
->structType
));
1161 else if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_BEA01
, STD_ID_LEN
))
1163 UDFPrint(("UDF: BEA01 Found\n"));
1165 else if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_TEA01
, STD_ID_LEN
))
1167 UDFPrint(("UDF: TEA01 Found\n"));
1170 else if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_NSR02
, STD_ID_LEN
))
1172 retStat
|= VRS_NSR02_FOUND
;
1173 UDFPrint(("UDF: NSR02 Found\n"));
1176 else if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_NSR03
, STD_ID_LEN
))
1178 retStat
|= VRS_NSR03_FOUND
;
1179 UDFPrint(("UDF: NSR03 Found\n"));
1185 MyFreePool__(buffer
);
1188 } // end UDFFindVRS()
1191 process Primary volume descriptor
1196 int8
* Buf
// pointer to buffer containing PVD
1199 PrimaryVolDesc
*pvoldesc
;
1200 // OSSTATUS RC = STATUS_SUCCESS;
1202 pvoldesc
= (PrimaryVolDesc
*)Buf
;
1203 UDFPrint(("UDF: PrimaryVolDesc:\n"));
1204 UDFPrint(("volDescSeqNum = %d\n", pvoldesc
->volDescSeqNum
));
1205 UDFPrint(("primaryVolDescNum = %d\n", pvoldesc
->primaryVolDescNum
));
1206 // remember recording time...
1207 Vcb
->VolCreationTime
= UDFTimeToNT(&(pvoldesc
->recordingDateAndTime
));
1209 #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent))
1210 if (Vcb
->VolIdent
.Buffer
) {
1211 MyFreePool__(Vcb
->VolIdent
.Buffer
);
1213 UDFGetDstring(&(Vcb
->VolIdent
), (dstring
*)&(pvoldesc
->volIdent
), CUR_IDENT_SZ
);
1215 UDFPrint(("volIdent[] = '%ws'\n", Vcb
->VolIdent
.Buffer
));
1217 UDFPrint(("volSeqNum = %d\n", pvoldesc
->volSeqNum
));
1218 UDFPrint(("maxVolSeqNum = %d\n", pvoldesc
->maxVolSeqNum
));
1219 UDFPrint(("interchangeLvl = %d\n", pvoldesc
->interchangeLvl
));
1220 UDFPrint(("maxInterchangeLvl = %d\n", pvoldesc
->maxInterchangeLvl
));
1221 UDFPrint(("charSetList = %d\n", pvoldesc
->charSetList
));
1222 UDFPrint(("maxCharSetList = %d\n", pvoldesc
->maxCharSetList
));
1223 // ...& just print VolSetIdent
1224 UNICODE_STRING instr
;
1225 #define CUR_IDENT_SZ (sizeof(pvoldesc->volSetIdent))
1226 UDFGetDstring(&instr
, (dstring
*)&(pvoldesc
->volSetIdent
), CUR_IDENT_SZ
);
1228 UDFPrint(("volSetIdent[] = '%ws'\n", instr
.Buffer
));
1229 // UDFPrint(("maxInterchangeLvl = %d\n", pvoldesc->maxInterchangeLvl));
1230 UDFPrint(("flags = %x\n", pvoldesc
->flags
));
1231 if(instr
.Buffer
) MyFreePool__(instr
.Buffer
);
1233 } // end UDFLoadPVolDesc()
1236 load Logical volume integrity descriptor
1239 UDFLoadLogicalVolInt(
1240 PDEVICE_OBJECT DeviceObject
,
1245 OSSTATUS RC
= STATUS_SUCCESS
;
1250 LogicalVolIntegrityDescImpUse
* LVID_iUse
;
1251 LogicalVolHeaderDesc
* LVID_hd
;
1253 BOOLEAN read_last
= FALSE
;
1254 uint32 lvid_count
= 0;
1258 MyFreePool__(Vcb
->LVid
);
1261 // walk through all sectors inside LogicalVolumeIntegrityDesc
1262 while(loc
.extLength
) {
1263 UDFPrint(("UDF: Reading LVID @%x (%x)\n", loc
.extLocation
, loc
.extLength
));
1264 len
= max(loc
.extLength
, Vcb
->BlockSize
);
1265 Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,len
);
1267 return STATUS_INSUFFICIENT_RESOURCES
;
1268 RC
= UDFReadTagged(Vcb
,Buf
, loc
.extLocation
, loc
.extLocation
, &ident
);
1269 if(!OS_SUCCESS(RC
)) {
1271 UDFPrint(("UDF: Reading LVID @%x (%x) failed.\n", loc
.extLocation
, loc
.extLength
));
1272 switch(Vcb
->PartitialDamagedVolumeAction
) {
1273 case UDF_PART_DAMAGED_RO
:
1274 UDFPrint(("UDF: Switch to r/o mode.\n"));
1275 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
1276 Vcb
->UserFSFlags
|= UDF_USER_FS_FLAGS_MEDIA_DEFECT_RO
;
1277 RC
= STATUS_SUCCESS
;
1279 case UDF_PART_DAMAGED_NO
:
1280 UDFPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n"));
1281 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
1282 //RC = STATUS_WRONG_VOLUME;
1284 case UDF_PART_DAMAGED_RW
:
1286 UDFPrint(("UDF: Keep r/w mode for your own risk.\n"));
1287 RC
= STATUS_SUCCESS
;
1288 // asume we have INTEGRITY_TYPE_CLOSE
1289 Vcb
->IntegrityType
= INTEGRITY_TYPE_CLOSE
;
1296 UDFRegisterFsStructure(Vcb
, loc
.extLocation
, len
);
1297 // handle Terminal Entry
1298 if(ident
== TID_TERMINAL_ENTRY
) {
1305 if(ident
!= TID_LOGICAL_VOL_INTEGRITY_DESC
) {
1306 RC
= STATUS_DISK_CORRUPT_ERROR
;
1310 Vcb
->LVid
= (LogicalVolIntegrityDesc
*)Buf
;
1311 RC
= UDFReadData(Vcb
, TRUE
, ((uint64
)(loc
.extLocation
)) << Vcb
->BlockSizeBits
, len
, FALSE
, Buf
, &_ReadBytes
);
1314 Vcb
->LVid
->nextIntegrityExt
.extLength
) {
1317 loc
= Vcb
->LVid
->nextIntegrityExt
;
1320 if(lvid_count
> UDF_MAX_LVID_CHAIN_LENGTH
) {
1321 RC
= STATUS_DISK_CORRUPT_ERROR
;
1327 // process last LVID
1328 Vcb
->origIntegrityType
=
1329 Vcb
->IntegrityType
= Vcb
->LVid
->integrityType
;
1330 Vcb
->LVid_loc
= loc
;
1332 LVID_iUse
= UDFGetLVIDiUse(Vcb
);
1334 UDFPrint(("UDF: Last LVID:\n"));
1335 UDFPrint((" minR: %x\n",LVID_iUse
->minUDFReadRev
));
1336 UDFPrint((" minW: %x\n",LVID_iUse
->minUDFWriteRev
));
1337 UDFPrint((" maxW: %x\n",LVID_iUse
->maxUDFWriteRev
));
1338 UDFPrint((" Type: %s\n",!Vcb
->IntegrityType
? "Open" : "Close"));
1340 Vcb
->minUDFReadRev
= LVID_iUse
->minUDFReadRev
;
1341 Vcb
->minUDFWriteRev
= LVID_iUse
->minUDFWriteRev
;
1342 Vcb
->maxUDFWriteRev
= LVID_iUse
->maxUDFWriteRev
;
1344 Vcb
->numFiles
= LVID_iUse
->numFiles
;
1345 Vcb
->numDirs
= LVID_iUse
->numDirs
;
1346 UDFPrint((" nFiles: %x\n",Vcb
->numFiles
));
1347 UDFPrint((" nDirs: %x\n",Vcb
->numDirs
));
1349 // Check if we can understand this format
1350 if(Vcb
->minUDFReadRev
> UDF_MAX_READ_REVISION
)
1351 RC
= STATUS_UNRECOGNIZED_VOLUME
;
1352 // Check if we know how to write here
1353 if(Vcb
->minUDFWriteRev
> UDF_MAX_WRITE_REVISION
) {
1354 UDFPrint((" Target FS requires: %x Revision => ReadOnly\n",Vcb
->minUDFWriteRev
));
1355 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
1356 Vcb
->UserFSFlags
|= UDF_USER_FS_FLAGS_NEW_FS_RO
;
1359 LVID_hd
= (LogicalVolHeaderDesc
*)&(Vcb
->LVid
->logicalVolContentsUse
);
1360 Vcb
->NextUniqueId
= LVID_hd
->uniqueID
;
1361 UDFPrint((" Next FID: %x\n",Vcb
->NextUniqueId
));
1367 } // end UDFLoadLogicalVolInt()
1371 load Logical volume descriptor
1375 PDEVICE_OBJECT DeviceObject
,
1381 LogicalVolDesc
*lvd
= (LogicalVolDesc
*)Buf
;
1384 OSSTATUS status
= STATUS_SUCCESS
;
1385 UDFPrint(("UDF: LogicalVolDesc\n"));
1386 // Validate partition map counter
1387 if(!(Vcb
->Partitions
)) {
1388 Vcb
->PartitionMaps
= lvd
->numPartitionMaps
;
1389 Vcb
->Partitions
= (PUDFPartMap
)MyAllocatePool__(NonPagedPool
, sizeof(UDFPartMap
) * Vcb
->PartitionMaps
);
1390 if(!Vcb
->Partitions
)
1391 return STATUS_INSUFFICIENT_RESOURCES
;
1393 if(Vcb
->PartitionMaps
!= lvd
->numPartitionMaps
)
1394 return STATUS_DISK_CORRUPT_ERROR
;
1396 UDFPrint(("UDF: volDescSeqNum = %x\n", lvd
->volDescSeqNum
));
1397 // Get logical block size (may be different from physical)
1398 Vcb
->LBlockSize
= lvd
->logicalBlockSize
;
1399 // Get current UDF revision
1400 // Get Read-Only flags
1401 UDFReadEntityID_Domain(Vcb
, &(lvd
->domainIdent
));
1403 if(Vcb
->LBlockSize
< Vcb
->BlockSize
)
1404 return STATUS_DISK_CORRUPT_ERROR
;
1405 switch(Vcb
->LBlockSize
) {
1406 case 512: Vcb
->LBlockSizeBits
= 9; break;
1407 case 1024: Vcb
->LBlockSizeBits
= 10; break;
1408 case 2048: Vcb
->LBlockSizeBits
= 11; break;
1409 case 4096: Vcb
->LBlockSizeBits
= 12; break;
1410 case 8192: Vcb
->LBlockSizeBits
= 13; break;
1411 case 16384: Vcb
->LBlockSizeBits
= 14; break;
1412 case 32768: Vcb
->LBlockSizeBits
= 15; break;
1413 case 65536: Vcb
->LBlockSizeBits
= 16; break;
1415 UDFPrint(("UDF: Bad block size (%ld)\n", Vcb
->LBlockSize
));
1416 return STATUS_DISK_CORRUPT_ERROR
;
1418 UDFPrint(("UDF: logical block size (%ld)\n", Vcb
->LBlockSize
));
1419 Vcb
->LB2B_Bits
= Vcb
->LBlockSizeBits
- Vcb
->BlockSizeBits
;
1420 UDFPrint(("UDF: mapTableLength = %x\n", lvd
->mapTableLength
));
1421 UDFPrint(("UDF: numPartitionMaps = %x\n", lvd
->numPartitionMaps
));
1422 // walk through all available part maps
1424 i
<Vcb
->PartitionMaps
&& offset
<lvd
->mapTableLength
;
1425 i
++,offset
+=((GenericPartitionMap
*)( ((uint8
*)(lvd
+1))+offset
) )->partitionMapLength
)
1427 GenericPartitionMap
* gpm
= (GenericPartitionMap
*)(((uint8
*)(lvd
+1))+offset
);
1428 type
= gpm
->partitionMapType
;
1429 UDFPrint(("Partition (%d) type %x, len %x\n", i
, type
, gpm
->partitionMapLength
));
1430 if(type
== PARTITION_MAP_TYPE_1
)
1432 GenericPartitionMap1
*gpm1
= (GenericPartitionMap1
*)(((uint8
*)(lvd
+1))+offset
);
1434 Vcb
->Partitions
[i
].PartitionType
= UDF_TYPE1_MAP15
;
1435 Vcb
->Partitions
[i
].VolumeSeqNum
= gpm1
->volSeqNum
;
1436 Vcb
->Partitions
[i
].PartitionNum
= gpm1
->partitionNum
;
1437 status
= STATUS_SUCCESS
;
1439 else if(type
== PARTITION_MAP_TYPE_2
)
1441 UdfPartitionMap2
* upm2
= (UdfPartitionMap2
*)(((uint8
*)(lvd
+1))+offset
);
1442 if(!strncmp((int8
*)&(upm2
->partIdent
.ident
), UDF_ID_VIRTUAL
, strlen(UDF_ID_VIRTUAL
)))
1444 UDFIdentSuffix
* udfis
=
1445 (UDFIdentSuffix
*)&(upm2
->partIdent
.identSuffix
);
1447 if( (udfis
->currentRev
== 0x0150)/* ||
1448 (Vcb->CurrentUDFRev == 0x0150)*/ ) {
1449 UDFPrint(("Found VAT 1.50\n"));
1450 Vcb
->Partitions
[i
].PartitionType
= UDF_VIRTUAL_MAP15
;
1452 if( (udfis
->currentRev
== 0x0200) ||
1453 (udfis
->currentRev
== 0x0201) /*||
1454 (Vcb->CurrentUDFRev == 0x0200) ||
1455 (Vcb->CurrentUDFRev == 0x0201)*/ ) {
1456 UDFPrint(("Found VAT 2.00\n"));
1457 Vcb
->Partitions
[i
].PartitionType
= UDF_VIRTUAL_MAP20
;
1459 status
= STATUS_SUCCESS
;
1461 else if(!strncmp((int8
*)&(upm2
->partIdent
.ident
), UDF_ID_SPARABLE
, strlen(UDF_ID_SPARABLE
)))
1463 UDFPrint(("Load sparing table\n"));
1464 PSPARABLE_PARTITION_MAP spm
= (PSPARABLE_PARTITION_MAP
)(((uint8
*)(lvd
+1))+offset
);
1465 Vcb
->Partitions
[i
].PartitionType
= UDF_SPARABLE_MAP15
;
1466 status
= UDFLoadSparingTable(Vcb
, spm
);
1468 else if(!strncmp((int8
*)&(upm2
->partIdent
.ident
), UDF_ID_METADATA
, strlen(UDF_ID_METADATA
)))
1470 UDFPrint(("Found metadata partition\n"));
1471 // PMETADATA_PARTITION_MAP mpm = (PMETADATA_PARTITION_MAP)(((uint8*)(lvd+1))+offset);
1472 Vcb
->Partitions
[i
].PartitionType
= UDF_METADATA_MAP25
;
1473 //status = UDFLoadSparingTable(Vcb, spm);
1477 UDFPrint(("Unknown ident: %s\n", upm2
->partIdent
.ident
));
1480 Vcb
->Partitions
[i
].VolumeSeqNum
= upm2
->volSeqNum
;
1481 Vcb
->Partitions
[i
].PartitionNum
= upm2
->partitionNum
;
1486 // remember FileSet location
1487 long_ad
*la
= (long_ad
*)&(lvd
->logicalVolContentsUse
[0]);
1488 *fileset
= (la
->extLocation
);
1489 UDFPrint(("FileSet found in LogicalVolDesc at block=%x, partition=%d\n",
1490 fileset
->logicalBlockNum
,
1491 fileset
->partitionReferenceNum
));
1493 if(OS_SUCCESS(status
)) {
1494 // load Integrity Desc if any
1495 if(lvd
->integritySeqExt
.extLength
)
1496 status
= UDFLoadLogicalVolInt(DeviceObject
,Vcb
,lvd
->integritySeqExt
);
1499 } // end UDFLoadLogicalVol()
1502 UDFLoadBogusLogicalVol(
1503 PDEVICE_OBJECT DeviceObject
,
1509 // LogicalVolDesc *lvd = (LogicalVolDesc *)Buf;
1510 UDFPrint(("UDF: Bogus LogicalVolDesc\n"));
1511 // Validate partition map counter
1512 if(!(Vcb
->Partitions
)) {
1513 Vcb
->PartitionMaps
= 1;
1514 Vcb
->Partitions
= (PUDFPartMap
)MyAllocatePool__(NonPagedPool
, sizeof(UDFPartMap
) * Vcb
->PartitionMaps
);
1515 if(!Vcb
->Partitions
)
1516 return STATUS_INSUFFICIENT_RESOURCES
;
1518 if(Vcb
->PartitionMaps
!= 1)
1519 return STATUS_DISK_CORRUPT_ERROR
;
1521 UDFPrint(("UDF: volDescSeqNum = %x\n", 0));
1522 // Get logical block size (may be different from physical)
1523 Vcb
->LBlockSize
= 2048;
1524 // Get current UDF revision
1525 // Get Read-Only flags
1526 // UDFReadEntityID_Domain(Vcb, &(lvd->domainIdent));
1528 if(Vcb
->LBlockSize
< Vcb
->BlockSize
)
1529 return STATUS_DISK_CORRUPT_ERROR
;
1530 Vcb
->LBlockSizeBits
= 11;
1531 UDFPrint(("UDF: logical block size (%ld)\n", Vcb
->LBlockSize
));
1532 Vcb
->LB2B_Bits
= Vcb
->LBlockSizeBits
- Vcb
->BlockSizeBits
;
1533 UDFPrint(("UDF: mapTableLength = %x\n", 0));
1534 UDFPrint(("UDF: numPartitionMaps = %x\n", 0));
1538 Vcb
->Partitions
[0].PartitionType
= UDF_TYPE1_MAP15
;
1539 Vcb
->Partitions
[0].VolumeSeqNum
= 0;
1540 Vcb
->Partitions
[0].PartitionNum
= 0;
1544 UDFPrint(("Found VAT 1.50\n"));
1545 Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP15;
1547 UDFPrint(("Found VAT 2.00\n"));
1548 Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP20;
1554 // remember FileSet location
1555 // long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]);
1556 fileset
->logicalBlockNum
= 0;
1557 fileset
->partitionReferenceNum
= 0;
1558 UDFPrint(("FileSet found in LogicalVolDesc at block=%x, partition=%d\n",
1559 fileset
->logicalBlockNum
,
1560 fileset
->partitionReferenceNum
));
1562 return STATUS_SUCCESS
;
1563 } // end UDFLoadBogusLogicalVol()
1566 This routine adds given Bitmap to existing one
1578 uint32 i
, lim
, j
, lba
, l
, lim2
, l2
, k
;
1587 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
1588 UDFPrint(("UDFAddXSpaceBitmap: at block=%x, partition=%d\n",
1592 if(!(Length
= (bm
->extLength
& UDF_EXTENT_LENGTH_MASK
))) return STATUS_SUCCESS
;
1593 i
=UDFPartStart(Vcb
, PartNum
);
1594 flags
= bm
->extLength
>> 30;
1595 if(!flags
/*|| flags == EXTENT_NOT_RECORDED_ALLOCATED*/) {
1596 tmp
= (int8
*)DbgAllocatePool(NonPagedPool
, max(Length
, Vcb
->BlockSize
));
1597 if(!tmp
) return STATUS_INSUFFICIENT_RESOURCES
;
1598 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
1599 locAddr
.logicalBlockNum
= bm
->extPosition
;
1600 // read header of the Bitmap
1601 if(!OS_SUCCESS(status
= UDFReadTagged(Vcb
, tmp
, lba
= UDFPartLbaToPhys(Vcb
, &(locAddr
)),
1602 locAddr
.logicalBlockNum
, &Ident
)) ) {
1607 if(Ident
!= TID_SPACE_BITMAP_DESC
) {
1608 status
= STATUS_DISK_CORRUPT_ERROR
;
1611 UDFRegisterFsStructure(Vcb
, lba
, Vcb
->BlockSize
);
1612 // read the whole Bitmap
1613 if(!OS_SUCCESS(status
= UDFReadData(Vcb
, FALSE
, ((uint64
)lba
)<<Vcb
->BlockSizeBits
, Length
, FALSE
, tmp
, &ReadBytes
)))
1615 UDFRegisterFsStructure(Vcb
, lba
, Length
);
1616 lim
= min(i
+ ((lim2
= ((PSPACE_BITMAP_DESC
)tmp
)->numOfBits
) << Vcb
->LB2B_Bits
), Vcb
->FSBM_BitCount
);
1617 tmp_bm
= tmp
+ sizeof(SPACE_BITMAP_DESC
);
1619 for(;(l
= UDFGetBitmapLen((uint32
*)tmp_bm
, j
, lim2
)) && (i
<lim
);) {
1620 // expand LBlocks to Sectors...
1621 l2
= l
<< Vcb
->LB2B_Bits
;
1623 if(bm_type
== UDF_FSPACE_BM
) {
1624 bit_set
= UDFGetFreeBit(tmp_bm
, j
);
1625 for(k
=0;(k
<l2
) && (i
<lim
);k
++) {
1628 UDFSetFreeBit(Vcb
->FSBM_Bitmap
, i
);
1629 UDFSetFreeBitOwner(Vcb
, i
);
1630 UDFSetZeroBit(Vcb
->ZSBM_Bitmap
, i
);
1633 UDFClrZeroBit(Vcb
->ZSBM_Bitmap
, i
);
1638 bit_set
= UDFGetZeroBit(tmp_bm
, j
);
1639 for(k
=0;(k
<l2
) && (i
<lim
);k
++) {
1642 UDFSetZeroBit(Vcb
->ZSBM_Bitmap
, i
);
1645 UDFClrZeroBit(Vcb
->ZSBM_Bitmap
, i
);
1653 /* } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1654 i=Vcb->Partitions[PartNum].PartitionRoot;
1655 lim = i + Vcb->Partitions[PartNum].PartitionLen;
1657 UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1660 return STATUS_SUCCESS
;
1661 } // end UDFAddXSpaceBitmap()
1664 This routine adds given Bitmap to existing one
1667 UDFVerifyXSpaceBitmap(
1676 // uint32 i, l2, k, lim, j, lim2;
1686 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
1688 UDFPrint((" UDFVerifyXSpaceBitmap: part %x\n", PartNum
));
1690 if(!(Length
= (bm
->extLength
& UDF_EXTENT_LENGTH_MASK
))) return STATUS_SUCCESS
;
1691 // i=UDFPartStart(Vcb, PartNum);
1692 flags
= bm
->extLength
>> 30;
1693 if(!flags
/*|| flags == EXTENT_NOT_RECORDED_ALLOCATED*/) {
1694 tmp
= (int8
*)DbgAllocatePool(NonPagedPool
, max(Length
, Vcb
->BlockSize
));
1695 if(!tmp
) return STATUS_INSUFFICIENT_RESOURCES
;
1696 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
1697 locAddr
.logicalBlockNum
= bm
->extPosition
;
1698 // read header of the Bitmap
1699 if(!OS_SUCCESS(status
= UDFReadTagged(Vcb
, tmp
, lba
= UDFPartLbaToPhys(Vcb
, &(locAddr
)),
1700 locAddr
.logicalBlockNum
, &Ident
)) ) {
1705 UDFPrint((" BM Lba %x\n", lba
));
1706 if(Ident
!= TID_SPACE_BITMAP_DESC
) {
1707 status
= STATUS_DISK_CORRUPT_ERROR
;
1710 // read the whole Bitmap
1711 if(!OS_SUCCESS(status
= UDFReadData(Vcb
, FALSE
, ((uint64
)lba
)<<Vcb
->BlockSizeBits
, Length
, FALSE
, tmp
, &ReadBytes
)))
1713 UDFRegisterFsStructure(Vcb
, lba
, Length
);
1714 // lim = min(i + ((lim2 = ((PSPACE_BITMAP_DESC)tmp)->numOfBits) << Vcb->LB2B_Bits), Vcb->FSBM_BitCount);
1715 // tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1717 /* for(;(l = UDFGetBitmapLen((uint32*)tmp_bm, j, lim2)) && (i<lim);) {
1718 // expand LBlocks to Sectors...
1719 l2 = l << Vcb->LB2B_Bits;
1721 if(bm_type == UDF_FSPACE_BM) {
1722 bit_set = UDFGetFreeBit(tmp_bm, j);
1723 for(k=0;(k<l2) && (i<lim);k++) {
1726 UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1727 UDFSetFreeBitOwner(Vcb, i);
1728 UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1731 UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1736 bit_set = UDFGetZeroBit(tmp_bm, j);
1737 for(k=0;(k<l2) && (i<lim);k++) {
1740 UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1743 UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1751 /* } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1752 i=Vcb->Partitions[PartNum].PartitionRoot;
1753 lim = i + Vcb->Partitions[PartNum].PartitionLen;
1755 UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1758 return STATUS_SUCCESS
;
1759 } // end UDFVerifyXSpaceBitmap()
1762 This routine subtracts given Bitmap to existing one
1780 if(!(Length = (bm->extLength & UDF_EXTENT_LENGTH_MASK))) return STATUS_SUCCESS;
1782 flags = bm->extLength >> 30;
1783 if(!flags || flags == EXTENT_NOT_RECORDED_ALLOCATED) {
1784 tmp = (int8*)MyAllocatePool__(NonPagedPool, Length);
1785 if(!tmp) return STATUS_INSUFFICIENT_RESOURCES;
1786 locAddr.partitionReferenceNum = (uint16)PartNum;
1787 locAddr.logicalBlockNum = bm->extPosition;
1788 if((!OS_SUCCESS(status = UDFReadTagged(Vcb, tmp, (j = UDFPartLbaToPhys(Vcb, &(locAddr))),
1789 locAddr.logicalBlockNum, &Ident))) ||
1790 (Ident != TID_SPACE_BITMAP_DESC) ) {
1794 if(!OS_SUCCESS(status = UDFReadData(Vcb, FALSE, ((uint64)j)<<Vcb->BlockSizeBits, Length, FALSE, tmp, &ReadBytes))) {
1798 lim = i + ((PSPACE_BITMAP_DESC)tmp)->numOfBits;
1799 tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1802 if(UDFGetUsedBit(tmp_bm, j)) UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1806 // } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1807 // i=Vcb->Partitions[PartNum].PartitionRoot;
1808 // lim = i + Vcb->Partitions[PartNum].PartitionLen;
1809 // for(;i<lim;i++) {
1810 // UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1813 return STATUS_SUCCESS;
1814 } // end UDFDelXSpaceBitmap() */
1817 This routine verifues FreeSpaceBitmap (internal) according to media
1818 parameters & input data
1821 UDFVerifyFreeSpaceBitmap(
1824 IN PPARTITION_HEADER_DESC phd
, // partition header pointing to Bitmaps
1825 IN uint32 Lba
// UnallocSpaceDesc
1836 PartNum
= UDFGetPartNumByPartNdx(Vcb
, PartNdx
);
1838 UDFPrint(("UDFVerifyFreeSpaceBitmap:\n"));
1839 // read info for partition header (if any)
1841 // read unallocated Bitmap
1842 if(!OS_SUCCESS(status
= UDFVerifyXSpaceBitmap(Vcb
, PartNum
, &(phd
->unallocatedSpaceBitmap
), UDF_FSPACE_BM
)))
1844 // read freed Bitmap
1845 if(!OS_SUCCESS(status
= UDFVerifyXSpaceBitmap(Vcb
, PartNum
, &(phd
->freedSpaceBitmap
), UDF_ZSPACE_BM
)))
1848 // read UnallocatedSpaceDesc & convert to Bitmap
1850 UDFPrint((" Lba @%x\n", Lba
));
1851 if(!(AllocDesc
= (int8
*)MyAllocatePool__(NonPagedPool
, Vcb
->LBlockSize
+ sizeof(EXTENT_AD
) )))
1852 return STATUS_INSUFFICIENT_RESOURCES
;
1853 RtlZeroMemory(((int8
*)AllocDesc
) + Vcb
->LBlockSize
, sizeof(EXTENT_AD
));
1854 if(!OS_SUCCESS(status
= UDFReadTagged(Vcb
, AllocDesc
, Lba
, Lba
, &Ident
)) ||
1855 !(Extent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, l
= (((PUNALLOC_SPACE_DESC
)AllocDesc
)->numAllocDescs
+1) * sizeof(EXTENT_AD
) ))) {
1856 MyFreePool__(AllocDesc
);
1859 UDFRegisterFsStructure(Vcb
, Lba
, Vcb
->BlockSize
);
1860 RtlCopyMemory((int8
*)Extent
, AllocDesc
+sizeof(UNALLOC_SPACE_DESC
), (((PUNALLOC_SPACE_DESC
)AllocDesc
)->numAllocDescs
+1) * sizeof(EXTENT_AD
) );
1861 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
1862 // read extent is recorded with relative addresses
1863 // so, we should convert it to suitable form
1864 for(i
=0; Extent
[i
].extLength
; i
++) {
1865 locAddr
.logicalBlockNum
= Extent
[i
].extLocation
;
1866 Extent
[i
].extLocation
= UDFPartLbaToPhys(Vcb
, &locAddr
);
1867 if(Extent
[i
].extLocation
== LBA_OUT_OF_EXTENT
) {
1869 MyFreePool__(AllocDesc
);
1870 return STATUS_DISK_CORRUPT_ERROR
;
1872 if((Extent
[i
].extLocation
>> 30) == EXTENT_NEXT_EXTENT_ALLOCDESC
) {
1873 // load continuation
1874 Lba
= Extent
[i
].extLocation
& UDF_EXTENT_LENGTH_MASK
;
1875 if(!OS_SUCCESS(status
= UDFReadTagged(Vcb
, AllocDesc
, Lba
, Lba
, &Ident
)) ||
1876 !(Extent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, (((PUNALLOC_SPACE_DESC
)AllocDesc
)->numAllocDescs
+1) * sizeof(EXTENT_AD
) ))) {
1877 MyFreePool__(AllocDesc
);
1880 if(Ident
== TID_UNALLOC_SPACE_DESC
) {
1881 UDFRegisterFsStructure(Vcb
, Lba
, Vcb
->BlockSize
);
1882 if(!(l
= MyReallocPool__((int8
*)Extent
, l
, (int8
**)&Extent
, i
*sizeof(EXTENT_MAP
)))) {
1883 MyFreePool__(Extent
);
1884 MyFreePool__(AllocDesc
);
1885 return STATUS_INSUFFICIENT_RESOURCES
;
1887 Extent
[i
].extLength
=
1888 Extent
[i
].extLocation
= 0;
1889 Extent
= UDFMergeMappings(Extent
, (PEXTENT_MAP
)(AllocDesc
+sizeof(UNALLOC_SPACE_DESC
)) );
1892 UDFPrint(("Broken unallocated space descriptor sequence\n"));
1897 // UDFMarkSpaceAsXXX(Vcb, (-1), Extent, AS_USED); // mark as used
1898 MyFreePool__(Extent
);
1899 MyFreePool__(AllocDesc
);
1900 status
= STATUS_SUCCESS
;
1903 } // end UDFBuildFreeSpaceBitmap()
1906 This routine builds FreeSpaceBitmap (internal) according to media
1907 parameters & input data
1910 UDFBuildFreeSpaceBitmap(
1913 IN PPARTITION_HEADER_DESC phd
, // partition header pointing to Bitmaps
1914 IN uint32 Lba
// UnallocSpaceDesc
1925 PartNum
= UDFGetPartNumByPartNdx(Vcb
, PartNdx
);
1926 if(!(Vcb
->FSBM_Bitmap
)) {
1927 // init Bitmap buffer if necessary
1928 Vcb
->FSBM_Bitmap
= (int8
*)DbgAllocatePool(NonPagedPool
, (i
= (Vcb
->LastPossibleLBA
+1+7)>>3) );
1929 if(!(Vcb
->FSBM_Bitmap
)) return STATUS_INSUFFICIENT_RESOURCES
;
1931 Vcb
->ZSBM_Bitmap
= (int8
*)DbgAllocatePool(NonPagedPool
, (i
= (Vcb
->LastPossibleLBA
+1+7)>>3) );
1932 if(!(Vcb
->ZSBM_Bitmap
)) {
1933 #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1935 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1936 MyFreePool__(Vcb
->FSBM_Bitmap
);
1937 Vcb
->FSBM_Bitmap
= NULL
;
1938 return STATUS_INSUFFICIENT_RESOURCES
;
1941 RtlZeroMemory(Vcb
->FSBM_Bitmap
, i
);
1942 RtlZeroMemory(Vcb
->ZSBM_Bitmap
, i
);
1943 #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1944 Vcb
->FSBM_Bitmap_owners
= (uint32
*)DbgAllocatePool(NonPagedPool
, (Vcb
->LastPossibleLBA
+1)*sizeof(uint32
));
1945 if(!(Vcb
->FSBM_Bitmap_owners
)) {
1946 MyFreePool__(Vcb
->ZSBM_Bitmap
);
1947 Vcb
->ZSBM_Bitmap
= NULL
;
1950 RtlFillMemory(Vcb
->FSBM_Bitmap_owners
, (Vcb
->LastPossibleLBA
+1)*sizeof(uint32
), 0xff);
1951 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1952 Vcb
->FSBM_ByteCount
= i
;
1953 Vcb
->FSBM_BitCount
= Vcb
->LastPossibleLBA
+1;
1955 // read info for partition header (if any)
1957 // read unallocated Bitmap
1958 if(!OS_SUCCESS(status
= UDFAddXSpaceBitmap(Vcb
, PartNum
, &(phd
->unallocatedSpaceBitmap
), UDF_FSPACE_BM
)))
1960 // read freed Bitmap
1961 if(!OS_SUCCESS(status
= UDFAddXSpaceBitmap(Vcb
, PartNum
, &(phd
->freedSpaceBitmap
), UDF_ZSPACE_BM
)))
1964 // read UnallocatedSpaceDesc & convert to Bitmap
1966 if(!(AllocDesc
= (int8
*)MyAllocatePool__(NonPagedPool
, Vcb
->LBlockSize
+ sizeof(EXTENT_AD
) )))
1967 return STATUS_INSUFFICIENT_RESOURCES
;
1968 RtlZeroMemory(((int8
*)AllocDesc
) + Vcb
->LBlockSize
, sizeof(EXTENT_AD
));
1969 if(!OS_SUCCESS(status
= UDFReadTagged(Vcb
, AllocDesc
, Lba
, Lba
, &Ident
)) ||
1970 !(Extent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, l
= (((PUNALLOC_SPACE_DESC
)AllocDesc
)->numAllocDescs
+1) * sizeof(EXTENT_AD
) ))) {
1971 MyFreePool__(AllocDesc
);
1974 UDFRegisterFsStructure(Vcb
, Lba
, Vcb
->BlockSize
);
1975 RtlCopyMemory((int8
*)Extent
, AllocDesc
+sizeof(UNALLOC_SPACE_DESC
), (((PUNALLOC_SPACE_DESC
)AllocDesc
)->numAllocDescs
+1) * sizeof(EXTENT_AD
) );
1976 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
1977 // read extent is recorded with relative addresses
1978 // so, we should convert it to suitable form
1979 for(i
=0; Extent
[i
].extLength
; i
++) {
1980 locAddr
.logicalBlockNum
= Extent
[i
].extLocation
;
1981 Extent
[i
].extLocation
= UDFPartLbaToPhys(Vcb
, &locAddr
);
1982 if(Extent
[i
].extLocation
== LBA_OUT_OF_EXTENT
) {
1984 MyFreePool__(AllocDesc
);
1985 return STATUS_DISK_CORRUPT_ERROR
;
1987 if((Extent
[i
].extLocation
>> 30) == EXTENT_NEXT_EXTENT_ALLOCDESC
) {
1988 // load continuation
1989 Lba
= Extent
[i
].extLocation
& UDF_EXTENT_LENGTH_MASK
;
1990 if(!OS_SUCCESS(status
= UDFReadTagged(Vcb
, AllocDesc
, Lba
, Lba
, &Ident
)) ||
1991 !(Extent
= (PEXTENT_MAP
)MyAllocatePool__(NonPagedPool
, (((PUNALLOC_SPACE_DESC
)AllocDesc
)->numAllocDescs
+1) * sizeof(EXTENT_AD
) ))) {
1992 MyFreePool__(AllocDesc
);
1995 if(Ident
== TID_UNALLOC_SPACE_DESC
) {
1996 UDFRegisterFsStructure(Vcb
, Lba
, Vcb
->BlockSize
);
1997 if(!(l
= MyReallocPool__((int8
*)Extent
, l
, (int8
**)&Extent
, i
*sizeof(EXTENT_MAP
)))) {
1998 MyFreePool__(Extent
);
1999 MyFreePool__(AllocDesc
);
2000 return STATUS_INSUFFICIENT_RESOURCES
;
2002 Extent
[i
].extLength
=
2003 Extent
[i
].extLocation
= 0;
2004 Extent
= UDFMergeMappings(Extent
, (PEXTENT_MAP
)(AllocDesc
+sizeof(UNALLOC_SPACE_DESC
)) );
2007 UDFPrint(("Broken unallocated space descriptor sequence\n"));
2012 UDFMarkSpaceAsXXX(Vcb
, (-1), Extent
, AS_USED
); // mark as used
2013 MyFreePool__(Extent
);
2014 MyFreePool__(AllocDesc
);
2017 } // end UDFVerifyFreeSpaceBitmap()
2020 process Partition descriptor
2028 PartitionDesc
*p
= (PartitionDesc
*)Buf
;
2031 BOOLEAN Found
= FALSE
;
2032 UDFPrint(("UDF: Pard Descr:\n"));
2033 UDFPrint((" volDescSeqNum = %x\n", p
->volDescSeqNum
));
2034 UDFPrint((" partitionFlags = %x\n", p
->partitionFlags
));
2035 UDFPrint((" partitionNumber = %x\n", p
->partitionNumber
));
2036 UDFPrint((" accessType = %x\n", p
->accessType
));
2037 UDFPrint((" partitionStartingLocation = %x\n", p
->partitionStartingLocation
));
2038 UDFPrint((" partitionLength = %x\n", p
->partitionLength
));
2039 // There is nothing interesting to comment here
2040 // Just look at Names & Messages....
2041 for (i
=0; i
<Vcb
->PartitionMaps
; i
++) {
2042 UDFPrint(("Searching map: (%d == %d)\n",
2043 Vcb
->Partitions
[i
].PartitionNum
, (p
->partitionNumber
) ));
2044 if(Vcb
->Partitions
[i
].PartitionNum
== (p
->partitionNumber
)) {
2046 Vcb
->Partitions
[i
].PartitionRoot
= p
->partitionStartingLocation
+ Vcb
->FirstLBA
;
2047 Vcb
->Partitions
[i
].PartitionLen
=
2048 min(p
->partitionLength
,
2049 Vcb
->LastPossibleLBA
- Vcb
->Partitions
[i
].PartitionRoot
); /* sectors */
2050 Vcb
->Partitions
[i
].UspaceBitmap
= 0xFFFFFFFF;
2051 Vcb
->Partitions
[i
].FspaceBitmap
= 0xFFFFFFFF;
2052 Vcb
->Partitions
[i
].AccessType
= p
->accessType
;
2053 UDFPrint(("Access mode %x\n", p
->accessType
));
2054 if(p
->accessType
== PARTITION_ACCESS_WO
) {
2055 Vcb
->CDR_Mode
= TRUE
;
2056 // Vcb->Partitions[i].PartitionLen = Vcb->LastPossibleLBA - p->partitionStartingLocation;
2057 } else if(p
->accessType
< PARTITION_ACCESS_WO
) {
2058 // Soft-read-only volume
2059 UDFPrint(("Soft Read-only volume\n"));
2060 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
2061 Vcb
->UserFSFlags
|= UDF_USER_FS_FLAGS_PART_RO
;
2062 } else if(p
->accessType
> PARTITION_ACCESS_MAX_KNOWN
) {
2063 return STATUS_UNRECOGNIZED_MEDIA
;
2066 if(!strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR02
) ||
2067 !strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR03
))
2069 PPARTITION_HEADER_DESC phd
;
2071 phd
= (PPARTITION_HEADER_DESC
)(p
->partitionContentsUse
);
2073 if(phd
->unallocatedSpaceTable
.extLength
)
2074 UDFPrint(("unallocatedSpaceTable (part %d)\n", i
));
2076 if(phd
->unallocatedSpaceBitmap
.extLength
) {
2077 Vcb
->Partitions
[i
].UspaceBitmap
=
2078 phd
->unallocatedSpaceBitmap
.extPosition
;
2079 UDFPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2080 i
, Vcb
->Partitions
[i
].UspaceBitmap
));
2083 if(phd
->partitionIntegrityTable
.extLength
)
2084 UDFPrint(("partitionIntegrityTable (part %d)\n", i
));
2085 if(phd
->freedSpaceTable
.extLength
)
2086 UDFPrint(("freedSpaceTable (part %d)\n", i
));
2088 if(phd
->freedSpaceBitmap
.extLength
) {
2089 Vcb
->Partitions
[i
].FspaceBitmap
=
2090 phd
->freedSpaceBitmap
.extPosition
;
2091 UDFPrint(("freedSpaceBitmap (part %d)\n", i
));
2093 RC
= UDFBuildFreeSpaceBitmap(Vcb
, i
, phd
, 0);
2094 //Vcb->Modified = FALSE;
2095 UDFPreClrModified(Vcb
);
2096 UDFClrModified(Vcb
);
2100 if ((Vcb
->Partitions
[i
].PartitionType
== UDF_VIRTUAL_MAP15
) ||
2101 (Vcb
->Partitions
[i
].PartitionType
== UDF_VIRTUAL_MAP20
)) {
2102 RC
= UDFLoadVAT(Vcb
, i
);
2105 WCacheFlushAll__(&(Vcb
->FastCache
), Vcb
);
2106 WCacheSetMode__(&(Vcb
->FastCache
), WCACHE_MODE_R
);
2107 Vcb
->LastModifiedTrack
= 0;
2114 UDFPrint(("Partition (%d) not found in partition map\n", (p
->partitionNumber
) ));
2116 UDFPrint(("Partition (%d:%d type %x) starts at physical %x, length %x\n",
2117 p
->partitionNumber
, i
-1, Vcb
->Partitions
[i
-1].PartitionType
,
2118 Vcb
->Partitions
[i
-1].PartitionRoot
, Vcb
->Partitions
[i
-1].PartitionLen
));
2121 return STATUS_SUCCESS
;
2122 } // end UDFLoadPartDesc()
2125 process Partition descriptor
2133 PartitionDesc
*p
= (PartitionDesc
*)Buf
;
2136 BOOLEAN Found
= FALSE
;
2137 UDFPrint(("UDF: Verify Part Descr:\n"));
2138 UDFPrint((" volDescSeqNum = %x\n", p
->volDescSeqNum
));
2139 UDFPrint((" partitionFlags = %x\n", p
->partitionFlags
));
2140 UDFPrint((" partitionNumber = %x\n", p
->partitionNumber
));
2141 UDFPrint((" accessType = %x\n", p
->accessType
));
2142 UDFPrint((" partitionStartingLocation = %x\n", p
->partitionStartingLocation
));
2143 UDFPrint((" partitionLength = %x\n", p
->partitionLength
));
2144 // There is nothing interesting to comment here
2145 // Just look at Names & Messages....
2146 for (i
=0; i
<Vcb
->PartitionMaps
; i
++) {
2147 UDFPrint(("Searching map: (%d == %d)\n",
2148 Vcb
->Partitions
[i
].PartitionNum
, (p
->partitionNumber
) ));
2149 if(Vcb
->Partitions
[i
].PartitionNum
== (p
->partitionNumber
)) {
2151 if(Vcb
->Partitions
[i
].PartitionRoot
!= p
->partitionStartingLocation
+ Vcb
->FirstLBA
)
2152 return STATUS_DISK_CORRUPT_ERROR
;
2153 if(Vcb
->Partitions
[i
].PartitionLen
!=
2154 min(p
->partitionLength
,
2155 Vcb
->LastPossibleLBA
- Vcb
->Partitions
[i
].PartitionRoot
)) /* sectors */
2156 return STATUS_DISK_CORRUPT_ERROR
;
2157 // Vcb->Partitions[i].UspaceBitmap = 0xFFFFFFFF;
2158 // Vcb->Partitions[i].FspaceBitmap = 0xFFFFFFFF;
2159 if(Vcb
->Partitions
[i
].AccessType
!= p
->accessType
)
2160 return STATUS_DISK_CORRUPT_ERROR
;
2161 UDFPrint(("Access mode %x\n", p
->accessType
));
2162 if(p
->accessType
== PARTITION_ACCESS_WO
) {
2163 if(Vcb
->CDR_Mode
!= TRUE
)
2164 return STATUS_DISK_CORRUPT_ERROR
;
2165 // Vcb->Partitions[i].PartitionLen = Vcb->LastPossibleLBA - p->partitionStartingLocation;
2166 } else if(p
->accessType
< PARTITION_ACCESS_WO
) {
2167 // Soft-read-only volume
2168 UDFPrint(("Soft Read-only volume\n"));
2169 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
))
2170 return STATUS_DISK_CORRUPT_ERROR
;
2171 } else if(p
->accessType
> PARTITION_ACCESS_MAX_KNOWN
) {
2172 return STATUS_UNRECOGNIZED_MEDIA
;
2175 if(!strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR02
) ||
2176 !strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR03
))
2178 PPARTITION_HEADER_DESC phd
;
2180 phd
= (PPARTITION_HEADER_DESC
)(p
->partitionContentsUse
);
2182 if(phd
->unallocatedSpaceTable
.extLength
)
2183 UDFPrint(("unallocatedSpaceTable (part %d)\n", i
));
2185 if(phd
->unallocatedSpaceBitmap
.extLength
) {
2186 if(Vcb
->Partitions
[i
].UspaceBitmap
==
2187 phd
->unallocatedSpaceBitmap
.extPosition
) {
2188 UDFPrint(("Warning: both USpaceBitmaps have same location\n"));
2190 UDFPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2191 i
, Vcb
->Partitions
[i
].UspaceBitmap
));
2194 if(phd
->partitionIntegrityTable
.extLength
)
2195 UDFPrint(("partitionIntegrityTable (part %d)\n", i
));
2196 if(phd
->freedSpaceTable
.extLength
)
2197 UDFPrint(("freedSpaceTable (part %d)\n", i
));
2199 if(phd
->freedSpaceBitmap
.extLength
) {
2200 if(Vcb
->Partitions
[i
].FspaceBitmap
==
2201 phd
->freedSpaceBitmap
.extPosition
) {
2202 UDFPrint(("Warning: both FSpaceBitmaps have same location\n"));
2204 UDFPrint(("freedSpaceBitmap (part %d)\n", i
));
2206 RC
= UDFVerifyFreeSpaceBitmap(Vcb
, i
, phd
, 0);
2207 //Vcb->Modified = FALSE;
2208 //UDFPreClrModified(Vcb);
2209 //UDFClrModified(Vcb);
2213 if ((Vcb
->Partitions
[i
].PartitionType
== UDF_VIRTUAL_MAP15
) ||
2214 (Vcb
->Partitions
[i
].PartitionType
== UDF_VIRTUAL_MAP20
)) {
2215 /* RC = UDFLoadVAT(Vcb, i);
2218 WCacheFlushAll__(&(Vcb->FastCache), Vcb);
2219 WCacheSetMode__(&(Vcb->FastCache), WCACHE_MODE_R);
2220 Vcb->LastModifiedTrack = 0;*/
2227 UDFPrint(("Partition (%d) not found in partition map\n", (p
->partitionNumber
) ));
2229 UDFPrint(("Partition (%d:%d type %x) starts at physical %x, length %x\n",
2230 p
->partitionNumber
, i
-1, Vcb
->Partitions
[i
-1].PartitionType
,
2231 Vcb
->Partitions
[i
-1].PartitionRoot
, Vcb
->Partitions
[i
-1].PartitionLen
));
2234 return STATUS_SUCCESS
;
2235 } // end UDFVerifyPartDesc()
2238 This routine scans VDS & fills special array with Desc locations
2244 IN uint32 lastblock
,
2245 IN PUDF_VDS_RECORD vds
,
2255 UDFPrint(("UDF: Read VDS (%x - %x)\n", block
, lastblock
));
2256 // Read the main descriptor sequence
2257 for (;(!done
&& block
<= lastblock
); block
++)
2259 status
= UDFReadTagged(Vcb
, Buf
, block
, block
, &ident
);
2260 if(!OS_SUCCESS(status
))
2262 UDFRegisterFsStructure(Vcb
, block
, Vcb
->BlockSize
);
2264 // Process each descriptor (ISO 13346 3/8.3-8.4)
2265 gd
= (struct GenericDesc
*)Buf
;
2266 vdsn
= gd
->volDescSeqNum
;
2267 UDFPrint(("LBA %x, Ident = %x, vdsn = %x\n", block
, ident
, vdsn
));
2270 case TID_PRIMARY_VOL_DESC
: // ISO 13346 3/10.1
2271 if(vdsn
>= vds
[VDS_POS_PRIMARY_VOL_DESC
].volDescSeqNum
)
2273 vds
[VDS_POS_PRIMARY_VOL_DESC
].volDescSeqNum
= vdsn
;
2274 vds
[VDS_POS_PRIMARY_VOL_DESC
].block
= block
;
2277 case TID_VOL_DESC_PTR
: // ISO 13346 3/10.3
2278 struct VolDescPtr
* pVDP
;
2279 if(vdsn
>= vds
[VDS_POS_VOL_DESC_PTR
].volDescSeqNum
)
2281 vds
[VDS_POS_VOL_DESC_PTR
].volDescSeqNum
= vdsn
;
2282 vds
[VDS_POS_VOL_DESC_PTR
].block
= block
;
2283 vds
[VDS_POS_RECURSION_COUNTER
].volDescSeqNum
++;
2284 if(vds
[VDS_POS_RECURSION_COUNTER
].volDescSeqNum
> MAX_VDS_PARTS
) {
2285 UDFPrint(("too long multipart VDS -> abort\n"));
2286 return STATUS_DISK_CORRUPT_ERROR
;
2288 pVDP
= (struct VolDescPtr
*)Buf
;
2289 UDFPrint(("multipart VDS...\n"));
2290 return UDFReadVDS(Vcb
, pVDP
->nextVolDescSeqExt
.extLocation
,
2291 pVDP
->nextVolDescSeqExt
.extLocation
+ (pVDP
->nextVolDescSeqExt
.extLocation
>> Vcb
->BlockSizeBits
),
2295 case TID_IMP_USE_VOL_DESC
: // ISO 13346 3/10.4
2296 if(vdsn
>= vds
[VDS_POS_IMP_USE_VOL_DESC
].volDescSeqNum
)
2298 vds
[VDS_POS_IMP_USE_VOL_DESC
].volDescSeqNum
= vdsn
;
2299 vds
[VDS_POS_IMP_USE_VOL_DESC
].block
= block
;
2302 case TID_PARTITION_DESC
: // ISO 13346 3/10.5
2303 if(!vds
[VDS_POS_PARTITION_DESC
].block
)
2304 vds
[VDS_POS_PARTITION_DESC
].block
= block
;
2306 case TID_LOGICAL_VOL_DESC
: // ISO 13346 3/10.6
2307 case TID_ADAPTEC_LOGICAL_VOL_DESC
: // Adaptec Compressed UDF extesion
2308 if(vdsn
>= vds
[VDS_POS_LOGICAL_VOL_DESC
].volDescSeqNum
)
2310 vds
[VDS_POS_LOGICAL_VOL_DESC
].volDescSeqNum
= vdsn
;
2311 vds
[VDS_POS_LOGICAL_VOL_DESC
].block
= block
;
2314 case TID_UNALLOC_SPACE_DESC
: // ISO 13346 3/10.8
2315 if(vdsn
>= vds
[VDS_POS_UNALLOC_SPACE_DESC
].volDescSeqNum
)
2317 vds
[VDS_POS_UNALLOC_SPACE_DESC
].volDescSeqNum
= vdsn
;
2318 vds
[VDS_POS_UNALLOC_SPACE_DESC
].block
= block
;
2321 case TID_TERMINATING_DESC
: // ISO 13346 3/10.9
2322 vds
[VDS_POS_TERMINATING_DESC
].block
= block
;
2327 return STATUS_SUCCESS
;
2331 UDFLoadImpUseVolDesc(
2337 ImpUseVolDesc
* iuvd
= (ImpUseVolDesc
*)Buf
;
2338 ImpUseVolDescImpUse
* iuvdiu
= (ImpUseVolDescImpUse
*)&(iuvd
->impUse
);
2339 UDFPrint(("UDF: Imp Use Vol Desc:\n"));
2340 UDFPrint((" volDescSeqNum = %x\n", iuvd
->volDescSeqNum
));
2341 UDFPrint(("UDF: Imp Use Vol Desc Imp Use:\n"));
2342 KdDump(iuvdiu
, sizeof(ImpUseVolDescImpUse
));
2344 return STATUS_SUCCESS
;
2345 } // UDFLoadImpUseVolDesc()
2348 UDFLoadUnallocatedSpaceDesc(
2353 UDFPrint(("UDF: Unallocated Space Desc:\n"));
2354 // UnallocatedSpaceDesc* usd = (UnallocatedSpaceDesc*)Buf;
2355 return STATUS_SUCCESS
;
2356 } // UDFLoadImpUseVolDesc()
2359 Process a main/reserve volume descriptor sequence.
2363 IN PDEVICE_OBJECT DeviceObject
,
2366 IN uint32 lastblock
,
2367 OUT lb_addr
*fileset
2370 OSSTATUS RC
= STATUS_SUCCESS
;
2371 int8
* Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
2372 UDF_VDS_RECORD vds
[VDS_POS_LENGTH
];
2379 if(!Buf
) try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
2380 RtlZeroMemory(vds
, sizeof(UDF_VDS_RECORD
) * VDS_POS_LENGTH
);
2381 if(!OS_SUCCESS(RC
= UDFReadVDS(Vcb
, block
, lastblock
, (PUDF_VDS_RECORD
)&vds
, Buf
)))
2383 // walk through Vol Desc Sequence according to locations gained by
2384 // UDFReadVDS() & do some procesing for each one
2385 // It is very simple dispath routine...
2386 for (i
=0; i
<VDS_POS_LENGTH
; i
++)
2390 if(!OS_SUCCESS(RC
= UDFReadTagged(Vcb
, Buf
, vds
[i
].block
, vds
[i
].block
, &ident
)))
2392 UDFRegisterFsStructure(Vcb
, vds
[i
].block
, Vcb
->BlockSize
);
2394 if(i
== VDS_POS_PRIMARY_VOL_DESC
) {
2395 UDFLoadPVolDesc(Vcb
,Buf
);
2396 if(!Vcb
->PVolDescAddr
.block
) {
2397 Vcb
->PVolDescAddr
= vds
[i
];
2399 Vcb
->PVolDescAddr2
= vds
[i
];
2402 if(i
== VDS_POS_LOGICAL_VOL_DESC
) {
2403 RC
= UDFLoadLogicalVol(DeviceObject
,Vcb
, Buf
, fileset
);
2404 if(!OS_SUCCESS(RC
)) try_return(RC
);
2407 if(i
== VDS_POS_IMP_USE_VOL_DESC
) {
2408 UDFLoadImpUseVolDesc(Vcb
, Buf
);
2410 if(i
== VDS_POS_UNALLOC_SPACE_DESC
) {
2411 UDFLoadUnallocatedSpaceDesc(Vcb
, Buf
);
2414 if(i
== VDS_POS_PARTITION_DESC
)
2416 Buf2
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
2417 if(!Buf2
) try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
2418 RC
= UDFLoadPartDesc(Vcb
,Buf
);
2419 if(!OS_SUCCESS(RC
)) try_return(RC
);
2420 for (j
=vds
[i
].block
+1; j
<vds
[VDS_POS_TERMINATING_DESC
].block
; j
++)
2422 RC
= UDFReadTagged(Vcb
,Buf2
, j
, j
, &ident
);
2423 if(!OS_SUCCESS(RC
)) try_return(RC
);
2424 UDFRegisterFsStructure(Vcb
, j
, Vcb
->BlockSize
);
2425 // gd = (struct GenericDesc *)Buf2;
2426 if(ident
== TID_PARTITION_DESC
) {
2427 RC
= UDFLoadPartDesc(Vcb
,Buf2
);
2428 if(!OS_SUCCESS(RC
)) try_return(RC
);
2429 } else if(ident
== TID_UNALLOC_SPACE_DESC
) {
2430 RC
= UDFBuildFreeSpaceBitmap(Vcb
,0,NULL
,j
);
2431 //Vcb->Modified = FALSE;
2432 UDFPreClrModified(Vcb
);
2433 UDFClrModified(Vcb
);
2442 if(i
== VDS_POS_LOGICAL_VOL_DESC
) {
2443 RC
= UDFLoadBogusLogicalVol(DeviceObject
,Vcb
, Buf
, fileset
);
2444 if(!OS_SUCCESS(RC
)) try_return(RC
);
2452 if(Buf
) MyFreePool__(Buf
);
2453 if(Buf2
) MyFreePool__(Buf2
);
2457 } // end UDFProcessSequence()
2460 Verifies a main/reserve volume descriptor sequence.
2464 IN PDEVICE_OBJECT DeviceObject
,
2467 IN uint32 lastblock
,
2468 OUT lb_addr
*fileset
2471 OSSTATUS RC
= STATUS_SUCCESS
;
2472 int8
* Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
2473 UDF_VDS_RECORD vds
[VDS_POS_LENGTH
];
2480 if(!Buf
) try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
2481 if(!block
) try_return (RC
= STATUS_SUCCESS
);
2482 RtlZeroMemory(vds
, sizeof(UDF_VDS_RECORD
) * VDS_POS_LENGTH
);
2483 if(!OS_SUCCESS(RC
= UDFReadVDS(Vcb
, block
, lastblock
, (PUDF_VDS_RECORD
)&vds
, Buf
)))
2486 for (i
=0; i
<VDS_POS_LENGTH
; i
++)
2490 if(!OS_SUCCESS(RC
= UDFReadTagged(Vcb
, Buf
, vds
[i
].block
, vds
[i
].block
, &ident
)))
2492 UDFRegisterFsStructure(Vcb
, vds
[i
].block
, Vcb
->BlockSize
);
2494 /* if(i == VDS_POS_PRIMARY_VOL_DESC)
2495 UDFLoadPVolDesc(Vcb,Buf);
2496 else if(i == VDS_POS_LOGICAL_VOL_DESC) {
2497 RC = UDFLoadLogicalVol(DeviceObject,Vcb, Buf, fileset);
2498 if(!OS_SUCCESS(RC)) try_return(RC);
2500 else*/ if(i
== VDS_POS_PARTITION_DESC
)
2502 Buf2
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
2503 if(!Buf2
) try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
2504 RC
= UDFVerifyPartDesc(Vcb
,Buf
);
2505 if(!OS_SUCCESS(RC
)) try_return(RC
);
2506 for (j
=vds
[i
].block
+1; j
<vds
[VDS_POS_TERMINATING_DESC
].block
; j
++)
2508 RC
= UDFReadTagged(Vcb
,Buf2
, j
, j
, &ident
);
2509 if(!OS_SUCCESS(RC
)) try_return(RC
);
2510 UDFRegisterFsStructure(Vcb
, j
, Vcb
->BlockSize
);
2511 // gd = (struct GenericDesc *)Buf2;
2512 if(ident
== TID_PARTITION_DESC
) {
2513 RC
= UDFVerifyPartDesc(Vcb
,Buf2
);
2514 if(!OS_SUCCESS(RC
)) try_return(RC
);
2515 } else if(ident
== TID_UNALLOC_SPACE_DESC
) {
2516 RC
= UDFVerifyFreeSpaceBitmap(Vcb
,0,NULL
,j
);
2517 Vcb
->Modified
= FALSE
;
2530 if(Buf
) MyFreePool__(Buf
);
2531 if(Buf2
) MyFreePool__(Buf2
);
2535 } // end UDFVerifySequence()
2538 remember some useful info about FileSet & RootDir location
2543 IN PFILE_SET_DESC fset
,
2545 OUT lb_addr
*sysstream
2548 *root
= fset
->rootDirectoryICB
.extLocation
;
2549 Vcb
->SerialNumber
= fset
->descTag
.tagSerialNum
;
2550 UDFPrint(("Rootdir at block=%x, partition=%d\n",
2551 root
->logicalBlockNum
, root
->partitionReferenceNum
));
2553 *sysstream
= fset
->streamDirectoryICB
.extLocation
;
2554 UDFPrint(("SysStream at block=%x, partition=%d\n",
2555 sysstream
->logicalBlockNum
, sysstream
->partitionReferenceNum
));
2557 // Get current UDF revision
2558 // Get Read-Only flags
2559 UDFReadEntityID_Domain(Vcb
, &(fset
->domainIdent
));
2561 } // end UDFLoadFileset()
2564 UDFIsCachedBadSequence(
2570 OSSTATUS RC
= STATUS_SUCCESS
;
2571 // Check if it is known bad sequence
2572 for(j
=0; j
<Vcb
->BadSeqLocIndex
; j
++) {
2573 if(Vcb
->BadSeqLoc
[j
] == Lba
) {
2574 RC
= Vcb
->BadSeqStatus
[j
];
2579 } // end UDFIsCachedBadSequence()
2582 UDFRememberBadSequence(
2589 if(!OS_SUCCESS(UDFIsCachedBadSequence(Vcb
, Lba
)))
2591 // Remenber bad sequence
2592 j
= Vcb
->BadSeqLocIndex
;
2593 Vcb
->BadSeqLocIndex
++;
2594 Vcb
->BadSeqLoc
[j
] = Lba
;
2595 Vcb
->BadSeqStatus
[j
] = RC
;
2596 } // end UDFRememberBadSequence()
2603 IN PDEVICE_OBJECT DeviceObject
,
2605 OUT lb_addr
*fileset
2608 OSSTATUS RC
= STATUS_UNRECOGNIZED_VOLUME
;
2609 OSSTATUS RC2
= STATUS_UNRECOGNIZED_VOLUME
;
2610 AnchorVolDescPtr
*anchor
;
2612 int8
* Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
2613 uint32 main_s
, main_e
;
2614 uint32 reserve_s
, reserve_e
;
2617 if(!Buf
) return STATUS_INSUFFICIENT_RESOURCES
;
2618 // walk through all available Anchors & load data
2619 for (i
=0; i
<MAX_ANCHOR_LOCATIONS
; i
++)
2621 if(Vcb
->Anchor
[i
] && (OS_SUCCESS(UDFReadTagged(Vcb
, Buf
,
2622 Vcb
->Anchor
[i
], Vcb
->Anchor
[i
] - Vcb
->FirstLBA
, &ident
))))
2624 anchor
= (AnchorVolDescPtr
*)Buf
;
2626 // Locate the main sequence
2627 main_s
= ( anchor
->mainVolDescSeqExt
.extLocation
);
2628 main_e
= ( anchor
->mainVolDescSeqExt
.extLength
);
2629 main_e
= main_e
>> Vcb
->BlockSizeBits
;
2632 // Locate the reserve sequence
2633 reserve_s
= (anchor
->reserveVolDescSeqExt
.extLocation
);
2634 reserve_e
= (anchor
->reserveVolDescSeqExt
.extLength
);
2635 reserve_e
= reserve_e
>> Vcb
->BlockSizeBits
;
2636 reserve_e
+= reserve_s
;
2638 // Check if it is known bad sequence
2639 RC
= UDFIsCachedBadSequence(Vcb
, main_s
);
2640 if(OS_SUCCESS(RC
)) {
2641 // Process the main & reserve sequences
2642 // responsible for finding the PartitionDesc(s)
2643 UDFPrint(("-----------------------------------\n"));
2644 UDFPrint(("UDF: Main sequence:\n"));
2645 RC
= UDFProcessSequence(DeviceObject
, Vcb
, main_s
, main_e
, fileset
);
2648 if(!OS_SUCCESS(RC
)) {
2649 // Remenber bad sequence
2650 UDFRememberBadSequence(Vcb
, main_s
, RC
);
2652 UDFPrint(("-----------------------------------\n"));
2653 UDFPrint(("UDF: Main sequence failed.\n"));
2654 UDFPrint(("UDF: Reserve sequence\n"));
2655 if(Vcb
->LVid
) MyFreePool__(Vcb
->LVid
);
2658 RC2
= UDFIsCachedBadSequence(Vcb
, reserve_s
);
2659 if(OS_SUCCESS(RC2
)) {
2660 RC2
= UDFProcessSequence(DeviceObject
, Vcb
, reserve_s
, reserve_e
, fileset
);
2663 if(OS_SUCCESS(RC2
)) {
2664 UDFPrint(("-----------------------------------\n"));
2665 Vcb
->VDS2_Len
= reserve_e
- reserve_s
;
2666 Vcb
->VDS2
= reserve_s
;
2667 RC
= STATUS_SUCCESS
;
2668 // Vcb is already Zero-filled
2669 // Vcb->VDS1_Len = 0;
2673 // This is also bad sequence. Remenber it too
2674 UDFRememberBadSequence(Vcb
, reserve_s
, RC
);
2677 // remember these values for umount__
2678 Vcb
->VDS1_Len
= main_e
- main_s
;
2680 /* if(Vcb->LVid) MyFreePool__(Vcb->LVid);
2682 if(OS_SUCCESS(UDFVerifySequence(DeviceObject
, Vcb
, reserve_s
, reserve_e
, fileset
)))
2684 UDFPrint(("-----------------------------------\n"));
2685 Vcb
->VDS2_Len
= reserve_e
- reserve_s
;
2686 Vcb
->VDS2
= reserve_s
;
2689 UDFPrint(("UDF: Reserve sequence verification failed.\n"));
2690 switch(Vcb
->PartitialDamagedVolumeAction
) {
2691 case UDF_PART_DAMAGED_RO
:
2692 UDFPrint(("UDF: Switch to r/o mode.\n"));
2693 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
2695 case UDF_PART_DAMAGED_NO
:
2696 UDFPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n"));
2697 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
2698 RC
= STATUS_WRONG_VOLUME
;
2700 case UDF_PART_DAMAGED_RW
:
2702 UDFPrint(("UDF: Keep r/w mode for your own risk.\n"));
2711 if(Vcb
->SparingCount
&&
2712 (Vcb
->NoFreeRelocationSpaceVolumeAction
!= UDF_PART_DAMAGED_RW
)) {
2713 UDFPrint(("UDF: No free Sparing Entries -> Switch to r/o mode.\n"));
2714 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
2717 if(i
== sizeof(Vcb
->Anchor
)/sizeof(int)) {
2718 UDFPrint(("No Anchor block found\n"));
2719 RC
= STATUS_UNRECOGNIZED_VOLUME
;
2722 UDFPrint(("Using anchor in block %x\n", Vcb
->Anchor
[i
]));
2727 } // end UDFLoadPartition()
2730 This routine scans FileSet sequence & returns pointer to last valid
2736 IN lb_addr
*Addr
, // Addr for the 1st FileSet
2737 IN OUT PFILE_SET_DESC FileSetDesc
2741 uint32 relLocExt
= Addr
->logicalBlockNum
;
2742 uint32 locExt
= UDFPartLbaToPhys(Vcb
, Addr
);
2744 uint32 relPrevExt
, prevExt
;
2746 relPrevExt
, prevExt
= NULL
;
2747 FileSetDesc
->nextExt
.extLength
= 1; // ;)
2748 // walk through FileSet chain
2749 // we've just pre-init'd extent length to read 1st FileSet
2750 while(FileSetDesc
->nextExt
.extLength
) {
2751 status
= UDFReadTagged(Vcb
, (int8
*)FileSetDesc
, locExt
, relLocExt
, &Ident
);
2752 if(!OS_SUCCESS(status
)) {
2753 FileSetDesc
->nextExt
.extLength
= 0;
2756 UDFRegisterFsStructure(Vcb
, locExt
, Vcb
->BlockSize
);
2757 if((locExt
== LBA_OUT_OF_EXTENT
) || (Ident
!= TID_FILE_SET_DESC
)) {
2758 // try to read previous FileSet
2759 if(!prevExt
) return STATUS_UNRECOGNIZED_VOLUME
;
2760 status
= UDFReadTagged(Vcb
, (int8
*)FileSetDesc
, prevExt
, relLocExt
, &Ident
);
2761 if(OS_SUCCESS(status
)) {
2762 UDFRegisterFsStructure(Vcb
, prevExt
, Vcb
->BlockSize
);
2767 relPrevExt
= relLocExt
;
2768 locExt
= UDFPartLbaToPhys(Vcb
, &(FileSetDesc
->nextExt
.extLocation
));
2770 return STATUS_SUCCESS
;
2771 } // end UDFFindLastFileSet()
2774 This routine reads all sparing tables & stores them in contiguos memory
2778 UDFLoadSparingTable(
2780 IN PSPARABLE_PARTITION_MAP PartMap
2783 PSPARING_MAP RelocMap
;
2784 PSPARING_MAP NewRelocMap
;
2786 uint32 i
=0, BC
, BC2
;
2787 PSPARING_TABLE SparTable
;
2788 uint32 TabSize
, NewSize
;
2790 uint32 SparTableLoc
;
2791 #ifdef UDF_TRACK_FS_STRUCTURES
2793 #endif //UDF_TRACK_FS_STRUCTURES
2797 Vcb
->SparingCountFree
= -1;
2799 UDFPrint(("UDF: Sparable Part Map:\n"));
2800 Vcb
->SparingTableLength
= PartMap
->sizeSparingTable
;
2801 BC
= (PartMap
->sizeSparingTable
>> Vcb
->BlockSizeBits
) + 1;
2802 UDFPrint((" partitionMapType = %x\n", PartMap
->partitionMapType
));
2803 UDFPrint((" partitionMapLength = %x\n", PartMap
->partitionMapLength
));
2804 UDFPrint((" volSeqNum = %x\n", PartMap
->volSeqNum
));
2805 UDFPrint((" partitionNum = %x\n", PartMap
->partitionNum
));
2806 UDFPrint((" packetLength = %x\n", PartMap
->packetLength
));
2807 UDFPrint((" numSparingTables = %x\n", PartMap
->numSparingTables
));
2808 UDFPrint((" sizeSparingTable = %x\n", PartMap
->sizeSparingTable
));
2809 SparTable
= (PSPARING_TABLE
)MyAllocatePool__(NonPagedPool
, BC
*Vcb
->BlockSize
);
2810 if(!SparTable
) return STATUS_INSUFFICIENT_RESOURCES
;
2811 if(Vcb
->SparingTable
) {
2812 // if a part of Sparing Table is already loaded,
2813 // update it with data from another one
2814 RelocMap
= Vcb
->SparingTable
;
2815 TabSize
= Vcb
->SparingCount
* sizeof(SPARING_ENTRY
);
2817 // do some init to load first part of Sparing Table
2818 RelocMap
= (PSPARING_MAP
)MyAllocatePool__(NonPagedPool
, RELOC_MAP_GRAN
);
2820 MyFreePool__(SparTable
);
2821 return STATUS_INSUFFICIENT_RESOURCES
;
2823 TabSize
= RELOC_MAP_GRAN
;
2824 Vcb
->SparingBlockSize
= PartMap
->packetLength
;
2826 // walk through all available Sparing Tables
2827 for(i
=0;i
<PartMap
->numSparingTables
;i
++) {
2828 // read (next) table
2829 SparTableLoc
= ((uint32
*)(PartMap
+1))[i
];
2830 for(n
=0; n
<Vcb
->SparingTableCount
; n
++) {
2831 if(Vcb
->SparingTableLoc
[i
] == SparTableLoc
) {
2832 UDFPrint((" already processed @%x\n",
2838 status
= UDFReadSectors(Vcb
, FALSE
, SparTableLoc
, 1, FALSE
, (int8
*)SparTable
, &ReadBytes
);
2839 // tag should be set to TID_UNUSED_DESC
2840 if(OS_SUCCESS(status
) && (SparTable
->descTag
.tagIdent
== TID_UNUSED_DESC
)) {
2842 UDFRegisterFsStructure(Vcb
, SparTableLoc
, Vcb
->BlockSize
);
2843 BC2
= ((sizeof(SPARING_TABLE
) +
2844 SparTable
->reallocationTableLen
*sizeof(SparingEntry
) +
2846 >> Vcb
->BlockSizeBits
);
2848 UDFPrint((" sizeSparingTable @%x too long: %x > %x\n",
2849 SparTableLoc
, BC2
, BC
2853 status
= UDFReadSectors(Vcb
, FALSE
, SparTableLoc
,
2854 BC2
, FALSE
, (int8
*)SparTable
, &ReadBytes
);
2855 UDFRegisterFsStructure(Vcb
, SparTableLoc
, BC2
<<Vcb
->BlockSizeBits
);
2857 if(!OS_SUCCESS(status
)) {
2858 UDFPrint((" Error reading sizeSparingTable @%x (%x)\n",
2863 // process sparing table
2864 NewSize
= sizeof(SparingEntry
)*SparTable
->reallocationTableLen
;
2865 TabSize
= MyReallocPool__((int8
*)RelocMap
, TabSize
, (int8
**)&RelocMap
, TabSize
+NewSize
);
2867 MyFreePool__(SparTable
);
2868 return STATUS_INSUFFICIENT_RESOURCES
;
2871 #ifdef UDF_TRACK_FS_STRUCTURES
2872 for(j
=0; j
<SparTable
->reallocationTableLen
; j
++) {
2873 UDFRegisterFsStructure(Vcb
, ((SparingEntry
*)(SparTable
+1))[j
].mappedLocation
, Vcb
->WriteBlockSize
);
2875 #endif //UDF_TRACK_FS_STRUCTURES
2877 Vcb
->SparingTableLoc
[Vcb
->SparingTableCount
] = SparTableLoc
;
2878 Vcb
->SparingTableCount
++;
2880 NewRelocMap
= (PSPARING_MAP
)(SparTable
+1);
2881 for(n
=0; n
<SparTable
->reallocationTableLen
; n
++) {
2883 for(m
=0; m
<Vcb
->SparingCount
; m
++) {
2884 if(RelocMap
[m
].mappedLocation
== NewRelocMap
[n
].mappedLocation
) {
2885 UDFPrint((" dup @%x (%x) vs @%x (%x)\n",
2886 RelocMap
[m
].origLocation
, RelocMap
[m
].mappedLocation
,
2887 NewRelocMap
[m
].origLocation
, NewRelocMap
[m
].mappedLocation
));
2890 if((RelocMap
[m
].origLocation
== NewRelocMap
[n
].origLocation
) &&
2891 (RelocMap
[m
].mappedLocation
!= NewRelocMap
[n
].mappedLocation
) &&
2892 (RelocMap
[m
].origLocation
!= SPARING_LOC_AVAILABLE
) &&
2893 (RelocMap
[m
].origLocation
!= SPARING_LOC_CORRUPTED
)) {
2894 UDFPrint((" conflict @%x (%x) vs @%x (%x)\n",
2895 RelocMap
[m
].origLocation
, RelocMap
[m
].m