]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[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 - 2018, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016, Microsoft Corporation<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include <Uefi.h>
10
11 #include <IndustryStandard/Acpi.h>
12
13 #include <Protocol/AcpiTable.h>
14 #include <Protocol/GraphicsOutput.h>
15 #include <Protocol/BootLogo.h>
16 #include <Protocol/BootLogo2.h>
17
18 #include <Guid/EventGroup.h>
19
20 #include <Library/BaseLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/DebugLib.h>
25 #include <Library/PcdLib.h>
26 #include <Library/SafeIntLib.h>
27 #include <Library/BmpSupportLib.h>
28
29 /**
30 Update information of logo image drawn on screen.
31
32 @param[in] This The pointer to the Boot Logo protocol 2 instance.
33 @param[in] BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer
34 is set to NULL, it indicates that logo image is no
35 longer on the screen.
36 @param[in] DestinationX X coordinate of destination for the BltBuffer.
37 @param[in] DestinationY Y coordinate of destination for the BltBuffer.
38 @param[in] Width Width of rectangle in BltBuffer in pixels.
39 @param[in] Height Hight of rectangle in BltBuffer in pixels.
40
41 @retval EFI_SUCCESS The boot logo information was updated.
42 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
43 @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to
44 insufficient memory resources.
45 **/
46 EFI_STATUS
47 EFIAPI
48 SetBootLogo (
49 IN EFI_BOOT_LOGO_PROTOCOL *This,
50 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
51 IN UINTN DestinationX,
52 IN UINTN DestinationY,
53 IN UINTN Width,
54 IN UINTN Height
55 );
56
57 /**
58 Update information of logo image drawn on screen.
59
60 @param[in] This The pointer to the Boot Logo protocol 2 instance.
61 @param[in] BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer
62 is set to NULL, it indicates that logo image is no
63 longer on the screen.
64 @param[in] DestinationX X coordinate of destination for the BltBuffer.
65 @param[in] DestinationY Y coordinate of destination for the BltBuffer.
66 @param[in] Width Width of rectangle in BltBuffer in pixels.
67 @param[in] Height Hight of rectangle in BltBuffer in pixels.
68
69 @retval EFI_SUCCESS The boot logo information was updated.
70 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
71 @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to
72 insufficient memory resources.
73 **/
74 EFI_STATUS
75 EFIAPI
76 SetBootLogo2 (
77 IN EDKII_BOOT_LOGO2_PROTOCOL *This,
78 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
79 IN UINTN DestinationX,
80 IN UINTN DestinationY,
81 IN UINTN Width,
82 IN UINTN Height
83 );
84
85 /**
86 Get the location of the boot logo on the screen.
87
88 @param[in] This The pointer to the Boot Logo Protocol 2 instance
89 @param[out] BltBuffer Returns pointer to the GOP BLT buffer that was
90 previously registered with SetBootLogo2(). The
91 buffer returned must not be modified or freed.
92 @param[out] DestinationX Returns the X start position of the GOP BLT buffer
93 that was previously registered with SetBootLogo2().
94 @param[out] DestinationY Returns the Y start position of the GOP BLT buffer
95 that was previously registered with SetBootLogo2().
96 @param[out] Width Returns the width of the GOP BLT buffer
97 that was previously registered with SetBootLogo2().
98 @param[out] Height Returns the height of the GOP BLT buffer
99 that was previously registered with SetBootLogo2().
100
101 @retval EFI_SUCCESS The location of the boot logo was returned.
102 @retval EFI_NOT_READY The boot logo has not been set.
103 @retval EFI_INVALID_PARAMETER BltBuffer is NULL.
104 @retval EFI_INVALID_PARAMETER DestinationX is NULL.
105 @retval EFI_INVALID_PARAMETER DestinationY is NULL.
106 @retval EFI_INVALID_PARAMETER Width is NULL.
107 @retval EFI_INVALID_PARAMETER Height is NULL.
108 **/
109 EFI_STATUS
110 EFIAPI
111 GetBootLogo2 (
112 IN EDKII_BOOT_LOGO2_PROTOCOL *This,
113 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer,
114 OUT UINTN *DestinationX,
115 OUT UINTN *DestinationY,
116 OUT UINTN *Width,
117 OUT UINTN *Height
118 );
119
120 //
121 // Boot Logo Protocol Handle
122 //
123 EFI_HANDLE mBootLogoHandle = NULL;
124
125 //
126 // Boot Logo Protocol Instance
127 //
128 EFI_BOOT_LOGO_PROTOCOL mBootLogoProtocolTemplate = {
129 SetBootLogo
130 };
131
132 ///
133 /// Boot Logo 2 Protocol instance
134 ///
135 EDKII_BOOT_LOGO2_PROTOCOL mBootLogo2ProtocolTemplate = {
136 SetBootLogo2,
137 GetBootLogo2
138 };
139
140 EFI_EVENT mBootGraphicsReadyToBootEvent;
141 UINTN mBootGraphicsResourceTableKey = 0;
142 BOOLEAN mIsLogoValid = FALSE;
143 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *mLogoBltBuffer = NULL;
144 UINTN mLogoDestX = 0;
145 UINTN mLogoDestY = 0;
146 UINTN mLogoWidth = 0;
147 UINTN mLogoHeight = 0;
148 BOOLEAN mAcpiBgrtInstalled = FALSE;
149 BOOLEAN mAcpiBgrtStatusChanged = FALSE;
150 BOOLEAN mAcpiBgrtBufferChanged = FALSE;
151
152 //
153 // ACPI Boot Graphics Resource Table template
154 //
155 EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE mBootGraphicsResourceTableTemplate = {
156 {
157 EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE,
158 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),
159 EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION, // Revision
160 0x00, // Checksum will be updated at runtime
161 //
162 // It is expected that these values will be updated at EntryPoint.
163 //
164 {0x00}, // OEM ID is a 6 bytes long field
165 0x00, // OEM Table ID(8 bytes long)
166 0x00, // OEM Revision
167 0x00, // Creator ID
168 0x00, // Creator Revision
169 },
170 EFI_ACPI_5_0_BGRT_VERSION, // Version
171 EFI_ACPI_5_0_BGRT_STATUS_VALID, // Status
172 EFI_ACPI_5_0_BGRT_IMAGE_TYPE_BMP, // Image Type
173 0, // Image Address
174 0, // Image Offset X
175 0 // Image Offset Y
176 };
177
178 /**
179 Update information of logo image drawn on screen.
180
181 @param This The pointer to the Boot Logo protocol instance.
182 @param BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer
183 is set to NULL, it indicates that logo image is no
184 longer on the screen.
185 @param DestinationX X coordinate of destination for the BltBuffer.
186 @param DestinationY Y coordinate of destination for the BltBuffer.
187 @param Width Width of rectangle in BltBuffer in pixels.
188 @param Height Hight of rectangle in BltBuffer in pixels.
189
190 @retval EFI_SUCCESS The boot logo information was updated.
191 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
192 @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to
193 insufficient memory resources.
194
195 **/
196 EFI_STATUS
197 EFIAPI
198 SetBootLogo (
199 IN EFI_BOOT_LOGO_PROTOCOL *This,
200 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
201 IN UINTN DestinationX,
202 IN UINTN DestinationY,
203 IN UINTN Width,
204 IN UINTN Height
205 )
206 {
207 //
208 // Call same service in Boot Logo 2 Protocol
209 //
210 return SetBootLogo2 (
211 &mBootLogo2ProtocolTemplate,
212 BltBuffer,
213 DestinationX,
214 DestinationY,
215 Width,
216 Height
217 );
218 }
219
220 /**
221 Update information of logo image drawn on screen.
222
223 @param[in] This The pointer to the Boot Logo protocol 2 instance.
224 @param[in] BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer
225 is set to NULL, it indicates that logo image is no
226 longer on the screen.
227 @param[in] DestinationX X coordinate of destination for the BltBuffer.
228 @param[in] DestinationY Y coordinate of destination for the BltBuffer.
229 @param[in] Width Width of rectangle in BltBuffer in pixels.
230 @param[in] Height Hight of rectangle in BltBuffer in pixels.
231
232 @retval EFI_SUCCESS The boot logo information was updated.
233 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
234 @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to
235 insufficient memory resources.
236 **/
237 EFI_STATUS
238 EFIAPI
239 SetBootLogo2 (
240 IN EDKII_BOOT_LOGO2_PROTOCOL *This,
241 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
242 IN UINTN DestinationX,
243 IN UINTN DestinationY,
244 IN UINTN Width,
245 IN UINTN Height
246 )
247 {
248 EFI_STATUS Status;
249 UINTN BufferSize;
250 UINT32 Result32;
251
252 if (BltBuffer == NULL) {
253 mIsLogoValid = FALSE;
254 mAcpiBgrtStatusChanged = TRUE;
255 return EFI_SUCCESS;
256 }
257
258 //
259 // Width and height are not allowed to be zero.
260 //
261 if (Width == 0 || Height == 0) {
262 return EFI_INVALID_PARAMETER;
263 }
264
265 //
266 // Verify destination, width, and height do not overflow 32-bit values.
267 // The Boot Graphics Resource Table only has 32-bit fields for these values.
268 //
269 Status = SafeUintnToUint32 (DestinationX, &Result32);
270 if (EFI_ERROR (Status)) {
271 return EFI_INVALID_PARAMETER;
272 }
273 Status = SafeUintnToUint32 (DestinationY, &Result32);
274 if (EFI_ERROR (Status)) {
275 return EFI_INVALID_PARAMETER;
276 }
277 Status = SafeUintnToUint32 (Width, &Result32);
278 if (EFI_ERROR (Status)) {
279 return EFI_INVALID_PARAMETER;
280 }
281 Status = SafeUintnToUint32 (Height, &Result32);
282 if (EFI_ERROR (Status)) {
283 return EFI_INVALID_PARAMETER;
284 }
285
286 //
287 // Ensure the Height * Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) does
288 // not overflow UINTN
289 //
290 Status = SafeUintnMult (
291 Width,
292 Height,
293 &BufferSize
294 );
295 if (EFI_ERROR (Status)) {
296 return EFI_UNSUPPORTED;
297 }
298 Status = SafeUintnMult (
299 BufferSize,
300 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),
301 &BufferSize
302 );
303 if (EFI_ERROR (Status)) {
304 return EFI_UNSUPPORTED;
305 }
306
307 //
308 // Update state
309 //
310 mAcpiBgrtBufferChanged = TRUE;
311
312 //
313 // Free old logo buffer
314 //
315 if (mLogoBltBuffer != NULL) {
316 FreePool (mLogoBltBuffer);
317 mLogoBltBuffer = NULL;
318 }
319
320 //
321 // Allocate new logo buffer
322 //
323 mLogoBltBuffer = AllocateCopyPool (BufferSize, BltBuffer);
324 if (mLogoBltBuffer == NULL) {
325 return EFI_OUT_OF_RESOURCES;
326 }
327
328 mLogoDestX = DestinationX;
329 mLogoDestY = DestinationY;
330 mLogoWidth = Width;
331 mLogoHeight = Height;
332 mIsLogoValid = TRUE;
333
334 return EFI_SUCCESS;
335 }
336
337 /**
338 Get the location of the boot logo on the screen.
339
340 @param[in] This The pointer to the Boot Logo Protocol 2 instance
341 @param[out] BltBuffer Returns pointer to the GOP BLT buffer that was
342 previously registered with SetBootLogo2(). The
343 buffer returned must not be modified or freed.
344 @param[out] DestinationX Returns the X start position of the GOP BLT buffer
345 that was previously registered with SetBootLogo2().
346 @param[out] DestinationY Returns the Y start position of the GOP BLT buffer
347 that was previously registered with SetBootLogo2().
348 @param[out] Width Returns the width of the GOP BLT buffer
349 that was previously registered with SetBootLogo2().
350 @param[out] Height Returns the height of the GOP BLT buffer
351 that was previously registered with SetBootLogo2().
352
353 @retval EFI_SUCCESS The location of the boot logo was returned.
354 @retval EFI_NOT_READY The boot logo has not been set.
355 @retval EFI_INVALID_PARAMETER BltBuffer is NULL.
356 @retval EFI_INVALID_PARAMETER DestinationX is NULL.
357 @retval EFI_INVALID_PARAMETER DestinationY is NULL.
358 @retval EFI_INVALID_PARAMETER Width is NULL.
359 @retval EFI_INVALID_PARAMETER Height is NULL.
360 **/
361 EFI_STATUS
362 EFIAPI
363 GetBootLogo2 (
364 IN EDKII_BOOT_LOGO2_PROTOCOL *This,
365 OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer,
366 OUT UINTN *DestinationX,
367 OUT UINTN *DestinationY,
368 OUT UINTN *Width,
369 OUT UINTN *Height
370 )
371 {
372 //
373 // If the boot logo has not been set with SetBootLogo() or SetBootLogo() was
374 // called with a NULL BltBuffer then the boot logo is not valid and
375 // EFI_NOT_READY is returned.
376 //
377 if (mLogoBltBuffer == NULL) {
378 DEBUG ((DEBUG_ERROR, "Request to get boot logo location before boot logo has been set.\n"));
379 return EFI_NOT_READY;
380 }
381
382 //
383 // Make sure none of the boot logo location parameters are NULL.
384 //
385 if (BltBuffer == NULL || DestinationX == NULL || DestinationY == NULL ||
386 Width == NULL || Height == NULL) {
387 return EFI_INVALID_PARAMETER;
388 }
389
390 //
391 // Boot logo is valid. Return values from module globals.
392 //
393 *BltBuffer = mLogoBltBuffer;
394 *DestinationX = mLogoDestX;
395 *DestinationY = mLogoDestY;
396 *Width = mLogoWidth;
397 *Height = mLogoHeight;
398
399 return EFI_SUCCESS;
400 }
401
402 /**
403 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
404 install the Boot Graphics Resource Table.
405
406 @param[in] Event The Event that is being processed.
407 @param[in] Context The Event Context.
408
409 **/
410 VOID
411 EFIAPI
412 BgrtReadyToBootEventNotify (
413 IN EFI_EVENT Event,
414 IN VOID *Context
415 )
416 {
417 EFI_STATUS Status;
418 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
419 VOID *ImageBuffer;
420 UINT32 BmpSize;
421
422 //
423 // Get ACPI Table protocol.
424 //
425 Status = gBS->LocateProtocol (
426 &gEfiAcpiTableProtocolGuid,
427 NULL,
428 (VOID **) &AcpiTableProtocol
429 );
430 if (EFI_ERROR (Status)) {
431 return;
432 }
433
434 //
435 // Check whether Boot Graphics Resource Table is already installed.
436 //
437 if (mAcpiBgrtInstalled) {
438 if (!mAcpiBgrtStatusChanged && !mAcpiBgrtBufferChanged) {
439 //
440 // Nothing has changed
441 //
442 return;
443 } else {
444 //
445 // If BGRT data change happens, then uninstall orignal AcpiTable first
446 //
447 Status = AcpiTableProtocol->UninstallAcpiTable (
448 AcpiTableProtocol,
449 mBootGraphicsResourceTableKey
450 );
451 if (EFI_ERROR (Status)) {
452 return;
453 }
454 }
455 } else {
456 //
457 // Check whether Logo exists
458 //
459 if (mLogoBltBuffer == NULL) {
460 return;
461 }
462 }
463
464 if (mAcpiBgrtBufferChanged) {
465 //
466 // Free the old BMP image buffer
467 //
468 ImageBuffer = (UINT8 *)(UINTN)mBootGraphicsResourceTableTemplate.ImageAddress;
469 if (ImageBuffer != NULL) {
470 FreePool (ImageBuffer);
471 }
472
473 //
474 // Convert GOP Blt buffer to BMP image. Pass in ImageBuffer set to NULL
475 // so the BMP image is allocated by TranslateGopBltToBmp().
476 //
477 ImageBuffer = NULL;
478 Status = TranslateGopBltToBmp (
479 mLogoBltBuffer,
480 (UINT32)mLogoHeight,
481 (UINT32)mLogoWidth,
482 &ImageBuffer,
483 &BmpSize
484 );
485 if (EFI_ERROR (Status)) {
486 return;
487 }
488
489 //
490 // Free the logo buffer
491 //
492 FreePool (mLogoBltBuffer);
493 mLogoBltBuffer = NULL;
494
495 //
496 // Update BMP image fields of the Boot Graphics Resource Table
497 //
498 mBootGraphicsResourceTableTemplate.ImageAddress = (UINT64)(UINTN)ImageBuffer;
499 mBootGraphicsResourceTableTemplate.ImageOffsetX = (UINT32)mLogoDestX;
500 mBootGraphicsResourceTableTemplate.ImageOffsetY = (UINT32)mLogoDestY;
501 }
502
503 //
504 // Update Status field of Boot Graphics Resource Table
505 //
506 if (mIsLogoValid) {
507 mBootGraphicsResourceTableTemplate.Status = EFI_ACPI_5_0_BGRT_STATUS_VALID;
508 } else {
509 mBootGraphicsResourceTableTemplate.Status = EFI_ACPI_5_0_BGRT_STATUS_INVALID;
510 }
511
512 //
513 // Update Checksum of Boot Graphics Resource Table
514 //
515 mBootGraphicsResourceTableTemplate.Header.Checksum = 0;
516 mBootGraphicsResourceTableTemplate.Header.Checksum =
517 CalculateCheckSum8 (
518 (UINT8 *)&mBootGraphicsResourceTableTemplate,
519 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE)
520 );
521
522 //
523 // Publish Boot Graphics Resource Table.
524 //
525 Status = AcpiTableProtocol->InstallAcpiTable (
526 AcpiTableProtocol,
527 &mBootGraphicsResourceTableTemplate,
528 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),
529 &mBootGraphicsResourceTableKey
530 );
531 if (EFI_ERROR (Status)) {
532 return;
533 }
534
535 mAcpiBgrtInstalled = TRUE;
536 mAcpiBgrtStatusChanged = FALSE;
537 mAcpiBgrtBufferChanged = FALSE;
538 }
539
540 /**
541 The module Entry Point of the Boot Graphics Resource Table DXE driver.
542
543 @param[in] ImageHandle The firmware allocated handle for the EFI image.
544 @param[in] SystemTable A pointer to the EFI System Table.
545
546 @retval EFI_SUCCESS The entry point is executed successfully.
547 @retval Other Some error occurs when executing this entry point.
548
549 **/
550 EFI_STATUS
551 EFIAPI
552 BootGraphicsDxeEntryPoint (
553 IN EFI_HANDLE ImageHandle,
554 IN EFI_SYSTEM_TABLE *SystemTable
555 )
556 {
557 EFI_STATUS Status;
558 EFI_ACPI_DESCRIPTION_HEADER *Header;
559
560 //
561 // Update Header fields of Boot Graphics Resource Table from PCDs
562 //
563 Header = &mBootGraphicsResourceTableTemplate.Header;
564 ZeroMem (Header->OemId, sizeof (Header->OemId));
565 CopyMem (
566 Header->OemId,
567 PcdGetPtr (PcdAcpiDefaultOemId),
568 MIN (PcdGetSize (PcdAcpiDefaultOemId), sizeof (Header->OemId))
569 );
570 WriteUnaligned64 (&Header->OemTableId, PcdGet64 (PcdAcpiDefaultOemTableId));
571 Header->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
572 Header->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
573 Header->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
574
575 //
576 // Install Boot Logo and Boot Logo 2 Protocols.
577 //
578 Status = gBS->InstallMultipleProtocolInterfaces (
579 &mBootLogoHandle,
580 &gEfiBootLogoProtocolGuid,
581 &mBootLogoProtocolTemplate,
582 &gEdkiiBootLogo2ProtocolGuid,
583 &mBootLogo2ProtocolTemplate,
584 NULL
585 );
586 ASSERT_EFI_ERROR (Status);
587
588 //
589 // Register notify function to install BGRT on ReadyToBoot Event.
590 //
591 Status = gBS->CreateEventEx (
592 EVT_NOTIFY_SIGNAL,
593 TPL_CALLBACK,
594 BgrtReadyToBootEventNotify,
595 NULL,
596 &gEfiEventReadyToBootGuid,
597 &mBootGraphicsReadyToBootEvent
598 );
599 ASSERT_EFI_ERROR (Status);
600
601 return Status;
602 }