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