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