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