MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
[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[in] 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 ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) {
1018 AbortReason = NULL;
1019 if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {
1020 if(ImageHeader->UpdateHardwareInstance != 0){
1021 //
1022 // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case
1023 // 1. FMP Image info Version < 3
1024 // 2. HardwareInstance doesn't match
1025 //
1026 if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION ||
1027 ImageHeader->UpdateHardwareInstance != TempFmpImageInfo->HardwareInstance) {
1028 continue;
1029 }
1030 }
1031 Image = (UINT8 *)(ImageHeader + 1);
1032 } else {
1033 //
1034 // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.
1035 // Header should exclude UpdateHardwareInstance field
1036 //
1037 Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);
1038 }
1039
1040 if (ImageHeader->UpdateVendorCodeSize == 0) {
1041 VendorCode = NULL;
1042 } else {
1043 VendorCode = Image + ImageHeader->UpdateImageSize;
1044 }
1045 DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));
1046 Status = Fmp->SetImage(
1047 Fmp,
1048 ImageHeader->UpdateImageIndex, // ImageIndex
1049 Image, // Image
1050 ImageHeader->UpdateImageSize, // ImageSize
1051 VendorCode, // VendorCode
1052 Update_Image_Progress, // Progress
1053 &AbortReason // AbortReason
1054 );
1055 DEBUG((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));
1056 if (AbortReason != NULL) {
1057 DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));
1058 FreePool(AbortReason);
1059 }
1060 RecordFmpCapsuleStatusVariable(
1061 CapsuleHeader, // CapsuleGuid
1062 Status, // CapsuleStatus
1063 Index - FmpCapsuleHeader->EmbeddedDriverCount, // PayloadIndex
1064 ImageHeader // ImageHeader
1065 );
1066 if (StatusRet != EFI_SUCCESS) {
1067 StatusRet = Status;
1068 }
1069 //
1070 // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface
1071 //
1072 if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION && EsrtProtocol != NULL) {
1073 StatusEsrt = EsrtProtocol->GetEsrtEntry(&TempFmpImageInfo->ImageTypeId, &EsrtEntry);
1074 if (!EFI_ERROR(StatusEsrt)){
1075 if (!EFI_ERROR(Status)) {
1076 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
1077 } else {
1078 EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
1079 }
1080 EsrtEntry.LastAttemptVersion = 0;
1081 EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);
1082 }
1083 }
1084 }
1085 }
1086 //
1087 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version
1088 //
1089 TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);
1090 }
1091 FreePool(FmpImageInfoBuf);
1092 }
1093 }
1094
1095 //
1096 // final check for AreAllImagesProcessed
1097 //
1098 *AreAllImagesProcessed = TRUE;
1099 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {
1100 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);
1101
1102 if (!IsFmpCapsuleProcessed(CapsuleHeader, Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader)) {
1103 *AreAllImagesProcessed = FALSE;
1104 break;
1105 }
1106 }
1107
1108 EXIT:
1109
1110 if (HandleBuffer != NULL) {
1111 FreePool(HandleBuffer);
1112 }
1113
1114 if (DriverDevicePath != NULL) {
1115 FreePool(DriverDevicePath);
1116 }
1117
1118 return StatusRet;
1119 }
1120
1121 /**
1122 Return if there is a FMP header below capsule header.
1123
1124 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1125
1126 @retval TRUE There is a FMP header below capsule header.
1127 @retval FALSE There is not a FMP header below capsule header
1128 **/
1129 BOOLEAN
1130 IsNestedFmpCapsule (
1131 IN EFI_CAPSULE_HEADER *CapsuleHeader
1132 )
1133 {
1134 EFI_STATUS Status;
1135 EFI_SYSTEM_RESOURCE_TABLE *Esrt;
1136 EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;
1137 UINTN Index;
1138 BOOLEAN EsrtGuidFound;
1139 EFI_CAPSULE_HEADER *NestedCapsuleHeader;
1140 UINTN NestedCapsuleSize;
1141 ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;
1142 EFI_SYSTEM_RESOURCE_ENTRY Entry;
1143
1144 EsrtGuidFound = FALSE;
1145
1146 //
1147 // Check ESRT protocol
1148 //
1149 Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);
1150 if (!EFI_ERROR(Status)) {
1151 Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);
1152 if (!EFI_ERROR(Status)) {
1153 EsrtGuidFound = TRUE;
1154 }
1155 }
1156
1157 //
1158 // Check ESRT configuration table
1159 //
1160 if (!EsrtGuidFound) {
1161 Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);
1162 if (!EFI_ERROR(Status)) {
1163 ASSERT (Esrt != NULL);
1164 EsrtEntry = (VOID *)(Esrt + 1);
1165 for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {
1166 if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
1167 EsrtGuidFound = TRUE;
1168 break;
1169 }
1170 }
1171 }
1172 }
1173 if (!EsrtGuidFound) {
1174 return FALSE;
1175 }
1176
1177 //
1178 // Check nested capsule header
1179 // FMP GUID after ESRT one
1180 //
1181 NestedCapsuleHeader = (EFI_CAPSULE_HEADER *)((UINT8 *)CapsuleHeader + CapsuleHeader->HeaderSize);
1182 NestedCapsuleSize = (UINTN)CapsuleHeader + CapsuleHeader->CapsuleImageSize - (UINTN)NestedCapsuleHeader;
1183 if (NestedCapsuleSize < sizeof(EFI_CAPSULE_HEADER)) {
1184 return FALSE;
1185 }
1186 if (!IsValidCapsuleHeader(NestedCapsuleHeader, NestedCapsuleSize)) {
1187 return FALSE;
1188 }
1189 if (!IsFmpCapsuleGuid(&NestedCapsuleHeader->CapsuleGuid)) {
1190 return FALSE;
1191 }
1192 DEBUG ((DEBUG_INFO, "IsNestedFmpCapsule\n"));
1193 return TRUE;
1194 }
1195
1196 /**
1197 Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
1198
1199 @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
1200
1201 @retval TRUE It is a system FMP.
1202 @retval FALSE It is a device FMP.
1203 **/
1204 BOOLEAN
1205 IsFmpCapsule (
1206 IN EFI_CAPSULE_HEADER *CapsuleHeader
1207 )
1208 {
1209 if (IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
1210 return TRUE;
1211 }
1212 if (IsNestedFmpCapsule(CapsuleHeader)) {
1213 return TRUE;
1214 }
1215 return FALSE;
1216 }
1217
1218 /**
1219 Those capsules supported by the firmwares.
1220
1221 Caution: This function may receive untrusted input.
1222
1223 @param[in] CapsuleHeader Points to a capsule header.
1224
1225 @retval EFI_SUCESS Input capsule is supported by firmware.
1226 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
1227 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct
1228 **/
1229 EFI_STATUS
1230 EFIAPI
1231 SupportCapsuleImage (
1232 IN EFI_CAPSULE_HEADER *CapsuleHeader
1233 )
1234 {
1235 //
1236 // check Display Capsule Guid
1237 //
1238 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
1239 return EFI_SUCCESS;
1240 }
1241
1242 if (IsFmpCapsule(CapsuleHeader)) {
1243 //
1244 // Check layout of FMP capsule
1245 //
1246 return ValidateFmpCapsule(CapsuleHeader, NULL);
1247 }
1248 DEBUG((DEBUG_ERROR, "Unknown Capsule Guid - %g\n", &CapsuleHeader->CapsuleGuid));
1249 return EFI_UNSUPPORTED;
1250 }
1251
1252 /**
1253 The firmware implements to process the capsule image.
1254
1255 Caution: This function may receive untrusted input.
1256
1257 @param[in] CapsuleHeader Points to a capsule header.
1258
1259 @retval EFI_SUCESS Process Capsule Image successfully.
1260 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
1261 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
1262 @retval EFI_OUT_OF_RESOURCES Not enough memory.
1263 **/
1264 EFI_STATUS
1265 EFIAPI
1266 ProcessCapsuleImage (
1267 IN EFI_CAPSULE_HEADER *CapsuleHeader
1268 )
1269 {
1270 EFI_STATUS Status;
1271 BOOLEAN AreAllImagesProcessed;
1272
1273 if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {
1274 return EFI_UNSUPPORTED;
1275 }
1276
1277 //
1278 // Display image in firmware update display capsule
1279 //
1280 if (CompareGuid (&gWindowsUxCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {
1281 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for WindowsUxCapsule ...\n"));
1282 Status = DisplayCapsuleImage(CapsuleHeader);
1283 RecordCapsuleStatusVariable(CapsuleHeader, Status);
1284 return Status;
1285 }
1286
1287 //
1288 // Check FMP capsule layout
1289 //
1290 if (IsFmpCapsule (CapsuleHeader)) {
1291 DEBUG((DEBUG_INFO, "ProcessCapsuleImage for FmpCapsule ...\n"));
1292 DEBUG((DEBUG_INFO, "ValidateFmpCapsule ...\n"));
1293 Status = ValidateFmpCapsule(CapsuleHeader, NULL);
1294 DEBUG((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));
1295 if (EFI_ERROR(Status)) {
1296 return Status;
1297 }
1298
1299 //
1300 // Press EFI FMP Capsule
1301 //
1302 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
1303 Status = ProcessFmpCapsuleImage(CapsuleHeader, &AreAllImagesProcessed);
1304 DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
1305
1306 if (!AreAllImagesProcessed) {
1307 mAreAllImagesProcessed = FALSE;
1308 }
1309
1310 return Status;
1311 }
1312
1313 return EFI_UNSUPPORTED;
1314 }
1315
1316 /**
1317 Callback function executed when the EndOfDxe event group is signaled.
1318
1319 @param[in] Event Event whose notification function is being invoked.
1320 @param[in] Context The pointer to the notification function's context, which
1321 is implementation-dependent.
1322 **/
1323 VOID
1324 EFIAPI
1325 DxeCapsuleLibEndOfDxe (
1326 IN EFI_EVENT Event,
1327 IN VOID *Context
1328 )
1329 {
1330 mDxeCapsuleLibEndOfDxe = TRUE;
1331 }
1332
1333 /**
1334 The constructor function.
1335
1336 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1337 @param[in] SystemTable A pointer to the EFI System Table.
1338
1339 @retval EFI_SUCCESS The constructor successfully .
1340 **/
1341 EFI_STATUS
1342 EFIAPI
1343 DxeCapsuleLibConstructor (
1344 IN EFI_HANDLE ImageHandle,
1345 IN EFI_SYSTEM_TABLE *SystemTable
1346 )
1347 {
1348 EFI_EVENT EndOfDxeEvent;
1349 EFI_STATUS Status;
1350
1351 Status = gBS->CreateEventEx (
1352 EVT_NOTIFY_SIGNAL,
1353 TPL_CALLBACK,
1354 DxeCapsuleLibEndOfDxe,
1355 NULL,
1356 &gEfiEndOfDxeEventGroupGuid,
1357 &EndOfDxeEvent
1358 );
1359 ASSERT_EFI_ERROR (Status);
1360
1361 InitCapsuleVariable();
1362
1363 return EFI_SUCCESS;
1364 }