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