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