]>
Commit | Line | Data |
---|---|---|
2f4dfa84 JJ |
1 | /** @file\r |
2 | FAT file system access routines for FAT recovery PEIM\r | |
3 | \r | |
e38f26a2 | 4 | Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r |
2f4dfa84 | 5 | \r |
eb6cb4ce | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
2f4dfa84 JJ |
7 | \r |
8 | **/\r | |
9 | \r | |
10 | #include "FatLitePeim.h"\r | |
11 | \r | |
2f4dfa84 JJ |
12 | /**\r |
13 | Check if there is a valid FAT in the corresponding Block device\r | |
14 | of the volume and if yes, fill in the relevant fields for the\r | |
15 | volume structure. Note there should be a valid Block device number\r | |
16 | already set.\r | |
17 | \r | |
e38f26a2 LG |
18 | @param PrivateData Global memory map for accessing global\r |
19 | variables.\r | |
20 | @param Volume On input, the BlockDeviceNumber field of the\r | |
21 | Volume should be a valid value. On successful\r | |
22 | output, all fields except the VolumeNumber\r | |
23 | field is initialized.\r | |
2f4dfa84 | 24 | \r |
e38f26a2 LG |
25 | @retval EFI_SUCCESS A FAT is found and the volume structure is\r |
26 | initialized.\r | |
27 | @retval EFI_NOT_FOUND There is no FAT on the corresponding device.\r | |
2f4dfa84 JJ |
28 | @retval EFI_DEVICE_ERROR There is something error while accessing device.\r |
29 | \r | |
30 | **/\r | |
31 | EFI_STATUS\r | |
32 | FatGetBpbInfo (\r | |
33 | IN PEI_FAT_PRIVATE_DATA *PrivateData,\r | |
34 | IN OUT PEI_FAT_VOLUME *Volume\r | |
35 | )\r | |
36 | {\r | |
37 | EFI_STATUS Status;\r | |
38 | PEI_FAT_BOOT_SECTOR Bpb;\r | |
39 | PEI_FAT_BOOT_SECTOR_EX BpbEx;\r | |
40 | UINT32 Sectors;\r | |
41 | UINT32 SectorsPerFat;\r | |
42 | UINT32 RootDirSectors;\r | |
43 | UINT64 FatLba;\r | |
44 | UINT64 RootLba;\r | |
45 | UINT64 FirstClusterLba;\r | |
46 | \r | |
47 | //\r | |
48 | // Read in the BPB\r | |
49 | //\r | |
50 | Status = FatReadDisk (\r | |
bcdcc416 MK |
51 | PrivateData,\r |
52 | Volume->BlockDeviceNo,\r | |
53 | 0,\r | |
54 | sizeof (PEI_FAT_BOOT_SECTOR_EX),\r | |
55 | &BpbEx\r | |
56 | );\r | |
2f4dfa84 JJ |
57 | if (EFI_ERROR (Status)) {\r |
58 | return Status;\r | |
59 | }\r | |
60 | \r | |
61 | CopyMem (\r | |
bcdcc416 MK |
62 | (UINT8 *)(&Bpb),\r |
63 | (UINT8 *)(&BpbEx),\r | |
2f4dfa84 JJ |
64 | sizeof (PEI_FAT_BOOT_SECTOR)\r |
65 | );\r | |
66 | \r | |
67 | Volume->FatType = FatUnknown;\r | |
68 | \r | |
bcdcc416 | 69 | Sectors = Bpb.Sectors;\r |
2f4dfa84 JJ |
70 | if (Sectors == 0) {\r |
71 | Sectors = Bpb.LargeSectors;\r | |
72 | }\r | |
73 | \r | |
74 | SectorsPerFat = Bpb.SectorsPerFat;\r | |
75 | if (SectorsPerFat == 0) {\r | |
76 | SectorsPerFat = BpbEx.LargeSectorsPerFat;\r | |
77 | Volume->FatType = Fat32;\r | |
78 | }\r | |
bcdcc416 | 79 | \r |
2f4dfa84 JJ |
80 | //\r |
81 | // Filter out those not a FAT\r | |
82 | //\r | |
bcdcc416 | 83 | if ((Bpb.Ia32Jump[0] != 0xe9) && (Bpb.Ia32Jump[0] != 0xeb) && (Bpb.Ia32Jump[0] != 0x49)) {\r |
2f4dfa84 JJ |
84 | return EFI_NOT_FOUND;\r |
85 | }\r | |
86 | \r | |
bcdcc416 | 87 | if ((Bpb.ReservedSectors == 0) || (Bpb.NoFats == 0) || (Sectors == 0)) {\r |
2f4dfa84 JJ |
88 | return EFI_NOT_FOUND;\r |
89 | }\r | |
90 | \r | |
bcdcc416 MK |
91 | if ((Bpb.SectorsPerCluster != 1) &&\r |
92 | (Bpb.SectorsPerCluster != 2) &&\r | |
93 | (Bpb.SectorsPerCluster != 4) &&\r | |
94 | (Bpb.SectorsPerCluster != 8) &&\r | |
95 | (Bpb.SectorsPerCluster != 16) &&\r | |
96 | (Bpb.SectorsPerCluster != 32) &&\r | |
97 | (Bpb.SectorsPerCluster != 64) &&\r | |
98 | (Bpb.SectorsPerCluster != 128)\r | |
99 | )\r | |
100 | {\r | |
2f4dfa84 JJ |
101 | return EFI_NOT_FOUND;\r |
102 | }\r | |
103 | \r | |
bcdcc416 | 104 | if ((Volume->FatType == Fat32) && ((SectorsPerFat == 0) || (BpbEx.FsVersion != 0))) {\r |
2f4dfa84 JJ |
105 | return EFI_NOT_FOUND;\r |
106 | }\r | |
107 | \r | |
bcdcc416 MK |
108 | if ((Bpb.Media != 0xf0) &&\r |
109 | (Bpb.Media != 0xf8) &&\r | |
110 | (Bpb.Media != 0xf9) &&\r | |
111 | (Bpb.Media != 0xfb) &&\r | |
112 | (Bpb.Media != 0xfc) &&\r | |
113 | (Bpb.Media != 0xfd) &&\r | |
114 | (Bpb.Media != 0xfe) &&\r | |
115 | (Bpb.Media != 0xff) &&\r | |
2f4dfa84 JJ |
116 | //\r |
117 | // FujitsuFMR\r | |
118 | //\r | |
bcdcc416 MK |
119 | (Bpb.Media != 0x00) &&\r |
120 | (Bpb.Media != 0x01) &&\r | |
121 | (Bpb.Media != 0xfa)\r | |
122 | )\r | |
123 | {\r | |
2f4dfa84 JJ |
124 | return EFI_NOT_FOUND;\r |
125 | }\r | |
126 | \r | |
bcdcc416 | 127 | if ((Volume->FatType != Fat32) && (Bpb.RootEntries == 0)) {\r |
2f4dfa84 JJ |
128 | return EFI_NOT_FOUND;\r |
129 | }\r | |
bcdcc416 | 130 | \r |
2f4dfa84 JJ |
131 | //\r |
132 | // If this is fat32, refuse to mount mirror-disabled volumes\r | |
133 | //\r | |
bcdcc416 | 134 | if ((Volume->FatType == Fat32) && ((BpbEx.ExtendedFlags & 0x80) != 0)) {\r |
2f4dfa84 JJ |
135 | return EFI_NOT_FOUND;\r |
136 | }\r | |
bcdcc416 | 137 | \r |
2f4dfa84 JJ |
138 | //\r |
139 | // Fill in the volume structure fields\r | |
140 | // (Sectors & SectorsPerFat is computed earlier already)\r | |
141 | //\r | |
142 | Volume->ClusterSize = Bpb.SectorSize * Bpb.SectorsPerCluster;\r | |
143 | Volume->RootEntries = Bpb.RootEntries;\r | |
144 | Volume->SectorSize = Bpb.SectorSize;\r | |
145 | \r | |
146 | RootDirSectors = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (Volume->SectorSize - 1)) / Volume->SectorSize;\r | |
147 | \r | |
bcdcc416 MK |
148 | FatLba = Bpb.ReservedSectors;\r |
149 | RootLba = Bpb.NoFats * SectorsPerFat + FatLba;\r | |
150 | FirstClusterLba = RootLba + RootDirSectors;\r | |
2f4dfa84 JJ |
151 | \r |
152 | Volume->VolumeSize = MultU64x32 (Sectors, Volume->SectorSize);\r | |
153 | Volume->FatPos = MultU64x32 (FatLba, Volume->SectorSize);\r | |
154 | Volume->RootDirPos = MultU64x32 (RootLba, Volume->SectorSize);\r | |
155 | Volume->FirstClusterPos = MultU64x32 (FirstClusterLba, Volume->SectorSize);\r | |
bcdcc416 | 156 | Volume->MaxCluster = (UINT32)(Sectors - FirstClusterLba) / Bpb.SectorsPerCluster;\r |
2f4dfa84 JJ |
157 | Volume->RootDirCluster = BpbEx.RootDirFirstCluster;\r |
158 | \r | |
159 | //\r | |
160 | // If this is not a fat32, determine if it's a fat16 or fat12\r | |
161 | //\r | |
162 | if (Volume->FatType != Fat32) {\r | |
2f4dfa84 JJ |
163 | if (Volume->MaxCluster >= 65525) {\r |
164 | return EFI_NOT_FOUND;\r | |
165 | }\r | |
166 | \r | |
167 | Volume->FatType = Volume->MaxCluster < 4085 ? Fat12 : Fat16;\r | |
168 | }\r | |
169 | \r | |
170 | return EFI_SUCCESS;\r | |
171 | }\r | |
172 | \r | |
2f4dfa84 JJ |
173 | /**\r |
174 | Gets the next cluster in the cluster chain\r | |
175 | \r | |
e38f26a2 LG |
176 | @param PrivateData Global memory map for accessing global variables\r |
177 | @param Volume The volume\r | |
178 | @param Cluster The cluster\r | |
179 | @param NextCluster The cluster number of the next cluster\r | |
2f4dfa84 | 180 | \r |
e38f26a2 LG |
181 | @retval EFI_SUCCESS The address is got\r |
182 | @retval EFI_INVALID_PARAMETER ClusterNo exceeds the MaxCluster of the volume.\r | |
2f4dfa84 JJ |
183 | @retval EFI_DEVICE_ERROR Read disk error\r |
184 | \r | |
185 | **/\r | |
186 | EFI_STATUS\r | |
187 | FatGetNextCluster (\r | |
188 | IN PEI_FAT_PRIVATE_DATA *PrivateData,\r | |
189 | IN PEI_FAT_VOLUME *Volume,\r | |
190 | IN UINT32 Cluster,\r | |
191 | OUT UINT32 *NextCluster\r | |
192 | )\r | |
193 | {\r | |
194 | EFI_STATUS Status;\r | |
195 | UINT64 FatEntryPos;\r | |
196 | UINT32 Dummy;\r | |
197 | \r | |
198 | *NextCluster = 0;\r | |
199 | \r | |
200 | if (Volume->FatType == Fat32) {\r | |
201 | FatEntryPos = Volume->FatPos + MultU64x32 (4, Cluster);\r | |
202 | \r | |
bcdcc416 | 203 | Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 4, NextCluster);\r |
2f4dfa84 JJ |
204 | *NextCluster &= 0x0fffffff;\r |
205 | \r | |
206 | //\r | |
207 | // Pad high bits for our FAT_CLUSTER_... macro definitions to work\r | |
208 | //\r | |
209 | if ((*NextCluster) >= 0x0ffffff7) {\r | |
210 | *NextCluster |= (-1 &~0xf);\r | |
211 | }\r | |
2f4dfa84 JJ |
212 | } else if (Volume->FatType == Fat16) {\r |
213 | FatEntryPos = Volume->FatPos + MultU64x32 (2, Cluster);\r | |
214 | \r | |
bcdcc416 | 215 | Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);\r |
2f4dfa84 JJ |
216 | \r |
217 | //\r | |
218 | // Pad high bits for our FAT_CLUSTER_... macro definitions to work\r | |
219 | //\r | |
220 | if ((*NextCluster) >= 0xfff7) {\r | |
221 | *NextCluster |= (-1 &~0xf);\r | |
222 | }\r | |
2f4dfa84 JJ |
223 | } else {\r |
224 | FatEntryPos = Volume->FatPos + DivU64x32Remainder (MultU64x32 (3, Cluster), 2, &Dummy);\r | |
225 | \r | |
bcdcc416 | 226 | Status = FatReadDisk (PrivateData, Volume->BlockDeviceNo, FatEntryPos, 2, NextCluster);\r |
2f4dfa84 JJ |
227 | \r |
228 | if ((Cluster & 0x01) != 0) {\r | |
229 | *NextCluster = (*NextCluster) >> 4;\r | |
230 | } else {\r | |
231 | *NextCluster = (*NextCluster) & 0x0fff;\r | |
232 | }\r | |
bcdcc416 | 233 | \r |
2f4dfa84 JJ |
234 | //\r |
235 | // Pad high bits for our FAT_CLUSTER_... macro definitions to work\r | |
236 | //\r | |
237 | if ((*NextCluster) >= 0x0ff7) {\r | |
238 | *NextCluster |= (-1 &~0xf);\r | |
239 | }\r | |
240 | }\r | |
241 | \r | |
242 | if (EFI_ERROR (Status)) {\r | |
243 | return EFI_DEVICE_ERROR;\r | |
244 | }\r | |
245 | \r | |
246 | return EFI_SUCCESS;\r | |
2f4dfa84 JJ |
247 | }\r |
248 | \r | |
2f4dfa84 JJ |
249 | /**\r |
250 | Set a file's CurrentPos and CurrentCluster, then compute StraightReadAmount.\r | |
251 | \r | |
e38f26a2 LG |
252 | @param PrivateData the global memory map\r |
253 | @param File the file\r | |
254 | @param Pos the Position which is offset from the file's\r | |
255 | CurrentPos\r | |
2f4dfa84 | 256 | \r |
e38f26a2 LG |
257 | @retval EFI_SUCCESS Success.\r |
258 | @retval EFI_INVALID_PARAMETER Pos is beyond file's size.\r | |
2f4dfa84 JJ |
259 | @retval EFI_DEVICE_ERROR Something error while accessing media.\r |
260 | \r | |
261 | **/\r | |
262 | EFI_STATUS\r | |
263 | FatSetFilePos (\r | |
264 | IN PEI_FAT_PRIVATE_DATA *PrivateData,\r | |
265 | IN PEI_FAT_FILE *File,\r | |
266 | IN UINT32 Pos\r | |
267 | )\r | |
268 | {\r | |
269 | EFI_STATUS Status;\r | |
270 | UINT32 AlignedPos;\r | |
271 | UINT32 Offset;\r | |
272 | UINT32 Cluster;\r | |
273 | UINT32 PrevCluster;\r | |
274 | \r | |
275 | if (File->IsFixedRootDir) {\r | |
2f4dfa84 JJ |
276 | if (Pos >= MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos) {\r |
277 | return EFI_INVALID_PARAMETER;\r | |
278 | }\r | |
279 | \r | |
bcdcc416 MK |
280 | File->CurrentPos += Pos;\r |
281 | File->StraightReadAmount = (UINT32)(MultU64x32 (File->Volume->RootEntries, 32) - File->CurrentPos);\r | |
2f4dfa84 | 282 | } else {\r |
2f4dfa84 | 283 | DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);\r |
bcdcc416 | 284 | AlignedPos = (UINT32)File->CurrentPos - (UINT32)Offset;\r |
2f4dfa84 JJ |
285 | \r |
286 | while\r | |
287 | (\r | |
bcdcc416 MK |
288 | !FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster) &&\r |
289 | AlignedPos + File->Volume->ClusterSize <= File->CurrentPos + Pos\r | |
290 | )\r | |
291 | {\r | |
2f4dfa84 | 292 | AlignedPos += File->Volume->ClusterSize;\r |
bcdcc416 MK |
293 | Status = FatGetNextCluster (\r |
294 | PrivateData,\r | |
295 | File->Volume,\r | |
296 | File->CurrentCluster,\r | |
297 | &File->CurrentCluster\r | |
298 | );\r | |
2f4dfa84 JJ |
299 | if (EFI_ERROR (Status)) {\r |
300 | return EFI_DEVICE_ERROR;\r | |
301 | }\r | |
302 | }\r | |
303 | \r | |
304 | if (FAT_CLUSTER_FUNCTIONAL (File->CurrentCluster)) {\r | |
305 | return EFI_INVALID_PARAMETER;\r | |
306 | }\r | |
307 | \r | |
308 | File->CurrentPos += Pos;\r | |
1d951a30 FT |
309 | //\r |
310 | // Calculate the amount of consecutive cluster occupied by the file.\r | |
311 | // FatReadFile() will use it to read these blocks once.\r | |
312 | //\r | |
bcdcc416 MK |
313 | File->StraightReadAmount = 0;\r |
314 | Cluster = File->CurrentCluster;\r | |
2f4dfa84 JJ |
315 | while (!FAT_CLUSTER_FUNCTIONAL (Cluster)) {\r |
316 | File->StraightReadAmount += File->Volume->ClusterSize;\r | |
bcdcc416 MK |
317 | PrevCluster = Cluster;\r |
318 | Status = FatGetNextCluster (PrivateData, File->Volume, Cluster, &Cluster);\r | |
2f4dfa84 JJ |
319 | if (EFI_ERROR (Status)) {\r |
320 | return EFI_DEVICE_ERROR;\r | |
321 | }\r | |
322 | \r | |
323 | if (Cluster != PrevCluster + 1) {\r | |
324 | break;\r | |
325 | }\r | |
326 | }\r | |
327 | \r | |
328 | DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);\r | |
bcdcc416 | 329 | File->StraightReadAmount -= (UINT32)Offset;\r |
2f4dfa84 JJ |
330 | }\r |
331 | \r | |
332 | return EFI_SUCCESS;\r | |
333 | }\r | |
334 | \r | |
2f4dfa84 JJ |
335 | /**\r |
336 | Reads file data. Updates the file's CurrentPos.\r | |
337 | \r | |
e38f26a2 LG |
338 | @param PrivateData Global memory map for accessing global variables\r |
339 | @param File The file.\r | |
340 | @param Size The amount of data to read.\r | |
341 | @param Buffer The buffer storing the data.\r | |
2f4dfa84 | 342 | \r |
e38f26a2 LG |
343 | @retval EFI_SUCCESS The data is read.\r |
344 | @retval EFI_INVALID_PARAMETER File is invalid.\r | |
2f4dfa84 JJ |
345 | @retval EFI_DEVICE_ERROR Something error while accessing media.\r |
346 | \r | |
347 | **/\r | |
348 | EFI_STATUS\r | |
349 | FatReadFile (\r | |
350 | IN PEI_FAT_PRIVATE_DATA *PrivateData,\r | |
351 | IN PEI_FAT_FILE *File,\r | |
352 | IN UINTN Size,\r | |
353 | OUT VOID *Buffer\r | |
354 | )\r | |
355 | {\r | |
356 | EFI_STATUS Status;\r | |
357 | CHAR8 *BufferPtr;\r | |
358 | UINT32 Offset;\r | |
359 | UINT64 PhysicalAddr;\r | |
360 | UINTN Amount;\r | |
361 | \r | |
362 | BufferPtr = Buffer;\r | |
363 | \r | |
364 | if (File->IsFixedRootDir) {\r | |
365 | //\r | |
366 | // This is the fixed root dir in FAT12 and FAT16\r | |
367 | //\r | |
368 | if (File->CurrentPos + Size > File->Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) {\r | |
369 | return EFI_INVALID_PARAMETER;\r | |
370 | }\r | |
371 | \r | |
372 | Status = FatReadDisk (\r | |
bcdcc416 MK |
373 | PrivateData,\r |
374 | File->Volume->BlockDeviceNo,\r | |
375 | File->Volume->RootDirPos + File->CurrentPos,\r | |
376 | Size,\r | |
377 | Buffer\r | |
378 | );\r | |
379 | File->CurrentPos += (UINT32)Size;\r | |
2f4dfa84 | 380 | return Status;\r |
2f4dfa84 | 381 | } else {\r |
2f4dfa84 | 382 | if ((File->Attributes & FAT_ATTR_DIRECTORY) == 0) {\r |
64b25f5d | 383 | Size = Size < (File->FileSize - File->CurrentPos) ? Size : (File->FileSize - File->CurrentPos);\r |
2f4dfa84 | 384 | }\r |
bcdcc416 | 385 | \r |
2f4dfa84 JJ |
386 | //\r |
387 | // This is a normal cluster based file\r | |
388 | //\r | |
389 | while (Size != 0) {\r | |
390 | DivU64x32Remainder (File->CurrentPos, File->Volume->ClusterSize, &Offset);\r | |
bcdcc416 | 391 | PhysicalAddr = File->Volume->FirstClusterPos + MultU64x32 (File->Volume->ClusterSize, File->CurrentCluster - 2);\r |
2f4dfa84 | 392 | \r |
bcdcc416 MK |
393 | Amount = File->StraightReadAmount;\r |
394 | Amount = Size > Amount ? Amount : Size;\r | |
2f4dfa84 | 395 | Status = FatReadDisk (\r |
bcdcc416 MK |
396 | PrivateData,\r |
397 | File->Volume->BlockDeviceNo,\r | |
398 | PhysicalAddr + Offset,\r | |
399 | Amount,\r | |
400 | BufferPtr\r | |
401 | );\r | |
2f4dfa84 JJ |
402 | if (EFI_ERROR (Status)) {\r |
403 | return EFI_DEVICE_ERROR;\r | |
404 | }\r | |
bcdcc416 | 405 | \r |
2f4dfa84 JJ |
406 | //\r |
407 | // Advance the file's current pos and current cluster\r | |
408 | //\r | |
bcdcc416 | 409 | FatSetFilePos (PrivateData, File, (UINT32)Amount);\r |
2f4dfa84 JJ |
410 | \r |
411 | BufferPtr += Amount;\r | |
bcdcc416 | 412 | Size -= Amount;\r |
2f4dfa84 JJ |
413 | }\r |
414 | \r | |
415 | return EFI_SUCCESS;\r | |
416 | }\r | |
417 | }\r | |
418 | \r | |
2f4dfa84 JJ |
419 | /**\r |
420 | This function reads the next item in the parent directory and\r | |
421 | initializes the output parameter SubFile (CurrentPos is initialized to 0).\r | |
422 | The function updates the CurrentPos of the parent dir to after the item read.\r | |
423 | If no more items were found, the function returns EFI_NOT_FOUND.\r | |
424 | \r | |
e38f26a2 LG |
425 | @param PrivateData Global memory map for accessing global variables\r |
426 | @param ParentDir The parent directory.\r | |
427 | @param SubFile The File structure containing the sub file that\r | |
428 | is caught.\r | |
2f4dfa84 | 429 | \r |
e38f26a2 LG |
430 | @retval EFI_SUCCESS The next sub file is obtained.\r |
431 | @retval EFI_INVALID_PARAMETER The ParentDir is not a directory.\r | |
432 | @retval EFI_NOT_FOUND No more sub file exists.\r | |
2f4dfa84 JJ |
433 | @retval EFI_DEVICE_ERROR Something error while accessing media.\r |
434 | \r | |
435 | **/\r | |
436 | EFI_STATUS\r | |
437 | FatReadNextDirectoryEntry (\r | |
438 | IN PEI_FAT_PRIVATE_DATA *PrivateData,\r | |
439 | IN PEI_FAT_FILE *ParentDir,\r | |
440 | OUT PEI_FAT_FILE *SubFile\r | |
441 | )\r | |
442 | {\r | |
bcdcc416 MK |
443 | EFI_STATUS Status;\r |
444 | FAT_DIRECTORY_ENTRY DirEntry;\r | |
445 | CHAR16 *Pos;\r | |
446 | CHAR16 BaseName[9];\r | |
447 | CHAR16 Ext[4];\r | |
2f4dfa84 | 448 | \r |
bcdcc416 | 449 | ZeroMem ((UINT8 *)SubFile, sizeof (PEI_FAT_FILE));\r |
2f4dfa84 JJ |
450 | \r |
451 | //\r | |
452 | // Pick a valid directory entry\r | |
453 | //\r | |
454 | while (1) {\r | |
455 | //\r | |
456 | // Read one entry\r | |
457 | //\r | |
458 | Status = FatReadFile (PrivateData, ParentDir, 32, &DirEntry);\r | |
459 | if (EFI_ERROR (Status)) {\r | |
460 | return EFI_DEVICE_ERROR;\r | |
461 | }\r | |
bcdcc416 | 462 | \r |
2f4dfa84 JJ |
463 | //\r |
464 | // We only search for *FILE* in root directory\r | |
465 | // Long file name entry is *NOT* supported\r | |
466 | //\r | |
3ba5368d | 467 | if (((DirEntry.Attributes & FAT_ATTR_DIRECTORY) == FAT_ATTR_DIRECTORY) || (DirEntry.Attributes == FAT_ATTR_LFN)) {\r |
2f4dfa84 JJ |
468 | continue;\r |
469 | }\r | |
bcdcc416 | 470 | \r |
2f4dfa84 JJ |
471 | //\r |
472 | // if this is a terminator dir entry, just return EFI_NOT_FOUND\r | |
473 | //\r | |
474 | if (DirEntry.FileName[0] == EMPTY_ENTRY_MARK) {\r | |
475 | return EFI_NOT_FOUND;\r | |
476 | }\r | |
bcdcc416 | 477 | \r |
2f4dfa84 JJ |
478 | //\r |
479 | // If this not an invalid entry neither an empty entry, this is what we want.\r | |
480 | // otherwise we will start a new loop to continue to find something meaningful\r | |
481 | //\r | |
bcdcc416 | 482 | if ((UINT8)DirEntry.FileName[0] != DELETE_ENTRY_MARK) {\r |
2f4dfa84 JJ |
483 | break;\r |
484 | }\r | |
485 | }\r | |
bcdcc416 | 486 | \r |
2f4dfa84 JJ |
487 | //\r |
488 | // fill in the output parameter\r | |
489 | //\r | |
490 | EngFatToStr (8, DirEntry.FileName, BaseName);\r | |
491 | EngFatToStr (3, DirEntry.FileName + 8, Ext);\r | |
492 | \r | |
bcdcc416 MK |
493 | Pos = (UINT16 *)SubFile->FileName;\r |
494 | SetMem ((UINT8 *)Pos, FAT_MAX_FILE_NAME_LENGTH, 0);\r | |
495 | CopyMem ((UINT8 *)Pos, (UINT8 *)BaseName, 2 * (StrLen (BaseName) + 1));\r | |
2f4dfa84 JJ |
496 | \r |
497 | if (Ext[0] != 0) {\r | |
498 | Pos += StrLen (BaseName);\r | |
499 | *Pos = '.';\r | |
500 | Pos++;\r | |
bcdcc416 | 501 | CopyMem ((UINT8 *)Pos, (UINT8 *)Ext, 2 * (StrLen (Ext) + 1));\r |
2f4dfa84 JJ |
502 | }\r |
503 | \r | |
504 | SubFile->Attributes = DirEntry.Attributes;\r | |
505 | SubFile->CurrentCluster = DirEntry.FileCluster;\r | |
506 | if (ParentDir->Volume->FatType == Fat32) {\r | |
507 | SubFile->CurrentCluster |= DirEntry.FileClusterHigh << 16;\r | |
508 | }\r | |
509 | \r | |
bcdcc416 MK |
510 | SubFile->CurrentPos = 0;\r |
511 | SubFile->FileSize = DirEntry.FileSize;\r | |
512 | SubFile->StartingCluster = SubFile->CurrentCluster;\r | |
513 | SubFile->Volume = ParentDir->Volume;\r | |
2f4dfa84 | 514 | \r |
2f4dfa84 JJ |
515 | //\r |
516 | // in Pei phase, time parameters do not need to be filled for minimum use.\r | |
517 | //\r | |
518 | return Status;\r | |
519 | }\r |