]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
MdeModulePkg DxeCapsuleLibFmp: Fix typo 'Press' to 'Process'
[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
271 if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {\r
272 DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));\r
273 return EFI_INVALID_PARAMETER;\r
274 }\r
275 FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);\r
276 if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||\r
277 (ImageHeader->Version < 1)) {\r
278 DEBUG((DEBUG_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));\r
279 return EFI_INVALID_PARAMETER;\r
280 }\r
281 if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
282 FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
283 }\r
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
621 @param[in,out] NoHandles The number of handles returned in Buffer.\r
622 @param[out] Buffer[out] A pointer to the buffer to return the requested array of handles.\r
623\r
624 @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of\r
625 handles in Buffer was returned in NoHandles.\r
626 @retval EFI_NOT_FOUND No handles match the search.\r
627 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.\r
628**/\r
629EFI_STATUS\r
630GetFmpHandleBufferByType (\r
631 IN EFI_GUID *UpdateImageTypeId,\r
632 IN UINT64 UpdateHardwareInstance,\r
633 IN OUT UINTN *NoHandles,\r
634 OUT EFI_HANDLE **Buffer\r
635 )\r
636{\r
637 EFI_STATUS Status;\r
638 EFI_HANDLE *HandleBuffer;\r
639 UINTN NumberOfHandles;\r
640 EFI_HANDLE *MatchedHandleBuffer;\r
641 UINTN MatchedNumberOfHandles;\r
642 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
643 UINTN Index;\r
644 UINTN ImageInfoSize;\r
645 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
646 UINT32 FmpImageInfoDescriptorVer;\r
647 UINT8 FmpImageInfoCount;\r
648 UINTN DescriptorSize;\r
649 UINT32 PackageVersion;\r
650 CHAR16 *PackageVersionName;\r
651 UINTN Index2;\r
652 EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;\r
653\r
654 *NoHandles = 0;\r
655 *Buffer = NULL;\r
656\r
657 Status = gBS->LocateHandleBuffer (\r
658 ByProtocol,\r
659 &gEfiFirmwareManagementProtocolGuid,\r
660 NULL,\r
661 &NumberOfHandles,\r
662 &HandleBuffer\r
663 );\r
664 if (EFI_ERROR(Status)) {\r
665 return Status;\r
666 }\r
667\r
668 MatchedNumberOfHandles = 0;\r
669 MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles);\r
670 if (MatchedHandleBuffer == NULL) {\r
671 FreePool (HandleBuffer);\r
672 return EFI_OUT_OF_RESOURCES;\r
673 }\r
674\r
675 for (Index = 0; Index < NumberOfHandles; Index++) {\r
676 Status = gBS->HandleProtocol(\r
677 HandleBuffer[Index],\r
678 &gEfiFirmwareManagementProtocolGuid,\r
679 (VOID **)&Fmp\r
680 );\r
681 if (EFI_ERROR(Status)) {\r
682 continue;\r
683 }\r
684\r
685 ImageInfoSize = 0;\r
686 Status = Fmp->GetImageInfo (\r
687 Fmp,\r
688 &ImageInfoSize,\r
689 NULL,\r
690 NULL,\r
691 NULL,\r
692 NULL,\r
693 NULL,\r
694 NULL\r
695 );\r
696 if (Status != EFI_BUFFER_TOO_SMALL) {\r
697 continue;\r
698 }\r
699\r
700 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
701 if (FmpImageInfoBuf == NULL) {\r
702 continue;\r
703 }\r
704\r
705 PackageVersionName = NULL;\r
706 Status = Fmp->GetImageInfo (\r
707 Fmp,\r
708 &ImageInfoSize, // ImageInfoSize\r
709 FmpImageInfoBuf, // ImageInfo\r
710 &FmpImageInfoDescriptorVer, // DescriptorVersion\r
711 &FmpImageInfoCount, // DescriptorCount\r
712 &DescriptorSize, // DescriptorSize\r
713 &PackageVersion, // PackageVersion\r
714 &PackageVersionName // PackageVersionName\r
715 );\r
716 if (EFI_ERROR(Status)) {\r
717 FreePool(FmpImageInfoBuf);\r
718 continue;\r
719 }\r
720\r
721 if (PackageVersionName != NULL) {\r
722 FreePool(PackageVersionName);\r
723 }\r
724\r
725 TempFmpImageInfo = FmpImageInfoBuf;\r
726 for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {\r
727 //\r
728 // Check if this FMP instance matches\r
729 //\r
730 if (CompareGuid(UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId)) {\r
731 if ((UpdateHardwareInstance == 0) ||\r
732 ((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) &&\r
733 (UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance))) {\r
734 MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];\r
735 MatchedNumberOfHandles++;\r
736 break;\r
737 }\r
738 }\r
739 TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);\r
740 }\r
741 FreePool(FmpImageInfoBuf);\r
742 }\r
743\r
744 if (MatchedNumberOfHandles == 0) {\r
745 return EFI_NOT_FOUND;\r
746 }\r
747\r
748 *NoHandles = MatchedNumberOfHandles;\r
749 *Buffer = MatchedHandleBuffer;\r
750\r
751 return EFI_SUCCESS;\r
752}\r
753\r
754/**\r
755 Return FmpImageInfoDescriptorVer by an FMP handle.\r
756\r
757 @param[in] Handle A FMP handle.\r
758\r
759 @return FmpImageInfoDescriptorVer associated with the FMP.\r
760**/\r
761UINT32\r
762GetFmpImageInfoDescriptorVer (\r
763 IN EFI_HANDLE Handle\r
764 )\r
765{\r
766 EFI_STATUS Status;\r
767 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
768 UINTN ImageInfoSize;\r
769 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
770 UINT32 FmpImageInfoDescriptorVer;\r
771 UINT8 FmpImageInfoCount;\r
772 UINTN DescriptorSize;\r
773 UINT32 PackageVersion;\r
774 CHAR16 *PackageVersionName;\r
775\r
776 Status = gBS->HandleProtocol(\r
777 Handle,\r
778 &gEfiFirmwareManagementProtocolGuid,\r
779 (VOID **)&Fmp\r
780 );\r
781 if (EFI_ERROR(Status)) {\r
782 return 0;\r
783 }\r
784\r
785 ImageInfoSize = 0;\r
786 Status = Fmp->GetImageInfo (\r
787 Fmp,\r
788 &ImageInfoSize,\r
789 NULL,\r
790 NULL,\r
791 NULL,\r
792 NULL,\r
793 NULL,\r
794 NULL\r
795 );\r
796 if (Status != EFI_BUFFER_TOO_SMALL) {\r
797 return 0;\r
798 }\r
799\r
800 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
801 if (FmpImageInfoBuf == NULL) {\r
802 return 0;\r
803 }\r
804\r
805 PackageVersionName = NULL;\r
806 Status = Fmp->GetImageInfo (\r
807 Fmp,\r
808 &ImageInfoSize, // ImageInfoSize\r
809 FmpImageInfoBuf, // ImageInfo\r
810 &FmpImageInfoDescriptorVer, // DescriptorVersion\r
811 &FmpImageInfoCount, // DescriptorCount\r
812 &DescriptorSize, // DescriptorSize\r
813 &PackageVersion, // PackageVersion\r
814 &PackageVersionName // PackageVersionName\r
815 );\r
816 if (EFI_ERROR(Status)) {\r
817 FreePool(FmpImageInfoBuf);\r
818 return 0;\r
819 }\r
820 return FmpImageInfoDescriptorVer;\r
821}\r
822\r
823/**\r
824 Set FMP image data.\r
825\r
826 @param[in] Handle A FMP handle.\r
827 @param[in] ImageHeader The payload image header.\r
828 @param[in] PayloadIndex The index of the payload.\r
829\r
830 @return The status of FMP->SetImage.\r
831**/\r
832EFI_STATUS\r
833SetFmpImageData (\r
834 IN EFI_HANDLE Handle,\r
835 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
836 IN UINTN PayloadIndex\r
837 )\r
838{\r
839 EFI_STATUS Status;\r
840 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
841 UINT8 *Image;\r
842 VOID *VendorCode;\r
843 CHAR16 *AbortReason;\r
1342bd44 844 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback;\r
3f31ea1b
JY
845\r
846 Status = gBS->HandleProtocol(\r
847 Handle,\r
848 &gEfiFirmwareManagementProtocolGuid,\r
849 (VOID **)&Fmp\r
850 );\r
851 if (EFI_ERROR(Status)) {\r
852 return Status;\r
853 }\r
854\r
57476106
KM
855 //\r
856 // Lookup Firmware Management Progress Protocol before SetImage() is called\r
857 // This is an optional protocol that may not be present on Handle.\r
858 //\r
859 Status = gBS->HandleProtocol (\r
860 Handle,\r
861 &gEdkiiFirmwareManagementProgressProtocolGuid,\r
862 (VOID **)&mFmpProgress\r
863 );\r
864 if (EFI_ERROR (Status)) {\r
865 mFmpProgress = NULL;\r
866 }\r
867\r
3f31ea1b
JY
868 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
869 Image = (UINT8 *)(ImageHeader + 1);\r
870 } else {\r
871 //\r
872 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,\r
873 // Header should exclude UpdateHardwareInstance field\r
874 //\r
875 Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
876 }\r
877\r
878 if (ImageHeader->UpdateVendorCodeSize == 0) {\r
879 VendorCode = NULL;\r
880 } else {\r
881 VendorCode = Image + ImageHeader->UpdateImageSize;\r
882 }\r
883 AbortReason = NULL;\r
884 DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));\r
885 DEBUG((DEBUG_INFO, "ImageTypeId - %g, ", &ImageHeader->UpdateImageTypeId));\r
886 DEBUG((DEBUG_INFO, "PayloadIndex - 0x%x, ", PayloadIndex));\r
887 DEBUG((DEBUG_INFO, "ImageIndex - 0x%x ", ImageHeader->UpdateImageIndex));\r
888 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
889 DEBUG((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));\r
890 }\r
891 DEBUG((DEBUG_INFO, "\n"));\r
57476106
KM
892\r
893 //\r
894 // Before calling SetImage(), reset the progress bar to 0%\r
895 //\r
1342bd44
AB
896 ProgressCallback = UpdateImageProgress;\r
897 Status = UpdateImageProgress (0);\r
898 if (EFI_ERROR (Status)) {\r
899 ProgressCallback = NULL;\r
900 }\r
57476106 901\r
3f31ea1b
JY
902 Status = Fmp->SetImage(\r
903 Fmp,\r
904 ImageHeader->UpdateImageIndex, // ImageIndex\r
905 Image, // Image\r
906 ImageHeader->UpdateImageSize, // ImageSize\r
907 VendorCode, // VendorCode\r
1342bd44 908 ProgressCallback, // Progress\r
3f31ea1b
JY
909 &AbortReason // AbortReason\r
910 );\r
57476106
KM
911 //\r
912 // Set the progress bar to 100% after returning from SetImage()\r
913 //\r
1342bd44
AB
914 if (ProgressCallback != NULL) {\r
915 UpdateImageProgress (100);\r
916 }\r
57476106 917\r
3f31ea1b
JY
918 DEBUG((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));\r
919 if (AbortReason != NULL) {\r
920 DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));\r
921 FreePool(AbortReason);\r
922 }\r
923\r
57476106
KM
924 //\r
925 // Clear mFmpProgress after SetImage() returns\r
926 //\r
927 mFmpProgress = NULL;\r
928\r
3f31ea1b
JY
929 return Status;\r
930}\r
931\r
932/**\r
933 Start a UEFI image in the FMP payload.\r
934\r
935 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..\r
936 @param[in] ImageSize The size in bytes of ImageBuffer.\r
937\r
938 @return The status of gBS->LoadImage and gBS->StartImage.\r
939**/\r
940EFI_STATUS\r
941StartFmpImage (\r
942 IN VOID *ImageBuffer,\r
943 IN UINTN ImageSize\r
944 )\r
945{\r
946 MEMMAP_DEVICE_PATH MemMapNode;\r
947 EFI_STATUS Status;\r
948 EFI_HANDLE ImageHandle;\r
949 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;\r
950 UINTN ExitDataSize;\r
951\r
952 SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));\r
953 MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;\r
954 MemMapNode.Header.SubType = HW_MEMMAP_DP;\r
955 MemMapNode.MemoryType = EfiBootServicesCode;\r
956 MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBuffer;\r
957 MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)ImageBuffer + ImageSize - 1);\r
958\r
959 DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);\r
960 if (DriverDevicePath == NULL) {\r
961 return EFI_OUT_OF_RESOURCES;\r
962 }\r
963\r
964 DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));\r
965 Status = gBS->LoadImage(\r
966 FALSE,\r
967 gImageHandle,\r
968 DriverDevicePath,\r
969 ImageBuffer,\r
970 ImageSize,\r
971 &ImageHandle\r
972 );\r
973 DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));\r
974 if (EFI_ERROR(Status)) {\r
975 FreePool(DriverDevicePath);\r
976 return Status;\r
977 }\r
978\r
979 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));\r
980 Status = gBS->StartImage(\r
981 ImageHandle,\r
982 &ExitDataSize,\r
983 NULL\r
984 );\r
985 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));\r
986 if (EFI_ERROR(Status)) {\r
987 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
988 }\r
989\r
990 FreePool(DriverDevicePath);\r
991 return Status;\r
992}\r
993\r
994/**\r
995 Record FMP capsule status.\r
996\r
997 @param[in] Handle A FMP handle.\r
998 @param[in] CapsuleHeader The capsule image header\r
999 @param[in] CapsuleStatus The capsule process stauts\r
1000 @param[in] PayloadIndex FMP payload index\r
1001 @param[in] ImageHeader FMP image header\r
1002**/\r
1003VOID\r
1004RecordFmpCapsuleStatus (\r
1005 IN EFI_HANDLE Handle, OPTIONAL\r
1006 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
1007 IN EFI_STATUS CapsuleStatus,\r
1008 IN UINTN PayloadIndex,\r
1009 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader\r
1010 )\r
1011{\r
1012 EFI_STATUS Status;\r
1013 EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath;\r
1014 UINT32 FmpImageInfoDescriptorVer;\r
1015 EFI_STATUS StatusEsrt;\r
1016 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
1017 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;\r
1018\r
1019 FmpDevicePath = NULL;\r
1020 if (Handle != NULL) {\r
1021 gBS->HandleProtocol(\r
1022 Handle,\r
1023 &gEfiDevicePathProtocolGuid,\r
1024 (VOID **)&FmpDevicePath\r
1025 );\r
1026 }\r
1027\r
1028 RecordFmpCapsuleStatusVariable (\r
1029 CapsuleHeader,\r
1030 CapsuleStatus,\r
1031 PayloadIndex,\r
1032 ImageHeader,\r
1033 FmpDevicePath\r
1034 );\r
1035\r
1036 //\r
1037 // Update corresponding ESRT entry LastAttemp Status\r
1038 //\r
1039 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
1040 if (EFI_ERROR (Status)) {\r
1041 return ;\r
1042 }\r
1043\r
1044 if (Handle == NULL) {\r
1045 return ;\r
1046 }\r
1047\r
1048 //\r
1049 // Update EsrtEntry For V1, V2 FMP instance.\r
1050 // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface\r
1051 //\r
1052 FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);\r
1053 if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {\r
1054 StatusEsrt = EsrtProtocol->GetEsrtEntry(&ImageHeader->UpdateImageTypeId, &EsrtEntry);\r
1055 if (!EFI_ERROR(StatusEsrt)){\r
1056 if (!EFI_ERROR(CapsuleStatus)) {\r
1057 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
1058 } else {\r
1059 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1060 }\r
1061 EsrtEntry.LastAttemptVersion = 0;\r
1062 EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);\r
1063 }\r
1064 }\r
1065}\r
1066\r
d2a16030
JY
1067/**\r
1068 Process Firmware management protocol data capsule.\r
1069\r
1070 This function assumes the caller validated the capsule by using\r
1071 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,\r
1072 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and\r
1073 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.\r
1074\r
1075 This function need support nested FMP capsule.\r
1076\r
11ee1bc9 1077 @param[in] CapsuleHeader Points to a capsule header.\r
d2a16030
JY
1078\r
1079 @retval EFI_SUCESS Process Capsule Image successfully.\r
1080 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
1081 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
1082 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
3f31ea1b 1083 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.\r
d2a16030
JY
1084**/\r
1085EFI_STATUS\r
1086ProcessFmpCapsuleImage (\r
3f31ea1b 1087 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
d2a16030
JY
1088 )\r
1089{\r
1090 EFI_STATUS Status;\r
d2a16030
JY
1091 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
1092 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
d2a16030
JY
1093 UINT64 *ItemOffsetList;\r
1094 UINT32 ItemNum;\r
1095 UINTN Index;\r
d2a16030 1096 EFI_HANDLE *HandleBuffer;\r
d2a16030 1097 UINTN NumberOfHandles;\r
d2a16030 1098 UINTN DriverLen;\r
3f31ea1b 1099 UINT64 UpdateHardwareInstance;\r
d2a16030 1100 UINTN Index2;\r
3f31ea1b
JY
1101 BOOLEAN NotReady;\r
1102 BOOLEAN Abort;\r
d2a16030
JY
1103\r
1104 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
3f31ea1b 1105 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));\r
d2a16030
JY
1106 }\r
1107\r
3f31ea1b
JY
1108 NotReady = FALSE;\r
1109 Abort = FALSE;\r
d2a16030
JY
1110\r
1111 DumpFmpCapsule(CapsuleHeader);\r
1112\r
1113 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
1114\r
1115 if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
1116 return EFI_INVALID_PARAMETER;\r
1117 }\r
1118 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
1119\r
1120 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
1121\r
1122 //\r
1123 // capsule in which driver count and payload count are both zero is not processed.\r
1124 //\r
1125 if (ItemNum == 0) {\r
d2a16030
JY
1126 return EFI_SUCCESS;\r
1127 }\r
1128\r
d2a16030
JY
1129 //\r
1130 // 1. Try to load & start all the drivers within capsule\r
1131 //\r
d2a16030 1132 for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\r
3f31ea1b
JY
1133 if ((FmpCapsuleHeader->PayloadItemCount == 0) &&\r
1134 (Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1)) {\r
d2a16030
JY
1135 //\r
1136 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER\r
1137 //\r
1138 DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];\r
1139 } else {\r
1140 DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];\r
1141 }\r
1142\r
3f31ea1b
JY
1143 Status = StartFmpImage (\r
1144 (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],\r
1145 DriverLen\r
1146 );\r
d2a16030
JY
1147 if (EFI_ERROR(Status)) {\r
1148 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
3f31ea1b 1149 return Status;\r
d2a16030
JY
1150 }\r
1151 }\r
1152\r
1153 //\r
1154 // 2. Route payload to right FMP instance\r
1155 //\r
1156 DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));\r
1157\r
3f31ea1b 1158 DumpAllFmpInfo ();\r
8f6db161 1159\r
3f31ea1b
JY
1160 //\r
1161 // Check all the payload entry in capsule payload list\r
1162 //\r
1163 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
1164 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
d2a16030 1165\r
3f31ea1b
JY
1166 UpdateHardwareInstance = 0;\r
1167 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
1168 UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;\r
1169 }\r
d2a16030 1170\r
3f31ea1b
JY
1171 Status = GetFmpHandleBufferByType (\r
1172 &ImageHeader->UpdateImageTypeId,\r
1173 UpdateHardwareInstance,\r
1174 &NumberOfHandles,\r
1175 &HandleBuffer\r
1176 );\r
1177 if (EFI_ERROR(Status)) {\r
1178 NotReady = TRUE;\r
1179 RecordFmpCapsuleStatus (\r
1180 NULL,\r
1181 CapsuleHeader,\r
1182 EFI_NOT_READY,\r
1183 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
1184 ImageHeader\r
1185 );\r
1186 continue;\r
1187 }\r
d2a16030 1188\r
3f31ea1b
JY
1189 for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {\r
1190 if (Abort) {\r
1191 RecordFmpCapsuleStatus (\r
1192 HandleBuffer[Index2],\r
1193 CapsuleHeader,\r
1194 EFI_ABORTED,\r
1195 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
1196 ImageHeader\r
1197 );\r
d2a16030
JY
1198 continue;\r
1199 }\r
1200\r
3f31ea1b
JY
1201 Status = SetFmpImageData (\r
1202 HandleBuffer[Index2],\r
1203 ImageHeader,\r
1204 Index - FmpCapsuleHeader->EmbeddedDriverCount\r
1205 );\r
1206 if (Status != EFI_SUCCESS) {\r
1207 Abort = TRUE;\r
d2a16030
JY
1208 }\r
1209\r
3f31ea1b
JY
1210 RecordFmpCapsuleStatus (\r
1211 HandleBuffer[Index2],\r
1212 CapsuleHeader,\r
1213 Status,\r
1214 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
1215 ImageHeader\r
1216 );\r
d2a16030 1217 }\r
3f31ea1b
JY
1218 if (HandleBuffer != NULL) {\r
1219 FreePool(HandleBuffer);\r
d2a16030
JY
1220 }\r
1221 }\r
1222\r
3f31ea1b
JY
1223 if (NotReady) {\r
1224 return EFI_NOT_READY;\r
d2a16030
JY
1225 }\r
1226\r
3f31ea1b
JY
1227 //\r
1228 // always return SUCCESS to indicate this capsule is processed.\r
1229 // The status of SetImage is recorded in capsule result variable.\r
1230 //\r
1231 return EFI_SUCCESS;\r
d2a16030
JY
1232}\r
1233\r
1234/**\r
1235 Return if there is a FMP header below capsule header.\r
1236\r
1237 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
1238\r
1239 @retval TRUE There is a FMP header below capsule header.\r
1240 @retval FALSE There is not a FMP header below capsule header\r
1241**/\r
1242BOOLEAN\r
1243IsNestedFmpCapsule (\r
1244 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1245 )\r
1246{\r
1247 EFI_STATUS Status;\r
d2a16030
JY
1248 EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;\r
1249 UINTN Index;\r
1250 BOOLEAN EsrtGuidFound;\r
1251 EFI_CAPSULE_HEADER *NestedCapsuleHeader;\r
1252 UINTN NestedCapsuleSize;\r
1253 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
1254 EFI_SYSTEM_RESOURCE_ENTRY Entry;\r
7f0301e3
KM
1255 EFI_HANDLE *HandleBuffer;\r
1256 UINTN NumberOfHandles;\r
d2a16030
JY
1257\r
1258 EsrtGuidFound = FALSE;\r
056563f1
JY
1259 if (mIsVirtualAddrConverted) {\r
1260 if(mEsrtTable != NULL) {\r
1261 EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);\r
1262 for (Index = 0; Index < mEsrtTable->FwResourceCount ; Index++, EsrtEntry++) {\r
d2a16030
JY
1263 if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {\r
1264 EsrtGuidFound = TRUE;\r
1265 break;\r
1266 }\r
1267 }\r
1268 }\r
056563f1
JY
1269 } else {\r
1270 //\r
1271 // Check ESRT protocol\r
1272 //\r
1273 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
1274 if (!EFI_ERROR(Status)) {\r
1275 Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);\r
1276 if (!EFI_ERROR(Status)) {\r
1277 EsrtGuidFound = TRUE;\r
1278 }\r
1279 }\r
1280\r
1281 //\r
7f0301e3 1282 // Check Firmware Management Protocols\r
056563f1
JY
1283 //\r
1284 if (!EsrtGuidFound) {\r
7f0301e3
KM
1285 HandleBuffer = NULL;\r
1286 Status = GetFmpHandleBufferByType (\r
1287 &CapsuleHeader->CapsuleGuid,\r
1288 0,\r
1289 &NumberOfHandles,\r
1290 &HandleBuffer\r
1291 );\r
056563f1 1292 if (!EFI_ERROR(Status)) {\r
7f0301e3
KM
1293 EsrtGuidFound = TRUE;\r
1294 }\r
1295 if (HandleBuffer != NULL) {\r
1296 FreePool (HandleBuffer);\r
056563f1
JY
1297 }\r
1298 }\r
d2a16030
JY
1299 }\r
1300 if (!EsrtGuidFound) {\r
1301 return FALSE;\r
1302 }\r
1303\r
1304 //\r
1305 // Check nested capsule header\r
1306 // FMP GUID after ESRT one\r
1307 //\r
1308 NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);\r
1309 NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;\r
1310 if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {\r
1311 return FALSE;\r
1312 }\r
1313 if (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {\r
1314 return FALSE;\r
1315 }\r
1316 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {\r
1317 return FALSE;\r
1318 }\r
1319 DEBUG ((DEBUG_INFO, "IsNestedFmpCapsule\n"));\r
1320 return TRUE;\r
1321}\r
1322\r
1323/**\r
1324 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.\r
1325\r
1326 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
1327\r
1328 @retval TRUE It is a system FMP.\r
1329 @retval FALSE It is a device FMP.\r
1330**/\r
1331BOOLEAN\r
1332IsFmpCapsule (\r
1333 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1334 )\r
1335{\r
1336 if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
1337 return TRUE;\r
1338 }\r
1339 if (IsNestedFmpCapsule(CapsuleHeader)) {\r
1340 return TRUE;\r
1341 }\r
1342 return FALSE;\r
1343}\r
1344\r
1345/**\r
1346 Those capsules supported by the firmwares.\r
1347\r
1348 Caution: This function may receive untrusted input.\r
1349\r
1350 @param[in] CapsuleHeader Points to a capsule header.\r
1351\r
1352 @retval EFI_SUCESS Input capsule is supported by firmware.\r
1353 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.\r
1354 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct\r
1355**/\r
1356EFI_STATUS\r
1357EFIAPI\r
1358SupportCapsuleImage (\r
1359 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1360 )\r
1361{\r
1362 //\r
1363 // check Display Capsule Guid\r
1364 //\r
1365 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
1366 return EFI_SUCCESS;\r
1367 }\r
1368\r
1369 if (IsFmpCapsule(CapsuleHeader)) {\r
1370 //\r
1371 // Check layout of FMP capsule\r
1372 //\r
1373 return ValidateFmpCapsule(CapsuleHeader, NULL);\r
1374 }\r
1375 DEBUG((DEBUG_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));\r
1376 return EFI_UNSUPPORTED;\r
1377}\r
1378\r
1379/**\r
1380 The firmware implements to process the capsule image.\r
1381\r
1382 Caution: This function may receive untrusted input.\r
1383\r
1384 @param[in] CapsuleHeader Points to a capsule header.\r
1385\r
1386 @retval EFI_SUCESS Process Capsule Image successfully.\r
1387 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
1388 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
1389 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
1390**/\r
1391EFI_STATUS\r
1392EFIAPI\r
1393ProcessCapsuleImage (\r
1394 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1395 )\r
1396{\r
1397 EFI_STATUS Status;\r
d2a16030
JY
1398\r
1399 if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {\r
3f31ea1b 1400 RecordCapsuleStatusVariable(CapsuleHeader, EFI_UNSUPPORTED);\r
d2a16030
JY
1401 return EFI_UNSUPPORTED;\r
1402 }\r
1403\r
1404 //\r
1405 // Display image in firmware update display capsule\r
1406 //\r
1407 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
1408 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));\r
1409 Status = DisplayCapsuleImage(CapsuleHeader);\r
1410 RecordCapsuleStatusVariable(CapsuleHeader, Status);\r
1411 return Status;\r
1412 }\r
1413\r
1414 //\r
1415 // Check FMP capsule layout\r
1416 //\r
1417 if (IsFmpCapsule (CapsuleHeader)) {\r
1418 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));\r
1419 DEBUG((DEBUG_INFO, "ValidateFmpCapsule ...\n"));\r
1420 Status = ValidateFmpCapsule(CapsuleHeader, NULL);\r
1421 DEBUG((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));\r
1422 if (EFI_ERROR(Status)) {\r
3f31ea1b 1423 RecordCapsuleStatusVariable(CapsuleHeader, Status);\r
d2a16030
JY
1424 return Status;\r
1425 }\r
1426\r
1427 //\r
a891bd73 1428 // Process EFI FMP Capsule\r
d2a16030
JY
1429 //\r
1430 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));\r
3f31ea1b 1431 Status = ProcessFmpCapsuleImage(CapsuleHeader);\r
d2a16030
JY
1432 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));\r
1433\r
d2a16030
JY
1434 return Status;\r
1435 }\r
1436\r
1437 return EFI_UNSUPPORTED;\r
1438}\r
1439\r
1440/**\r
1441 Callback function executed when the EndOfDxe event group is signaled.\r
1442\r
1443 @param[in] Event Event whose notification function is being invoked.\r
1444 @param[in] Context The pointer to the notification function's context, which\r
1445 is implementation-dependent.\r
1446**/\r
1447VOID\r
1448EFIAPI\r
1449DxeCapsuleLibEndOfDxe (\r
1450 IN EFI_EVENT Event,\r
1451 IN VOID *Context\r
1452 )\r
1453{\r
1454 mDxeCapsuleLibEndOfDxe = TRUE;\r
1455}\r
1456\r
1457/**\r
1458 The constructor function.\r
1459\r
1460 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1461 @param[in] SystemTable A pointer to the EFI System Table.\r
1462\r
1463 @retval EFI_SUCCESS The constructor successfully .\r
1464**/\r
1465EFI_STATUS\r
1466EFIAPI\r
1467DxeCapsuleLibConstructor (\r
1468 IN EFI_HANDLE ImageHandle,\r
1469 IN EFI_SYSTEM_TABLE *SystemTable\r
1470 )\r
1471{\r
d2a16030
JY
1472 EFI_STATUS Status;\r
1473\r
1474 Status = gBS->CreateEventEx (\r
1475 EVT_NOTIFY_SIGNAL,\r
1476 TPL_CALLBACK,\r
1477 DxeCapsuleLibEndOfDxe,\r
1478 NULL,\r
1479 &gEfiEndOfDxeEventGroupGuid,\r
96b17e00 1480 &mDxeCapsuleLibEndOfDxeEvent\r
d2a16030
JY
1481 );\r
1482 ASSERT_EFI_ERROR (Status);\r
1483\r
1484 InitCapsuleVariable();\r
1485\r
1486 return EFI_SUCCESS;\r
1487}\r
96b17e00
HW
1488\r
1489/**\r
1490 The destructor function closes the End of DXE event.\r
1491\r
1492 @param ImageHandle The firmware allocated handle for the EFI image.\r
1493 @param SystemTable A pointer to the EFI System Table.\r
1494\r
1495 @retval EFI_SUCCESS The destructor completed successfully.\r
1496**/\r
1497EFI_STATUS\r
1498EFIAPI\r
1499DxeCapsuleLibDestructor (\r
1500 IN EFI_HANDLE ImageHandle,\r
1501 IN EFI_SYSTEM_TABLE *SystemTable\r
1502 )\r
1503{\r
1504 EFI_STATUS Status;\r
1505\r
1506 //\r
1507 // Close the End of DXE event.\r
1508 //\r
1509 Status = gBS->CloseEvent (mDxeCapsuleLibEndOfDxeEvent);\r
1510 ASSERT_EFI_ERROR (Status);\r
1511\r
1512 return EFI_SUCCESS;\r
1513}\r