]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Disk/CdExpressPei/PeiCdExpress.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / CdExpressPei / PeiCdExpress.c
... / ...
CommitLineData
1/** @file\r
2 Source file for CD recovery PEIM\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 "PeiCdExpress.h"\r
11\r
12PEI_CD_EXPRESS_PRIVATE_DATA *mPrivateData = NULL;\r
13CHAR8 *mRecoveryFileName;\r
14UINTN mRecoveryFileNameSize;\r
15\r
16/**\r
17 Installs the Device Recovery Module PPI, Initialize BlockIo Ppi\r
18 installation notification\r
19\r
20 @param FileHandle The file handle of the image.\r
21 @param PeiServices General purpose services available to every PEIM.\r
22\r
23 @retval EFI_SUCCESS The function completed successfully.\r
24 @retval EFI_OUT_OF_RESOURCES There is not enough system memory.\r
25\r
26**/\r
27EFI_STATUS\r
28EFIAPI\r
29CdExpressPeimEntry (\r
30 IN EFI_PEI_FILE_HANDLE FileHandle,\r
31 IN CONST EFI_PEI_SERVICES **PeiServices\r
32 )\r
33{\r
34 EFI_STATUS Status;\r
35 PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData;\r
36\r
37 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
38 return EFI_SUCCESS;\r
39 }\r
40\r
41 PrivateData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*PrivateData)));\r
42 if (PrivateData == NULL) {\r
43 return EFI_OUT_OF_RESOURCES;\r
44 }\r
45\r
46 mRecoveryFileNameSize = PcdGetSize (PcdRecoveryFileName) / sizeof (CHAR16);\r
47 mRecoveryFileName = AllocatePool (mRecoveryFileNameSize);\r
48 if (mRecoveryFileName == NULL) {\r
49 return EFI_OUT_OF_RESOURCES;\r
50 }\r
51\r
52 Status = UnicodeStrToAsciiStrS (PcdGetPtr (PcdRecoveryFileName), mRecoveryFileName, mRecoveryFileNameSize);\r
53 if (EFI_ERROR (Status)) {\r
54 return Status;\r
55 }\r
56\r
57 //\r
58 // Initialize Private Data (to zero, as is required by subsequent operations)\r
59 //\r
60 ZeroMem (PrivateData, sizeof (*PrivateData));\r
61 PrivateData->Signature = PEI_CD_EXPRESS_PRIVATE_DATA_SIGNATURE;\r
62\r
63 PrivateData->BlockBuffer = AllocatePages (EFI_SIZE_TO_PAGES (PEI_CD_BLOCK_SIZE));\r
64 if (PrivateData->BlockBuffer == NULL) {\r
65 return EFI_OUT_OF_RESOURCES;\r
66 }\r
67\r
68 PrivateData->CapsuleCount = 0;\r
69 Status = UpdateBlocksAndVolumes (PrivateData, TRUE);\r
70 Status = UpdateBlocksAndVolumes (PrivateData, FALSE);\r
71\r
72 //\r
73 // Installs Ppi\r
74 //\r
75 PrivateData->DeviceRecoveryPpi.GetNumberRecoveryCapsules = GetNumberRecoveryCapsules;\r
76 PrivateData->DeviceRecoveryPpi.GetRecoveryCapsuleInfo = GetRecoveryCapsuleInfo;\r
77 PrivateData->DeviceRecoveryPpi.LoadRecoveryCapsule = LoadRecoveryCapsule;\r
78\r
79 PrivateData->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
80 PrivateData->PpiDescriptor.Guid = &gEfiPeiDeviceRecoveryModulePpiGuid;\r
81 PrivateData->PpiDescriptor.Ppi = &PrivateData->DeviceRecoveryPpi;\r
82\r
83 Status = PeiServicesInstallPpi (&PrivateData->PpiDescriptor);\r
84 if (EFI_ERROR (Status)) {\r
85 return EFI_OUT_OF_RESOURCES;\r
86 }\r
87\r
88 //\r
89 // PrivateData is allocated now, set it to the module variable\r
90 //\r
91 mPrivateData = PrivateData;\r
92\r
93 //\r
94 // Installs Block Io Ppi notification function\r
95 //\r
96 PrivateData->NotifyDescriptor.Flags =\r
97 (\r
98 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK\r
99 );\r
100 PrivateData->NotifyDescriptor.Guid = &gEfiPeiVirtualBlockIoPpiGuid;\r
101 PrivateData->NotifyDescriptor.Notify = BlockIoNotifyEntry;\r
102\r
103 PrivateData->NotifyDescriptor2.Flags =\r
104 (\r
105 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |\r
106 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST\r
107 );\r
108 PrivateData->NotifyDescriptor2.Guid = &gEfiPeiVirtualBlockIo2PpiGuid;\r
109 PrivateData->NotifyDescriptor2.Notify = BlockIoNotifyEntry;\r
110\r
111 return PeiServicesNotifyPpi (&PrivateData->NotifyDescriptor);\r
112}\r
113\r
114/**\r
115 BlockIo installation notification function.\r
116\r
117 This function finds out all the current Block IO PPIs in the system and add them\r
118 into private data.\r
119\r
120 @param PeiServices Indirect reference to the PEI Services Table.\r
121 @param NotifyDescriptor Address of the notification descriptor data structure.\r
122 @param Ppi Address of the PPI that was installed.\r
123\r
124 @retval EFI_SUCCESS The function completes successfully.\r
125\r
126**/\r
127EFI_STATUS\r
128EFIAPI\r
129BlockIoNotifyEntry (\r
130 IN EFI_PEI_SERVICES **PeiServices,\r
131 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
132 IN VOID *Ppi\r
133 )\r
134{\r
135 if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiVirtualBlockIo2PpiGuid)) {\r
136 UpdateBlocksAndVolumes (mPrivateData, TRUE);\r
137 } else {\r
138 UpdateBlocksAndVolumes (mPrivateData, FALSE);\r
139 }\r
140\r
141 return EFI_SUCCESS;\r
142}\r
143\r
144/**\r
145 Finds out all the current Block IO PPIs in the system and add them into private data.\r
146\r
147 @param PrivateData The private data structure that contains recovery module information.\r
148 @param BlockIo2 Boolean to show whether using BlockIo2 or BlockIo.\r
149\r
150 @retval EFI_SUCCESS The blocks and volumes are updated successfully.\r
151\r
152**/\r
153EFI_STATUS\r
154UpdateBlocksAndVolumes (\r
155 IN OUT PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData,\r
156 IN BOOLEAN BlockIo2\r
157 )\r
158{\r
159 EFI_STATUS Status;\r
160 EFI_PEI_PPI_DESCRIPTOR *TempPpiDescriptor;\r
161 UINTN BlockIoPpiInstance;\r
162 EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;\r
163 EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi;\r
164 UINTN NumberBlockDevices;\r
165 UINTN IndexBlockDevice;\r
166 EFI_PEI_BLOCK_IO_MEDIA Media;\r
167 EFI_PEI_BLOCK_IO2_MEDIA Media2;\r
168 EFI_PEI_SERVICES **PeiServices;\r
169\r
170 IndexBlockDevice = 0;\r
171 BlockIo2Ppi = NULL;\r
172 BlockIoPpi = NULL;\r
173 //\r
174 // Find out all Block Io Ppi instances within the system\r
175 // Assuming all device Block Io Peims are dispatched already\r
176 //\r
177 for (BlockIoPpiInstance = 0; BlockIoPpiInstance < PEI_CD_EXPRESS_MAX_BLOCK_IO_PPI; BlockIoPpiInstance++) {\r
178 if (BlockIo2) {\r
179 Status = PeiServicesLocatePpi (\r
180 &gEfiPeiVirtualBlockIo2PpiGuid,\r
181 BlockIoPpiInstance,\r
182 &TempPpiDescriptor,\r
183 (VOID **)&BlockIo2Ppi\r
184 );\r
185 } else {\r
186 Status = PeiServicesLocatePpi (\r
187 &gEfiPeiVirtualBlockIoPpiGuid,\r
188 BlockIoPpiInstance,\r
189 &TempPpiDescriptor,\r
190 (VOID **)&BlockIoPpi\r
191 );\r
192 }\r
193\r
194 if (EFI_ERROR (Status)) {\r
195 //\r
196 // Done with all Block Io Ppis\r
197 //\r
198 break;\r
199 }\r
200\r
201 PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer ();\r
202 if (BlockIo2) {\r
203 Status = BlockIo2Ppi->GetNumberOfBlockDevices (\r
204 PeiServices,\r
205 BlockIo2Ppi,\r
206 &NumberBlockDevices\r
207 );\r
208 } else {\r
209 Status = BlockIoPpi->GetNumberOfBlockDevices (\r
210 PeiServices,\r
211 BlockIoPpi,\r
212 &NumberBlockDevices\r
213 );\r
214 }\r
215\r
216 if (EFI_ERROR (Status) || (NumberBlockDevices == 0)) {\r
217 continue;\r
218 }\r
219\r
220 //\r
221 // Just retrieve the first block, should emulate all blocks.\r
222 //\r
223 for (IndexBlockDevice = 1; IndexBlockDevice <= NumberBlockDevices && PrivateData->CapsuleCount < PEI_CD_EXPRESS_MAX_CAPSULE_NUMBER; IndexBlockDevice++) {\r
224 if (BlockIo2) {\r
225 Status = BlockIo2Ppi->GetBlockDeviceMediaInfo (\r
226 PeiServices,\r
227 BlockIo2Ppi,\r
228 IndexBlockDevice,\r
229 &Media2\r
230 );\r
231 if (EFI_ERROR (Status) ||\r
232 !Media2.MediaPresent ||\r
233 ((Media2.InterfaceType != MSG_ATAPI_DP) && (Media2.InterfaceType != MSG_USB_DP)) ||\r
234 (Media2.BlockSize != PEI_CD_BLOCK_SIZE)\r
235 )\r
236 {\r
237 continue;\r
238 }\r
239\r
240 DEBUG ((DEBUG_INFO, "PeiCdExpress InterfaceType is %d\n", Media2.InterfaceType));\r
241 DEBUG ((DEBUG_INFO, "PeiCdExpress MediaPresent is %d\n", Media2.MediaPresent));\r
242 DEBUG ((DEBUG_INFO, "PeiCdExpress BlockSize is 0x%x\n", Media2.BlockSize));\r
243 } else {\r
244 Status = BlockIoPpi->GetBlockDeviceMediaInfo (\r
245 PeiServices,\r
246 BlockIoPpi,\r
247 IndexBlockDevice,\r
248 &Media\r
249 );\r
250 if (EFI_ERROR (Status) ||\r
251 !Media.MediaPresent ||\r
252 ((Media.DeviceType != IdeCDROM) && (Media.DeviceType != UsbMassStorage)) ||\r
253 (Media.BlockSize != PEI_CD_BLOCK_SIZE)\r
254 )\r
255 {\r
256 continue;\r
257 }\r
258\r
259 DEBUG ((DEBUG_INFO, "PeiCdExpress DeviceType is %d\n", Media.DeviceType));\r
260 DEBUG ((DEBUG_INFO, "PeiCdExpress MediaPresent is %d\n", Media.MediaPresent));\r
261 DEBUG ((DEBUG_INFO, "PeiCdExpress BlockSize is 0x%x\n", Media.BlockSize));\r
262 }\r
263\r
264 DEBUG ((DEBUG_INFO, "PeiCdExpress Status is %d\n", Status));\r
265\r
266 DEBUG ((DEBUG_INFO, "IndexBlockDevice is %d\n", IndexBlockDevice));\r
267 PrivateData->CapsuleData[PrivateData->CapsuleCount].IndexBlock = IndexBlockDevice;\r
268 if (BlockIo2) {\r
269 PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo2 = BlockIo2Ppi;\r
270 } else {\r
271 PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo = BlockIoPpi;\r
272 }\r
273\r
274 Status = FindRecoveryCapsules (PrivateData);\r
275 DEBUG ((DEBUG_INFO, "Status is %d\n", Status));\r
276\r
277 if (EFI_ERROR (Status)) {\r
278 continue;\r
279 }\r
280\r
281 PrivateData->CapsuleCount++;\r
282 }\r
283 }\r
284\r
285 return EFI_SUCCESS;\r
286}\r
287\r
288/**\r
289 Finds out the recovery capsule in the current volume.\r
290\r
291 @param PrivateData The private data structure that contains recovery module information.\r
292\r
293 @retval EFI_SUCCESS The recovery capsule is successfully found in the volume.\r
294 @retval EFI_NOT_FOUND The recovery capsule is not found in the volume.\r
295\r
296**/\r
297EFI_STATUS\r
298EFIAPI\r
299FindRecoveryCapsules (\r
300 IN OUT PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData\r
301 )\r
302{\r
303 EFI_STATUS Status;\r
304 UINTN Lba;\r
305 EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;\r
306 EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi;\r
307 UINTN BufferSize;\r
308 UINT8 *Buffer;\r
309 UINT8 Type;\r
310 UINT8 *StandardID;\r
311 UINT32 RootDirLBA;\r
312 PEI_CD_EXPRESS_DIR_FILE_RECORD *RoorDirRecord;\r
313 UINTN VolumeSpaceSize;\r
314 BOOLEAN StartOfVolume;\r
315 UINTN OriginalLBA;\r
316 UINTN IndexBlockDevice;\r
317\r
318 Buffer = PrivateData->BlockBuffer;\r
319 BufferSize = PEI_CD_BLOCK_SIZE;\r
320\r
321 Lba = 16;\r
322 //\r
323 // The volume descriptor starts on Lba 16\r
324 //\r
325 IndexBlockDevice = PrivateData->CapsuleData[PrivateData->CapsuleCount].IndexBlock;\r
326 BlockIoPpi = PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo;\r
327 BlockIo2Ppi = PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo2;\r
328\r
329 VolumeSpaceSize = 0;\r
330 StartOfVolume = TRUE;\r
331 OriginalLBA = 16;\r
332\r
333 while (TRUE) {\r
334 SetMem (Buffer, BufferSize, 0);\r
335 if (BlockIo2Ppi != NULL) {\r
336 Status = BlockIo2Ppi->ReadBlocks (\r
337 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
338 BlockIo2Ppi,\r
339 IndexBlockDevice,\r
340 Lba,\r
341 BufferSize,\r
342 Buffer\r
343 );\r
344 } else {\r
345 Status = BlockIoPpi->ReadBlocks (\r
346 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
347 BlockIoPpi,\r
348 IndexBlockDevice,\r
349 Lba,\r
350 BufferSize,\r
351 Buffer\r
352 );\r
353 }\r
354\r
355 if (EFI_ERROR (Status)) {\r
356 return Status;\r
357 }\r
358\r
359 StandardID = (UINT8 *)(Buffer + PEI_CD_EXPRESS_STANDARD_ID_OFFSET);\r
360 if (!StringCmp (StandardID, (UINT8 *)PEI_CD_STANDARD_ID, PEI_CD_EXPRESS_STANDARD_ID_SIZE, TRUE)) {\r
361 break;\r
362 }\r
363\r
364 if (StartOfVolume) {\r
365 OriginalLBA = Lba;\r
366 StartOfVolume = FALSE;\r
367 }\r
368\r
369 Type = *(UINT8 *)(Buffer + PEI_CD_EXPRESS_VOLUME_TYPE_OFFSET);\r
370 if (Type == PEI_CD_EXPRESS_VOLUME_TYPE_TERMINATOR) {\r
371 if (VolumeSpaceSize == 0) {\r
372 break;\r
373 } else {\r
374 Lba = (OriginalLBA + VolumeSpaceSize);\r
375 VolumeSpaceSize = 0;\r
376 StartOfVolume = TRUE;\r
377 continue;\r
378 }\r
379 }\r
380\r
381 if (Type != PEI_CD_EXPRESS_VOLUME_TYPE_PRIMARY) {\r
382 Lba++;\r
383 continue;\r
384 }\r
385\r
386 VolumeSpaceSize = *(UINT32 *)(Buffer + PEI_CD_EXPRESS_VOLUME_SPACE_OFFSET);\r
387\r
388 RoorDirRecord = (PEI_CD_EXPRESS_DIR_FILE_RECORD *)(Buffer + PEI_CD_EXPRESS_ROOT_DIR_RECORD_OFFSET);\r
389 RootDirLBA = RoorDirRecord->LocationOfExtent[0];\r
390\r
391 Status = RetrieveCapsuleFileFromRoot (PrivateData, BlockIoPpi, BlockIo2Ppi, IndexBlockDevice, RootDirLBA);\r
392 if (!EFI_ERROR (Status)) {\r
393 //\r
394 // Just look for the first primary descriptor\r
395 //\r
396 return EFI_SUCCESS;\r
397 }\r
398\r
399 Lba++;\r
400 }\r
401\r
402 return EFI_NOT_FOUND;\r
403}\r
404\r
405/**\r
406 Retrieves the recovery capsule in root directory of the current volume.\r
407\r
408 @param PrivateData The private data structure that contains recovery module information.\r
409 @param BlockIoPpi The Block IO PPI used to access the volume.\r
410 @param BlockIo2Ppi The Block IO 2 PPI used to access the volume.\r
411 @param IndexBlockDevice The index of current block device.\r
412 @param Lba The starting logic block address to retrieve capsule.\r
413\r
414 @retval EFI_SUCCESS The recovery capsule is successfully found in the volume.\r
415 @retval EFI_NOT_FOUND The recovery capsule is not found in the volume.\r
416 @retval Others\r
417\r
418**/\r
419EFI_STATUS\r
420EFIAPI\r
421RetrieveCapsuleFileFromRoot (\r
422 IN OUT PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData,\r
423 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi,\r
424 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi,\r
425 IN UINTN IndexBlockDevice,\r
426 IN UINT32 Lba\r
427 )\r
428{\r
429 EFI_STATUS Status;\r
430 UINTN BufferSize;\r
431 UINT8 *Buffer;\r
432 PEI_CD_EXPRESS_DIR_FILE_RECORD *FileRecord;\r
433 UINTN Index;\r
434\r
435 Buffer = PrivateData->BlockBuffer;\r
436 BufferSize = PEI_CD_BLOCK_SIZE;\r
437\r
438 SetMem (Buffer, BufferSize, 0);\r
439\r
440 if (BlockIo2Ppi != NULL) {\r
441 Status = BlockIo2Ppi->ReadBlocks (\r
442 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
443 BlockIo2Ppi,\r
444 IndexBlockDevice,\r
445 Lba,\r
446 BufferSize,\r
447 Buffer\r
448 );\r
449 } else {\r
450 Status = BlockIoPpi->ReadBlocks (\r
451 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
452 BlockIoPpi,\r
453 IndexBlockDevice,\r
454 Lba,\r
455 BufferSize,\r
456 Buffer\r
457 );\r
458 }\r
459\r
460 if (EFI_ERROR (Status)) {\r
461 return Status;\r
462 }\r
463\r
464 while (1) {\r
465 FileRecord = (PEI_CD_EXPRESS_DIR_FILE_RECORD *)Buffer;\r
466\r
467 if (FileRecord->Length == 0) {\r
468 break;\r
469 }\r
470\r
471 //\r
472 // Not intend to check other flag now\r
473 //\r
474 if ((FileRecord->Flag & PEI_CD_EXPRESS_DIR_FILE_REC_FLAG_ISDIR) != 0) {\r
475 Buffer += FileRecord->Length;\r
476 continue;\r
477 }\r
478\r
479 for (Index = 0; Index < FileRecord->FileIDLength; Index++) {\r
480 if (FileRecord->FileID[Index] == ';') {\r
481 break;\r
482 }\r
483 }\r
484\r
485 if (Index != mRecoveryFileNameSize - 1) {\r
486 Buffer += FileRecord->Length;\r
487 continue;\r
488 }\r
489\r
490 if (!StringCmp (FileRecord->FileID, (UINT8 *)mRecoveryFileName, mRecoveryFileNameSize - 1, FALSE)) {\r
491 Buffer += FileRecord->Length;\r
492 continue;\r
493 }\r
494\r
495 PrivateData->CapsuleData[PrivateData->CapsuleCount].CapsuleStartLBA = FileRecord->LocationOfExtent[0];\r
496 PrivateData->CapsuleData[PrivateData->CapsuleCount].CapsuleBlockAlignedSize =\r
497 (\r
498 FileRecord->DataLength[0] /\r
499 PEI_CD_BLOCK_SIZE +\r
500 1\r
501 ) *\r
502 PEI_CD_BLOCK_SIZE;\r
503 PrivateData->CapsuleData[PrivateData->CapsuleCount].CapsuleSize = FileRecord->DataLength[0];\r
504\r
505 return EFI_SUCCESS;\r
506 }\r
507\r
508 return EFI_NOT_FOUND;\r
509}\r
510\r
511/**\r
512 Returns the number of DXE capsules residing on the device.\r
513\r
514 This function searches for DXE capsules from the associated device and returns\r
515 the number and maximum size in bytes of the capsules discovered. Entry 1 is\r
516 assumed to be the highest load priority and entry N is assumed to be the lowest\r
517 priority.\r
518\r
519 @param[in] PeiServices General-purpose services that are available\r
520 to every PEIM\r
521 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI\r
522 instance.\r
523 @param[out] NumberRecoveryCapsules Pointer to a caller-allocated UINTN. On\r
524 output, *NumberRecoveryCapsules contains\r
525 the number of recovery capsule images\r
526 available for retrieval from this PEIM\r
527 instance.\r
528\r
529 @retval EFI_SUCCESS One or more capsules were discovered.\r
530 @retval EFI_DEVICE_ERROR A device error occurred.\r
531 @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.\r
532\r
533**/\r
534EFI_STATUS\r
535EFIAPI\r
536GetNumberRecoveryCapsules (\r
537 IN EFI_PEI_SERVICES **PeiServices,\r
538 IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,\r
539 OUT UINTN *NumberRecoveryCapsules\r
540 )\r
541{\r
542 PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData;\r
543\r
544 PrivateData = PEI_CD_EXPRESS_PRIVATE_DATA_FROM_THIS (This);\r
545 UpdateBlocksAndVolumes (PrivateData, TRUE);\r
546 UpdateBlocksAndVolumes (PrivateData, FALSE);\r
547 *NumberRecoveryCapsules = PrivateData->CapsuleCount;\r
548\r
549 if (*NumberRecoveryCapsules == 0) {\r
550 return EFI_NOT_FOUND;\r
551 }\r
552\r
553 return EFI_SUCCESS;\r
554}\r
555\r
556/**\r
557 Returns the size and type of the requested recovery capsule.\r
558\r
559 This function gets the size and type of the capsule specified by CapsuleInstance.\r
560\r
561 @param[in] PeiServices General-purpose services that are available to every PEIM\r
562 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI\r
563 instance.\r
564 @param[in] CapsuleInstance Specifies for which capsule instance to retrieve\r
565 the information. This parameter must be between\r
566 one and the value returned by GetNumberRecoveryCapsules()\r
567 in NumberRecoveryCapsules.\r
568 @param[out] Size A pointer to a caller-allocated UINTN in which\r
569 the size of the requested recovery module is\r
570 returned.\r
571 @param[out] CapsuleType A pointer to a caller-allocated EFI_GUID in which\r
572 the type of the requested recovery capsule is\r
573 returned. The semantic meaning of the value\r
574 returned is defined by the implementation.\r
575\r
576 @retval EFI_SUCCESS One or more capsules were discovered.\r
577 @retval EFI_DEVICE_ERROR A device error occurred.\r
578 @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found.\r
579\r
580**/\r
581EFI_STATUS\r
582EFIAPI\r
583GetRecoveryCapsuleInfo (\r
584 IN EFI_PEI_SERVICES **PeiServices,\r
585 IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,\r
586 IN UINTN CapsuleInstance,\r
587 OUT UINTN *Size,\r
588 OUT EFI_GUID *CapsuleType\r
589 )\r
590{\r
591 PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData;\r
592 UINTN NumberRecoveryCapsules;\r
593 EFI_STATUS Status;\r
594\r
595 Status = GetNumberRecoveryCapsules (PeiServices, This, &NumberRecoveryCapsules);\r
596\r
597 if (EFI_ERROR (Status)) {\r
598 return Status;\r
599 }\r
600\r
601 if ((CapsuleInstance == 0) || (CapsuleInstance > NumberRecoveryCapsules)) {\r
602 return EFI_NOT_FOUND;\r
603 }\r
604\r
605 PrivateData = PEI_CD_EXPRESS_PRIVATE_DATA_FROM_THIS (This);\r
606\r
607 *Size = PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleSize;\r
608 CopyMem (\r
609 CapsuleType,\r
610 &gRecoveryOnDataCdGuid,\r
611 sizeof (EFI_GUID)\r
612 );\r
613\r
614 return EFI_SUCCESS;\r
615}\r
616\r
617/**\r
618 Loads a DXE capsule from some media into memory.\r
619\r
620 This function, by whatever mechanism, retrieves a DXE capsule from some device\r
621 and loads it into memory. Note that the published interface is device neutral.\r
622\r
623 @param[in] PeiServices General-purpose services that are available\r
624 to every PEIM\r
625 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI\r
626 instance.\r
627 @param[in] CapsuleInstance Specifies which capsule instance to retrieve.\r
628 @param[out] Buffer Specifies a caller-allocated buffer in which\r
629 the requested recovery capsule will be returned.\r
630\r
631 @retval EFI_SUCCESS The capsule was loaded correctly.\r
632 @retval EFI_DEVICE_ERROR A device error occurred.\r
633 @retval EFI_NOT_FOUND A requested recovery DXE capsule cannot be found.\r
634\r
635**/\r
636EFI_STATUS\r
637EFIAPI\r
638LoadRecoveryCapsule (\r
639 IN EFI_PEI_SERVICES **PeiServices,\r
640 IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,\r
641 IN UINTN CapsuleInstance,\r
642 OUT VOID *Buffer\r
643 )\r
644{\r
645 EFI_STATUS Status;\r
646 PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData;\r
647 EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;\r
648 EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi;\r
649 UINTN NumberRecoveryCapsules;\r
650\r
651 Status = GetNumberRecoveryCapsules (PeiServices, This, &NumberRecoveryCapsules);\r
652\r
653 if (EFI_ERROR (Status)) {\r
654 return Status;\r
655 }\r
656\r
657 if ((CapsuleInstance == 0) || (CapsuleInstance > NumberRecoveryCapsules)) {\r
658 return EFI_NOT_FOUND;\r
659 }\r
660\r
661 PrivateData = PEI_CD_EXPRESS_PRIVATE_DATA_FROM_THIS (This);\r
662 BlockIoPpi = PrivateData->CapsuleData[CapsuleInstance - 1].BlockIo;\r
663 BlockIo2Ppi = PrivateData->CapsuleData[CapsuleInstance - 1].BlockIo2;\r
664\r
665 if (BlockIo2Ppi != NULL) {\r
666 Status = BlockIo2Ppi->ReadBlocks (\r
667 PeiServices,\r
668 BlockIo2Ppi,\r
669 PrivateData->CapsuleData[CapsuleInstance - 1].IndexBlock,\r
670 PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleStartLBA,\r
671 PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleBlockAlignedSize,\r
672 Buffer\r
673 );\r
674 } else {\r
675 Status = BlockIoPpi->ReadBlocks (\r
676 PeiServices,\r
677 BlockIoPpi,\r
678 PrivateData->CapsuleData[CapsuleInstance - 1].IndexBlock,\r
679 PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleStartLBA,\r
680 PrivateData->CapsuleData[CapsuleInstance - 1].CapsuleBlockAlignedSize,\r
681 Buffer\r
682 );\r
683 }\r
684\r
685 return Status;\r
686}\r
687\r
688/**\r
689 This function compares two ASCII strings in case sensitive/insensitive way.\r
690\r
691 @param Source1 The first string.\r
692 @param Source2 The second string.\r
693 @param Size The maximum comparison length.\r
694 @param CaseSensitive Flag to indicate whether the comparison is case sensitive.\r
695\r
696 @retval TRUE The two strings are the same.\r
697 @retval FALSE The two string are not the same.\r
698\r
699**/\r
700BOOLEAN\r
701StringCmp (\r
702 IN UINT8 *Source1,\r
703 IN UINT8 *Source2,\r
704 IN UINTN Size,\r
705 IN BOOLEAN CaseSensitive\r
706 )\r
707{\r
708 UINTN Index;\r
709 UINT8 Dif;\r
710\r
711 for (Index = 0; Index < Size; Index++) {\r
712 if (Source1[Index] == Source2[Index]) {\r
713 continue;\r
714 }\r
715\r
716 if (!CaseSensitive) {\r
717 Dif = (UINT8)((Source1[Index] > Source2[Index]) ? (Source1[Index] - Source2[Index]) : (Source2[Index] - Source1[Index]));\r
718 if (Dif == ('a' - 'A')) {\r
719 continue;\r
720 }\r
721 }\r
722\r
723 return FALSE;\r
724 }\r
725\r
726 return TRUE;\r
727}\r