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