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