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