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