TianoCore EDK2 master
Loading...
Searching...
No Matches
FatLiteAccess.c
Go to the documentation of this file.
1
10#include "FatLitePeim.h"
11
33 IN PEI_FAT_PRIVATE_DATA *PrivateData,
34 IN OUT PEI_FAT_VOLUME *Volume
35 )
36{
37 EFI_STATUS Status;
40 UINT32 Sectors;
41 UINT32 SectorsPerFat;
42 UINT32 RootDirSectors;
43 UINT64 FatLba;
44 UINT64 RootLba;
45 UINT64 FirstClusterLba;
46
47 //
48 // Read in the BPB
49 //
50 Status = FatReadDisk (
51 PrivateData,
52 Volume->BlockDeviceNo,
53 0,
55 &BpbEx
56 );
57 if (EFI_ERROR (Status)) {
58 return Status;
59 }
60
61 CopyMem (
62 (UINT8 *)(&Bpb),
63 (UINT8 *)(&BpbEx),
64 sizeof (PEI_FAT_BOOT_SECTOR)
65 );
66
67 Volume->FatType = FatUnknown;
68
69 Sectors = Bpb.Sectors;
70 if (Sectors == 0) {
71 Sectors = Bpb.LargeSectors;
72 }
73
74 SectorsPerFat = Bpb.SectorsPerFat;
75 if (SectorsPerFat == 0) {
76 SectorsPerFat = BpbEx.LargeSectorsPerFat;
77 Volume->FatType = Fat32;
78 }
79
80 //
81 // Filter out those not a FAT
82 //
83 if ((Bpb.Ia32Jump[0] != 0xe9) && (Bpb.Ia32Jump[0] != 0xeb) && (Bpb.Ia32Jump[0] != 0x49)) {
84 return EFI_NOT_FOUND;
85 }
86
87 if ((Bpb.ReservedSectors == 0) || (Bpb.NoFats == 0) || (Sectors == 0)) {
88 return EFI_NOT_FOUND;
89 }
90
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)
99 )
100 {
101 return EFI_NOT_FOUND;
102 }
103
104 if ((Volume->FatType == Fat32) && ((SectorsPerFat == 0) || (BpbEx.FsVersion != 0))) {
105 return EFI_NOT_FOUND;
106 }
107
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) &&
116 //
117 // FujitsuFMR
118 //
119 (Bpb.Media != 0x00) &&
120 (Bpb.Media != 0x01) &&
121 (Bpb.Media != 0xfa)
122 )
123 {
124 return EFI_NOT_FOUND;
125 }
126
127 if ((Volume->FatType != Fat32) && (Bpb.RootEntries == 0)) {
128 return EFI_NOT_FOUND;
129 }
130
131 //
132 // If this is fat32, refuse to mount mirror-disabled volumes
133 //
134 if ((Volume->FatType == Fat32) && ((BpbEx.ExtendedFlags & 0x80) != 0)) {
135 return EFI_NOT_FOUND;
136 }
137
138 //
139 // Fill in the volume structure fields
140 // (Sectors & SectorsPerFat is computed earlier already)
141 //
142 Volume->ClusterSize = Bpb.SectorSize * Bpb.SectorsPerCluster;
143 Volume->RootEntries = Bpb.RootEntries;
144 Volume->SectorSize = Bpb.SectorSize;
145
146 RootDirSectors = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (Volume->SectorSize - 1)) / Volume->SectorSize;
147
148 FatLba = Bpb.ReservedSectors;
149 RootLba = Bpb.NoFats * SectorsPerFat + FatLba;
150 FirstClusterLba = RootLba + RootDirSectors;
151
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;
158
159 //
160 // If this is not a fat32, determine if it's a fat16 or fat12
161 //
162 if (Volume->FatType != Fat32) {
163 if (Volume->MaxCluster >= 65525) {
164 return EFI_NOT_FOUND;
165 }
166
167 Volume->FatType = Volume->MaxCluster < 4085 ? Fat12 : Fat16;
168 }
169
170 return EFI_SUCCESS;
171}
172
188 IN PEI_FAT_PRIVATE_DATA *PrivateData,
189 IN PEI_FAT_VOLUME *Volume,
190 IN UINT32 Cluster,
191 OUT UINT32 *NextCluster
192 )
193{
194 EFI_STATUS Status;
195 UINT64 FatEntryPos;
196 UINT32 Dummy;
197
198 *NextCluster = 0;
199
200 if (Volume->FatType == Fat32) {
201 FatEntryPos = Volume->FatPos + MultU64x32 (4, Cluster);
202
203 Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 4, NextCluster);
204 *NextCluster &= 0x0fffffff;
205
206 //
207 // Pad high bits for our FAT_CLUSTER_... macro definitions to work
208 //
209 if ((*NextCluster) >= 0x0ffffff7) {
210 *NextCluster |= (-1 &~0xf);
211 }
212 } else if (Volume->FatType == Fat16) {
213 FatEntryPos = Volume->FatPos + MultU64x32 (2, Cluster);
214
215 Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);
216
217 //
218 // Pad high bits for our FAT_CLUSTER_... macro definitions to work
219 //
220 if ((*NextCluster) >= 0xfff7) {
221 *NextCluster |= (-1 &~0xf);
222 }
223 } else {
224 FatEntryPos = Volume->FatPos + DivU64x32Remainder (MultU64x32 (3, Cluster), 2, &Dummy);
225
226 Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);
227
228 if ((Cluster & 0x01) != 0) {
229 *NextCluster = (*NextCluster) >> 4;
230 } else {
231 *NextCluster = (*NextCluster) & 0x0fff;
232 }
233
234 //
235 // Pad high bits for our FAT_CLUSTER_... macro definitions to work
236 //
237 if ((*NextCluster) >= 0x0ff7) {
238 *NextCluster |= (-1 &~0xf);
239 }
240 }
241
242 if (EFI_ERROR (Status)) {
243 return EFI_DEVICE_ERROR;
244 }
245
246 return EFI_SUCCESS;
247}
248
264 IN PEI_FAT_PRIVATE_DATA *PrivateData,
265 IN PEI_FAT_FILE *File,
266 IN UINT32 Pos
267 )
268{
269 EFI_STATUS Status;
270 UINT32 AlignedPos;
271 UINT32 Offset;
272 UINT32 Cluster;
273 UINT32 PrevCluster;
274
275 if (File->IsFixedRootDir) {
276 if (Pos >= MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos) {
277 return EFI_INVALID_PARAMETER;
278 }
279
280 File->CurrentPos += Pos;
281 File->StraightReadAmount = (UINT32)(MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos);
282 } else {
283 DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
284 AlignedPos = (UINT32)File->CurrentPos - (UINT32)Offset;
285
286 while
287 (
288 !FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster) &&
289 AlignedPos + File->Volume->ClusterSize <= File->CurrentPos + Pos
290 )
291 {
292 AlignedPos += File->Volume->ClusterSize;
293 Status = FatGetNextCluster (
294 PrivateData,
295 File->Volume,
296 File->CurrentCluster,
297 &File->CurrentCluster
298 );
299 if (EFI_ERROR (Status)) {
300 return EFI_DEVICE_ERROR;
301 }
302 }
303
304 if (FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster)) {
305 return EFI_INVALID_PARAMETER;
306 }
307
308 File->CurrentPos += Pos;
309 //
310 // Calculate the amount of consecutive cluster occupied by the file.
311 // FatReadFile() will use it to read these blocks once.
312 //
313 File->StraightReadAmount = 0;
314 Cluster = File->CurrentCluster;
315 while (!FAT_CLUSTER_FUNCTIONAL (Cluster)) {
316 File->StraightReadAmount += File->Volume->ClusterSize;
317 PrevCluster = Cluster;
318 Status = FatGetNextCluster (PrivateData, File->Volume, Cluster, &Cluster);
319 if (EFI_ERROR (Status)) {
320 return EFI_DEVICE_ERROR;
321 }
322
323 if (Cluster != PrevCluster + 1) {
324 break;
325 }
326 }
327
328 DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
329 File->StraightReadAmount -= (UINT32)Offset;
330 }
331
332 return EFI_SUCCESS;
333}
334
350 IN PEI_FAT_PRIVATE_DATA *PrivateData,
351 IN PEI_FAT_FILE *File,
352 IN UINTN Size,
353 OUT VOID *Buffer
354 )
355{
356 EFI_STATUS Status;
357 CHAR8 *BufferPtr;
358 UINT32 Offset;
359 UINT64 PhysicalAddr;
360 UINTN Amount;
361
362 BufferPtr = Buffer;
363
364 if (File->IsFixedRootDir) {
365 //
366 // This is the fixed root dir in FAT12 and FAT16
367 //
368 if (File->CurrentPos + Size > File->Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) {
369 return EFI_INVALID_PARAMETER;
370 }
371
372 Status = FatReadDisk (
373 PrivateData,
374 File->Volume->BlockDeviceNo,
375 File->Volume->RootDirPos + File->CurrentPos,
376 Size,
377 Buffer
378 );
379 File->CurrentPos += (UINT32)Size;
380 return Status;
381 } else {
382 if ((File->Attributes & FAT_ATTR_DIRECTORY) == 0) {
383 Size = Size < (File->FileSize - File->CurrentPos) ? Size : (File->FileSize - File->CurrentPos);
384 }
385
386 //
387 // This is a normal cluster based file
388 //
389 while (Size != 0) {
390 DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);
391 PhysicalAddr = File->Volume->FirstClusterPos + MultU64x32 (File->Volume->ClusterSize, File->CurrentCluster - 2);
392
393 Amount = File->StraightReadAmount;
394 Amount = Size > Amount ? Amount : Size;
395 Status = FatReadDisk (
396 PrivateData,
397 File->Volume->BlockDeviceNo,
398 PhysicalAddr + Offset,
399 Amount,
400 BufferPtr
401 );
402 if (EFI_ERROR (Status)) {
403 return EFI_DEVICE_ERROR;
404 }
405
406 //
407 // Advance the file's current pos and current cluster
408 //
409 FatSetFilePos (PrivateData, File, (UINT32)Amount);
410
411 BufferPtr += Amount;
412 Size -= Amount;
413 }
414
415 return EFI_SUCCESS;
416 }
417}
418
438 IN PEI_FAT_PRIVATE_DATA *PrivateData,
439 IN PEI_FAT_FILE *ParentDir,
440 OUT PEI_FAT_FILE *SubFile
441 )
442{
443 EFI_STATUS Status;
444 FAT_DIRECTORY_ENTRY DirEntry;
445 CHAR16 *Pos;
446 CHAR16 BaseName[9];
447 CHAR16 Ext[4];
448
449 ZeroMem ((UINT8 *)SubFile, sizeof (PEI_FAT_FILE));
450
451 //
452 // Pick a valid directory entry
453 //
454 while (1) {
455 //
456 // Read one entry
457 //
458 Status = FatReadFile (PrivateData, ParentDir, 32, &DirEntry);
459 if (EFI_ERROR (Status)) {
460 return EFI_DEVICE_ERROR;
461 }
462
463 //
464 // We only search for *FILE* in root directory
465 // Long file name entry is *NOT* supported
466 //
467 if (((DirEntry.Attributes & FAT_ATTR_DIRECTORY) == FAT_ATTR_DIRECTORY) || (DirEntry.Attributes == FAT_ATTR_LFN)) {
468 continue;
469 }
470
471 //
472 // if this is a terminator dir entry, just return EFI_NOT_FOUND
473 //
474 if (DirEntry.FileName[0] == EMPTY_ENTRY_MARK) {
475 return EFI_NOT_FOUND;
476 }
477
478 //
479 // If this not an invalid entry neither an empty entry, this is what we want.
480 // otherwise we will start a new loop to continue to find something meaningful
481 //
482 if ((UINT8)DirEntry.FileName[0] != DELETE_ENTRY_MARK) {
483 break;
484 }
485 }
486
487 //
488 // fill in the output parameter
489 //
490 EngFatToStr (8, DirEntry.FileName, BaseName);
491 EngFatToStr (3, DirEntry.FileName + 8, Ext);
492
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));
496
497 if (Ext[0] != 0) {
498 Pos += StrLen (BaseName);
499 *Pos = '.';
500 Pos++;
501 CopyMem ((UINT8 *)Pos, (UINT8 *)Ext, 2 * (StrLen (Ext) + 1));
502 }
503
504 SubFile->Attributes = DirEntry.Attributes;
505 SubFile->CurrentCluster = DirEntry.FileCluster;
506 if (ParentDir->Volume->FatType == Fat32) {
507 SubFile->CurrentCluster |= DirEntry.FileClusterHigh << 16;
508 }
509
510 SubFile->CurrentPos = 0;
511 SubFile->FileSize = DirEntry.FileSize;
512 SubFile->StartingCluster = SubFile->CurrentCluster;
513 SubFile->Volume = ParentDir->Volume;
514
515 //
516 // in Pei phase, time parameters do not need to be filled for minimum use.
517 //
518 return Status;
519}
UINT64 UINTN
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI DivU64x32Remainder(IN UINT64 Dividend, IN UINT32 Divisor, OUT UINT32 *Remainder OPTIONAL)
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
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)
Definition: SetMemWrapper.c:38
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)
Definition: FatLiteAccess.c:32
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)
Definition: FatLiteLib.c:307
EFI_STATUS FatReadDisk(IN PEI_FAT_PRIVATE_DATA *PrivateData, IN UINTN BlockDeviceNo, IN UINT64 StartingAddress, IN UINTN Size, OUT VOID *Buffer)
Definition: FatLiteLib.c:221
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112