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