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