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