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