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