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