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