]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
MdeModulePkg/DxeCapsuleLibFmp: Unload image on EFI_SECURITY_VIOLATION
[mirror_edk2.git] / MdeModulePkg / Library / DxeCapsuleLibFmp / DxeCapsuleLib.c
CommitLineData
d2a16030
JY
1/** @file\r
2 DXE capsule library.\r
3\r
4 Caution: This module requires additional review when modified.\r
5 This module will have external input - capsule image.\r
6 This external input must be validated carefully to avoid security issue like\r
7 buffer overflow, integer overflow.\r
8\r
9 SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),\r
1ec2e7d0
MK
10 ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and\r
11 performs basic validation.\r
d2a16030 12\r
28889a78 13 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
9d510e61 14 SPDX-License-Identifier: BSD-2-Clause-Patent\r
d2a16030
JY
15\r
16**/\r
17\r
18#include <PiDxe.h>\r
19\r
d2a16030
JY
20#include <IndustryStandard/WindowsUxCapsule.h>\r
21\r
22#include <Guid/FmpCapsule.h>\r
23#include <Guid/SystemResourceTable.h>\r
24#include <Guid/EventGroup.h>\r
25\r
26#include <Library/BaseLib.h>\r
27#include <Library/DebugLib.h>\r
28#include <Library/BaseMemoryLib.h>\r
29#include <Library/DxeServicesTableLib.h>\r
30#include <Library/UefiBootServicesTableLib.h>\r
31#include <Library/UefiRuntimeServicesTableLib.h>\r
32#include <Library/MemoryAllocationLib.h>\r
33#include <Library/CapsuleLib.h>\r
34#include <Library/DevicePathLib.h>\r
35#include <Library/UefiLib.h>\r
1ec2e7d0 36#include <Library/BmpSupportLib.h>\r
d2a16030
JY
37\r
38#include <Protocol/GraphicsOutput.h>\r
39#include <Protocol/EsrtManagement.h>\r
40#include <Protocol/FirmwareManagement.h>\r
57476106 41#include <Protocol/FirmwareManagementProgress.h>\r
d2a16030
JY
42#include <Protocol/DevicePath.h>\r
43\r
03286264
DB
44EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable = NULL;\r
45BOOLEAN mIsVirtualAddrConverted = FALSE;\r
d948cf83 46\r
96b17e00
HW
47BOOLEAN mDxeCapsuleLibEndOfDxe = FALSE;\r
48EFI_EVENT mDxeCapsuleLibEndOfDxeEvent = NULL;\r
d2a16030 49\r
57476106
KM
50EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *mFmpProgress = NULL;\r
51\r
d2a16030
JY
52/**\r
53 Initialize capsule related variables.\r
54**/\r
55VOID\r
56InitCapsuleVariable (\r
57 VOID\r
58 );\r
59\r
d2a16030
JY
60/**\r
61 Record capsule status variable.\r
62\r
63 @param[in] CapsuleHeader The capsule image header\r
64 @param[in] CapsuleStatus The capsule process stauts\r
65\r
66 @retval EFI_SUCCESS The capsule status variable is recorded.\r
67 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\r
68**/\r
69EFI_STATUS\r
70RecordCapsuleStatusVariable (\r
71 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
72 IN EFI_STATUS CapsuleStatus\r
73 );\r
74\r
75/**\r
76 Record FMP capsule status variable.\r
77\r
78 @param[in] CapsuleHeader The capsule image header\r
79 @param[in] CapsuleStatus The capsule process stauts\r
80 @param[in] PayloadIndex FMP payload index\r
81 @param[in] ImageHeader FMP image header\r
8f6db161 82 @param[in] FmpDevicePath DevicePath associated with the FMP producer\r
28889a78 83 @param[in] CapFileName Capsule file name\r
d2a16030
JY
84\r
85 @retval EFI_SUCCESS The capsule status variable is recorded.\r
86 @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\r
87**/\r
88EFI_STATUS\r
89RecordFmpCapsuleStatusVariable (\r
90 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
91 IN EFI_STATUS CapsuleStatus,\r
92 IN UINTN PayloadIndex,\r
8f6db161 93 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
28889a78
WX
94 IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OPTIONAL\r
95 IN CHAR16 *CapFileName OPTIONAL\r
d2a16030
JY
96 );\r
97\r
98/**\r
99 Function indicate the current completion progress of the firmware\r
100 update. Platform may override with own specific progress function.\r
101\r
57476106
KM
102 @param[in] Completion A value between 1 and 100 indicating the current\r
103 completion progress of the firmware update\r
d2a16030 104\r
57476106
KM
105 @retval EFI_SUCESS The capsule update progress was updated.\r
106 @retval EFI_INVALID_PARAMETER Completion is greater than 100%.\r
d2a16030
JY
107**/\r
108EFI_STATUS\r
109EFIAPI\r
57476106 110UpdateImageProgress (\r
d2a16030 111 IN UINTN Completion\r
57476106 112 );\r
d2a16030 113\r
28889a78
WX
114/**\r
115 Return if this capsule is a capsule name capsule, based upon CapsuleHeader.\r
116\r
117 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
118\r
119 @retval TRUE It is a capsule name capsule.\r
120 @retval FALSE It is not a capsule name capsule.\r
121**/\r
122BOOLEAN\r
123IsCapsuleNameCapsule (\r
124 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
125 )\r
126{\r
127 return CompareGuid (&CapsuleHeader->CapsuleGuid, &gEdkiiCapsuleOnDiskNameGuid);\r
128}\r
129\r
d2a16030
JY
130/**\r
131 Return if this CapsuleGuid is a FMP capsule GUID or not.\r
132\r
133 @param[in] CapsuleGuid A pointer to EFI_GUID\r
134\r
135 @retval TRUE It is a FMP capsule GUID.\r
136 @retval FALSE It is not a FMP capsule GUID.\r
137**/\r
138BOOLEAN\r
139IsFmpCapsuleGuid (\r
140 IN EFI_GUID *CapsuleGuid\r
141 )\r
142{\r
143 if (CompareGuid(&gEfiFmpCapsuleGuid, CapsuleGuid)) {\r
144 return TRUE;\r
145 }\r
146\r
147 return FALSE;\r
148}\r
149\r
150/**\r
151 Validate if it is valid capsule header\r
152\r
153 Caution: This function may receive untrusted input.\r
154\r
155 This function assumes the caller provided correct CapsuleHeader pointer\r
156 and CapsuleSize.\r
157\r
158 This function validates the fields in EFI_CAPSULE_HEADER.\r
159\r
160 @param[in] CapsuleHeader Points to a capsule header.\r
161 @param[in] CapsuleSize Size of the whole capsule image.\r
162\r
163**/\r
164BOOLEAN\r
165IsValidCapsuleHeader (\r
166 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
167 IN UINT64 CapsuleSize\r
168 )\r
169{\r
170 if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {\r
171 return FALSE;\r
172 }\r
173 if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {\r
174 return FALSE;\r
175 }\r
176 return TRUE;\r
177}\r
178\r
179/**\r
180 Validate Fmp capsules layout.\r
181\r
182 Caution: This function may receive untrusted input.\r
183\r
184 This function assumes the caller validated the capsule by using\r
185 IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.\r
186 The capsule buffer size is CapsuleHeader->CapsuleImageSize.\r
187\r
188 This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\r
189 and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.\r
190\r
191 This function need support nested FMP capsule.\r
192\r
193 @param[in] CapsuleHeader Points to a capsule header.\r
194 @param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.\r
195\r
196 @retval EFI_SUCESS Input capsule is a correct FMP capsule.\r
197 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.\r
198**/\r
199EFI_STATUS\r
200ValidateFmpCapsule (\r
201 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
202 OUT UINT16 *EmbeddedDriverCount OPTIONAL\r
203 )\r
204{\r
205 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
206 UINT8 *EndOfCapsule;\r
207 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
208 UINT8 *EndOfPayload;\r
209 UINT64 *ItemOffsetList;\r
210 UINT32 ItemNum;\r
211 UINTN Index;\r
212 UINTN FmpCapsuleSize;\r
213 UINTN FmpCapsuleHeaderSize;\r
214 UINT64 FmpImageSize;\r
215 UINTN FmpImageHeaderSize;\r
216\r
217 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
218 return ValidateFmpCapsule ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), EmbeddedDriverCount);\r
219 }\r
220\r
221 if (CapsuleHeader->HeaderSize >= CapsuleHeader->CapsuleImageSize) {\r
222 DEBUG((DEBUG_ERROR, "HeaderSize(0x%x) >= CapsuleImageSize(0x%x)\n", CapsuleHeader->HeaderSize, CapsuleHeader->CapsuleImageSize));\r
223 return EFI_INVALID_PARAMETER;\r
224 }\r
225\r
226 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
227 EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;\r
228 FmpCapsuleSize = (UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader;\r
229\r
230 if (FmpCapsuleSize < sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER)) {\r
231 DEBUG((DEBUG_ERROR, "FmpCapsuleSize(0x%x) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\n", FmpCapsuleSize));\r
232 return EFI_INVALID_PARAMETER;\r
233 }\r
234\r
235 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER\r
236 if (FmpCapsuleHeader->Version != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
237 DEBUG((DEBUG_ERROR, "FmpCapsuleHeader->Version(0x%x) != EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION\n", FmpCapsuleHeader->Version));\r
238 return EFI_INVALID_PARAMETER;\r
239 }\r
240 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
241\r
242 // No overflow\r
243 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
244\r
245 if ((FmpCapsuleSize - sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER))/sizeof(UINT64) < ItemNum) {\r
246 DEBUG((DEBUG_ERROR, "ItemNum(0x%x) too big\n", ItemNum));\r
247 return EFI_INVALID_PARAMETER;\r
248 }\r
249 FmpCapsuleHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER) + sizeof(UINT64)*ItemNum;\r
250\r
251 // Check ItemOffsetList\r
252 for (Index = 0; Index < ItemNum; Index++) {\r
253 if (ItemOffsetList[Index] >= FmpCapsuleSize) {\r
254 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) >= FmpCapsuleSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleSize));\r
255 return EFI_INVALID_PARAMETER;\r
256 }\r
257 if (ItemOffsetList[Index] < FmpCapsuleHeaderSize) {\r
258 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < FmpCapsuleHeaderSize(0x%x)\n", Index, ItemOffsetList[Index], FmpCapsuleHeaderSize));\r
259 return EFI_INVALID_PARAMETER;\r
260 }\r
261 //\r
262 // All the address in ItemOffsetList must be stored in ascending order\r
263 //\r
264 if (Index > 0) {\r
265 if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {\r
0f3cd8a9 266 DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index - 1, ItemOffsetList[Index - 1]));\r
d2a16030
JY
267 return EFI_INVALID_PARAMETER;\r
268 }\r
269 }\r
270 }\r
271\r
272 // Check EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\r
273 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
274 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
275 if (Index == ItemNum - 1) {\r
276 EndOfPayload = (UINT8 *)((UINTN)EndOfCapsule - (UINTN)FmpCapsuleHeader);\r
277 } else {\r
278 EndOfPayload = (UINT8 *)(UINTN)ItemOffsetList[Index+1];\r
279 }\r
280 FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];\r
281\r
d2a16030
JY
282 FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);\r
283 if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||\r
284 (ImageHeader->Version < 1)) {\r
285 DEBUG((DEBUG_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));\r
286 return EFI_INVALID_PARAMETER;\r
287 }\r
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
51a3985c
DB
1033 //\r
1034 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created\r
1035 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.\r
1036 // If the caller doesn't have the option to defer the execution of an image, we should\r
1037 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.\r
1038 //\r
1039 if (Status == EFI_SECURITY_VIOLATION) {\r
1040 gBS->UnloadImage (ImageHandle);\r
1041 }\r
3f31ea1b
JY
1042 FreePool(DriverDevicePath);\r
1043 return Status;\r
1044 }\r
1045\r
1046 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));\r
1047 Status = gBS->StartImage(\r
1048 ImageHandle,\r
1049 &ExitDataSize,\r
1050 NULL\r
1051 );\r
1052 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));\r
1053 if (EFI_ERROR(Status)) {\r
1054 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
1055 }\r
1056\r
1057 FreePool(DriverDevicePath);\r
1058 return Status;\r
1059}\r
1060\r
1061/**\r
1062 Record FMP capsule status.\r
1063\r
28889a78 1064 @param[in] Handle A FMP handle.\r
3f31ea1b
JY
1065 @param[in] CapsuleHeader The capsule image header\r
1066 @param[in] CapsuleStatus The capsule process stauts\r
1067 @param[in] PayloadIndex FMP payload index\r
1068 @param[in] ImageHeader FMP image header\r
28889a78 1069 @param[in] CapFileName Capsule file name\r
3f31ea1b
JY
1070**/\r
1071VOID\r
1072RecordFmpCapsuleStatus (\r
1073 IN EFI_HANDLE Handle, OPTIONAL\r
1074 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
1075 IN EFI_STATUS CapsuleStatus,\r
1076 IN UINTN PayloadIndex,\r
28889a78
WX
1077 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
1078 IN CHAR16 *CapFileName OPTIONAL\r
3f31ea1b
JY
1079 )\r
1080{\r
1081 EFI_STATUS Status;\r
1082 EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath;\r
1083 UINT32 FmpImageInfoDescriptorVer;\r
1084 EFI_STATUS StatusEsrt;\r
1085 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
1086 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;\r
1087\r
1088 FmpDevicePath = NULL;\r
1089 if (Handle != NULL) {\r
1090 gBS->HandleProtocol(\r
1091 Handle,\r
1092 &gEfiDevicePathProtocolGuid,\r
1093 (VOID **)&FmpDevicePath\r
1094 );\r
1095 }\r
1096\r
1097 RecordFmpCapsuleStatusVariable (\r
1098 CapsuleHeader,\r
1099 CapsuleStatus,\r
1100 PayloadIndex,\r
1101 ImageHeader,\r
28889a78
WX
1102 FmpDevicePath,\r
1103 CapFileName\r
3f31ea1b
JY
1104 );\r
1105\r
1106 //\r
1107 // Update corresponding ESRT entry LastAttemp Status\r
1108 //\r
1109 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
1110 if (EFI_ERROR (Status)) {\r
1111 return ;\r
1112 }\r
1113\r
1114 if (Handle == NULL) {\r
1115 return ;\r
1116 }\r
1117\r
1118 //\r
1119 // Update EsrtEntry For V1, V2 FMP instance.\r
1bf23e6b 1120 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface\r
3f31ea1b
JY
1121 //\r
1122 FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);\r
1123 if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {\r
1124 StatusEsrt = EsrtProtocol->GetEsrtEntry(&ImageHeader->UpdateImageTypeId, &EsrtEntry);\r
1125 if (!EFI_ERROR(StatusEsrt)){\r
1126 if (!EFI_ERROR(CapsuleStatus)) {\r
1127 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
1128 } else {\r
1129 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
1130 }\r
1131 EsrtEntry.LastAttemptVersion = 0;\r
1132 EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);\r
1133 }\r
1134 }\r
1135}\r
1136\r
d2a16030
JY
1137/**\r
1138 Process Firmware management protocol data capsule.\r
1139\r
1140 This function assumes the caller validated the capsule by using\r
1141 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,\r
1142 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and\r
1143 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.\r
1144\r
1145 This function need support nested FMP capsule.\r
1146\r
69feaa37 1147 @param[in] CapsuleHeader Points to a capsule header.\r
28889a78 1148 @param[in] CapFileName Capsule file name.\r
69feaa37 1149 @param[out] ResetRequired Indicates whether reset is required or not.\r
d2a16030
JY
1150\r
1151 @retval EFI_SUCESS Process Capsule Image successfully.\r
1152 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
1153 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
1154 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
3f31ea1b 1155 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.\r
d2a16030
JY
1156**/\r
1157EFI_STATUS\r
1158ProcessFmpCapsuleImage (\r
69feaa37 1159 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
28889a78 1160 IN CHAR16 *CapFileName, OPTIONAL\r
69feaa37 1161 OUT BOOLEAN *ResetRequired OPTIONAL\r
d2a16030
JY
1162 )\r
1163{\r
1164 EFI_STATUS Status;\r
d2a16030
JY
1165 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
1166 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
d2a16030
JY
1167 UINT64 *ItemOffsetList;\r
1168 UINT32 ItemNum;\r
1169 UINTN Index;\r
d2a16030 1170 EFI_HANDLE *HandleBuffer;\r
69feaa37 1171 BOOLEAN *ResetRequiredBuffer;\r
d2a16030 1172 UINTN NumberOfHandles;\r
d2a16030 1173 UINTN DriverLen;\r
3f31ea1b 1174 UINT64 UpdateHardwareInstance;\r
d2a16030 1175 UINTN Index2;\r
3f31ea1b
JY
1176 BOOLEAN NotReady;\r
1177 BOOLEAN Abort;\r
d2a16030
JY
1178\r
1179 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
28889a78 1180 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), CapFileName, ResetRequired);\r
d2a16030
JY
1181 }\r
1182\r
3f31ea1b
JY
1183 NotReady = FALSE;\r
1184 Abort = FALSE;\r
d2a16030
JY
1185\r
1186 DumpFmpCapsule(CapsuleHeader);\r
1187\r
1188 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
1189\r
1190 if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
1191 return EFI_INVALID_PARAMETER;\r
1192 }\r
1193 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
1194\r
1195 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
1196\r
1197 //\r
1198 // capsule in which driver count and payload count are both zero is not processed.\r
1199 //\r
1200 if (ItemNum == 0) {\r
d2a16030
JY
1201 return EFI_SUCCESS;\r
1202 }\r
1203\r
d2a16030
JY
1204 //\r
1205 // 1. Try to load & start all the drivers within capsule\r
1206 //\r
d2a16030 1207 for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\r
3f31ea1b
JY
1208 if ((FmpCapsuleHeader->PayloadItemCount == 0) &&\r
1209 (Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1)) {\r
d2a16030
JY
1210 //\r
1211 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER\r
1212 //\r
1213 DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];\r
1214 } else {\r
1215 DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];\r
1216 }\r
1217\r
3f31ea1b
JY
1218 Status = StartFmpImage (\r
1219 (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],\r
1220 DriverLen\r
1221 );\r
d2a16030
JY
1222 if (EFI_ERROR(Status)) {\r
1223 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
3f31ea1b 1224 return Status;\r
d2a16030
JY
1225 }\r
1226 }\r
1227\r
1228 //\r
1229 // 2. Route payload to right FMP instance\r
1230 //\r
1231 DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));\r
1232\r
3f31ea1b 1233 DumpAllFmpInfo ();\r
8f6db161 1234\r
3f31ea1b
JY
1235 //\r
1236 // Check all the payload entry in capsule payload list\r
1237 //\r
1238 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
1239 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
d2a16030 1240\r
3f31ea1b
JY
1241 UpdateHardwareInstance = 0;\r
1242 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
1243 UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;\r
1244 }\r
d2a16030 1245\r
3f31ea1b
JY
1246 Status = GetFmpHandleBufferByType (\r
1247 &ImageHeader->UpdateImageTypeId,\r
1248 UpdateHardwareInstance,\r
1249 &NumberOfHandles,\r
69feaa37
SZ
1250 &HandleBuffer,\r
1251 &ResetRequiredBuffer\r
3f31ea1b 1252 );\r
df4c1298
SZ
1253 if (EFI_ERROR(Status) ||\r
1254 (HandleBuffer == NULL) ||\r
1255 (ResetRequiredBuffer == NULL)) {\r
3f31ea1b
JY
1256 NotReady = TRUE;\r
1257 RecordFmpCapsuleStatus (\r
1258 NULL,\r
1259 CapsuleHeader,\r
1260 EFI_NOT_READY,\r
1261 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
28889a78
WX
1262 ImageHeader,\r
1263 CapFileName\r
3f31ea1b
JY
1264 );\r
1265 continue;\r
1266 }\r
d2a16030 1267\r
3f31ea1b
JY
1268 for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {\r
1269 if (Abort) {\r
1270 RecordFmpCapsuleStatus (\r
1271 HandleBuffer[Index2],\r
1272 CapsuleHeader,\r
1273 EFI_ABORTED,\r
1274 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
28889a78
WX
1275 ImageHeader,\r
1276 CapFileName\r
3f31ea1b 1277 );\r
d2a16030
JY
1278 continue;\r
1279 }\r
1280\r
3f31ea1b
JY
1281 Status = SetFmpImageData (\r
1282 HandleBuffer[Index2],\r
1283 ImageHeader,\r
1284 Index - FmpCapsuleHeader->EmbeddedDriverCount\r
1285 );\r
1286 if (Status != EFI_SUCCESS) {\r
1287 Abort = TRUE;\r
69feaa37
SZ
1288 } else {\r
1289 if (ResetRequired != NULL) {\r
1290 *ResetRequired |= ResetRequiredBuffer[Index2];\r
1291 }\r
d2a16030
JY
1292 }\r
1293\r
3f31ea1b
JY
1294 RecordFmpCapsuleStatus (\r
1295 HandleBuffer[Index2],\r
1296 CapsuleHeader,\r
1297 Status,\r
1298 Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
28889a78
WX
1299 ImageHeader,\r
1300 CapFileName\r
3f31ea1b 1301 );\r
d2a16030 1302 }\r
3f31ea1b
JY
1303 if (HandleBuffer != NULL) {\r
1304 FreePool(HandleBuffer);\r
d2a16030 1305 }\r
69feaa37
SZ
1306 if (ResetRequiredBuffer != NULL) {\r
1307 FreePool(ResetRequiredBuffer);\r
1308 }\r
d2a16030
JY
1309 }\r
1310\r
3f31ea1b
JY
1311 if (NotReady) {\r
1312 return EFI_NOT_READY;\r
d2a16030
JY
1313 }\r
1314\r
3f31ea1b
JY
1315 //\r
1316 // always return SUCCESS to indicate this capsule is processed.\r
1317 // The status of SetImage is recorded in capsule result variable.\r
1318 //\r
1319 return EFI_SUCCESS;\r
d2a16030
JY
1320}\r
1321\r
1322/**\r
1323 Return if there is a FMP header below capsule header.\r
1324\r
1325 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
1326\r
1327 @retval TRUE There is a FMP header below capsule header.\r
1328 @retval FALSE There is not a FMP header below capsule header\r
1329**/\r
1330BOOLEAN\r
1331IsNestedFmpCapsule (\r
1332 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1333 )\r
1334{\r
1335 EFI_STATUS Status;\r
d2a16030
JY
1336 EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;\r
1337 UINTN Index;\r
1338 BOOLEAN EsrtGuidFound;\r
1339 EFI_CAPSULE_HEADER *NestedCapsuleHeader;\r
1340 UINTN NestedCapsuleSize;\r
1341 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
1342 EFI_SYSTEM_RESOURCE_ENTRY Entry;\r
1343\r
1344 EsrtGuidFound = FALSE;\r
056563f1
JY
1345 if (mIsVirtualAddrConverted) {\r
1346 if(mEsrtTable != NULL) {\r
1347 EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);\r
1348 for (Index = 0; Index < mEsrtTable->FwResourceCount ; Index++, EsrtEntry++) {\r
d2a16030
JY
1349 if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {\r
1350 EsrtGuidFound = TRUE;\r
1351 break;\r
1352 }\r
1353 }\r
1354 }\r
056563f1
JY
1355 } else {\r
1356 //\r
1357 // Check ESRT protocol\r
1358 //\r
1359 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
1360 if (!EFI_ERROR(Status)) {\r
1361 Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);\r
1362 if (!EFI_ERROR(Status)) {\r
1363 EsrtGuidFound = TRUE;\r
1364 }\r
1365 }\r
1366\r
1367 //\r
7f0301e3 1368 // Check Firmware Management Protocols\r
056563f1
JY
1369 //\r
1370 if (!EsrtGuidFound) {\r
7f0301e3
KM
1371 Status = GetFmpHandleBufferByType (\r
1372 &CapsuleHeader->CapsuleGuid,\r
1373 0,\r
69feaa37
SZ
1374 NULL,\r
1375 NULL,\r
1376 NULL\r
7f0301e3 1377 );\r
056563f1 1378 if (!EFI_ERROR(Status)) {\r
7f0301e3
KM
1379 EsrtGuidFound = TRUE;\r
1380 }\r
056563f1 1381 }\r
d2a16030
JY
1382 }\r
1383 if (!EsrtGuidFound) {\r
1384 return FALSE;\r
1385 }\r
1386\r
1387 //\r
1388 // Check nested capsule header\r
1389 // FMP GUID after ESRT one\r
1390 //\r
1391 NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);\r
1392 NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;\r
1393 if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {\r
1394 return FALSE;\r
1395 }\r
1396 if (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {\r
1397 return FALSE;\r
1398 }\r
1399 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {\r
1400 return FALSE;\r
1401 }\r
1402 DEBUG ((DEBUG_INFO, "IsNestedFmpCapsule\n"));\r
1403 return TRUE;\r
1404}\r
1405\r
1406/**\r
1407 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.\r
1408\r
1409 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
1410\r
1411 @retval TRUE It is a system FMP.\r
1412 @retval FALSE It is a device FMP.\r
1413**/\r
1414BOOLEAN\r
1415IsFmpCapsule (\r
1416 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1417 )\r
1418{\r
1419 if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
1420 return TRUE;\r
1421 }\r
1422 if (IsNestedFmpCapsule(CapsuleHeader)) {\r
1423 return TRUE;\r
1424 }\r
1425 return FALSE;\r
1426}\r
1427\r
1428/**\r
1429 Those capsules supported by the firmwares.\r
1430\r
1431 Caution: This function may receive untrusted input.\r
1432\r
1433 @param[in] CapsuleHeader Points to a capsule header.\r
1434\r
1435 @retval EFI_SUCESS Input capsule is supported by firmware.\r
1436 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.\r
1437 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct\r
1438**/\r
1439EFI_STATUS\r
1440EFIAPI\r
1441SupportCapsuleImage (\r
1442 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1443 )\r
1444{\r
1445 //\r
1446 // check Display Capsule Guid\r
1447 //\r
1448 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
1449 return EFI_SUCCESS;\r
1450 }\r
1451\r
28889a78
WX
1452 //\r
1453 // Check capsule file name capsule\r
1454 //\r
1455 if (IsCapsuleNameCapsule(CapsuleHeader)) {\r
1456 return EFI_SUCCESS;\r
1457 }\r
1458\r
d2a16030 1459 if (IsFmpCapsule(CapsuleHeader)) {\r
8a1a7774
LG
1460 //\r
1461 // Fake capsule header is valid case in QueryCapsuleCpapbilities().\r
1462 //\r
1463 if (CapsuleHeader->HeaderSize == CapsuleHeader->CapsuleImageSize) {\r
1464 return EFI_SUCCESS;\r
1465 }\r
d2a16030
JY
1466 //\r
1467 // Check layout of FMP capsule\r
1468 //\r
1469 return ValidateFmpCapsule(CapsuleHeader, NULL);\r
1470 }\r
1471 DEBUG((DEBUG_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));\r
1472 return EFI_UNSUPPORTED;\r
1473}\r
1474\r
1475/**\r
1476 The firmware implements to process the capsule image.\r
1477\r
1478 Caution: This function may receive untrusted input.\r
1479\r
1480 @param[in] CapsuleHeader Points to a capsule header.\r
28889a78 1481 @param[in] CapFileName Capsule file name.\r
69feaa37 1482 @param[out] ResetRequired Indicates whether reset is required or not.\r
d2a16030
JY
1483\r
1484 @retval EFI_SUCESS Process Capsule Image successfully.\r
1485 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
1486 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
1487 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
1488**/\r
1489EFI_STATUS\r
1490EFIAPI\r
69feaa37
SZ
1491ProcessThisCapsuleImage (\r
1492 IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
28889a78 1493 IN CHAR16 *CapFileName, OPTIONAL\r
69feaa37 1494 OUT BOOLEAN *ResetRequired OPTIONAL\r
d2a16030
JY
1495 )\r
1496{\r
1497 EFI_STATUS Status;\r
d2a16030
JY
1498\r
1499 if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {\r
3f31ea1b 1500 RecordCapsuleStatusVariable(CapsuleHeader, EFI_UNSUPPORTED);\r
d2a16030
JY
1501 return EFI_UNSUPPORTED;\r
1502 }\r
1503\r
1504 //\r
1505 // Display image in firmware update display capsule\r
1506 //\r
1507 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
1508 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));\r
1509 Status = DisplayCapsuleImage(CapsuleHeader);\r
1510 RecordCapsuleStatusVariable(CapsuleHeader, Status);\r
1511 return Status;\r
1512 }\r
1513\r
1514 //\r
1515 // Check FMP capsule layout\r
1516 //\r
1517 if (IsFmpCapsule (CapsuleHeader)) {\r
1518 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));\r
1519 DEBUG((DEBUG_INFO, "ValidateFmpCapsule ...\n"));\r
1520 Status = ValidateFmpCapsule(CapsuleHeader, NULL);\r
1521 DEBUG((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));\r
1522 if (EFI_ERROR(Status)) {\r
3f31ea1b 1523 RecordCapsuleStatusVariable(CapsuleHeader, Status);\r
d2a16030
JY
1524 return Status;\r
1525 }\r
1526\r
1527 //\r
a891bd73 1528 // Process EFI FMP Capsule\r
d2a16030
JY
1529 //\r
1530 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));\r
28889a78 1531 Status = ProcessFmpCapsuleImage(CapsuleHeader, CapFileName, ResetRequired);\r
d2a16030
JY
1532 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));\r
1533\r
d2a16030
JY
1534 return Status;\r
1535 }\r
1536\r
1537 return EFI_UNSUPPORTED;\r
1538}\r
1539\r
69feaa37
SZ
1540/**\r
1541 The firmware implements to process the capsule image.\r
1542\r
1543 Caution: This function may receive untrusted input.\r
1544\r
1545 @param[in] CapsuleHeader Points to a capsule header.\r
1546\r
1547 @retval EFI_SUCESS Process Capsule Image successfully.\r
1548 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
1549 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
1550 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
1551**/\r
1552EFI_STATUS\r
1553EFIAPI\r
1554ProcessCapsuleImage (\r
1555 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
1556 )\r
1557{\r
28889a78 1558 return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL);\r
69feaa37
SZ
1559}\r
1560\r
d2a16030
JY
1561/**\r
1562 Callback function executed when the EndOfDxe event group is signaled.\r
1563\r
1564 @param[in] Event Event whose notification function is being invoked.\r
1565 @param[in] Context The pointer to the notification function's context, which\r
1566 is implementation-dependent.\r
1567**/\r
1568VOID\r
1569EFIAPI\r
1570DxeCapsuleLibEndOfDxe (\r
1571 IN EFI_EVENT Event,\r
1572 IN VOID *Context\r
1573 )\r
1574{\r
1575 mDxeCapsuleLibEndOfDxe = TRUE;\r
1576}\r
1577\r
1578/**\r
1579 The constructor function.\r
1580\r
1581 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1582 @param[in] SystemTable A pointer to the EFI System Table.\r
1583\r
1584 @retval EFI_SUCCESS The constructor successfully .\r
1585**/\r
1586EFI_STATUS\r
1587EFIAPI\r
1588DxeCapsuleLibConstructor (\r
1589 IN EFI_HANDLE ImageHandle,\r
1590 IN EFI_SYSTEM_TABLE *SystemTable\r
1591 )\r
1592{\r
d2a16030
JY
1593 EFI_STATUS Status;\r
1594\r
1595 Status = gBS->CreateEventEx (\r
1596 EVT_NOTIFY_SIGNAL,\r
1597 TPL_CALLBACK,\r
1598 DxeCapsuleLibEndOfDxe,\r
1599 NULL,\r
1600 &gEfiEndOfDxeEventGroupGuid,\r
96b17e00 1601 &mDxeCapsuleLibEndOfDxeEvent\r
d2a16030
JY
1602 );\r
1603 ASSERT_EFI_ERROR (Status);\r
1604\r
1605 InitCapsuleVariable();\r
1606\r
1607 return EFI_SUCCESS;\r
1608}\r
96b17e00
HW
1609\r
1610/**\r
1611 The destructor function closes the End of DXE event.\r
1612\r
1613 @param ImageHandle The firmware allocated handle for the EFI image.\r
1614 @param SystemTable A pointer to the EFI System Table.\r
1615\r
1616 @retval EFI_SUCCESS The destructor completed successfully.\r
1617**/\r
1618EFI_STATUS\r
1619EFIAPI\r
1620DxeCapsuleLibDestructor (\r
1621 IN EFI_HANDLE ImageHandle,\r
1622 IN EFI_SYSTEM_TABLE *SystemTable\r
1623 )\r
1624{\r
1625 EFI_STATUS Status;\r
1626\r
1627 //\r
1628 // Close the End of DXE event.\r
1629 //\r
1630 Status = gBS->CloseEvent (mDxeCapsuleLibEndOfDxeEvent);\r
1631 ASSERT_EFI_ERROR (Status);\r
1632\r
1633 return EFI_SUCCESS;\r
1634}\r