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