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