]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.c
MdeModulePkg/BootGraphicsResourceTableDxe: Use BmpSupportLib
[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 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
18 #include <Protocol/AcpiTable.h>
19 #include <Protocol/GraphicsOutput.h>
20 #include <Protocol/BootLogo.h>
21
22 #include <Guid/EventGroup.h>
23
24 #include <Library/BaseLib.h>
25 #include <Library/BaseMemoryLib.h>
26 #include <Library/MemoryAllocationLib.h>
27 #include <Library/UefiBootServicesTableLib.h>
28 #include <Library/DebugLib.h>
29 #include <Library/PcdLib.h>
30 #include <Library/SafeIntLib.h>
31 #include <Library/BmpSupportLib.h>
32
33 /**
34 Update information of logo image drawn on screen.
35
36 @param This The pointer to the Boot Logo protocol instance.
37 @param BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer
38 is set to NULL, it indicates that logo image is no
39 longer on the screen.
40 @param DestinationX X coordinate of destination for the BltBuffer.
41 @param DestinationY Y coordinate of destination for the BltBuffer.
42 @param Width Width of rectangle in BltBuffer in pixels.
43 @param Height Hight of rectangle in BltBuffer in pixels.
44
45 @retval EFI_SUCCESS The boot logo information was updated.
46 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
47 @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to
48 insufficient memory resources.
49
50 **/
51 EFI_STATUS
52 EFIAPI
53 SetBootLogo (
54 IN EFI_BOOT_LOGO_PROTOCOL *This,
55 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
56 IN UINTN DestinationX,
57 IN UINTN DestinationY,
58 IN UINTN Width,
59 IN UINTN Height
60 );
61
62 //
63 // Boot Logo Protocol Handle
64 //
65 EFI_HANDLE mBootLogoHandle = NULL;
66
67 //
68 // Boot Logo Protocol Instance
69 //
70 EFI_BOOT_LOGO_PROTOCOL mBootLogoProtocolTemplate = {
71 SetBootLogo
72 };
73
74 EFI_EVENT mBootGraphicsReadyToBootEvent;
75 UINTN mBootGraphicsResourceTableKey = 0;
76 BOOLEAN mIsLogoValid = FALSE;
77 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *mLogoBltBuffer = NULL;
78 UINTN mLogoDestX = 0;
79 UINTN mLogoDestY = 0;
80 UINTN mLogoWidth = 0;
81 UINTN mLogoHeight = 0;
82 BOOLEAN mAcpiBgrtInstalled = FALSE;
83 BOOLEAN mAcpiBgrtStatusChanged = FALSE;
84 BOOLEAN mAcpiBgrtBufferChanged = FALSE;
85
86 //
87 // ACPI Boot Graphics Resource Table template
88 //
89 EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE mBootGraphicsResourceTableTemplate = {
90 {
91 EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE,
92 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),
93 EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_REVISION, // Revision
94 0x00, // Checksum will be updated at runtime
95 //
96 // It is expected that these values will be updated at EntryPoint.
97 //
98 {0x00}, // OEM ID is a 6 bytes long field
99 0x00, // OEM Table ID(8 bytes long)
100 0x00, // OEM Revision
101 0x00, // Creator ID
102 0x00, // Creator Revision
103 },
104 EFI_ACPI_5_0_BGRT_VERSION, // Version
105 EFI_ACPI_5_0_BGRT_STATUS_VALID, // Status
106 EFI_ACPI_5_0_BGRT_IMAGE_TYPE_BMP, // Image Type
107 0, // Image Address
108 0, // Image Offset X
109 0 // Image Offset Y
110 };
111
112 /**
113 Update information of logo image drawn on screen.
114
115 @param This The pointer to the Boot Logo protocol instance.
116 @param BltBuffer The BLT buffer for logo drawn on screen. If BltBuffer
117 is set to NULL, it indicates that logo image is no
118 longer on the screen.
119 @param DestinationX X coordinate of destination for the BltBuffer.
120 @param DestinationY Y coordinate of destination for the BltBuffer.
121 @param Width Width of rectangle in BltBuffer in pixels.
122 @param Height Hight of rectangle in BltBuffer in pixels.
123
124 @retval EFI_SUCCESS The boot logo information was updated.
125 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
126 @retval EFI_OUT_OF_RESOURCES The logo information was not updated due to
127 insufficient memory resources.
128
129 **/
130 EFI_STATUS
131 EFIAPI
132 SetBootLogo (
133 IN EFI_BOOT_LOGO_PROTOCOL *This,
134 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
135 IN UINTN DestinationX,
136 IN UINTN DestinationY,
137 IN UINTN Width,
138 IN UINTN Height
139 )
140 {
141 EFI_STATUS Status;
142 UINTN BufferSize;
143 UINT32 Result32;
144
145 if (BltBuffer == NULL) {
146 mIsLogoValid = FALSE;
147 mAcpiBgrtStatusChanged = TRUE;
148 return EFI_SUCCESS;
149 }
150
151 //
152 // Width and height are not allowed to be zero.
153 //
154 if (Width == 0 || Height == 0) {
155 return EFI_INVALID_PARAMETER;
156 }
157
158 //
159 // Verify destination, width, and height do not overflow 32-bit values.
160 // The Boot Graphics Resource Table only has 32-bit fields for these values.
161 //
162 Status = SafeUintnToUint32 (DestinationX, &Result32);
163 if (EFI_ERROR (Status)) {
164 return EFI_INVALID_PARAMETER;
165 }
166 Status = SafeUintnToUint32 (DestinationY, &Result32);
167 if (EFI_ERROR (Status)) {
168 return EFI_INVALID_PARAMETER;
169 }
170 Status = SafeUintnToUint32 (Width, &Result32);
171 if (EFI_ERROR (Status)) {
172 return EFI_INVALID_PARAMETER;
173 }
174 Status = SafeUintnToUint32 (Height, &Result32);
175 if (EFI_ERROR (Status)) {
176 return EFI_INVALID_PARAMETER;
177 }
178
179 //
180 // Ensure the Height * Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) does
181 // not overflow UINTN
182 //
183 Status = SafeUintnMult (
184 Width,
185 Height,
186 &BufferSize
187 );
188 if (EFI_ERROR (Status)) {
189 return EFI_UNSUPPORTED;
190 }
191 Status = SafeUintnMult (
192 BufferSize,
193 sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),
194 &BufferSize
195 );
196 if (EFI_ERROR (Status)) {
197 return EFI_UNSUPPORTED;
198 }
199
200 //
201 // Update state
202 //
203 mAcpiBgrtBufferChanged = TRUE;
204
205 //
206 // Free old logo buffer
207 //
208 if (mLogoBltBuffer != NULL) {
209 FreePool (mLogoBltBuffer);
210 mLogoBltBuffer = NULL;
211 }
212
213 //
214 // Allocate new logo buffer
215 //
216 mLogoBltBuffer = AllocateCopyPool (BufferSize, BltBuffer);
217 if (mLogoBltBuffer == NULL) {
218 return EFI_OUT_OF_RESOURCES;
219 }
220
221 mLogoDestX = DestinationX;
222 mLogoDestY = DestinationY;
223 mLogoWidth = Width;
224 mLogoHeight = Height;
225 mIsLogoValid = TRUE;
226
227 return EFI_SUCCESS;
228 }
229
230 /**
231 Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to
232 install the Boot Graphics Resource Table.
233
234 @param[in] Event The Event that is being processed.
235 @param[in] Context The Event Context.
236
237 **/
238 VOID
239 EFIAPI
240 BgrtReadyToBootEventNotify (
241 IN EFI_EVENT Event,
242 IN VOID *Context
243 )
244 {
245 EFI_STATUS Status;
246 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
247 VOID *ImageBuffer;
248 UINT32 BmpSize;
249
250 //
251 // Get ACPI Table protocol.
252 //
253 Status = gBS->LocateProtocol (
254 &gEfiAcpiTableProtocolGuid,
255 NULL,
256 (VOID **) &AcpiTableProtocol
257 );
258 if (EFI_ERROR (Status)) {
259 return;
260 }
261
262 //
263 // Check whether Boot Graphics Resource Table is already installed.
264 //
265 if (mAcpiBgrtInstalled) {
266 if (!mAcpiBgrtStatusChanged && !mAcpiBgrtBufferChanged) {
267 //
268 // Nothing has changed
269 //
270 return;
271 } else {
272 //
273 // If BGRT data change happens, then uninstall orignal AcpiTable first
274 //
275 Status = AcpiTableProtocol->UninstallAcpiTable (
276 AcpiTableProtocol,
277 mBootGraphicsResourceTableKey
278 );
279 if (EFI_ERROR (Status)) {
280 return;
281 }
282 }
283 } else {
284 //
285 // Check whether Logo exists
286 //
287 if (mLogoBltBuffer == NULL) {
288 return;
289 }
290 }
291
292 if (mAcpiBgrtBufferChanged) {
293 //
294 // Free the old BMP image buffer
295 //
296 ImageBuffer = (UINT8 *)(UINTN)mBootGraphicsResourceTableTemplate.ImageAddress;
297 if (ImageBuffer != NULL) {
298 FreePool (ImageBuffer);
299 }
300
301 //
302 // Convert GOP Blt buffer to BMP image. Pass in ImageBuffer set to NULL
303 // so the BMP image is allocated by TranslateGopBltToBmp().
304 //
305 ImageBuffer = NULL;
306 Status = TranslateGopBltToBmp (
307 mLogoBltBuffer,
308 (UINT32)mLogoHeight,
309 (UINT32)mLogoWidth,
310 &ImageBuffer,
311 &BmpSize
312 );
313 if (EFI_ERROR (Status)) {
314 return;
315 }
316
317 //
318 // Free the logo buffer
319 //
320 FreePool (mLogoBltBuffer);
321 mLogoBltBuffer = NULL;
322
323 //
324 // Update BMP image fields of the Boot Graphics Resource Table
325 //
326 mBootGraphicsResourceTableTemplate.ImageAddress = (UINT64)(UINTN)ImageBuffer;
327 mBootGraphicsResourceTableTemplate.ImageOffsetX = (UINT32)mLogoDestX;
328 mBootGraphicsResourceTableTemplate.ImageOffsetY = (UINT32)mLogoDestY;
329 }
330
331 //
332 // Update Status field of Boot Graphics Resource Table
333 //
334 if (mIsLogoValid) {
335 mBootGraphicsResourceTableTemplate.Status = EFI_ACPI_5_0_BGRT_STATUS_VALID;
336 } else {
337 mBootGraphicsResourceTableTemplate.Status = EFI_ACPI_5_0_BGRT_STATUS_INVALID;
338 }
339
340 //
341 // Update Checksum of Boot Graphics Resource Table
342 //
343 mBootGraphicsResourceTableTemplate.Header.Checksum = 0;
344 mBootGraphicsResourceTableTemplate.Header.Checksum =
345 CalculateCheckSum8 (
346 (UINT8 *)&mBootGraphicsResourceTableTemplate,
347 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE)
348 );
349
350 //
351 // Publish Boot Graphics Resource Table.
352 //
353 Status = AcpiTableProtocol->InstallAcpiTable (
354 AcpiTableProtocol,
355 &mBootGraphicsResourceTableTemplate,
356 sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),
357 &mBootGraphicsResourceTableKey
358 );
359 if (EFI_ERROR (Status)) {
360 return;
361 }
362
363 mAcpiBgrtInstalled = TRUE;
364 mAcpiBgrtStatusChanged = FALSE;
365 mAcpiBgrtBufferChanged = FALSE;
366 }
367
368 /**
369 The module Entry Point of the Boot Graphics Resource Table DXE driver.
370
371 @param[in] ImageHandle The firmware allocated handle for the EFI image.
372 @param[in] SystemTable A pointer to the EFI System Table.
373
374 @retval EFI_SUCCESS The entry point is executed successfully.
375 @retval Other Some error occurs when executing this entry point.
376
377 **/
378 EFI_STATUS
379 EFIAPI
380 BootGraphicsDxeEntryPoint (
381 IN EFI_HANDLE ImageHandle,
382 IN EFI_SYSTEM_TABLE *SystemTable
383 )
384 {
385 EFI_STATUS Status;
386 EFI_ACPI_DESCRIPTION_HEADER *Header;
387
388 //
389 // Update Header fields of Boot Graphics Resource Table from PCDs
390 //
391 Header = &mBootGraphicsResourceTableTemplate.Header;
392 ZeroMem (Header->OemId, sizeof (Header->OemId));
393 CopyMem (
394 Header->OemId,
395 PcdGetPtr (PcdAcpiDefaultOemId),
396 MIN (PcdGetSize (PcdAcpiDefaultOemId), sizeof (Header->OemId))
397 );
398 WriteUnaligned64 (&Header->OemTableId, PcdGet64 (PcdAcpiDefaultOemTableId));
399 Header->OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
400 Header->CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
401 Header->CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
402
403 //
404 // Install Boot Logo protocol.
405 //
406 Status = gBS->InstallMultipleProtocolInterfaces (
407 &mBootLogoHandle,
408 &gEfiBootLogoProtocolGuid,
409 &mBootLogoProtocolTemplate,
410 NULL
411 );
412 ASSERT_EFI_ERROR (Status);
413
414 //
415 // Register notify function to install BGRT on ReadyToBoot Event.
416 //
417 Status = gBS->CreateEventEx (
418 EVT_NOTIFY_SIGNAL,
419 TPL_CALLBACK,
420 BgrtReadyToBootEventNotify,
421 NULL,
422 &gEfiEventReadyToBootGuid,
423 &mBootGraphicsReadyToBootEvent
424 );
425 ASSERT_EFI_ERROR (Status);
426
427 return Status;
428 }