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