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