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