]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.c
Fix a bug in DxeImageVerificationLib which will pass incorrect trust cert size to...
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / BootGraphicsResourceTableDxe / BootGraphicsResourceTableDxe.c
CommitLineData
0284e90c
LG
1/** @file\r
2 This module install ACPI Boot Graphics Resource Table (BGRT).\r
3\r
cbafa15e 4 Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
0284e90c
LG
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12**/\r
13\r
14#include <Uefi.h>\r
15\r
16#include <IndustryStandard/Acpi50.h>\r
17#include <IndustryStandard/Bmp.h>\r
18\r
19#include <Protocol/AcpiTable.h>\r
20#include <Protocol/GraphicsOutput.h>\r
21#include <Protocol/BootLogo.h>\r
22\r
23#include <Guid/EventGroup.h>\r
24\r
25#include <Library/BaseLib.h>\r
26#include <Library/BaseMemoryLib.h>\r
27#include <Library/MemoryAllocationLib.h>\r
28#include <Library/UefiBootServicesTableLib.h>\r
29#include <Library/DebugLib.h>\r
30\r
31//\r
32// ACPI table information used to initialize tables.\r
33//\r
34#define EFI_ACPI_OEM_ID "INTEL"\r
35#define EFI_ACPI_OEM_TABLE_ID 0x2020204F4E414954ULL // "TIANO "\r
36#define EFI_ACPI_OEM_REVISION 0x00000001\r
37#define EFI_ACPI_CREATOR_ID 0x5446534D // TBD "MSFT"\r
38#define EFI_ACPI_CREATOR_REVISION 0x01000013 // TBD\r
39\r
40//\r
41// Module globals.\r
42//\r
43EFI_EVENT mBootGraphicsReadyToBootEvent;\r
44UINTN mBootGraphicsResourceTableKey = 0;\r
45\r
46EFI_HANDLE mBootLogoHandle = NULL;\r
47BOOLEAN mIsLogoValid = FALSE;\r
48EFI_GRAPHICS_OUTPUT_BLT_PIXEL *mLogoBltBuffer = NULL;\r
49UINTN mLogoDestX = 0;\r
50UINTN mLogoDestY = 0;\r
51UINTN mLogoWidth = 0;\r
52UINTN mLogoHeight = 0;\r
53\r
54BMP_IMAGE_HEADER mBmpImageHeaderTemplate = {\r
55 'B', // CharB\r
56 'M', // CharM\r
57 0, // Size will be updated at runtime\r
58 {0, 0}, // Reserved\r
59 sizeof (BMP_IMAGE_HEADER), // ImageOffset\r
60 sizeof (BMP_IMAGE_HEADER) - OFFSET_OF (BMP_IMAGE_HEADER, HeaderSize), // HeaderSize\r
61 0, // PixelWidth will be updated at runtime\r
62 0, // PixelHeight will be updated at runtime\r
63 1, // Planes\r
64 24, // BitPerPixel\r
65 0, // CompressionType\r
66 0, // ImageSize will be updated at runtime\r
67 0, // XPixelsPerMeter\r
68 0, // YPixelsPerMeter\r
69 0, // NumberOfColors\r
70 0 // ImportantColors\r
71};\r
72\r
73BOOLEAN mAcpiBgrtInstalled = FALSE;\r
cbafa15e 74BOOLEAN mAcpiBgrtStatusChanged = FALSE;\r
75BOOLEAN mAcpiBgrtBufferChanged = FALSE;\r
0284e90c
LG
76\r
77EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE mBootGraphicsResourceTableTemplate = {\r
78 {\r
79 EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE,\r
80 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),\r
81 EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION, // Revision\r
82 0x00, // Checksum will be updated at runtime\r
83 //\r
84 // It is expected that these values will be updated at runtime.\r
85 //\r
86 EFI_ACPI_OEM_ID, // OEMID is a 6 bytes long field\r
87 EFI_ACPI_OEM_TABLE_ID, // OEM table identification(8 bytes long)\r
88 EFI_ACPI_OEM_REVISION, // OEM revision number\r
89 EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID\r
90 EFI_ACPI_CREATOR_REVISION, // ASL compiler revision number\r
91 },\r
92 EFI_ACPI_5_0_BGRT_VERSION, // Version\r
93 EFI_ACPI_5_0_BGRT_STATUS_VALID, // Status\r
94 EFI_ACPI_5_0_BGRT_IMAGE_TYPE_BMP, // Image Type\r
95 0, // Image Address\r
96 0, // Image Offset X\r
97 0 // Image Offset Y\r
98};\r
99\r
100/**\r
101 Update information of logo image drawn on screen.\r
102\r
103 @param This The pointer to the Boot Logo protocol instance.\r
104 @param BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer\r
105 is set to NULL, it indicates that logo image is no\r
106 longer on the screen.\r
107 @param DestinationX X coordinate of destination for the BltBuffer.\r
108 @param DestinationY Y coordinate of destination for the BltBuffer.\r
109 @param Width Width of rectangle in BltBuffer in pixels.\r
110 @param Height Hight of rectangle in BltBuffer in pixels.\r
111\r
112 @retval EFI_SUCCESS The boot logo information was updated.\r
113 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
114 @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to\r
115 insufficient memory resources.\r
116\r
117**/\r
118EFI_STATUS\r
119EFIAPI\r
120SetBootLogo (\r
121 IN EFI_BOOT_LOGO_PROTOCOL *This,\r
122 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
123 IN UINTN DestinationX,\r
124 IN UINTN DestinationY,\r
125 IN UINTN Width,\r
126 IN UINTN Height\r
127 );\r
128\r
129EFI_BOOT_LOGO_PROTOCOL mBootLogoProtocolTemplate = { SetBootLogo };\r
130\r
131/**\r
132 Update information of logo image drawn on screen.\r
133\r
134 @param This The pointer to the Boot Logo protocol instance.\r
135 @param BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer\r
136 is set to NULL, it indicates that logo image is no\r
137 longer on the screen.\r
138 @param DestinationX X coordinate of destination for the BltBuffer.\r
139 @param DestinationY Y coordinate of destination for the BltBuffer.\r
140 @param Width Width of rectangle in BltBuffer in pixels.\r
141 @param Height Hight of rectangle in BltBuffer in pixels.\r
142\r
143 @retval EFI_SUCCESS The boot logo information was updated.\r
144 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
145 @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to\r
146 insufficient memory resources.\r
147\r
148**/\r
149EFI_STATUS\r
150EFIAPI\r
151SetBootLogo (\r
152 IN EFI_BOOT_LOGO_PROTOCOL *This,\r
153 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,\r
154 IN UINTN DestinationX,\r
155 IN UINTN DestinationY,\r
156 IN UINTN Width,\r
157 IN UINTN Height\r
158 )\r
159{\r
a46c3657
ED
160 UINT64 BufferSize;\r
161\r
0284e90c
LG
162 if (BltBuffer == NULL) {\r
163 mIsLogoValid = FALSE;\r
cbafa15e 164 mAcpiBgrtStatusChanged = TRUE;\r
0284e90c
LG
165 return EFI_SUCCESS;\r
166 }\r
167\r
168 if (Width == 0 || Height == 0) {\r
169 return EFI_INVALID_PARAMETER;\r
170 }\r
cbafa15e 171 \r
172 mAcpiBgrtBufferChanged = TRUE;\r
0284e90c
LG
173 if (mLogoBltBuffer != NULL) {\r
174 FreePool (mLogoBltBuffer);\r
cbafa15e 175 mLogoBltBuffer = NULL;\r
0284e90c 176 }\r
a46c3657
ED
177 \r
178 //\r
179 // Ensure the Height * Width doesn't overflow\r
180 //\r
181 if (Height > DivU64x64Remainder ((UINTN) ~0, Width, NULL)) {\r
182 return EFI_UNSUPPORTED;\r
183 }\r
184 BufferSize = MultU64x64 (Width, Height);\r
185 \r
186 //\r
187 // Ensure the BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
188 //\r
189 if (BufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
190 return EFI_UNSUPPORTED;\r
191 }\r
0284e90c
LG
192\r
193 mLogoBltBuffer = AllocateCopyPool (\r
a46c3657 194 (UINTN)BufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),\r
0284e90c
LG
195 BltBuffer\r
196 );\r
197 if (mLogoBltBuffer == NULL) {\r
198 return EFI_OUT_OF_RESOURCES;\r
199 }\r
200 mLogoDestX = DestinationX;\r
201 mLogoDestY = DestinationY;\r
202 mLogoWidth = Width;\r
203 mLogoHeight = Height;\r
204 mIsLogoValid = TRUE;\r
205\r
206 return EFI_SUCCESS;\r
207}\r
208\r
209/**\r
210 This function calculates and updates an UINT8 checksum.\r
211\r
212 @param[in] Buffer Pointer to buffer to checksum.\r
213 @param[in] Size Number of bytes to checksum.\r
214\r
215**/\r
216VOID\r
217BgrtAcpiTableChecksum (\r
218 IN UINT8 *Buffer,\r
219 IN UINTN Size\r
220 )\r
221{\r
222 UINTN ChecksumOffset;\r
223\r
224 ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);\r
225\r
226 //\r
227 // Set checksum to 0 first.\r
228 //\r
229 Buffer[ChecksumOffset] = 0;\r
230\r
231 //\r
232 // Update checksum value.\r
233 //\r
234 Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);\r
235}\r
236\r
237/**\r
238 Allocate EfiReservedMemoryType below 4G memory address.\r
239\r
240 This function allocates EfiReservedMemoryType below 4G memory address.\r
241\r
242 @param[in] Size Size of memory to allocate.\r
243\r
244 @return Allocated address for output.\r
245\r
246**/\r
247VOID *\r
248BgrtAllocateReservedMemoryBelow4G (\r
249 IN UINTN Size\r
250 )\r
251{\r
252 UINTN Pages;\r
253 EFI_PHYSICAL_ADDRESS Address;\r
254 EFI_STATUS Status;\r
255 VOID *Buffer;\r
256\r
257 Pages = EFI_SIZE_TO_PAGES (Size);\r
258 Address = 0xffffffff;\r
259\r
260 Status = gBS->AllocatePages (\r
261 AllocateMaxAddress,\r
262 EfiReservedMemoryType,\r
263 Pages,\r
264 &Address\r
265 );\r
266 ASSERT_EFI_ERROR (Status);\r
267\r
268 Buffer = (VOID *) (UINTN) Address;\r
269 ZeroMem (Buffer, Size);\r
270\r
271 return Buffer;\r
272}\r
273\r
274/**\r
275 Install Boot Graphics Resource Table to ACPI table.\r
276\r
277 @return Status code.\r
278\r
279**/\r
280EFI_STATUS\r
281InstallBootGraphicsResourceTable (\r
282 VOID\r
283 )\r
284{\r
285 EFI_STATUS Status;\r
286 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
287 UINT8 *ImageBuffer;\r
288 UINTN PaddingSize;\r
289 UINTN BmpSize;\r
cbafa15e 290 UINTN OrigBmpSize;\r
0284e90c
LG
291 UINT8 *Image;\r
292 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPixel;\r
293 UINTN Col;\r
294 UINTN Row;\r
295\r
0284e90c
LG
296 //\r
297 // Get ACPI Table protocol.\r
298 //\r
299 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
300 if (EFI_ERROR (Status)) {\r
301 return Status;\r
302 }\r
303\r
304 //\r
cbafa15e 305 // Check whether Boot Graphics Resource Table is already installed.\r
0284e90c 306 //\r
cbafa15e 307 if (mAcpiBgrtInstalled) {\r
308 if (!mAcpiBgrtStatusChanged && !mAcpiBgrtBufferChanged) {\r
309 //\r
310 // Nothing has changed\r
311 //\r
312 return EFI_SUCCESS;\r
313 } else {\r
314 //\r
315 // If BGRT data change happens. Uninstall Orignal AcpiTable first\r
316 //\r
317 Status = AcpiTableProtocol->UninstallAcpiTable (\r
318 AcpiTableProtocol,\r
319 mBootGraphicsResourceTableKey\r
320 );\r
321 if (EFI_ERROR (Status)) {\r
322 return Status;\r
323 } \r
324 }\r
325 } else {\r
326 //\r
327 // Check whether Logo exist.\r
328 //\r
329 if ( mLogoBltBuffer == NULL) {\r
330 return EFI_NOT_FOUND;\r
331 }\r
0284e90c
LG
332 }\r
333\r
cbafa15e 334 if (mAcpiBgrtBufferChanged) {\r
335 //\r
336 // reserve original BGRT buffer size\r
337 //\r
338 OrigBmpSize = mBmpImageHeaderTemplate.ImageSize + sizeof (BMP_IMAGE_HEADER);\r
339 //\r
340 // Free orignal BMP memory \r
341 // \r
342 if (mBootGraphicsResourceTableTemplate.ImageAddress) {\r
343 gBS->FreePages(mBootGraphicsResourceTableTemplate.ImageAddress, EFI_SIZE_TO_PAGES(OrigBmpSize));\r
344 }\r
0284e90c 345\r
cbafa15e 346 //\r
347 // Allocate memory for BMP file.\r
348 //\r
349 PaddingSize = mLogoWidth & 0x3;\r
a46c3657
ED
350\r
351 //\r
352 // First check mLogoWidth * 3 + PaddingSize doesn't overflow\r
353 //\r
354 if (mLogoWidth > (((UINT32) ~0) - PaddingSize) / 3 ) {\r
355 return EFI_UNSUPPORTED;\r
356 }\r
357\r
358 //\r
359 // Second check (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER) doesn't overflow\r
360 //\r
361 if (mLogoHeight > (((UINT32) ~0) - sizeof (BMP_IMAGE_HEADER)) / (mLogoWidth * 3 + PaddingSize)) {\r
362 return EFI_UNSUPPORTED;\r
363 }\r
364 \r
cbafa15e 365 BmpSize = (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER);\r
366 ImageBuffer = BgrtAllocateReservedMemoryBelow4G (BmpSize);\r
367 if (ImageBuffer == NULL) {\r
368 return EFI_OUT_OF_RESOURCES;\r
369 }\r
0284e90c 370\r
cbafa15e 371 mBmpImageHeaderTemplate.Size = (UINT32) BmpSize;\r
372 mBmpImageHeaderTemplate.ImageSize = (UINT32) BmpSize - sizeof (BMP_IMAGE_HEADER);\r
373 mBmpImageHeaderTemplate.PixelWidth = (UINT32) mLogoWidth;\r
374 mBmpImageHeaderTemplate.PixelHeight = (UINT32) mLogoHeight;\r
375 CopyMem (ImageBuffer, &mBmpImageHeaderTemplate, sizeof (BMP_IMAGE_HEADER));\r
376 \r
377 //\r
378 // Convert BLT buffer to BMP file.\r
379 //\r
380 Image = ImageBuffer + sizeof (BMP_IMAGE_HEADER);\r
381 for (Row = 0; Row < mLogoHeight; Row++) {\r
0284e90c
LG
382 BltPixel = &mLogoBltBuffer[(mLogoHeight - Row - 1) * mLogoWidth];\r
383\r
384 for (Col = 0; Col < mLogoWidth; Col++) {\r
385 *Image++ = BltPixel->Blue;\r
386 *Image++ = BltPixel->Green;\r
387 *Image++ = BltPixel->Red;\r
388 BltPixel++;\r
389 }\r
390\r
cbafa15e 391 //\r
392 // Padding for 4 byte alignment.\r
393 //\r
394 Image += PaddingSize;\r
395 }\r
396 FreePool (mLogoBltBuffer);\r
397 mLogoBltBuffer = NULL;\r
398\r
399 mBootGraphicsResourceTableTemplate.ImageAddress = (UINT64) (UINTN) ImageBuffer;\r
400 mBootGraphicsResourceTableTemplate.ImageOffsetX = (UINT32) mLogoDestX;\r
401 mBootGraphicsResourceTableTemplate.ImageOffsetY = (UINT32) mLogoDestY;\r
0284e90c 402 }\r
0284e90c
LG
403\r
404 mBootGraphicsResourceTableTemplate.Status = (UINT8) (mIsLogoValid ? EFI_ACPI_5_0_BGRT_STATUS_VALID : EFI_ACPI_5_0_BGRT_STATUS_INVALID);\r
0284e90c
LG
405\r
406 //\r
407 // Update Checksum.\r
408 //\r
409 BgrtAcpiTableChecksum ((UINT8 *) &mBootGraphicsResourceTableTemplate, sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE));\r
410\r
411 //\r
412 // Publish Boot Graphics Resource Table.\r
413 //\r
414 Status = AcpiTableProtocol->InstallAcpiTable (\r
415 AcpiTableProtocol,\r
416 &mBootGraphicsResourceTableTemplate,\r
417 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),\r
418 &mBootGraphicsResourceTableKey\r
419 );\r
420 if (EFI_ERROR (Status)) {\r
421 return Status;\r
422 }\r
423\r
424 mAcpiBgrtInstalled = TRUE;\r
cbafa15e 425 mAcpiBgrtStatusChanged = FALSE;\r
426 mAcpiBgrtBufferChanged = FALSE;\r
427 \r
0284e90c
LG
428 return Status;\r
429}\r
430\r
431/**\r
432 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to\r
433 install the Boot Graphics Resource Table.\r
434\r
435 @param[in] Event The Event that is being processed.\r
436 @param[in] Context The Event Context.\r
437\r
438**/\r
439VOID\r
440EFIAPI\r
441BgrtReadyToBootEventNotify (\r
442 IN EFI_EVENT Event,\r
443 IN VOID *Context\r
444 )\r
445{\r
446 InstallBootGraphicsResourceTable ();\r
447}\r
448\r
449/**\r
450 The module Entry Point of the Boot Graphics Resource Table DXE driver.\r
451\r
452 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
453 @param[in] SystemTable A pointer to the EFI System Table.\r
454\r
455 @retval EFI_SUCCESS The entry point is executed successfully.\r
456 @retval Other Some error occurs when executing this entry point.\r
457\r
458**/\r
459EFI_STATUS\r
460EFIAPI\r
461BootGraphicsDxeEntryPoint (\r
462 IN EFI_HANDLE ImageHandle,\r
463 IN EFI_SYSTEM_TABLE *SystemTable\r
464 )\r
465{\r
466 EFI_STATUS Status;\r
467\r
468 //\r
469 // Install Boot Logo protocol.\r
470 //\r
471 Status = gBS->InstallMultipleProtocolInterfaces (\r
472 &mBootLogoHandle,\r
473 &gEfiBootLogoProtocolGuid,\r
474 &mBootLogoProtocolTemplate,\r
475 NULL\r
476 );\r
477 ASSERT_EFI_ERROR (Status);\r
478\r
479 //\r
480 // Register notify function to install BGRT on ReadyToBoot Event.\r
481 //\r
482 Status = gBS->CreateEventEx (\r
483 EVT_NOTIFY_SIGNAL,\r
484 TPL_CALLBACK,\r
485 BgrtReadyToBootEventNotify,\r
486 NULL,\r
487 &gEfiEventReadyToBootGuid,\r
488 &mBootGraphicsReadyToBootEvent\r
489 );\r
490 ASSERT_EFI_ERROR (Status);\r
491\r
492 return Status;\r
493}\r