[BOOTLIB]: ACPI support (RSDP, XSDT/RSDT and arbitrary table lookup + mapping)
authorAlex Ionescu <aionescu@gmail.com>
Thu, 7 Jan 2016 23:43:15 +0000 (23:43 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Thu, 7 Jan 2016 23:43:15 +0000 (23:43 +0000)
[BOOTLIB]: Additional text and graphics console support. Among other things, we have now gained the ability to fill a buffer with a particular color.
[BOOTLIB]: OEM Bitmap (ACPI 5!) support.
[BOOTMGR]: Continue making a few more initialization calls now that bootlib supports more functionality.

svn path=/trunk/; revision=70539

14 files changed:
reactos/boot/environ/app/bootmgr/bootmgr.c
reactos/boot/environ/include/bcd.h
reactos/boot/environ/include/bl.h
reactos/boot/environ/include/efi/Acpi.h [new file with mode: 0644]
reactos/boot/environ/lib/firmware/efi/firmware.c
reactos/boot/environ/lib/io/display/display.c
reactos/boot/environ/lib/io/display/efi/gop.c
reactos/boot/environ/lib/io/display/efi/guicons.c
reactos/boot/environ/lib/io/display/efi/textcons.c
reactos/boot/environ/lib/io/display/guicons.c
reactos/boot/environ/lib/io/display/textcons.c
reactos/boot/environ/lib/misc/font.c
reactos/boot/environ/lib/misc/resource.c
reactos/boot/environ/lib/misc/util.c

index 3f6e628..1b75729 100644 (file)
@@ -1032,6 +1032,66 @@ BmFwMemoryInitialize (
     }
 }
 
+NTSTATUS
+BmpBgDisplayClearScreen (
+    _In_ ULONG Color
+    )
+{
+    /* Not yet supported */
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BlXmiInitialize (
+    _In_ PWCHAR Stylesheet
+    )
+{
+    /* Reset the cursor type */
+    BlDisplaySetCursorType(0);
+
+    /* Nope, not doing any XML stuff */
+    return STATUS_SUCCESS;
+}
+
+VOID
+BlImgQueryCodeIntegrityBootOptions (
+    _In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry,
+    _Out_ PBOOLEAN IntegrityChecksDisabled, 
+    _Out_ PBOOLEAN TestSigningEnabled
+    )
+{
+    
+    NTSTATUS Status;
+    BOOLEAN Value;
+
+    /* Check if /DISABLEINTEGRITYCHECKS is on */
+    Status = BlGetBootOptionBoolean(ApplicationEntry->BcdData,
+                                    BcdLibraryBoolean_DisableIntegrityChecks,
+                                    &Value);
+    *IntegrityChecksDisabled = NT_SUCCESS(Status) && (Value);
+
+    /* Check if /TESTSIGNING is on */
+    Status = BlGetBootOptionBoolean(ApplicationEntry->BcdData,
+                                    BcdLibraryBoolean_AllowPrereleaseSignatures,
+                                    &Value);
+    *TestSigningEnabled = NT_SUCCESS(Status) && (Value);
+}
+
+NTSTATUS
+BmFwVerifySelfIntegrity (
+    VOID
+    )
+{
+    EfiPrintf(L"Device Type %d Local Type %d\r\n", BlpBootDevice->DeviceType, BlpBootDevice->Local.Type);
+    if ((BlpBootDevice->DeviceType == LocalDevice) &&
+        (BlpBootDevice->Local.Type == CdRomDevice) &&
+        (BlpApplicationFlags & BL_APPLICATION_ENTRY_FLAG_NO_GUID))
+    {
+        return STATUS_SUCCESS;
+    }
+
+    return 0xC0000428;
+}
 
 /*++
  * @name BmMain
@@ -1059,6 +1119,7 @@ BmMain (
     HANDLE BcdHandle;
     PBL_BCD_OPTION EarlyOptions;
     PWCHAR Stylesheet;
+    BOOLEAN XmlLoaded, DisableIntegrity, TestSigning;
 
     EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\n");
 
@@ -1166,23 +1227,66 @@ BmMain (
         goto Quickie;
     }
 
+    /* Initialize the XML Engine (as a side-effect, resets cursor) */
+    Status = BlXmiInitialize(Stylesheet);
+    if (!NT_SUCCESS(Status))
+    {
+        EfiPrintf(L"\r\nBlXmiInitialize failed 0x%x\r\n", Status);
+        goto Failure;
+    }
+    XmlLoaded = TRUE;
+
+    /* Check if there's an active bitmap visible */
+    if (!BlDisplayValidOemBitmap())
+    {
+        /* Nope, make the screen black using BGFX */
+        if (!NT_SUCCESS(BmpBgDisplayClearScreen(0xFF000000)))
+        {
+            /* BGFX isn't active, use standard display */
+            BlDisplayClearScreen();
+        }
+    }
+
+#ifdef _BIT_LOCKER_
+    /* Bitlocker will take over screen UI if enabled */
+    FveDisplayScreen = BmFveDisplayScreen;
+#endif
+
+    /* Check if any bypass options are enabled */
+    BlImgQueryCodeIntegrityBootOptions(&BlpApplicationEntry,
+                                        &DisableIntegrity,
+                                        &TestSigning);
+    if (!DisableIntegrity)
+    {
+        /* Integrity checks are enabled, so validate our signature */
+        Status = BmFwVerifySelfIntegrity();
+        if (!NT_SUCCESS(Status))
+        {
+            /* Signature invalid, fail boot */
+           // goto Failure;
+        }
+    }
+
+//        BlXmiWrite(L"<bootmgr/>");
+
+    //BlSecureBootCheckForFactoryReset();
+
+
     /* do more stuff!! */
     EfiPrintf(BlResourceFindMessage(BM_MSG_TEST));
-    //EfiPrintf(Stylesheet);
+    EfiPrintf(Stylesheet);
     EfiStall(10000000);
 
-//Failure:
+Failure:
     /* Check if we got here due to an internal error */
     if (BmpInternalBootError)
     {
         /* If XML is available, display the error */
-#if 0
         if (XmlLoaded)
         {
-            BmDisplayDumpError(0, 0);
-            BmErrorPurge();
+            //BmDisplayDumpError(0, 0);
+            //BmErrorPurge();
         }
-#endif
 
         /* Don't do a fatal error -- return back to firmware */
         goto Quickie;
index a843911..f00133c 100644 (file)
@@ -79,7 +79,8 @@ typedef enum BcdLibraryElementTypes
     BcdLibraryBoolean_BootUxDisable = 0x1600006C,
     BcdLibraryBoolean_BootShutdownDisabled = 0x16000074,
     BcdLibraryIntegerList_AllowedInMemorySettings = 0x17000077,
-    BcdLibraryBoolean_ForceFipsCrypto = 0x16000079
+    BcdLibraryBoolean_ForceFipsCrypto = 0x16000079,
+    BcdLibraryBoolean_MobileGraphics = 0x1600007A /* Undocumented */
 } BcdLibraryElementTypes;
 
 typedef enum BcdOSLoaderElementTypes
index f2d69de..c78683e 100644 (file)
@@ -28,6 +28,9 @@
 /* PE Headers */
 #include <ntimage.h>
 
+/* ACPI Headers */
+#include <drivers/acpi/acpi.h>
+
 /* UEFI Headers */
 #include <Uefi.h>
 #include <DevicePath.h>
@@ -35,6 +38,7 @@
 #include <GraphicsOutput.h>
 #include <UgaDraw.h>
 #include <BlockIo.h>
+#include <Acpi.h>
 
 /* Registry Headers */
 #define __FREELDR_H
@@ -445,7 +449,7 @@ typedef
 NTSTATUS
 (*PCONSOLE_CLEAR_TEXT) (
     _In_ struct _BL_TEXT_CONSOLE* Console,
-    _In_ ULONG Attribute
+    _In_ BOOLEAN LineOnly
     );
 
 typedef
@@ -1097,7 +1101,45 @@ typedef struct _BL_DEFERRED_FONT_FILE
     ULONG Flags;
     PBL_DEVICE_DESCRIPTOR Device;
     PWCHAR FontPath;
-} BL_DEFERRED_FONT_FILE, *PBL_DEFERRED_FONT_FILE;;
+} BL_DEFERRED_FONT_FILE, *PBL_DEFERRED_FONT_FILE;
+
+#pragma pack(push)
+#pragma pack(1)
+typedef struct _BMP_HEADER
+{
+    USHORT Signature;
+    ULONG Size;
+    USHORT Reserved[2];
+    ULONG Offset;
+} BMP_HEADER, *PBMP_HEADER;
+
+typedef struct _DIB_HEADER
+{
+    ULONG Size;
+    ULONG Width;
+    ULONG Height;
+    USHORT Planes;
+    USHORT BitCount;
+    ULONG Compression;
+    ULONG SizeImage;
+    ULONG XPelsPerMeter;
+    ULONG YPelsPerMEter;
+    ULONG ClrUsed;
+    ULONG ClrImportant;
+} DIB_HEADER, *PDIB_HEADER;
+
+typedef struct _BITMAP
+{
+    BMP_HEADER BmpHeader;
+    DIB_HEADER DibHeader;
+} BITMAP, *PBITMAP;
+#pragma pack(pop)
+
+typedef struct _COORD
+{
+    ULONG X;
+    ULONG Y;
+} COORD, *PCOORD;
 
 /* INLINE ROUTINES ***********************************************************/
 
@@ -1252,6 +1294,12 @@ EfiConInReset (
     VOID
     );
 
+NTSTATUS
+EfiConOutOutputString (
+    _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
+    _In_ PWCHAR String
+    );
+
 NTSTATUS
 EfiConOutQueryMode (
     _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
@@ -1348,6 +1396,11 @@ EfiIsDevicePathParent (
     _In_ EFI_DEVICE_PATH *DevicePath2
     );
 
+NTSTATUS
+EfipGetRsdt (
+    _Out_ PPHYSICAL_ADDRESS FoundRsdt
+    );
+
 /* PLATFORM TIMER ROUTINES ***************************************************/
 
 NTSTATUS
@@ -1380,6 +1433,16 @@ BfLoadDeferredFontFiles (
     VOID
     );
 
+NTSTATUS
+BfClearScreen  (
+    _In_ PBL_GRAPHICS_CONSOLE Console
+    );
+
+NTSTATUS
+BfClearToEndOfLine (
+    _In_ PBL_GRAPHICS_CONSOLE Console
+    );
+
 /* FILESYSTEM ROUTINES *******************************************************/
 
 NTSTATUS
@@ -1444,6 +1507,12 @@ BlUtlUpdateProgress (
     _Out_opt_ PBOOLEAN Completed
     );
 
+NTSTATUS
+BlUtlGetAcpiTable (
+    _Out_ PVOID* TableAddress,
+    _In_ ULONG Signature
+    );
+
 EFI_STATUS
 EfiGetEfiStatusCode(
     _In_ NTSTATUS Status
@@ -1845,6 +1914,32 @@ BlDisplayGetScreenResolution (
     _Out_ PULONG Vres
     );
 
+VOID
+BlDisplayInvalidateOemBitmap (
+    VOID
+    );
+
+PBITMAP
+BlDisplayGetOemBitmap (
+    _Out_ PCOORD Offset, 
+    _Out_opt_ PULONG Flags
+    );
+
+BOOLEAN
+BlDisplayValidOemBitmap (
+    VOID
+    );
+
+NTSTATUS
+BlDisplayClearScreen (
+    VOID
+    );
+
+NTSTATUS
+BlDisplaySetCursorType (
+    _In_ ULONG Type
+    );
+
 /* I/O ROUTINES **************************************************************/
 
 NTSTATUS
@@ -1962,11 +2057,30 @@ ConsoleGraphicalDestruct (
     _In_ struct _BL_GRAPHICS_CONSOLE* Console
     );
 
+NTSTATUS
+ConsoleGraphicalClearText (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ BOOLEAN LineOnly
+    );
+
+NTSTATUS
+ConsoleGraphicalClearPixels  (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ ULONG Color
+    );
+
 NTSTATUS
 ConsoleGraphicalReinitialize (
     _In_ struct _BL_GRAPHICS_CONSOLE* Console
     );
 
+NTSTATUS
+ConsoleGraphicalSetTextState (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ ULONG Mask,
+    _In_ PBL_DISPLAY_STATE TextState
+    );
+
 BOOLEAN
 ConsoleGraphicalIsEnabled (
     _In_ struct _BL_GRAPHICS_CONSOLE* Console
@@ -2029,7 +2143,7 @@ ConsoleTextLocalSetTextResolution (
 NTSTATUS
 ConsoleTextLocalClearText (
     _In_ struct _BL_TEXT_CONSOLE* Console,
-    _In_ ULONG Attribute
+    _In_ BOOLEAN LineOnly
     );
 
 NTSTATUS
@@ -2052,6 +2166,12 @@ ConsolepFindResolution (
     _In_ ULONG MaxIndex
     );
 
+NTSTATUS
+ConsoleFirmwareTextClear (
+    _In_ PBL_TEXT_CONSOLE Console,
+    _In_ BOOLEAN LineOnly
+    );
+
 VOID
 ConsoleFirmwareTextClose (
     _In_ PBL_TEXT_CONSOLE TextConsole
@@ -2095,6 +2215,12 @@ ConsoleFirmwareGraphicalDisable (
     _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole
     );
 
+NTSTATUS
+ConsoleFirmwareGraphicalClear (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ ULONG Color
+    );
+
 NTSTATUS
 ConsoleFirmwareGraphicalEnable (
     _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole
@@ -2143,6 +2269,22 @@ ConsoleInputLocalEraseBuffer (
     _In_opt_ PULONG ValueToFill
     );
 
+VOID
+ConsolepClearBuffer (
+    _In_ PUCHAR FrameBuffer,
+    _In_ ULONG Width,
+    _In_ PUCHAR FillColor,
+    _In_ ULONG Height,
+    _In_ ULONG ScanlineWidth,
+    _In_ ULONG PixelDepth
+    );
+    
+NTSTATUS
+ConsolepConvertColorToPixel (
+    _In_ BL_COLOR Color,
+    _Out_ PUCHAR Pixel
+    );
+
 extern ULONG MmDescriptorCallTreeCount;
 extern ULONG BlpApplicationFlags;
 extern BL_LIBRARY_PARAMETERS BlpLibraryParameters;
@@ -2158,6 +2300,8 @@ extern EFI_GUID EfiLoadedImageProtocol;
 extern EFI_GUID EfiDevicePathProtocol;
 extern EFI_GUID EfiBlockIoProtocol;
 extern EFI_GUID EfiSimpleTextInputExProtocol;
+extern EFI_GUID EfiRootAcpiTableGuid;
+extern EFI_GUID EfiRootAcpiTable10Guid;
 extern ULONG ConsoleGraphicalResolutionListFlags;
 extern BL_DISPLAY_MODE ConsoleGraphicalResolutionList[];
 extern BL_DISPLAY_MODE ConsoleTextResolutionList[];
diff --git a/reactos/boot/environ/include/efi/Acpi.h b/reactos/boot/environ/include/efi/Acpi.h
new file mode 100644 (file)
index 0000000..3897ae6
--- /dev/null
@@ -0,0 +1,46 @@
+/** @file
+  GUIDs used for ACPI entries in the EFI system table
+
+  These GUIDs point the ACPI tables as defined in the ACPI specifications.
+  ACPI 2.0 specification defines the ACPI 2.0 GUID. UEFI 2.0 defines the 
+  ACPI 2.0 Table GUID and ACPI Table GUID.
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials                          
+  are licensed and made available under the terms and conditions of the BSD License         
+  which accompanies this distribution.  The full text of the license may be found at        
+  http://opensource.org/licenses/bsd-license.php                                            
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+  @par Revision Reference:
+  GUIDs defined in UEFI 2.0 spec.
+
+**/
+
+#ifndef __ACPI_GUID_H__
+#define __ACPI_GUID_H__
+
+#define ACPI_TABLE_GUID \
+  { \
+    0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+  }
+
+#define EFI_ACPI_TABLE_GUID \
+  { \
+    0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
+  }
+
+#define ACPI_10_TABLE_GUID     ACPI_TABLE_GUID
+
+//
+// ACPI 2.0 or newer tables should use EFI_ACPI_TABLE_GUID.
+//
+#define EFI_ACPI_20_TABLE_GUID EFI_ACPI_TABLE_GUID
+
+extern EFI_GUID gEfiAcpiTableGuid;
+extern EFI_GUID gEfiAcpi10TableGuid;
+extern EFI_GUID gEfiAcpi20TableGuid;
+
+#endif
index 3ec3fdf..63cf44f 100644 (file)
@@ -23,6 +23,7 @@ EFI_RUNTIME_SERVICES *EfiRT;
 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *EfiConOut;
 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *EfiConIn;
 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx;
+PHYSICAL_ADDRESS EfiRsdt;
 
 EFI_GUID EfiGraphicsOutputProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
 EFI_GUID EfiUgaDrawProtocol = EFI_UGA_DRAW_PROTOCOL_GUID;
@@ -30,6 +31,8 @@ EFI_GUID EfiLoadedImageProtocol = EFI_LOADED_IMAGE_PROTOCOL_GUID;
 EFI_GUID EfiDevicePathProtocol = EFI_DEVICE_PATH_PROTOCOL_GUID;
 EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
 EFI_GUID EfiBlockIoProtocol = EFI_BLOCK_IO_PROTOCOL_GUID;
+EFI_GUID EfiRootAcpiTableGuid = EFI_ACPI_20_TABLE_GUID;
+EFI_GUID EfiRootAcpiTable10Guid = EFI_ACPI_TABLE_GUID;
 
 WCHAR BlScratchBuffer[8192];
 
@@ -624,6 +627,37 @@ EfiConOutEnableCursor (
     return EfiGetNtStatusCode(EfiStatus);
 }
 
+NTSTATUS
+EfiConOutOutputString (
+    _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
+    _In_ PWCHAR String
+    )
+{
+    BL_ARCH_MODE OldMode;
+    EFI_STATUS EfiStatus;
+
+    /* Are we in protected mode? */
+    OldMode = CurrentExecutionContext->Mode;
+    if (OldMode != BlRealMode)
+    {
+        /* FIXME: Not yet implemented */
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    /* Make the EFI call */
+    EfiStatus = TextInterface->OutputString(TextInterface, String);
+
+    /* Switch back to protected mode if we came from there */
+    if (OldMode != BlRealMode)
+    {
+        BlpArchSwitchContext(OldMode);
+    }
+
+    /* Convert the error to an NTSTATUS */
+    return EfiGetNtStatusCode(EfiStatus);
+}
+
+
 VOID
 EfiConOutReadCurrentMode (
     _In_ SIMPLE_TEXT_OUTPUT_INTERFACE *TextInterface,
@@ -881,6 +915,129 @@ EfiAllocatePages (
     return EfiGetNtStatusCode(EfiStatus);
 }
 
+NTSTATUS
+EfipGetSystemTable (
+    _In_ EFI_GUID *TableGuid,
+    _Out_ PPHYSICAL_ADDRESS TableAddress
+    )
+{
+    ULONG i;
+    NTSTATUS Status;
+
+    /* Assume failure */
+    Status = STATUS_NOT_FOUND;
+
+    /* Loop through the configuration tables */
+    for (i = 0; i < EfiST->NumberOfTableEntries; i++)
+    {
+        /* Check if this one matches the one we want */
+        if (RtlEqualMemory(&EfiST->ConfigurationTable[i].VendorGuid,
+                           TableGuid,
+                           sizeof(*TableGuid)))
+        {
+            /* Return its address */
+            TableAddress->QuadPart = (ULONG_PTR)EfiST->ConfigurationTable[i].VendorTable;
+            Status = STATUS_SUCCESS;
+            break;
+        }
+    }
+
+    /* Return the search result */
+    return Status;
+}
+
+NTSTATUS
+EfipGetRsdt (
+    _Out_ PPHYSICAL_ADDRESS FoundRsdt
+    )
+{
+    NTSTATUS Status;
+    ULONG Length;
+    PHYSICAL_ADDRESS RsdpAddress, Rsdt;
+    PRSDP Rsdp;
+
+    /* Assume failure */
+    Length = 0;
+    Rsdp = NULL;
+
+    /* Check if we already know it */
+    if (EfiRsdt.QuadPart)
+    {
+        /* Return it */
+        *FoundRsdt = EfiRsdt;
+        return STATUS_SUCCESS;
+    }
+
+    /* Otherwise, look for the ACPI 2.0 RSDP (XSDT really) */
+    Status = EfipGetSystemTable(&EfiRootAcpiTableGuid, &RsdpAddress);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Didn't fint it, look for the ACPI 1.0 RSDP (RSDT really) */
+        Status = EfipGetSystemTable(&EfiRootAcpiTable10Guid, &RsdpAddress);
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+    }
+
+    /* Map it */
+    Length = sizeof(*Rsdp);
+    Status = BlMmMapPhysicalAddressEx((PVOID*)&Rsdp,
+                                      0,
+                                      Length,
+                                      RsdpAddress);
+    if (NT_SUCCESS(Status))
+    {
+        /* Check the revision (anything >= 2.0 is XSDT) */
+        if (Rsdp->Revision)
+        {
+            /* Check if the table is bigger than just its header */
+            if (Rsdp->Length > Length)
+            {
+                /* Capture the real length */
+                Length = Rsdp->Length;
+
+                /* Unmap our header mapping */
+                BlMmUnmapVirtualAddressEx(Rsdp, sizeof(*Rsdp));
+
+                /* And map the whole thing now */
+                Status = BlMmMapPhysicalAddressEx((PVOID*)&Rsdp,
+                                                  0,
+                                                  Length,
+                                                  RsdpAddress);
+                if (!NT_SUCCESS(Status))
+                {
+                    return Status;
+                }
+            }
+
+            /* Read the XSDT address from the table*/
+            Rsdt = Rsdp->XsdtAddress;
+        }
+        else
+        {
+            /* ACPI 1.0 so just read the RSDT */
+            Rsdt.QuadPart = Rsdp->RsdtAddress;
+        }
+
+        /* Save it for later */
+        EfiRsdt = Rsdt;
+
+        /* And return it back */
+        *FoundRsdt = Rsdt;
+    }
+
+    /* Check if we had mapped the RSDP */
+    if (Rsdp)
+    {
+        /* Unmap it */
+        BlMmUnmapVirtualAddressEx(Rsdp, Length);
+    }
+
+    /* Return search result back to caller */
+    return Status;
+}
+
 BL_MEMORY_ATTR
 MmFwpGetOsAttributeType (
     _In_ ULONGLONG Attribute
index 78611a6..d7d5b24 100644 (file)
@@ -723,3 +723,273 @@ BlDisplayGetScreenResolution (
     /* Return if we got a valid resolution back */
     return Status;
 }
+
+VOID
+BlDisplayInvalidateOemBitmap (
+    VOID
+    )
+{
+    PBGRT_TABLE BgrtTable;
+    NTSTATUS Status;
+
+    /* Search for the BGRT */
+    Status = BlUtlGetAcpiTable((PVOID*)&BgrtTable, BGRT_SIGNATURE);
+    if (NT_SUCCESS(Status))
+    {
+        /* Mark the bitmap as invalid */
+        BgrtTable->Status &= BGRT_STATUS_IMAGE_VALID;
+
+        /* Unmap the table */
+        BlMmUnmapVirtualAddressEx(BgrtTable, BgrtTable->Header.Length);
+    }
+}
+
+PBITMAP
+BlDisplayGetOemBitmap (
+    _In_opt_ PCOORD Offsets,
+    _Out_opt_ PULONG Flags
+    )
+{
+    NTSTATUS Status;
+    ULONG Size;
+    PHYSICAL_ADDRESS PhysicalAddress;
+    PBGRT_TABLE BgrtTable;
+    PBITMAP Bitmap;
+    PBMP_HEADER Header;
+
+    Bitmap = NULL;
+    BgrtTable = NULL;
+
+    /* Search for the BGRT */
+    Status = BlUtlGetAcpiTable((PVOID*)&BgrtTable, BGRT_SIGNATURE);
+    if (!NT_SUCCESS(Status))
+    {
+        EfiPrintf(L"no BGRT found\r\n");
+        goto Quickie;
+    }
+
+    /* Make sure this is really a BGRT */
+    if (BgrtTable->Header.Signature != BGRT_SIGNATURE)
+    {
+        Status = STATUS_ACPI_INVALID_TABLE;
+        goto Quickie;
+    }
+
+    /* Make sure the BGRT table length is valid */
+    if (BgrtTable->Header.Length != sizeof(*BgrtTable))
+    {
+        Status = STATUS_ACPI_INVALID_TABLE;
+        goto Quickie;
+    }
+
+    /* Make sure its a bitmap */
+    if (BgrtTable->ImageType != BgrtImageTypeBitmap)
+    {
+        Status = STATUS_ACPI_INVALID_TABLE;
+        goto Quickie;
+    }
+
+    /* Make sure it's somewhere in RAM */
+    if (!BgrtTable->LogoAddress)
+    {
+        Status = STATUS_ACPI_INVALID_TABLE;
+        goto Quickie;
+    }
+
+    /* Map the bitmap header only for now */
+    PhysicalAddress.QuadPart = BgrtTable->LogoAddress;
+    Status = BlMmMapPhysicalAddressEx((PVOID*)&Header,
+                                      0,
+                                      sizeof(BMP_HEADER),
+                                      PhysicalAddress);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quickie;
+    }
+
+    /* Capture the real size of the header */
+    Size = Header->Size;
+
+    /* Unmap the bitmap header */
+    BlMmUnmapVirtualAddressEx(BgrtTable, sizeof(BMP_HEADER));
+
+    /* If the real size is smaller than at least a V3 bitmap, bail out */
+    if (Size < sizeof(BITMAP))
+    {
+        Status = STATUS_ACPI_INVALID_TABLE;
+        goto Quickie;
+    }
+
+    /* Map the real size of the header */
+    Status = BlMmMapPhysicalAddressEx((PVOID*)&Bitmap,
+                                      0,
+                                      Size,
+                                      PhysicalAddress);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Quickie;
+    }
+
+    /* Make sure this is a non-compressed 24-bit or 32-bit V3 bitmap */
+    if ((Bitmap->BmpHeader.Signature != 'MB') ||
+        (Bitmap->DibHeader.Compression) ||
+        ((Bitmap->DibHeader.BitCount != 24) &&
+         (Bitmap->DibHeader.BitCount != 32)) ||
+        (Bitmap->DibHeader.Size != sizeof(BITMAP)))
+    {
+        Status = STATUS_ACPI_INVALID_TABLE;
+        goto Quickie;
+    }
+
+    /* Check if caller wants the offsets back */
+    if (Offsets)
+    {
+        /* Give them away */
+        Offsets->X = BgrtTable->OffsetX;
+        Offsets->Y = BgrtTable->OffsetY;
+    }
+
+    /* Check if the caller wants flags */
+    if (Flags)
+    {
+        /* Return if the image is valid */
+        *Flags = BgrtTable->Status & BGRT_STATUS_IMAGE_VALID;
+    }
+
+Quickie:
+    /* Check if we had mapped the BGRT */
+    if (BgrtTable)
+    {
+        /* Unmap it */
+        BlMmUnmapVirtualAddressEx(BgrtTable, BgrtTable->Header.Length);
+    }
+
+    /* Check if this is the failure path */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Did we have the OEM bitmap mapped? */
+        if (Bitmap)
+        {
+            /* Unmap it */
+            BlMmUnmapVirtualAddressEx(Bitmap, Bitmap->BmpHeader.Size);
+        }
+
+        /* No bitmap to return */
+        Bitmap = NULL;
+    }
+
+    /* Return the bitmap back, if any */
+    return Bitmap;
+}
+
+BOOLEAN
+BlDisplayValidOemBitmap (
+    VOID
+    )
+{
+    PBITMAP Bitmap;
+    ULONG HRes, VRes, Height, Width, Flags;
+    COORD Offsets;
+    BOOLEAN Result;
+    NTSTATUS Status;
+
+    /* First check if mobile graphics are enabled */
+    Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
+                                    BcdLibraryBoolean_MobileGraphics,
+                                    &Result);
+    if ((NT_SUCCESS(Status)) && (Result))
+    {
+        /* Yes, so use the firmware image */
+        return TRUE;
+    }
+
+    /* Nope, so we'll check the ACPI OEM bitmap */
+    Result = FALSE;
+    Bitmap = BlDisplayGetOemBitmap(&Offsets, &Flags);
+
+    /* Is there one? */
+    if (Bitmap)
+    {
+        /* Is it valid? */
+        if (Flags & BGRT_STATUS_IMAGE_VALID)
+        {
+            /* Get the current screen resolution */
+            Status = BlDisplayGetScreenResolution(&HRes, &VRes);
+            if (NT_SUCCESS(Status))
+            {
+                /* Is there a valid width? */
+                Width = Bitmap->DibHeader.Width;
+                if (Width)
+                {
+                    /* Is there a valid height? */
+                    Height = Bitmap->DibHeader.Height;
+                    if (Height)
+                    {
+                        /* Will if fit on this screen? */
+                        if (((Width + Offsets.X) <= HRes) &&
+                            ((Height + Offsets.Y) <= VRes))
+                        {
+                            /* Then it's all good! */
+                            Result = TRUE;
+                        }
+                    }
+                }
+            }
+        }
+
+        /* Unmap the bitmap for now, it will be drawn later */
+        BlMmUnmapVirtualAddressEx(Bitmap, Bitmap->BmpHeader.Size);
+    }
+
+    /* Return that a valid OEM bitmap exists */
+    return Result;
+}
+
+NTSTATUS
+BlDisplayClearScreen (
+    VOID
+    )
+{
+    NTSTATUS Status;
+    PBL_TEXT_CONSOLE TextConsole;
+
+    /* Nothing to do if there's no text console */
+    Status = STATUS_SUCCESS;
+    TextConsole = DspTextConsole;
+    if (TextConsole)
+    {
+        /* Otherwise, clear the whole screen */
+        Status = TextConsole->Callbacks->ClearText(TextConsole, FALSE);
+        if (NT_SUCCESS(Status))
+        {
+            /* Invalidate the OEM bitmap at this point */
+            BlDisplayInvalidateOemBitmap();
+        }
+    }
+
+    /* All done */
+    return Status;
+};
+
+NTSTATUS
+BlDisplaySetCursorType (
+    _In_ ULONG Type
+    )
+{
+    NTSTATUS Status;
+    PBL_TEXT_CONSOLE TextConsole;
+    BL_DISPLAY_STATE State;
+
+    /* Nothing to do if there's no text console */
+    Status = STATUS_SUCCESS;
+    TextConsole = DspTextConsole;
+    if (TextConsole)
+    {
+        /* Write visibility state and call the function to change it */
+        State.CursorVisible = Type;
+        Status = TextConsole->Callbacks->SetTextState(TextConsole, 8, &State);
+    }
+
+    /* All done */
+    return Status;
+}
index 1c564fc..503d108 100644 (file)
@@ -120,7 +120,7 @@ ConsoleEfiGopEnable (
         }
 
         /* Reset the OEM bitmap and get the new more information */
-//        BlDisplayInvalidateOemBitmap();
+        BlDisplayInvalidateOemBitmap();
         EfiGopGetCurrentMode(Protocol, &Dummy, &ModeInformation);
     }
 
@@ -166,7 +166,7 @@ ConsoleEfiGopEnable (
     {
         /* We failed seomewhere, reset the mode and the OEM bitmap back */
         EfiGopSetMode(Protocol, CurrentMode);
-        //BlDisplayInvalidateOemBitmap();
+        BlDisplayInvalidateOemBitmap();
     }
 
     /* Return back to caller */
@@ -186,7 +186,7 @@ ConsoleEfiGopClose (
     {
         /* Restore the old mode and reset the OEM bitmap in ACPI */
         EfiGopSetMode(GraphicsConsole->Protocol, OldMode);
-        //BlDisplayInvalidateOemBitmap();
+        BlDisplayInvalidateOemBitmap();
     }
 
     /* Close the GOP protocol */
index 3e81617..441ccb2 100644 (file)
@@ -86,6 +86,44 @@ ConsoleEfiGraphicalOpenProtocol (
     return STATUS_UNSUCCESSFUL;
 }
 
+NTSTATUS
+ConsoleFirmwareGraphicalClear (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ ULONG Color
+    )
+{
+    NTSTATUS Status;
+    UCHAR Pixel[4] = { 0 };
+
+    /* Convert the standard color to a firmware pixel color */
+    Status = ConsolepConvertColorToPixel(Color, Pixel);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    /* Check if this is GOP or UGA */
+    if (Console->Type == BlUgaConsole)
+    {
+        EfiPrintf(L"Uga not supported\r\n");
+        Status = STATUS_NOT_IMPLEMENTED;
+    }
+    else
+    {
+        /* For GOP, just fill the screen */
+        ConsolepClearBuffer(Console->FrameBuffer,
+                            Console->DisplayMode.HRes,
+                            Pixel,
+                            Console->DisplayMode.VRes,
+                            Console->PixelsPerScanLine,
+                            Console->PixelDepth);
+        Status = STATUS_SUCCESS;
+    }
+
+    /* All clear */
+    return Status;
+}
+
 NTSTATUS
 ConsoleFirmwareGraphicalEnable (
     _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole
index 5fb7d7d..886a966 100644 (file)
@@ -551,4 +551,75 @@ ConsoleInputLocalEraseBuffer (
 
     /* All done */
     return Status;
-}
\ No newline at end of file
+}
+
+NTSTATUS
+ConsoleFirmwareTextClear ( 
+    _In_ PBL_TEXT_CONSOLE Console, 
+    _In_ BOOLEAN LineOnly
+    )
+{
+    BL_ARCH_MODE OldMode;
+    EFI_STATUS EfiStatus;
+    NTSTATUS Status;
+    ULONG i, Column, Row, TextWidth, TextHeight;
+
+    /* Get the text resolution */
+    BlDisplayGetTextCellResolution(&TextWidth, &TextHeight);
+
+    /* Are we just clearing a line? */
+    if (LineOnly)
+    {
+        /* Get the current column and row */
+        Column = Console->State.XPos / TextWidth;
+        Row = Console->State.YPos / TextHeight;
+        
+        /* Loop over every remaining character */
+        for (i = 0; i < Console->DisplayMode.HRes - Column - 1; i++)
+        {
+            /* Write a space on top of it */
+            Status = EfiConOutOutputString(Console->Protocol, L" ");
+            if (!NT_SUCCESS(Status))
+            {
+                break;
+            }
+        }
+
+        /* And reset the cursor back at the initial position */
+        Status = EfiConOutSetCursorPosition(Console->Protocol,
+                                            Column,
+                                            Row);
+    }
+    else
+    {
+        /* Are we in protected mode? */
+        OldMode = CurrentExecutionContext->Mode;
+        if (OldMode != BlRealMode)
+        {
+            /* FIXME: Not yet implemented */
+            return STATUS_NOT_IMPLEMENTED;
+        }
+
+        /* Clear the scren */
+        EfiStatus = Console->Protocol->ClearScreen(Console->Protocol);
+
+        /* Switch back to protected mode if we came from there */
+        if (OldMode != BlRealMode)
+        {
+            BlpArchSwitchContext(OldMode);
+        }
+
+        /* Conver to NT status -- did that work? */
+        Status = EfiGetNtStatusCode(EfiStatus);
+        if (NT_SUCCESS(Status))
+        {
+            /* Reset current positions */
+            Console->State.XPos = 0;
+            Console->State.YPos = 0;
+        }
+    }
+
+    /* All done */
+    return Status;
+}
+
index 0867411..f4d8c9a 100644 (file)
@@ -16,7 +16,12 @@ BL_GRAPHICS_CONSOLE_VTABLE ConsoleGraphicalVtbl =
 {
     {
         (PCONSOLE_DESTRUCT)ConsoleGraphicalDestruct,
-        (PCONSOLE_REINITIALIZE)ConsoleGraphicalReinitialize
+        (PCONSOLE_REINITIALIZE)ConsoleGraphicalReinitialize,
+        ConsoleTextBaseGetTextState,
+        (PCONSOLE_SET_TEXT_STATE)ConsoleGraphicalSetTextState,
+        NULL, // GetTextResolution
+        NULL, // SetTextResolution
+        (PCONSOLE_CLEAR_TEXT)ConsoleGraphicalClearText
     },
     ConsoleGraphicalIsEnabled,
     ConsoleGraphicalEnable,
@@ -28,6 +33,27 @@ BL_GRAPHICS_CONSOLE_VTABLE ConsoleGraphicalVtbl =
 
 /* FUNCTIONS *****************************************************************/
 
+NTSTATUS
+ConsoleGraphicalSetTextState (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ ULONG Mask,
+    _In_ PBL_DISPLAY_STATE TextState
+    )
+{
+    /* Is the text console active? */
+    if (Console->TextConsole.Active)
+    {
+        /* Let it handle that */
+        return ConsoleFirmwareTextSetState(&Console->TextConsole,
+                                           Mask,
+                                           TextState);
+    }
+
+    /* Not yet */
+    EfiPrintf(L"FFX set not implemented\r\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 NTSTATUS
 ConsoleGraphicalConstruct (
     _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole
@@ -79,6 +105,219 @@ ConsoleGraphicalConstruct (
     return STATUS_SUCCESS;
 }
 
+VOID
+ConsolepClearBuffer (
+    _In_ PUCHAR FrameBuffer,
+    _In_ ULONG Width,
+    _In_ PUCHAR FillColor,
+    _In_ ULONG Height,
+    _In_ ULONG ScanlineWidth,
+    _In_ ULONG PixelDepth
+    )
+{
+    PUCHAR Scanline, Current, FrameBufferEnd, LineEnd;
+    ULONG LineBytes, WidthBytes, BytesPerPixel;
+
+    /* Get the BPP */
+    BytesPerPixel = PixelDepth / 8;
+
+    /* Using that, calculate the size of a scan line */
+    LineBytes = ScanlineWidth * BytesPerPixel;
+
+    /* And the size of line we'll have to clear */
+    WidthBytes = Width * BytesPerPixel;
+
+    /* Allocat a scanline */
+    Scanline = BlMmAllocateHeap(WidthBytes);
+    if (Scanline)
+    {
+        /* For each remaining pixel on the scanline */
+        Current = Scanline;
+        while (Width--)
+        {
+            /* Copy in the fill color */
+            RtlCopyMemory(Current, FillColor, BytesPerPixel);
+            Current += BytesPerPixel;
+        }
+
+        /* For each scanline in the frame buffer */
+        while (Height--)
+        {
+            /* Copy our constructed scanline */
+            RtlCopyMemory(FrameBuffer, Scanline, WidthBytes);
+            FrameBuffer += LineBytes;
+        }
+    }
+    else
+    {
+        FrameBufferEnd = FrameBuffer + Height * LineBytes;
+        ScanlineWidth = BytesPerPixel * (ScanlineWidth - Width);
+        while (FrameBuffer != FrameBufferEnd)
+        {
+            if (FrameBuffer != (FrameBuffer + WidthBytes))
+            {
+                LineEnd = FrameBuffer + WidthBytes;
+                do
+                {
+                    RtlCopyMemory(FrameBuffer, FillColor, BytesPerPixel);
+                    FrameBuffer += BytesPerPixel;
+                }
+                while (FrameBuffer != LineEnd);
+            }
+
+            FrameBuffer += ScanlineWidth;
+        }
+    }
+}
+
+NTSTATUS
+ConsolepConvertColorToPixel (
+    _In_ BL_COLOR Color,
+    _Out_ PUCHAR Pixel
+    )
+{
+    NTSTATUS Status;
+
+    /* Assume success */
+    Status = STATUS_SUCCESS;
+
+    /* Convert the color to a pixel value */
+    switch (Color)
+    {
+    case Black:
+        Pixel[1] = 0;
+        Pixel[2] = 0;
+        Pixel[0] = 0;
+        break;
+    case Blue:
+        Pixel[1] = 0;
+        Pixel[2] = 0;
+        Pixel[0] = 0x7F;
+        break;
+    case Green:
+        Pixel[1] = 0x7F;
+        Pixel[2] = 0;
+        Pixel[0] = 0;
+        break;
+    case Cyan:
+        Pixel[1] = 0x7F;
+        Pixel[2] = 0;
+        Pixel[0] = 0x7F;
+        break;
+    case Red:
+        Pixel[1] = 0;
+        Pixel[2] = 0x7F;
+        Pixel[0] = 0x7F;
+        break;
+    case Magenta:
+        Pixel[1] = 0;
+        Pixel[2] = 0x7F;
+        Pixel[0] = 0x7F;
+        break;
+    case Brown:
+        Pixel[1] = 0x3F;
+        Pixel[2] = 0x7F;
+        Pixel[0] = 0;
+        break;
+    case LtGray:
+        Pixel[1] = 0xBFu;
+        Pixel[2] = 0xBFu;
+        *Pixel = 0xBFu;
+        break;
+    case Gray:
+        Pixel[1] = 0x7F;
+        Pixel[2] = 0x7F;
+        Pixel[0] = 0x7F;
+        break;
+    case LtBlue:
+        Pixel[1] = 0;
+        Pixel[2] = 0;
+        Pixel[0] = 0xFF;
+        break;
+    case LtGreen:
+        Pixel[1] = 0xFF;
+        Pixel[2] = 0;
+        Pixel[0] = 0;
+        break;
+    case LtCyan:
+        Pixel[1] = 0xFF;
+        Pixel[2] = 0;
+        Pixel[0] = 0xFF;
+        break;
+    case LtRed:
+        Pixel[1] = 0;
+        Pixel[2] = 0xFF;
+        Pixel[0] = 0;
+        break;
+    case LtMagenta:
+        Pixel[1] = 0;
+        Pixel[2] = 0xFF;
+        Pixel[0] = 0xFF;
+        break;
+    case Yellow:
+        Pixel[1] = 0xFF;
+        Pixel[2] = 0xFF;
+        Pixel[0] = 0;
+        break;
+    case White:
+        Pixel[1] = 0xFF;
+        Pixel[2] = 0xFF;
+        Pixel[0] = 0xFF;
+        break;
+    default:
+        Status = STATUS_INVALID_PARAMETER;
+        break;
+    }
+    return Status;
+}
+
+NTSTATUS
+ConsoleGraphicalClearPixels  (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ ULONG Color
+    )
+{
+    NTSTATUS Status;
+
+    /* Check if the text console is active */
+    if (Console->TextConsole.Active)
+    {
+        /* We shouldn't be here */
+        Status = STATUS_UNSUCCESSFUL;
+    }
+    else
+    {
+        /* Clear it in graphics mode */
+        Status = ConsoleFirmwareGraphicalClear(Console, Color);
+    }
+
+    /* All good */
+    return Status;
+}
+
+NTSTATUS
+ConsoleGraphicalClearText (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ BOOLEAN LineOnly
+    )
+{
+    /* Is the text console active? */
+    if (Console->TextConsole.Active)
+    {
+        /* Let firmware clear do it */
+        return ConsoleFirmwareTextClear(&Console->TextConsole, LineOnly);
+    }
+
+    /* Are we clearing a line only? */
+    if (LineOnly)
+    {
+        return BfClearToEndOfLine(Console);
+    }
+
+    /* Nope -- the whole screen */
+    return BfClearScreen(Console);
+}
+
 BOOLEAN
 ConsoleGraphicalIsEnabled  (
     _In_ PBL_GRAPHICS_CONSOLE Console
index e005b64..10f3def 100644 (file)
@@ -55,11 +55,11 @@ ConsoleTextBaseGetTextState (
 NTSTATUS
 ConsoleTextLocalSetTextState (
     _In_ struct _BL_TEXT_CONSOLE* Console,
-    _In_ ULONG Flags,
+    _In_ ULONG Mask,
     _In_ PBL_DISPLAY_STATE TextState
     )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    return ConsoleFirmwareTextSetState(Console, Mask, TextState);
 }
 
 NTSTATUS
@@ -84,10 +84,10 @@ ConsoleTextLocalSetTextResolution (
 NTSTATUS
 ConsoleTextLocalClearText (
     _In_ struct _BL_TEXT_CONSOLE* Console,
-    _In_ ULONG Attribute
+    _In_ BOOLEAN LineOnly
     )
 {
-    return STATUS_NOT_IMPLEMENTED;
+    return ConsoleFirmwareTextClear(Console, LineOnly);
 }
 
 NTSTATUS
index 88f20a3..199a395 100644 (file)
@@ -134,3 +134,63 @@ BfLoadDeferredFontFiles (
     /* Return load status */
     return Status;
 }
+
+NTSTATUS
+BfiFlipCursorCharacter (
+    _In_ PBL_GRAPHICS_CONSOLE Console,
+    _In_ BOOLEAN Visible
+    )
+{
+    /* not implemented */
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BfClearToEndOfLine (
+    _In_ PBL_GRAPHICS_CONSOLE Console
+    )
+{
+    /* not implemented */
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+BfClearScreen  (
+    _In_ PBL_GRAPHICS_CONSOLE Console
+    )
+{
+    NTSTATUS Status;
+
+    /* Reset the cursor position */
+    Console->TextConsole.State.XPos = 0;
+    Console->TextConsole.State.YPos = 0;
+
+    /* Fill the screen with the background color */
+    Status = ConsoleGraphicalClearPixels(Console,
+                                         Console->TextConsole.State.BgColor);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    /* Check if the cursor should be visible */
+    if (Console->TextConsole.State.CursorVisible)
+    {
+        /* Load any fonts at this time */
+        if (!IsListEmpty(&BfiDeferredListHead))
+        {
+            BfLoadDeferredFontFiles();
+        }
+
+        /* Switch the cursor to visible */
+        Status = BfiFlipCursorCharacter(Console, TRUE);
+    }
+    else
+    {
+        /* Nothing left to do */
+        Status = STATUS_SUCCESS;
+    }
+
+    /* Return cursor flip result, if any */
+    return Status;
+}
index 0615e70..6e34e0a 100644 (file)
@@ -55,7 +55,7 @@ ResSelectLocale (
     }
 
     /* Check if that failed, or if we're using fallback */
-    if (!NT_SUCCESS(Status) || !(Primary))
+    if (!(Primary) || !(NT_SUCCESS(Status)))
     {
         /* Set the fallback pointers */
         ResRootDirectory = ResRootDirectoryFallback;
@@ -68,7 +68,6 @@ ResSelectLocale (
         if (!NT_SUCCESS(Status))
         {
             /* Fallback to text mode (yes, this is the API...) */
-            EfiPrintf(L"Locale failed, falling back to text mode\r\n");
             return BlDisplaySetScreenResolution();
         }
     }
index a5301d6..dbeb79a 100644 (file)
@@ -12,8 +12,8 @@
 
 /* DATA VARIABLES ************************************************************/
 
-PVOID UtlRsdt;
-PVOID UtlXsdt;
+PRSDT UtlRsdt;
+PXSDT UtlXsdt;
 
 PVOID UtlMcContext;
 PVOID UtlMcDisplayMessageRoutine;
@@ -30,6 +30,152 @@ PVOID UtlProgressInfo;
 
 /* FUNCTIONS *****************************************************************/
 
+NTSTATUS
+BlUtlGetAcpiTable (
+    _Out_ PVOID* TableAddress,
+    _In_ ULONG Signature
+    )
+{
+    ULONG i, TableCount, HeaderLength;
+    NTSTATUS Status;
+    PRSDT Rsdt;
+    PXSDT Xsdt;
+    PHYSICAL_ADDRESS PhysicalAddress; 
+    PDESCRIPTION_HEADER Header;
+
+    Header = 0;
+
+    /* Make sure there's an output parameter */
+    if (!TableAddress)
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Get the currently known RSDT and XSDT */
+    Rsdt = (PRSDT)UtlRsdt;
+    Xsdt = (PXSDT)UtlXsdt;
+
+    /* Is there an RSDT? */
+    if (!Rsdt)
+    {
+        /* No -- is there an XSDT? */
+        if (!Xsdt)
+        {
+            /* No. Look up the RSDT */
+            Status = EfipGetRsdt(&PhysicalAddress);
+            if (!NT_SUCCESS(Status))
+            {
+                EfiPrintf(L"no rsdp found\r\n");
+                return Status;
+            }
+
+            /* Map the header */
+            Status = BlMmMapPhysicalAddressEx((PVOID)&Header,
+                                              0,
+                                              sizeof(*Header),
+                                              PhysicalAddress);
+            if (!NT_SUCCESS(Status))
+            {
+                return Status;
+            }
+
+            /* Unmap the header */
+            BlMmUnmapVirtualAddressEx(Header, sizeof(*Header));
+
+            /* Map the whole table */
+            Status = BlMmMapPhysicalAddressEx((PVOID)&Header,
+                                              0,
+                                              Header->Length,
+                                              PhysicalAddress);
+            if (!NT_SUCCESS(Status))
+            {
+                return Status;
+            }
+
+            /* Check if its an XSDT or an RSDT */
+            if (Header->Signature == XSDT_SIGNATURE)
+            {
+                /* It's an XSDT */
+                Xsdt = (PXSDT)Header;
+                UtlXsdt = Xsdt;
+            }
+            else
+            {
+                /* It's an RSDT */
+                Rsdt = (PRSDT)Header;
+                UtlRsdt = Rsdt;
+            }
+        }
+    }
+
+    /* OK, so do we have an XSDT after all? */
+    if (Xsdt)
+    {
+        /* Yes... how big is it? */
+        HeaderLength = Xsdt->Header.Length;
+        if (HeaderLength >= sizeof(*Header))
+        {
+            HeaderLength = sizeof(*Header);
+        }
+
+        /* Based on that, how many tables are there? */
+        TableCount = (Xsdt->Header.Length - HeaderLength) / sizeof(PHYSICAL_ADDRESS);
+    }
+    else
+    {
+        /* Nope, we have an RSDT. How big is it? */
+        HeaderLength = Rsdt->Header.Length;
+        if (HeaderLength >= sizeof(*Header))
+        {
+            HeaderLength = sizeof(*Header);
+        }
+
+        /* Based on that, how many tables are there? */
+        TableCount = (Rsdt->Header.Length - HeaderLength) / sizeof(ULONG);
+    }
+
+    /* Loop through the ACPI tables */
+    for (i = 0; i < TableCount; i++)
+    {
+        /* For an XSDT, read the 64-bit address directly */
+        if (Xsdt)
+        {
+            PhysicalAddress = Xsdt->Tables[i];
+        }
+        else
+        {
+            /* For RSDT, cast it */
+            PhysicalAddress.QuadPart = Rsdt->Tables[i];
+        }
+
+        /* Map the header */
+        Status = BlMmMapPhysicalAddressEx((PVOID)&Header,
+                                          0,
+                                          sizeof(*Header),
+                                          PhysicalAddress);
+        if (!NT_SUCCESS(Status))
+        {
+            return Status;
+        }
+
+        /* Is it the right one? */
+        if (Header->Signature == Signature)
+        {
+            /* Unmap the header */
+            BlMmUnmapVirtualAddressEx(Header, sizeof(*Header));
+
+            /* Map the whole table */
+            return BlMmMapPhysicalAddressEx(TableAddress,
+                                            0,
+                                            Header->Length,
+                                            PhysicalAddress);
+        }
+    }
+
+    /* Requested table does not exist */
+    return STATUS_NOT_FOUND;
+}
+
 VOID
 BlUtlUpdateProgress (
     _In_ ULONG Percentage,