]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.c
MdeModulePkg/BootGraphicsResourceTableDxe: don't allocate below 4 GB
[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
0284e90c
LG
229/**\r
230 Install Boot Graphics Resource Table to ACPI table.\r
231\r
232 @return Status code.\r
233\r
234**/\r
235EFI_STATUS\r
236InstallBootGraphicsResourceTable (\r
237 VOID\r
238 )\r
239{\r
240 EFI_STATUS Status;\r
241 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;\r
242 UINT8 *ImageBuffer;\r
243 UINTN PaddingSize;\r
244 UINTN BmpSize;\r
cbafa15e 245 UINTN OrigBmpSize;\r
0284e90c
LG
246 UINT8 *Image;\r
247 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPixel;\r
248 UINTN Col;\r
249 UINTN Row;\r
250\r
0284e90c
LG
251 //\r
252 // Get ACPI Table protocol.\r
253 //\r
254 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);\r
255 if (EFI_ERROR (Status)) {\r
256 return Status;\r
257 }\r
258\r
259 //\r
cbafa15e 260 // Check whether Boot Graphics Resource Table is already installed.\r
0284e90c 261 //\r
cbafa15e 262 if (mAcpiBgrtInstalled) {\r
263 if (!mAcpiBgrtStatusChanged && !mAcpiBgrtBufferChanged) {\r
264 //\r
265 // Nothing has changed\r
266 //\r
267 return EFI_SUCCESS;\r
268 } else {\r
269 //\r
270 // If BGRT data change happens. Uninstall Orignal AcpiTable first\r
271 //\r
272 Status = AcpiTableProtocol->UninstallAcpiTable (\r
273 AcpiTableProtocol,\r
274 mBootGraphicsResourceTableKey\r
275 );\r
276 if (EFI_ERROR (Status)) {\r
277 return Status;\r
278 } \r
279 }\r
280 } else {\r
281 //\r
282 // Check whether Logo exist.\r
283 //\r
284 if ( mLogoBltBuffer == NULL) {\r
285 return EFI_NOT_FOUND;\r
286 }\r
0284e90c
LG
287 }\r
288\r
cbafa15e 289 if (mAcpiBgrtBufferChanged) {\r
290 //\r
291 // reserve original BGRT buffer size\r
292 //\r
293 OrigBmpSize = mBmpImageHeaderTemplate.ImageSize + sizeof (BMP_IMAGE_HEADER);\r
294 //\r
295 // Free orignal BMP memory \r
296 // \r
297 if (mBootGraphicsResourceTableTemplate.ImageAddress) {\r
298 gBS->FreePages(mBootGraphicsResourceTableTemplate.ImageAddress, EFI_SIZE_TO_PAGES(OrigBmpSize));\r
299 }\r
0284e90c 300\r
cbafa15e 301 //\r
302 // Allocate memory for BMP file.\r
303 //\r
304 PaddingSize = mLogoWidth & 0x3;\r
a46c3657
ED
305\r
306 //\r
307 // First check mLogoWidth * 3 + PaddingSize doesn't overflow\r
308 //\r
309 if (mLogoWidth > (((UINT32) ~0) - PaddingSize) / 3 ) {\r
310 return EFI_UNSUPPORTED;\r
311 }\r
312\r
313 //\r
314 // Second check (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER) doesn't overflow\r
315 //\r
316 if (mLogoHeight > (((UINT32) ~0) - sizeof (BMP_IMAGE_HEADER)) / (mLogoWidth * 3 + PaddingSize)) {\r
317 return EFI_UNSUPPORTED;\r
318 }\r
4c58575e
CZ
319\r
320 //\r
321 // The image should be stored in EfiBootServicesData, allowing the system to reclaim the memory\r
322 //\r
cbafa15e 323 BmpSize = (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER);\r
09da1108 324 ImageBuffer = AllocatePages (EFI_SIZE_TO_PAGES (BmpSize));\r
cbafa15e 325 if (ImageBuffer == NULL) {\r
326 return EFI_OUT_OF_RESOURCES;\r
327 }\r
0284e90c 328\r
09da1108
AB
329 ZeroMem (ImageBuffer, BmpSize);\r
330\r
cbafa15e 331 mBmpImageHeaderTemplate.Size = (UINT32) BmpSize;\r
332 mBmpImageHeaderTemplate.ImageSize = (UINT32) BmpSize - sizeof (BMP_IMAGE_HEADER);\r
333 mBmpImageHeaderTemplate.PixelWidth = (UINT32) mLogoWidth;\r
334 mBmpImageHeaderTemplate.PixelHeight = (UINT32) mLogoHeight;\r
335 CopyMem (ImageBuffer, &mBmpImageHeaderTemplate, sizeof (BMP_IMAGE_HEADER));\r
336 \r
337 //\r
338 // Convert BLT buffer to BMP file.\r
339 //\r
340 Image = ImageBuffer + sizeof (BMP_IMAGE_HEADER);\r
341 for (Row = 0; Row < mLogoHeight; Row++) {\r
0284e90c
LG
342 BltPixel = &mLogoBltBuffer[(mLogoHeight - Row - 1) * mLogoWidth];\r
343\r
344 for (Col = 0; Col < mLogoWidth; Col++) {\r
345 *Image++ = BltPixel->Blue;\r
346 *Image++ = BltPixel->Green;\r
347 *Image++ = BltPixel->Red;\r
348 BltPixel++;\r
349 }\r
350\r
cbafa15e 351 //\r
352 // Padding for 4 byte alignment.\r
353 //\r
354 Image += PaddingSize;\r
355 }\r
356 FreePool (mLogoBltBuffer);\r
357 mLogoBltBuffer = NULL;\r
358\r
359 mBootGraphicsResourceTableTemplate.ImageAddress = (UINT64) (UINTN) ImageBuffer;\r
360 mBootGraphicsResourceTableTemplate.ImageOffsetX = (UINT32) mLogoDestX;\r
361 mBootGraphicsResourceTableTemplate.ImageOffsetY = (UINT32) mLogoDestY;\r
0284e90c 362 }\r
0284e90c
LG
363\r
364 mBootGraphicsResourceTableTemplate.Status = (UINT8) (mIsLogoValid ? EFI_ACPI_5_0_BGRT_STATUS_VALID : EFI_ACPI_5_0_BGRT_STATUS_INVALID);\r
0284e90c
LG
365\r
366 //\r
367 // Update Checksum.\r
368 //\r
369 BgrtAcpiTableChecksum ((UINT8 *) &mBootGraphicsResourceTableTemplate, sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE));\r
370\r
371 //\r
372 // Publish Boot Graphics Resource Table.\r
373 //\r
374 Status = AcpiTableProtocol->InstallAcpiTable (\r
375 AcpiTableProtocol,\r
376 &mBootGraphicsResourceTableTemplate,\r
377 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),\r
378 &mBootGraphicsResourceTableKey\r
379 );\r
380 if (EFI_ERROR (Status)) {\r
381 return Status;\r
382 }\r
383\r
384 mAcpiBgrtInstalled = TRUE;\r
cbafa15e 385 mAcpiBgrtStatusChanged = FALSE;\r
386 mAcpiBgrtBufferChanged = FALSE;\r
387 \r
0284e90c
LG
388 return Status;\r
389}\r
390\r
391/**\r
392 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to\r
393 install the Boot Graphics Resource Table.\r
394\r
395 @param[in] Event The Event that is being processed.\r
396 @param[in] Context The Event Context.\r
397\r
398**/\r
399VOID\r
400EFIAPI\r
401BgrtReadyToBootEventNotify (\r
402 IN EFI_EVENT Event,\r
403 IN VOID *Context\r
404 )\r
405{\r
406 InstallBootGraphicsResourceTable ();\r
407}\r
408\r
409/**\r
410 The module Entry Point of the Boot Graphics Resource Table DXE driver.\r
411\r
412 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
413 @param[in] SystemTable A pointer to the EFI System Table.\r
414\r
415 @retval EFI_SUCCESS The entry point is executed successfully.\r
416 @retval Other Some error occurs when executing this entry point.\r
417\r
418**/\r
419EFI_STATUS\r
420EFIAPI\r
421BootGraphicsDxeEntryPoint (\r
422 IN EFI_HANDLE ImageHandle,\r
423 IN EFI_SYSTEM_TABLE *SystemTable\r
424 )\r
425{\r
426 EFI_STATUS Status;\r
e84f07b5
SZ
427 UINT64 OemTableId;\r
428\r
429 CopyMem (\r
430 mBootGraphicsResourceTableTemplate.Header.OemId,\r
431 PcdGetPtr (PcdAcpiDefaultOemId),\r
432 sizeof (mBootGraphicsResourceTableTemplate.Header.OemId)\r
433 );\r
434 OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);\r
435 CopyMem (&mBootGraphicsResourceTableTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));\r
436 mBootGraphicsResourceTableTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);\r
437 mBootGraphicsResourceTableTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);\r
438 mBootGraphicsResourceTableTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);\r
0284e90c
LG
439\r
440 //\r
441 // Install Boot Logo protocol.\r
442 //\r
443 Status = gBS->InstallMultipleProtocolInterfaces (\r
444 &mBootLogoHandle,\r
445 &gEfiBootLogoProtocolGuid,\r
446 &mBootLogoProtocolTemplate,\r
447 NULL\r
448 );\r
449 ASSERT_EFI_ERROR (Status);\r
450\r
451 //\r
452 // Register notify function to install BGRT on ReadyToBoot Event.\r
453 //\r
454 Status = gBS->CreateEventEx (\r
455 EVT_NOTIFY_SIGNAL,\r
456 TPL_CALLBACK,\r
457 BgrtReadyToBootEventNotify,\r
458 NULL,\r
459 &gEfiEventReadyToBootGuid,\r
460 &mBootGraphicsReadyToBootEvent\r
461 );\r
462 ASSERT_EFI_ERROR (Status);\r
463\r
464 return Status;\r
465}\r