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
21 #define XCHG_DD(a,b) \
24 PULONG _from_, _to_; \
25 _from_ = ((PULONG)&(b)); \
26 _to_ = ((PULONG)&(a)); \
32 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_MOUNT
37 IN PUNICODE_STRING UName
,
42 #ifndef UDF_READ_ONLY_BUILD
44 This routine loads specified bitmap.
45 It is also allocate space if the bitmap is not allocated.
48 UDFPrepareXSpaceBitmap(
50 IN OUT PSHORT_AD XSpaceBitmap
,
51 IN OUT PEXTENT_INFO XSBMExtInfo
,
66 if(!(XSpaceBitmap
->extLength
)) {
69 return STATUS_SUCCESS
;
72 PartNum
= UDFGetPartNumByPartNdx(Vcb
, Vcb
->PartitionMaps
-1);
73 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
74 plen
= UDFPartStart(Vcb
, PartNum
) + UDFPartLen(Vcb
, PartNum
);
77 LBS
= Vcb
->LBlockSize
;
79 *XSl
= sizeof(SPACE_BITMAP_DESC
) + ((plen
+7)>>3);
80 _XSBM
= (int8
*)DbgAllocatePool(NonPagedPool
, (*XSl
+ BS
- 1) & ~(BS
-1) );
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
) {
92 XSBMExtInfo
->Mapping
= UDFExtentToMapping(&TmpExt
);
93 XSBMExtInfo
->Offset
= 0;
94 XSBMExtInfo
->Length
= *XSl
;
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
) ))
103 if(XSBMExtInfo
->Mapping
[1].extLength
) {
104 KdPrint(("Can't allocate space for Freed Space bitmap\n"));
107 *XSl
= (uint32
)(XSBMExtInfo
->Length
);
108 XSpaceBitmap
->extPosition
= UDFPhysLbaToPart(Vcb
, PartNum
, XSBMExtInfo
->Mapping
[0].extLocation
);
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
) {
121 XSBMExtInfo
->Mapping
= UDFExtentToMapping(&TmpExt
);
122 XSBMExtInfo
->Offset
= 0;
123 XSBMExtInfo
->Length
= *XSl
;
130 return STATUS_INSUFFICIENT_RESOURCES
;
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
)) {
142 status
= STATUS_FILE_CORRUPT_ERROR
;
144 if(XSBMExtInfo
->Mapping
) {
145 MyFreePool__(XSBMExtInfo
->Mapping
);
146 XSBMExtInfo
->Mapping
= NULL
;
155 return STATUS_SUCCESS
;
158 case EXTENT_NEXT_EXTENT_ALLOCDESC
:
159 case EXTENT_NOT_RECORDED_NOT_ALLOCATED
:
160 case EXTENT_NOT_RECORDED_ALLOCATED
: {
166 PSPACE_BITMAP_DESC XSDesc
= (PSPACE_BITMAP_DESC
)(*XSBM
);
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
);
175 return STATUS_SUCCESS
;
176 } // end UDFPrepareXSpaceBitmap()
179 This routine updates Freed & Unallocated space bitmaps
182 UDFUpdateXSpaceBitmaps(
185 IN PPARTITION_HEADER_DESC phd
// partition header pointing to Bitmaps
189 uint32 plen
, pstart
, pend
;
195 OSSTATUS status
, status2
;
199 EXTENT_INFO FSBMExtInfo
, USBMExtInfo
;
203 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
205 plen
= UDFPartLen(Vcb
, PartNum
);
206 locAddr
.partitionReferenceNum
= (uint16
)PartNum
;
207 // prepare bitmaps for updating
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
)) {
216 pstart
= UDFPartStart(Vcb
, PartNum
);
217 new_bm
= Vcb
->FSBM_Bitmap
;
218 old_bm
= Vcb
->FSBM_OldBitmap
;
219 bad_bm
= Vcb
->BSBM_Bitmap
;
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
);
229 KdPrint(("Can't update USBM\n"));
232 if(USBMExtInfo
.Mapping
) MyFreePool__(USBMExtInfo
.Mapping
);
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
);
239 KdPrint(("Can't update FSBM\n"));
241 if(FSBMExtInfo
.Mapping
) MyFreePool__(FSBMExtInfo
.Mapping
);
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
);
249 // if we have some bad bits, mark corresponding area as BAD
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
);
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
)) {
266 if(USBM
) UDFSetUsedBit(upart_bm
, j
);
267 if(FSBM
) UDFSetUsedBit(fpart_bm
, j
);
273 status
= UDFWriteExtent(Vcb
, &USBMExtInfo
, 0, USl
, FALSE
, USBM
, &WrittenBytes
);
275 MyFreePool__(USBMExtInfo
.Mapping
);
278 status2
= UDFWriteExtent(Vcb
, &FSBMExtInfo
, 0, FSl
, FALSE
, FSBM
, &WrittenBytes
);
280 MyFreePool__(FSBMExtInfo
.Mapping
);
286 if(!OS_SUCCESS(status
))
289 } // end UDFUpdateXSpaceBitmaps()
292 This routine updates Partition Desc & associated data structures
300 PartitionDesc
*p
= (PartitionDesc
*)Buf
;
305 for(i
=0; i
<Vcb
->PartitionMaps
; i
++)
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
)))
311 PPARTITION_HEADER_DESC phd
;
313 phd
= (PPARTITION_HEADER_DESC
)(p
->partitionContentsUse
);
315 if(phd
->unallocatedSpaceTable
.extLength
) {
316 // rebuild unallocatedSpaceTable
317 KdPrint(("unallocatedSpaceTable (part %d)\n", i
));
319 if(phd
->freedSpaceTable
.extLength
) {
320 // rebuild freedSpaceTable
321 KdPrint(("freedSpaceTable (part %d)\n", i
));
324 UDFUpdateXSpaceBitmaps(Vcb
, p
->partitionNumber
, phd
);
326 UDFSetUpTag(Vcb
, PTag
, PTag
->descCRCLength
, PTag
->tagLocation
);
327 UDFWriteSectors(Vcb
, TRUE
, PTag
->tagLocation
, 1, FALSE
, Buf
, &WrittenBytes
);
330 return STATUS_SUCCESS
;
331 } // end UDFUpdatePartDesc()
334 This routine blanks Unalloc Space Desc
342 PUNALLOC_SPACE_DESC usd;
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;
354 update Logical volume integrity descriptor
357 UDFUpdateLogicalVolInt(
362 OSSTATUS RC
= STATUS_SUCCESS
;
365 // uint32 lvid_count = 0;
368 LogicalVolIntegrityDesc
*lvid
;
369 LogicalVolIntegrityDescImpUse
* LVID_iUse
;
370 LogicalVolHeaderDesc
* LVID_hd
;
371 uint32
* partFreeSpace
;
372 BOOLEAN equal
= FALSE
;
375 return STATUS_SUCCESS
;
377 return STATUS_UNSUCCESSFUL
;
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
);
383 if(lvid
->descTag
.tagSerialNum
> UDF_LVID_TTL
) {
384 // TODO: allocate space for new LVID
387 LVID_iUse
= UDFGetLVIDiUse(Vcb
);
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
))
396 LVID_iUse
->minUDFReadRev
= Vcb
->minUDFReadRev
;
397 LVID_iUse
->minUDFWriteRev
= Vcb
->minUDFWriteRev
;
398 LVID_iUse
->maxUDFWriteRev
= Vcb
->maxUDFWriteRev
;
400 LVID_iUse
->numFiles
= Vcb
->numFiles
;
401 LVID_iUse
->numDirs
= Vcb
->numDirs
;
404 UDFSetEntityID_imp(&(LVID_iUse
->impIdent
), UDF_ID_DEVELOPER
);
408 KdPrint(("UDF: Opening LVID\n"));
409 lvid
->integrityType
= INTEGRITY_TYPE_CLOSE
;
411 KdPrint(("UDF: Closing LVID\n"));
412 lvid
->integrityType
= INTEGRITY_TYPE_OPEN
;
415 equal
= equal
&& (Vcb
->IntegrityType
== lvid
->integrityType
);
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
;
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
;
431 KdPrint(("UDF: equal Ids\n"));
432 return STATUS_SUCCESS
;
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
),
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
;
451 } // end UDFUpdateLogicalVolInt()
454 This routine reads all sparing tables & stores them in contiguos memory
458 UDFUpdateSparingTable(
462 PSPARING_MAP RelocMap
;
463 // PSPARING_MAP NewRelocMap;
464 OSSTATUS status
= STATUS_SUCCESS
;
465 OSSTATUS status2
= STATUS_SUCCESS
;
467 PSPARING_TABLE SparTable
;
473 KdPrint(("UDF: Updating Sparable Part Map:\n"));
474 if(!Vcb
->SparingTableModified
) return STATUS_SUCCESS
;
475 if(!Vcb
->SparingTable
) return STATUS_SUCCESS
;
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
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
);
491 XCHG_DD(RelocMap
[i
-1].mappedLocation
, RelocMap
[i
].mappedLocation
);
495 if(RelocMap
[i
-1].origLocation
== SPARING_LOC_AVAILABLE
&&
496 RelocMap
[i
].origLocation
== SPARING_LOC_AVAILABLE
&&
497 RelocMap
[i
-1].mappedLocation
> RelocMap
[i
].mappedLocation
) {
503 for(i
=0;i
<Vcb
->SparingCount
;i
++) {
504 KdPrint((" @%x -> %x \n",
505 RelocMap
[i
].origLocation
, RelocMap
[i
].mappedLocation
));
508 Vcb
->SparingTableModified
= FALSE
;
510 // KdPrint((" sparing table unchanged\n"));
511 // MyFreePool__(SparTable);
512 // return STATUS_SUCCESS;
515 // walk through all available Sparing Tables
516 for(i
=0;i
<Vcb
->SparingTableCount
;i
++) {
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
)) {
523 BC2
= ((sizeof(SPARING_TABLE
) +
524 SparTable
->reallocationTableLen
*sizeof(SparingEntry
) +
526 >> Vcb
->BlockSizeBits
);
528 KdPrint((" sizeSparingTable @%x too long: %x > %x\n",
529 Vcb
->SparingTableLoc
[i
], BC2
, BC
533 status
= UDFReadSectors(Vcb
, FALSE
, Vcb
->SparingTableLoc
[i
],
534 BC2
, FALSE
, (int8
*)SparTable
, &ReadBytes
);
536 if(!OS_SUCCESS(status
)) {
537 KdPrint((" Error reading sizeSparingTable @%x (%x)\n",
538 Vcb
->SparingTableLoc
[i
], BC2
543 BC2
= ((sizeof(SPARING_TABLE
) +
544 Vcb
->SparingCount
*sizeof(SparingEntry
) +
546 >> Vcb
->BlockSizeBits
);
548 KdPrint((" new sizeSparingTable @%x too long: %x > %x\n",
549 Vcb
->SparingTableLoc
[i
], BC2
, BC
554 SparTable
->reallocationTableLen
= (USHORT
)Vcb
->SparingCount
;
555 RtlCopyMemory((SparTable
+1), RelocMap
, Vcb
->SparingCount
*sizeof(SparingEntry
));
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));
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
)) {
583 MyFreePool__(SparTable
);
584 if(!OS_SUCCESS(status2
)) {
588 } // end UDFUpdateSparingTable()
591 update Logical volume descriptor
596 IN UDF_VDS_RECORD Lba
,
597 IN PUNICODE_STRING VolIdent
600 LogicalVolDesc
* lvd
= NULL
;
601 #define CUR_IDENT_SZ (sizeof(lvd->logicalVolIdent))
602 dstring CS0
[CUR_IDENT_SZ
];
605 OSSTATUS status
= STATUS_SUCCESS
;
606 // OSSTATUS status2 = STATUS_SUCCESS;
608 status
= UDFUpdateSparingTable(Vcb
);
610 if(!(Vcb
->CompatFlags
& UDF_VCB_IC_W2K_COMPAT_VLABEL
)) {
614 lvd
= (LogicalVolDesc
*)MyAllocatePool__(NonPagedPool
, max(Vcb
->BlockSize
, sizeof(LogicalVolDesc
)) );
617 status
= STATUS_INSUFFICIENT_RESOURCES
;
621 KdPrint(("UDF: Updating LVD @%x (%x)\n", Lba
.block
, Vcb
->BlockSize
));
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
;
632 status
= STATUS_INVALID_PARAMETER
;
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
;
642 if(RtlCompareMemory(lvd
->logicalVolIdent
, CS0
, CUR_IDENT_SZ
) == CUR_IDENT_SZ
) {
644 KdPrint(("UDF: equal VolIds\n"));
645 status
= STATUS_SUCCESS
;
648 RtlCopyMemory(lvd
->logicalVolIdent
, CS0
, CUR_IDENT_SZ
);
650 lvd
->descTag
.tagSerialNum
--;
651 UDFSetUpTag(Vcb
, (tag
*)lvd
, lvd
->descTag
.descCRCLength
, Lba
.block
);
653 status
= UDFWriteSectors(Vcb
, TRUE
, Lba
.block
, 1, FALSE
, (int8
*)lvd
, &WrittenBytes
);
663 } // end UDFUpdateLogicalVol()
666 This routine updates volume descriptor sequence
677 int8
* Buf
= (int8
*)DbgAllocatePool(NonPagedPool
,Vcb
->LBlockSize
);
678 UDF_VDS_RECORD vds
[VDS_POS_LENGTH
];
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
))) {
690 // update USD (if any)
691 for (i=0; i<VDS_POS_LENGTH; i++) {
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);
699 return STATUS_INSUFFICIENT_RESOURCES;
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);
713 for (i
=0; i
<VDS_POS_LENGTH
; i
++) {
715 status
= UDFReadTagged(Vcb
, Buf
, vds
[i
].block
, vds
[i
].block
, &ident
);
716 if(!OS_SUCCESS(status
))
719 if(i
== VDS_POS_PARTITION_DESC
) {
722 // update partition descriptor(s)
723 int8
* Buf2
= (int8
*)DbgAllocatePool(NonPagedPool
,Vcb
->BlockSize
);
726 return STATUS_INSUFFICIENT_RESOURCES
;
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
);
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
))
748 } // end UDFUpdateVDS()
749 #endif //UDF_READ_ONLY_BUILD
754 IN PUNICODE_STRING UName
,
760 uint32 len
= Length
-1;
762 UDFCompressUnicode(UName
, &CS0
, &len
);
764 return STATUS_INSUFFICIENT_RESOURCES
;
767 return STATUS_INVALID_PARAMETER
;
769 RtlCopyMemory(Dest
, CS0
, len
);
772 RtlZeroMemory(Dest
+len
, Length
-1-len
);
773 Dest
[Length
-1] = (uint8
)len
;
775 } // end UDFSetDstring()
780 IN OUT PUNICODE_STRING UName
,
785 uint32 len
= Dest
[Length
-1];
787 UDFDecompressUnicode(UName
, Dest
, len
, NULL
);
789 } // end UDFGetDstring()
791 #ifndef UDF_READ_ONLY_BUILD
793 This routine updates Volume Label & some other features stored in
799 IN UDF_VDS_RECORD Lba
,
800 IN PUNICODE_STRING VolIdent
803 #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent))
804 PrimaryVolDesc
* pvoldesc
= (PrimaryVolDesc
*)MyAllocatePool__(NonPagedPool
, max(Vcb
->BlockSize
, sizeof(PrimaryVolDesc
)) );
806 dstring CS0
[CUR_IDENT_SZ
];
810 if(!pvoldesc
) return STATUS_INSUFFICIENT_RESOURCES
;
812 KdPrint(("UDF: Updating PVD @%x (%x)\n", Lba
.block
, Vcb
->BlockSize
));
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
;
823 status
= STATUS_INVALID_PARAMETER
;
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
;
833 if(RtlCompareMemory(pvoldesc
->volIdent
, CS0
, CUR_IDENT_SZ
) == CUR_IDENT_SZ
) {
835 status
= STATUS_SUCCESS
;
838 RtlCopyMemory(pvoldesc
->volIdent
, CS0
, CUR_IDENT_SZ
);
840 pvoldesc
->descTag
.tagSerialNum
--;
841 UDFSetUpTag(Vcb
, (tag
*)pvoldesc
, pvoldesc
->descTag
.descCRCLength
, Lba
.block
);
843 status
= UDFWriteSectors(Vcb
, TRUE
, Lba
.block
, 1, FALSE
, (int8
*)pvoldesc
, &WrittenBytes
);
845 MyFreePool__(pvoldesc
);
849 } // end UDFUpdateVolIdent()
850 #endif //UDF_READ_ONLY_BUILD
853 UDFUpdateNonAllocated(
859 uint32 plen
, pstart
, pend
;
862 PEXTENT_MAP Map
= NULL
;
863 PEXTENT_INFO DataLoc
;
865 KdPrint(("UDFUpdateNonAllocated:\n"));
866 if(!Vcb
->NonAllocFileInfo
) {
867 return STATUS_SUCCESS
;
869 if(!(bad_bm
= Vcb
->BSBM_Bitmap
)) {
870 return STATUS_SUCCESS
;
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
;
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
);
885 for(i
=pstart
; i
<pend
; i
++) {
886 if(!UDFGetBadBit(bad_bm
, i
))
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
));
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
);
902 UDFPackMapping(Vcb
, DataLoc
);
903 DataLoc
->Length
= UDFGetExtentLength(DataLoc
->Mapping
);
904 UDFFlushFile__(Vcb
, Vcb
->NonAllocFileInfo
);
906 // ensure that BAD space is marked as USED
907 UDFMarkSpaceAsXXX(Vcb
, 0, &(DataLoc
->Mapping
[0]), AS_USED
); // mark as used
909 KdPrint(("UDFUpdateNonAllocated: done\n"));
910 return STATUS_SUCCESS
;
911 } // end UDFUpdateNonAllocated()
914 This routine rebuilds & flushes all system areas
921 #ifndef UDF_READ_ONLY_BUILD
924 if(((Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_READ_ONLY
) &&
925 !(UDFGlobalData
.UDFFlags
& UDF_DATA_FLAGS_UNREGISTERED
))
927 return STATUS_SUCCESS
;
928 // prevent discarding metadata
929 Vcb
->VCBFlags
|= UDF_VCB_ASSUME_ALL_USED
;
931 // flush internal cache
932 if(WCacheGetWriteBlockCount__(&(Vcb
->FastCache
)) >= (Vcb
->WriteBlockSize
>> Vcb
->BlockSizeBits
) )
933 WCacheFlushAll__(&(Vcb
->FastCache
), Vcb
);
935 return UDFRecordVAT(Vcb
);
938 UDFFlushAllCachedAllocations(Vcb
, UDF_PREALLOC_CLASS_FE
);
939 UDFFlushAllCachedAllocations(Vcb
, UDF_PREALLOC_CLASS_DIR
);
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
);
948 // synchronize BAD Block bitmap and NonAllocatable
949 UDFUpdateNonAllocated(Vcb
);
951 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
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"));
960 UDFUpdateVolIdent(Vcb
, Vcb
->PVolDescAddr
, &(Vcb
->VolIdent
));
961 UDFUpdateVolIdent(Vcb
, Vcb
->PVolDescAddr2
, &(Vcb
->VolIdent
));
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
)) {
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"));
978 UDFUpdateVDS(Vcb
, Vcb
->VDS1
, Vcb
->VDS1
+ Vcb
->VDS1_Len
, flags
);
979 UDFUpdateVDS(Vcb
, Vcb
->VDS2
, Vcb
->VDS2
+ Vcb
->VDS2_Len
, flags
);
982 // Update Integrity Desc if any
983 if(Vcb
->LVid
&& Vcb
->origIntegrityType
== INTEGRITY_TYPE_CLOSE
) {
984 UDFUpdateLogicalVolInt(Vcb
, TRUE
);
988 RtlCopyMemory(Vcb
->FSBM_OldBitmap
, Vcb
->FSBM_Bitmap
, Vcb
->FSBM_ByteCount
);
990 //skip_update_bitmap:
992 Vcb
->VCBFlags
&= ~UDF_VCB_ASSUME_ALL_USED
;
994 UDFReleaseResource(&(Vcb
->BitMapResource1
));
995 #endif //UDF_READ_ONLY_BUILD
997 return STATUS_SUCCESS
;
998 } // end UDFUmount__()
1000 /*************************************************************************
1003 Find an anchor volume descriptor.
1004 The UDFGetDiskInfoAndVerify() will invoke this routine to find & check
1005 Anchor Volume Descriptors on the target device
1009 PVCB Vcb
// Volume control block
1012 // OSSTATUS RC = STATUS_SUCCESS;
1018 int8
* Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
1019 BOOLEAN MRW_candidate
;
1020 BOOLEAN IsMRW
= (Vcb
->MRWStatus
!= 0);
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;
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;
1043 // ... and check them
1044 for (i
=0; i
<sizeof(Vcb
->Anchor
)/sizeof(int); i
++) {
1045 if(Vcb
->Anchor
[i
] > Vcb
->LastLBA
)
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
))) {
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
;
1066 if(status
== STATUS_NONEXISTENT_SECTOR
) {
1067 KdPrint(("UDF: disk seems to be incomplete\n"));
1072 if((ident
!= TID_ANCHOR_VOL_DESC_PTR
) && ((i
<6) ||
1073 (ident
!= TID_FILE_ENTRY
&& ident
!= TID_EXTENDED_FILE_ENTRY
))) {
1076 KdPrint(("UDF: Found AVD at %x (point %d)\n",Vcb
->Anchor
[i
], i
));
1078 LastBlock
= Vcb
->LastLBA
;
1080 KdPrint(("UDF: looks like we _*really*_ have MRW....\n"));
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
;
1088 UDFRegisterFsStructure(Vcb
, Vcb
->Anchor
[i
], Vcb
->BlockSize
);
1096 KdPrint(("UDF: -----------------\nUDF: Last block %x\n",LastBlock
));
1099 } // end UDFFindAnchor()
1102 Look for Volume recognition sequence
1109 VolStructDesc
*vsd
= NULL
;
1112 uint32 BeginOffset
= Vcb
->FirstLBA
;
1114 int8
* buffer
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
1117 if(!buffer
) return 0;
1118 // Relative to First LBA in Last Session
1119 offset
= Vcb
->FirstLBA
+ 0x10;
1121 KdPrint(("UDFFindVRS:\n"));
1123 // Process the sequence (if applicable)
1124 for (;(offset
-BeginOffset
<=0x20); offset
++) {
1126 RC
= UDFReadSectors(Vcb
, FALSE
, offset
, 1, FALSE
, buffer
, &ReadBytes
);
1127 if(!OS_SUCCESS(RC
)) continue;
1129 // Look for ISO descriptors
1130 vsd
= (VolStructDesc
*)(buffer
);
1132 if(vsd
->stdIdent
[0]) {
1133 if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_CD001
, STD_ID_LEN
))
1135 retStat
|= VRS_ISO9660_FOUND
;
1136 switch (vsd
->structType
)
1139 KdPrint(("UDF: ISO9660 Boot Record found\n"));
1142 KdPrint(("UDF: ISO9660 Primary Volume Descriptor found\n"));
1145 KdPrint(("UDF: ISO9660 Supplementary Volume Descriptor found\n"));
1148 KdPrint(("UDF: ISO9660 Volume Partition Descriptor found\n"));
1151 KdPrint(("UDF: ISO9660 Volume Descriptor Set Terminator found\n"));
1154 KdPrint(("UDF: ISO9660 VRS (%u) found\n", vsd
->structType
));
1158 else if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_BEA01
, STD_ID_LEN
))
1160 KdPrint(("UDF: BEA01 Found\n"));
1162 else if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_TEA01
, STD_ID_LEN
))
1164 KdPrint(("UDF: TEA01 Found\n"));
1167 else if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_NSR02
, STD_ID_LEN
))
1169 retStat
|= VRS_NSR02_FOUND
;
1170 KdPrint(("UDF: NSR02 Found\n"));
1173 else if(!strncmp((int8
*)(&vsd
->stdIdent
), STD_ID_NSR03
, STD_ID_LEN
))
1175 retStat
|= VRS_NSR03_FOUND
;
1176 KdPrint(("UDF: NSR03 Found\n"));
1182 MyFreePool__(buffer
);
1185 } // end UDFFindVRS()
1188 process Primary volume descriptor
1193 int8
* Buf
// pointer to buffer containing PVD
1196 PrimaryVolDesc
*pvoldesc
;
1197 // OSSTATUS RC = STATUS_SUCCESS;
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
));
1206 #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent))
1207 if (Vcb
->VolIdent
.Buffer
) {
1208 MyFreePool__(Vcb
->VolIdent
.Buffer
);
1210 UDFGetDstring(&(Vcb
->VolIdent
), (dstring
*)&(pvoldesc
->volIdent
), CUR_IDENT_SZ
);
1212 KdPrint(("volIdent[] = '%ws'\n", Vcb
->VolIdent
.Buffer
));
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
);
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
);
1230 } // end UDFLoadPVolDesc()
1233 load Logical volume integrity descriptor
1236 UDFLoadLogicalVolInt(
1237 PDEVICE_OBJECT DeviceObject
,
1242 OSSTATUS RC
= STATUS_SUCCESS
;
1247 LogicalVolIntegrityDescImpUse
* LVID_iUse
;
1248 LogicalVolHeaderDesc
* LVID_hd
;
1250 BOOLEAN read_last
= FALSE
;
1251 uint32 lvid_count
= 0;
1255 MyFreePool__(Vcb
->LVid
);
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
);
1264 return STATUS_INSUFFICIENT_RESOURCES
;
1265 RC
= UDFReadTagged(Vcb
,Buf
, loc
.extLocation
, loc
.extLocation
, &ident
);
1266 if(!OS_SUCCESS(RC
)) {
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
;
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;
1281 case UDF_PART_DAMAGED_RW
:
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
;
1293 UDFRegisterFsStructure(Vcb
, loc
.extLocation
, len
);
1294 // handle Terminal Entry
1295 if(ident
== TID_TERMINAL_ENTRY
) {
1302 if(ident
!= TID_LOGICAL_VOL_INTEGRITY_DESC
) {
1303 RC
= STATUS_DISK_CORRUPT_ERROR
;
1307 Vcb
->LVid
= (LogicalVolIntegrityDesc
*)Buf
;
1308 RC
= UDFReadData(Vcb
, TRUE
, ((uint64
)(loc
.extLocation
)) << Vcb
->BlockSizeBits
, len
, FALSE
, Buf
, &_ReadBytes
);
1311 Vcb
->LVid
->nextIntegrityExt
.extLength
) {
1314 loc
= Vcb
->LVid
->nextIntegrityExt
;
1318 if(lvid_count
> UDF_MAX_LVID_CHAIN_LENGTH
) {
1319 RC
= STATUS_DISK_CORRUPT_ERROR
;
1324 // process last LVID
1325 Vcb
->origIntegrityType
=
1326 Vcb
->IntegrityType
= Vcb
->LVid
->integrityType
;
1327 Vcb
->LVid_loc
= loc
;
1329 LVID_iUse
= UDFGetLVIDiUse(Vcb
);
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"));
1337 Vcb
->minUDFReadRev
= LVID_iUse
->minUDFReadRev
;
1338 Vcb
->minUDFWriteRev
= LVID_iUse
->minUDFWriteRev
;
1339 Vcb
->maxUDFWriteRev
= LVID_iUse
->maxUDFWriteRev
;
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
));
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
;
1356 LVID_hd
= (LogicalVolHeaderDesc
*)&(Vcb
->LVid
->logicalVolContentsUse
);
1357 Vcb
->NextUniqueId
= LVID_hd
->uniqueID
;
1358 KdPrint((" Next FID: %x\n",Vcb
->NextUniqueId
));
1364 } // end UDFLoadLogicalVolInt()
1368 load Logical volume descriptor
1372 PDEVICE_OBJECT DeviceObject
,
1378 LogicalVolDesc
*lvd
= (LogicalVolDesc
*)Buf
;
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
;
1390 if(Vcb
->PartitionMaps
!= lvd
->numPartitionMaps
)
1391 return STATUS_DISK_CORRUPT_ERROR
;
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
));
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;
1412 KdPrint(("UDF: Bad block size (%ld)\n", Vcb
->LBlockSize
));
1413 return STATUS_DISK_CORRUPT_ERROR
;
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
1421 i
<Vcb
->PartitionMaps
&& offset
<lvd
->mapTableLength
;
1422 i
++,offset
+=((GenericPartitionMap
*)( ((uint8
*)(lvd
+1))+offset
) )->partitionMapLength
)
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
)
1429 GenericPartitionMap1
*gpm1
= (GenericPartitionMap1
*)(((uint8
*)(lvd
+1))+offset
);
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
;
1436 else if(type
== PARTITION_MAP_TYPE_2
)
1438 UdfPartitionMap2
* upm2
= (UdfPartitionMap2
*)(((uint8
*)(lvd
+1))+offset
);
1439 if(!strncmp((int8
*)&(upm2
->partIdent
.ident
), UDF_ID_VIRTUAL
, strlen(UDF_ID_VIRTUAL
)))
1441 UDFIdentSuffix
* udfis
=
1442 (UDFIdentSuffix
*)&(upm2
->partIdent
.identSuffix
);
1444 if( (udfis
->currentRev
== 0x0150)/* ||
1445 (Vcb->CurrentUDFRev == 0x0150)*/ ) {
1446 KdPrint(("Found VAT 1.50\n"));
1447 Vcb
->Partitions
[i
].PartitionType
= UDF_VIRTUAL_MAP15
;
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
;
1456 status
= STATUS_SUCCESS
;
1458 else if(!strncmp((int8
*)&(upm2
->partIdent
.ident
), UDF_ID_SPARABLE
, strlen(UDF_ID_SPARABLE
)))
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
);
1465 else if(!strncmp((int8
*)&(upm2
->partIdent
.ident
), UDF_ID_METADATA
, strlen(UDF_ID_METADATA
)))
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);
1474 KdPrint(("Unknown ident: %s\n", upm2
->partIdent
.ident
));
1477 Vcb
->Partitions
[i
].VolumeSeqNum
= upm2
->volSeqNum
;
1478 Vcb
->Partitions
[i
].PartitionNum
= upm2
->partitionNum
;
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
));
1490 if(OS_SUCCESS(status
)) {
1491 // load Integrity Desc if any
1492 if(lvd
->integritySeqExt
.extLength
)
1493 status
= UDFLoadLogicalVolInt(DeviceObject
,Vcb
,lvd
->integritySeqExt
);
1496 } // end UDFLoadLogicalVol()
1499 UDFLoadBogusLogicalVol(
1500 PDEVICE_OBJECT DeviceObject
,
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
;
1515 if(Vcb
->PartitionMaps
!= 1)
1516 return STATUS_DISK_CORRUPT_ERROR
;
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));
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));
1535 Vcb
->Partitions
[0].PartitionType
= UDF_TYPE1_MAP15
;
1536 Vcb
->Partitions
[0].VolumeSeqNum
= 0;
1537 Vcb
->Partitions
[0].PartitionNum
= 0;
1541 KdPrint(("Found VAT 1.50\n"));
1542 Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP15;
1544 KdPrint(("Found VAT 2.00\n"));
1545 Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP20;
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
));
1559 return STATUS_SUCCESS
;
1560 } // end UDFLoadBogusLogicalVol()
1563 This routine adds given Bitmap to existing one
1575 uint32 i
, lim
, j
, lba
, l
, lim2
, l2
, k
;
1584 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
1585 KdPrint(("UDFAddXSpaceBitmap: at block=%x, partition=%d\n",
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
)) ) {
1604 if(Ident
!= TID_SPACE_BITMAP_DESC
) {
1605 status
= STATUS_DISK_CORRUPT_ERROR
;
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
)))
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
);
1616 for(;(l
= UDFGetBitmapLen((uint32
*)tmp_bm
, j
, lim2
)) && (i
<lim
);) {
1617 // expand LBlocks to Sectors...
1618 l2
= l
<< Vcb
->LB2B_Bits
;
1620 if(bm_type
== UDF_FSPACE_BM
) {
1621 bit_set
= UDFGetFreeBit(tmp_bm
, j
);
1622 for(k
=0;(k
<l2
) && (i
<lim
);k
++) {
1625 UDFSetFreeBit(Vcb
->FSBM_Bitmap
, i
);
1626 UDFSetFreeBitOwner(Vcb
, i
);
1627 UDFSetZeroBit(Vcb
->ZSBM_Bitmap
, i
);
1630 UDFClrZeroBit(Vcb
->ZSBM_Bitmap
, i
);
1635 bit_set
= UDFGetZeroBit(tmp_bm
, j
);
1636 for(k
=0;(k
<l2
) && (i
<lim
);k
++) {
1639 UDFSetZeroBit(Vcb
->ZSBM_Bitmap
, i
);
1642 UDFClrZeroBit(Vcb
->ZSBM_Bitmap
, i
);
1650 /* } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1651 i=Vcb->Partitions[PartNum].PartitionRoot;
1652 lim = i + Vcb->Partitions[PartNum].PartitionLen;
1654 UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1657 return STATUS_SUCCESS
;
1658 } // end UDFAddXSpaceBitmap()
1661 This routine adds given Bitmap to existing one
1664 UDFVerifyXSpaceBitmap(
1673 // uint32 i, lim, j, lba, l, lim2, l2, k;
1674 uint32 i
, lim
, j
, lba
, lim2
;
1683 UDF_CHECK_BITMAP_RESOURCE(Vcb
);
1685 KdPrint((" UDFVerifyXSpaceBitmap: part %x\n", PartNum
));
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
)) ) {
1702 KdPrint((" BM Lba %x\n", lba
));
1703 if(Ident
!= TID_SPACE_BITMAP_DESC
) {
1704 status
= STATUS_DISK_CORRUPT_ERROR
;
1707 // read the whole Bitmap
1708 if(!OS_SUCCESS(status
= UDFReadData(Vcb
, FALSE
, ((uint64
)lba
)<<Vcb
->BlockSizeBits
, Length
, FALSE
, tmp
, &ReadBytes
)))
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
);
1714 /* for(;(l = UDFGetBitmapLen((uint32*)tmp_bm, j, lim2)) && (i<lim);) {
1715 // expand LBlocks to Sectors...
1716 l2 = l << Vcb->LB2B_Bits;
1718 if(bm_type == UDF_FSPACE_BM) {
1719 bit_set = UDFGetFreeBit(tmp_bm, j);
1720 for(k=0;(k<l2) && (i<lim);k++) {
1723 UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1724 UDFSetFreeBitOwner(Vcb, i);
1725 UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1728 UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1733 bit_set = UDFGetZeroBit(tmp_bm, j);
1734 for(k=0;(k<l2) && (i<lim);k++) {
1737 UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1740 UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1748 /* } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1749 i=Vcb->Partitions[PartNum].PartitionRoot;
1750 lim = i + Vcb->Partitions[PartNum].PartitionLen;
1752 UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1755 return STATUS_SUCCESS
;
1756 } // end UDFVerifyXSpaceBitmap()
1759 This routine subtracts given Bitmap to existing one
1777 if(!(Length = (bm->extLength & UDF_EXTENT_LENGTH_MASK))) return STATUS_SUCCESS;
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) ) {
1791 if(!OS_SUCCESS(status = UDFReadData(Vcb, FALSE, ((uint64)j)<<Vcb->BlockSizeBits, Length, FALSE, tmp, &ReadBytes))) {
1795 lim = i + ((PSPACE_BITMAP_DESC)tmp)->numOfBits;
1796 tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1799 if(UDFGetUsedBit(tmp_bm, j)) UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
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);
1810 return STATUS_SUCCESS;
1811 } // end UDFDelXSpaceBitmap() */
1814 This routine verifues FreeSpaceBitmap (internal) according to media
1815 parameters & input data
1818 UDFVerifyFreeSpaceBitmap(
1821 IN PPARTITION_HEADER_DESC phd
, // partition header pointing to Bitmaps
1822 IN uint32 Lba
// UnallocSpaceDesc
1833 PartNum
= UDFGetPartNumByPartNdx(Vcb
, PartNdx
);
1835 KdPrint(("UDFVerifyFreeSpaceBitmap:\n"));
1836 // read info for partition header (if any)
1838 // read unallocated Bitmap
1839 if(!OS_SUCCESS(status
= UDFVerifyXSpaceBitmap(Vcb
, PartNum
, &(phd
->unallocatedSpaceBitmap
), UDF_FSPACE_BM
)))
1841 // read freed Bitmap
1842 if(!OS_SUCCESS(status
= UDFVerifyXSpaceBitmap(Vcb
, PartNum
, &(phd
->freedSpaceBitmap
), UDF_ZSPACE_BM
)))
1845 // read UnallocatedSpaceDesc & convert to Bitmap
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
);
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
) {
1866 MyFreePool__(AllocDesc
);
1867 return STATUS_DISK_CORRUPT_ERROR
;
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
);
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
;
1884 Extent
[i
].extLength
=
1885 Extent
[i
].extLocation
= 0;
1886 Extent
= UDFMergeMappings(Extent
, (PEXTENT_MAP
)(AllocDesc
+sizeof(UNALLOC_SPACE_DESC
)) );
1889 KdPrint(("Broken unallocated space descriptor sequence\n"));
1894 // UDFMarkSpaceAsXXX(Vcb, (-1), Extent, AS_USED); // mark as used
1895 MyFreePool__(Extent
);
1896 MyFreePool__(AllocDesc
);
1897 status
= STATUS_SUCCESS
;
1900 } // end UDFBuildFreeSpaceBitmap()
1903 This routine builds FreeSpaceBitmap (internal) according to media
1904 parameters & input data
1907 UDFBuildFreeSpaceBitmap(
1910 IN PPARTITION_HEADER_DESC phd
, // partition header pointing to Bitmaps
1911 IN uint32 Lba
// UnallocSpaceDesc
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
;
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
1932 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1933 MyFreePool__(Vcb
->FSBM_Bitmap
);
1934 Vcb
->FSBM_Bitmap
= NULL
;
1935 return STATUS_INSUFFICIENT_RESOURCES
;
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
;
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;
1952 // read info for partition header (if any)
1954 // read unallocated Bitmap
1955 if(!OS_SUCCESS(status
= UDFAddXSpaceBitmap(Vcb
, PartNum
, &(phd
->unallocatedSpaceBitmap
), UDF_FSPACE_BM
)))
1957 // read freed Bitmap
1958 if(!OS_SUCCESS(status
= UDFAddXSpaceBitmap(Vcb
, PartNum
, &(phd
->freedSpaceBitmap
), UDF_ZSPACE_BM
)))
1961 // read UnallocatedSpaceDesc & convert to Bitmap
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
);
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
) {
1981 MyFreePool__(AllocDesc
);
1982 return STATUS_DISK_CORRUPT_ERROR
;
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
);
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
;
1999 Extent
[i
].extLength
=
2000 Extent
[i
].extLocation
= 0;
2001 Extent
= UDFMergeMappings(Extent
, (PEXTENT_MAP
)(AllocDesc
+sizeof(UNALLOC_SPACE_DESC
)) );
2004 KdPrint(("Broken unallocated space descriptor sequence\n"));
2009 UDFMarkSpaceAsXXX(Vcb
, (-1), Extent
, AS_USED
); // mark as used
2010 MyFreePool__(Extent
);
2011 MyFreePool__(AllocDesc
);
2014 } // end UDFVerifyFreeSpaceBitmap()
2017 process Partition descriptor
2025 PartitionDesc
*p
= (PartitionDesc
*)Buf
;
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
)) {
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
;
2063 if(!strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR02
) ||
2064 !strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR03
))
2066 PPARTITION_HEADER_DESC phd
;
2068 phd
= (PPARTITION_HEADER_DESC
)(p
->partitionContentsUse
);
2070 if(phd
->unallocatedSpaceTable
.extLength
)
2071 KdPrint(("unallocatedSpaceTable (part %d)\n", i
));
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
));
2080 if(phd
->partitionIntegrityTable
.extLength
)
2081 KdPrint(("partitionIntegrityTable (part %d)\n", i
));
2082 if(phd
->freedSpaceTable
.extLength
)
2083 KdPrint(("freedSpaceTable (part %d)\n", i
));
2085 if(phd
->freedSpaceBitmap
.extLength
) {
2086 Vcb
->Partitions
[i
].FspaceBitmap
=
2087 phd
->freedSpaceBitmap
.extPosition
;
2088 KdPrint(("freedSpaceBitmap (part %d)\n", i
));
2090 RC
= UDFBuildFreeSpaceBitmap(Vcb
, i
, phd
, 0);
2091 //Vcb->Modified = FALSE;
2092 UDFPreClrModified(Vcb
);
2093 UDFClrModified(Vcb
);
2097 if ((Vcb
->Partitions
[i
].PartitionType
== UDF_VIRTUAL_MAP15
) ||
2098 (Vcb
->Partitions
[i
].PartitionType
== UDF_VIRTUAL_MAP20
)) {
2099 RC
= UDFLoadVAT(Vcb
, i
);
2102 WCacheFlushAll__(&(Vcb
->FastCache
), Vcb
);
2103 WCacheSetMode__(&(Vcb
->FastCache
), WCACHE_MODE_R
);
2104 Vcb
->LastModifiedTrack
= 0;
2111 KdPrint(("Partition (%d) not found in partition map\n", (p
->partitionNumber
) ));
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
));
2118 return STATUS_SUCCESS
;
2119 } // end UDFLoadPartDesc()
2122 process Partition descriptor
2130 PartitionDesc
*p
= (PartitionDesc
*)Buf
;
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
)) {
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
;
2172 if(!strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR02
) ||
2173 !strcmp((int8
*)&(p
->partitionContents
.ident
), PARTITION_CONTENTS_NSR03
))
2175 PPARTITION_HEADER_DESC phd
;
2177 phd
= (PPARTITION_HEADER_DESC
)(p
->partitionContentsUse
);
2179 if(phd
->unallocatedSpaceTable
.extLength
)
2180 KdPrint(("unallocatedSpaceTable (part %d)\n", i
));
2182 if(phd
->unallocatedSpaceBitmap
.extLength
) {
2183 if(Vcb
->Partitions
[i
].UspaceBitmap
==
2184 phd
->unallocatedSpaceBitmap
.extPosition
) {
2185 KdPrint(("Warning: both USpaceBitmaps have same location\n"));
2187 KdPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2188 i
, Vcb
->Partitions
[i
].UspaceBitmap
));
2191 if(phd
->partitionIntegrityTable
.extLength
)
2192 KdPrint(("partitionIntegrityTable (part %d)\n", i
));
2193 if(phd
->freedSpaceTable
.extLength
)
2194 KdPrint(("freedSpaceTable (part %d)\n", i
));
2196 if(phd
->freedSpaceBitmap
.extLength
) {
2197 if(Vcb
->Partitions
[i
].FspaceBitmap
==
2198 phd
->freedSpaceBitmap
.extPosition
) {
2199 KdPrint(("Warning: both FSpaceBitmaps have same location\n"));
2201 KdPrint(("freedSpaceBitmap (part %d)\n", i
));
2203 RC
= UDFVerifyFreeSpaceBitmap(Vcb
, i
, phd
, 0);
2204 //Vcb->Modified = FALSE;
2205 //UDFPreClrModified(Vcb);
2206 //UDFClrModified(Vcb);
2210 if ((Vcb
->Partitions
[i
].PartitionType
== UDF_VIRTUAL_MAP15
) ||
2211 (Vcb
->Partitions
[i
].PartitionType
== UDF_VIRTUAL_MAP20
)) {
2212 /* RC = UDFLoadVAT(Vcb, i);
2215 WCacheFlushAll__(&(Vcb->FastCache), Vcb);
2216 WCacheSetMode__(&(Vcb->FastCache), WCACHE_MODE_R);
2217 Vcb->LastModifiedTrack = 0;*/
2224 KdPrint(("Partition (%d) not found in partition map\n", (p
->partitionNumber
) ));
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
));
2231 return STATUS_SUCCESS
;
2232 } // end UDFVerifyPartDesc()
2235 This routine scans VDS & fills special array with Desc locations
2241 IN uint32 lastblock
,
2242 IN PUDF_VDS_RECORD vds
,
2252 KdPrint(("UDF: Read VDS (%x - %x)\n", block
, lastblock
));
2253 // Read the main descriptor sequence
2254 for (;(!done
&& block
<= lastblock
); block
++)
2256 status
= UDFReadTagged(Vcb
, Buf
, block
, block
, &ident
);
2257 if(!OS_SUCCESS(status
))
2259 UDFRegisterFsStructure(Vcb
, block
, Vcb
->BlockSize
);
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
));
2267 case TID_PRIMARY_VOL_DESC
: // ISO 13346 3/10.1
2268 if(vdsn
>= vds
[VDS_POS_PRIMARY_VOL_DESC
].volDescSeqNum
)
2270 vds
[VDS_POS_PRIMARY_VOL_DESC
].volDescSeqNum
= vdsn
;
2271 vds
[VDS_POS_PRIMARY_VOL_DESC
].block
= block
;
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
)
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
;
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
),
2292 case TID_IMP_USE_VOL_DESC
: // ISO 13346 3/10.4
2293 if(vdsn
>= vds
[VDS_POS_IMP_USE_VOL_DESC
].volDescSeqNum
)
2295 vds
[VDS_POS_IMP_USE_VOL_DESC
].volDescSeqNum
= vdsn
;
2296 vds
[VDS_POS_IMP_USE_VOL_DESC
].block
= block
;
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
;
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
)
2307 vds
[VDS_POS_LOGICAL_VOL_DESC
].volDescSeqNum
= vdsn
;
2308 vds
[VDS_POS_LOGICAL_VOL_DESC
].block
= block
;
2311 case TID_UNALLOC_SPACE_DESC
: // ISO 13346 3/10.8
2312 if(vdsn
>= vds
[VDS_POS_UNALLOC_SPACE_DESC
].volDescSeqNum
)
2314 vds
[VDS_POS_UNALLOC_SPACE_DESC
].volDescSeqNum
= vdsn
;
2315 vds
[VDS_POS_UNALLOC_SPACE_DESC
].block
= block
;
2318 case TID_TERMINATING_DESC
: // ISO 13346 3/10.9
2319 vds
[VDS_POS_TERMINATING_DESC
].block
= block
;
2324 return STATUS_SUCCESS
;
2328 UDFLoadImpUseVolDesc(
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()
2343 UDFLoadUnallocatedSpaceDesc(
2348 KdPrint(("UDF: Unallocated Space Desc:\n"));
2349 // UnallocatedSpaceDesc* usd = (UnallocatedSpaceDesc*)Buf;
2350 return STATUS_SUCCESS
;
2351 } // UDFLoadImpUseVolDesc()
2354 Process a main/reserve volume descriptor sequence.
2358 IN PDEVICE_OBJECT DeviceObject
,
2361 IN uint32 lastblock
,
2362 OUT lb_addr
*fileset
2365 OSSTATUS RC
= STATUS_SUCCESS
;
2366 int8
* Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
2367 UDF_VDS_RECORD vds
[VDS_POS_LENGTH
];
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
)))
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
++)
2385 if(!OS_SUCCESS(RC
= UDFReadTagged(Vcb
, Buf
, vds
[i
].block
, vds
[i
].block
, &ident
)))
2387 UDFRegisterFsStructure(Vcb
, vds
[i
].block
, Vcb
->BlockSize
);
2389 if(i
== VDS_POS_PRIMARY_VOL_DESC
) {
2390 UDFLoadPVolDesc(Vcb
,Buf
);
2391 if(!Vcb
->PVolDescAddr
.block
) {
2392 Vcb
->PVolDescAddr
= vds
[i
];
2394 Vcb
->PVolDescAddr2
= vds
[i
];
2397 if(i
== VDS_POS_LOGICAL_VOL_DESC
) {
2398 RC
= UDFLoadLogicalVol(DeviceObject
,Vcb
, Buf
, fileset
);
2399 if(!OS_SUCCESS(RC
)) try_return(RC
);
2402 if(i
== VDS_POS_IMP_USE_VOL_DESC
) {
2403 UDFLoadImpUseVolDesc(Vcb
, Buf
);
2405 if(i
== VDS_POS_UNALLOC_SPACE_DESC
) {
2406 UDFLoadUnallocatedSpaceDesc(Vcb
, Buf
);
2409 if(i
== VDS_POS_PARTITION_DESC
)
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
++)
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
);
2437 if(i
== VDS_POS_LOGICAL_VOL_DESC
) {
2438 RC
= UDFLoadBogusLogicalVol(DeviceObject
,Vcb
, Buf
, fileset
);
2439 if(!OS_SUCCESS(RC
)) try_return(RC
);
2447 if(Buf
) MyFreePool__(Buf
);
2448 if(Buf2
) MyFreePool__(Buf2
);
2452 } // end UDFProcessSequence()
2455 Verifies a main/reserve volume descriptor sequence.
2459 IN PDEVICE_OBJECT DeviceObject
,
2462 IN uint32 lastblock
,
2463 OUT lb_addr
*fileset
2466 OSSTATUS RC
= STATUS_SUCCESS
;
2467 int8
* Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
2468 UDF_VDS_RECORD vds
[VDS_POS_LENGTH
];
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
)))
2481 for (i
=0; i
<VDS_POS_LENGTH
; i
++)
2485 if(!OS_SUCCESS(RC
= UDFReadTagged(Vcb
, Buf
, vds
[i
].block
, vds
[i
].block
, &ident
)))
2487 UDFRegisterFsStructure(Vcb
, vds
[i
].block
, Vcb
->BlockSize
);
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);
2495 else*/ if(i
== VDS_POS_PARTITION_DESC
)
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
++)
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
;
2525 if(Buf
) MyFreePool__(Buf
);
2526 if(Buf2
) MyFreePool__(Buf2
);
2530 } // end UDFVerifySequence()
2533 remember some useful info about FileSet & RootDir location
2538 IN PFILE_SET_DESC fset
,
2540 OUT lb_addr
*sysstream
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
));
2548 *sysstream
= fset
->streamDirectoryICB
.extLocation
;
2549 KdPrint(("SysStream at block=%x, partition=%d\n",
2550 sysstream
->logicalBlockNum
, sysstream
->partitionReferenceNum
));
2552 // Get current UDF revision
2553 // Get Read-Only flags
2554 UDFReadEntityID_Domain(Vcb
, &(fset
->domainIdent
));
2556 } // end UDFLoadFileset()
2559 UDFIsCachedBadSequence(
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
];
2574 } // end UDFIsCachedBadSequence()
2577 UDFRememberBadSequence(
2584 if(!OS_SUCCESS(UDFIsCachedBadSequence(Vcb
, Lba
)))
2586 // Remenber bad sequence
2587 j
= Vcb
->BadSeqLocIndex
;
2588 Vcb
->BadSeqLocIndex
++;
2589 Vcb
->BadSeqLoc
[j
] = Lba
;
2590 Vcb
->BadSeqStatus
[j
] = RC
;
2591 } // end UDFRememberBadSequence()
2598 IN PDEVICE_OBJECT DeviceObject
,
2600 OUT lb_addr
*fileset
2603 OSSTATUS RC
= STATUS_UNRECOGNIZED_VOLUME
;
2604 OSSTATUS RC2
= STATUS_UNRECOGNIZED_VOLUME
;
2605 AnchorVolDescPtr
*anchor
;
2607 int8
* Buf
= (int8
*)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
2608 uint32 main_s
, main_e
;
2609 uint32 reserve_s
, reserve_e
;
2612 if(!Buf
) return STATUS_INSUFFICIENT_RESOURCES
;
2613 // walk through all available Anchors & load data
2614 for (i
=0; i
<MAX_ANCHOR_LOCATIONS
; i
++)
2616 if(Vcb
->Anchor
[i
] && (OS_SUCCESS(UDFReadTagged(Vcb
, Buf
,
2617 Vcb
->Anchor
[i
], Vcb
->Anchor
[i
] - Vcb
->FirstLBA
, &ident
))))
2619 anchor
= (AnchorVolDescPtr
*)Buf
;
2621 // Locate the main sequence
2622 main_s
= ( anchor
->mainVolDescSeqExt
.extLocation
);
2623 main_e
= ( anchor
->mainVolDescSeqExt
.extLength
);
2624 main_e
= main_e
>> Vcb
->BlockSizeBits
;
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
;
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
);
2643 if(!OS_SUCCESS(RC
)) {
2644 // Remenber bad sequence
2645 UDFRememberBadSequence(Vcb
, main_s
, RC
);
2647 KdPrint(("-----------------------------------\n"));
2648 KdPrint(("UDF: Main sequence failed.\n"));
2649 KdPrint(("UDF: Reserve sequence\n"));
2650 if(Vcb
->LVid
) MyFreePool__(Vcb
->LVid
);
2653 RC2
= UDFIsCachedBadSequence(Vcb
, reserve_s
);
2654 if(OS_SUCCESS(RC2
)) {
2655 RC2
= UDFProcessSequence(DeviceObject
, Vcb
, reserve_s
, reserve_e
, fileset
);
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;
2668 // This is also bad sequence. Remenber it too
2669 UDFRememberBadSequence(Vcb
, reserve_s
, RC
);
2672 // remember these values for umount__
2673 Vcb
->VDS1_Len
= main_e
- main_s
;
2675 /* if(Vcb->LVid) MyFreePool__(Vcb->LVid);
2677 if(OS_SUCCESS(UDFVerifySequence(DeviceObject
, Vcb
, reserve_s
, reserve_e
, fileset
)))
2679 KdPrint(("-----------------------------------\n"));
2680 Vcb
->VDS2_Len
= reserve_e
- reserve_s
;
2681 Vcb
->VDS2
= reserve_s
;
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
;
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
;
2695 case UDF_PART_DAMAGED_RW
:
2697 KdPrint(("UDF: Keep r/w mode for your own risk.\n"));
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
;
2712 if(i
== sizeof(Vcb
->Anchor
)/sizeof(int)) {
2713 KdPrint(("No Anchor block found\n"));
2714 RC
= STATUS_UNRECOGNIZED_VOLUME
;
2717 KdPrint(("Using anchor in block %x\n", Vcb
->Anchor
[i
]));
2722 } // end UDFLoadPartition()
2725 This routine scans FileSet sequence & returns pointer to last valid
2731 IN lb_addr
*Addr
, // Addr for the 1st FileSet
2732 IN OUT PFILE_SET_DESC FileSetDesc
2736 uint32 relLocExt
= Addr
->logicalBlockNum
;
2737 uint32 locExt
= UDFPartLbaToPhys(Vcb
, Addr
);
2739 uint32 relPrevExt
, prevExt
;
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;
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
);
2762 relPrevExt
= relLocExt
;
2763 locExt
= UDFPartLbaToPhys(Vcb
, &(FileSetDesc
->nextExt
.extLocation
));
2765 return STATUS_SUCCESS
;
2766 } // end UDFFindLastFileSet()
2769 This routine reads all sparing tables & stores them in contiguos memory
2773 UDFLoadSparingTable(
2775 IN PSPARABLE_PARTITION_MAP PartMap
2778 PSPARING_MAP RelocMap
;
2779 PSPARING_MAP NewRelocMap
;
2781 uint32 i
=0, BC
, BC2
;
2782 PSPARING_TABLE SparTable
;
2783 uint32 TabSize
, NewSize
;
2785 uint32 SparTableLoc
;
2786 #ifdef UDF_TRACK_FS_STRUCTURES
2788 #endif //UDF_TRACK_FS_STRUCTURES
2792 Vcb
->SparingCountFree
= -1;
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
);
2812 // do some init to load first part of Sparing Table
2813 RelocMap
= (PSPARING_MAP
)MyAllocatePool__(NonPagedPool
, RELOC_MAP_GRAN
);
2815 MyFreePool__(SparTable
);
2816 return STATUS_INSUFFICIENT_RESOURCES
;
2818 TabSize
= RELOC_MAP_GRAN
;
2819 Vcb
->SparingBlockSize
= PartMap
->packetLength
;
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",
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
)) {
2837 UDFRegisterFsStructure(Vcb
, SparTableLoc
, Vcb
->BlockSize
);
2838 BC2
= ((sizeof(SPARING_TABLE
) +
2839 SparTable
->reallocationTableLen
*sizeof(SparingEntry
) +
2841 >> Vcb
->BlockSizeBits
);
2843 KdPrint((" sizeSparingTable @%x too long: %x > %x\n",
2844 SparTableLoc
, BC2
, BC
2848 status
= UDFReadSectors(Vcb
, FALSE
, SparTableLoc
,
2849 BC2
, FALSE
, (int8
*)SparTable
, &ReadBytes
);
2850 UDFRegisterFsStructure(Vcb
, SparTableLoc
, BC2
<<Vcb
->BlockSizeBits
);
2852 if(!OS_SUCCESS(status
)) {
2853 KdPrint((" Error reading sizeSparingTable @%x (%x)\n",
2858 // process sparing table
2859 NewSize
= sizeof(SparingEntry
)*SparTable
->reallocationTableLen
;
2860 TabSize
= MyReallocPool__((int8
*)RelocMap
, TabSize
, (int8
**)&RelocMap
, TabSize
+NewSize
);
2862 MyFreePool__(SparTable
);
2863 return STATUS_INSUFFICIENT_RESOURCES
;
2866 #ifdef UDF_TRACK_FS_STRUCTURES
2867 for(j
=0; j
<SparTable
->reallocationTableLen
; j
++) {
2868 UDFRegisterFsStructure(Vcb
, ((SparingEntry
*)(SparTable
+1))[j
].mappedLocation
, Vcb
->WriteBlockSize
);
2870 #endif //UDF_TRACK_FS_STRUCTURES
2872 Vcb
->SparingTableLoc
[Vcb
->SparingTableCount
] = SparTableLoc
;
2873 Vcb
->SparingTableCount
++;
2875 NewRelocMap
= (PSPARING_MAP
)(SparTable
+1);
2876 for(n
=0; n
<SparTable
->reallocationTableLen
; n
++) {
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
));
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
));
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
;
2907 RtlCopyMemory((int8*)(RelocMap+Vcb->SparingCount),
2908 (int8*)(SparTable+1), NewSize);
2909 Vcb->SparingCount += NewSize/sizeof(SPARING_ENTRY);
2911 if(Vcb
->SparingTableCount
>= MAX_SPARING_TABLE_LOCATIONS
) {
2912 KdPrint((" too many Sparing Tables\n"));
2917 Vcb
->SparingTable
= RelocMap
;
2918 MyFreePool__(SparTable
);
2919 return STATUS_SUCCESS
;
2920 } // end UDFLoadSparingTable()
2923 This routine checks if buffer is ZERO-filled
2936 uint32 len
= Length
;
2945 __asm jne
short not_all_zeros
2957 uint32
* tmp
= (uint32
*)Buf
;
2960 for(i
=0; i
<Length
/4; i
++) {
2961 if(tmp
[i
]) return FALSE
;
2967 } // end UDFCheckZeroBuf()
2970 check if this is an UDF-formatted disk
2973 UDFGetDiskInfoAndVerify(
2974 IN PDEVICE_OBJECT DeviceObject
, // the target device object
2975 IN PVCB Vcb
// Volume control block from this DevObj
2978 OSSTATUS RC
= STATUS_UNRECOGNIZED_VOLUME
;
2981 PFILE_SET_DESC FileSetDesc
= NULL
;
2986 KdPrint(("UDFGetDiskInfoAndVerify\n"));
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"));
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
;
3005 Vcb
->NSRDesc
= NSRDesc
;
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
);
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
;
3020 try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
3023 RC
= UDFLoadPartition(DeviceObject
,Vcb
,&fileset
);
3024 if(!OS_SUCCESS(RC
)) {
3025 if(RC
== STATUS_UNRECOGNIZED_VOLUME
) {
3026 KdPrint(("UDFGetDiskInfoAndVerify: check NSR presence\n"));
3032 FileSetDesc
= (PFILE_SET_DESC
)MyAllocatePool__(NonPagedPool
,Vcb
->BlockSize
);
3033 if(!FileSetDesc
) try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
3035 RC
= UDFFindLastFileSet(Vcb
,&fileset
,FileSetDesc
);
3036 if(!OS_SUCCESS(RC
)) try_return(RC
);
3038 UDFLoadFileset(Vcb
,FileSetDesc
, &(Vcb
->RootLbAddr
), &(Vcb
->SysStreamLbAddr
));
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
);
3046 if(FileSetDesc
) MyFreePool__(FileSetDesc
);
3047 if(Buf
) MyFreePool__(Buf
);
3052 } // end UDFGetDiskInfoAndVerify()