2 * PROJECT: ReactOS FAT file system driver
3 * LICENSE: GNU GPLv3 as published by the Free Software Foundation
4 * FILE: drivers/filesystems/fastfat/fat.c
5 * PURPOSE: FAT support routines
6 * PROGRAMMERS: Aleksey Bragin <aleksey@reactos.org>
9 /* INCLUDES *****************************************************************/
14 /* PROTOTYPES ***************************************************************/
18 FatValidBpb(IN PBIOS_PARAMETER_BLOCK Bpb
);
20 /* VARIABLES ****************************************************************/
24 FatValidBpb(IN PBIOS_PARAMETER_BLOCK Bpb
)
26 return (FatValidBytesPerSector(Bpb
->BytesPerSector
)
27 && FatValidSectorsPerCluster(Bpb
->SectorsPerCluster
)
28 && Bpb
->ReservedSectors
> 0
30 && (Bpb
->Sectors
> 0 || Bpb
->LargeSectors
> 0)
31 && (Bpb
->SectorsPerFat
> 0
32 || (Bpb
->LargeSectorsPerFat
> 0 && Bpb
->FsVersion
== 0))
33 && (Bpb
->Media
== 0xf0
40 || Bpb
->Media
== 0xff)
41 && (Bpb
->SectorsPerFat
== 0 || Bpb
->RootEntries
> 0)
42 && (Bpb
->SectorsPerFat
> 0 || !Bpb
->MirrorDisabled
));
46 * Determines the index of the set bit.
49 * Number having a single bit set.
52 * Index of the set bit.
61 - ((Number
>> 1) & 033333333333)
62 - ((Number
>> 2) & 011111111111);
63 return (((Temp
+ (Temp
>> 3)) & 030707070707) % 63);
68 FatiInitializeVcb(PVCB Vcb
)
70 ULONG ClustersCapacity
;
72 /* Various characteristics needed for navigation in FAT */
73 if ((Vcb
->Sectors
= Vcb
->Bpb
.Sectors
) == 0)
74 Vcb
->Sectors
= Vcb
->Bpb
.LargeSectors
;
75 if ((Vcb
->SectorsPerFat
= Vcb
->Bpb
.SectorsPerFat
) == 0)
76 Vcb
->SectorsPerFat
= Vcb
->Bpb
.LargeSectorsPerFat
;
77 Vcb
->RootDirent
= Vcb
->Bpb
.ReservedSectors
+ Vcb
->Bpb
.Fats
* Vcb
->SectorsPerFat
;
78 Vcb
->RootDirentSectors
= BytesToSectors(Vcb
,
79 Vcb
->Bpb
.RootEntries
* sizeof(DIR_ENTRY
));
80 Vcb
->DataArea
= Vcb
->RootDirent
+ Vcb
->RootDirentSectors
;
81 Vcb
->Clusters
= (Vcb
->Sectors
- Vcb
->Bpb
.ReservedSectors
82 - Vcb
->Bpb
.Fats
* Vcb
->SectorsPerFat
83 - Vcb
->RootDirentSectors
) / Vcb
->Bpb
.SectorsPerCluster
;
84 if (Vcb
->BytesPerClusterLog
< 4087)
86 Vcb
->IndexDepth
= 0x0c;
87 //Vcb->Methods = Fat12Methods;
91 Vcb
->IndexDepth
= 0x10;
92 //Vcb->Methods = Fat16Methods;
94 /* Large Sectors are used for FAT32 */
95 if (Vcb
->Bpb
.Sectors
== 0) {
96 Vcb
->IndexDepth
= 0x20;
97 //Vcb->Methods = Fat32Methods;
99 ClustersCapacity
= (SectorsToBytes(Vcb
, Vcb
->Sectors
) * 0x8 / Vcb
->IndexDepth
) - 1;
100 if (Vcb
->Clusters
> ClustersCapacity
)
101 Vcb
->Clusters
= ClustersCapacity
;
102 Vcb
->BytesPerCluster
= SectorsToBytes(Vcb
, Vcb
->Bpb
.SectorsPerCluster
);
103 Vcb
->BytesPerClusterLog
= FatPowerOfTwo(Vcb
->BytesPerCluster
);
104 Vcb
->BeyondLastClusterInFat
= ((LONGLONG
) Vcb
->Clusters
) * Vcb
->IndexDepth
/ 0x8;
106 /* Update real volume size with the real value. */
107 Vcb
->Header
.FileSize
.QuadPart
=
108 Vcb
->Header
.AllocationSize
.QuadPart
= SectorsToBytes(Vcb
, Vcb
->Sectors
);
113 FatInitializeVcb(IN PFAT_IRP_CONTEXT IrpContext
,
115 IN PDEVICE_OBJECT TargetDeviceObject
,
121 LARGE_INTEGER Offset
;
123 RtlZeroMemory(Vcb
, sizeof(*Vcb
));
125 /* Initialize list head, so that it will
126 * not fail in cleanup.
128 InitializeListHead(&Vcb
->VcbLinks
);
130 /* Setup FCB Header */
131 Vcb
->Header
.NodeTypeCode
= FAT_NTC_VCB
;
132 Vcb
->Header
.NodeByteSize
= sizeof(*Vcb
);
134 /* Setup Vcb fields */
135 Vcb
->TargetDeviceObject
= TargetDeviceObject
;
136 ObReferenceObject(TargetDeviceObject
);
139 /* Setup FCB Header */
140 ExInitializeFastMutex(&Vcb
->HeaderMutex
);
141 FsRtlSetupAdvancedHeader(&Vcb
->Header
, &Vcb
->HeaderMutex
);
143 /* Create Volume File Object */
144 Vcb
->StreamFileObject
= IoCreateStreamFileObject(NULL
,
145 Vcb
->TargetDeviceObject
);
147 /* We have to setup all FCB fields needed for CC */
148 Vcb
->StreamFileObject
->FsContext
= Vcb
;
149 Vcb
->StreamFileObject
->SectionObjectPointer
= &Vcb
->SectionObjectPointers
;
151 /* At least full boot sector should be available */
152 //Vcb->Header.FileSize.QuadPart = sizeof(PACKED_BOOT_SECTOR);
153 //Vcb->Header.AllocationSize.QuadPart = sizeof(PACKED_BOOT_SECTOR);
154 Vcb
->Header
.ValidDataLength
.HighPart
= MAXLONG
;
155 Vcb
->Header
.ValidDataLength
.LowPart
= MAXULONG
;
157 Vcb
->Header
.AllocationSize
.QuadPart
= Int32x32To64(5*1024, 1024*1024); //HACK: 5 Gb
158 Vcb
->Header
.FileSize
.QuadPart
= Vcb
->Header
.AllocationSize
.QuadPart
;
160 /* Set VCB to a good condition */
161 Vcb
->Condition
= VcbGood
;
163 /* Initialize VCB's resource */
164 ExInitializeResourceLite(&Vcb
->Resource
);
167 CcInitializeCacheMap(Vcb
->StreamFileObject
,
168 (PCC_FILE_SIZES
)&Vcb
->Header
.AllocationSize
,
170 &FatGlobalData
.CacheMgrNoopCallbacks
,
173 /* Read boot sector */
177 /* Note: Volume Read path does not require
178 * any of the parameters set further
181 if (CcMapData(Vcb
->StreamFileObject
,
183 sizeof(PACKED_BOOT_SECTOR
),
188 PPACKED_BOOT_SECTOR BootSector
= (PPACKED_BOOT_SECTOR
) Buffer
;
189 FatUnpackBios(&Vcb
->Bpb
, &BootSector
->PackedBpb
);
190 if (!(FatBootSectorJumpValid(BootSector
->Jump
) &&
191 FatValidBpb(&Vcb
->Bpb
)))
193 Status
= STATUS_UNRECOGNIZED_VOLUME
;
195 CopyUchar4(&Vcb
->Vpb
->SerialNumber
, BootSector
->Id
);
200 Status
= STATUS_UNRECOGNIZED_VOLUME
;
201 goto FatInitializeVcbCleanup
;
204 /* Set up notifications */
205 FsRtlNotifyInitializeSync(&Vcb
->NotifySync
);
206 InitializeListHead(&Vcb
->NotifyList
);
208 /* Call helper function */
209 FatiInitializeVcb(Vcb
);
211 /* Add this Vcb to global Vcb list */
212 (VOID
)FatAcquireExclusiveGlobal(IrpContext
);
213 InsertTailList(&FatGlobalData
.VcbListHead
, &Vcb
->VcbLinks
);
214 FatReleaseGlobal(IrpContext
);
216 return STATUS_SUCCESS
;
218 FatInitializeVcbCleanup
:
220 /* Unwind the routine actions */
221 FatUninitializeVcb(Vcb
);
227 FatUninitializeVcb(IN PVCB Vcb
)
229 LARGE_INTEGER ZeroSize
;
231 ZeroSize
.QuadPart
= 0LL;
233 /* Close volume file */
234 if (Vcb
->StreamFileObject
!= NULL
)
236 /* Uninitialize CC. */
237 CcUninitializeCacheMap(Vcb
->StreamFileObject
, &ZeroSize
, NULL
);
238 ObDereferenceObject(Vcb
->StreamFileObject
);
239 Vcb
->StreamFileObject
= NULL
;
242 /* Free notifications stuff */
243 FsRtlNotifyUninitializeSync(&Vcb
->NotifySync
);
245 /* Unlink from global Vcb list. */
246 RemoveEntryList(&Vcb
->VcbLinks
);
248 /* Release Target Device */
249 ObDereferenceObject(Vcb
->TargetDeviceObject
);
250 Vcb
->TargetDeviceObject
= NULL
;