From 101f65a4359d598bc2c13e6d1c0a5532e4037a85 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 7 Sep 2015 17:35:59 +0000 Subject: [PATCH] [BOOTMGFW] - Start GOP graphics console support. Checkpoint commit, currently WIP, untested. - Cleanup memory allocation/type/caching flags in a single unified enumeration. - Implement memory mapping functions for physical real mode only. svn path=/trunk/; revision=69094 --- reactos/boot/environ/app/bootmgr/efiemu.c | 3 - reactos/boot/environ/include/bl.h | 113 +++- .../boot/environ/include/efi/GraphicsOutput.h | 276 ++++++++++ reactos/boot/environ/include/efi/UgaDraw.h | 166 ++++++ .../boot/environ/lib/firmware/efi/firmware.c | 248 ++++++++- reactos/boot/environ/lib/mm/descriptor.c | 4 +- reactos/boot/environ/lib/mm/heapalloc.c | 2 +- reactos/boot/environ/lib/mm/mm.c | 162 ++++++ reactos/boot/environ/lib/mm/pagealloc.c | 13 +- reactos/boot/environ/lib/platform/display.c | 494 +++++++++++++++++- 10 files changed, 1446 insertions(+), 35 deletions(-) create mode 100644 reactos/boot/environ/include/efi/GraphicsOutput.h create mode 100644 reactos/boot/environ/include/efi/UgaDraw.h diff --git a/reactos/boot/environ/app/bootmgr/efiemu.c b/reactos/boot/environ/app/bootmgr/efiemu.c index 1c700dddb8e..2edc2eaee8e 100644 --- a/reactos/boot/environ/app/bootmgr/efiemu.c +++ b/reactos/boot/environ/app/bootmgr/efiemu.c @@ -25,9 +25,6 @@ typedef struct _BOOT_APPLICATION_PARAMETER_BLOCK_SCRATCH ULONG BlpApplicationFlags; -GUID EfiLoadedImageProtocol = EFI_LOADED_IMAGE_PROTOCOL_GUID; -GUID EfiDevicePathProtocol = EFI_DEVICE_PATH_PROTOCOL_GUID; - BOOT_APPLICATION_PARAMETER_BLOCK_SCRATCH EfiInitScratch; /* FUNCTIONS *****************************************************************/ diff --git a/reactos/boot/environ/include/bl.h b/reactos/boot/environ/include/bl.h index da0456bb299..8621120cd24 100644 --- a/reactos/boot/environ/include/bl.h +++ b/reactos/boot/environ/include/bl.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include VOID EarlyPrint(_In_ PWCHAR Format, ...); @@ -61,13 +63,6 @@ EarlyPrint(_In_ PWCHAR Format, ...); #define BL_MM_ADD_DESCRIPTOR_NEVER_TRUNCATE_FLAG 0x20 #define BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG 0x2000 -#define BL_MM_DESCRIPTOR_REQUIRES_FIXED_FLAG 0x40000 -#define BL_MM_DESCRIPTOR_REQUIRES_COALESCING_FLAG 0x2000000 -#define BL_MM_DESCRIPTOR_REQUIRES_UPDATING_FLAG 0x4000000 -#define BL_MM_DESCRIPTOR_NEVER_USE_FIRMWARE_FLAG 0x8000000 -#define BL_MM_DESCRIPTOR_SPECIAL_PAGES_FLAG 0x20000000 -#define BL_MM_DESCRIPTOR_CAME_FROM_FIRMWARE_FLAG 0x80000000 - #define BL_MM_REQUEST_DEFAULT_TYPE 1 #define BL_MM_REQUEST_TOP_DOWN_TYPE 2 @@ -193,15 +188,45 @@ typedef enum _BL_MEMORY_TYPE typedef enum _BL_MEMORY_ATTR { - BlMemoryUncached = 1, - BlMemoryWriteCombined = 2, - BlMemoryWriteThrough = 4, - BlMemoryWriteBack = 8, - BlMemoryUncachedExported = 0x10, - BlMemoryWriteProtected = 0x100, - BlMemoryReadProtected = 0x200, - BlMemoryExecuteProtected = 0x400, - BlMemoryRuntime = 0x1000000 + // + // Memory Caching Attributes + // + BlMemoryUncached = 0x00000001, + BlMemoryWriteCombined = 0x00000002, + BlMemoryWriteThrough = 0x00000004, + BlMemoryWriteBack = 0x00000008, + BlMemoryUncachedExported = 0x00000010, + BlMemoryValidCacheAttributes = BlMemoryUncached | BlMemoryWriteCombined | BlMemoryWriteThrough | BlMemoryWriteBack | BlMemoryUncachedExported, + BlMemoryValidCacheAttributeMask = 0x000000FF, + + // + // Memory Protection Attributes + // + BlMemoryWriteProtected = 0x00000100, + BlMemoryReadProtected = 0x00000200, + BlMemoryExecuteProtected = 0x00000400, + BlMemoryValidProtectionAttributes = BlMemoryWriteProtected | BlMemoryReadProtected | BlMemoryExecuteProtected, + BlMemoryValidProtectionAttributeMask = 0x0000FF00, + + // + // Memory Allocation Attributes + // + BlMemoryNonFixed = 0x00020000, + BlMemoryFixed = 0x00040000, + BlMemoryValidAllocationAttributes = BlMemoryNonFixed | BlMemoryFixed, + BlMemoryValidAllocationAttributeMask = 0x00FF0000, + + // + // Memory Type Attributes + // + BlMemoryRuntime = 0x01000000, + BlMemoryCoalesced = 0x02000000, + BlMemoryUpdate = 0x04000000, + BlMemoryNonFirmware = 0x08000000, + BlMemorySpecial = 0x20000000, + BlMemoryFirmware = 0x80000000, + BlMemoryValidTypeAttributes = BlMemoryRuntime | BlMemoryCoalesced | BlMemoryUpdate | BlMemoryNonFirmware | BlMemorySpecial | BlMemoryFirmware, + BlMemoryValidTypeAttributeMask = 0xFF000000, } BL_MEMORY_ATTR; /* CALLBACKS *****************************************************************/ @@ -655,6 +680,47 @@ EfiConOutEnableCursor ( _In_ BOOLEAN Visible ); +NTSTATUS +EfiLocateHandleBuffer ( + _In_ EFI_LOCATE_SEARCH_TYPE SearchType, + _In_ EFI_GUID *Protocol, + _Inout_ PULONG HandleCount, + _Inout_ EFI_HANDLE** Buffer + ); + +NTSTATUS +EfiOpenProtocol ( + _In_ EFI_HANDLE Handle, + _In_ EFI_GUID *Protocol, + _Out_ PVOID* Interface + ); + +NTSTATUS +EfiCloseProtocol ( + _In_ EFI_HANDLE Handle, + _In_ EFI_GUID *Protocol + ); + +NTSTATUS +EfiGopGetCurrentMode ( + _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, + _Out_ UINTN* Mode, + _Out_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information + ); + +NTSTATUS +EfiGopSetMode ( + _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, + _In_ ULONG Mode + ); + +VOID +EfiGopGetFrameBuffer ( + _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, + _Out_ PHYSICAL_ADDRESS* FrameBuffer, + _Out_ UINTN *FrameBufferSize + ); + /* PLATFORM TIMER ROUTINES ***************************************************/ NTSTATUS @@ -773,6 +839,16 @@ MmFwGetMemoryMap ( _In_ ULONG Flags ); +/* VIRTUAL MEMORY ROUTINES ***************************************************/ + +NTSTATUS +BlMmMapPhysicalAddressEx ( + _In_ PVOID* VirtualAddress, + _In_ ULONG Attributes, + _In_ ULONGLONG Size, + _In_ PHYSICAL_ADDRESS PhysicalAddress + ); + /* HEAP ALLOCATOR ROUTINES ***************************************************/ PVOID @@ -801,5 +877,10 @@ extern PBL_ARCH_CONTEXT CurrentExecutionContext; extern PBL_DEVICE_DESCRIPTOR BlpBootDevice; extern BL_APPLICATION_ENTRY BlpApplicationEntry; extern SIMPLE_TEXT_OUTPUT_INTERFACE *EfiConOut; +extern EFI_GUID EfiGraphicsOutputProtocol; +extern EFI_GUID EfiUgaDrawProtocol; +extern EFI_GUID EfiLoadedImageProtocol; +extern EFI_GUID EfiDevicePathProtocol; +extern EFI_GUID EfiSimpleTextInputExProtocol; #endif diff --git a/reactos/boot/environ/include/efi/GraphicsOutput.h b/reactos/boot/environ/include/efi/GraphicsOutput.h new file mode 100644 index 00000000000..a3432ce1d6e --- /dev/null +++ b/reactos/boot/environ/include/efi/GraphicsOutput.h @@ -0,0 +1,276 @@ +/** @file + Graphics Output Protocol from the UEFI 2.0 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef __GRAPHICS_OUTPUT_H__ +#define __GRAPHICS_OUTPUT_H__ + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { \ + 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ + } + +typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +typedef enum { + /// + /// A pixel is 32-bits and byte zero represents red, byte one represents green, + /// byte two represents blue, and byte three is reserved. This is the definition + /// for the physical frame buffer. The byte values for the red, green, and blue + /// components represent the color intensity. This color intensity value range + /// from a minimum intensity of 0 to maximum intensity of 255. + /// + PixelRedGreenBlueReserved8BitPerColor, + /// + /// A pixel is 32-bits and byte zero represents blue, byte one represents green, + /// byte two represents red, and byte three is reserved. This is the definition + /// for the physical frame buffer. The byte values for the red, green, and blue + /// components represent the color intensity. This color intensity value range + /// from a minimum intensity of 0 to maximum intensity of 255. + /// + PixelBlueGreenRedReserved8BitPerColor, + /// + /// The Pixel definition of the physical frame buffer. + /// + PixelBitMask, + /// + /// This mode does not support a physical frame buffer. + /// + PixelBltOnly, + /// + /// Valid EFI_GRAPHICS_PIXEL_FORMAT enum values are less than this value. + /// + PixelFormatMax +} EFI_GRAPHICS_PIXEL_FORMAT; + +typedef struct { + /// + /// The version of this data structure. A value of zero represents the + /// EFI_GRAPHICS_OUTPUT_MODE_INFORMATION structure as defined in this specification. + /// + UINT32 Version; + /// + /// The size of video screen in pixels in the X dimension. + /// + UINT32 HorizontalResolution; + /// + /// The size of video screen in pixels in the Y dimension. + /// + UINT32 VerticalResolution; + /// + /// Enumeration that defines the physical format of the pixel. A value of PixelBltOnly + /// implies that a linear frame buffer is not available for this mode. + /// + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + /// + /// This bit-mask is only valid if PixelFormat is set to PixelPixelBitMask. + /// A bit being set defines what bits are used for what purpose such as Red, Green, Blue, or Reserved. + /// + EFI_PIXEL_BITMASK PixelInformation; + /// + /// Defines the number of pixel elements per video memory line. + /// + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +/** + Returns information for an available graphics mode that the graphics device + and the set of active video output devices supports. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Valid mode information was returned. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_INVALID_PARAMETER ModeNumber is not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE)( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ); + +/** + Set the video device into the specified mode and clears the visible portions of + the output display to black. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber Abstraction that defines the current video mode. + + @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE)( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ); + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; + +typedef union { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; + UINT32 Raw; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; + +/// +/// actions for BltOperations +/// +typedef enum { + /// + /// Write data from the BltBuffer pixel (0, 0) + /// directly to every pixel of the video display rectangle + /// (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + /// Only one pixel will be used from the BltBuffer. Delta is NOT used. + /// + EfiBltVideoFill, + + /// + /// Read data from the video display rectangle + /// (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + /// the BltBuffer rectangle (DestinationX, DestinationY ) + /// (DestinationX + Width, DestinationY + Height). If DestinationX or + /// DestinationY is not zero then Delta must be set to the length in bytes + /// of a row in the BltBuffer. + /// + EfiBltVideoToBltBuffer, + + /// + /// Write data from the BltBuffer rectangle + /// (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + /// video display rectangle (DestinationX, DestinationY) + /// (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + /// not zero then Delta must be set to the length in bytes of a row in the + /// BltBuffer. + /// + EfiBltBufferToVideo, + + /// + /// Copy from the video display rectangle (SourceX, SourceY) + /// (SourceX + Width, SourceY + Height) to the video display rectangle + /// (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + /// The BltBuffer and Delta are not used in this mode. + /// + EfiBltVideoToVideo, + + EfiGraphicsOutputBltOperationMax +} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; + +/** + Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer. + + @param This Protocol instance pointer. + @param BltBuffer The data to transfer to the graphics screen. + Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). + @param BltOperation The operation to perform when copying BltBuffer on to the graphics screen. + @param SourceX The X coordinate of source for the BltOperation. + @param SourceY The Y coordinate of source for the BltOperation. + @param DestinationX The X coordinate of destination for the BltOperation. + @param DestinationY The Y coordinate of destination for the BltOperation. + @param Width The width of a rectangle in the blt rectangle in pixels. + @param Height The height of a rectangle in the blt rectangle in pixels. + @param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation. + If a Delta of zero is used, the entire BltBuffer is being operated on. + If a subrectangle of the BltBuffer is being used then Delta + represents the number of bytes in a row of the BltBuffer. + + @retval EFI_SUCCESS BltBuffer was drawn to the graphics screen. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT)( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +typedef struct { + /// + /// The number of modes supported by QueryMode() and SetMode(). + /// + UINT32 MaxMode; + /// + /// Current Mode of the graphics device. Valid mode numbers are 0 to MaxMode -1. + /// + UINT32 Mode; + /// + /// Pointer to read-only EFI_GRAPHICS_OUTPUT_MODE_INFORMATION data. + /// + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + /// + /// Size of Info structure in bytes. + /// + UINTN SizeOfInfo; + /// + /// Base address of graphics linear frame buffer. + /// Offset zero in FrameBufferBase represents the upper left pixel of the display. + /// + EFI_PHYSICAL_ADDRESS FrameBufferBase; + /// + /// Amount of frame buffer needed to support the active mode as defined by + /// PixelsPerScanLine xVerticalResolution x PixelElementSize. + /// + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +/// +/// Provides a basic abstraction to set video modes and copy pixels to and from +/// the graphics controller's frame buffer. The linear address of the hardware +/// frame buffer is also exposed so software can write directly to the video hardware. +/// +struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { + EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; + /// + /// Pointer to EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE data. + /// + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; +}; + +extern EFI_GUID gEfiGraphicsOutputProtocolGuid; + +#endif diff --git a/reactos/boot/environ/include/efi/UgaDraw.h b/reactos/boot/environ/include/efi/UgaDraw.h new file mode 100644 index 00000000000..f501a6c17f4 --- /dev/null +++ b/reactos/boot/environ/include/efi/UgaDraw.h @@ -0,0 +1,166 @@ +/** @file + UGA Draw protocol from the EFI 1.10 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef __UGA_DRAW_H__ +#define __UGA_DRAW_H__ + + +#define EFI_UGA_DRAW_PROTOCOL_GUID \ + { \ + 0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 } \ + } + +typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL; + +/** + Return the current video mode information. + + @param This The EFI_UGA_DRAW_PROTOCOL instance. + @param HorizontalResolution The size of video screen in pixels in the X dimension. + @param VerticalResolution The size of video screen in pixels in the Y dimension. + @param ColorDepth Number of bits per pixel, currently defined to be 32. + @param RefreshRate The refresh rate of the monitor in Hertz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE)( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ); + +/** + Set the current video mode information. + + @param This The EFI_UGA_DRAW_PROTOCOL instance. + @param HorizontalResolution The size of video screen in pixels in the X dimension. + @param VerticalResolution The size of video screen in pixels in the Y dimension. + @param ColorDepth Number of bits per pixel, currently defined to be 32. + @param RefreshRate The refresh rate of the monitor in Hertz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_SET_MODE)( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ); + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_UGA_PIXEL; + +typedef union { + EFI_UGA_PIXEL Pixel; + UINT32 Raw; +} EFI_UGA_PIXEL_UNION; + +/// +/// Enumration value for actions of Blt operations. +/// +typedef enum { + EfiUgaVideoFill, ///< Write data from the BltBuffer pixel (SourceX, SourceY) + ///< directly to every pixel of the video display rectangle + ///< (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + ///< Only one pixel will be used from the BltBuffer. Delta is NOT used. + + EfiUgaVideoToBltBuffer, ///< Read data from the video display rectangle + ///< (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + ///< the BltBuffer rectangle (DestinationX, DestinationY ) + ///< (DestinationX + Width, DestinationY + Height). If DestinationX or + ///< DestinationY is not zero then Delta must be set to the length in bytes + ///< of a row in the BltBuffer. + + EfiUgaBltBufferToVideo, ///< Write data from the BltBuffer rectangle + ///< (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + ///< video display rectangle (DestinationX, DestinationY) + ///< (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + ///< not zero then Delta must be set to the length in bytes of a row in the + ///< BltBuffer. + + EfiUgaVideoToVideo, ///< Copy from the video display rectangle (SourceX, SourceY) + ///< (SourceX + Width, SourceY + Height) .to the video display rectangle + ///< (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + ///< The BltBuffer and Delta are not used in this mode. + + EfiUgaBltMax ///< Maxmimum value for enumration value of Blt operation. If a Blt operation + ///< larger or equal to this enumration value, it is invalid. +} EFI_UGA_BLT_OPERATION; + +/** + Blt a rectangle of pixels on the graphics screen. + + @param[in] This - Protocol instance pointer. + @param[in] BltBuffer - Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL) + @param[in] BltOperation - Operation to perform on BlitBuffer and video memory + @param[in] SourceX - X coordinate of source for the BltBuffer. + @param[in] SourceY - Y coordinate of source for the BltBuffer. + @param[in] DestinationX - X coordinate of destination for the BltBuffer. + @param[in] DestinationY - Y coordinate of destination for the BltBuffer. + @param[in] Width - Width of rectangle in BltBuffer in pixels. + @param[in] Height - Hight of rectangle in BltBuffer in pixels. + @param[in] Delta - OPTIONAL + + @retval EFI_SUCCESS - The Blt operation completed. + @retval EFI_INVALID_PARAMETER - BltOperation is not valid. + @retval EFI_DEVICE_ERROR - A hardware error occured writting to the video buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_BLT)( + IN EFI_UGA_DRAW_PROTOCOL * This, + IN EFI_UGA_PIXEL * BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +/// +/// This protocol provides a basic abstraction to set video modes and +/// copy pixels to and from the graphics controller's frame buffer. +/// +struct _EFI_UGA_DRAW_PROTOCOL { + EFI_UGA_DRAW_PROTOCOL_GET_MODE GetMode; + EFI_UGA_DRAW_PROTOCOL_SET_MODE SetMode; + EFI_UGA_DRAW_PROTOCOL_BLT Blt; +}; + +extern EFI_GUID gEfiUgaDrawProtocolGuid; + +#endif diff --git a/reactos/boot/environ/lib/firmware/efi/firmware.c b/reactos/boot/environ/lib/firmware/efi/firmware.c index 37a8e1b00c2..2c4bb31efec 100644 --- a/reactos/boot/environ/lib/firmware/efi/firmware.c +++ b/reactos/boot/environ/lib/firmware/efi/firmware.c @@ -12,8 +12,6 @@ /* DATA VARIABLES ************************************************************/ -GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; - PBL_FIRMWARE_DESCRIPTOR EfiFirmwareParameters; BL_FIRMWARE_DESCRIPTOR EfiFirmwareData; EFI_HANDLE EfiImageHandle; @@ -26,6 +24,12 @@ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *EfiConOut; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *EfiConIn; EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *EfiConInEx; +EFI_GUID EfiGraphicsOutputProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; +EFI_GUID EfiUgaDrawProtocol = EFI_UGA_DRAW_PROTOCOL_GUID; +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; + /* FUNCTIONS *****************************************************************/ NTSTATUS @@ -92,6 +96,65 @@ EfiOpenProtocol ( return Status; } +NTSTATUS +EfiCloseProtocol ( + _In_ EFI_HANDLE Handle, + _In_ EFI_GUID *Protocol + ) +{ + EFI_STATUS EfiStatus; + NTSTATUS Status; + BL_ARCH_MODE OldMode; + + /* Are we using virtual memory/ */ + if (MmTranslationType != BlNone) + { + /* We need complex tracking to make this work */ + //Status = EfiVmOpenProtocol(Handle, Protocol, Interface); + Status = STATUS_NOT_SUPPORTED; + } + else + { + /* Are we on legacy 1.02? */ + if (EfiST->FirmwareRevision == EFI_1_02_SYSTEM_TABLE_REVISION) + { + /* Nothing to close */ + EfiStatus = STATUS_SUCCESS; + } + else + { + /* Are we in protected mode? */ + OldMode = CurrentExecutionContext->Mode; + if (OldMode != BlRealMode) + { + /* FIXME: Not yet implemented */ + return STATUS_NOT_IMPLEMENTED; + } + + /* Use the UEFI version */ + EfiStatus = EfiBS->CloseProtocol(Handle, Protocol, EfiImageHandle, NULL); + + /* Switch back to protected mode if we came from there */ + if (OldMode != BlRealMode) + { + BlpArchSwitchContext(OldMode); + } + + /* Normalize not found as success */ + if (EfiStatus == EFI_NOT_FOUND) + { + EfiStatus = EFI_SUCCESS; + } + } + + /* Convert the error to an NTSTATUS */ + Status = EfiGetNtStatusCode(EfiStatus); + } + + /* All done */ + return Status; +} + NTSTATUS EfiConInExSetState ( _In_ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *ConInEx, @@ -426,6 +489,187 @@ EfiConOutReadCurrentMode ( } } +VOID +EfiGopGetFrameBuffer ( + _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, + _Out_ PHYSICAL_ADDRESS* FrameBuffer, + _Out_ UINTN *FrameBufferSize + ) +{ + BL_ARCH_MODE OldMode; + + /* Are we in protected mode? */ + OldMode = CurrentExecutionContext->Mode; + if (OldMode != BlRealMode) + { + /* FIXME: Not yet implemented */ + return; + } + + /* Make the EFI call */ + FrameBuffer->QuadPart = GopInterface->Mode->FrameBufferBase; + *FrameBufferSize = GopInterface->Mode->FrameBufferSize; + + /* Switch back to protected mode if we came from there */ + if (OldMode != BlRealMode) + { + BlpArchSwitchContext(OldMode); + } +} + +NTSTATUS +EfiGopGetCurrentMode ( + _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, + _Out_ UINTN* Mode, + _Out_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Information + ) +{ + BL_ARCH_MODE OldMode; + + /* Are we in protected mode? */ + OldMode = CurrentExecutionContext->Mode; + if (OldMode != BlRealMode) + { + /* FIXME: Not yet implemented */ + return STATUS_NOT_IMPLEMENTED; + } + + /* Make the EFI call */ + *Mode = GopInterface->Mode->Mode; + RtlCopyMemory(Information, GopInterface->Mode, sizeof(*Information)); + + /* Switch back to protected mode if we came from there */ + if (OldMode != BlRealMode) + { + BlpArchSwitchContext(OldMode); + } + + /* Return back */ + return STATUS_SUCCESS; +} + +NTSTATUS +EfiGopSetMode ( + _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopInterface, + _In_ ULONG Mode + ) +{ + BL_ARCH_MODE OldMode; + EFI_STATUS EfiStatus; + BOOLEAN ModeChanged; + NTSTATUS Status; + + /* Are we in protected mode? */ + OldMode = CurrentExecutionContext->Mode; + if (OldMode != BlRealMode) + { + /* FIXME: Not yet implemented */ + return STATUS_NOT_IMPLEMENTED; + } + + /* Make the EFI call */ + if (Mode == GopInterface->Mode->Mode) + { + EfiStatus = EFI_SUCCESS; + ModeChanged = FALSE; + } + { + EfiStatus = GopInterface->SetMode(GopInterface, Mode); + ModeChanged = TRUE; + } + + /* Switch back to protected mode if we came from there */ + if (OldMode != BlRealMode) + { + BlpArchSwitchContext(OldMode); + } + + /* Print out to the debugger if the mode was changed */ + Status = EfiGetNtStatusCode(EfiStatus); + if ((ModeChanged) && (NT_SUCCESS(Status))) + { + /* FIXME @TODO: Should be BlStatusPrint */ + EarlyPrint(L"Console video mode set to 0x%x\r\n", Mode); + } + + /* Convert the error to an NTSTATUS */ + return Status; +} + +NTSTATUS +EfiLocateHandleBuffer ( + _In_ EFI_LOCATE_SEARCH_TYPE SearchType, + _In_ EFI_GUID *Protocol, + _Inout_ PULONG HandleCount, + _Inout_ EFI_HANDLE** Buffer + ) +{ + BL_ARCH_MODE OldMode; + EFI_STATUS EfiStatus; + UINTN BufferSize; + + /* Bail out if we're missing parameters */ + if (!(Buffer) || !(HandleCount)) + { + return STATUS_INVALID_PARAMETER; + } + + /* Check if a buffer was passed in*/ + if (*Buffer) + { + /* Then we should already have a buffer size*/ + BufferSize = sizeof(EFI_HANDLE) * *HandleCount; + } + else + { + /* Then no buffer size exists */ + BufferSize = 0; + } + + /* Are we in protected mode? */ + OldMode = CurrentExecutionContext->Mode; + if (OldMode != BlRealMode) + { + /* FIXME: Not yet implemented */ + return STATUS_NOT_IMPLEMENTED; + } + + /* Try the first time */ + EfiStatus = EfiBS->LocateHandle(SearchType, Protocol, NULL, &BufferSize, *Buffer); + if (EfiStatus == EFI_BUFFER_TOO_SMALL) + { + /* Did we have an existing buffer? */ + if (*Buffer) + { + /* Free it */ + BlMmFreeHeap(*Buffer); + } + + /* Allocate a new one */ + *Buffer = BlMmAllocateHeap(BufferSize); + if (!(*Buffer)) + { + /* No space, fail */ + return STATUS_NO_MEMORY; + } + + /* Try again */ + EfiStatus = EfiBS->LocateHandle(SearchType, Protocol, NULL, &BufferSize, *Buffer); + + /* Switch back to protected mode if we came from there */ + if (OldMode != BlRealMode) + { + BlpArchSwitchContext(OldMode); + } + } + + /* Return the number of handles */ + *HandleCount = BufferSize / sizeof(EFI_HANDLE); + + /* Convert the error to an NTSTATUS */ + return EfiGetNtStatusCode(EfiStatus); +} + NTSTATUS EfiAllocatePages ( _In_ ULONG Type, diff --git a/reactos/boot/environ/lib/mm/descriptor.c b/reactos/boot/environ/lib/mm/descriptor.c index 5157e1f842a..847efc02f76 100644 --- a/reactos/boot/environ/lib/mm/descriptor.c +++ b/reactos/boot/environ/lib/mm/descriptor.c @@ -387,7 +387,7 @@ MmMdAddDescriptorToList ( else { /* Coalesce if the descriptor requires it */ - if (MemoryDescriptor->Flags & BL_MM_DESCRIPTOR_REQUIRES_COALESCING_FLAG) + if (MemoryDescriptor->Flags & BlMemoryCoalesced) { Flags |= BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG; } @@ -400,7 +400,7 @@ MmMdAddDescriptorToList ( } /* Update the current list pointer if the descriptor requires it */ - if (MemoryDescriptor->Flags & BL_MM_DESCRIPTOR_REQUIRES_UPDATING_FLAG) + if (MemoryDescriptor->Flags & BlMemoryUpdate) { Flags |= BL_MM_ADD_DESCRIPTOR_UPDATE_LIST_POINTER_FLAG; } diff --git a/reactos/boot/environ/lib/mm/heapalloc.c b/reactos/boot/environ/lib/mm/heapalloc.c index 833a9030769..c5fe0926c56 100644 --- a/reactos/boot/environ/lib/mm/heapalloc.c +++ b/reactos/boot/environ/lib/mm/heapalloc.c @@ -23,7 +23,7 @@ typedef struct _BL_HEAP_POINTER ULONG_PTR BufferFree : 1; ULONG_PTR BufferOnHeap : 1; ULONG_PTR NotUsed : 1; - ULONG_PTR BufferPointer : (sizeof(ULONG_PTR) - BL_HEAP_POINTER_FLAG_BITS); + ULONG_PTR BufferPointer : ((8 * sizeof(ULONG_PTR)) - BL_HEAP_POINTER_FLAG_BITS); }; PVOID P; }; diff --git a/reactos/boot/environ/lib/mm/mm.c b/reactos/boot/environ/lib/mm/mm.c index 7c3dcdfe540..4b51c74bd3c 100644 --- a/reactos/boot/environ/lib/mm/mm.c +++ b/reactos/boot/environ/lib/mm/mm.c @@ -42,6 +42,168 @@ BlMmRemoveBadMemory ( return STATUS_SUCCESS; } +NTSTATUS +MmSelectMappingAddress ( + _Out_ PVOID* MappingAddress, + _In_ ULONGLONG Size, + _In_ ULONG AllocationAttributes, + _In_ ULONG Flags, + _In_ PHYSICAL_ADDRESS PhysicalAddress + ) +{ + /* Are we in physical mode? */ + if (MmTranslationType == BlNone) + { + /* Just return the physical address as the mapping address */ + *MappingAddress = (PVOID)PhysicalAddress.LowPart; + return STATUS_SUCCESS; + } + + /* Have to allocate physical pages */ + EarlyPrint(L"VM Todo\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +MmMapPhysicalAddress ( + _Inout_ PPHYSICAL_ADDRESS PhysicalAddress, + _Out_ PVOID VirtualAddress, + _Inout_ PULONGLONG Size, + _In_ ULONG CacheAttributes + ) +{ + ULONGLONG MappingSize; + + /* Fail if any parameters are missing */ + if (!(PhysicalAddress) || !(VirtualAddress) || !(Size)) + { + return STATUS_INVALID_PARAMETER; + } + + /* Fail if the size is over 32-bits */ + MappingSize = *Size; + if (MappingSize > 0xFFFFFFFF) + { + return STATUS_INVALID_PARAMETER; + } + + /* Nothing to do if we're in physical mode */ + if (MmTranslationType == BlNone) + { + return STATUS_SUCCESS; + } + + /* Can't use virtual memory in real mode */ + if (CurrentExecutionContext->Mode == BlRealMode) + { + return STATUS_UNSUCCESSFUL; + } + + EarlyPrint(L"VM todo\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +BlMmMapPhysicalAddressEx ( + _In_ PVOID* VirtualAddress, + _In_ ULONG Flags, + _In_ ULONGLONG Size, + _In_ PHYSICAL_ADDRESS PhysicalAddress + ) +{ + NTSTATUS Status; + PVOID MappingAddress; + PHYSICAL_ADDRESS MappedAddress; + PVOID MappedBase; + ULONGLONG MapSize; + UCHAR CacheAttributes; + + /* Increase call depth */ + ++MmDescriptorCallTreeCount; + + /* Check if any parameters are missing */ + if (!(VirtualAddress) || !(Size)) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Check for fixed allocation without an actual address */ + if ((Flags & BlMemoryFixed) && + (PhysicalAddress.QuadPart == -1) && + !(*VirtualAddress)) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Check for invalid requirement flag, if one is present */ + if (((Flags & BlMemoryValidAllocationAttributes) != BlMemoryFixed) && + ((Flags & BlMemoryValidAllocationAttributes) != BlMemoryNonFixed) && + (Flags & BlMemoryValidAllocationAttributes)) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Check for invalid cache attribute flags */ + if (((Flags & BlMemoryValidCacheAttributeMask) - 1) & + (Flags & BlMemoryValidCacheAttributeMask)) + { + Status = STATUS_INVALID_PARAMETER; + goto Quickie; + } + + /* Select an address to map this at */ + Status = MmSelectMappingAddress(&MappingAddress, + Size, + Flags & BlMemoryValidAllocationAttributes, + Flags, + PhysicalAddress); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Map the selected address, using the appropriate caching attributes */ + MappedAddress = PhysicalAddress; + MapSize = Size; + CacheAttributes = ((Flags & BlMemoryValidCacheAttributeMask) != 0x20) ? + (Flags & BlMemoryValidCacheAttributeMask) : 0; + Status = MmMapPhysicalAddress(&MappedAddress, + &MappingAddress, + &MapSize, + CacheAttributes); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Compute the final adress where the mapping was made */ + MappedBase = (PVOID)((ULONG_PTR)MappingAddress + + PhysicalAddress.LowPart - + MappedAddress.LowPart); + + /* Check if we're in physical or virtual mode */ + if (MmTranslationType != BlNone) + { + /* For virtual memory, there's more to do */ + EarlyPrint(L"VM not supported for mapping\n"); + Status = STATUS_NOT_IMPLEMENTED; + goto Quickie; + } + + /* Return the mapped virtual address */ + Status = STATUS_SUCCESS; + *VirtualAddress = MappedBase; + +Quickie: + /* Cleanup descriptors and reduce depth */ + MmMdFreeGlobalDescriptors(); + --MmDescriptorCallTreeCount; + return Status; +} + NTSTATUS BlpMmInitialize ( _In_ PBL_MEMORY_DATA MemoryData, diff --git a/reactos/boot/environ/lib/mm/pagealloc.c b/reactos/boot/environ/lib/mm/pagealloc.c index 5b97d5004a7..17a261336f7 100644 --- a/reactos/boot/environ/lib/mm/pagealloc.c +++ b/reactos/boot/environ/lib/mm/pagealloc.c @@ -141,8 +141,8 @@ MmPapAllocateRegionFromMdl ( /* Are we using the physical memory list, and are we OK with using firmware? */ if ((CurrentList == &MmMdlUnmappedUnallocated) && - !((Request->Flags & BL_MM_DESCRIPTOR_NEVER_USE_FIRMWARE_FLAG) || - (LocalDescriptor.Flags & BL_MM_DESCRIPTOR_NEVER_USE_FIRMWARE_FLAG))) + !((Request->Flags & BlMemoryNonFirmware) || + (LocalDescriptor.Flags & BlMemoryNonFirmware))) { /* Allocate the requested address from EFI */ EfiAddress = LocalDescriptor.BasePage << PAGE_SHIFT; @@ -222,7 +222,7 @@ MmPapAllocateRegionFromMdl ( /* Remember if it came from EFI */ if (GotFwPages) { - FoundDescriptor->Flags |= BL_MM_DESCRIPTOR_CAME_FROM_FIRMWARE_FLAG; + FoundDescriptor->Flags |= BlMemoryFirmware; } /* Add the descriptor to the requested list */ @@ -253,7 +253,7 @@ MmPaAllocatePages ( /* Heap and page directory/table pages have a special flag */ if ((MemoryType >= BlLoaderHeap) && (MemoryType <= BlLoaderReferencePage)) { - Request->Flags |= BL_MM_DESCRIPTOR_SPECIAL_PAGES_FLAG; + Request->Flags |= BlMemorySpecial; } /* Try to find a free region of RAM matching this range and request */ @@ -334,7 +334,7 @@ MmPapAllocatePhysicalPagesInRange ( Request.VirtualRange.Maximum = 0; /* Check if a fixed allocation was requested*/ - if (Attributes & BL_MM_DESCRIPTOR_REQUIRES_FIXED_FLAG) + if (Attributes & BlMemoryFixed) { /* Force the only available range to be the passed in address */ Request.BaseRange.Minimum = BaseAddress->QuadPart >> PAGE_SHIFT; @@ -425,8 +425,7 @@ MmPapAllocatePagesInRange ( else { /* Check if this is a fixed allocation */ - BaseAddress.QuadPart = (Attributes & BL_MM_DESCRIPTOR_REQUIRES_FIXED_FLAG) ? - *PhysicalAddress : 0; + BaseAddress.QuadPart = (Attributes & BlMemoryFixed) ? *PhysicalAddress : 0; /* Allocate the pages */ Status = MmPapAllocatePhysicalPagesInRange(&BaseAddress, diff --git a/reactos/boot/environ/lib/platform/display.c b/reactos/boot/environ/lib/platform/display.c index fdf33634415..86d86fa59e4 100644 --- a/reactos/boot/environ/lib/platform/display.c +++ b/reactos/boot/environ/lib/platform/display.c @@ -120,6 +120,12 @@ typedef struct _BL_TEXT_CONSOLE_VTABLE PCONSOLE_WRITE_TEXT WriteText; } BL_TEXT_CONSOLE_VTABLE, *PBL_TEXT_CONSOLE_VTABLE; +typedef struct _BL_GRAPHICS_CONSOLE_VTABLE +{ + BL_TEXT_CONSOLE_VTABLE Text; + /// more for graphics /// +} BL_GRAPHICS_CONSOLE_VTABLE, *PBL_GRAPHICS_CONSOLE_VTABLE; + typedef struct _BL_TEXT_CONSOLE { PBL_TEXT_CONSOLE_VTABLE Callbacks; @@ -131,6 +137,36 @@ typedef struct _BL_TEXT_CONSOLE EFI_SIMPLE_TEXT_OUTPUT_MODE OldMode; } BL_TEXT_CONSOLE, *PBL_TEXT_CONSOLE; +typedef enum _BL_GRAPHICS_CONSOLE_TYPE +{ + BlGopConsole, + BlUgaConsole +} BL_GRAPHICS_CONSOLE_TYPE; + +typedef struct _BL_GRAPHICS_CONSOLE +{ + BL_TEXT_CONSOLE TextConsole; + + BL_DISPLAY_MODE DisplayMode; + + ULONG PixelDepth; + + ULONG FgColor; + ULONG BgColor; + + BL_DISPLAY_MODE OldDisplayMode; + ULONG OldPixelDepth; + + EFI_HANDLE Handle; + BL_GRAPHICS_CONSOLE_TYPE Type; + EFI_GRAPHICS_OUTPUT_PROTOCOL* Protocol; + PVOID FrameBuffer; + ULONG FrameBufferSize; + ULONG PixelsPerScanLine; + ULONG Mode; + ULONG OldMode; +} BL_GRAPHICS_CONSOLE, *PBL_GRAPHICS_CONSOLE; + PVOID BfiCachedStrikeData; LIST_ENTRY BfiDeferredListHead; LIST_ENTRY BfiFontFileListHead; @@ -144,6 +180,7 @@ BL_DISPLAY_MODE ConsoleGraphicalResolutionList[3] = {800, 600, 800}, {1024, 600, 1024} }; +ULONG ConsoleGraphicalResolutionListSize = RTL_NUMBER_OF(ConsoleGraphicalResolutionList); BL_DISPLAY_MODE ConsoleTextResolutionList[1] = { @@ -211,6 +248,11 @@ BL_TEXT_CONSOLE_VTABLE ConsoleTextLocalVtbl = ConsoleTextLocalWriteText }; +BL_GRAPHICS_CONSOLE_VTABLE ConsoleGraphicalVtbl = +{ + {NULL}, +}; + PVOID DspRemoteInputConsole; PVOID DspTextConsole; PVOID DspGraphicalConsole; @@ -722,6 +764,269 @@ ConsoleFirmwareTextOpen ( return STATUS_SUCCESS; } +NTSTATUS +ConsoleEfiUgaOpen ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole + ) +{ + EarlyPrint(L"UGA not implemented\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +ConsoleEfiGopGetGraphicalFormat ( + _In_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeInfo, + _Out_ PULONG PixelDepth + ) +{ + /* Convert the format to depth */ + if (ModeInfo->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) + { + *PixelDepth = 32; + return STATUS_SUCCESS; + } + if (ModeInfo->PixelFormat == PixelBitMask) + { + *PixelDepth = 24; + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + +BOOLEAN +ConsoleEfiGopIsPixelFormatSupported ( + _In_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode + ) +{ + BOOLEAN Supported; + EFI_PIXEL_BITMASK PixelMask; + + Supported = FALSE; + + /* Check if it's simple BGR8 */ + if (Mode->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) + { + Supported = TRUE; + } + else + { + /* Otherwise, we can check if it's a masked format */ + if (Mode->PixelFormat == PixelBitMask) + { + /* Check if the masked format is BGR8 */ + PixelMask.BlueMask = 0xFF; + PixelMask.GreenMask = 0xFF00; + PixelMask.RedMask = 0xFF0000; + PixelMask.ReservedMask = 0; + if (RtlEqualMemory(&Mode->PixelInformation, + &PixelMask, + sizeof(PixelMask))) + { + Supported = TRUE; + } + } + } + + /* Return if the format was supported */ + return Supported; +} + +#define BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG 0x01 +#define BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG 0x02 + +NTSTATUS +ConsoleEfiGopFindModeFromAllowed ( + _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopProtocol, + _In_ PBL_DISPLAY_MODE SupportedModes, + _In_ ULONG MaximumIndex, + _Out_ PULONG SupportedMode + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +VOID +ConsoleEfiUgaClose ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole + ) +{ + return; +} + +VOID +ConsoleEfiGopClose ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole + ) +{ + ULONG OldMode; + + /* Did we switch modes when we turned on the console? */ + OldMode = GraphicsConsole->OldMode; + if (GraphicsConsole->Mode != OldMode) + { + /* Restore the old mode and reset the OEM bitmap in ACPI */ + EfiGopSetMode(GraphicsConsole->Protocol, OldMode); + //BlDisplayInvalidateOemBitmap(); + } + + /* Close the GOP protocol */ + EfiCloseProtocol(GraphicsConsole->Handle, + &EfiGraphicsOutputProtocol); +} + +VOID +ConsoleFirmwareGraphicalClose ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole + ) +{ + /* Call the correct close routine based on the console mode */ + if (GraphicsConsole->Type == BlUgaConsole) + { + ConsoleEfiUgaClose(GraphicsConsole); + } + else + { + ConsoleEfiGopClose(GraphicsConsole); + } + +} +NTSTATUS +ConsoleEfiGopOpen ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole + ) +{ + NTSTATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GopProtocol; + ULONG Mode, PixelDepth; + UINTN CurrentMode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInformation; + BOOLEAN CurrentModeOk; + + /* Open a handle to GOP */ + Status = EfiOpenProtocol(GraphicsConsole->Handle, + &EfiGraphicsOutputProtocol, + (PVOID*)&GopProtocol); + if (!NT_SUCCESS(Status)) + { + return STATUS_NOT_SUPPORTED; + } + + /* Get the current mode */ + Status = EfiGopGetCurrentMode(GopProtocol, &CurrentMode, &ModeInformation); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + Mode = CurrentMode; + + /* Check if any custom BCD options were provided */ + if (ConsoleGraphicalResolutionListFlags & + (BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG | + BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG)) + { + /* We'll have to find a mode */ + CurrentModeOk = FALSE; + } + else + { + /* Then we should be in the default mode, check if the pixel format is OK */ + CurrentModeOk = ConsoleEfiGopIsPixelFormatSupported(&ModeInformation); + } + + /* Is the mode/format OK? */ + if (!CurrentModeOk) + { + /* Nope -- we'll have to go find one */ + Status = ConsoleEfiGopFindModeFromAllowed(GopProtocol, + ConsoleGraphicalResolutionList, + ConsoleGraphicalResolutionListSize, + &Mode); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + } + + /* Store mode information */ + GraphicsConsole->Protocol = GopProtocol; + GraphicsConsole->Mode = Mode; + GraphicsConsole->OldMode = CurrentMode; + + /* Get format information */ + Status = ConsoleEfiGopGetGraphicalFormat(&ModeInformation, &PixelDepth); + if (NT_SUCCESS(Status)) + { + /* Store it */ + GraphicsConsole->OldDisplayMode.HRes = ModeInformation.HorizontalResolution; + GraphicsConsole->OldDisplayMode.VRes = ModeInformation.VerticalResolution; + GraphicsConsole->OldDisplayMode.HRes2 = ModeInformation.PixelsPerScanLine; + GraphicsConsole->PixelDepth = PixelDepth; + return STATUS_SUCCESS; + } + +Quickie: + /* We failed, close the protocol and return the failure code */ + EfiCloseProtocol(GraphicsConsole->Handle, &EfiGraphicsOutputProtocol); + return Status; +} + +NTSTATUS +ConsoleEfiGraphicalOpenProtocol ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole, + _In_ BL_GRAPHICS_CONSOLE_TYPE Type + ) +{ + ULONG HandleIndex, HandleCount; + EFI_HANDLE* HandleArray; + EFI_HANDLE Handle; + NTSTATUS Status; + PVOID Interface; + + /* Find a device handle that implements either GOP or UGA */ + HandleCount = 0; + HandleArray = NULL; + Status = EfiLocateHandleBuffer(ByProtocol, + (Type == BlGopConsole) ? + &EfiGraphicsOutputProtocol : + &EfiUgaDrawProtocol, + &HandleCount, + &HandleArray); + if (!NT_SUCCESS(Status)) + { + /* Nothing supports this (no video card?) */ + return STATUS_UNSUCCESSFUL; + } + + /* Scan through the handles we received */ + for (HandleIndex = 0; HandleCount < HandleIndex; HandleIndex++) + { + /* Try to open each one */ + GraphicsConsole->Handle = HandleArray[HandleIndex]; + Handle = HandleArray[HandleIndex]; + if (NT_SUCCESS(EfiOpenProtocol(Handle, + &EfiDevicePathProtocol, + &Interface))) + { + /* Test worked, close the protocol */ + EfiCloseProtocol(Handle, &EfiDevicePathProtocol); + + /* Now open the real protocol we want, either UGA or GOP */ + Status = Type ? ConsoleEfiUgaOpen(GraphicsConsole) : + ConsoleEfiGopOpen(GraphicsConsole); + if (NT_SUCCESS(Status)) + { + /* It worked -- store the type of console this is */ + GraphicsConsole->Type = Type; + return STATUS_SUCCESS; + } + } + } + + /* We failed to find a working GOP/UGA protocol provider */ + return STATUS_UNSUCCESSFUL; +} + NTSTATUS ConsoleTextLocalDestruct ( _In_ struct _BL_TEXT_CONSOLE* Console @@ -801,7 +1106,7 @@ DsppGraphicsDisabledByBcd ( ) { //EarlyPrint(L"Disabling graphics\n"); - return TRUE; + return FALSE; } NTSTATUS @@ -859,6 +1164,177 @@ ConsoleTextLocalConstruct ( return STATUS_SUCCESS; } +NTSTATUS +ConsoleEfiUgaSetResolution ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole, + _In_ PBL_DISPLAY_MODE DisplayMode, + _In_ ULONG DisplayModeCount + ) +{ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +ConsoleEfiGopEnable ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole + ) +{ + PVOID FrameBuffer; + UINTN CurrentMode, Dummy; + ULONG Mode, PixelDepth; + UINTN FrameBufferSize; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInformation; + EFI_GRAPHICS_OUTPUT_PROTOCOL* Protocol; + NTSTATUS Status; + PHYSICAL_ADDRESS FrameBufferPhysical; + + /* Capture the current mode and protocol */ + Mode = GraphicsConsole->Mode; + Protocol = GraphicsConsole->Protocol; + + /* Get the current mode and its information */ + Status = EfiGopGetCurrentMode(Protocol, &CurrentMode, &ModeInformation); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* Check if we're not in the mode we should be */ + if (CurrentMode != Mode) + { + /* Switch modes */ + Status = EfiGopSetMode(Protocol, Mode); + if (Status < 0) + { + return Status; + } + + /* Reset the OEM bitmap and get the new more information */ +// BlDisplayInvalidateOemBitmap(); + EfiGopGetCurrentMode(Protocol, &Dummy, &ModeInformation); + } + + /* Get the pixel depth for this mode */ + Status = ConsoleEfiGopGetGraphicalFormat(&ModeInformation, &PixelDepth); + if (NT_SUCCESS(Status)) + { + /* Get the framebuffer for this mode */ + EfiGopGetFrameBuffer(Protocol, &FrameBufferPhysical, &FrameBufferSize); + + /* Map the framebuffer, try as writeback first */ + FrameBuffer = NULL; + Status = BlMmMapPhysicalAddressEx(&FrameBuffer, + BlMemoryWriteBack, + FrameBufferSize, + FrameBufferPhysical); + if (!NT_SUCCESS(Status)) + { + /* That didn't work, so try uncached next */ + Status = BlMmMapPhysicalAddressEx(&FrameBuffer, + BlMemoryUncached, + FrameBufferSize, + FrameBufferPhysical); + } + } + + /* Check if getting all the required information worked out */ + if (NT_SUCCESS(Status)) + { + /* Capture the resolution, depth, and framebuffer information */ + GraphicsConsole->DisplayMode.HRes = ModeInformation.HorizontalResolution; + GraphicsConsole->DisplayMode.VRes = ModeInformation.VerticalResolution; + GraphicsConsole->DisplayMode.HRes2 = ModeInformation.PixelsPerScanLine; + GraphicsConsole->PixelDepth = PixelDepth; + GraphicsConsole->FrameBuffer = FrameBuffer; + GraphicsConsole->FrameBufferSize = FrameBufferSize; + GraphicsConsole->PixelsPerScanLine = ModeInformation.PixelsPerScanLine; + + /* All good */ + Status = STATUS_SUCCESS; + } + else if (CurrentMode != GraphicsConsole->Mode) + { + /* We failed seomewhere, reset the mode and the OEM bitmap back */ + EfiGopSetMode(Protocol, CurrentMode); + //BlDisplayInvalidateOemBitmap(); + } + + /* Return back to caller */ + return Status; +} + +NTSTATUS +ConsoleFirmwareGraphicalEnable ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole + ) +{ + NTSTATUS Status; + + /* Check what type of console this is */ + if (GraphicsConsole->Type == BlUgaConsole) + { + /* Handle UGA */ + Status = ConsoleEfiUgaSetResolution(GraphicsConsole, + &GraphicsConsole->DisplayMode, + 1); + } + else + { + /* Handle GOP */ + Status = ConsoleEfiGopEnable(GraphicsConsole); + } + + /* Return back to caller */ + return Status; +} + +NTSTATUS +ConsoleGraphicalConstruct ( + _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole + ) +{ + NTSTATUS Status; + + /* Create a text console */ + Status = ConsoleTextLocalConstruct(&GraphicsConsole->TextConsole, FALSE); + if (!NT_SUCCESS(Status)) + { + return Status; + } + + /* But overwrite its callbacks with ours */ + GraphicsConsole->TextConsole.Callbacks = &ConsoleGraphicalVtbl.Text; + + /* Try to create a GOP console */ + Status = ConsoleEfiGraphicalOpenProtocol(GraphicsConsole, BlGopConsole); + if (!NT_SUCCESS(Status)) + { + /* That failed, try an older EFI 1.02 UGA console */ + Status = ConsoleEfiGraphicalOpenProtocol(GraphicsConsole, BlUgaConsole); + if (!NT_SUCCESS(Status)) + { + /* That failed too, give up */ + ConsoleTextLocalDestruct(&GraphicsConsole->TextConsole); + return STATUS_UNSUCCESSFUL; + } + } + + /* Enable the console */ + Status = ConsoleFirmwareGraphicalEnable(GraphicsConsole); + if (!NT_SUCCESS(Status)) + { + /* Failed to enable it, undo everything */ + ConsoleFirmwareGraphicalClose(GraphicsConsole); + ConsoleTextLocalDestruct(&GraphicsConsole->TextConsole); + return STATUS_UNSUCCESSFUL; + } + + /* Save the graphics text color from the text mode text color */ + GraphicsConsole->FgColor = GraphicsConsole->TextConsole.State.FgColor; + GraphicsConsole->BgColor = GraphicsConsole->TextConsole.State.BgColor; + return STATUS_SUCCESS; +} + NTSTATUS DsppInitialize ( _In_ ULONG Flags @@ -869,7 +1345,7 @@ DsppInitialize ( NTSTATUS Status; PBL_DISPLAY_MODE DisplayMode; //ULONG GraphicsResolution; - PVOID GraphicsConsole; + PBL_GRAPHICS_CONSOLE GraphicsConsole; // PVOID RemoteConsole; PBL_TEXT_CONSOLE TextConsole; @@ -944,8 +1420,18 @@ DsppInitialize ( /* Do we need graphics mode after all? */ if (!NoGraphics) { - EarlyPrint(L"Display path not handled\n"); - return STATUS_NOT_SUPPORTED; + /* Yep -- go allocate it */ + GraphicsConsole = BlMmAllocateHeap(sizeof(*GraphicsConsole)); + if (GraphicsConsole) + { + /* Construct it */ + Status = ConsoleGraphicalConstruct(GraphicsConsole); + if (!NT_SUCCESS(Status)) + { + BlMmFreeHeap(GraphicsConsole); + GraphicsConsole = NULL; + } + } } /* Are we using something else than the default mode? */