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