]> git.proxmox.com Git - mirror_edk2.git/blame - QuarkPlatformPkg/Platform/Pei/PlatformInit/Generic/Recovery.c
PcAtChipsetPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / QuarkPlatformPkg / Platform / Pei / PlatformInit / Generic / Recovery.c
CommitLineData
b303605e
MK
1/** @file\r
2Install Platform EFI_PEI_RECOVERY_MODULE_PPI and Implementation of\r
3EFI_PEI_LOAD_RECOVERY_CAPSULE service.\r
4\r
fb308fdb 5Copyright (c) 2013-2016 Intel Corporation.\r
b303605e
MK
6\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full 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 "CommonHeader.h"\r
18#include "PlatformEarlyInit.h"\r
19\r
20#include <Ppi/BlockIo.h>\r
21\r
22//\r
23// Capsule Types supported in this platform module\r
24//\r
25#include <Guid/CapsuleOnFatFloppyDisk.h>\r
26#include <Guid/CapsuleOnFatIdeDisk.h>\r
27#include <Guid/CapsuleOnFatUsbDisk.h>\r
28#include <Guid/CapsuleOnDataCD.h>\r
29#include <Guid/QuarkCapsuleGuid.h>\r
30\r
31#include <Ppi/RecoveryModule.h>\r
32#include <Ppi/DeviceRecoveryModule.h>\r
33\r
34#include <Library/PeiServicesLib.h>\r
35\r
36//\r
37// Required Service\r
38//\r
39EFI_STATUS\r
40EFIAPI\r
41PlatformRecoveryModule (\r
42 IN EFI_PEI_SERVICES **PeiServices,\r
43 IN EFI_PEI_RECOVERY_MODULE_PPI *This\r
44 );\r
45\r
46VOID\r
47AssertNoCapsulesError (\r
48 IN EFI_PEI_SERVICES **PeiServices\r
49 );\r
50\r
51VOID\r
52AssertMediaDeviceError (\r
53 IN EFI_PEI_SERVICES **PeiServices\r
54 );\r
55\r
56VOID\r
57ReportLoadCapsuleSuccess (\r
58 IN EFI_PEI_SERVICES **PeiServices\r
59 );\r
60\r
61VOID\r
62CheckIfMediaPresentOnBlockIoDevice (\r
63 IN EFI_PEI_SERVICES **PeiServices,\r
64 IN OUT BOOLEAN *MediaDeviceError,\r
65 IN OUT BOOLEAN *MediaPresent\r
66 );\r
67\r
68//\r
69// Module globals\r
70//\r
71EFI_PEI_RECOVERY_MODULE_PPI mRecoveryPpi = { PlatformRecoveryModule };\r
72\r
73EFI_PEI_PPI_DESCRIPTOR mRecoveryPpiList = {\r
74 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
75 &gEfiPeiRecoveryModulePpiGuid,\r
76 &mRecoveryPpi\r
77};\r
78\r
79EFI_STATUS\r
80EFIAPI\r
81PeimInitializeRecovery (\r
82 IN EFI_PEI_SERVICES **PeiServices\r
83 )\r
84/*++\r
85\r
86Routine Description:\r
87\r
88 Provide the functionality of the Recovery Module.\r
89\r
90Arguments:\r
91\r
92 PeiServices - General purpose services available to every PEIM.\r
93\r
94Returns:\r
95\r
96 EFI_SUCCESS - If the interface could be successfully\r
97 installed.\r
98\r
99--*/\r
100{\r
101 EFI_STATUS Status;\r
102\r
103 Status = PeiServicesInstallPpi (&mRecoveryPpiList);\r
104\r
105 return Status;\r
106}\r
107\r
108EFI_STATUS\r
109EFIAPI\r
110PlatformRecoveryModule (\r
111 IN EFI_PEI_SERVICES **PeiServices,\r
112 IN EFI_PEI_RECOVERY_MODULE_PPI *This\r
113 )\r
114/*++\r
115\r
116Routine Description:\r
117\r
118 Provide the functionality of the Platform Recovery Module.\r
119\r
120Arguments:\r
121\r
122 PeiServices - General purpose services available to every PEIM.\r
123 This - Pointer to EFI_PEI_RECOVERY_MODULE_PPI.\r
124\r
125Returns:\r
126\r
127 EFI_SUCCESS - If the interface could be successfully\r
128 installed.\r
129 EFI_UNSUPPORTED - Not supported.\r
130\r
131--*/\r
132{\r
133 EFI_STATUS Status;\r
134 EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *DeviceRecoveryModule;\r
135 UINTN NumberOfImageProviders;\r
136 BOOLEAN ProviderAvailable;\r
137 UINTN NumberRecoveryCapsules;\r
138 UINTN RecoveryCapsuleSize;\r
139 EFI_GUID DeviceId;\r
b303605e
MK
140 EFI_PHYSICAL_ADDRESS Address;\r
141 VOID *Buffer;\r
142 EFI_CAPSULE_HEADER *CapsuleHeader;\r
143 EFI_PEI_HOB_POINTERS Hob;\r
b303605e
MK
144 BOOLEAN HobUpdate;\r
145 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
146 UINTN Index;\r
b303605e
MK
147 EFI_GUID mEfiCapsuleHeaderGuid = QUARK_CAPSULE_GUID;\r
148\r
149 Index = 0;\r
150\r
151 Status = EFI_SUCCESS;\r
b303605e
MK
152 HobUpdate = FALSE;\r
153\r
154 ProviderAvailable = TRUE;\r
b303605e
MK
155 NumberOfImageProviders = 0;\r
156\r
157 DeviceRecoveryModule = NULL;\r
158\r
159 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Entry\n"));\r
160\r
161 //\r
162 // Search the platform for some recovery capsule if the DXE IPL\r
163 // discovered a recovery condition and has requested a load.\r
164 //\r
165 while (ProviderAvailable) {\r
166\r
167 Status = PeiServicesLocatePpi (\r
168 &gEfiPeiDeviceRecoveryModulePpiGuid,\r
169 Index,\r
170 NULL,\r
171 (VOID **)&DeviceRecoveryModule\r
172 );\r
173\r
174 if (!EFI_ERROR (Status)) {\r
175 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Device Recovery PPI located\n"));\r
176 NumberOfImageProviders++;\r
177\r
178 Status = DeviceRecoveryModule->GetNumberRecoveryCapsules (\r
179 PeiServices,\r
180 DeviceRecoveryModule,\r
181 &NumberRecoveryCapsules\r
182 );\r
183\r
184 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Number Of Recovery Capsules: %d\n", NumberRecoveryCapsules));\r
185\r
186 if (NumberRecoveryCapsules == 0) {\r
187 Index++;\r
188 } else {\r
189 break;\r
190 }\r
191 } else {\r
192 ProviderAvailable = FALSE;\r
193 }\r
194 }\r
195 //\r
196 // The number of recovery capsules is 0.\r
197 //\r
198 if (!ProviderAvailable) {\r
199 AssertNoCapsulesError (PeiServices);\r
200 }\r
201 //\r
202 // If there is an image provider, get the capsule ID\r
203 //\r
204 if (ProviderAvailable) {\r
205 RecoveryCapsuleSize = 0;\r
206 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
207 Status = DeviceRecoveryModule->GetRecoveryCapsuleInfo (\r
208 PeiServices,\r
209 DeviceRecoveryModule,\r
210 0,\r
211 &RecoveryCapsuleSize,\r
212 &DeviceId\r
213 );\r
214 } else {\r
215 Status = DeviceRecoveryModule->GetRecoveryCapsuleInfo (\r
216 PeiServices,\r
217 DeviceRecoveryModule,\r
218 1,\r
219 &RecoveryCapsuleSize,\r
220 &DeviceId\r
221 );\r
222\r
223\r
224 }\r
225\r
226 if (EFI_ERROR (Status)) {\r
227 return Status;\r
228 }\r
229\r
230 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Capsule Size: %d\n", RecoveryCapsuleSize));\r
231\r
232 //\r
233 // Only support the 2 capsule types known\r
234 // Future enhancement is to rank-order the selection\r
235 //\r
236 if ((!CompareGuid (&DeviceId, &gPeiCapsuleOnFatIdeDiskGuid)) &&\r
237 (!CompareGuid (&DeviceId, &gPeiCapsuleOnDataCDGuid)) &&\r
238 (!CompareGuid (&DeviceId, &gPeiCapsuleOnFatUsbDiskGuid))\r
239 ) {\r
240 return EFI_UNSUPPORTED;\r
241 }\r
242\r
243 Buffer = NULL;\r
244 Address = (UINTN) AllocatePages ((RecoveryCapsuleSize - 1) / 0x1000 + 1);\r
245 ASSERT (Address);\r
246\r
247 Buffer = (UINT8 *) (UINTN) Address;\r
248 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
249 Status = DeviceRecoveryModule->LoadRecoveryCapsule (\r
250 PeiServices,\r
251 DeviceRecoveryModule,\r
252 0,\r
253 Buffer\r
254 );\r
255 } else {\r
256 Status = DeviceRecoveryModule->LoadRecoveryCapsule (\r
257 PeiServices,\r
258 DeviceRecoveryModule,\r
259 1,\r
260 Buffer\r
261 );\r
262\r
263 }\r
264\r
265 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "LoadRecoveryCapsule Returns: %r\n", Status));\r
266\r
267 if (Status == EFI_DEVICE_ERROR) {\r
268 AssertMediaDeviceError (PeiServices);\r
269 }\r
270\r
271 if (EFI_ERROR (Status)) {\r
272 return Status;\r
273 } else {\r
274 ReportLoadCapsuleSuccess (PeiServices);\r
275 }\r
276\r
277 //\r
278 // Update FV Hob if found\r
279 //\r
280 Buffer = (VOID *)((UINT8 *) Buffer);\r
281 Status = PeiServicesGetHobList ((VOID **)&Hob.Raw);\r
b303605e
MK
282 while (!END_OF_HOB_LIST (Hob)) {\r
283 if (Hob.Header->HobType == EFI_HOB_TYPE_FV) {\r
284 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Hob FV Length: %x\n", Hob.FirmwareVolume->Length));\r
285\r
286 if (Hob.FirmwareVolume->BaseAddress == (UINTN) PcdGet32 (PcdFlashFvMainBase)) {\r
287 HobUpdate = TRUE;\r
288 //\r
289 // This looks like the Hob we are interested in\r
290 //\r
291 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Hob Updated\n"));\r
292 Hob.FirmwareVolume->BaseAddress = (UINTN) Buffer;\r
293 Hob.FirmwareVolume->Length = RecoveryCapsuleSize;\r
294 }\r
295 }\r
296\r
297 Hob.Raw = GET_NEXT_HOB (Hob);\r
298 }\r
299 //\r
300 // Check if the top of the file is a firmware volume header\r
301 //\r
302 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;\r
303 CapsuleHeader = (EFI_CAPSULE_HEADER *) Buffer;\r
304 if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
305 //\r
306 // build FV Hob if it is not built before\r
307 //\r
308 if (!HobUpdate) {\r
309 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "FV Hob is not found, Build FV Hob then..\n"));\r
310 BuildFvHob (\r
311 (UINTN) Buffer,\r
312 FvHeader->FvLength\r
313 );\r
314\r
315 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Install FV Info PPI..\n"));\r
316\r
317 PeiServicesInstallFvInfoPpi (\r
318 NULL,\r
319 Buffer,\r
320 (UINT32) FvHeader->FvLength,\r
321 NULL,\r
322 NULL\r
323 );\r
324 }\r
325 //\r
326 // Point to the location immediately after the FV.\r
327 //\r
328 CapsuleHeader = (EFI_CAPSULE_HEADER *) ((UINT8 *) Buffer + FvHeader->FvLength);\r
329 }\r
330\r
331 //\r
332 // Check if pointer is still within the buffer\r
333 //\r
334 if ((UINTN) CapsuleHeader < (UINTN) ((UINT8 *) Buffer + RecoveryCapsuleSize)) {\r
335\r
336 //\r
337 // Check if it is a capsule\r
338 //\r
339 if (CompareGuid ((EFI_GUID *) CapsuleHeader, &mEfiCapsuleHeaderGuid)) {\r
340\r
341 //\r
342 // Set bootmode to capsule update so the capsule hob gets the right bootmode in the hob header.\r
343 //\r
344 Status = PeiServicesSetBootMode (BOOT_ON_FLASH_UPDATE);\r
345 if (EFI_ERROR (Status)) {\r
346 return Status;\r
347 }\r
348\r
349 //\r
350 // Build capsule hob\r
351 //\r
352 BuildCvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader, (UINT64)CapsuleHeader->CapsuleImageSize);\r
353 }\r
354 }\r
355 }\r
356\r
357 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Module Returning: %r\n", Status));\r
358 return Status;\r
359}\r
360\r
361/*\r
362 AssertNoCapsulesError:\r
363 There were no recovery capsules found.\r
364 Case 1: Report the error that no recovery block io device/media is readable and assert.\r
365 Case 2: Report the error that there is no media present on any recovery block io device and assert.\r
366 Case 3: There is media present on some recovery block io device,\r
367 but there is no recovery capsule on it. Report the error and assert.\r
368*/\r
369VOID\r
370AssertNoCapsulesError (\r
371 IN EFI_PEI_SERVICES **PeiServices\r
372 )\r
373{\r
374 BOOLEAN MediaDeviceError;\r
375 BOOLEAN MediaPresent;\r
376\r
377 MediaDeviceError = TRUE;\r
378 MediaPresent = FALSE;\r
379\r
380 CheckIfMediaPresentOnBlockIoDevice (PeiServices, &MediaDeviceError, &MediaPresent);\r
381/* if (MediaDeviceError) {\r
382 ReportStatusCode (\r
383 (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),\r
384 (EFI_PERIPHERAL_RECOVERY_MEDIA | EFI_P_EC_MEDIA_DEVICE_ERROR)\r
385 );\r
386\r
387 } else if (!MediaPresent) {\r
388 ReportStatusCode (\r
389 (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),\r
390 (EFI_PERIPHERAL_RECOVERY_MEDIA | EFI_P_EC_MEDIA_NOT_PRESENT)\r
391 );\r
392\r
393 } else {\r
394 ReportStatusCode (\r
395 (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),\r
396 (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_EC_NO_RECOVERY_CAPSULE)\r
397 );\r
398 }*/\r
399 //\r
400 // Hang.\r
401 //\r
402 CpuDeadLoop();\r
403}\r
404\r
405#define MAX_BLOCK_IO_PPI 32\r
406\r
407/*\r
408 CheckIfMediaPresentOnBlockIoDevice:\r
409 Checks to see whether there was a media device error or to see if there is media present.\r
410*/\r
411VOID\r
412CheckIfMediaPresentOnBlockIoDevice (\r
413 IN EFI_PEI_SERVICES **PeiServices,\r
414 IN OUT BOOLEAN *MediaDeviceError,\r
415 IN OUT BOOLEAN *MediaPresent\r
416 )\r
417{\r
418 EFI_STATUS Status;\r
419 UINTN BlockIoPpiInstance;\r
420 EFI_PEI_RECOVERY_BLOCK_IO_PPI *BlockIoPpi;\r
421 UINTN NumberBlockDevices;\r
422 EFI_PEI_BLOCK_IO_MEDIA Media;\r
423\r
424 *MediaDeviceError = TRUE;\r
425 *MediaPresent = FALSE;\r
426\r
427 for (BlockIoPpiInstance = 0; BlockIoPpiInstance < MAX_BLOCK_IO_PPI; BlockIoPpiInstance++) {\r
428 Status = PeiServicesLocatePpi (\r
429 &gEfiPeiVirtualBlockIoPpiGuid,\r
430 BlockIoPpiInstance,\r
431 NULL,\r
432 (VOID **)&BlockIoPpi\r
433 );\r
434 if (EFI_ERROR (Status)) {\r
435 //\r
436 // Done with all Block Io Ppis\r
437 //\r
438 break;\r
439 }\r
440\r
441 Status = BlockIoPpi->GetNumberOfBlockDevices (\r
442 PeiServices,\r
443 BlockIoPpi,\r
444 &NumberBlockDevices\r
445 );\r
446 if (EFI_ERROR (Status) || (NumberBlockDevices == 0)) {\r
447 continue;\r
448 }\r
449 //\r
450 // Just retrieve the first block\r
451 //\r
452 Status = BlockIoPpi->GetBlockDeviceMediaInfo (\r
453 PeiServices,\r
454 BlockIoPpi,\r
455 0,\r
456 &Media\r
457 );\r
458 if (!EFI_ERROR (Status)) {\r
459 *MediaDeviceError = FALSE;\r
460 if (Media.MediaPresent) {\r
461 *MediaPresent = TRUE;\r
462 break;\r
463 }\r
464 }\r
465 }\r
466}\r
467\r
468VOID\r
469AssertMediaDeviceError (\r
470 IN EFI_PEI_SERVICES **PeiServices\r
471 )\r
472{\r
473/* ReportStatusCode (\r
474 (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),\r
475 (EFI_PERIPHERAL_RECOVERY_MEDIA | EFI_P_EC_MEDIA_DEVICE_ERROR)\r
476 );\r
477*/\r
478 CpuDeadLoop ();\r
479}\r
480\r
481VOID\r
482ReportLoadCapsuleSuccess (\r
483 IN EFI_PEI_SERVICES **PeiServices\r
484 )\r
485{\r
486 //\r
487 // EFI_SW_PEI_PC_CAPSULE_START: (from the status code spec):\r
488 // Loaded the recovery capsule. About to hand off control to the capsule.\r
489 //\r
490/* ReportStatusCode (\r
491 EFI_PROGRESS_CODE,\r
492 (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_CAPSULE_LOAD_SUCCESS)\r
493 );*/\r
494}\r
495\r