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