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