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