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