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