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