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