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