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