]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
MdeModulePkg DxeCapsuleLib: Use Attr to know whether reset is required
[mirror_edk2.git] / MdeModulePkg / Library / DxeCapsuleLibFmp / DxeCapsuleLib.c
CommitLineData
d2a16030
JY
1/** @file\r
2 DXE capsule library.\r
3\r
4 Caution: This module requires additional review when modified.\r
5 This module will have external input - capsule image.\r
6 This external input must be validated carefully to avoid security issue like\r
7 buffer overflow, integer overflow.\r
8\r
9 SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),\r
1ec2e7d0
MK
10 ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and\r
11 performs basic validation.\r
d2a16030 12\r
1ec2e7d0 13 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
d2a16030
JY
14 This program and the accompanying materials\r
15 are licensed and made available under the terms and conditions of the BSD License\r
16 which accompanies this distribution. The full text of the license may be found at\r
17 http://opensource.org/licenses/bsd-license.php\r
18\r
19 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
20 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
21\r
22**/\r
23\r
24#include <PiDxe.h>\r
25\r
d2a16030
JY
26#include <IndustryStandard/WindowsUxCapsule.h>\r
27\r
28#include <Guid/FmpCapsule.h>\r
29#include <Guid/SystemResourceTable.h>\r
30#include <Guid/EventGroup.h>\r
31\r
32#include <Library/BaseLib.h>\r
33#include <Library/DebugLib.h>\r
34#include <Library/BaseMemoryLib.h>\r
35#include <Library/DxeServicesTableLib.h>\r
36#include <Library/UefiBootServicesTableLib.h>\r
37#include <Library/UefiRuntimeServicesTableLib.h>\r
38#include <Library/MemoryAllocationLib.h>\r
39#include <Library/CapsuleLib.h>\r
40#include <Library/DevicePathLib.h>\r
41#include <Library/UefiLib.h>\r
42#include <Library/PcdLib.h>\r
1ec2e7d0 43#include <Library/BmpSupportLib.h>\r
d2a16030
JY
44\r
45#include <Protocol/GraphicsOutput.h>\r
46#include <Protocol/EsrtManagement.h>\r
47#include <Protocol/FirmwareManagement.h>\r
57476106 48#include <Protocol/FirmwareManagementProgress.h>\r
d2a16030
JY
49#include <Protocol/DevicePath.h>\r
50\r
03286264
DB
51EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable = NULL;\r
52BOOLEAN mIsVirtualAddrConverted = FALSE;\r
d948cf83 53\r
96b17e00
HW
54BOOLEAN mDxeCapsuleLibEndOfDxe = FALSE;\r
55EFI_EVENT mDxeCapsuleLibEndOfDxeEvent = NULL;\r
d2a16030 56\r
57476106
KM
57EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *mFmpProgress = NULL;\r
58\r
d2a16030
JY
59/**\r
60 Initialize capsule related variables.\r
61**/\r
62VOID\r
63InitCapsuleVariable (\r
64 VOID\r
65 );\r
66\r
d2a16030
JY
67/**\r
68 Record capsule status variable.\r
69\r
70 @param[in] CapsuleHeader The capsule image header\r
71 @param[in] CapsuleStatus The capsule process stauts\r
72\r
73 @retval EFI_SUCCESS The capsule status variable is recorded.\r
74 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\r
75**/\r
76EFI_STATUS\r
77RecordCapsuleStatusVariable (\r
78 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
79 IN EFI_STATUS CapsuleStatus\r
80 );\r
81\r
82/**\r
83 Record FMP capsule status variable.\r
84\r
85 @param[in] CapsuleHeader The capsule image header\r
86 @param[in] CapsuleStatus The capsule process stauts\r
87 @param[in] PayloadIndex FMP payload index\r
88 @param[in] ImageHeader FMP image header\r
8f6db161 89 @param[in] FmpDevicePath DevicePath associated with the FMP producer\r
d2a16030
JY
90\r
91 @retval EFI_SUCCESS The capsule status variable is recorded.\r
92 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\r
93**/\r
94EFI_STATUS\r
95RecordFmpCapsuleStatusVariable (\r
96 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
97 IN EFI_STATUS CapsuleStatus,\r
98 IN UINTN PayloadIndex,\r
8f6db161
JY
99 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
100 IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL\r
d2a16030
JY
101 );\r
102\r
103/**\r
104 Function indicate the current completion progress of the firmware\r
105 update. Platform may override with own specific progress function.\r
106\r
57476106
KM
107 @param[in] Completion A value between 1 and 100 indicating the current\r
108 completion progress of the firmware update\r
d2a16030 109\r
57476106
KM
110 @retval EFI_SUCESS The capsule update progress was updated.\r
111 @retval EFI_INVALID_PARAMETER Completion is greater than 100%.\r
d2a16030
JY
112**/\r
113EFI_STATUS\r
114EFIAPI\r
57476106 115UpdateImageProgress (\r
d2a16030 116 IN UINTN Completion\r
57476106 117 );\r
d2a16030
JY
118\r
119/**\r
120 Return if this CapsuleGuid is a FMP capsule GUID or not.\r
121\r
122 @param[in] CapsuleGuid A pointer to EFI_GUID\r
123\r
124 @retval TRUE It is a FMP capsule GUID.\r
125 @retval FALSE It is not a FMP capsule GUID.\r
126**/\r
127BOOLEAN\r
128IsFmpCapsuleGuid (\r
129 IN EFI_GUID *CapsuleGuid\r
130 )\r
131{\r
132 if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) {\r
133 return TRUE;\r
134 }\r
135\r
136 return FALSE;\r
137}\r
138\r
139/**\r
140 Validate if it is valid capsule header\r
141\r
142 Caution: This function may receive untrusted input.\r
143\r
144 This function assumes the caller provided correct CapsuleHeader pointer\r
145 and CapsuleSize.\r
146\r
147 This function validates the fields in EFI_CAPSULE_HEADER.\r
148\r
149 @param[in] CapsuleHeader Points to a capsule header.\r
150 @param[in] CapsuleSize Size of the whole capsule image.\r
151\r
152**/\r
153BOOLEAN\r
154IsValidCapsuleHeader (\r
155 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
156 IN UINT64 CapsuleSize\r
157 )\r
158{\r
159 if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {\r
160 return FALSE;\r
161 }\r
162 if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {\r
163 return FALSE;\r
164 }\r
165 return TRUE;\r
166}\r
167\r
168/**\r
169 Validate Fmp capsules layout.\r
170\r
171 Caution: This function may receive untrusted input.\r
172\r
173 This function assumes the caller validated the capsule by using\r
174 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.\r
175 The capsule buffer size is CapsuleHeader->CapsuleImageSize.\r
176\r
177 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\r
178 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.\r
179\r
180 This function need support nested FMP capsule.\r
181\r
182 @param[in] CapsuleHeader Points to a capsule header.\r
183 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.\r
184\r
185 @retval EFI_SUCESS Input capsule is a correct FMP capsule.\r
186 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.\r
187**/\r
188EFI_STATUS\r
189ValidateFmpCapsule (\r
190 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
191 OUT UINT16 *EmbeddedDriverCount OPTIONAL\r
192 )\r
193{\r
194 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
195 UINT8 *EndOfCapsule;\r
196 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
197 UINT8 *EndOfPayload;\r
198 UINT64 *ItemOffsetList;\r
199 UINT32 ItemNum;\r
200 UINTN Index;\r
201 UINTN FmpCapsuleSize;\r
202 UINTN FmpCapsuleHeaderSize;\r
203 UINT64 FmpImageSize;\r
204 UINTN FmpImageHeaderSize;\r
205\r
206 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
207 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), EmbeddedDriverCount);\r
208 }\r
209\r
210 if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {\r
211 DEBUG((DEBUG_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));\r
212 return EFI_INVALID_PARAMETER;\r
213 }\r
214\r
215 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
216 EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;\r
217 FmpCapsuleSize = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;\r
218\r
219 if (FmpCapsuleSize < sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {\r
220 DEBUG((DEBUG_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));\r
221 return EFI_INVALID_PARAMETER;\r
222 }\r
223\r
224 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\r
225 if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
226 DEBUG((DEBUG_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));\r
227 return EFI_INVALID_PARAMETER;\r
228 }\r
229 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
230\r
231 // No overflow\r
232 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
233\r
234 if ((FmpCapsuleSize - sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof(UINT64) < ItemNum) {\r
235 DEBUG((DEBUG_ERROR, "ItemNum(0x%x) too big\n", ItemNum));\r
236 return EFI_INVALID_PARAMETER;\r
237 }\r
238 FmpCapsuleHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64)*ItemNum;\r
239\r
240 // Check ItemOffsetList\r
241 for (Index = 0; Index < ItemNum; Index++) {\r
242 if (ItemOffsetList[Index] >= FmpCapsuleSize) {\r
243 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));\r
244 return EFI_INVALID_PARAMETER;\r
245 }\r
246 if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {\r
247 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));\r
248 return EFI_INVALID_PARAMETER;\r
249 }\r
250 //\r
251 // All the address in ItemOffsetList must be stored in ascending order\r
252 //\r
253 if (Index > 0) {\r
254 if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {\r
0f3cd8a9 255 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index - 1, ItemOffsetList[Index - 1]));\r
d2a16030
JY
256 return EFI_INVALID_PARAMETER;\r
257 }\r
258 }\r
259 }\r
260\r
261 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\r
262 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
263 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
264 if (Index == ItemNum - 1) {\r
265 EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);\r
266 } else {\r
267 EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];\r
268 }\r
269 FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];\r
270\r
d2a16030
JY
271 FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);\r
272 if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||\r
273 (ImageHeader->Version < 1)) {\r
274 DEBUG((DEBUG_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));\r
275 return EFI_INVALID_PARAMETER;\r
276 }\r
277 if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
278 FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
279 }\r
83e10078
SZ
280 if (FmpImageSize < FmpImageHeaderSize) {\r
281 DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize, FmpImageHeaderSize));\r
282 return EFI_INVALID_PARAMETER;\r
283 }\r
d2a16030
JY
284\r
285 // No overflow\r
286 if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {\r
287 DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) mismatch, UpdateImageSize(0x%x) UpdateVendorCodeSize(0x%x)\n", FmpImageSize, ImageHeader->UpdateImageSize, ImageHeader->UpdateVendorCodeSize));\r
288 return EFI_INVALID_PARAMETER;\r
289 }\r
290 }\r
291\r
292 if (ItemNum == 0) {\r
293 //\r
294 // No driver & payload element in FMP\r
295 //\r
296 EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);\r
297 if (EndOfPayload != EndOfCapsule) {\r
298 DEBUG((DEBUG_ERROR, "EndOfPayload(0x%x) mismatch, EndOfCapsule(0x%x)\n", EndOfPayload, EndOfCapsule));\r
299 return EFI_INVALID_PARAMETER;\r
300 }\r
301 return EFI_UNSUPPORTED;\r
302 }\r
303\r
304 if (EmbeddedDriverCount != NULL) {\r
305 *EmbeddedDriverCount = FmpCapsuleHeader->EmbeddedDriverCount;\r
306 }\r
307\r
308 return EFI_SUCCESS;\r
309}\r
310\r
d2a16030
JY
311/**\r
312 Those capsules supported by the firmwares.\r
313\r
314 Caution: This function may receive untrusted input.\r
315\r
316 @param[in] CapsuleHeader Points to a capsule header.\r
317\r
318 @retval EFI_SUCESS Input capsule is supported by firmware.\r
319 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.\r
320**/\r
321EFI_STATUS\r
322DisplayCapsuleImage (\r
323 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
324 )\r
325{\r
326 DISPLAY_DISPLAY_PAYLOAD *ImagePayload;\r
327 UINTN PayloadSize;\r
328 EFI_STATUS Status;\r
329 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
330 UINTN BltSize;\r
331 UINTN Height;\r
332 UINTN Width;\r
333 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
334\r
d0976b9a
RN
335 //\r
336 // UX capsule doesn't have extended header entries.\r
337 //\r
338 if (CapsuleHeader->HeaderSize != sizeof (EFI_CAPSULE_HEADER)) {\r
339 return EFI_UNSUPPORTED;\r
340 }\r
341 ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)((UINTN) CapsuleHeader + CapsuleHeader->HeaderSize);\r
342 //\r
343 // (CapsuleImageSize > HeaderSize) is guaranteed by IsValidCapsuleHeader().\r
344 //\r
345 PayloadSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;\r
346\r
347 //\r
348 // Make sure the image payload at least contain the DISPLAY_DISPLAY_PAYLOAD header.\r
349 // Further size check is performed by the logic translating BMP to GOP BLT.\r
350 //\r
351 if (PayloadSize <= sizeof (DISPLAY_DISPLAY_PAYLOAD)) {\r
352 return EFI_INVALID_PARAMETER;\r
353 }\r
d2a16030
JY
354\r
355 if (ImagePayload->Version != 1) {\r
356 return EFI_UNSUPPORTED;\r
357 }\r
358 if (CalculateCheckSum8((UINT8 *)CapsuleHeader, CapsuleHeader->CapsuleImageSize) != 0) {\r
359 return EFI_UNSUPPORTED;\r
360 }\r
361 //\r
362 // Only Support Bitmap by now\r
363 //\r
364 if (ImagePayload->ImageType != 0) {\r
365 return EFI_UNSUPPORTED;\r
366 }\r
367\r
368 //\r
369 // Try to open GOP\r
370 //\r
371 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);\r
372 if (EFI_ERROR (Status)) {\r
373 Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&GraphicsOutput);\r
374 if (EFI_ERROR(Status)) {\r
375 return EFI_UNSUPPORTED;\r
376 }\r
377 }\r
378\r
379 if (GraphicsOutput->Mode->Mode != ImagePayload->Mode) {\r
380 return EFI_UNSUPPORTED;\r
381 }\r
382\r
383 Blt = NULL;\r
384 Width = 0;\r
385 Height = 0;\r
1ec2e7d0 386 Status = TranslateBmpToGopBlt (\r
d2a16030
JY
387 ImagePayload + 1,\r
388 PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),\r
1ec2e7d0 389 &Blt,\r
d2a16030
JY
390 &BltSize,\r
391 &Height,\r
392 &Width\r
393 );\r
394\r
395 if (EFI_ERROR (Status)) {\r
396 return Status;\r
397 }\r
398\r
399 Status = GraphicsOutput->Blt (\r
400 GraphicsOutput,\r
401 Blt,\r
402 EfiBltBufferToVideo,\r
403 0,\r
404 0,\r
405 (UINTN) ImagePayload->OffsetX,\r
406 (UINTN) ImagePayload->OffsetY,\r
407 Width,\r
408 Height,\r
409 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
410 );\r
411\r
412 FreePool(Blt);\r
413\r
414 return Status;\r
415}\r
416\r
417/**\r
418 Dump FMP information.\r
419\r
420 @param[in] ImageInfoSize The size of ImageInfo, in bytes.\r
421 @param[in] ImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
422 @param[in] DescriptorVersion The version of EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
423 @param[in] DescriptorCount The count of EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
424 @param[in] DescriptorSize The size of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR, in bytes.\r
425 @param[in] PackageVersion The version of package.\r
426 @param[in] PackageVersionName The version name of package.\r
427**/\r
428VOID\r
429DumpFmpImageInfo (\r
430 IN UINTN ImageInfoSize,\r
431 IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,\r
432 IN UINT32 DescriptorVersion,\r
433 IN UINT8 DescriptorCount,\r
434 IN UINTN DescriptorSize,\r
435 IN UINT32 PackageVersion,\r
436 IN CHAR16 *PackageVersionName\r
437 )\r
438{\r
439 EFI_FIRMWARE_IMAGE_DESCRIPTOR *CurrentImageInfo;\r
440 UINTN Index;\r
441\r
442 DEBUG((DEBUG_VERBOSE, " DescriptorVersion - 0x%x\n", DescriptorVersion));\r
443 DEBUG((DEBUG_VERBOSE, " DescriptorCount - 0x%x\n", DescriptorCount));\r
444 DEBUG((DEBUG_VERBOSE, " DescriptorSize - 0x%x\n", DescriptorSize));\r
445 DEBUG((DEBUG_VERBOSE, " PackageVersion - 0x%x\n", PackageVersion));\r
446 DEBUG((DEBUG_VERBOSE, " PackageVersionName - %s\n\n", PackageVersionName));\r
447 CurrentImageInfo = ImageInfo;\r
448 for (Index = 0; Index < DescriptorCount; Index++) {\r
449 DEBUG((DEBUG_VERBOSE, " ImageDescriptor (%d)\n", Index));\r
450 DEBUG((DEBUG_VERBOSE, " ImageIndex - 0x%x\n", CurrentImageInfo->ImageIndex));\r
451 DEBUG((DEBUG_VERBOSE, " ImageTypeId - %g\n", &CurrentImageInfo->ImageTypeId));\r
452 DEBUG((DEBUG_VERBOSE, " ImageId - 0x%lx\n", CurrentImageInfo->ImageId));\r
453 DEBUG((DEBUG_VERBOSE, " ImageIdName - %s\n", CurrentImageInfo->ImageIdName));\r
454 DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", CurrentImageInfo->Version));\r
455 DEBUG((DEBUG_VERBOSE, " VersionName - %s\n", CurrentImageInfo->VersionName));\r
456 DEBUG((DEBUG_VERBOSE, " Size - 0x%x\n", CurrentImageInfo->Size));\r
457 DEBUG((DEBUG_VERBOSE, " AttributesSupported - 0x%lx\n", CurrentImageInfo->AttributesSupported));\r
458 DEBUG((DEBUG_VERBOSE, " AttributesSetting - 0x%lx\n", CurrentImageInfo->AttributesSetting));\r
459 DEBUG((DEBUG_VERBOSE, " Compatibilities - 0x%lx\n", CurrentImageInfo->Compatibilities));\r
460 if (DescriptorVersion > 1) {\r
461 DEBUG((DEBUG_VERBOSE, " LowestSupportedImageVersion - 0x%x\n", CurrentImageInfo->LowestSupportedImageVersion));\r
462 if (DescriptorVersion > 2) {\r
463 DEBUG((DEBUG_VERBOSE, " LastAttemptVersion - 0x%x\n", CurrentImageInfo->LastAttemptVersion));\r
464 DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", CurrentImageInfo->LastAttemptStatus));\r
465 DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", CurrentImageInfo->HardwareInstance));\r
466 }\r
467 }\r
468 //\r
469 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version\r
470 //\r
471 CurrentImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)CurrentImageInfo + DescriptorSize);\r
472 }\r
473}\r
474\r
475/**\r
476 Dump a non-nested FMP capsule.\r
477\r
478 @param[in] CapsuleHeader A pointer to CapsuleHeader\r
479**/\r
480VOID\r
481DumpFmpCapsule (\r
482 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
483 )\r
484{\r
485 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
486 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
487 UINTN Index;\r
488 UINT64 *ItemOffsetList;\r
489\r
490 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);\r
491\r
492 DEBUG((DEBUG_VERBOSE, "FmpCapsule:\n"));\r
493 DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", FmpCapsuleHeader->Version));\r
494 DEBUG((DEBUG_VERBOSE, " EmbeddedDriverCount - 0x%x\n", FmpCapsuleHeader->EmbeddedDriverCount));\r
495 DEBUG((DEBUG_VERBOSE, " PayloadItemCount - 0x%x\n", FmpCapsuleHeader->PayloadItemCount));\r
496\r
497 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
498 for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\r
499 DEBUG((DEBUG_VERBOSE, " ItemOffsetList[%d] - 0x%lx\n", Index, ItemOffsetList[Index]));\r
500 }\r
16f69227 501 for (; Index < (UINT32)FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; Index++) {\r
d2a16030
JY
502 DEBUG((DEBUG_VERBOSE, " ItemOffsetList[%d] - 0x%lx\n", Index, ItemOffsetList[Index]));\r
503 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
504\r
505 DEBUG((DEBUG_VERBOSE, " ImageHeader:\n"));\r
506 DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", ImageHeader->Version));\r
507 DEBUG((DEBUG_VERBOSE, " UpdateImageTypeId - %g\n", &ImageHeader->UpdateImageTypeId));\r
508 DEBUG((DEBUG_VERBOSE, " UpdateImageIndex - 0x%x\n", ImageHeader->UpdateImageIndex));\r
509 DEBUG((DEBUG_VERBOSE, " UpdateImageSize - 0x%x\n", ImageHeader->UpdateImageSize));\r
510 DEBUG((DEBUG_VERBOSE, " UpdateVendorCodeSize - 0x%x\n", ImageHeader->UpdateVendorCodeSize));\r
511 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
512 DEBUG((DEBUG_VERBOSE, " UpdateHardwareInstance - 0x%lx\n", ImageHeader->UpdateHardwareInstance));\r
513 }\r
514 }\r
515}\r
516\r
3f31ea1b
JY
517/**\r
518 Dump all FMP information.\r
519**/\r
520VOID\r
521DumpAllFmpInfo (\r
522 VOID\r
523 )\r
524{\r
525 EFI_STATUS Status;\r
526 EFI_HANDLE *HandleBuffer;\r
527 UINTN NumberOfHandles;\r
528 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
529 UINTN Index;\r
530 UINTN ImageInfoSize;\r
531 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
532 UINT32 FmpImageInfoDescriptorVer;\r
533 UINT8 FmpImageInfoCount;\r
534 UINTN DescriptorSize;\r
535 UINT32 PackageVersion;\r
536 CHAR16 *PackageVersionName;\r
537\r
538 Status = gBS->LocateHandleBuffer (\r
539 ByProtocol,\r
540 &gEfiFirmwareManagementProtocolGuid,\r
541 NULL,\r
542 &NumberOfHandles,\r
543 &HandleBuffer\r
544 );\r
545 if (EFI_ERROR(Status)) {\r
546 return ;\r
547 }\r
548\r
549 for (Index = 0; Index < NumberOfHandles; Index++) {\r
550 Status = gBS->HandleProtocol(\r
551 HandleBuffer[Index],\r
552 &gEfiFirmwareManagementProtocolGuid,\r
553 (VOID **)&Fmp\r
554 );\r
555 if (EFI_ERROR(Status)) {\r
556 continue;\r
557 }\r
558\r
559 ImageInfoSize = 0;\r
560 Status = Fmp->GetImageInfo (\r
561 Fmp,\r
562 &ImageInfoSize,\r
563 NULL,\r
564 NULL,\r
565 NULL,\r
566 NULL,\r
567 NULL,\r
568 NULL\r
569 );\r
570 if (Status != EFI_BUFFER_TOO_SMALL) {\r
571 continue;\r
572 }\r
573\r
574 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
575 if (FmpImageInfoBuf == NULL) {\r
576 continue;\r
577 }\r
578\r
579 PackageVersionName = NULL;\r
580 Status = Fmp->GetImageInfo (\r
581 Fmp,\r
582 &ImageInfoSize, // ImageInfoSize\r
583 FmpImageInfoBuf, // ImageInfo\r
584 &FmpImageInfoDescriptorVer, // DescriptorVersion\r
585 &FmpImageInfoCount, // DescriptorCount\r
586 &DescriptorSize, // DescriptorSize\r
587 &PackageVersion, // PackageVersion\r
588 &PackageVersionName // PackageVersionName\r
589 );\r
590 if (EFI_ERROR(Status)) {\r
591 FreePool(FmpImageInfoBuf);\r
592 continue;\r
593 }\r
594\r
595 DEBUG((DEBUG_INFO, "FMP (%d) ImageInfo:\n", Index));\r
596 DumpFmpImageInfo(\r
597 ImageInfoSize, // ImageInfoSize\r
598 FmpImageInfoBuf, // ImageInfo\r
599 FmpImageInfoDescriptorVer, // DescriptorVersion\r
600 FmpImageInfoCount, // DescriptorCount\r
601 DescriptorSize, // DescriptorSize\r
602 PackageVersion, // PackageVersion\r
603 PackageVersionName // PackageVersionName\r
604 );\r
605\r
606 if (PackageVersionName != NULL) {\r
607 FreePool(PackageVersionName);\r
608 }\r
609\r
610 FreePool(FmpImageInfoBuf);\r
611 }\r
612\r
613 return ;\r
614}\r
615\r
616/**\r
617 Get FMP handle by ImageTypeId and HardwareInstance.\r
618\r
619 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.\r
620 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.\r
69feaa37
SZ
621 @param[out] NoHandles The number of handles returned in HandleBuf.\r
622 @param[out] HandleBuf A pointer to the buffer to return the requested array of handles.\r
623 @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for\r
624 the requested array of handles.\r
625\r
626 @retval EFI_SUCCESS The array of handles and their reset required flag were returned in\r
627 HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf\r
628 was returned in NoHandles.\r
3f31ea1b
JY
629 @retval EFI_NOT_FOUND No handles match the search.\r
630 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.\r
631**/\r
632EFI_STATUS\r
633GetFmpHandleBufferByType (\r
634 IN EFI_GUID *UpdateImageTypeId,\r
635 IN UINT64 UpdateHardwareInstance,\r
69feaa37
SZ
636 OUT UINTN *NoHandles, OPTIONAL\r
637 OUT EFI_HANDLE **HandleBuf, OPTIONAL\r
638 OUT BOOLEAN **ResetRequiredBuf OPTIONAL\r
3f31ea1b
JY
639 )\r
640{\r
641 EFI_STATUS Status;\r
642 EFI_HANDLE *HandleBuffer;\r
643 UINTN NumberOfHandles;\r
644 EFI_HANDLE *MatchedHandleBuffer;\r
69feaa37 645 BOOLEAN *MatchedResetRequiredBuffer;\r
3f31ea1b
JY
646 UINTN MatchedNumberOfHandles;\r
647 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
648 UINTN Index;\r
649 UINTN ImageInfoSize;\r
650 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
651 UINT32 FmpImageInfoDescriptorVer;\r
652 UINT8 FmpImageInfoCount;\r
653 UINTN DescriptorSize;\r
654 UINT32 PackageVersion;\r
655 CHAR16 *PackageVersionName;\r
656 UINTN Index2;\r
657 EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;\r
658\r
69feaa37
SZ
659 if (NoHandles != NULL) {\r
660 *NoHandles = 0;\r
661 }\r
662 if (HandleBuf != NULL) {\r
663 *HandleBuf = NULL;\r
664 }\r
665 if (ResetRequiredBuf != NULL) {\r
666 *ResetRequiredBuf = NULL;\r
667 }\r
3f31ea1b
JY
668\r
669 Status = gBS->LocateHandleBuffer (\r
670 ByProtocol,\r
671 &gEfiFirmwareManagementProtocolGuid,\r
672 NULL,\r
673 &NumberOfHandles,\r
674 &HandleBuffer\r
675 );\r
676 if (EFI_ERROR(Status)) {\r
677 return Status;\r
678 }\r
679\r
680 MatchedNumberOfHandles = 0;\r
69feaa37
SZ
681\r
682 MatchedHandleBuffer = NULL;\r
683 if (HandleBuf != NULL) {\r
684 MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles);\r
685 if (MatchedHandleBuffer == NULL) {\r
686 FreePool (HandleBuffer);\r
687 return EFI_OUT_OF_RESOURCES;\r
688 }\r
689 }\r
690\r
691 MatchedResetRequiredBuffer = NULL;\r
692 if (ResetRequiredBuf != NULL) {\r
693 MatchedResetRequiredBuffer = AllocateZeroPool (sizeof(BOOLEAN) * NumberOfHandles);\r
694 if (MatchedResetRequiredBuffer == NULL) {\r
695 if (MatchedHandleBuffer != NULL) {\r
696 FreePool (MatchedHandleBuffer);\r
697 }\r
698 FreePool (HandleBuffer);\r
699 return EFI_OUT_OF_RESOURCES;\r
700 }\r
3f31ea1b
JY
701 }\r
702\r
703 for (Index = 0; Index < NumberOfHandles; Index++) {\r
704 Status = gBS->HandleProtocol(\r
705 HandleBuffer[Index],\r
706 &gEfiFirmwareManagementProtocolGuid,\r
707 (VOID **)&Fmp\r
708 );\r
709 if (EFI_ERROR(Status)) {\r
710 continue;\r
711 }\r
712\r
713 ImageInfoSize = 0;\r
714 Status = Fmp->GetImageInfo (\r
715 Fmp,\r
716 &ImageInfoSize,\r
717 NULL,\r
718 NULL,\r
719 NULL,\r
720 NULL,\r
721 NULL,\r
722 NULL\r
723 );\r
724 if (Status != EFI_BUFFER_TOO_SMALL) {\r
725 continue;\r
726 }\r
727\r
728 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
729 if (FmpImageInfoBuf == NULL) {\r
730 continue;\r
731 }\r
732\r
733 PackageVersionName = NULL;\r
734 Status = Fmp->GetImageInfo (\r
735 Fmp,\r
736 &ImageInfoSize, // ImageInfoSize\r
737 FmpImageInfoBuf, // ImageInfo\r
738 &FmpImageInfoDescriptorVer, // DescriptorVersion\r
739 &FmpImageInfoCount, // DescriptorCount\r
740 &DescriptorSize, // DescriptorSize\r
741 &PackageVersion, // PackageVersion\r
742 &PackageVersionName // PackageVersionName\r
743 );\r
744 if (EFI_ERROR(Status)) {\r
745 FreePool(FmpImageInfoBuf);\r
746 continue;\r
747 }\r
748\r
749 if (PackageVersionName != NULL) {\r
750 FreePool(PackageVersionName);\r
751 }\r
752\r
753 TempFmpImageInfo = FmpImageInfoBuf;\r
754 for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {\r
755 //\r
756 // Check if this FMP instance matches\r
757 //\r
758 if (CompareGuid(UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId)) {\r
759 if ((UpdateHardwareInstance == 0) ||\r
760 ((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) &&\r
761 (UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance))) {\r
69feaa37
SZ
762 if (MatchedHandleBuffer != NULL) {\r
763 MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];\r
764 }\r
765 if (MatchedResetRequiredBuffer != NULL) {\r
766 MatchedResetRequiredBuffer[MatchedNumberOfHandles] = (((TempFmpImageInfo->AttributesSupported & \r
767 IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) &&\r
768 ((TempFmpImageInfo->AttributesSetting &\r
769 IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0));\r
770 }\r
3f31ea1b
JY
771 MatchedNumberOfHandles++;\r
772 break;\r
773 }\r
774 }\r
775 TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);\r
776 }\r
777 FreePool(FmpImageInfoBuf);\r
778 }\r
779\r
780 if (MatchedNumberOfHandles == 0) {\r
781 return EFI_NOT_FOUND;\r
782 }\r
783\r
69feaa37
SZ
784 if (NoHandles != NULL) {\r
785 *NoHandles = MatchedNumberOfHandles;\r
786 }\r
787 if (HandleBuf != NULL) {\r
788 *HandleBuf = MatchedHandleBuffer;\r
789 }\r
790 if (ResetRequiredBuf != NULL) {\r
791 *ResetRequiredBuf = MatchedResetRequiredBuffer;\r
792 }\r
3f31ea1b
JY
793\r
794 return EFI_SUCCESS;\r
795}\r
796\r
797/**\r
798 Return FmpImageInfoDescriptorVer by an FMP handle.\r
799\r
800 @param[in] Handle A FMP handle.\r
801\r
802 @return FmpImageInfoDescriptorVer associated with the FMP.\r
803**/\r
804UINT32\r
805GetFmpImageInfoDescriptorVer (\r
806 IN EFI_HANDLE Handle\r
807 )\r
808{\r
809 EFI_STATUS Status;\r
810 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
811 UINTN ImageInfoSize;\r
812 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
813 UINT32 FmpImageInfoDescriptorVer;\r
814 UINT8 FmpImageInfoCount;\r
815 UINTN DescriptorSize;\r
816 UINT32 PackageVersion;\r
817 CHAR16 *PackageVersionName;\r
818\r
819 Status = gBS->HandleProtocol(\r
820 Handle,\r
821 &gEfiFirmwareManagementProtocolGuid,\r
822 (VOID **)&Fmp\r
823 );\r
824 if (EFI_ERROR(Status)) {\r
825 return 0;\r
826 }\r
827\r
828 ImageInfoSize = 0;\r
829 Status = Fmp->GetImageInfo (\r
830 Fmp,\r
831 &ImageInfoSize,\r
832 NULL,\r
833 NULL,\r
834 NULL,\r
835 NULL,\r
836 NULL,\r
837 NULL\r
838 );\r
839 if (Status != EFI_BUFFER_TOO_SMALL) {\r
840 return 0;\r
841 }\r
842\r
843 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
844 if (FmpImageInfoBuf == NULL) {\r
845 return 0;\r
846 }\r
847\r
848 PackageVersionName = NULL;\r
849 Status = Fmp->GetImageInfo (\r
850 Fmp,\r
851 &ImageInfoSize, // ImageInfoSize\r
852 FmpImageInfoBuf, // ImageInfo\r
853 &FmpImageInfoDescriptorVer, // DescriptorVersion\r
854 &FmpImageInfoCount, // DescriptorCount\r
855 &DescriptorSize, // DescriptorSize\r
856 &PackageVersion, // PackageVersion\r
857 &PackageVersionName // PackageVersionName\r
858 );\r
859 if (EFI_ERROR(Status)) {\r
860 FreePool(FmpImageInfoBuf);\r
861 return 0;\r
862 }\r
863 return FmpImageInfoDescriptorVer;\r
864}\r
865\r
866/**\r
867 Set FMP image data.\r
868\r
869 @param[in] Handle A FMP handle.\r
870 @param[in] ImageHeader The payload image header.\r
871 @param[in] PayloadIndex The index of the payload.\r
872\r
873 @return The status of FMP->SetImage.\r
874**/\r
875EFI_STATUS\r
876SetFmpImageData (\r
877 IN EFI_HANDLE Handle,\r
878 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
879 IN UINTN PayloadIndex\r
880 )\r
881{\r
882 EFI_STATUS Status;\r
883 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
884 UINT8 *Image;\r
885 VOID *VendorCode;\r
886 CHAR16 *AbortReason;\r
1342bd44 887 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback;\r
3f31ea1b
JY
888\r
889 Status = gBS->HandleProtocol(\r
890 Handle,\r
891 &gEfiFirmwareManagementProtocolGuid,\r
892 (VOID **)&Fmp\r
893 );\r
894 if (EFI_ERROR(Status)) {\r
895 return Status;\r
896 }\r
897\r
57476106
KM
898 //\r
899 // Lookup Firmware Management Progress Protocol before SetImage() is called\r
900 // This is an optional protocol that may not be present on Handle.\r
901 //\r
902 Status = gBS->HandleProtocol (\r
903 Handle,\r
904 &gEdkiiFirmwareManagementProgressProtocolGuid,\r
905 (VOID **)&mFmpProgress\r
906 );\r
907 if (EFI_ERROR (Status)) {\r
908 mFmpProgress = NULL;\r
909 }\r
910\r
3f31ea1b
JY
911 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
912 Image = (UINT8 *)(ImageHeader + 1);\r
913 } else {\r
914 //\r
915 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,\r
916 // Header should exclude UpdateHardwareInstance field\r
917 //\r
918 Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
919 }\r
920\r
921 if (ImageHeader->UpdateVendorCodeSize == 0) {\r
922 VendorCode = NULL;\r
923 } else {\r
924 VendorCode = Image + ImageHeader->UpdateImageSize;\r
925 }\r
926 AbortReason = NULL;\r
927 DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));\r
928 DEBUG((DEBUG_INFO, "ImageTypeId - %g, ", &ImageHeader->UpdateImageTypeId));\r
929 DEBUG((DEBUG_INFO, "PayloadIndex - 0x%x, ", PayloadIndex));\r
930 DEBUG((DEBUG_INFO, "ImageIndex - 0x%x ", ImageHeader->UpdateImageIndex));\r
931 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
932 DEBUG((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));\r
933 }\r
934 DEBUG((DEBUG_INFO, "\n"));\r
57476106
KM
935\r
936 //\r
937 // Before calling SetImage(), reset the progress bar to 0%\r
938 //\r
1342bd44
AB
939 ProgressCallback = UpdateImageProgress;\r
940 Status = UpdateImageProgress (0);\r
941 if (EFI_ERROR (Status)) {\r
942 ProgressCallback = NULL;\r
943 }\r
57476106 944\r
3f31ea1b
JY
945 Status = Fmp->SetImage(\r
946 Fmp,\r
947 ImageHeader->UpdateImageIndex, // ImageIndex\r
948 Image, // Image\r
949 ImageHeader->UpdateImageSize, // ImageSize\r
950 VendorCode, // VendorCode\r
1342bd44 951 ProgressCallback, // Progress\r
3f31ea1b
JY
952 &AbortReason // AbortReason\r
953 );\r
57476106
KM
954 //\r
955 // Set the progress bar to 100% after returning from SetImage()\r
956 //\r
1342bd44
AB
957 if (ProgressCallback != NULL) {\r
958 UpdateImageProgress (100);\r
959 }\r
57476106 960\r
3f31ea1b
JY
961 DEBUG((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));\r
962 if (AbortReason != NULL) {\r
963 DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));\r
964 FreePool(AbortReason);\r
965 }\r
966\r
57476106
KM
967 //\r
968 // Clear mFmpProgress after SetImage() returns\r
969 //\r
970 mFmpProgress = NULL;\r
971\r
3f31ea1b
JY
972 return Status;\r
973}\r
974\r
975/**\r
976 Start a UEFI image in the FMP payload.\r
977\r
978 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..\r
979 @param[in] ImageSize The size in bytes of ImageBuffer.\r
980\r
981 @return The status of gBS->LoadImage and gBS->StartImage.\r
982**/\r
983EFI_STATUS\r
984StartFmpImage (\r
985 IN VOID *ImageBuffer,\r
986 IN UINTN ImageSize\r
987 )\r
988{\r
989 MEMMAP_DEVICE_PATH MemMapNode;\r
990 EFI_STATUS Status;\r
991 EFI_HANDLE ImageHandle;\r
992 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;\r
993 UINTN ExitDataSize;\r
994\r
995 SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));\r
996 MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;\r
997 MemMapNode.Header.SubType = HW_MEMMAP_DP;\r
998 MemMapNode.MemoryType = EfiBootServicesCode;\r
999 MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBuffer;\r
1000 MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)ImageBuffer + ImageSize - 1);\r
1001\r
1002 DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);\r
1003 if (DriverDevicePath == NULL) {\r
1004 return EFI_OUT_OF_RESOURCES;\r
1005 }\r
1006\r
1007 DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));\r
1008 Status = gBS->LoadImage(\r
1009 FALSE,\r
1010 gImageHandle,\r
1011 DriverDevicePath,\r
1012 ImageBuffer,\r
1013 ImageSize,\r
1014 &ImageHandle\r
1015 );\r
1016 DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));\r
1017 if (EFI_ERROR(Status)) {\r
1018 FreePool(DriverDevicePath);\r
1019 return Status;\r
1020 }\r
1021\r
1022 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));\r
1023 Status = gBS->StartImage(\r
1024 ImageHandle,\r
1025 &ExitDataSize,\r
1026 NULL\r
1027 );\r
1028 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));\r
1029 if (EFI_ERROR(Status)) {\r
1030 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
1031 }\r
1032\r
1033 FreePool(DriverDevicePath);\r
1034 return Status;\r
1035}\r
1036\r
1037/**\r
1038 Record FMP capsule status.\r
1039\r
1040 @param[in] Handle A FMP handle.\r
1041 @param[in] CapsuleHeader The capsule image header\r
1042 @param[in] CapsuleStatus The capsule process stauts\r
1043 @param[in] PayloadIndex FMP payload index\r
1044 @param[in] ImageHeader FMP image header\r
1045**/\r
1046VOID\r
1047RecordFmpCapsuleStatus (\r
1048 IN EFI_HANDLE Handle, OPTIONAL\r
1049 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
1050 IN EFI_STATUS CapsuleStatus,\r
1051 IN UINTN PayloadIndex,\r
1052 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader\r
1053 )\r
1054{\r
1055 EFI_STATUS Status;\r
1056 EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath;\r
1057 UINT32 FmpImageInfoDescriptorVer;\r
1058 EFI_STATUS StatusEsrt;\r
1059 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
1060 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;\r
1061\r
1062 FmpDevicePath = NULL;\r
1063 if (Handle != NULL) {\r
1064 gBS->HandleProtocol(\r
1065 Handle,\r
1066 &gEfiDevicePathProtocolGuid,\r
1067 (VOID **)&FmpDevicePath\r
1068 );\r
1069 }\r
1070\r
1071 RecordFmpCapsuleStatusVariable (\r
1072 CapsuleHeader,\r
1073 CapsuleStatus,\r
1074 PayloadIndex,\r
1075 ImageHeader,\r
1076 FmpDevicePath\r
1077 );\r
1078\r
1079 //\r
1080 // Update corresponding ESRT entry LastAttemp Status\r
1081 //\r
1082 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
1083 if (EFI_ERROR (Status)) {\r
1084 return ;\r
1085 }\r
1086\r
1087 if (Handle == NULL) {\r
1088 return ;\r
1089 }\r
1090\r
1091 //\r
1092 // Update EsrtEntry For V1, V2 FMP instance.\r
1bf23e6b 1093 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface\r
3f31ea1b
JY
1094 //\r
1095 FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);\r
1096 if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {\r
1097 StatusEsrt = EsrtProtocol->GetEsrtEntry(&ImageHeader->UpdateImageTypeId, &EsrtEntry);\r
1098 if (!EFI_ERROR(StatusEsrt)){\r
1099 if (!EFI_ERROR(CapsuleStatus)) {\r
1100 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
1101 } else {\r
1102 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1103 }\r
1104 EsrtEntry.LastAttemptVersion = 0;\r
1105 EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);\r
1106 }\r
1107 }\r
1108}\r
1109\r
d2a16030
JY
1110/**\r
1111 Process Firmware management protocol data capsule.\r
1112\r
1113 This function assumes the caller validated the capsule by using\r
1114 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,\r
1115 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and\r
1116 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.\r
1117\r
1118 This function need support nested FMP capsule.\r
1119\r
69feaa37
SZ
1120 @param[in] CapsuleHeader Points to a capsule header.\r
1121 @param[out] ResetRequired Indicates whether reset is required or not.\r
d2a16030
JY
1122\r
1123 @retval EFI_SUCESS Process Capsule Image successfully.\r
1124 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
1125 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
1126 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
3f31ea1b 1127 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.\r
d2a16030
JY
1128**/\r
1129EFI_STATUS\r
1130ProcessFmpCapsuleImage (\r
69feaa37
SZ
1131 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
1132 OUT BOOLEAN *ResetRequired OPTIONAL\r
d2a16030
JY
1133 )\r
1134{\r
1135 EFI_STATUS Status;\r
d2a16030
JY
1136 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
1137 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
d2a16030
JY
1138 UINT64 *ItemOffsetList;\r
1139 UINT32 ItemNum;\r
1140 UINTN Index;\r
d2a16030 1141 EFI_HANDLE *HandleBuffer;\r
69feaa37 1142 BOOLEAN *ResetRequiredBuffer;\r
d2a16030 1143 UINTN NumberOfHandles;\r
d2a16030 1144 UINTN DriverLen;\r
3f31ea1b 1145 UINT64 UpdateHardwareInstance;\r
d2a16030 1146 UINTN Index2;\r
3f31ea1b
JY
1147 BOOLEAN NotReady;\r
1148 BOOLEAN Abort;\r
d2a16030
JY
1149\r
1150 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
69feaa37 1151 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);\r
d2a16030
JY
1152 }\r
1153\r
3f31ea1b
JY
1154 NotReady = FALSE;\r
1155 Abort = FALSE;\r
d2a16030
JY
1156\r
1157 DumpFmpCapsule(CapsuleHeader);\r
1158\r
1159 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
1160\r
1161 if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
1162 return EFI_INVALID_PARAMETER;\r
1163 }\r
1164 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
1165\r
1166 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
1167\r
1168 //\r
1169 // capsule in which driver count and payload count are both zero is not processed.\r
1170 //\r
1171 if (ItemNum == 0) {\r
d2a16030
JY
1172 return EFI_SUCCESS;\r
1173 }\r
1174\r
d2a16030
JY
1175 //\r
1176 // 1. Try to load & start all the drivers within capsule\r
1177 //\r
d2a16030 1178 for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\r
3f31ea1b
JY
1179 if ((FmpCapsuleHeader->PayloadItemCount == 0) &&\r
1180 (Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1)) {\r
d2a16030
JY
1181 //\r
1182 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER\r
1183 //\r
1184 DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];\r
1185 } else {\r
1186 DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];\r
1187 }\r
1188\r
3f31ea1b
JY
1189 Status = StartFmpImage (\r
1190 (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],\r
1191 DriverLen\r
1192 );\r
d2a16030
JY
1193 if (EFI_ERROR(Status)) {\r
1194 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
3f31ea1b 1195 return Status;\r
d2a16030
JY
1196 }\r
1197 }\r
1198\r
1199 //\r
1200 // 2. Route payload to right FMP instance\r
1201 //\r
1202 DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));\r
1203\r
3f31ea1b 1204 DumpAllFmpInfo ();\r
8f6db161 1205\r
3f31ea1b
JY
1206 //\r
1207 // Check all the payload entry in capsule payload list\r
1208 //\r
1209 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
1210 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
d2a16030 1211\r
3f31ea1b
JY
1212 UpdateHardwareInstance = 0;\r
1213 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
1214 UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;\r
1215 }\r
d2a16030 1216\r
3f31ea1b
JY
1217 Status = GetFmpHandleBufferByType (\r
1218 &ImageHeader->UpdateImageTypeId,\r
1219 UpdateHardwareInstance,\r
1220 &NumberOfHandles,\r
69feaa37
SZ
1221 &HandleBuffer,\r
1222 &ResetRequiredBuffer\r
3f31ea1b
JY
1223 );\r
1224 if (EFI_ERROR(Status)) {\r
1225 NotReady = TRUE;\r
1226 RecordFmpCapsuleStatus (\r
1227 NULL,\r
1228 CapsuleHeader,\r
1229 EFI_NOT_READY,\r
1230 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
1231 ImageHeader\r
1232 );\r
1233 continue;\r
1234 }\r
d2a16030 1235\r
3f31ea1b
JY
1236 for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {\r
1237 if (Abort) {\r
1238 RecordFmpCapsuleStatus (\r
1239 HandleBuffer[Index2],\r
1240 CapsuleHeader,\r
1241 EFI_ABORTED,\r
1242 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
1243 ImageHeader\r
1244 );\r
d2a16030
JY
1245 continue;\r
1246 }\r
1247\r
3f31ea1b
JY
1248 Status = SetFmpImageData (\r
1249 HandleBuffer[Index2],\r
1250 ImageHeader,\r
1251 Index - FmpCapsuleHeader->EmbeddedDriverCount\r
1252 );\r
1253 if (Status != EFI_SUCCESS) {\r
1254 Abort = TRUE;\r
69feaa37
SZ
1255 } else {\r
1256 if (ResetRequired != NULL) {\r
1257 *ResetRequired |= ResetRequiredBuffer[Index2];\r
1258 }\r
d2a16030
JY
1259 }\r
1260\r
3f31ea1b
JY
1261 RecordFmpCapsuleStatus (\r
1262 HandleBuffer[Index2],\r
1263 CapsuleHeader,\r
1264 Status,\r
1265 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
1266 ImageHeader\r
1267 );\r
d2a16030 1268 }\r
3f31ea1b
JY
1269 if (HandleBuffer != NULL) {\r
1270 FreePool(HandleBuffer);\r
d2a16030 1271 }\r
69feaa37
SZ
1272 if (ResetRequiredBuffer != NULL) {\r
1273 FreePool(ResetRequiredBuffer);\r
1274 }\r
d2a16030
JY
1275 }\r
1276\r
3f31ea1b
JY
1277 if (NotReady) {\r
1278 return EFI_NOT_READY;\r
d2a16030
JY
1279 }\r
1280\r
3f31ea1b
JY
1281 //\r
1282 // always return SUCCESS to indicate this capsule is processed.\r
1283 // The status of SetImage is recorded in capsule result variable.\r
1284 //\r
1285 return EFI_SUCCESS;\r
d2a16030
JY
1286}\r
1287\r
1288/**\r
1289 Return if there is a FMP header below capsule header.\r
1290\r
1291 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
1292\r
1293 @retval TRUE There is a FMP header below capsule header.\r
1294 @retval FALSE There is not a FMP header below capsule header\r
1295**/\r
1296BOOLEAN\r
1297IsNestedFmpCapsule (\r
1298 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1299 )\r
1300{\r
1301 EFI_STATUS Status;\r
d2a16030
JY
1302 EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;\r
1303 UINTN Index;\r
1304 BOOLEAN EsrtGuidFound;\r
1305 EFI_CAPSULE_HEADER *NestedCapsuleHeader;\r
1306 UINTN NestedCapsuleSize;\r
1307 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
1308 EFI_SYSTEM_RESOURCE_ENTRY Entry;\r
1309\r
1310 EsrtGuidFound = FALSE;\r
056563f1
JY
1311 if (mIsVirtualAddrConverted) {\r
1312 if(mEsrtTable != NULL) {\r
1313 EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);\r
1314 for (Index = 0; Index < mEsrtTable->FwResourceCount ; Index++, EsrtEntry++) {\r
d2a16030
JY
1315 if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {\r
1316 EsrtGuidFound = TRUE;\r
1317 break;\r
1318 }\r
1319 }\r
1320 }\r
056563f1
JY
1321 } else {\r
1322 //\r
1323 // Check ESRT protocol\r
1324 //\r
1325 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
1326 if (!EFI_ERROR(Status)) {\r
1327 Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);\r
1328 if (!EFI_ERROR(Status)) {\r
1329 EsrtGuidFound = TRUE;\r
1330 }\r
1331 }\r
1332\r
1333 //\r
7f0301e3 1334 // Check Firmware Management Protocols\r
056563f1
JY
1335 //\r
1336 if (!EsrtGuidFound) {\r
7f0301e3
KM
1337 Status = GetFmpHandleBufferByType (\r
1338 &CapsuleHeader->CapsuleGuid,\r
1339 0,\r
69feaa37
SZ
1340 NULL,\r
1341 NULL,\r
1342 NULL\r
7f0301e3 1343 );\r
056563f1 1344 if (!EFI_ERROR(Status)) {\r
7f0301e3
KM
1345 EsrtGuidFound = TRUE;\r
1346 }\r
056563f1 1347 }\r
d2a16030
JY
1348 }\r
1349 if (!EsrtGuidFound) {\r
1350 return FALSE;\r
1351 }\r
1352\r
1353 //\r
1354 // Check nested capsule header\r
1355 // FMP GUID after ESRT one\r
1356 //\r
1357 NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);\r
1358 NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;\r
1359 if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {\r
1360 return FALSE;\r
1361 }\r
1362 if (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {\r
1363 return FALSE;\r
1364 }\r
1365 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {\r
1366 return FALSE;\r
1367 }\r
1368 DEBUG ((DEBUG_INFO, "IsNestedFmpCapsule\n"));\r
1369 return TRUE;\r
1370}\r
1371\r
1372/**\r
1373 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.\r
1374\r
1375 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
1376\r
1377 @retval TRUE It is a system FMP.\r
1378 @retval FALSE It is a device FMP.\r
1379**/\r
1380BOOLEAN\r
1381IsFmpCapsule (\r
1382 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1383 )\r
1384{\r
1385 if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
1386 return TRUE;\r
1387 }\r
1388 if (IsNestedFmpCapsule(CapsuleHeader)) {\r
1389 return TRUE;\r
1390 }\r
1391 return FALSE;\r
1392}\r
1393\r
1394/**\r
1395 Those capsules supported by the firmwares.\r
1396\r
1397 Caution: This function may receive untrusted input.\r
1398\r
1399 @param[in] CapsuleHeader Points to a capsule header.\r
1400\r
1401 @retval EFI_SUCESS Input capsule is supported by firmware.\r
1402 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.\r
1403 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct\r
1404**/\r
1405EFI_STATUS\r
1406EFIAPI\r
1407SupportCapsuleImage (\r
1408 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1409 )\r
1410{\r
1411 //\r
1412 // check Display Capsule Guid\r
1413 //\r
1414 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
1415 return EFI_SUCCESS;\r
1416 }\r
1417\r
1418 if (IsFmpCapsule(CapsuleHeader)) {\r
1419 //\r
1420 // Check layout of FMP capsule\r
1421 //\r
1422 return ValidateFmpCapsule(CapsuleHeader, NULL);\r
1423 }\r
1424 DEBUG((DEBUG_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));\r
1425 return EFI_UNSUPPORTED;\r
1426}\r
1427\r
1428/**\r
1429 The firmware implements to process the capsule image.\r
1430\r
1431 Caution: This function may receive untrusted input.\r
1432\r
1433 @param[in] CapsuleHeader Points to a capsule header.\r
69feaa37 1434 @param[out] ResetRequired Indicates whether reset is required or not.\r
d2a16030
JY
1435\r
1436 @retval EFI_SUCESS Process Capsule Image successfully.\r
1437 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
1438 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
1439 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
1440**/\r
1441EFI_STATUS\r
1442EFIAPI\r
69feaa37
SZ
1443ProcessThisCapsuleImage (\r
1444 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
1445 OUT BOOLEAN *ResetRequired OPTIONAL\r
d2a16030
JY
1446 )\r
1447{\r
1448 EFI_STATUS Status;\r
d2a16030
JY
1449\r
1450 if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {\r
3f31ea1b 1451 RecordCapsuleStatusVariable(CapsuleHeader, EFI_UNSUPPORTED);\r
d2a16030
JY
1452 return EFI_UNSUPPORTED;\r
1453 }\r
1454\r
1455 //\r
1456 // Display image in firmware update display capsule\r
1457 //\r
1458 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
1459 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));\r
1460 Status = DisplayCapsuleImage(CapsuleHeader);\r
1461 RecordCapsuleStatusVariable(CapsuleHeader, Status);\r
1462 return Status;\r
1463 }\r
1464\r
1465 //\r
1466 // Check FMP capsule layout\r
1467 //\r
1468 if (IsFmpCapsule (CapsuleHeader)) {\r
1469 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));\r
1470 DEBUG((DEBUG_INFO, "ValidateFmpCapsule ...\n"));\r
1471 Status = ValidateFmpCapsule(CapsuleHeader, NULL);\r
1472 DEBUG((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));\r
1473 if (EFI_ERROR(Status)) {\r
3f31ea1b 1474 RecordCapsuleStatusVariable(CapsuleHeader, Status);\r
d2a16030
JY
1475 return Status;\r
1476 }\r
1477\r
1478 //\r
a891bd73 1479 // Process EFI FMP Capsule\r
d2a16030
JY
1480 //\r
1481 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));\r
69feaa37 1482 Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);\r
d2a16030
JY
1483 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));\r
1484\r
d2a16030
JY
1485 return Status;\r
1486 }\r
1487\r
1488 return EFI_UNSUPPORTED;\r
1489}\r
1490\r
69feaa37
SZ
1491/**\r
1492 The firmware implements to process the capsule image.\r
1493\r
1494 Caution: This function may receive untrusted input.\r
1495\r
1496 @param[in] CapsuleHeader Points to a capsule header.\r
1497\r
1498 @retval EFI_SUCESS Process Capsule Image successfully.\r
1499 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
1500 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
1501 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
1502**/\r
1503EFI_STATUS\r
1504EFIAPI\r
1505ProcessCapsuleImage (\r
1506 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1507 )\r
1508{\r
1509 return ProcessThisCapsuleImage (CapsuleHeader, NULL);\r
1510}\r
1511\r
d2a16030
JY
1512/**\r
1513 Callback function executed when the EndOfDxe event group is signaled.\r
1514\r
1515 @param[in] Event Event whose notification function is being invoked.\r
1516 @param[in] Context The pointer to the notification function's context, which\r
1517 is implementation-dependent.\r
1518**/\r
1519VOID\r
1520EFIAPI\r
1521DxeCapsuleLibEndOfDxe (\r
1522 IN EFI_EVENT Event,\r
1523 IN VOID *Context\r
1524 )\r
1525{\r
1526 mDxeCapsuleLibEndOfDxe = TRUE;\r
1527}\r
1528\r
1529/**\r
1530 The constructor function.\r
1531\r
1532 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1533 @param[in] SystemTable A pointer to the EFI System Table.\r
1534\r
1535 @retval EFI_SUCCESS The constructor successfully .\r
1536**/\r
1537EFI_STATUS\r
1538EFIAPI\r
1539DxeCapsuleLibConstructor (\r
1540 IN EFI_HANDLE ImageHandle,\r
1541 IN EFI_SYSTEM_TABLE *SystemTable\r
1542 )\r
1543{\r
d2a16030
JY
1544 EFI_STATUS Status;\r
1545\r
1546 Status = gBS->CreateEventEx (\r
1547 EVT_NOTIFY_SIGNAL,\r
1548 TPL_CALLBACK,\r
1549 DxeCapsuleLibEndOfDxe,\r
1550 NULL,\r
1551 &gEfiEndOfDxeEventGroupGuid,\r
96b17e00 1552 &mDxeCapsuleLibEndOfDxeEvent\r
d2a16030
JY
1553 );\r
1554 ASSERT_EFI_ERROR (Status);\r
1555\r
1556 InitCapsuleVariable();\r
1557\r
1558 return EFI_SUCCESS;\r
1559}\r
96b17e00
HW
1560\r
1561/**\r
1562 The destructor function closes the End of DXE event.\r
1563\r
1564 @param ImageHandle The firmware allocated handle for the EFI image.\r
1565 @param SystemTable A pointer to the EFI System Table.\r
1566\r
1567 @retval EFI_SUCCESS The destructor completed successfully.\r
1568**/\r
1569EFI_STATUS\r
1570EFIAPI\r
1571DxeCapsuleLibDestructor (\r
1572 IN EFI_HANDLE ImageHandle,\r
1573 IN EFI_SYSTEM_TABLE *SystemTable\r
1574 )\r
1575{\r
1576 EFI_STATUS Status;\r
1577\r
1578 //\r
1579 // Close the End of DXE event.\r
1580 //\r
1581 Status = gBS->CloseEvent (mDxeCapsuleLibEndOfDxeEvent);\r
1582 ASSERT_EFI_ERROR (Status);\r
1583\r
1584 return EFI_SUCCESS;\r
1585}\r