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