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