]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.c
Clean up include of ACPI header file so that only IndustryStandard/Acpi.h is needed...
[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 - 2012, 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 EfiReservedMemoryType below 4G memory address.
239
240 This function allocates EfiReservedMemoryType 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 BgrtAllocateReservedMemoryBelow4G (
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 EfiReservedMemoryType,
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 BmpSize = (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER);
366 ImageBuffer = BgrtAllocateReservedMemoryBelow4G (BmpSize);
367 if (ImageBuffer == NULL) {
368 return EFI_OUT_OF_RESOURCES;
369 }
370
371 mBmpImageHeaderTemplate.Size = (UINT32) BmpSize;
372 mBmpImageHeaderTemplate.ImageSize = (UINT32) BmpSize - sizeof (BMP_IMAGE_HEADER);
373 mBmpImageHeaderTemplate.PixelWidth = (UINT32) mLogoWidth;
374 mBmpImageHeaderTemplate.PixelHeight = (UINT32) mLogoHeight;
375 CopyMem (ImageBuffer, &mBmpImageHeaderTemplate, sizeof (BMP_IMAGE_HEADER));
376
377 //
378 // Convert BLT buffer to BMP file.
379 //
380 Image = ImageBuffer + sizeof (BMP_IMAGE_HEADER);
381 for (Row = 0; Row < mLogoHeight; Row++) {
382 BltPixel = &mLogoBltBuffer[(mLogoHeight - Row - 1) * mLogoWidth];
383
384 for (Col = 0; Col < mLogoWidth; Col++) {
385 *Image++ = BltPixel->Blue;
386 *Image++ = BltPixel->Green;
387 *Image++ = BltPixel->Red;
388 BltPixel++;
389 }
390
391 //
392 // Padding for 4 byte alignment.
393 //
394 Image += PaddingSize;
395 }
396 FreePool (mLogoBltBuffer);
397 mLogoBltBuffer = NULL;
398
399 mBootGraphicsResourceTableTemplate.ImageAddress = (UINT64) (UINTN) ImageBuffer;
400 mBootGraphicsResourceTableTemplate.ImageOffsetX = (UINT32) mLogoDestX;
401 mBootGraphicsResourceTableTemplate.ImageOffsetY = (UINT32) mLogoDestY;
402 }
403
404 mBootGraphicsResourceTableTemplate.Status = (UINT8) (mIsLogoValid ? EFI_ACPI_5_0_BGRT_STATUS_VALID : EFI_ACPI_5_0_BGRT_STATUS_INVALID);
405
406 //
407 // Update Checksum.
408 //
409 BgrtAcpiTableChecksum ((UINT8 *) &mBootGraphicsResourceTableTemplate, sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE));
410
411 //
412 // Publish Boot Graphics Resource Table.
413 //
414 Status = AcpiTableProtocol->InstallAcpiTable (
415 AcpiTableProtocol,
416 &mBootGraphicsResourceTableTemplate,
417 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),
418 &mBootGraphicsResourceTableKey
419 );
420 if (EFI_ERROR (Status)) {
421 return Status;
422 }
423
424 mAcpiBgrtInstalled = TRUE;
425 mAcpiBgrtStatusChanged = FALSE;
426 mAcpiBgrtBufferChanged = FALSE;
427
428 return Status;
429 }
430
431 /**
432 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
433 install the Boot Graphics Resource Table.
434
435 @param[in] Event The Event that is being processed.
436 @param[in] Context The Event Context.
437
438 **/
439 VOID
440 EFIAPI
441 BgrtReadyToBootEventNotify (
442 IN EFI_EVENT Event,
443 IN VOID *Context
444 )
445 {
446 InstallBootGraphicsResourceTable ();
447 }
448
449 /**
450 The module Entry Point of the Boot Graphics Resource Table DXE driver.
451
452 @param[in] ImageHandle The firmware allocated handle for the EFI image.
453 @param[in] SystemTable A pointer to the EFI System Table.
454
455 @retval EFI_SUCCESS The entry point is executed successfully.
456 @retval Other Some error occurs when executing this entry point.
457
458 **/
459 EFI_STATUS
460 EFIAPI
461 BootGraphicsDxeEntryPoint (
462 IN EFI_HANDLE ImageHandle,
463 IN EFI_SYSTEM_TABLE *SystemTable
464 )
465 {
466 EFI_STATUS Status;
467
468 //
469 // Install Boot Logo protocol.
470 //
471 Status = gBS->InstallMultipleProtocolInterfaces (
472 &mBootLogoHandle,
473 &gEfiBootLogoProtocolGuid,
474 &mBootLogoProtocolTemplate,
475 NULL
476 );
477 ASSERT_EFI_ERROR (Status);
478
479 //
480 // Register notify function to install BGRT on ReadyToBoot Event.
481 //
482 Status = gBS->CreateEventEx (
483 EVT_NOTIFY_SIGNAL,
484 TPL_CALLBACK,
485 BgrtReadyToBootEventNotify,
486 NULL,
487 &gEfiEventReadyToBootGuid,
488 &mBootGraphicsReadyToBootEvent
489 );
490 ASSERT_EFI_ERROR (Status);
491
492 return Status;
493 }