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