]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
85848279d44c370861302010aabd9dca6861a302
[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 FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);
272 if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||
273 (ImageHeader->Version < 1)) {
274 DEBUG((DEBUG_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));
275 return EFI_INVALID_PARAMETER;
276 }
277 if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
278 FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
279 }
280 if (FmpImageSize < FmpImageHeaderSize) {
281 DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize, FmpImageHeaderSize));
282 return EFI_INVALID_PARAMETER;
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 FreePool (HandleBuffer);
614
615 return ;
616 }
617
618 /**
619 Get FMP handle by ImageTypeId and HardwareInstance.
620
621 @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.
622 @param[in] UpdateHardwareInstance The HardwareInstance to target with this update.
623 @param[out] NoHandles The number of handles returned in HandleBuf.
624 @param[out] HandleBuf A pointer to the buffer to return the requested array of handles.
625 @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for
626 the requested array of handles.
627
628 @retval EFI_SUCCESS The array of handles and their reset required flag were returned in
629 HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf
630 was returned in NoHandles.
631 @retval EFI_NOT_FOUND No handles match the search.
632 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
633 **/
634 EFI_STATUS
635 GetFmpHandleBufferByType (
636 IN EFI_GUID *UpdateImageTypeId,
637 IN UINT64 UpdateHardwareInstance,
638 OUT UINTN *NoHandles, OPTIONAL
639 OUT EFI_HANDLE **HandleBuf, OPTIONAL
640 OUT BOOLEAN **ResetRequiredBuf OPTIONAL
641 )
642 {
643 EFI_STATUS Status;
644 EFI_HANDLE *HandleBuffer;
645 UINTN NumberOfHandles;
646 EFI_HANDLE *MatchedHandleBuffer;
647 BOOLEAN *MatchedResetRequiredBuffer;
648 UINTN MatchedNumberOfHandles;
649 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
650 UINTN Index;
651 UINTN ImageInfoSize;
652 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
653 UINT32 FmpImageInfoDescriptorVer;
654 UINT8 FmpImageInfoCount;
655 UINTN DescriptorSize;
656 UINT32 PackageVersion;
657 CHAR16 *PackageVersionName;
658 UINTN Index2;
659 EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;
660
661 if (NoHandles != NULL) {
662 *NoHandles = 0;
663 }
664 if (HandleBuf != NULL) {
665 *HandleBuf = NULL;
666 }
667 if (ResetRequiredBuf != NULL) {
668 *ResetRequiredBuf = NULL;
669 }
670
671 Status = gBS->LocateHandleBuffer (
672 ByProtocol,
673 &gEfiFirmwareManagementProtocolGuid,
674 NULL,
675 &NumberOfHandles,
676 &HandleBuffer
677 );
678 if (EFI_ERROR(Status)) {
679 return Status;
680 }
681
682 MatchedNumberOfHandles = 0;
683
684 MatchedHandleBuffer = NULL;
685 if (HandleBuf != NULL) {
686 MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles);
687 if (MatchedHandleBuffer == NULL) {
688 FreePool (HandleBuffer);
689 return EFI_OUT_OF_RESOURCES;
690 }
691 }
692
693 MatchedResetRequiredBuffer = NULL;
694 if (ResetRequiredBuf != NULL) {
695 MatchedResetRequiredBuffer = AllocateZeroPool (sizeof(BOOLEAN) * NumberOfHandles);
696 if (MatchedResetRequiredBuffer == NULL) {
697 if (MatchedHandleBuffer != NULL) {
698 FreePool (MatchedHandleBuffer);
699 }
700 FreePool (HandleBuffer);
701 return EFI_OUT_OF_RESOURCES;
702 }
703 }
704
705 for (Index = 0; Index < NumberOfHandles; Index++) {
706 Status = gBS->HandleProtocol(
707 HandleBuffer[Index],
708 &gEfiFirmwareManagementProtocolGuid,
709 (VOID **)&Fmp
710 );
711 if (EFI_ERROR(Status)) {
712 continue;
713 }
714
715 ImageInfoSize = 0;
716 Status = Fmp->GetImageInfo (
717 Fmp,
718 &ImageInfoSize,
719 NULL,
720 NULL,
721 NULL,
722 NULL,
723 NULL,
724 NULL
725 );
726 if (Status != EFI_BUFFER_TOO_SMALL) {
727 continue;
728 }
729
730 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
731 if (FmpImageInfoBuf == NULL) {
732 continue;
733 }
734
735 PackageVersionName = NULL;
736 Status = Fmp->GetImageInfo (
737 Fmp,
738 &ImageInfoSize, // ImageInfoSize
739 FmpImageInfoBuf, // ImageInfo
740 &FmpImageInfoDescriptorVer, // DescriptorVersion
741 &FmpImageInfoCount, // DescriptorCount
742 &DescriptorSize, // DescriptorSize
743 &PackageVersion, // PackageVersion
744 &PackageVersionName // PackageVersionName
745 );
746 if (EFI_ERROR(Status)) {
747 FreePool(FmpImageInfoBuf);
748 continue;
749 }
750
751 if (PackageVersionName != NULL) {
752 FreePool(PackageVersionName);
753 }
754
755 TempFmpImageInfo = FmpImageInfoBuf;
756 for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {
757 //
758 // Check if this FMP instance matches
759 //
760 if (CompareGuid(UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId)) {
761 if ((UpdateHardwareInstance == 0) ||
762 ((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) &&
763 (UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance))) {
764 if (MatchedHandleBuffer != NULL) {
765 MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];
766 }
767 if (MatchedResetRequiredBuffer != NULL) {
768 MatchedResetRequiredBuffer[MatchedNumberOfHandles] = (((TempFmpImageInfo->AttributesSupported &
769 IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) &&
770 ((TempFmpImageInfo->AttributesSetting &
771 IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0));
772 }
773 MatchedNumberOfHandles++;
774 break;
775 }
776 }
777 TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
778 }
779 FreePool(FmpImageInfoBuf);
780 }
781
782 FreePool (HandleBuffer);
783
784 if (MatchedNumberOfHandles == 0) {
785 return EFI_NOT_FOUND;
786 }
787
788 if (NoHandles != NULL) {
789 *NoHandles = MatchedNumberOfHandles;
790 }
791 if (HandleBuf != NULL) {
792 *HandleBuf = MatchedHandleBuffer;
793 }
794 if (ResetRequiredBuf != NULL) {
795 *ResetRequiredBuf = MatchedResetRequiredBuffer;
796 }
797
798 return EFI_SUCCESS;
799 }
800
801 /**
802 Return FmpImageInfoDescriptorVer by an FMP handle.
803
804 @param[in] Handle A FMP handle.
805
806 @return FmpImageInfoDescriptorVer associated with the FMP.
807 **/
808 UINT32
809 GetFmpImageInfoDescriptorVer (
810 IN EFI_HANDLE Handle
811 )
812 {
813 EFI_STATUS Status;
814 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
815 UINTN ImageInfoSize;
816 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;
817 UINT32 FmpImageInfoDescriptorVer;
818 UINT8 FmpImageInfoCount;
819 UINTN DescriptorSize;
820 UINT32 PackageVersion;
821 CHAR16 *PackageVersionName;
822
823 Status = gBS->HandleProtocol(
824 Handle,
825 &gEfiFirmwareManagementProtocolGuid,
826 (VOID **)&Fmp
827 );
828 if (EFI_ERROR(Status)) {
829 return 0;
830 }
831
832 ImageInfoSize = 0;
833 Status = Fmp->GetImageInfo (
834 Fmp,
835 &ImageInfoSize,
836 NULL,
837 NULL,
838 NULL,
839 NULL,
840 NULL,
841 NULL
842 );
843 if (Status != EFI_BUFFER_TOO_SMALL) {
844 return 0;
845 }
846
847 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);
848 if (FmpImageInfoBuf == NULL) {
849 return 0;
850 }
851
852 PackageVersionName = NULL;
853 Status = Fmp->GetImageInfo (
854 Fmp,
855 &ImageInfoSize, // ImageInfoSize
856 FmpImageInfoBuf, // ImageInfo
857 &FmpImageInfoDescriptorVer, // DescriptorVersion
858 &FmpImageInfoCount, // DescriptorCount
859 &DescriptorSize, // DescriptorSize
860 &PackageVersion, // PackageVersion
861 &PackageVersionName // PackageVersionName
862 );
863 if (EFI_ERROR(Status)) {
864 FreePool(FmpImageInfoBuf);
865 return 0;
866 }
867 return FmpImageInfoDescriptorVer;
868 }
869
870 /**
871 Set FMP image data.
872
873 @param[in] Handle A FMP handle.
874 @param[in] ImageHeader The payload image header.
875 @param[in] PayloadIndex The index of the payload.
876
877 @return The status of FMP->SetImage.
878 **/
879 EFI_STATUS
880 SetFmpImageData (
881 IN EFI_HANDLE Handle,
882 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
883 IN UINTN PayloadIndex
884 )
885 {
886 EFI_STATUS Status;
887 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
888 UINT8 *Image;
889 VOID *VendorCode;
890 CHAR16 *AbortReason;
891 EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback;
892
893 Status = gBS->HandleProtocol(
894 Handle,
895 &gEfiFirmwareManagementProtocolGuid,
896 (VOID **)&Fmp
897 );
898 if (EFI_ERROR(Status)) {
899 return Status;
900 }
901
902 //
903 // Lookup Firmware Management Progress Protocol before SetImage() is called
904 // This is an optional protocol that may not be present on Handle.
905 //
906 Status = gBS->HandleProtocol (
907 Handle,
908 &gEdkiiFirmwareManagementProgressProtocolGuid,
909 (VOID **)&mFmpProgress
910 );
911 if (EFI_ERROR (Status)) {
912 mFmpProgress = NULL;
913 }
914
915 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
916 Image = (UINT8 *)(ImageHeader + 1);
917 } else {
918 //
919 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,
920 // Header should exclude UpdateHardwareInstance field
921 //
922 Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
923 }
924
925 if (ImageHeader->UpdateVendorCodeSize == 0) {
926 VendorCode = NULL;
927 } else {
928 VendorCode = Image + ImageHeader->UpdateImageSize;
929 }
930 AbortReason = NULL;
931 DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));
932 DEBUG((DEBUG_INFO, "ImageTypeId - %g, ", &ImageHeader->UpdateImageTypeId));
933 DEBUG((DEBUG_INFO, "PayloadIndex - 0x%x, ", PayloadIndex));
934 DEBUG((DEBUG_INFO, "ImageIndex - 0x%x ", ImageHeader->UpdateImageIndex));
935 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
936 DEBUG((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));
937 }
938 DEBUG((DEBUG_INFO, "\n"));
939
940 //
941 // Before calling SetImage(), reset the progress bar to 0%
942 //
943 ProgressCallback = UpdateImageProgress;
944 Status = UpdateImageProgress (0);
945 if (EFI_ERROR (Status)) {
946 ProgressCallback = NULL;
947 }
948
949 Status = Fmp->SetImage(
950 Fmp,
951 ImageHeader->UpdateImageIndex, // ImageIndex
952 Image, // Image
953 ImageHeader->UpdateImageSize, // ImageSize
954 VendorCode, // VendorCode
955 ProgressCallback, // Progress
956 &AbortReason // AbortReason
957 );
958 //
959 // Set the progress bar to 100% after returning from SetImage()
960 //
961 if (ProgressCallback != NULL) {
962 UpdateImageProgress (100);
963 }
964
965 DEBUG((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));
966 if (AbortReason != NULL) {
967 DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));
968 FreePool(AbortReason);
969 }
970
971 //
972 // Clear mFmpProgress after SetImage() returns
973 //
974 mFmpProgress = NULL;
975
976 return Status;
977 }
978
979 /**
980 Start a UEFI image in the FMP payload.
981
982 @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..
983 @param[in] ImageSize The size in bytes of ImageBuffer.
984
985 @return The status of gBS->LoadImage and gBS->StartImage.
986 **/
987 EFI_STATUS
988 StartFmpImage (
989 IN VOID *ImageBuffer,
990 IN UINTN ImageSize
991 )
992 {
993 MEMMAP_DEVICE_PATH MemMapNode;
994 EFI_STATUS Status;
995 EFI_HANDLE ImageHandle;
996 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;
997 UINTN ExitDataSize;
998
999 SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));
1000 MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;
1001 MemMapNode.Header.SubType = HW_MEMMAP_DP;
1002 MemMapNode.MemoryType = EfiBootServicesCode;
1003 MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBuffer;
1004 MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)ImageBuffer + ImageSize - 1);
1005
1006 DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);
1007 if (DriverDevicePath == NULL) {
1008 return EFI_OUT_OF_RESOURCES;
1009 }
1010
1011 DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));
1012 Status = gBS->LoadImage(
1013 FALSE,
1014 gImageHandle,
1015 DriverDevicePath,
1016 ImageBuffer,
1017 ImageSize,
1018 &ImageHandle
1019 );
1020 DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));
1021 if (EFI_ERROR(Status)) {
1022 FreePool(DriverDevicePath);
1023 return Status;
1024 }
1025
1026 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));
1027 Status = gBS->StartImage(
1028 ImageHandle,
1029 &ExitDataSize,
1030 NULL
1031 );
1032 DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));
1033 if (EFI_ERROR(Status)) {
1034 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
1035 }
1036
1037 FreePool(DriverDevicePath);
1038 return Status;
1039 }
1040
1041 /**
1042 Record FMP capsule status.
1043
1044 @param[in] Handle A FMP handle.
1045 @param[in] CapsuleHeader The capsule image header
1046 @param[in] CapsuleStatus The capsule process stauts
1047 @param[in] PayloadIndex FMP payload index
1048 @param[in] ImageHeader FMP image header
1049 **/
1050 VOID
1051 RecordFmpCapsuleStatus (
1052 IN EFI_HANDLE Handle, OPTIONAL
1053 IN EFI_CAPSULE_HEADER *CapsuleHeader,
1054 IN EFI_STATUS CapsuleStatus,
1055 IN UINTN PayloadIndex,
1056 IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
1057 )
1058 {
1059 EFI_STATUS Status;
1060 EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath;
1061 UINT32 FmpImageInfoDescriptorVer;
1062 EFI_STATUS StatusEsrt;
1063 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
1064 EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;
1065
1066 FmpDevicePath = NULL;
1067 if (Handle != NULL) {
1068 gBS->HandleProtocol(
1069 Handle,
1070 &gEfiDevicePathProtocolGuid,
1071 (VOID **)&FmpDevicePath
1072 );
1073 }
1074
1075 RecordFmpCapsuleStatusVariable (
1076 CapsuleHeader,
1077 CapsuleStatus,
1078 PayloadIndex,
1079 ImageHeader,
1080 FmpDevicePath
1081 );
1082
1083 //
1084 // Update corresponding ESRT entry LastAttemp Status
1085 //
1086 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
1087 if (EFI_ERROR (Status)) {
1088 return ;
1089 }
1090
1091 if (Handle == NULL) {
1092 return ;
1093 }
1094
1095 //
1096 // Update EsrtEntry For V1, V2 FMP instance.
1097 // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface
1098 //
1099 FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);
1100 if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {
1101 StatusEsrt = EsrtProtocol->GetEsrtEntry(&ImageHeader->UpdateImageTypeId, &EsrtEntry);
1102 if (!EFI_ERROR(StatusEsrt)){
1103 if (!EFI_ERROR(CapsuleStatus)) {
1104 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
1105 } else {
1106 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
1107 }
1108 EsrtEntry.LastAttemptVersion = 0;
1109 EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
1110 }
1111 }
1112 }
1113
1114 /**
1115 Process Firmware management protocol data capsule.
1116
1117 This function assumes the caller validated the capsule by using
1118 ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,
1119 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and
1120 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.
1121
1122 This function need support nested FMP capsule.
1123
1124 @param[in] CapsuleHeader Points to a capsule header.
1125 @param[out] ResetRequired Indicates whether reset is required or not.
1126
1127 @retval EFI_SUCESS Process Capsule Image successfully.
1128 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1129 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1130 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1131 @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.
1132 **/
1133 EFI_STATUS
1134 ProcessFmpCapsuleImage (
1135 IN EFI_CAPSULE_HEADER *CapsuleHeader,
1136 OUT BOOLEAN *ResetRequired OPTIONAL
1137 )
1138 {
1139 EFI_STATUS Status;
1140 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;
1141 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;
1142 UINT64 *ItemOffsetList;
1143 UINT32 ItemNum;
1144 UINTN Index;
1145 EFI_HANDLE *HandleBuffer;
1146 BOOLEAN *ResetRequiredBuffer;
1147 UINTN NumberOfHandles;
1148 UINTN DriverLen;
1149 UINT64 UpdateHardwareInstance;
1150 UINTN Index2;
1151 BOOLEAN NotReady;
1152 BOOLEAN Abort;
1153
1154 if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
1155 return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);
1156 }
1157
1158 NotReady = FALSE;
1159 Abort = FALSE;
1160
1161 DumpFmpCapsule(CapsuleHeader);
1162
1163 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);
1164
1165 if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {
1166 return EFI_INVALID_PARAMETER;
1167 }
1168 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);
1169
1170 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;
1171
1172 //
1173 // capsule in which driver count and payload count are both zero is not processed.
1174 //
1175 if (ItemNum == 0) {
1176 return EFI_SUCCESS;
1177 }
1178
1179 //
1180 // 1. Try to load & start all the drivers within capsule
1181 //
1182 for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {
1183 if ((FmpCapsuleHeader->PayloadItemCount == 0) &&
1184 (Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1)) {
1185 //
1186 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER
1187 //
1188 DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];
1189 } else {
1190 DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];
1191 }
1192
1193 Status = StartFmpImage (
1194 (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],
1195 DriverLen
1196 );
1197 if (EFI_ERROR(Status)) {
1198 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));
1199 return Status;
1200 }
1201 }
1202
1203 //
1204 // 2. Route payload to right FMP instance
1205 //
1206 DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));
1207
1208 DumpAllFmpInfo ();
1209
1210 //
1211 // Check all the payload entry in capsule payload list
1212 //
1213 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
1214 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
1215
1216 UpdateHardwareInstance = 0;
1217 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
1218 UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;
1219 }
1220
1221 Status = GetFmpHandleBufferByType (
1222 &ImageHeader->UpdateImageTypeId,
1223 UpdateHardwareInstance,
1224 &NumberOfHandles,
1225 &HandleBuffer,
1226 &ResetRequiredBuffer
1227 );
1228 if (EFI_ERROR(Status)) {
1229 NotReady = TRUE;
1230 RecordFmpCapsuleStatus (
1231 NULL,
1232 CapsuleHeader,
1233 EFI_NOT_READY,
1234 Index - FmpCapsuleHeader->EmbeddedDriverCount,
1235 ImageHeader
1236 );
1237 continue;
1238 }
1239
1240 for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {
1241 if (Abort) {
1242 RecordFmpCapsuleStatus (
1243 HandleBuffer[Index2],
1244 CapsuleHeader,
1245 EFI_ABORTED,
1246 Index - FmpCapsuleHeader->EmbeddedDriverCount,
1247 ImageHeader
1248 );
1249 continue;
1250 }
1251
1252 Status = SetFmpImageData (
1253 HandleBuffer[Index2],
1254 ImageHeader,
1255 Index - FmpCapsuleHeader->EmbeddedDriverCount
1256 );
1257 if (Status != EFI_SUCCESS) {
1258 Abort = TRUE;
1259 } else {
1260 if (ResetRequired != NULL) {
1261 *ResetRequired |= ResetRequiredBuffer[Index2];
1262 }
1263 }
1264
1265 RecordFmpCapsuleStatus (
1266 HandleBuffer[Index2],
1267 CapsuleHeader,
1268 Status,
1269 Index - FmpCapsuleHeader->EmbeddedDriverCount,
1270 ImageHeader
1271 );
1272 }
1273 if (HandleBuffer != NULL) {
1274 FreePool(HandleBuffer);
1275 }
1276 if (ResetRequiredBuffer != NULL) {
1277 FreePool(ResetRequiredBuffer);
1278 }
1279 }
1280
1281 if (NotReady) {
1282 return EFI_NOT_READY;
1283 }
1284
1285 //
1286 // always return SUCCESS to indicate this capsule is processed.
1287 // The status of SetImage is recorded in capsule result variable.
1288 //
1289 return EFI_SUCCESS;
1290 }
1291
1292 /**
1293 Return if there is a FMP header below capsule header.
1294
1295 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1296
1297 @retval TRUE There is a FMP header below capsule header.
1298 @retval FALSE There is not a FMP header below capsule header
1299 **/
1300 BOOLEAN
1301 IsNestedFmpCapsule (
1302 IN EFI_CAPSULE_HEADER *CapsuleHeader
1303 )
1304 {
1305 EFI_STATUS Status;
1306 EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
1307 UINTN Index;
1308 BOOLEAN EsrtGuidFound;
1309 EFI_CAPSULE_HEADER *NestedCapsuleHeader;
1310 UINTN NestedCapsuleSize;
1311 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
1312 EFI_SYSTEM_RESOURCE_ENTRY Entry;
1313
1314 EsrtGuidFound = FALSE;
1315 if (mIsVirtualAddrConverted) {
1316 if(mEsrtTable != NULL) {
1317 EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);
1318 for (Index = 0; Index < mEsrtTable->FwResourceCount ; Index++, EsrtEntry++) {
1319 if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
1320 EsrtGuidFound = TRUE;
1321 break;
1322 }
1323 }
1324 }
1325 } else {
1326 //
1327 // Check ESRT protocol
1328 //
1329 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
1330 if (!EFI_ERROR(Status)) {
1331 Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);
1332 if (!EFI_ERROR(Status)) {
1333 EsrtGuidFound = TRUE;
1334 }
1335 }
1336
1337 //
1338 // Check Firmware Management Protocols
1339 //
1340 if (!EsrtGuidFound) {
1341 Status = GetFmpHandleBufferByType (
1342 &CapsuleHeader->CapsuleGuid,
1343 0,
1344 NULL,
1345 NULL,
1346 NULL
1347 );
1348 if (!EFI_ERROR(Status)) {
1349 EsrtGuidFound = TRUE;
1350 }
1351 }
1352 }
1353 if (!EsrtGuidFound) {
1354 return FALSE;
1355 }
1356
1357 //
1358 // Check nested capsule header
1359 // FMP GUID after ESRT one
1360 //
1361 NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
1362 NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;
1363 if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
1364 return FALSE;
1365 }
1366 if (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {
1367 return FALSE;
1368 }
1369 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {
1370 return FALSE;
1371 }
1372 DEBUG ((DEBUG_INFO, "IsNestedFmpCapsule\n"));
1373 return TRUE;
1374 }
1375
1376 /**
1377 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1378
1379 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1380
1381 @retval TRUE It is a system FMP.
1382 @retval FALSE It is a device FMP.
1383 **/
1384 BOOLEAN
1385 IsFmpCapsule (
1386 IN EFI_CAPSULE_HEADER *CapsuleHeader
1387 )
1388 {
1389 if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
1390 return TRUE;
1391 }
1392 if (IsNestedFmpCapsule(CapsuleHeader)) {
1393 return TRUE;
1394 }
1395 return FALSE;
1396 }
1397
1398 /**
1399 Those capsules supported by the firmwares.
1400
1401 Caution: This function may receive untrusted input.
1402
1403 @param[in] CapsuleHeader Points to a capsule header.
1404
1405 @retval EFI_SUCESS Input capsule is supported by firmware.
1406 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1407 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1408 **/
1409 EFI_STATUS
1410 EFIAPI
1411 SupportCapsuleImage (
1412 IN EFI_CAPSULE_HEADER *CapsuleHeader
1413 )
1414 {
1415 //
1416 // check Display Capsule Guid
1417 //
1418 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
1419 return EFI_SUCCESS;
1420 }
1421
1422 if (IsFmpCapsule(CapsuleHeader)) {
1423 //
1424 // Check layout of FMP capsule
1425 //
1426 return ValidateFmpCapsule(CapsuleHeader, NULL);
1427 }
1428 DEBUG((DEBUG_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));
1429 return EFI_UNSUPPORTED;
1430 }
1431
1432 /**
1433 The firmware implements to process the capsule image.
1434
1435 Caution: This function may receive untrusted input.
1436
1437 @param[in] CapsuleHeader Points to a capsule header.
1438 @param[out] ResetRequired Indicates whether reset is required or not.
1439
1440 @retval EFI_SUCESS Process Capsule Image successfully.
1441 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1442 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1443 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1444 **/
1445 EFI_STATUS
1446 EFIAPI
1447 ProcessThisCapsuleImage (
1448 IN EFI_CAPSULE_HEADER *CapsuleHeader,
1449 OUT BOOLEAN *ResetRequired OPTIONAL
1450 )
1451 {
1452 EFI_STATUS Status;
1453
1454 if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
1455 RecordCapsuleStatusVariable(CapsuleHeader, EFI_UNSUPPORTED);
1456 return EFI_UNSUPPORTED;
1457 }
1458
1459 //
1460 // Display image in firmware update display capsule
1461 //
1462 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
1463 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1464 Status = DisplayCapsuleImage(CapsuleHeader);
1465 RecordCapsuleStatusVariable(CapsuleHeader, Status);
1466 return Status;
1467 }
1468
1469 //
1470 // Check FMP capsule layout
1471 //
1472 if (IsFmpCapsule (CapsuleHeader)) {
1473 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
1474 DEBUG((DEBUG_INFO, "ValidateFmpCapsule ...\n"));
1475 Status = ValidateFmpCapsule(CapsuleHeader, NULL);
1476 DEBUG((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));
1477 if (EFI_ERROR(Status)) {
1478 RecordCapsuleStatusVariable(CapsuleHeader, Status);
1479 return Status;
1480 }
1481
1482 //
1483 // Process EFI FMP Capsule
1484 //
1485 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
1486 Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);
1487 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
1488
1489 return Status;
1490 }
1491
1492 return EFI_UNSUPPORTED;
1493 }
1494
1495 /**
1496 The firmware implements to process the capsule image.
1497
1498 Caution: This function may receive untrusted input.
1499
1500 @param[in] CapsuleHeader Points to a capsule header.
1501
1502 @retval EFI_SUCESS Process Capsule Image successfully.
1503 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1504 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1505 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1506 **/
1507 EFI_STATUS
1508 EFIAPI
1509 ProcessCapsuleImage (
1510 IN EFI_CAPSULE_HEADER *CapsuleHeader
1511 )
1512 {
1513 return ProcessThisCapsuleImage (CapsuleHeader, NULL);
1514 }
1515
1516 /**
1517 Callback function executed when the EndOfDxe event group is signaled.
1518
1519 @param[in] Event Event whose notification function is being invoked.
1520 @param[in] Context The pointer to the notification function's context, which
1521 is implementation-dependent.
1522 **/
1523 VOID
1524 EFIAPI
1525 DxeCapsuleLibEndOfDxe (
1526 IN EFI_EVENT Event,
1527 IN VOID *Context
1528 )
1529 {
1530 mDxeCapsuleLibEndOfDxe = TRUE;
1531 }
1532
1533 /**
1534 The constructor function.
1535
1536 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1537 @param[in] SystemTable A pointer to the EFI System Table.
1538
1539 @retval EFI_SUCCESS The constructor successfully .
1540 **/
1541 EFI_STATUS
1542 EFIAPI
1543 DxeCapsuleLibConstructor (
1544 IN EFI_HANDLE ImageHandle,
1545 IN EFI_SYSTEM_TABLE *SystemTable
1546 )
1547 {
1548 EFI_STATUS Status;
1549
1550 Status = gBS->CreateEventEx (
1551 EVT_NOTIFY_SIGNAL,
1552 TPL_CALLBACK,
1553 DxeCapsuleLibEndOfDxe,
1554 NULL,
1555 &gEfiEndOfDxeEventGroupGuid,
1556 &mDxeCapsuleLibEndOfDxeEvent
1557 );
1558 ASSERT_EFI_ERROR (Status);
1559
1560 InitCapsuleVariable();
1561
1562 return EFI_SUCCESS;
1563 }
1564
1565 /**
1566 The destructor function closes the End of DXE event.
1567
1568 @param ImageHandle The firmware allocated handle for the EFI image.
1569 @param SystemTable A pointer to the EFI System Table.
1570
1571 @retval EFI_SUCCESS The destructor completed successfully.
1572 **/
1573 EFI_STATUS
1574 EFIAPI
1575 DxeCapsuleLibDestructor (
1576 IN EFI_HANDLE ImageHandle,
1577 IN EFI_SYSTEM_TABLE *SystemTable
1578 )
1579 {
1580 EFI_STATUS Status;
1581
1582 //
1583 // Close the End of DXE event.
1584 //
1585 Status = gBS->CloseEvent (mDxeCapsuleLibEndOfDxeEvent);
1586 ASSERT_EFI_ERROR (Status);
1587
1588 return EFI_SUCCESS;
1589 }