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