]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/FatPei/FatLiteApi.c
FatPkg/FatPei: Remove PcdFrameworkCompatibilitySupport usage
[mirror_edk2.git] / FatPkg / FatPei / FatLiteApi.c
CommitLineData
2f4dfa84
JJ
1/** @file\r
2 FAT recovery PEIM entry point, Ppi Functions and FAT Api functions.\r
3\r
8dc1f4ec 4Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
2f4dfa84 5\r
eb6cb4ce 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
2f4dfa84
JJ
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
e38f26a2
LG
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
2f4dfa84
JJ
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
e38f26a2
LG
40 @param PrivateData Global memory map for accessing global\r
41 variables.\r
8a467be1 42 @param BlockIo2 Boolean to show whether using BlockIo2 or BlockIo\r
2f4dfa84
JJ
43\r
44 @retval EFI_SUCCESS The function completed successfully.\r
45\r
46**/\r
47EFI_STATUS\r
48UpdateBlocksAndVolumes (\r
8a467be1
FT
49 IN OUT PEI_FAT_PRIVATE_DATA *PrivateData,\r
50 IN BOOLEAN BlockIo2\r
2f4dfa84
JJ
51 )\r
52{\r
8a467be1
FT
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
2f4dfa84
JJ
64\r
65 PeiServices = (EFI_PEI_SERVICES **) GetPeiServicesTablePointer ();\r
4819b3e8
FT
66 BlockIo2Ppi = NULL;\r
67 BlockIoPpi = NULL;\r
2f4dfa84
JJ
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
8a467be1
FT
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
2f4dfa84
JJ
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
8a467be1
FT
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
2f4dfa84
JJ
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
8a467be1
FT
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
4819b3e8
FT
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
8a467be1
FT
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
4819b3e8
FT
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
2f4dfa84
JJ
151 }\r
152\r
4819b3e8 153 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].IoAlign = 0;\r
2f4dfa84
JJ
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
2f4dfa84 160 PrivateData->BlockDevice[PrivateData->BlockDeviceCount].PhysicalDevNo = (UINT8) Index;\r
2f4dfa84
JJ
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
e38f26a2
LG
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
2f4dfa84
JJ
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
8a467be1
FT
218 if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiVirtualBlockIo2PpiGuid)) {\r
219 UpdateBlocksAndVolumes (mPrivateData, TRUE);\r
220 } else {\r
221 UpdateBlocksAndVolumes (mPrivateData, FALSE);\r
222 }\r
2f4dfa84
JJ
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
e38f26a2
LG
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
2f4dfa84 235\r
e38f26a2
LG
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
2f4dfa84
JJ
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
8a467be1 284 PrivateData->PpiDescriptor.Ppi = &PrivateData->DeviceRecoveryPpi;\r
2f4dfa84
JJ
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
8a467be1
FT
295 UpdateBlocksAndVolumes (PrivateData, TRUE);\r
296 UpdateBlocksAndVolumes (PrivateData, FALSE);\r
2f4dfa84
JJ
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
8a467be1
FT
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
2f4dfa84
JJ
313 (\r
314 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |\r
315 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST\r
316 );\r
8a467be1
FT
317 PrivateData->NotifyDescriptor[1].Guid = &gEfiPeiVirtualBlockIo2PpiGuid;\r
318 PrivateData->NotifyDescriptor[1].Notify = BlockIoNotifyEntry;\r
319 return PeiServicesNotifyPpi (&PrivateData->NotifyDescriptor[0]);\r
2f4dfa84
JJ
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
e38f26a2
LG
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
2f4dfa84
JJ
329 priority.\r
330\r
e38f26a2 331 @param[in] PeiServices General-purpose services that are available\r
2f4dfa84
JJ
332 to every PEIM\r
333 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI\r
334 instance.\r
e38f26a2
LG
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
2f4dfa84
JJ
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
46cd2cb6 367 Status = FindRecoveryFile (PrivateData, Index, (CHAR16 *)PcdGetPtr(PcdRecoveryFileName), &Handle);\r
2f4dfa84
JJ
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
e38f26a2 391 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI\r
2f4dfa84 392 instance.\r
e38f26a2
LG
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
2f4dfa84 396 in NumberRecoveryCapsules.\r
e38f26a2
LG
397 @param[out] Size A pointer to a caller-allocated UINTN in which\r
398 the size of the requested recovery module is\r
2f4dfa84 399 returned.\r
e38f26a2
LG
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
2f4dfa84
JJ
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
2f4dfa84
JJ
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
46cd2cb6 445 Status = FindRecoveryFile (PrivateData, Index, (CHAR16 *)PcdGetPtr(PcdRecoveryFileName), &Handle);\r
2f4dfa84
JJ
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
8a467be1
FT
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
796ef9da
HW
478 case MSG_NVME_NAMESPACE_DP:\r
479 CopyGuid (CapsuleType, &gRecoveryOnFatNvmeDiskGuid);\r
480 break;\r
481\r
8a467be1
FT
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
2f4dfa84
JJ
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
e38f26a2 523 @param[in] PeiServices General-purpose services that are available\r
2f4dfa84
JJ
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
e38f26a2 528 @param[out] Buffer Specifies a caller-allocated buffer in which\r
2f4dfa84
JJ
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
2f4dfa84
JJ
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
46cd2cb6 569 Status = FindRecoveryFile (PrivateData, Index, (CHAR16 *)PcdGetPtr(PcdRecoveryFileName), &Handle);\r
2f4dfa84
JJ
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
e38f26a2
LG
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
2f4dfa84 602\r
e38f26a2
LG
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
2f4dfa84
JJ
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
1d951a30 633 ZeroMem (&Parent, sizeof (PEI_FAT_FILE));\r
2f4dfa84
JJ
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
1d951a30
FT
650 //\r
651 // Compare whether the file name is recovery file name.\r
652 //\r
2f4dfa84
JJ
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
1d951a30
FT
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
2f4dfa84
JJ
671 *Handle = File;\r
672\r
673 return EFI_SUCCESS;\r
674\r
675}\r