]> git.proxmox.com Git - mirror_edk2.git/blame - 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
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
1436aea4
MK
12PEI_CD_EXPRESS_PRIVATE_DATA *mPrivateData = NULL;\r
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
1436aea4
MK
30 IN EFI_PEI_FILE_HANDLE FileHandle,\r
31 IN CONST EFI_PEI_SERVICES **PeiServices\r
30c00a1c 32 )\r
33{\r
1436aea4
MK
34 EFI_STATUS Status;\r
35 PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData;\r
30c00a1c 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
1436aea4
MK
46 mRecoveryFileNameSize = PcdGetSize (PcdRecoveryFileName) / sizeof (CHAR16);\r
47 mRecoveryFileName = AllocatePool (mRecoveryFileNameSize);\r
97533607
JY
48 if (mRecoveryFileName == NULL) {\r
49 return EFI_OUT_OF_RESOURCES;\r
50 }\r
1436aea4
MK
51\r
52 Status = UnicodeStrToAsciiStrS (PcdGetPtr (PcdRecoveryFileName), mRecoveryFileName, mRecoveryFileNameSize);\r
53 if (EFI_ERROR (Status)) {\r
97533607
JY
54 return Status;\r
55 }\r
56\r
30c00a1c 57 //\r
58 // Initialize Private Data (to zero, as is required by subsequent operations)\r
59 //\r
60 ZeroMem (PrivateData, sizeof (*PrivateData));\r
1436aea4 61 PrivateData->Signature = PEI_CD_EXPRESS_PRIVATE_DATA_SIGNATURE;\r
30c00a1c 62\r
1436aea4 63 PrivateData->BlockBuffer = AllocatePages (EFI_SIZE_TO_PAGES (PEI_CD_BLOCK_SIZE));\r
30c00a1c 64 if (PrivateData->BlockBuffer == NULL) {\r
65 return EFI_OUT_OF_RESOURCES;\r
66 }\r
67\r
68 PrivateData->CapsuleCount = 0;\r
1436aea4
MK
69 Status = UpdateBlocksAndVolumes (PrivateData, TRUE);\r
70 Status = UpdateBlocksAndVolumes (PrivateData, FALSE);\r
30c00a1c 71\r
72 //\r
73 // Installs Ppi\r
74 //\r
1436aea4
MK
75 PrivateData->DeviceRecoveryPpi.GetNumberRecoveryCapsules = GetNumberRecoveryCapsules;\r
76 PrivateData->DeviceRecoveryPpi.GetRecoveryCapsuleInfo = GetRecoveryCapsuleInfo;\r
77 PrivateData->DeviceRecoveryPpi.LoadRecoveryCapsule = LoadRecoveryCapsule;\r
30c00a1c 78\r
f9964c80
FT
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
30c00a1c 82\r
83 Status = PeiServicesInstallPpi (&PrivateData->PpiDescriptor);\r
84 if (EFI_ERROR (Status)) {\r
85 return EFI_OUT_OF_RESOURCES;\r
86 }\r
1436aea4 87\r
30c00a1c 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
1436aea4 98 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK\r
30c00a1c 99 );\r
1436aea4
MK
100 PrivateData->NotifyDescriptor.Guid = &gEfiPeiVirtualBlockIoPpiGuid;\r
101 PrivateData->NotifyDescriptor.Notify = BlockIoNotifyEntry;\r
f9964c80
FT
102\r
103 PrivateData->NotifyDescriptor2.Flags =\r
104 (\r
1436aea4
MK
105 EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK |\r
106 EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST\r
f9964c80 107 );\r
1436aea4
MK
108 PrivateData->NotifyDescriptor2.Guid = &gEfiPeiVirtualBlockIo2PpiGuid;\r
109 PrivateData->NotifyDescriptor2.Notify = BlockIoNotifyEntry;\r
f9964c80 110\r
30c00a1c 111 return PeiServicesNotifyPpi (&PrivateData->NotifyDescriptor);\r
30c00a1c 112}\r
113\r
114/**\r
d1102dba
LG
115 BlockIo installation notification function.\r
116\r
30c00a1c 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
f9964c80
FT
135 if (CompareGuid (NotifyDescriptor->Guid, &gEfiPeiVirtualBlockIo2PpiGuid)) {\r
136 UpdateBlocksAndVolumes (mPrivateData, TRUE);\r
137 } else {\r
138 UpdateBlocksAndVolumes (mPrivateData, FALSE);\r
139 }\r
30c00a1c 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
f9964c80 148 @param BlockIo2 Boolean to show whether using BlockIo2 or BlockIo.\r
30c00a1c 149\r
150 @retval EFI_SUCCESS The blocks and volumes are updated successfully.\r
151\r
152**/\r
153EFI_STATUS\r
154UpdateBlocksAndVolumes (\r
1436aea4
MK
155 IN OUT PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData,\r
156 IN BOOLEAN BlockIo2\r
30c00a1c 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
f9964c80 163 EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi;\r
30c00a1c 164 UINTN NumberBlockDevices;\r
165 UINTN IndexBlockDevice;\r
166 EFI_PEI_BLOCK_IO_MEDIA Media;\r
f9964c80 167 EFI_PEI_BLOCK_IO2_MEDIA Media2;\r
30c00a1c 168 EFI_PEI_SERVICES **PeiServices;\r
169\r
170 IndexBlockDevice = 0;\r
02c9f144
FT
171 BlockIo2Ppi = NULL;\r
172 BlockIoPpi = NULL;\r
30c00a1c 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
f9964c80
FT
178 if (BlockIo2) {\r
179 Status = PeiServicesLocatePpi (\r
1436aea4
MK
180 &gEfiPeiVirtualBlockIo2PpiGuid,\r
181 BlockIoPpiInstance,\r
182 &TempPpiDescriptor,\r
183 (VOID **)&BlockIo2Ppi\r
184 );\r
f9964c80
FT
185 } else {\r
186 Status = PeiServicesLocatePpi (\r
1436aea4
MK
187 &gEfiPeiVirtualBlockIoPpiGuid,\r
188 BlockIoPpiInstance,\r
189 &TempPpiDescriptor,\r
190 (VOID **)&BlockIoPpi\r
191 );\r
f9964c80 192 }\r
1436aea4 193\r
30c00a1c 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
1436aea4 201 PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer ();\r
f9964c80
FT
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
1436aea4
MK
210 PeiServices,\r
211 BlockIoPpi,\r
212 &NumberBlockDevices\r
213 );\r
f9964c80 214 }\r
1436aea4 215\r
30c00a1c 216 if (EFI_ERROR (Status) || (NumberBlockDevices == 0)) {\r
217 continue;\r
218 }\r
1436aea4 219\r
30c00a1c 220 //\r
221 // Just retrieve the first block, should emulate all blocks.\r
222 //\r
1436aea4 223 for (IndexBlockDevice = 1; IndexBlockDevice <= NumberBlockDevices && PrivateData->CapsuleCount < PEI_CD_EXPRESS_MAX_CAPSULE_NUMBER; IndexBlockDevice++) {\r
f9964c80
FT
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
1436aea4 233 ((Media2.InterfaceType != MSG_ATAPI_DP) && (Media2.InterfaceType != MSG_USB_DP)) ||\r
f9964c80 234 (Media2.BlockSize != PEI_CD_BLOCK_SIZE)\r
1436aea4
MK
235 )\r
236 {\r
f9964c80
FT
237 continue;\r
238 }\r
1436aea4 239\r
87000d77
MK
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
f9964c80
FT
243 } else {\r
244 Status = BlockIoPpi->GetBlockDeviceMediaInfo (\r
1436aea4
MK
245 PeiServices,\r
246 BlockIoPpi,\r
247 IndexBlockDevice,\r
248 &Media\r
249 );\r
f9964c80
FT
250 if (EFI_ERROR (Status) ||\r
251 !Media.MediaPresent ||\r
1436aea4 252 ((Media.DeviceType != IdeCDROM) && (Media.DeviceType != UsbMassStorage)) ||\r
f9964c80 253 (Media.BlockSize != PEI_CD_BLOCK_SIZE)\r
1436aea4
MK
254 )\r
255 {\r
f9964c80
FT
256 continue;\r
257 }\r
1436aea4 258\r
87000d77
MK
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
30c00a1c 262 }\r
263\r
87000d77 264 DEBUG ((DEBUG_INFO, "PeiCdExpress Status is %d\n", Status));\r
30c00a1c 265\r
87000d77 266 DEBUG ((DEBUG_INFO, "IndexBlockDevice is %d\n", IndexBlockDevice));\r
f9964c80
FT
267 PrivateData->CapsuleData[PrivateData->CapsuleCount].IndexBlock = IndexBlockDevice;\r
268 if (BlockIo2) {\r
269 PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo2 = BlockIo2Ppi;\r
270 } else {\r
1436aea4 271 PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo = BlockIoPpi;\r
f9964c80 272 }\r
1436aea4 273\r
30c00a1c 274 Status = FindRecoveryCapsules (PrivateData);\r
87000d77 275 DEBUG ((DEBUG_INFO, "Status is %d\n", Status));\r
30c00a1c 276\r
277 if (EFI_ERROR (Status)) {\r
278 continue;\r
279 }\r
d1102dba 280\r
30c00a1c 281 PrivateData->CapsuleCount++;\r
282 }\r
30c00a1c 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
1436aea4 300 IN OUT PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData\r
30c00a1c 301 )\r
302{\r
303 EFI_STATUS Status;\r
304 UINTN Lba;\r
305 EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;\r
f9964c80 306 EFI_PEI_RECOVERY_BLOCK_IO2_PPI *BlockIo2Ppi;\r
30c00a1c 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
1436aea4
MK
318 Buffer = PrivateData->BlockBuffer;\r
319 BufferSize = PEI_CD_BLOCK_SIZE;\r
30c00a1c 320\r
1436aea4 321 Lba = 16;\r
30c00a1c 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
f9964c80 327 BlockIo2Ppi = PrivateData->CapsuleData[PrivateData->CapsuleCount].BlockIo2;\r
30c00a1c 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
f9964c80
FT
335 if (BlockIo2Ppi != NULL) {\r
336 Status = BlockIo2Ppi->ReadBlocks (\r
1436aea4
MK
337 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
338 BlockIo2Ppi,\r
339 IndexBlockDevice,\r
340 Lba,\r
341 BufferSize,\r
342 Buffer\r
343 );\r
f9964c80
FT
344 } else {\r
345 Status = BlockIoPpi->ReadBlocks (\r
1436aea4
MK
346 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
347 BlockIoPpi,\r
348 IndexBlockDevice,\r
349 Lba,\r
350 BufferSize,\r
351 Buffer\r
352 );\r
f9964c80 353 }\r
1436aea4 354\r
30c00a1c 355 if (EFI_ERROR (Status)) {\r
356 return Status;\r
357 }\r
358\r
1436aea4
MK
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
30c00a1c 361 break;\r
362 }\r
363\r
364 if (StartOfVolume) {\r
365 OriginalLBA = Lba;\r
366 StartOfVolume = FALSE;\r
367 }\r
368\r
1436aea4 369 Type = *(UINT8 *)(Buffer + PEI_CD_EXPRESS_VOLUME_TYPE_OFFSET);\r
30c00a1c 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
1436aea4 386 VolumeSpaceSize = *(UINT32 *)(Buffer + PEI_CD_EXPRESS_VOLUME_SPACE_OFFSET);\r
30c00a1c 387\r
1436aea4
MK
388 RoorDirRecord = (PEI_CD_EXPRESS_DIR_FILE_RECORD *)(Buffer + PEI_CD_EXPRESS_ROOT_DIR_RECORD_OFFSET);\r
389 RootDirLBA = RoorDirRecord->LocationOfExtent[0];\r
30c00a1c 390\r
1436aea4 391 Status = RetrieveCapsuleFileFromRoot (PrivateData, BlockIoPpi, BlockIo2Ppi, IndexBlockDevice, RootDirLBA);\r
30c00a1c 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
f9964c80 410 @param BlockIo2Ppi The Block IO 2 PPI used to access the volume.\r
30c00a1c 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
d1102dba 416 @retval Others\r
30c00a1c 417\r
418**/\r
419EFI_STATUS\r
420EFIAPI\r
421RetrieveCapsuleFileFromRoot (\r
1436aea4
MK
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
30c00a1c 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
1436aea4
MK
435 Buffer = PrivateData->BlockBuffer;\r
436 BufferSize = PEI_CD_BLOCK_SIZE;\r
30c00a1c 437\r
438 SetMem (Buffer, BufferSize, 0);\r
439\r
f9964c80
FT
440 if (BlockIo2Ppi != NULL) {\r
441 Status = BlockIo2Ppi->ReadBlocks (\r
1436aea4
MK
442 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
443 BlockIo2Ppi,\r
444 IndexBlockDevice,\r
445 Lba,\r
446 BufferSize,\r
447 Buffer\r
448 );\r
f9964c80
FT
449 } else {\r
450 Status = BlockIoPpi->ReadBlocks (\r
1436aea4
MK
451 (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (),\r
452 BlockIoPpi,\r
453 IndexBlockDevice,\r
454 Lba,\r
455 BufferSize,\r
456 Buffer\r
457 );\r
f9964c80 458 }\r
1436aea4 459\r
30c00a1c 460 if (EFI_ERROR (Status)) {\r
461 return Status;\r
462 }\r
463\r
464 while (1) {\r
1436aea4 465 FileRecord = (PEI_CD_EXPRESS_DIR_FILE_RECORD *)Buffer;\r
30c00a1c 466\r
467 if (FileRecord->Length == 0) {\r
468 break;\r
469 }\r
1436aea4 470\r
30c00a1c 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
97533607 485 if (Index != mRecoveryFileNameSize - 1) {\r
30c00a1c 486 Buffer += FileRecord->Length;\r
487 continue;\r
488 }\r
489\r
97533607 490 if (!StringCmp (FileRecord->FileID, (UINT8 *)mRecoveryFileName, mRecoveryFileNameSize - 1, FALSE)) {\r
30c00a1c 491 Buffer += FileRecord->Length;\r
492 continue;\r
493 }\r
494\r
1436aea4 495 PrivateData->CapsuleData[PrivateData->CapsuleCount].CapsuleStartLBA = FileRecord->LocationOfExtent[0];\r
9381ad87 496 PrivateData->CapsuleData[PrivateData->CapsuleCount].CapsuleBlockAlignedSize =\r
30c00a1c 497 (\r
1436aea4
MK
498 FileRecord->DataLength[0] /\r
499 PEI_CD_BLOCK_SIZE +\r
500 1\r
30c00a1c 501 ) *\r
502 PEI_CD_BLOCK_SIZE;\r
9381ad87 503 PrivateData->CapsuleData[PrivateData->CapsuleCount].CapsuleSize = FileRecord->DataLength[0];\r
30c00a1c 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
d1102dba
LG
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
30c00a1c 517 priority.\r
518\r
d1102dba 519 @param[in] PeiServices General-purpose services that are available\r
30c00a1c 520 to every PEIM\r
521 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI\r
522 instance.\r
d1102dba
LG
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
30c00a1c 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
1436aea4
MK
537 IN EFI_PEI_SERVICES **PeiServices,\r
538 IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This,\r
539 OUT UINTN *NumberRecoveryCapsules\r
30c00a1c 540 )\r
541{\r
1436aea4 542 PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData;\r
30c00a1c 543\r
544 PrivateData = PEI_CD_EXPRESS_PRIVATE_DATA_FROM_THIS (This);\r
f9964c80
FT
545 UpdateBlocksAndVolumes (PrivateData, TRUE);\r
546 UpdateBlocksAndVolumes (PrivateData, FALSE);\r
30c00a1c 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
d1102dba 562 @param[in] This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI\r
30c00a1c 563 instance.\r
d1102dba
LG
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
30c00a1c 567 in NumberRecoveryCapsules.\r
d1102dba
LG
568 @param[out] Size A pointer to a caller-allocated UINTN in which\r
569 the size of the requested recovery module is\r
30c00a1c 570 returned.\r
d1102dba
LG
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
30c00a1c 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
1436aea4
MK
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
30c00a1c 589 )\r
590{\r
1436aea4
MK
591 PEI_CD_EXPRESS_PRIVATE_DATA *PrivateData;\r
592 UINTN NumberRecoveryCapsules;\r
593 EFI_STATUS Status;\r
30c00a1c 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
30c00a1c 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
1436aea4
MK
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
30c00a1c 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
30c00a1c 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
f9964c80 663 BlockIo2Ppi = PrivateData->CapsuleData[CapsuleInstance - 1].BlockIo2;\r
30c00a1c 664\r
f9964c80
FT
665 if (BlockIo2Ppi != NULL) {\r
666 Status = BlockIo2Ppi->ReadBlocks (\r
1436aea4
MK
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
f9964c80
FT
674 } else {\r
675 Status = BlockIoPpi->ReadBlocks (\r
1436aea4
MK
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
f9964c80 683 }\r
1436aea4 684\r
30c00a1c 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
1436aea4
MK
702 IN UINT8 *Source1,\r
703 IN UINT8 *Source2,\r
704 IN UINTN Size,\r
705 IN BOOLEAN CaseSensitive\r
30c00a1c 706 )\r
707{\r
1436aea4
MK
708 UINTN Index;\r
709 UINT8 Dif;\r
30c00a1c 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
1436aea4 717 Dif = (UINT8)((Source1[Index] > Source2[Index]) ? (Source1[Index] - Source2[Index]) : (Source2[Index] - Source1[Index]));\r
30c00a1c 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