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