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