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