f83ed12a5163bcd421659c42c9cef3b2aa9bdf73
[reactos.git] / reactos / 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 /* Display re-initialization not yet handled */
280 if (LibraryParameters.LibraryFlags & BL_LIBRARY_FLAG_REINITIALIZE_ALL)
281 {
282 EfiPrintf(L"Display path not handled\r\n");
283 return STATUS_NOT_SUPPORTED;
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 else
344 {
345 /* TEST */
346 RtlFillMemory(GraphicsConsole->FrameBuffer, GraphicsConsole->FrameBufferSize, 0x55);
347 }
348 }
349 }
350
351 /* Are we using something else than the default mode? */
352 if (DisplayMode != &ConsoleGraphicalResolutionList[0])
353 {
354 EfiPrintf(L"Display path not handled\r\n");
355 return STATUS_NOT_SUPPORTED;
356 }
357
358 /* Mask out all the flags now */
359 ConsoleGraphicalResolutionListFlags &= ~(BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG |
360 BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG);
361 }
362
363 /* Do we have a graphics console? */
364 TextConsole = NULL;
365 if (!GraphicsConsole)
366 {
367 /* Nope -- go allocate a text console */
368 TextConsole = BlMmAllocateHeap(sizeof(*TextConsole));
369 if (TextConsole)
370 {
371 /* Construct it */
372 Status = ConsoleTextLocalConstruct(TextConsole, TRUE);
373 if (!NT_SUCCESS(Status))
374 {
375 BlMmFreeHeap(TextConsole);
376 TextConsole = NULL;
377 }
378 }
379 }
380
381 /* Initialize all globals to NULL */
382 DspRemoteInputConsole = NULL;
383 DspTextConsole = NULL;
384 DspGraphicalConsole = NULL;
385
386 /* If we don't have a text console, go get a remote console */
387 RemoteConsole = NULL;
388 if (!TextConsole)
389 {
390 ConsoleCreateRemoteConsole(&RemoteConsole);
391 }
392
393 /* Do we have a remote console? */
394 if (!RemoteConsole)
395 {
396 /* Nope -- what about a graphical one? */
397 if (GraphicsConsole)
398 {
399 /* Yes, use it for both graphics and text */
400 DspGraphicalConsole = GraphicsConsole;
401 DspTextConsole = GraphicsConsole;
402 }
403 else if (TextConsole)
404 {
405 /* Nope, but we have a text console */
406 DspTextConsole = TextConsole;
407 }
408
409 /* Console has been setup */
410 return STATUS_SUCCESS;
411 }
412
413 /* We have a remote console -- have to figure out how to use it*/
414 EfiPrintf(L"Display path not handled\r\n");
415 return STATUS_NOT_SUPPORTED;
416 }
417
418 NTSTATUS
419 DsppReinitialize (
420 _In_ ULONG Flags
421 )
422 {
423 PBL_TEXT_CONSOLE TextConsole;
424 PBL_GRAPHICS_CONSOLE GraphicsConsole;
425 NTSTATUS Status;
426 ULONGLONG GraphicsResolution;
427 BOOLEAN HighestMode;
428 BL_DISPLAY_MODE CurrentResolution;
429
430 /* Do we have local input yet? */
431 if (!DspLocalInputConsole)
432 {
433 /* Create it now */
434 ConsoleCreateLocalInputConsole();
435 }
436
437 /* If a graphics console is present without a remote console... */
438 TextConsole = NULL;
439 if (!(DspRemoteInputConsole) && (DspGraphicalConsole))
440 {
441 /* Try to create a remote console */
442 ConsoleCreateRemoteConsole(&TextConsole);
443 }
444
445 /* All good for now */
446 Status = STATUS_SUCCESS;
447
448 /* Now check if we were able to create the remote console */
449 if (TextConsole)
450 {
451 EfiPrintf(L"EMS not supported\r\n");
452 return STATUS_NOT_IMPLEMENTED;
453 }
454
455 /* Set a local for the right cast */
456 GraphicsConsole = DspGraphicalConsole;
457
458 /* Nothing to do without a graphics console being reinitialized */
459 if (!(Flags & BL_LIBRARY_FLAG_REINITIALIZE_ALL) ||
460 !(GraphicsConsole) ||
461 !(((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->IsEnabled(GraphicsConsole)))
462 {
463 return Status;
464 }
465
466 /* Check if graphics are disabled in the BCD */
467 if (DsppGraphicsDisabledByBcd())
468 {
469 /* Turn off the graphics console, switching back to text mode */
470 Status = ((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->Enable(GraphicsConsole, FALSE);
471 }
472
473 /* Check if a custom graphics resolution is set */
474 if (MiscGetBootOption(BlpApplicationEntry.BcdData,
475 BcdLibraryInteger_GraphicsResolution))
476 {
477 /* Check what it's set to */
478 Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
479 BcdLibraryInteger_GraphicsResolution,
480 &GraphicsResolution);
481 if (!NT_SUCCESS(Status))
482 {
483 return Status;
484 }
485
486 /* Now check our current graphical resolution */
487 Status = ((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->GetGraphicalResolution(GraphicsConsole,
488 &CurrentResolution);
489 if (!NT_SUCCESS(Status))
490 {
491 return Status;
492 }
493
494 /* Remember that we're forcing a video mode */
495 ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG;
496
497 /* Check which resolution to set */
498 if (!GraphicsResolution)
499 {
500 /* 1024x768 */
501 EfiPrintf(L"Display selection not yet handled\r\n");
502 return STATUS_NOT_IMPLEMENTED;
503 }
504 else if (GraphicsResolution == 1)
505 {
506 /* 800x600 */
507 EfiPrintf(L"Display selection not yet handled\r\n");
508 return STATUS_NOT_IMPLEMENTED;
509 }
510 else if (GraphicsResolution == 2)
511 {
512 /* 1024x600 */
513 EfiPrintf(L"Display selection not yet handled\r\n");
514 return STATUS_NOT_IMPLEMENTED;
515 }
516 }
517
518 /* Check if the force highest mode setting is present */
519 if (MiscGetBootOption(BlpApplicationEntry.BcdData,
520 BcdLibraryBoolean_GraphicsForceHighestMode))
521 {
522 /* Check what it's set to */
523 Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
524 BcdLibraryBoolean_GraphicsForceHighestMode,
525 &HighestMode);
526 if ((NT_SUCCESS(Status)) && (HighestMode))
527 {
528 /* Remember that high rest mode is being forced */
529 ConsoleGraphicalResolutionListFlags |= BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG;
530
531 /* Turn it on */
532 //((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->SetGraphicalResolution(GraphicsConsole, 0, 0);
533
534 /* All done now */
535 ConsoleGraphicalResolutionListFlags |= ~BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG;
536 EfiPrintf(L"High res mode not yet handled\r\n");
537 Status = STATUS_NOT_IMPLEMENTED;
538 }
539 }
540
541 /* Return back to the caller */
542 return Status;
543 }
544
545 NTSTATUS
546 BlpDisplayReinitialize (
547 VOID
548 )
549 {
550 NTSTATUS Status;
551 PBL_TEXT_CONSOLE TextConsole;
552 PBL_INPUT_CONSOLE InputConsole;
553
554 /* Do we have a local console? */
555 InputConsole = DspLocalInputConsole;
556 if (InputConsole)
557 {
558 /* Reinitialize it */
559 Status = InputConsole->Callbacks->Reinitialize((PBL_TEXT_CONSOLE)InputConsole);
560 if (!NT_SUCCESS(Status))
561 {
562 return Status;
563 }
564 }
565
566 /* Do we have a text console? */
567 TextConsole = DspTextConsole;
568 if (TextConsole)
569 {
570 /* Reinitialize it */
571 Status = TextConsole->Callbacks->Reinitialize(TextConsole);
572 }
573
574 /* Return status */
575 return Status;
576 }
577
578 NTSTATUS
579 BlpDisplayInitialize (
580 _In_ ULONG Flags
581 )
582 {
583 NTSTATUS Status;
584
585 /* Are we resetting or initializing? */
586 if (Flags & BL_LIBRARY_FLAG_REINITIALIZE)
587 {
588 /* This is a reset */
589 Status = DsppReinitialize(Flags);
590 if (NT_SUCCESS(Status))
591 {
592 /* Re-initialize the class as well */
593 Status = BlpDisplayReinitialize();
594 }
595 }
596 else
597 {
598 /* Initialize the display */
599 Status = DsppInitialize(Flags);
600 }
601
602 /* Return display initialization state */
603 return Status;
604 }
605
606 VOID
607 BlDisplayGetTextCellResolution (
608 _Out_ PULONG TextWidth,
609 _Out_ PULONG TextHeight
610 )
611 {
612 NTSTATUS Status;
613 PBL_GRAPHICS_CONSOLE GraphicsConsole;
614
615 /* If the caller doesn't want anything, bail out */
616 if (!(TextWidth) || !(TextHeight))
617 {
618 return;
619 }
620
621 /* Do we have a text console? */
622 Status = STATUS_UNSUCCESSFUL;
623 if (DspTextConsole)
624 {
625 /* Do we have a graphics console? */
626 GraphicsConsole = DspGraphicalConsole;
627 if (GraphicsConsole)
628 {
629 /* Is it currently active? */
630 if (((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->IsEnabled(GraphicsConsole))
631 {
632 /* Yep -- query it */
633 EfiPrintf(L"GFX active, not supported query\r\n");
634 Status = STATUS_NOT_IMPLEMENTED;
635 //Status = ((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->GetTextCellResolution(GraphicsConsole);
636 }
637 }
638 }
639
640 /* Check if we failed to get it from the graphics console */
641 if (!NT_SUCCESS(Status))
642 {
643 /* Set default text size */
644 *TextWidth = 8;
645 *TextHeight = 8;
646 }
647 }
648
649 NTSTATUS
650 BlDisplaySetScreenResolution (
651 VOID
652 )
653 {
654 PBL_GRAPHICS_CONSOLE Console;
655 NTSTATUS Status;
656
657 /* Assume success */
658 Status = STATUS_SUCCESS;
659
660 /* Do we have a graphics console? */
661 Console = DspGraphicalConsole;
662 if (Console)
663 {
664 /* Is it currently active? */
665 if (((PBL_GRAPHICS_CONSOLE_VTABLE)Console->TextConsole.Callbacks)->IsEnabled(Console))
666 {
667 /* If so, disable it */
668 return ((PBL_GRAPHICS_CONSOLE_VTABLE)Console->TextConsole.Callbacks)->Enable(Console, FALSE);
669 }
670 }
671
672 /* We should've now fallen back to text mode */
673 if (!DspTextConsole)
674 {
675 /* Then fail, as no display appears active */
676 Status = STATUS_UNSUCCESSFUL;
677 }
678
679 /* Return back to the caller */
680 return Status;
681 }
682
683 NTSTATUS
684 BlDisplayGetScreenResolution (
685 _Out_ PULONG HRes,
686 _Out_ PULONG VRes
687 )
688 {
689 NTSTATUS Status;
690 BL_DISPLAY_MODE Resolution;
691 PBL_GRAPHICS_CONSOLE GraphicsConsole;
692
693 /* Assume failure if no consoles are active */
694 Status = STATUS_UNSUCCESSFUL;
695
696 /* Do we have a text console? */
697 if (DspTextConsole)
698 {
699 /* Do we have an active graphics console? */
700 GraphicsConsole = DspGraphicalConsole;
701 if ((GraphicsConsole) &&
702 (((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->IsEnabled(GraphicsConsole)))
703 {
704 /* Get the resolution */
705 Status = ((PBL_GRAPHICS_CONSOLE_VTABLE)GraphicsConsole->TextConsole.Callbacks)->GetGraphicalResolution(GraphicsConsole, &Resolution);
706 if (NT_SUCCESS(Status))
707 {
708 /* Return it back to the caller */
709 *HRes = Resolution.HRes;
710 *VRes = Resolution.VRes;
711 }
712 }
713 else
714 {
715 /* Return defaults */
716 *HRes = 640;
717 *VRes = 200;
718 Status = STATUS_SUCCESS;
719 }
720 }
721
722 /* Return if we got a valid resolution back */
723 return Status;
724 }
725
726 VOID
727 BlDisplayInvalidateOemBitmap (
728 VOID
729 )
730 {
731 PBGRT_TABLE BgrtTable;
732 NTSTATUS Status;
733
734 /* Search for the BGRT */
735 Status = BlUtlGetAcpiTable((PVOID*)&BgrtTable, BGRT_SIGNATURE);
736 if (NT_SUCCESS(Status))
737 {
738 /* Mark the bitmap as invalid */
739 BgrtTable->Status &= BGRT_STATUS_IMAGE_VALID;
740
741 /* Unmap the table */
742 BlMmUnmapVirtualAddressEx(BgrtTable, BgrtTable->Header.Length);
743 }
744 }
745
746 PBITMAP
747 BlDisplayGetOemBitmap (
748 _In_opt_ PCOORD Offsets,
749 _Out_opt_ PULONG Flags
750 )
751 {
752 NTSTATUS Status;
753 ULONG Size;
754 PHYSICAL_ADDRESS PhysicalAddress;
755 PBGRT_TABLE BgrtTable;
756 PBITMAP Bitmap;
757 PBMP_HEADER Header;
758
759 Bitmap = NULL;
760 BgrtTable = NULL;
761
762 /* Search for the BGRT */
763 Status = BlUtlGetAcpiTable((PVOID*)&BgrtTable, BGRT_SIGNATURE);
764 if (!NT_SUCCESS(Status))
765 {
766 EfiPrintf(L"no BGRT found\r\n");
767 goto Quickie;
768 }
769
770 /* Make sure this is really a BGRT */
771 if (BgrtTable->Header.Signature != BGRT_SIGNATURE)
772 {
773 Status = STATUS_ACPI_INVALID_TABLE;
774 goto Quickie;
775 }
776
777 /* Make sure the BGRT table length is valid */
778 if (BgrtTable->Header.Length != sizeof(*BgrtTable))
779 {
780 Status = STATUS_ACPI_INVALID_TABLE;
781 goto Quickie;
782 }
783
784 /* Make sure its a bitmap */
785 if (BgrtTable->ImageType != BgrtImageTypeBitmap)
786 {
787 Status = STATUS_ACPI_INVALID_TABLE;
788 goto Quickie;
789 }
790
791 /* Make sure it's somewhere in RAM */
792 if (!BgrtTable->LogoAddress)
793 {
794 Status = STATUS_ACPI_INVALID_TABLE;
795 goto Quickie;
796 }
797
798 /* Map the bitmap header only for now */
799 PhysicalAddress.QuadPart = BgrtTable->LogoAddress;
800 Status = BlMmMapPhysicalAddressEx((PVOID*)&Header,
801 0,
802 sizeof(BMP_HEADER),
803 PhysicalAddress);
804 if (!NT_SUCCESS(Status))
805 {
806 goto Quickie;
807 }
808
809 /* Capture the real size of the header */
810 Size = Header->Size;
811
812 /* Unmap the bitmap header */
813 BlMmUnmapVirtualAddressEx(BgrtTable, sizeof(BMP_HEADER));
814
815 /* If the real size is smaller than at least a V3 bitmap, bail out */
816 if (Size < sizeof(BITMAP))
817 {
818 Status = STATUS_ACPI_INVALID_TABLE;
819 goto Quickie;
820 }
821
822 /* Map the real size of the header */
823 Status = BlMmMapPhysicalAddressEx((PVOID*)&Bitmap,
824 0,
825 Size,
826 PhysicalAddress);
827 if (!NT_SUCCESS(Status))
828 {
829 goto Quickie;
830 }
831
832 /* Make sure this is a non-compressed 24-bit or 32-bit V3 bitmap */
833 if ((Bitmap->BmpHeader.Signature != 'MB') ||
834 (Bitmap->DibHeader.Compression) ||
835 ((Bitmap->DibHeader.BitCount != 24) &&
836 (Bitmap->DibHeader.BitCount != 32)) ||
837 (Bitmap->DibHeader.Size != sizeof(BITMAP)))
838 {
839 Status = STATUS_ACPI_INVALID_TABLE;
840 goto Quickie;
841 }
842
843 /* Check if caller wants the offsets back */
844 if (Offsets)
845 {
846 /* Give them away */
847 Offsets->X = BgrtTable->OffsetX;
848 Offsets->Y = BgrtTable->OffsetY;
849 }
850
851 /* Check if the caller wants flags */
852 if (Flags)
853 {
854 /* Return if the image is valid */
855 *Flags = BgrtTable->Status & BGRT_STATUS_IMAGE_VALID;
856 }
857
858 Quickie:
859 /* Check if we had mapped the BGRT */
860 if (BgrtTable)
861 {
862 /* Unmap it */
863 BlMmUnmapVirtualAddressEx(BgrtTable, BgrtTable->Header.Length);
864 }
865
866 /* Check if this is the failure path */
867 if (!NT_SUCCESS(Status))
868 {
869 /* Did we have the OEM bitmap mapped? */
870 if (Bitmap)
871 {
872 /* Unmap it */
873 BlMmUnmapVirtualAddressEx(Bitmap, Bitmap->BmpHeader.Size);
874 }
875
876 /* No bitmap to return */
877 Bitmap = NULL;
878 }
879
880 /* Return the bitmap back, if any */
881 return Bitmap;
882 }
883
884 BOOLEAN
885 BlDisplayValidOemBitmap (
886 VOID
887 )
888 {
889 PBITMAP Bitmap;
890 ULONG HRes, VRes, Height, Width, Flags;
891 COORD Offsets;
892 BOOLEAN Result;
893 NTSTATUS Status;
894
895 /* First check if mobile graphics are enabled */
896 Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
897 BcdLibraryBoolean_MobileGraphics,
898 &Result);
899 if ((NT_SUCCESS(Status)) && (Result))
900 {
901 /* Yes, so use the firmware image */
902 return TRUE;
903 }
904
905 /* Nope, so we'll check the ACPI OEM bitmap */
906 Result = FALSE;
907 Bitmap = BlDisplayGetOemBitmap(&Offsets, &Flags);
908
909 /* Is there one? */
910 if (Bitmap)
911 {
912 /* Is it valid? */
913 if (Flags & BGRT_STATUS_IMAGE_VALID)
914 {
915 /* Get the current screen resolution */
916 Status = BlDisplayGetScreenResolution(&HRes, &VRes);
917 if (NT_SUCCESS(Status))
918 {
919 /* Is there a valid width? */
920 Width = Bitmap->DibHeader.Width;
921 if (Width)
922 {
923 /* Is there a valid height? */
924 Height = Bitmap->DibHeader.Height;
925 if (Height)
926 {
927 /* Will if fit on this screen? */
928 if (((Width + Offsets.X) <= HRes) &&
929 ((Height + Offsets.Y) <= VRes))
930 {
931 /* Then it's all good! */
932 Result = TRUE;
933 }
934 }
935 }
936 }
937 }
938
939 /* Unmap the bitmap for now, it will be drawn later */
940 BlMmUnmapVirtualAddressEx(Bitmap, Bitmap->BmpHeader.Size);
941 }
942
943 /* Return that a valid OEM bitmap exists */
944 return Result;
945 }
946
947 NTSTATUS
948 BlDisplayClearScreen (
949 VOID
950 )
951 {
952 NTSTATUS Status;
953 PBL_TEXT_CONSOLE TextConsole;
954
955 /* Nothing to do if there's no text console */
956 Status = STATUS_SUCCESS;
957 TextConsole = DspTextConsole;
958 if (TextConsole)
959 {
960 /* Otherwise, clear the whole screen */
961 Status = TextConsole->Callbacks->ClearText(TextConsole, FALSE);
962 if (NT_SUCCESS(Status))
963 {
964 /* Invalidate the OEM bitmap at this point */
965 BlDisplayInvalidateOemBitmap();
966 }
967 }
968
969 /* All done */
970 return Status;
971 };
972
973 NTSTATUS
974 BlDisplaySetCursorType (
975 _In_ ULONG Type
976 )
977 {
978 NTSTATUS Status;
979 PBL_TEXT_CONSOLE TextConsole;
980 BL_DISPLAY_STATE State;
981
982 /* Nothing to do if there's no text console */
983 Status = STATUS_SUCCESS;
984 TextConsole = DspTextConsole;
985 if (TextConsole)
986 {
987 /* Write visibility state and call the function to change it */
988 State.CursorVisible = Type;
989 Status = TextConsole->Callbacks->SetTextState(TextConsole, 8, &State);
990 }
991
992 /* All done */
993 return Status;
994 }