]> git.proxmox.com Git - mirror_edk2.git/blob - Vlv2TbltDevicePkg/PlatformInitPei/Recovery.c
BaseTools: Fix corner-cases of --hash feature
[mirror_edk2.git] / Vlv2TbltDevicePkg / PlatformInitPei / Recovery.c
1 /** @file
2
3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7
8
9 Module Name:
10
11
12 Recovery.c
13
14 Abstract:
15
16 Tiano PEIM to provide the platform recovery functionality.
17
18 --*/
19
20 #include "PlatformEarlyInit.h"
21
22 #define PEI_FVMAIN_COMPACT_GUID \
23 {0x4A538818, 0x5AE0, 0x4eb2, 0xB2, 0xEB, 0x48, 0x8b, 0x23, 0x65, 0x70, 0x22};
24
25 EFI_GUID FvMainCompactFileGuid = PEI_FVMAIN_COMPACT_GUID;
26
27 //
28 // Required Service
29 //
30 EFI_STATUS
31 EFIAPI
32 PlatformRecoveryModule (
33 IN CONST EFI_PEI_SERVICES **PeiServices,
34 IN EFI_PEI_RECOVERY_MODULE_PPI *This
35 );
36
37 //
38 // Module globals
39 //
40
41 typedef struct {
42 EFI_GUID CapsuleGuid;
43 UINT32 HeaderSize;
44 UINT32 Flags;
45 UINT32 CapsuleImageSize;
46 UINT32 SequenceNumber;
47 EFI_GUID InstanceId;
48 UINT32 OffsetToSplitInformation;
49 UINT32 OffsetToCapsuleBody;
50 UINT32 OffsetToOemDefinedHeader;
51 UINT32 OffsetToAuthorInformation;
52 UINT32 OffsetToRevisionInformation;
53 UINT32 OffsetToShortDescription;
54 UINT32 OffsetToLongDescription;
55 UINT32 OffsetToApplicableDevices;
56 } OLD_EFI_CAPSULE_HEADER;
57
58
59 static EFI_PEI_RECOVERY_MODULE_PPI mRecoveryPpi = {
60 PlatformRecoveryModule
61 };
62
63 static EFI_PEI_PPI_DESCRIPTOR mRecoveryPpiList = {
64 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
65 &gEfiPeiRecoveryModulePpiGuid,
66 &mRecoveryPpi
67 };
68
69 /**
70 Provide the functionality of the Recovery Module.
71
72 @param PeiServices General purpose services available to every PEIM.
73
74 @retval Status EFI_SUCCESS if the interface could be successfully
75 installed
76
77 **/
78 EFI_STATUS
79 EFIAPI
80 PeimInitializeRecovery (
81 IN CONST EFI_PEI_SERVICES **PeiServices
82 )
83 {
84 EFI_STATUS Status;
85
86 Status = (*PeiServices)->InstallPpi (
87 PeiServices,
88 &mRecoveryPpiList
89 );
90
91 return Status;
92 }
93
94 /**
95 Provide the functionality of the Ea Recovery Module.
96
97 @param PeiServices General purpose services available to every PEIM.
98 @param This Pointer to PEI_RECOVERY_MODULE_INTERFACE.
99
100 @retval EFI_SUCCESS If the interface could be successfully
101 installed.
102 @retval EFI_UNSUPPORTED Not supported.
103
104 **/
105 EFI_STATUS
106 EFIAPI
107 PlatformRecoveryModule (
108 IN CONST EFI_PEI_SERVICES **PeiServices,
109 IN EFI_PEI_RECOVERY_MODULE_PPI *This
110 )
111 {
112 EFI_STATUS Status;
113 EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *DeviceRecoveryModule;
114 UINTN NumberOfImageProviders;
115 BOOLEAN ProviderAvailable;
116 UINTN NumberRecoveryCapsules;
117 UINTN RecoveryCapsuleSize;
118 EFI_GUID DeviceId;
119 BOOLEAN ImageFound;
120 EFI_PHYSICAL_ADDRESS Address;
121 VOID *Buffer;
122 OLD_EFI_CAPSULE_HEADER *CapsuleHeader;
123 EFI_PEI_HOB_POINTERS Hob;
124 EFI_PEI_HOB_POINTERS HobOld;
125 EFI_HOB_CAPSULE_VOLUME *CapsuleHob;
126 BOOLEAN HobUpdate;
127 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
128 UINTN Index;
129 BOOLEAN FoundFvMain;
130 BOOLEAN FoundCapsule;
131 static EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID;
132 EFI_PEI_STALL_PPI *StallPpi;
133
134 (*PeiServices)->ReportStatusCode (
135 PeiServices,
136 EFI_PROGRESS_CODE,
137 EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_RECOVERY_BEGIN,
138 0,
139 NULL,
140 NULL
141 );
142
143 Status = (**PeiServices).LocatePpi (
144 PeiServices,
145 &gEfiPeiStallPpiGuid,
146 0,
147 NULL,
148 &StallPpi
149 );
150 ASSERT_EFI_ERROR (Status);
151
152 StallPpi->Stall(
153 PeiServices,
154 StallPpi,
155 5000000
156 );
157
158
159 Index = 0;
160
161 Status = EFI_SUCCESS;
162 HobUpdate = FALSE;
163
164 ProviderAvailable = TRUE;
165 ImageFound = FALSE;
166 NumberOfImageProviders = 0;
167
168 DeviceRecoveryModule = NULL;
169
170 FoundCapsule = FALSE;
171 FoundFvMain = FALSE;
172
173 DEBUG ((EFI_D_ERROR | EFI_D_LOAD, "Recovery Entry\n"));
174
175 //
176 // Search the platform for some recovery capsule if the DXE IPL
177 // discovered a recovery condition and has requested a load.
178 //
179 while (ProviderAvailable == TRUE) {
180
181 Status = (*PeiServices)->LocatePpi (
182 PeiServices,
183 &gEfiPeiDeviceRecoveryModulePpiGuid,
184 Index,
185 NULL,
186 &DeviceRecoveryModule
187 );
188
189 if (!EFI_ERROR (Status)) {
190 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Device Recovery PPI located\n"));
191 NumberOfImageProviders++;
192
193 Status = DeviceRecoveryModule->GetNumberRecoveryCapsules (
194 (EFI_PEI_SERVICES**)PeiServices,
195 DeviceRecoveryModule,
196 &NumberRecoveryCapsules
197 );
198
199 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Number Of Recovery Capsules: %d\n", NumberRecoveryCapsules));
200
201 if (NumberRecoveryCapsules == 0) {
202 Index++;
203 } else {
204 break;
205 }
206 } else {
207 ProviderAvailable = FALSE;
208 }
209 }
210
211 //
212 // If there is an image provider, get the capsule ID
213 //
214 if (ProviderAvailable) {
215 RecoveryCapsuleSize = 0;
216
217 Status = DeviceRecoveryModule->GetRecoveryCapsuleInfo (
218 (EFI_PEI_SERVICES**)PeiServices,
219 DeviceRecoveryModule,
220 0,
221 &RecoveryCapsuleSize,
222 &DeviceId
223 );
224
225 if (EFI_ERROR (Status)) {
226 return Status;
227 }
228
229 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Capsule Size: %d\n", RecoveryCapsuleSize));
230
231 //
232 // Only support the 2 capsule types known
233 // Future enhancement is to rank-order the selection
234 //
235 if ((!CompareGuid (&DeviceId, &gRecoveryOnFatIdeDiskGuid)) &&
236 (!CompareGuid (&DeviceId, &gRecoveryOnFatFloppyDiskGuid)) &&
237 (!CompareGuid (&DeviceId, &gRecoveryOnDataCdGuid)) &&
238 (!CompareGuid (&DeviceId, &gRecoveryOnFatUsbDiskGuid))
239 ) {
240 return EFI_UNSUPPORTED;
241 }
242
243 Buffer = NULL;
244 Status = (*PeiServices)->AllocatePages (
245 PeiServices,
246 EfiBootServicesCode,
247 (RecoveryCapsuleSize - 1) / 0x1000 + 1,
248 &Address
249 );
250
251 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "AllocatePage Returns: %r\n", Status));
252
253 if (EFI_ERROR(Status)) {
254 return Status;
255 }
256
257 Buffer = (UINT8 *) (UINTN) Address;
258
259 (*PeiServices)->ReportStatusCode (
260 PeiServices,
261 EFI_PROGRESS_CODE,
262 EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_CAPSULE_LOAD,
263 0,
264 NULL,
265 NULL
266 );
267
268 Status = DeviceRecoveryModule->LoadRecoveryCapsule (
269 (EFI_PEI_SERVICES**)PeiServices,
270 DeviceRecoveryModule,
271 0,
272 Buffer
273 );
274
275 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "LoadRecoveryCapsule Returns: %r\n", Status));
276
277 if (EFI_ERROR (Status)) {
278 return Status;
279 }
280
281 //
282 // Update FV Hob if found
283 //
284 Status = (*PeiServices)->GetHobList (PeiServices, &Hob.Raw);
285 HobOld.Raw = Hob.Raw;
286 while (!END_OF_HOB_LIST (Hob)) {
287 if (Hob.Header->HobType == EFI_HOB_TYPE_FV) {
288 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Hob FV Length: %x\n", Hob.FirmwareVolume->Length));
289 //
290 // BUGBUG Why is it a FV hob if it is greater than 0x50000?
291 //
292 if (Hob.FirmwareVolume->Length > 0x50000) {
293 HobUpdate = TRUE;
294 //
295 // This looks like the Hob we are interested in
296 //
297 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Hob Updated\n"));
298 Hob.FirmwareVolume->BaseAddress = (UINTN) Buffer;
299 Hob.FirmwareVolume->Length = RecoveryCapsuleSize;
300 }
301 }
302 Hob.Raw = GET_NEXT_HOB (Hob);
303 }
304
305 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Buffer;
306 CapsuleHeader = (OLD_EFI_CAPSULE_HEADER *)Buffer;
307
308 //
309 // Check if top of file is a capsule
310 //
311 if (CompareGuid ((EFI_GUID *)CapsuleHeader, &mEfiCapsuleHeaderGuid)) {
312 FoundCapsule = TRUE;
313 } else if (FvHeader->Signature == EFI_FVH_SIGNATURE) {
314 //
315 // Assume the Firmware volume is a "FVMAIN" image
316 //
317 FoundFvMain = TRUE;
318 }
319
320 if (FoundFvMain) {
321 //
322 // build FV Hob if it is not built before
323 //
324 if (!HobUpdate) {
325 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "FV Hob is not found, Build FV Hob then..\n"));
326
327 BuildFvHob (
328 (UINTN)FvHeader,
329 FvHeader->FvLength
330 );
331 }
332 }
333
334 if (FoundCapsule) {
335 //
336 // Build capsule hob
337 //
338 Status = (*PeiServices)->CreateHob (
339 PeiServices,
340 EFI_HOB_TYPE_CV,
341 sizeof (EFI_HOB_CAPSULE_VOLUME),
342 &CapsuleHob
343 );
344 if (EFI_ERROR (Status)) {
345 return Status;
346 }
347 CapsuleHob->BaseAddress = (UINT64)((UINTN)CapsuleHeader + (UINTN)CapsuleHeader->OffsetToCapsuleBody);
348 CapsuleHob->Length = (UINT64)((UINTN)CapsuleHeader->CapsuleImageSize -(UINTN)CapsuleHeader->OffsetToCapsuleBody);
349 (*PeiServices)->ReportStatusCode (
350 PeiServices,
351 EFI_PROGRESS_CODE,
352 EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEIM_PC_CAPSULE_START,
353 0,
354 NULL,
355 NULL
356 );
357 }
358 }
359 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Recovery Module Returning: %r\n", Status));
360 return Status;
361 }