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