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