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