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