]> git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/FatPei/FatLiteApi.c
0bf6ddae6a4f9202c54014151274d3bc64044e8a
[mirror_edk2.git] / FatPkg / FatPei / FatLiteApi.c
1 /** @file
2 FAT recovery PEIM entry point, Ppi Functions and FAT Api functions.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "FatLitePeim.h"
11
12 PEI_FAT_PRIVATE_DATA *mPrivateData = NULL;
13
14 /**
15 BlockIo installation nofication function. Find out all the current BlockIO
16 PPIs in the system and add them into private data. Assume there is
17
18 @param PeiServices General purpose services available to every
19 PEIM.
20 @param NotifyDescriptor The typedef structure of the notification
21 descriptor. Not used in this function.
22 @param Ppi The typedef structure of the PPI descriptor.
23 Not used in this function.
24
25 @retval EFI_SUCCESS The function completed successfully.
26
27 **/
28 EFI_STATUS
29 EFIAPI
30 BlockIoNotifyEntry (
31 IN EFI_PEI_SERVICES **PeiServices,
32 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
33 IN VOID *Ppi
34 );
35
36
37 /**
38 Discover all the block I/O devices to find the FAT volume.
39
40 @param PrivateData Global memory map for accessing global
41 variables.
42 @param BlockIo2 Boolean to show whether using BlockIo2 or BlockIo
43
44 @retval EFI_SUCCESS The function completed successfully.
45
46 **/
47 EFI_STATUS
48 UpdateBlocksAndVolumes (
49 IN OUT PEI_FAT_PRIVATE_DATA *PrivateData,
50 IN BOOLEAN BlockIo2
51 )
52 {
53 EFI_STATUS Status;
54 EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;
55 UINTN BlockIoPpiInstance;
56 EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;
57 EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi;
58 UINTN NumberBlockDevices;
59 UINTN Index;
60 EFI_PEI_BLOCK_IO_MEDIA Media;
61 EFI_PEI_BLOCK_IO2_MEDIA Media2;
62 PEI_FAT_VOLUME Volume;
63 EFI_PEI_SERVICES **PeiServices;
64
65 PeiServices = (EFI_PEI_SERVICES **) GetPeiServicesTablePointer ();
66 BlockIo2Ppi = NULL;
67 BlockIoPpi = NULL;
68 //
69 // Clean up caches
70 //
71 for (Index = 0; Index < PEI_FAT_CACHE_SIZE; Index++) {
72 PrivateData->CacheBuffer[Index].Valid = FALSE;
73 }
74
75 PrivateData->BlockDeviceCount = 0;
76
77 //
78 // Find out all Block Io Ppi instances within the system
79 // Assuming all device Block Io Peims are dispatched already
80 //
81 for (BlockIoPpiInstance = 0; BlockIoPpiInstance < PEI_FAT_MAX_BLOCK_IO_PPI; BlockIoPpiInstance++) {
82 if (BlockIo2) {
83 Status = PeiServicesLocatePpi (
84 &gEfiPeiVirtualBlockIo2PpiGuid,
85 BlockIoPpiInstance,
86 &TempPpiDescriptor,
87 (VOID **) &BlockIo2Ppi
88 );
89 } else {
90 Status = PeiServicesLocatePpi (
91 &gEfiPeiVirtualBlockIoPpiGuid,
92 BlockIoPpiInstance,
93 &TempPpiDescriptor,
94 (VOID **) &BlockIoPpi
95 );
96 }
97 if (EFI_ERROR (Status)) {
98 //
99 // Done with all Block Io Ppis
100 //
101 break;
102 }
103
104 if (BlockIo2) {
105 Status = BlockIo2Ppi->GetNumberOfBlockDevices (
106 PeiServices,
107 BlockIo2Ppi,
108 &NumberBlockDevices
109 );
110 } else {
111 Status = BlockIoPpi->GetNumberOfBlockDevices (
112 PeiServices,
113 BlockIoPpi,
114 &NumberBlockDevices
115 );
116 }
117 if (EFI_ERROR (Status)) {
118 continue;
119 }
120
121 for (Index = 1; Index <= NumberBlockDevices && PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE; Index++) {
122
123 if (BlockIo2) {
124 Status = BlockIo2Ppi->GetBlockDeviceMediaInfo (
125 PeiServices,
126 BlockIo2Ppi,
127 Index,
128 &Media2
129 );
130 if (EFI_ERROR (Status) || !Media2.MediaPresent) {
131 continue;
132 }
133 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].BlockIo2 = BlockIo2Ppi;
134 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].InterfaceType = Media2.InterfaceType;
135 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].LastBlock = Media2.LastBlock;
136 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].BlockSize = Media2.BlockSize;
137 } else {
138 Status = BlockIoPpi->GetBlockDeviceMediaInfo (
139 PeiServices,
140 BlockIoPpi,
141 Index,
142 &Media
143 );
144 if (EFI_ERROR (Status) || !Media.MediaPresent) {
145 continue;
146 }
147 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].BlockIo = BlockIoPpi;
148 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].DevType = Media.DeviceType;
149 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].LastBlock = Media.LastBlock;
150 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].BlockSize = (UINT32) Media.BlockSize;
151 }
152
153 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].IoAlign = 0;
154 //
155 // Not used here
156 //
157 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].Logical = FALSE;
158 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].PartitionChecked = FALSE;
159
160 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].PhysicalDevNo = (UINT8) Index;
161 PrivateData->BlockDeviceCount++;
162 }
163 }
164 //
165 // Find out all logical devices
166 //
167 FatFindPartitions (PrivateData);
168
169 //
170 // Build up file system volume array
171 //
172 PrivateData->VolumeCount = 0;
173 for (Index = 0; Index < PrivateData->BlockDeviceCount; Index++) {
174 Volume.BlockDeviceNo = Index;
175 Status = FatGetBpbInfo (PrivateData, &Volume);
176 if (Status == EFI_SUCCESS) {
177 //
178 // Add the detected volume to the volume array
179 //
180 CopyMem (
181 (UINT8 *) &(PrivateData->Volume[PrivateData->VolumeCount]),
182 (UINT8 *) &Volume,
183 sizeof (PEI_FAT_VOLUME)
184 );
185 PrivateData->VolumeCount += 1;
186 if (PrivateData->VolumeCount >= PEI_FAT_MAX_VOLUME) {
187 break;
188 }
189 }
190 }
191
192 return EFI_SUCCESS;
193 }
194
195
196 /**
197 BlockIo installation notification function. Find out all the current BlockIO
198 PPIs in the system and add them into private data. Assume there is
199
200 @param PeiServices General purpose services available to every
201 PEIM.
202 @param NotifyDescriptor The typedef structure of the notification
203 descriptor. Not used in this function.
204 @param Ppi The typedef structure of the PPI descriptor.
205 Not used in this function.
206
207 @retval EFI_SUCCESS The function completed successfully.
208
209 **/
210 EFI_STATUS
211 EFIAPI
212 BlockIoNotifyEntry (
213 IN EFI_PEI_SERVICES **PeiServices,
214 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
215 IN VOID *Ppi
216 )
217 {
218 if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiVirtualBlockIo2PpiGuid)) {
219 UpdateBlocksAndVolumes (mPrivateData, TRUE);
220 } else {
221 UpdateBlocksAndVolumes (mPrivateData, FALSE);
222 }
223 return EFI_SUCCESS;
224 }
225
226
227 /**
228 Installs the Device Recovery Module PPI, Initialize BlockIo Ppi
229 installation notification
230
231 @param FileHandle Handle of the file being invoked. Type
232 EFI_PEI_FILE_HANDLE is defined in
233 FfsFindNextFile().
234 @param PeiServices Describes the list of possible PEI Services.
235
236 @retval EFI_SUCCESS The entry point was executed successfully.
237 @retval EFI_OUT_OF_RESOURCES There is no enough memory to complete the
238 operations.
239
240 **/
241 EFI_STATUS
242 EFIAPI
243 FatPeimEntry (
244 IN EFI_PEI_FILE_HANDLE FileHandle,
245 IN CONST EFI_PEI_SERVICES **PeiServices
246 )
247 {
248 EFI_STATUS Status;
249 EFI_PHYSICAL_ADDRESS Address;
250 PEI_FAT_PRIVATE_DATA *PrivateData;
251
252 Status = PeiServicesRegisterForShadow (FileHandle);
253 if (!EFI_ERROR (Status)) {
254 return Status;
255 }
256
257 Status = PeiServicesAllocatePages (
258 EfiBootServicesCode,
259 (sizeof (PEI_FAT_PRIVATE_DATA) - 1) / PEI_FAT_MEMMORY_PAGE_SIZE + 1,
260 &Address
261 );
262 if (EFI_ERROR (Status)) {
263 return EFI_OUT_OF_RESOURCES;
264 }
265
266 PrivateData = (PEI_FAT_PRIVATE_DATA *) (UINTN) Address;
267
268 //
269 // Initialize Private Data (to zero, as is required by subsequent operations)
270 //
271 ZeroMem ((UINT8 *) PrivateData, sizeof (PEI_FAT_PRIVATE_DATA));
272
273 PrivateData->Signature = PEI_FAT_PRIVATE_DATA_SIGNATURE;
274
275 //
276 // Installs Ppi
277 //
278 PrivateData->DeviceRecoveryPpi.GetNumberRecoveryCapsules = GetNumberRecoveryCapsules;
279 PrivateData->DeviceRecoveryPpi.GetRecoveryCapsuleInfo = GetRecoveryCapsuleInfo;
280 PrivateData->DeviceRecoveryPpi.LoadRecoveryCapsule = LoadRecoveryCapsule;
281
282 PrivateData->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
283 PrivateData->PpiDescriptor.Guid = &gEfiPeiDeviceRecoveryModulePpiGuid;
284 PrivateData->PpiDescriptor.Ppi = &PrivateData->DeviceRecoveryPpi;
285
286 Status = PeiServicesInstallPpi (&PrivateData->PpiDescriptor);
287 if (EFI_ERROR (Status)) {
288 return EFI_OUT_OF_RESOURCES;
289 }
290 //
291 // Other initializations
292 //
293 PrivateData->BlockDeviceCount = 0;
294
295 UpdateBlocksAndVolumes (PrivateData, TRUE);
296 UpdateBlocksAndVolumes (PrivateData, FALSE);
297
298 //
299 // PrivateData is allocated now, set it to the module variable
300 //
301 mPrivateData = PrivateData;
302
303 //
304 // Installs Block Io Ppi notification function
305 //
306 PrivateData->NotifyDescriptor[0].Flags =
307 (
308 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
309 );
310 PrivateData->NotifyDescriptor[0].Guid = &gEfiPeiVirtualBlockIoPpiGuid;
311 PrivateData->NotifyDescriptor[0].Notify = BlockIoNotifyEntry;
312 PrivateData->NotifyDescriptor[1].Flags =
313 (
314 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |
315 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
316 );
317 PrivateData->NotifyDescriptor[1].Guid = &gEfiPeiVirtualBlockIo2PpiGuid;
318 PrivateData->NotifyDescriptor[1].Notify = BlockIoNotifyEntry;
319 return PeiServicesNotifyPpi (&PrivateData->NotifyDescriptor[0]);
320 }
321
322
323 /**
324 Returns the number of DXE capsules residing on the device.
325
326 This function searches for DXE capsules from the associated device and returns
327 the number and maximum size in bytes of the capsules discovered. Entry 1 is
328 assumed to be the highest load priority and entry N is assumed to be the lowest
329 priority.
330
331 @param[in] PeiServices General-purpose services that are available
332 to every PEIM
333 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
334 instance.
335 @param[out] NumberRecoveryCapsules Pointer to a caller-allocated UINTN. On
336 output, *NumberRecoveryCapsules contains
337 the number of recovery capsule images
338 available for retrieval from this PEIM
339 instance.
340
341 @retval EFI_SUCCESS One or more capsules were discovered.
342 @retval EFI_DEVICE_ERROR A device error occurred.
343 @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
344
345 **/
346 EFI_STATUS
347 EFIAPI
348 GetNumberRecoveryCapsules (
349 IN EFI_PEI_SERVICES **PeiServices,
350 IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
351 OUT UINTN *NumberRecoveryCapsules
352 )
353 {
354 EFI_STATUS Status;
355 PEI_FAT_PRIVATE_DATA *PrivateData;
356 UINTN Index;
357 UINTN RecoveryCapsuleCount;
358 PEI_FILE_HANDLE Handle;
359
360 PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
361
362 //
363 // Search each volume in the root directory for the Recovery capsule
364 //
365 RecoveryCapsuleCount = 0;
366 for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
367 Status = FindRecoveryFile (PrivateData, Index, (CHAR16 *)PcdGetPtr(PcdRecoveryFileName), &Handle);
368 if (EFI_ERROR (Status)) {
369 continue;
370 }
371
372 RecoveryCapsuleCount++;
373 }
374
375 *NumberRecoveryCapsules = RecoveryCapsuleCount;
376
377 if (*NumberRecoveryCapsules == 0) {
378 return EFI_NOT_FOUND;
379 }
380
381 return EFI_SUCCESS;
382 }
383
384
385 /**
386 Returns the size and type of the requested recovery capsule.
387
388 This function gets the size and type of the capsule specified by CapsuleInstance.
389
390 @param[in] PeiServices General-purpose services that are available to every PEIM
391 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
392 instance.
393 @param[in] CapsuleInstance Specifies for which capsule instance to retrieve
394 the information. This parameter must be between
395 one and the value returned by GetNumberRecoveryCapsules()
396 in NumberRecoveryCapsules.
397 @param[out] Size A pointer to a caller-allocated UINTN in which
398 the size of the requested recovery module is
399 returned.
400 @param[out] CapsuleType A pointer to a caller-allocated EFI_GUID in which
401 the type of the requested recovery capsule is
402 returned. The semantic meaning of the value
403 returned is defined by the implementation.
404
405 @retval EFI_SUCCESS One or more capsules were discovered.
406 @retval EFI_DEVICE_ERROR A device error occurred.
407 @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.
408
409 **/
410 EFI_STATUS
411 EFIAPI
412 GetRecoveryCapsuleInfo (
413 IN EFI_PEI_SERVICES **PeiServices,
414 IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
415 IN UINTN CapsuleInstance,
416 OUT UINTN *Size,
417 OUT EFI_GUID *CapsuleType
418 )
419 {
420 EFI_STATUS Status;
421 PEI_FAT_PRIVATE_DATA *PrivateData;
422 UINTN Index;
423 UINTN BlockDeviceNo;
424 UINTN RecoveryCapsuleCount;
425 PEI_FILE_HANDLE Handle;
426 UINTN NumberRecoveryCapsules;
427
428 Status = GetNumberRecoveryCapsules (PeiServices, This, &NumberRecoveryCapsules);
429
430 if (EFI_ERROR (Status)) {
431 return Status;
432 }
433
434 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
435 CapsuleInstance = CapsuleInstance + 1;
436 }
437
438 if ((CapsuleInstance == 0) || (CapsuleInstance > NumberRecoveryCapsules)) {
439 return EFI_NOT_FOUND;
440 }
441
442 PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
443
444 //
445 // Search each volume in the root directory for the Recovery capsule
446 //
447 RecoveryCapsuleCount = 0;
448 for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
449 Status = FindRecoveryFile (PrivateData, Index, (CHAR16 *)PcdGetPtr(PcdRecoveryFileName), &Handle);
450
451 if (EFI_ERROR (Status)) {
452 continue;
453 }
454
455 if (CapsuleInstance - 1 == RecoveryCapsuleCount) {
456 //
457 // Get file size
458 //
459 *Size = (UINTN) (((PEI_FAT_FILE *) Handle)->FileSize);
460
461 //
462 // Find corresponding physical block device
463 //
464 BlockDeviceNo = PrivateData->Volume[Index].BlockDeviceNo;
465 while (PrivateData->BlockDevice[BlockDeviceNo].Logical && BlockDeviceNo < PrivateData->BlockDeviceCount) {
466 BlockDeviceNo = PrivateData->BlockDevice[BlockDeviceNo].ParentDevNo;
467 }
468 //
469 // Fill in the Capsule Type GUID according to the block device type
470 //
471 if (BlockDeviceNo < PrivateData->BlockDeviceCount) {
472 if (PrivateData->BlockDevice[BlockDeviceNo].BlockIo2 != NULL) {
473 switch (PrivateData->BlockDevice[BlockDeviceNo].InterfaceType) {
474 case MSG_ATAPI_DP:
475 CopyGuid (CapsuleType, &gRecoveryOnFatIdeDiskGuid);
476 break;
477
478 case MSG_USB_DP:
479 CopyGuid (CapsuleType, &gRecoveryOnFatUsbDiskGuid);
480 break;
481
482 case MSG_NVME_NAMESPACE_DP:
483 CopyGuid (CapsuleType, &gRecoveryOnFatNvmeDiskGuid);
484 break;
485
486 default:
487 break;
488 }
489 }
490 if (PrivateData->BlockDevice[BlockDeviceNo].BlockIo != NULL) {
491 switch (PrivateData->BlockDevice[BlockDeviceNo].DevType) {
492 case LegacyFloppy:
493 CopyGuid (CapsuleType, &gRecoveryOnFatFloppyDiskGuid);
494 break;
495
496 case IdeCDROM:
497 case IdeLS120:
498 CopyGuid (CapsuleType, &gRecoveryOnFatIdeDiskGuid);
499 break;
500
501 case UsbMassStorage:
502 CopyGuid (CapsuleType, &gRecoveryOnFatUsbDiskGuid);
503 break;
504
505 default:
506 break;
507 }
508 }
509 }
510
511 return EFI_SUCCESS;
512 }
513
514 RecoveryCapsuleCount++;
515 }
516
517 return EFI_NOT_FOUND;
518 }
519
520
521 /**
522 Loads a DXE capsule from some media into memory.
523
524 This function, by whatever mechanism, retrieves a DXE capsule from some device
525 and loads it into memory. Note that the published interface is device neutral.
526
527 @param[in] PeiServices General-purpose services that are available
528 to every PEIM
529 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI
530 instance.
531 @param[in] CapsuleInstance Specifies which capsule instance to retrieve.
532 @param[out] Buffer Specifies a caller-allocated buffer in which
533 the requested recovery capsule will be returned.
534
535 @retval EFI_SUCCESS The capsule was loaded correctly.
536 @retval EFI_DEVICE_ERROR A device error occurred.
537 @retval EFI_NOT_FOUND A requested recovery DXE capsule cannot be found.
538
539 **/
540 EFI_STATUS
541 EFIAPI
542 LoadRecoveryCapsule (
543 IN EFI_PEI_SERVICES **PeiServices,
544 IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,
545 IN UINTN CapsuleInstance,
546 OUT VOID *Buffer
547 )
548 {
549 EFI_STATUS Status;
550 PEI_FAT_PRIVATE_DATA *PrivateData;
551 UINTN Index;
552 UINTN RecoveryCapsuleCount;
553 PEI_FILE_HANDLE Handle;
554 UINTN NumberRecoveryCapsules;
555
556 Status = GetNumberRecoveryCapsules (PeiServices, This, &NumberRecoveryCapsules);
557
558 if (EFI_ERROR (Status)) {
559 return Status;
560 }
561
562 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
563 CapsuleInstance = CapsuleInstance + 1;
564 }
565
566 if ((CapsuleInstance == 0) || (CapsuleInstance > NumberRecoveryCapsules)) {
567 return EFI_NOT_FOUND;
568 }
569
570 PrivateData = PEI_FAT_PRIVATE_DATA_FROM_THIS (This);
571
572 //
573 // Search each volume in the root directory for the Recovery capsule
574 //
575 RecoveryCapsuleCount = 0;
576 for (Index = 0; Index < PrivateData->VolumeCount; Index++) {
577 Status = FindRecoveryFile (PrivateData, Index, (CHAR16 *)PcdGetPtr(PcdRecoveryFileName), &Handle);
578 if (EFI_ERROR (Status)) {
579 continue;
580 }
581
582 if (CapsuleInstance - 1 == RecoveryCapsuleCount) {
583
584 Status = FatReadFile (
585 PrivateData,
586 Handle,
587 (UINTN) (((PEI_FAT_FILE *) Handle)->FileSize),
588 Buffer
589 );
590 return Status;
591 }
592
593 RecoveryCapsuleCount++;
594 }
595
596 return EFI_NOT_FOUND;
597 }
598
599
600 /**
601 Finds the recovery file on a FAT volume.
602 This function finds the the recovery file named FileName on a specified FAT volume and returns
603 its FileHandle pointer.
604
605 @param PrivateData Global memory map for accessing global
606 variables.
607 @param VolumeIndex The index of the volume.
608 @param FileName The recovery file name to find.
609 @param Handle The output file handle.
610
611 @retval EFI_DEVICE_ERROR Some error occured when operating the FAT
612 volume.
613 @retval EFI_NOT_FOUND The recovery file was not found.
614 @retval EFI_SUCCESS The recovery file was successfully found on the
615 FAT volume.
616
617 **/
618 EFI_STATUS
619 FindRecoveryFile (
620 IN PEI_FAT_PRIVATE_DATA *PrivateData,
621 IN UINTN VolumeIndex,
622 IN CHAR16 *FileName,
623 OUT PEI_FILE_HANDLE *Handle
624 )
625 {
626 EFI_STATUS Status;
627 PEI_FAT_FILE Parent;
628 PEI_FAT_FILE *File;
629
630 File = &PrivateData->File;
631
632 //
633 // VolumeIndex must be less than PEI_FAT_MAX_VOLUME because PrivateData->VolumeCount
634 // cannot be larger than PEI_FAT_MAX_VOLUME when detecting recovery volume.
635 //
636 ASSERT (VolumeIndex < PEI_FAT_MAX_VOLUME);
637
638 //
639 // Construct root directory file
640 //
641 ZeroMem (&Parent, sizeof (PEI_FAT_FILE));
642 Parent.IsFixedRootDir = (BOOLEAN) ((PrivateData->Volume[VolumeIndex].FatType == Fat32) ? FALSE : TRUE);
643 Parent.Attributes = FAT_ATTR_DIRECTORY;
644 Parent.CurrentPos = 0;
645 Parent.CurrentCluster = Parent.IsFixedRootDir ? 0 : PrivateData->Volume[VolumeIndex].RootDirCluster;
646 Parent.StartingCluster = Parent.CurrentCluster;
647 Parent.Volume = &PrivateData->Volume[VolumeIndex];
648
649 Status = FatSetFilePos (PrivateData, &Parent, 0);
650 if (EFI_ERROR (Status)) {
651 return EFI_DEVICE_ERROR;
652 }
653 //
654 // Search for recovery capsule in root directory
655 //
656 Status = FatReadNextDirectoryEntry (PrivateData, &Parent, File);
657 while (Status == EFI_SUCCESS) {
658 //
659 // Compare whether the file name is recovery file name.
660 //
661 if (EngStriColl (PrivateData, FileName, File->FileName)) {
662 break;
663 }
664
665 Status = FatReadNextDirectoryEntry (PrivateData, &Parent, File);
666 }
667
668 if (EFI_ERROR (Status)) {
669 return EFI_NOT_FOUND;
670 }
671
672 //
673 // Get the recovery file, set its file position to 0.
674 //
675 if (File->StartingCluster != 0) {
676 Status = FatSetFilePos (PrivateData, File, 0);
677 }
678
679 *Handle = File;
680
681 return EFI_SUCCESS;
682
683 }