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