]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/BootLogoLib/BootLogoLib.c
OvmfPkg/PlatformBds: Do not call BootLogoEnableLogo
[mirror_edk2.git] / MdeModulePkg / Library / BootLogoLib / BootLogoLib.c
1 /** @file
2 This library is only intended to be used by PlatformBootManagerLib
3 to show progress bar and LOGO.
4
5 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials are licensed and made available under
7 the terms and conditions of the BSD License that accompanies this distribution.
8 The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <PiDxe.h>
17 #include <Protocol/SimpleTextOut.h>
18 #include <Protocol/PlatformLogo.h>
19 #include <Protocol/GraphicsOutput.h>
20 #include <Protocol/UgaDraw.h>
21 #include <Protocol/BootLogo.h>
22 #include <Library/BaseLib.h>
23 #include <Library/UefiLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/UefiBootServicesTableLib.h>
26 #include <Library/DxeServicesLib.h>
27 #include <Library/PcdLib.h>
28 #include <Library/MemoryAllocationLib.h>
29 #include <Library/DebugLib.h>
30 #include <Library/ImageDecoderLib.h>
31
32 /**
33 Show LOGO on all consoles.
34
35 @param[in] ImageFormat Format of the image file.
36 @param[in] LogoFile The file name of logo to display.
37 @param[in] Attribute The display attributes of the image returned.
38 @param[in] OffsetX The X offset of the image regarding the Attribute.
39 @param[in] OffsetY The Y offset of the image regarding the Attribute.
40
41 @retval EFI_SUCCESS Logo was displayed.
42 @retval EFI_UNSUPPORTED Logo was not found or cannot be displayed.
43 **/
44 EFI_STATUS
45 EFIAPI
46 BootLogoEnableLogo (
47 IN IMAGE_FORMAT ImageFormat,
48 IN EFI_GUID *Logo,
49 IN EDKII_PLATFORM_LOGO_DISPLAY_ATTRIBUTE Attribute,
50 IN INTN OffsetX,
51 IN INTN OffsetY
52 )
53 {
54 EFI_STATUS Status;
55 EDKII_PLATFORM_LOGO_PROTOCOL *PlatformLogo;
56 UINT32 SizeOfX;
57 UINT32 SizeOfY;
58 INTN DestX;
59 INTN DestY;
60 UINT8 *ImageData;
61 UINTN ImageSize;
62 UINTN BltSize;
63 UINT32 Instance;
64 UINTN Height;
65 UINTN Width;
66 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
67 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
68 UINT32 ColorDepth;
69 UINT32 RefreshRate;
70 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
71 EFI_BOOT_LOGO_PROTOCOL *BootLogo;
72 UINTN NumberOfLogos;
73 EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LogoBlt;
74 UINTN LogoDestX;
75 UINTN LogoDestY;
76 UINTN LogoHeight;
77 UINTN LogoWidth;
78 UINTN NewDestX;
79 UINTN NewDestY;
80 UINTN NewHeight;
81 UINTN NewWidth;
82 UINTN BufferSize;
83
84 UgaDraw = NULL;
85 //
86 // Try to open GOP first
87 //
88 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
89 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
90 GraphicsOutput = NULL;
91 //
92 // Open GOP failed, try to open UGA
93 //
94 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
95 if (EFI_ERROR (Status)) {
96 UgaDraw = NULL;
97 }
98 }
99 if (EFI_ERROR (Status)) {
100 return EFI_UNSUPPORTED;
101 }
102
103 Status = gBS->LocateProtocol (&gEdkiiPlatformLogoProtocolGuid, NULL, (VOID **) &PlatformLogo);
104 if (EFI_ERROR (Status)) {
105 PlatformLogo = NULL;
106 }
107
108 if ((Logo == NULL) && (PlatformLogo == NULL)) {
109 return EFI_UNSUPPORTED;
110 }
111
112 //
113 // Try to open Boot Logo Protocol.
114 //
115 Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
116 if (EFI_ERROR (Status)) {
117 BootLogo = NULL;
118 }
119
120 //
121 // Erase Cursor from screen
122 //
123 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
124
125 if (GraphicsOutput != NULL) {
126 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
127 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
128
129 } else {
130 ASSERT (UgaDraw != NULL);
131 Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
132 if (EFI_ERROR (Status)) {
133 return EFI_UNSUPPORTED;
134 }
135 }
136
137 Blt = NULL;
138 NumberOfLogos = 0;
139 LogoDestX = 0;
140 LogoDestY = 0;
141 LogoHeight = 0;
142 LogoWidth = 0;
143 NewDestX = 0;
144 NewDestY = 0;
145 NewHeight = 0;
146 NewWidth = 0;
147 Instance = 0;
148 DestX = 0;
149 DestY = 0;
150 while (TRUE) {
151 ImageData = NULL;
152 ImageSize = 0;
153
154 if (PlatformLogo != NULL) {
155 //
156 // Get image from OEMBadging protocol.
157 //
158 Status = PlatformLogo->GetImage (
159 PlatformLogo,
160 &Instance,
161 &ImageFormat,
162 &ImageData,
163 &ImageSize,
164 &Attribute,
165 &OffsetX,
166 &OffsetY
167 );
168 if (EFI_ERROR (Status)) {
169 break;
170 }
171
172 } else {
173 //
174 // Get the specified image from FV.
175 //
176 Status = GetSectionFromAnyFv (Logo, EFI_SECTION_RAW, 0, (VOID **) &ImageData, &ImageSize);
177 if (EFI_ERROR (Status)) {
178 return EFI_UNSUPPORTED;
179 }
180 }
181
182 if (Blt != NULL) {
183 FreePool (Blt);
184 }
185
186 Status = DecodeImage (ImageFormat, ImageData, ImageSize, &Blt, &BltSize, &Width, &Height);
187 FreePool (ImageData);
188 if (EFI_ERROR (Status)) {
189 if (Logo != NULL) {
190 //
191 // Directly return failure for single LOGO
192 //
193 return Status;
194 } else {
195 continue;
196 }
197 }
198
199 //
200 // Calculate the display position according to Attribute.
201 //
202 switch (Attribute) {
203 case EdkiiPlatformLogoDisplayAttributeLeftTop:
204 DestX = 0;
205 DestY = 0;
206 break;
207 case EdkiiPlatformLogoDisplayAttributeCenterTop:
208 DestX = (SizeOfX - Width) / 2;
209 DestY = 0;
210 break;
211 case EdkiiPlatformLogoDisplayAttributeRightTop:
212 DestX = SizeOfX - Width;
213 DestY = 0;
214 break;
215
216 case EdkiiPlatformLogoDisplayAttributeCenterLeft:
217 DestX = 0;
218 DestY = (SizeOfY - Height) / 2;
219 break;
220 case EdkiiPlatformLogoDisplayAttributeCenter:
221 DestX = (SizeOfX - Width) / 2;
222 DestY = (SizeOfY - Height) / 2;
223 break;
224 case EdkiiPlatformLogoDisplayAttributeCenterRight:
225 DestX = SizeOfX - Width;
226 DestY = (SizeOfY - Height) / 2;
227 break;
228
229 case EdkiiPlatformLogoDisplayAttributeLeftBottom:
230 DestX = 0;
231 DestY = SizeOfY - Height;
232 break;
233 case EdkiiPlatformLogoDisplayAttributeCenterBottom:
234 DestX = (SizeOfX - Width) / 2;
235 DestY = SizeOfY - Height;
236 break;
237 case EdkiiPlatformLogoDisplayAttributeRightBottom:
238 DestX = SizeOfX - Width;
239 DestY = SizeOfY - Height;
240 break;
241
242 default:
243 ASSERT (FALSE);
244 break;
245 }
246
247 DestX += OffsetX;
248 DestY += OffsetY;
249
250 if ((DestX >= 0) && (DestY >= 0)) {
251 if (GraphicsOutput != NULL) {
252 Status = GraphicsOutput->Blt (
253 GraphicsOutput,
254 Blt,
255 EfiBltBufferToVideo,
256 0,
257 0,
258 (UINTN) DestX,
259 (UINTN) DestY,
260 Width,
261 Height,
262 Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
263 );
264 } else {
265 ASSERT (UgaDraw != NULL);
266 Status = UgaDraw->Blt (
267 UgaDraw,
268 (EFI_UGA_PIXEL *) Blt,
269 EfiUgaBltBufferToVideo,
270 0,
271 0,
272 (UINTN) DestX,
273 (UINTN) DestY,
274 Width,
275 Height,
276 Width * sizeof (EFI_UGA_PIXEL)
277 );
278 }
279
280 //
281 // Report displayed Logo information.
282 //
283 if (!EFI_ERROR (Status)) {
284 NumberOfLogos++;
285
286 if (LogoWidth == 0) {
287 //
288 // The first Logo.
289 //
290 LogoDestX = (UINTN) DestX;
291 LogoDestY = (UINTN) DestY;
292 LogoWidth = Width;
293 LogoHeight = Height;
294 } else {
295 //
296 // Merge new logo with old one.
297 //
298 NewDestX = MIN ((UINTN) DestX, LogoDestX);
299 NewDestY = MIN ((UINTN) DestY, LogoDestY);
300 NewWidth = MAX ((UINTN) DestX + Width, LogoDestX + LogoWidth) - NewDestX;
301 NewHeight = MAX ((UINTN) DestY + Height, LogoDestY + LogoHeight) - NewDestY;
302
303 LogoDestX = NewDestX;
304 LogoDestY = NewDestY;
305 LogoWidth = NewWidth;
306 LogoHeight = NewHeight;
307 }
308 }
309 }
310
311 if (PlatformLogo == NULL) {
312 break;
313 }
314 }
315
316 if (BootLogo == NULL || NumberOfLogos == 0) {
317 //
318 // No logo displayed.
319 //
320 if (Blt != NULL) {
321 FreePool (Blt);
322 }
323
324 return Status;
325 }
326
327 //
328 // Advertise displayed Logo information.
329 //
330 if (NumberOfLogos == 1) {
331 //
332 // Only one logo displayed, use its Blt buffer directly for BootLogo protocol.
333 //
334 LogoBlt = Blt;
335 Status = EFI_SUCCESS;
336 } else {
337 //
338 // More than one Logo displayed, get merged BltBuffer using VideoToBuffer operation.
339 //
340 if (Blt != NULL) {
341 FreePool (Blt);
342 }
343
344 //
345 // Ensure the LogoHeight * LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow
346 //
347 if (LogoHeight > MAX_UINTN / LogoWidth / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)) {
348 return EFI_UNSUPPORTED;
349 }
350 BufferSize = LogoWidth * LogoHeight * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
351
352 LogoBlt = AllocatePool (BufferSize);
353 if (LogoBlt == NULL) {
354 return EFI_OUT_OF_RESOURCES;
355 }
356
357 if (GraphicsOutput != NULL) {
358 Status = GraphicsOutput->Blt (
359 GraphicsOutput,
360 LogoBlt,
361 EfiBltVideoToBltBuffer,
362 LogoDestX,
363 LogoDestY,
364 0,
365 0,
366 LogoWidth,
367 LogoHeight,
368 LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
369 );
370 } else {
371 Status = UgaDraw->Blt (
372 UgaDraw,
373 (EFI_UGA_PIXEL *) LogoBlt,
374 EfiUgaVideoToBltBuffer,
375 LogoDestX,
376 LogoDestY,
377 0,
378 0,
379 LogoWidth,
380 LogoHeight,
381 LogoWidth * sizeof (EFI_UGA_PIXEL)
382 );
383 }
384 }
385
386 if (!EFI_ERROR (Status)) {
387 BootLogo->SetBootLogo (BootLogo, LogoBlt, LogoDestX, LogoDestY, LogoWidth, LogoHeight);
388 }
389 FreePool (LogoBlt);
390
391 return Status;
392 }
393
394 /**
395 Use SystemTable Conout to turn on video based Simple Text Out consoles. The
396 Simple Text Out screens will now be synced up with all non video output devices
397
398 @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
399
400 **/
401 EFI_STATUS
402 EFIAPI
403 BootLogoDisableLogo (
404 VOID
405 )
406 {
407
408 //
409 // Enable Cursor on Screen
410 //
411 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
412 return EFI_SUCCESS;
413 }
414
415
416 /**
417
418 Update progress bar with title above it. It only works in Graphics mode.
419
420 @param TitleForeground Foreground color for Title.
421 @param TitleBackground Background color for Title.
422 @param Title Title above progress bar.
423 @param ProgressColor Progress bar color.
424 @param Progress Progress (0-100)
425 @param PreviousValue The previous value of the progress.
426
427 @retval EFI_STATUS Success update the progress bar
428
429 **/
430 EFI_STATUS
431 EFIAPI
432 BootLogoUpdateProgress (
433 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
434 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
435 IN CHAR16 *Title,
436 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
437 IN UINTN Progress,
438 IN UINTN PreviousValue
439 )
440 {
441 EFI_STATUS Status;
442 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
443 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
444 UINT32 SizeOfX;
445 UINT32 SizeOfY;
446 UINT32 ColorDepth;
447 UINT32 RefreshRate;
448 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
449 UINTN BlockHeight;
450 UINTN BlockWidth;
451 UINTN BlockNum;
452 UINTN PosX;
453 UINTN PosY;
454 UINTN Index;
455
456 if (Progress > 100) {
457 return EFI_INVALID_PARAMETER;
458 }
459
460 UgaDraw = NULL;
461 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput);
462 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
463 GraphicsOutput = NULL;
464
465 Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw);
466 if (EFI_ERROR (Status)) {
467 UgaDraw = NULL;
468 }
469 }
470 if (EFI_ERROR (Status)) {
471 return EFI_UNSUPPORTED;
472 }
473
474 SizeOfX = 0;
475 SizeOfY = 0;
476 if (GraphicsOutput != NULL) {
477 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
478 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
479 } else if (UgaDraw != NULL) {
480 Status = UgaDraw->GetMode (
481 UgaDraw,
482 &SizeOfX,
483 &SizeOfY,
484 &ColorDepth,
485 &RefreshRate
486 );
487 if (EFI_ERROR (Status)) {
488 return EFI_UNSUPPORTED;
489 }
490 } else {
491 return EFI_UNSUPPORTED;
492 }
493
494 BlockWidth = SizeOfX / 100;
495 BlockHeight = SizeOfY / 50;
496
497 BlockNum = Progress;
498
499 PosX = 0;
500 PosY = SizeOfY * 48 / 50;
501
502 if (BlockNum == 0) {
503 //
504 // Clear progress area
505 //
506 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
507
508 if (GraphicsOutput != NULL) {
509 Status = GraphicsOutput->Blt (
510 GraphicsOutput,
511 &Color,
512 EfiBltVideoFill,
513 0,
514 0,
515 0,
516 PosY - EFI_GLYPH_HEIGHT - 1,
517 SizeOfX,
518 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
519 SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
520 );
521 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
522 Status = UgaDraw->Blt (
523 UgaDraw,
524 (EFI_UGA_PIXEL *) &Color,
525 EfiUgaVideoFill,
526 0,
527 0,
528 0,
529 PosY - EFI_GLYPH_HEIGHT - 1,
530 SizeOfX,
531 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
532 SizeOfX * sizeof (EFI_UGA_PIXEL)
533 );
534 } else {
535 return EFI_UNSUPPORTED;
536 }
537 }
538 //
539 // Show progress by drawing blocks
540 //
541 for (Index = PreviousValue; Index < BlockNum; Index++) {
542 PosX = Index * BlockWidth;
543 if (GraphicsOutput != NULL) {
544 Status = GraphicsOutput->Blt (
545 GraphicsOutput,
546 &ProgressColor,
547 EfiBltVideoFill,
548 0,
549 0,
550 PosX,
551 PosY,
552 BlockWidth - 1,
553 BlockHeight,
554 (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
555 );
556 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
557 Status = UgaDraw->Blt (
558 UgaDraw,
559 (EFI_UGA_PIXEL *) &ProgressColor,
560 EfiUgaVideoFill,
561 0,
562 0,
563 PosX,
564 PosY,
565 BlockWidth - 1,
566 BlockHeight,
567 (BlockWidth) * sizeof (EFI_UGA_PIXEL)
568 );
569 } else {
570 return EFI_UNSUPPORTED;
571 }
572 }
573
574 PrintXY (
575 (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,
576 PosY - EFI_GLYPH_HEIGHT - 1,
577 &TitleForeground,
578 &TitleBackground,
579 Title
580 );
581
582 return EFI_SUCCESS;
583 }