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