42 UINT32 RootDirSectors;
45 UINT64 FirstClusterLba;
52 Volume->BlockDeviceNo,
57 if (EFI_ERROR (Status)) {
67 Volume->FatType = FatUnknown;
69 Sectors = Bpb.Sectors;
71 Sectors = Bpb.LargeSectors;
74 SectorsPerFat = Bpb.SectorsPerFat;
75 if (SectorsPerFat == 0) {
76 SectorsPerFat = BpbEx.LargeSectorsPerFat;
77 Volume->FatType = Fat32;
83 if ((Bpb.Ia32Jump[0] != 0xe9) && (Bpb.Ia32Jump[0] != 0xeb) && (Bpb.Ia32Jump[0] != 0x49)) {
87 if ((Bpb.ReservedSectors == 0) || (Bpb.NoFats == 0) || (Sectors == 0)) {
91 if ((Bpb.SectorsPerCluster != 1) &&
92 (Bpb.SectorsPerCluster != 2) &&
93 (Bpb.SectorsPerCluster != 4) &&
94 (Bpb.SectorsPerCluster != 8) &&
95 (Bpb.SectorsPerCluster != 16) &&
96 (Bpb.SectorsPerCluster != 32) &&
97 (Bpb.SectorsPerCluster != 64) &&
98 (Bpb.SectorsPerCluster != 128)
101 return EFI_NOT_FOUND;
104 if ((Volume->FatType == Fat32) && ((SectorsPerFat == 0) || (BpbEx.FsVersion != 0))) {
105 return EFI_NOT_FOUND;
108 if ((Bpb.Media != 0xf0) &&
109 (Bpb.Media != 0xf8) &&
110 (Bpb.Media != 0xf9) &&
111 (Bpb.Media != 0xfb) &&
112 (Bpb.Media != 0xfc) &&
113 (Bpb.Media != 0xfd) &&
114 (Bpb.Media != 0xfe) &&
115 (Bpb.Media != 0xff) &&
119 (Bpb.Media != 0x00) &&
120 (Bpb.Media != 0x01) &&
124 return EFI_NOT_FOUND;
127 if ((Volume->FatType != Fat32) && (Bpb.RootEntries == 0)) {
128 return EFI_NOT_FOUND;
134 if ((Volume->FatType == Fat32) && ((BpbEx.ExtendedFlags & 0x80) != 0)) {
135 return EFI_NOT_FOUND;
142 Volume->ClusterSize = Bpb.SectorSize * Bpb.SectorsPerCluster;
143 Volume->RootEntries = Bpb.RootEntries;
144 Volume->SectorSize = Bpb.SectorSize;
146 RootDirSectors = ((Volume->RootEntries *
sizeof (
FAT_DIRECTORY_ENTRY)) + (Volume->SectorSize - 1)) / Volume->SectorSize;
148 FatLba = Bpb.ReservedSectors;
149 RootLba = Bpb.NoFats * SectorsPerFat + FatLba;
150 FirstClusterLba = RootLba + RootDirSectors;
152 Volume->VolumeSize =
MultU64x32 (Sectors, Volume->SectorSize);
153 Volume->FatPos =
MultU64x32 (FatLba, Volume->SectorSize);
154 Volume->RootDirPos =
MultU64x32 (RootLba, Volume->SectorSize);
155 Volume->FirstClusterPos =
MultU64x32 (FirstClusterLba, Volume->SectorSize);
156 Volume->MaxCluster = (UINT32)(Sectors - FirstClusterLba) / Bpb.SectorsPerCluster;
157 Volume->RootDirCluster = BpbEx.RootDirFirstCluster;
162 if (Volume->FatType != Fat32) {
163 if (Volume->MaxCluster >= 65525) {
164 return EFI_NOT_FOUND;
167 Volume->FatType = Volume->MaxCluster < 4085 ? Fat12 : Fat16;
191 OUT UINT32 *NextCluster
200 if (Volume->FatType == Fat32) {
201 FatEntryPos = Volume->FatPos +
MultU64x32 (4, Cluster);
203 Status =
FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 4, NextCluster);
204 *NextCluster &= 0x0fffffff;
209 if ((*NextCluster) >= 0x0ffffff7) {
210 *NextCluster |= (-1 &~0xf);
212 }
else if (Volume->FatType == Fat16) {
213 FatEntryPos = Volume->FatPos +
MultU64x32 (2, Cluster);
215 Status =
FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);
220 if ((*NextCluster) >= 0xfff7) {
221 *NextCluster |= (-1 &~0xf);
226 Status =
FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);
228 if ((Cluster & 0x01) != 0) {
229 *NextCluster = (*NextCluster) >> 4;
231 *NextCluster = (*NextCluster) & 0x0fff;
237 if ((*NextCluster) >= 0x0ff7) {
238 *NextCluster |= (-1 &~0xf);
242 if (EFI_ERROR (Status)) {
243 return EFI_DEVICE_ERROR;
275 if (File->IsFixedRootDir) {
276 if (Pos >=
MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos) {
277 return EFI_INVALID_PARAMETER;
280 File->CurrentPos += Pos;
281 File->StraightReadAmount = (UINT32)(
MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos);
284 AlignedPos = (UINT32)File->CurrentPos - (UINT32)Offset;
288 !FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster) &&
289 AlignedPos + File->Volume->ClusterSize <= File->CurrentPos + Pos
292 AlignedPos += File->Volume->ClusterSize;
296 File->CurrentCluster,
297 &File->CurrentCluster
299 if (EFI_ERROR (Status)) {
300 return EFI_DEVICE_ERROR;
304 if (FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster)) {
305 return EFI_INVALID_PARAMETER;
308 File->CurrentPos += Pos;
313 File->StraightReadAmount = 0;
314 Cluster = File->CurrentCluster;
315 while (!FAT_CLUSTER_FUNCTIONAL (Cluster)) {
316 File->StraightReadAmount += File->Volume->ClusterSize;
317 PrevCluster = Cluster;
319 if (EFI_ERROR (Status)) {
320 return EFI_DEVICE_ERROR;
323 if (Cluster != PrevCluster + 1) {
329 File->StraightReadAmount -= (UINT32)Offset;
364 if (File->IsFixedRootDir) {
369 return EFI_INVALID_PARAMETER;
374 File->Volume->BlockDeviceNo,
375 File->Volume->RootDirPos + File->CurrentPos,
379 File->CurrentPos += (UINT32)Size;
382 if ((File->Attributes & FAT_ATTR_DIRECTORY) == 0) {
383 Size = Size < (File->FileSize - File->CurrentPos) ? Size : (File->FileSize - File->CurrentPos);
391 PhysicalAddr = File->Volume->FirstClusterPos +
MultU64x32 (File->Volume->ClusterSize, File->CurrentCluster - 2);
393 Amount = File->StraightReadAmount;
394 Amount = Size > Amount ? Amount : Size;
397 File->Volume->BlockDeviceNo,
398 PhysicalAddr + Offset,
402 if (EFI_ERROR (Status)) {
403 return EFI_DEVICE_ERROR;
458 Status =
FatReadFile (PrivateData, ParentDir, 32, &DirEntry);
459 if (EFI_ERROR (Status)) {
460 return EFI_DEVICE_ERROR;
467 if (((DirEntry.Attributes & FAT_ATTR_DIRECTORY) == FAT_ATTR_DIRECTORY) || (DirEntry.Attributes == FAT_ATTR_LFN)) {
474 if (DirEntry.FileName[0] == EMPTY_ENTRY_MARK) {
475 return EFI_NOT_FOUND;
482 if ((UINT8)DirEntry.FileName[0] != DELETE_ENTRY_MARK) {
493 Pos = (UINT16 *)SubFile->FileName;
494 SetMem ((UINT8 *)Pos, FAT_MAX_FILE_NAME_LENGTH, 0);
495 CopyMem ((UINT8 *)Pos, (UINT8 *)BaseName, 2 * (
StrLen (BaseName) + 1));
501 CopyMem ((UINT8 *)Pos, (UINT8 *)Ext, 2 * (
StrLen (Ext) + 1));
504 SubFile->Attributes = DirEntry.Attributes;
505 SubFile->CurrentCluster = DirEntry.FileCluster;
506 if (ParentDir->Volume->FatType == Fat32) {
507 SubFile->CurrentCluster |= DirEntry.FileClusterHigh << 16;
510 SubFile->CurrentPos = 0;
511 SubFile->FileSize = DirEntry.FileSize;
512 SubFile->StartingCluster = SubFile->CurrentCluster;
513 SubFile->Volume = ParentDir->Volume;
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
UINT64 EFIAPI DivU64x32Remainder(IN UINT64 Dividend, IN UINT32 Divisor, OUT UINT32 *Remainder OPTIONAL)
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS FatReadNextDirectoryEntry(IN PEI_FAT_PRIVATE_DATA *PrivateData, IN PEI_FAT_FILE *ParentDir, OUT PEI_FAT_FILE *SubFile)
EFI_STATUS FatGetBpbInfo(IN PEI_FAT_PRIVATE_DATA *PrivateData, IN OUT PEI_FAT_VOLUME *Volume)
EFI_STATUS FatSetFilePos(IN PEI_FAT_PRIVATE_DATA *PrivateData, IN PEI_FAT_FILE *File, IN UINT32 Pos)
EFI_STATUS FatReadFile(IN PEI_FAT_PRIVATE_DATA *PrivateData, IN PEI_FAT_FILE *File, IN UINTN Size, OUT VOID *Buffer)
EFI_STATUS FatGetNextCluster(IN PEI_FAT_PRIVATE_DATA *PrivateData, IN PEI_FAT_VOLUME *Volume, IN UINT32 Cluster, OUT UINT32 *NextCluster)
VOID EngFatToStr(IN UINTN FatSize, IN CHAR8 *Fat, OUT CHAR16 *Str)
EFI_STATUS FatReadDisk(IN PEI_FAT_PRIVATE_DATA *PrivateData, IN UINTN BlockDeviceNo, IN UINT64 StartingAddress, IN UINTN Size, OUT VOID *Buffer)