[BOOTMGFW]
authorAlex Ionescu <aionescu@gmail.com>
Mon, 7 Sep 2015 17:35:59 +0000 (17:35 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 7 Sep 2015 17:35:59 +0000 (17:35 +0000)
- 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
reactos/boot/environ/include/bl.h
reactos/boot/environ/include/efi/GraphicsOutput.h [new file with mode: 0644]
reactos/boot/environ/include/efi/UgaDraw.h [new file with mode: 0644]
reactos/boot/environ/lib/firmware/efi/firmware.c
reactos/boot/environ/lib/mm/descriptor.c
reactos/boot/environ/lib/mm/heapalloc.c
reactos/boot/environ/lib/mm/mm.c
reactos/boot/environ/lib/mm/pagealloc.c
reactos/boot/environ/lib/platform/display.c

index 1c700dd..2edc2ea 100644 (file)
@@ -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 *****************************************************************/
index da0456b..8621120 100644 (file)
@@ -26,6 +26,8 @@
 #include <Uefi.h>
 #include <DevicePath.h>
 #include <LoadedImage.h>
+#include <GraphicsOutput.h>
+#include <UgaDraw.h>
 
 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 (file)
index 0000000..a3432ce
--- /dev/null
@@ -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.<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.             
+
+**/
+
+#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 (file)
index 0000000..f501a6c
--- /dev/null
@@ -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.<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.
+
+**/
+
+#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
index 37a8e1b..2c4bb31 100644 (file)
@@ -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,
index 5157e1f..847efc0 100644 (file)
@@ -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;
     }
index 833a903..c5fe092 100644 (file)
@@ -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;
     };
index 7c3dcdf..4b51c74 100644 (file)
@@ -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,
index 5b97d50..17a2613 100644 (file)
@@ -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,
index fdf3363..86d86fa 100644 (file)
@@ -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? */