1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Library
4 * FILE: boot/environ/lib/platform/display.c
5 * PURPOSE: Boot Library Display Management Routines
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "bl.h"
12 #include <bcd.h>
13
14 /* DATA VARIABLES ************************************************************/
15
16 PVOID BfiCachedStrikeData;
17 LIST_ENTRY BfiDeferredListHead;
18 LIST_ENTRY BfiFontFileListHead;
19 PVOID BfiGraphicsRectangle;
20
21 ULONG ConsoleGraphicalResolutionListFlags;
22 BL_DISPLAY_MODE ConsoleGraphicalResolutionList[3] =
23 {
24 {1024, 768, 1024},
25 {800, 600, 800},
26 {1024, 600, 1024}
27 };
28 ULONG ConsoleGraphicalResolutionListSize = RTL_NUMBER_OF(ConsoleGraphicalResolutionList);
29
30 BL_DISPLAY_MODE ConsoleTextResolutionList[1] =
31 {
32 {80, 25, 80}
33 };
34
35 PVOID DspRemoteInputConsole;
36 PVOID DspTextConsole;
37 PVOID DspGraphicalConsole;
38 PVOID DspLocalInputConsole;
39
40 /* FUNCTIONS *****************************************************************/
41
42 BOOLEAN
DsppGraphicsDisabledByBcd(VOID)43 DsppGraphicsDisabledByBcd (
44 VOID
45 )
46 {
47 BOOLEAN Disabled;
48 NTSTATUS Status;
49
50 /* Get the boot option, and if present, return the result */
51 Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
52 BcdLibraryBoolean_GraphicsModeDisabled,
53 &Disabled);
54 return (NT_SUCCESS(Status) && (Disabled));
55 }
56
57 NTSTATUS
DsppLoadFontFile(_In_ PWCHAR FontFileName)58 DsppLoadFontFile (
59 _In_ PWCHAR FontFileName
60 )
61 {
62 PBL_DEVICE_DESCRIPTOR FontDevice;
63 NTSTATUS Status;
64 SIZE_T NameLength, DirectoryLength, TotalLength;
65 PWCHAR FontPath, FontDirectory;
66 BL_LIBRARY_PARAMETERS LibraryParameters;
67 BOOLEAN CustomDirectory, CustomDevice;
68
69 /* Initialize locals */
70 CustomDirectory = TRUE;
71 CustomDevice = TRUE;
72 FontDevice = NULL;
73 FontPath = NULL;
74 FontDirectory = NULL;
75
76 /* Check if a custom font path should be used */
77 Status = BlGetBootOptionString(BlpApplicationEntry.BcdData,
78 BcdLibraryString_FontPath,
79 &FontDirectory);
80 if (!NT_SUCCESS(Status))
81 {
82 /* Nope, use the one configured by the library */
83 CustomDirectory = FALSE;
84 RtlCopyMemory(&LibraryParameters,
85 &BlpLibraryParameters,
86 sizeof(LibraryParameters)),
87 FontDirectory = LibraryParameters.FontBaseDirectory;
88 }
89
90 /* Do we still not have a font directory? */
91 if (!FontDirectory)
92 {
93 /* Use the boot device and boot directory */
94 CustomDevice = FALSE;
95 FontDevice = BlpBootDevice;
96 FontDirectory = L"\\EFI\\Microsoft\\Boot\\Fonts";
97 }
98 else
99 {
100 /* Otherwise, if we have a font directory, what device is the app on? */
101 Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData,
102 BcdLibraryDevice_ApplicationDevice,
103 &FontDevice,
104 NULL);
105 if (!NT_SUCCESS(Status))
106 {
107 /* If we don't know the device, we can't open the path */
108 goto Quickie;
109 }
110 }
111
112 /* Figure out the length of the file name, and of the directory */
113 NameLength = wcslen(FontFileName);
114 DirectoryLength = wcslen(FontDirectory);
115
116 /* Safely add them up*/
117 Status = RtlSIZETAdd(NameLength, DirectoryLength, &TotalLength);
118 if (!NT_SUCCESS(Status))
119 {
120 goto Quickie;
121 }
122
123 /* Convert to bytes */
124 Status = RtlSIZETMult(TotalLength, sizeof(WCHAR), &TotalLength);
125 if (!NT_SUCCESS(Status))
126 {
127 goto Quickie;
128 }
129
130 /* Add a terminating NUL */
131 Status = RtlSIZETAdd(TotalLength, sizeof(UNICODE_NULL), &TotalLength);
132 if (!NT_SUCCESS(Status))
133 {
134 goto Quickie;
135 }
136
137 /* Allocate the final buffer for it */
138 FontPath = BlMmAllocateHeap(TotalLength);
139 if (!FontPath)
140 {
141 Status = STATUS_NO_MEMORY;
142 goto Quickie;
143 }
144
145 /* Concatenate the directory with the file name */
146 wcscpy(FontPath, FontDirectory);
147 wcscat(FontPath, FontFileName);
148
149 /* Try to load this font */
150 Status = BfLoadFontFile(FontDevice, FontPath);
151
152 Quickie:
153 /* Check if we had a custom font device allocated and free it */
154 if ((CustomDevice) && (FontDevice))
155 {
156 BlMmFreeHeap(FontDevice);
157 }
158
159 /* Check if we had a custom font directory allocated and free it */
160 if ((CustomDirectory) && (CustomDevice))
161 {
162 ASSERT(FontDirectory);
163 BlMmFreeHeap(FontDirectory);
164 }
165
166 /* Check if we had allocated a font path and free it */
167 if (FontPath)
168 {
169 BlMmFreeHeap(FontPath);
170 }
171
172 /* Return back */
173 return Status;
174 }
175
176 NTSTATUS
BlpDisplayRegisterLocale(_In_ PWCHAR Locale)177 BlpDisplayRegisterLocale (
178 _In_ PWCHAR Locale
179 )
180 {
181 BOOLEAN StandardLocale;
182 NTSTATUS Status;
183 PWCHAR FontFileName;
184 PBL_DEFERRED_FONT_FILE DeferredFont;
185 PLIST_ENTRY NextEntry;
186 WCHAR Prefix[3];
187
188 /* Assume custom locale */
189 StandardLocale = FALSE;
190
191 /* Bail out if the locale string seems invalid */
192 if (wcslen(Locale) < 2)
193 {
194 return STATUS_INVALID_PARAMETER;
195 }
196
197 /* Check the prefix first, then traditional vs. simplified */
198 Prefix[0] = Locale[0];
199 Prefix[1] = Locale[1];
200 Prefix[2] = UNICODE_NULL;
201 if (!_wcsicmp(Prefix, L"ja"))
202 {
203 FontFileName = L"\\jpn_boot.ttf";
204 }
205 else if (!_wcsicmp(Prefix, L"ko"))
206 {
207 FontFileName = L"\\kor_boot.ttf";
208 }
209 else if (!(_wcsicmp(Locale, L"zh-CN")) ||
210 !(_wcsicmp(Locale, L"zh-CHS")) ||
211 !(_wcsicmp(Locale, L"zh-Hans")))
212 {
213 FontFileName = L"\\chs_boot.ttf";
214 }
215 else if (!(_wcsicmp(Locale, L"zh-TW")) &&
216 !(_wcsicmp(Locale, L"zh-CHT")) &&
217 !(_wcsicmp(Locale, L"zh-HK")) &&
218 !(_wcsicmp(Locale, L"zh-Hant")))
219 {
220 FontFileName = L"\\cht_boot.ttf";
221 }
222 else
223 {
224 StandardLocale = TRUE;
225 FontFileName = L"\\wgl4_boot.ttf";
226 }
227
228 /* Parse all the currently deferred fonts*/
229 NextEntry = BfiDeferredListHead.Flink;
230 while (NextEntry != &BfiDeferredListHead)
231 {
232 /* Grab the font */
233 DeferredFont = CONTAINING_RECORD(NextEntry, BL_DEFERRED_FONT_FILE, ListEntry);
234
235 /* Move to the next entry, and remove this one */
236 NextEntry = NextEntry->Flink;
237 RemoveEntryList(&DeferredFont->ListEntry);
238
239 /* Free the deferred font, we'll be loading a new one */
240 BfiFreeDeferredFontFile(DeferredFont);
241 }
242
243 /* Load the primary font */
244 Status = DsppLoadFontFile(FontFileName);
245 if (NT_SUCCESS(Status) && !(StandardLocale))
246 {
247 /* Also load the standard US one if we loaded a different one */
248 Status = DsppLoadFontFile(L"\\wgl4_boot.ttf");
249 }
250
251 /* Return back to caller */
252 return Status;
253 }
254
255 NTSTATUS
DsppInitialize(_In_ ULONG Flags)256 DsppInitialize (
257 _In_ ULONG Flags
258 )
259 {
260 BL_LIBRARY_PARAMETERS LibraryParameters = BlpLibraryParameters;
261 BOOLEAN NoGraphics, HighestMode;
262 NTSTATUS Status;
263 PBL_DISPLAY_MODE DisplayMode;
264 ULONGLONG GraphicsResolution;
265 PBL_GRAPHICS_CONSOLE GraphicsConsole;
266 PBL_TEXT_CONSOLE TextConsole, RemoteConsole;
267
268 /* Initialize font data */
269 BfiCachedStrikeData = 0;
270 InitializeListHead(&BfiDeferredListHead);
271 InitializeListHead(&BfiFontFileListHead);
272
273 /* Allocate the font rectangle */
274 BfiGraphicsRectangle = BlMmAllocateHeap(90);
275 if (!BfiGraphicsRectangle)
276 {
277 return STATUS_NO_MEMORY;
278 }
279
280 /* Check if display re-initialization is requested */
281 if (LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE_ALL)
282 {
283 /* Recreate a local input console */
284 ConsoleCreateLocalInputConsole();
285 }
286
287 /* Check if no graphics console is needed */
288 if ((Flags & BL_LIBRARY_FLAG_NO_GRAPHICS_CONSOLE) ||
289 (DsppGraphicsDisabledByBcd()))
290 {
291 /* Remember this */
292 NoGraphics = TRUE;
293 }
294 else
295 {
296 /* No graphics -- remember this */
297 NoGraphics = FALSE;
298 }
299
300 /* On first load, we always initialize a graphics display */
301 GraphicsConsole = NULL;
302 if (!(Flags & BL_LIBRARY_FLAG_REINITIALIZE_ALL) || !(NoGraphics))
303 {
304 /* Default to mode 0 (1024x768) */
305 DisplayMode = &ConsoleGraphicalResolutionList[0];
306
307 /* Check what resolution to use*/
308 Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
309 BcdLibraryInteger_GraphicsResolution,
310 &GraphicsResolution);
311 if (NT_SUCCESS(Status))
312 {
313 ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG;
314 EfiPrintf(L"Display selection not yet handled\r\n");
315 return STATUS_NOT_IMPLEMENTED;
316 }
317
318 /* Check if the highest mode should be forced */
319 Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
320 BcdLibraryBoolean_GraphicsForceHighestMode,
321 &HighestMode);
322 if (NT_SUCCESS(Status))
323 {
324 ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG;
325 EfiPrintf(L"High res mode not yet handled\r\n");
326 return STATUS_NOT_IMPLEMENTED;
327 }
328
329 /* Do we need graphics mode after all? */
330 if (!NoGraphics)
331 {
332 /* Yep -- go allocate it */
333 GraphicsConsole = BlMmAllocateHeap(sizeof(*GraphicsConsole));
334 if (GraphicsConsole)
335 {
336 /* Construct it */
337 Status = ConsoleGraphicalConstruct(GraphicsConsole);
338 if (!NT_SUCCESS(Status))
339 {
340 EfiPrintf(L"GFX FAILED: %lx\r\n", Status);
341 BlMmFreeHeap(GraphicsConsole);
342 GraphicsConsole = NULL;
343 }
344 }
345 }
346
347 /* Are we using something else than the default mode? */
348 if (DisplayMode != &ConsoleGraphicalResolutionList[0])
349 {
350 EfiPrintf(L"Display path not handled\r\n");
351 return STATUS_NOT_SUPPORTED;
352 }
353
354 /* Mask out all the flags now */
355 ConsoleGraphicalResolutionListFlags &= ~(BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG |
356 BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG);
357 }
358
359 /* Do we have a graphics console? */
360 TextConsole = NULL;
361 if (!GraphicsConsole)
362 {
363 /* Nope -- go allocate a text console */
364 TextConsole = BlMmAllocateHeap(sizeof(*TextConsole));
365 if (TextConsole)
366 {
367 /* Construct it */
368 Status = ConsoleTextLocalConstruct(TextConsole, TRUE);
369 if (!NT_SUCCESS(Status))
370 {
371 BlMmFreeHeap(TextConsole);
372 TextConsole = NULL;
373 }
374 }
375 }
376
377 /* Initialize all globals to NULL */
378 DspRemoteInputConsole = NULL;
379 DspTextConsole = NULL;
380 DspGraphicalConsole = NULL;
381
382 /* If we don't have a text console, go get a remote console */
383 RemoteConsole = NULL;
384 if (!TextConsole)
385 {
386 ConsoleCreateRemoteConsole(&RemoteConsole);
387 }
388
389 /* Do we have a remote console? */
390 if (!RemoteConsole)
391 {
392 /* Nope -- what about a graphical one? */
393 if (GraphicsConsole)
394 {
395 /* Yes, use it for both graphics and text */
396 DspGraphicalConsole = GraphicsConsole;
397 DspTextConsole = GraphicsConsole;
398 }
399 else if (TextConsole)
400 {
401 /* Nope, but we have a text console */
402 DspTextConsole = TextConsole;
403 }
404
405 /* Console has been setup */
406 return STATUS_SUCCESS;
407 }
408
409 /* We have a remote console -- have to figure out how to use it*/
410 EfiPrintf(L"Display path not handled\r\n");
411 return STATUS_NOT_SUPPORTED;
412 }
413
414 NTSTATUS
DsppReinitialize(_In_ ULONG Flags)415 DsppReinitialize (
416 _In_ ULONG Flags
417 )
418 {
419 PBL_TEXT_CONSOLE TextConsole;
420 PBL_GRAPHICS_CONSOLE GraphicsConsole;
421 NTSTATUS Status;
422 ULONGLONG GraphicsResolution;
423 BOOLEAN HighestMode;
424 BL_DISPLAY_MODE CurrentResolution;
425
426 /* Do we have local input yet? */
427 if (!DspLocalInputConsole)
428 {
429 /* Create it now */
430 ConsoleCreateLocalInputConsole();
431 }
432
433 /* If a graphics console is present without a remote console... */
434 TextConsole = NULL;
435 if (!(DspRemoteInputConsole) && (DspGraphicalConsole))
436 {
437 /* Try to create a remote console */
438 ConsoleCreateRemoteConsole(&TextConsole);
439 }
440
441 /* All good for now */
442 Status = STATUS_SUCCESS;
443
444 /* Now check if we were able to create the remote console */
445 if (TextConsole)
446 {
447 EfiPrintf(L"EMS not supported\r\n");
448 return STATUS_NOT_IMPLEMENTED;
449 }
450
451 /* Set a local for the right cast */
452 GraphicsConsole = DspGraphicalConsole;
453
454 /* Nothing to do without a graphics console being reinitialized */
455 if (!(Flags & BL_LIBRARY_FLAG_REINITIALIZE_ALL) ||
456 !(GraphicsConsole) ||
457 !(((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->IsEnabled(GraphicsConsole)))
458 {
459 return Status;
460 }
461
462 /* Check if graphics are disabled in the BCD */
463 if (DsppGraphicsDisabledByBcd())
464 {
465 /* Turn off the graphics console, switching back to text mode */
466 Status = ((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->Enable(GraphicsConsole, FALSE);
467 }
468
469 /* Check if a custom graphics resolution is set */
470 if (MiscGetBootOption(BlpApplicationEntry.BcdData,
471 BcdLibraryInteger_GraphicsResolution))
472 {
473 /* Check what it's set to */
474 Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
475 BcdLibraryInteger_GraphicsResolution,
476 &GraphicsResolution);
477 if (!NT_SUCCESS(Status))
478 {
479 return Status;
480 }
481
482 /* Now check our current graphical resolution */
483 Status = ((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->GetGraphicalResolution(GraphicsConsole,
484 &CurrentResolution);
485 if (!NT_SUCCESS(Status))
486 {
487 return Status;
488 }
489
490 /* Remember that we're forcing a video mode */
491 ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG;
492
493 /* Check which resolution to set */
494 if (!GraphicsResolution)
495 {
496 /* 1024x768 */
497 EfiPrintf(L"Display selection not yet handled\r\n");
498 return STATUS_NOT_IMPLEMENTED;
499 }
500 else if (GraphicsResolution == 1)
501 {
502 /* 800x600 */
503 EfiPrintf(L"Display selection not yet handled\r\n");
504 return STATUS_NOT_IMPLEMENTED;
505 }
506 else if (GraphicsResolution == 2)
507 {
508 /* 1024x600 */
509 EfiPrintf(L"Display selection not yet handled\r\n");
510 return STATUS_NOT_IMPLEMENTED;
511 }
512 }
513
514 /* Check if the force highest mode setting is present */
515 if (MiscGetBootOption(BlpApplicationEntry.BcdData,
516 BcdLibraryBoolean_GraphicsForceHighestMode))
517 {
518 /* Check what it's set to */
519 Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
520 BcdLibraryBoolean_GraphicsForceHighestMode,
521 &HighestMode);
522 if ((NT_SUCCESS(Status)) && (HighestMode))
523 {
524 /* Remember that high rest mode is being forced */
525 ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG;
526
527 /* Turn it on */
528 //((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->SetGraphicalResolution(GraphicsConsole, 0, 0);
529
530 /* All done now */
531 ConsoleGraphicalResolutionListFlags |= ~BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG;
532 EfiPrintf(L"High res mode not yet handled\r\n");
533 Status = STATUS_NOT_IMPLEMENTED;
534 }
535 }
536
537 /* Return back to the caller */
538 return Status;
539 }
540
541 NTSTATUS
BlpDisplayReinitialize(VOID)542 BlpDisplayReinitialize (
543 VOID
544 )
545 {
546 NTSTATUS Status = STATUS_SUCCESS;
547 PBL_TEXT_CONSOLE TextConsole;
548 PBL_INPUT_CONSOLE InputConsole;
549
550 /* Do we have a local console? */
551 InputConsole = DspLocalInputConsole;
552 if (InputConsole)
553 {
554 /* Reinitialize it */
555 Status = InputConsole->Callbacks->Reinitialize((PBL_TEXT_CONSOLE)InputConsole);
556 if (!NT_SUCCESS(Status))
557 {
558 return Status;
559 }
560 }
561
562 /* Do we have a text console? */
563 TextConsole = DspTextConsole;
564 if (TextConsole)
565 {
566 /* Reinitialize it */
567 Status = TextConsole->Callbacks->Reinitialize(TextConsole);
568 }
569
570 /* Return status */
571 return Status;
572 }
573
574 NTSTATUS
BlpDisplayInitialize(_In_ ULONG Flags)575 BlpDisplayInitialize (
576 _In_ ULONG Flags
577 )
578 {
579 NTSTATUS Status;
580
581 /* Are we resetting or initializing? */
582 if (Flags & BL_LIBRARY_FLAG_REINITIALIZE)
583 {
584 /* This is a reset */
585 Status = DsppReinitialize(Flags);
586 if (NT_SUCCESS(Status))
587 {
588 /* Re-initialize the class as well */
589 Status = BlpDisplayReinitialize();
590 }
591 }
592 else
593 {
594 /* Initialize the display */
595 Status = DsppInitialize(Flags);
596 }
597
598 /* Return display initialization state */
599 return Status;
600 }
601
602 VOID
BlDisplayGetTextCellResolution(_Out_ PULONG TextWidth,_Out_ PULONG TextHeight)603 BlDisplayGetTextCellResolution (
604 _Out_ PULONG TextWidth,
605 _Out_ PULONG TextHeight
606 )
607 {
608 NTSTATUS Status;
609 PBL_GRAPHICS_CONSOLE GraphicsConsole;
610
611 /* If the caller doesn't want anything, bail out */
612 if (!(TextWidth) || !(TextHeight))
613 {
614 return;
615 }
616
617 /* Do we have a text console? */
618 Status = STATUS_UNSUCCESSFUL;
619 if (DspTextConsole)
620 {
621 /* Do we have a graphics console? */
622 GraphicsConsole = DspGraphicalConsole;
623 if (GraphicsConsole)
624 {
625 /* Is it currently active? */
626 if (((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->IsEnabled(GraphicsConsole))
627 {
628 /* Yep -- query it */
629 EfiPrintf(L"GFX active, not supported query\r\n");
630 Status = STATUS_NOT_IMPLEMENTED;
631 //Status = ((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->GetTextCellResolution(GraphicsConsole);
632 }
633 }
634 }
635
636 /* Check if we failed to get it from the graphics console */
637 if (!NT_SUCCESS(Status))
638 {
639 /* Set default text size */
640 *TextWidth = 8;
641 *TextHeight = 8;
642 }
643 }
644
645 NTSTATUS
BlDisplaySetScreenResolution(VOID)646 BlDisplaySetScreenResolution (
647 VOID
648 )
649 {
650 PBL_GRAPHICS_CONSOLE Console;
651 NTSTATUS Status;
652
653 /* Assume success */
654 Status = STATUS_SUCCESS;
655
656 /* Do we have a graphics console? */
657 Console = DspGraphicalConsole;
658 if (Console)
659 {
660 /* Is it currently active? */
661 if (((PBL_GRAPHICS_CONSOLE_VTABLE)Console->TextConsole.Callbacks)->IsEnabled(Console))
662 {
663 /* If so, disable it */
664 return ((PBL_GRAPHICS_CONSOLE_VTABLE)Console->TextConsole.Callbacks)->Enable(Console, FALSE);
665 }
666 }
667
668 /* We should've now fallen back to text mode */
669 if (!DspTextConsole)
670 {
671 /* Then fail, as no display appears active */
672 Status = STATUS_UNSUCCESSFUL;
673 }
674
675 /* Return back to the caller */
676 return Status;
677 }
678
679 NTSTATUS
BlDisplayGetScreenResolution(_Out_ PULONG HRes,_Out_ PULONG VRes)680 BlDisplayGetScreenResolution (
681 _Out_ PULONG HRes,
682 _Out_ PULONG VRes
683 )
684 {
685 NTSTATUS Status;
686 BL_DISPLAY_MODE Resolution;
687 PBL_GRAPHICS_CONSOLE GraphicsConsole;
688
689 /* Assume failure if no consoles are active */
690 Status = STATUS_UNSUCCESSFUL;
691
692 /* Do we have a text console? */
693 if (DspTextConsole)
694 {
695 /* Do we have an active graphics console? */
696 GraphicsConsole = DspGraphicalConsole;
697 if ((GraphicsConsole) &&
698 (((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->IsEnabled(GraphicsConsole)))
699 {
700 /* Get the resolution */
701 Status = ((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->GetGraphicalResolution(GraphicsConsole, &Resolution);
702 if (NT_SUCCESS(Status))
703 {
704 /* Return it back to the caller */
705 *HRes = Resolution.HRes;
706 *VRes = Resolution.VRes;
707 }
708 }
709 else
710 {
711 /* Return defaults */
712 *HRes = 640;
713 *VRes = 200;
714 Status = STATUS_SUCCESS;
715 }
716 }
717
718 /* Return if we got a valid resolution back */
719 return Status;
720 }
721
722 VOID
BlDisplayInvalidateOemBitmap(VOID)723 BlDisplayInvalidateOemBitmap (
724 VOID
725 )
726 {
727 PBGRT_TABLE BgrtTable;
728 NTSTATUS Status;
729
730 /* Search for the BGRT */
731 Status = BlUtlGetAcpiTable((PVOID*)&BgrtTable, BGRT_SIGNATURE);
732 if (NT_SUCCESS(Status))
733 {
734 /* Mark the bitmap as invalid */
735 BgrtTable->Status &= ~BGRT_STATUS_IMAGE_VALID;
736
737 /* Unmap the table */
738 BlMmUnmapVirtualAddressEx(BgrtTable, BgrtTable->Header.Length);
739 }
740 }
741
742 PBITMAP
BlDisplayGetOemBitmap(_In_opt_ PCOORD Offsets,_Out_opt_ PULONG Flags)743 BlDisplayGetOemBitmap (
744 _In_opt_ PCOORD Offsets,
745 _Out_opt_ PULONG Flags
746 )
747 {
748 NTSTATUS Status;
749 ULONG Size;
750 PHYSICAL_ADDRESS PhysicalAddress;
751 PBGRT_TABLE BgrtTable;
752 PBITMAP Bitmap;
753 PBMP_HEADER Header;
754
755 Bitmap = NULL;
756 BgrtTable = NULL;
757
758 /* Search for the BGRT */
759 Status = BlUtlGetAcpiTable((PVOID*)&BgrtTable, BGRT_SIGNATURE);
760 if (!NT_SUCCESS(Status))
761 {
762 goto Quickie;
763 }
764
765 /* Make sure this is really a BGRT */
766 if (BgrtTable->Header.Signature != BGRT_SIGNATURE)
767 {
768 Status = STATUS_ACPI_INVALID_TABLE;
769 goto Quickie;
770 }
771
772 /* Make sure the BGRT table length is valid */
773 if (BgrtTable->Header.Length != sizeof(*BgrtTable))
774 {
775 Status = STATUS_ACPI_INVALID_TABLE;
776 goto Quickie;
777 }
778
779 /* Make sure its a bitmap */
780 if (BgrtTable->ImageType != BgrtImageTypeBitmap)
781 {
782 Status = STATUS_ACPI_INVALID_TABLE;
783 goto Quickie;
784 }
785
786 /* Make sure it's somewhere in RAM */
787 if (!BgrtTable->LogoAddress)
788 {
789 Status = STATUS_ACPI_INVALID_TABLE;
790 goto Quickie;
791 }
792
793 /* Map the bitmap header only for now */
794 PhysicalAddress.QuadPart = BgrtTable->LogoAddress;
795 Status = BlMmMapPhysicalAddressEx((PVOID*)&Header,
796 0,
797 sizeof(BMP_HEADER),
798 PhysicalAddress);
799 if (!NT_SUCCESS(Status))
800 {
801 goto Quickie;
802 }
803
804 /* Capture the real size of the header */
805 Size = Header->Size;
806
807 /* Unmap the bitmap header */
808 BlMmUnmapVirtualAddressEx(BgrtTable, sizeof(BMP_HEADER));
809
810 /* If the real size is smaller than at least a V3 bitmap, bail out */
811 if (Size < sizeof(BITMAP))
812 {
813 Status = STATUS_ACPI_INVALID_TABLE;
814 goto Quickie;
815 }
816
817 /* Map the real size of the header */
818 Status = BlMmMapPhysicalAddressEx((PVOID*)&Bitmap,
819 0,
820 Size,
821 PhysicalAddress);
822 if (!NT_SUCCESS(Status))
823 {
824 goto Quickie;
825 }
826
827 /* Make sure this is a non-compressed 24-bit or 32-bit V3 bitmap */
828 if ((Bitmap->BmpHeader.Signature != 'MB') ||
829 (Bitmap->DibHeader.Compression) ||
830 ((Bitmap->DibHeader.BitCount != 24) &&
831 (Bitmap->DibHeader.BitCount != 32)) ||
832 (Bitmap->DibHeader.Size != sizeof(DIB_HEADER)))
833 {
834 Status = STATUS_ACPI_INVALID_TABLE;
835 goto Quickie;
836 }
837
838 /* Check if caller wants the offsets back */
839 if (Offsets)
840 {
841 /* Give them away */
842 Offsets->X = BgrtTable->OffsetX;
843 Offsets->Y = BgrtTable->OffsetY;
844 }
845
846 /* Check if the caller wants flags */
847 if (Flags)
848 {
849 /* Return if the image is valid */
850 *Flags = BgrtTable->Status & BGRT_STATUS_IMAGE_VALID;
851 }
852
853 Quickie:
854 /* Check if we had mapped the BGRT */
855 if (BgrtTable)
856 {
857 /* Unmap it */
858 BlMmUnmapVirtualAddressEx(BgrtTable, BgrtTable->Header.Length);
859 }
860
861 /* Check if this is the failure path */
862 if (!NT_SUCCESS(Status))
863 {
864 /* Did we have the OEM bitmap mapped? */
865 if (Bitmap)
866 {
867 /* Unmap it */
868 BlMmUnmapVirtualAddressEx(Bitmap, Bitmap->BmpHeader.Size);
869 }
870
871 /* No bitmap to return */
872 Bitmap = NULL;
873 }
874
875 /* Return the bitmap back, if any */
876 return Bitmap;
877 }
878
879 BOOLEAN
BlDisplayValidOemBitmap(VOID)880 BlDisplayValidOemBitmap (
881 VOID
882 )
883 {
884 PBITMAP Bitmap;
885 ULONG HRes, VRes, Height, Width, Flags;
886 COORD Offsets;
887 BOOLEAN Result;
888 NTSTATUS Status;
889
890 /* First check if mobile graphics are enabled */
891 Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
892 BcdLibraryBoolean_MobileGraphics,
893 &Result);
894 if ((NT_SUCCESS(Status)) && (Result))
895 {
896 /* Yes, so use the firmware image */
897 return TRUE;
898 }
899
900 /* Nope, so we'll check the ACPI OEM bitmap */
901 Result = FALSE;
902 Bitmap = BlDisplayGetOemBitmap(&Offsets, &Flags);
903
904 /* Is there one? */
905 if (Bitmap)
906 {
907 /* Is it valid? */
908 if (Flags & BGRT_STATUS_IMAGE_VALID)
909 {
910 /* Get the current screen resolution */
911 Status = BlDisplayGetScreenResolution(&HRes, &VRes);
912 if (NT_SUCCESS(Status))
913 {
914 /* Is there a valid width? */
915 Width = Bitmap->DibHeader.Width;
916 if (Width)
917 {
918 /* Is there a valid height? */
919 Height = Bitmap->DibHeader.Height;
920 if (Height)
921 {
922 /* Will if fit on this screen? */
923 if (((Width + Offsets.X) <= HRes) &&
924 ((Height + Offsets.Y) <= VRes))
925 {
926 /* Then it's all good! */
927 Result = TRUE;
928 }
929 }
930 }
931 }
932 }
933
934 /* Unmap the bitmap for now, it will be drawn later */
935 BlMmUnmapVirtualAddressEx(Bitmap, Bitmap->BmpHeader.Size);
936 }
937
938 /* Return that a valid OEM bitmap exists */
939 return Result;
940 }
941
942 NTSTATUS
BlDisplayClearScreen(VOID)943 BlDisplayClearScreen (
944 VOID
945 )
946 {
947 NTSTATUS Status;
948 PBL_TEXT_CONSOLE TextConsole;
949
950 /* Nothing to do if there's no text console */
951 Status = STATUS_SUCCESS;
952 TextConsole = DspTextConsole;
953 if (TextConsole)
954 {
955 /* Otherwise, clear the whole screen */
956 Status = TextConsole->Callbacks->ClearText(TextConsole, FALSE);
957 if (NT_SUCCESS(Status))
958 {
959 /* Invalidate the OEM bitmap at this point */
960 BlDisplayInvalidateOemBitmap();
961 }
962 }
963
964 /* All done */
965 return Status;
966 };
967
968 NTSTATUS
BlDisplaySetCursorType(_In_ ULONG Type)969 BlDisplaySetCursorType (
970 _In_ ULONG Type
971 )
972 {
973 NTSTATUS Status;
974 PBL_TEXT_CONSOLE TextConsole;
975 BL_DISPLAY_STATE State;
976
977 /* Nothing to do if there's no text console */
978 Status = STATUS_SUCCESS;
979 TextConsole = DspTextConsole;
980 if (TextConsole)
981 {
982 /* Write visibility state and call the function to change it */
983 State.CursorVisible = Type;
984 Status = TextConsole->Callbacks->SetTextState(TextConsole, 8, &State);
985 }
986
987 /* All done */
988 return Status;
989 }
990