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 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 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 = 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 ((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 } 989