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