]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.c
Enhance BGRT driver to install BGRT table upon every ReadyToBoot event
[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/Acpi50.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 if (BltBuffer == NULL) {
161 mIsLogoValid = FALSE;
162 mAcpiBgrtStatusChanged = TRUE;
163 return EFI_SUCCESS;
164 }
165
166 if (Width == 0 || Height == 0) {
167 return EFI_INVALID_PARAMETER;
168 }
169
170 mAcpiBgrtBufferChanged = TRUE;
171 if (mLogoBltBuffer != NULL) {
172 FreePool (mLogoBltBuffer);
173 mLogoBltBuffer = NULL;
174 }
175
176 mLogoBltBuffer = AllocateCopyPool (
177 Width * Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),
178 BltBuffer
179 );
180 if (mLogoBltBuffer == NULL) {
181 return EFI_OUT_OF_RESOURCES;
182 }
183 mLogoDestX = DestinationX;
184 mLogoDestY = DestinationY;
185 mLogoWidth = Width;
186 mLogoHeight = Height;
187 mIsLogoValid = TRUE;
188
189 return EFI_SUCCESS;
190 }
191
192 /**
193 This function calculates and updates an UINT8 checksum.
194
195 @param[in] Buffer Pointer to buffer to checksum.
196 @param[in] Size Number of bytes to checksum.
197
198 **/
199 VOID
200 BgrtAcpiTableChecksum (
201 IN UINT8 *Buffer,
202 IN UINTN Size
203 )
204 {
205 UINTN ChecksumOffset;
206
207 ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
208
209 //
210 // Set checksum to 0 first.
211 //
212 Buffer[ChecksumOffset] = 0;
213
214 //
215 // Update checksum value.
216 //
217 Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);
218 }
219
220 /**
221 Allocate EfiReservedMemoryType below 4G memory address.
222
223 This function allocates EfiReservedMemoryType below 4G memory address.
224
225 @param[in] Size Size of memory to allocate.
226
227 @return Allocated address for output.
228
229 **/
230 VOID *
231 BgrtAllocateReservedMemoryBelow4G (
232 IN UINTN Size
233 )
234 {
235 UINTN Pages;
236 EFI_PHYSICAL_ADDRESS Address;
237 EFI_STATUS Status;
238 VOID *Buffer;
239
240 Pages = EFI_SIZE_TO_PAGES (Size);
241 Address = 0xffffffff;
242
243 Status = gBS->AllocatePages (
244 AllocateMaxAddress,
245 EfiReservedMemoryType,
246 Pages,
247 &Address
248 );
249 ASSERT_EFI_ERROR (Status);
250
251 Buffer = (VOID *) (UINTN) Address;
252 ZeroMem (Buffer, Size);
253
254 return Buffer;
255 }
256
257 /**
258 Install Boot Graphics Resource Table to ACPI table.
259
260 @return Status code.
261
262 **/
263 EFI_STATUS
264 InstallBootGraphicsResourceTable (
265 VOID
266 )
267 {
268 EFI_STATUS Status;
269 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
270 UINT8 *ImageBuffer;
271 UINTN PaddingSize;
272 UINTN BmpSize;
273 UINTN OrigBmpSize;
274 UINT8 *Image;
275 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltPixel;
276 UINTN Col;
277 UINTN Row;
278
279 //
280 // Get ACPI Table protocol.
281 //
282 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
283 if (EFI_ERROR (Status)) {
284 return Status;
285 }
286
287 //
288 // Check whether Boot Graphics Resource Table is already installed.
289 //
290 if (mAcpiBgrtInstalled) {
291 if (!mAcpiBgrtStatusChanged && !mAcpiBgrtBufferChanged) {
292 //
293 // Nothing has changed
294 //
295 return EFI_SUCCESS;
296 } else {
297 //
298 // If BGRT data change happens. Uninstall Orignal AcpiTable first
299 //
300 Status = AcpiTableProtocol->UninstallAcpiTable (
301 AcpiTableProtocol,
302 mBootGraphicsResourceTableKey
303 );
304 if (EFI_ERROR (Status)) {
305 return Status;
306 }
307 }
308 } else {
309 //
310 // Check whether Logo exist.
311 //
312 if ( mLogoBltBuffer == NULL) {
313 return EFI_NOT_FOUND;
314 }
315 }
316
317 if (mAcpiBgrtBufferChanged) {
318 //
319 // reserve original BGRT buffer size
320 //
321 OrigBmpSize = mBmpImageHeaderTemplate.ImageSize + sizeof (BMP_IMAGE_HEADER);
322 //
323 // Free orignal BMP memory
324 //
325 if (mBootGraphicsResourceTableTemplate.ImageAddress) {
326 gBS->FreePages(mBootGraphicsResourceTableTemplate.ImageAddress, EFI_SIZE_TO_PAGES(OrigBmpSize));
327 }
328
329 //
330 // Allocate memory for BMP file.
331 //
332 PaddingSize = mLogoWidth & 0x3;
333 BmpSize = (mLogoWidth * 3 + PaddingSize) * mLogoHeight + sizeof (BMP_IMAGE_HEADER);
334 ImageBuffer = BgrtAllocateReservedMemoryBelow4G (BmpSize);
335 if (ImageBuffer == NULL) {
336 return EFI_OUT_OF_RESOURCES;
337 }
338
339 mBmpImageHeaderTemplate.Size = (UINT32) BmpSize;
340 mBmpImageHeaderTemplate.ImageSize = (UINT32) BmpSize - sizeof (BMP_IMAGE_HEADER);
341 mBmpImageHeaderTemplate.PixelWidth = (UINT32) mLogoWidth;
342 mBmpImageHeaderTemplate.PixelHeight = (UINT32) mLogoHeight;
343 CopyMem (ImageBuffer, &mBmpImageHeaderTemplate, sizeof (BMP_IMAGE_HEADER));
344
345 //
346 // Convert BLT buffer to BMP file.
347 //
348 Image = ImageBuffer + sizeof (BMP_IMAGE_HEADER);
349 for (Row = 0; Row < mLogoHeight; Row++) {
350 BltPixel = &mLogoBltBuffer[(mLogoHeight - Row - 1) * mLogoWidth];
351
352 for (Col = 0; Col < mLogoWidth; Col++) {
353 *Image++ = BltPixel->Blue;
354 *Image++ = BltPixel->Green;
355 *Image++ = BltPixel->Red;
356 BltPixel++;
357 }
358
359 //
360 // Padding for 4 byte alignment.
361 //
362 Image += PaddingSize;
363 }
364 FreePool (mLogoBltBuffer);
365 mLogoBltBuffer = NULL;
366
367 mBootGraphicsResourceTableTemplate.ImageAddress = (UINT64) (UINTN) ImageBuffer;
368 mBootGraphicsResourceTableTemplate.ImageOffsetX = (UINT32) mLogoDestX;
369 mBootGraphicsResourceTableTemplate.ImageOffsetY = (UINT32) mLogoDestY;
370 }
371
372 mBootGraphicsResourceTableTemplate.Status = (UINT8) (mIsLogoValid ? EFI_ACPI_5_0_BGRT_STATUS_VALID : EFI_ACPI_5_0_BGRT_STATUS_INVALID);
373
374 //
375 // Update Checksum.
376 //
377 BgrtAcpiTableChecksum ((UINT8 *) &mBootGraphicsResourceTableTemplate, sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE));
378
379 //
380 // Publish Boot Graphics Resource Table.
381 //
382 Status = AcpiTableProtocol->InstallAcpiTable (
383 AcpiTableProtocol,
384 &mBootGraphicsResourceTableTemplate,
385 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),
386 &mBootGraphicsResourceTableKey
387 );
388 if (EFI_ERROR (Status)) {
389 return Status;
390 }
391
392 mAcpiBgrtInstalled = TRUE;
393 mAcpiBgrtStatusChanged = FALSE;
394 mAcpiBgrtBufferChanged = FALSE;
395
396 return Status;
397 }
398
399 /**
400 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
401 install the Boot Graphics Resource Table.
402
403 @param[in] Event The Event that is being processed.
404 @param[in] Context The Event Context.
405
406 **/
407 VOID
408 EFIAPI
409 BgrtReadyToBootEventNotify (
410 IN EFI_EVENT Event,
411 IN VOID *Context
412 )
413 {
414 InstallBootGraphicsResourceTable ();
415 }
416
417 /**
418 The module Entry Point of the Boot Graphics Resource Table DXE driver.
419
420 @param[in] ImageHandle The firmware allocated handle for the EFI image.
421 @param[in] SystemTable A pointer to the EFI System Table.
422
423 @retval EFI_SUCCESS The entry point is executed successfully.
424 @retval Other Some error occurs when executing this entry point.
425
426 **/
427 EFI_STATUS
428 EFIAPI
429 BootGraphicsDxeEntryPoint (
430 IN EFI_HANDLE ImageHandle,
431 IN EFI_SYSTEM_TABLE *SystemTable
432 )
433 {
434 EFI_STATUS Status;
435
436 //
437 // Install Boot Logo protocol.
438 //
439 Status = gBS->InstallMultipleProtocolInterfaces (
440 &mBootLogoHandle,
441 &gEfiBootLogoProtocolGuid,
442 &mBootLogoProtocolTemplate,
443 NULL
444 );
445 ASSERT_EFI_ERROR (Status);
446
447 //
448 // Register notify function to install BGRT on ReadyToBoot Event.
449 //
450 Status = gBS->CreateEventEx (
451 EVT_NOTIFY_SIGNAL,
452 TPL_CALLBACK,
453 BgrtReadyToBootEventNotify,
454 NULL,
455 &gEfiEventReadyToBootGuid,
456 &mBootGraphicsReadyToBootEvent
457 );
458 ASSERT_EFI_ERROR (Status);
459
460 return Status;
461 }