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