1 /* 2 * COPYRIGHT: See COPYING.ARM in the top level directory 3 * PROJECT: ReactOS UEFI Boot Library 4 * FILE: boot/environ/lib/io/display/efi/gop.c 5 * PURPOSE: Boot Library EFI GOP Routines 6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "bl.h" 12 13 /* DATA VARIABLES ************************************************************/ 14 15 /* FUNCTIONS *****************************************************************/ 16 17 NTSTATUS 18 ConsoleEfiGopGetGraphicalFormat ( 19 _In_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeInfo, 20 _Out_ PULONG PixelDepth 21 ) 22 { 23 /* Convert the format to depth */ 24 if (ModeInfo->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) 25 { 26 *PixelDepth = 32; 27 return STATUS_SUCCESS; 28 } 29 if (ModeInfo->PixelFormat == PixelBitMask) 30 { 31 *PixelDepth = 24; 32 return STATUS_SUCCESS; 33 } 34 return STATUS_UNSUCCESSFUL; 35 } 36 37 BOOLEAN 38 ConsoleEfiGopIsPixelFormatSupported ( 39 _In_ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Mode 40 ) 41 { 42 BOOLEAN Supported; 43 EFI_PIXEL_BITMASK PixelMask; 44 45 Supported = FALSE; 46 47 /* Check if it's simple BGR8 */ 48 if (Mode->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) 49 { 50 Supported = TRUE; 51 } 52 else 53 { 54 /* Otherwise, we can check if it's a masked format */ 55 if (Mode->PixelFormat == PixelBitMask) 56 { 57 /* Check if the masked format is BGR8 */ 58 PixelMask.BlueMask = 0xFF; 59 PixelMask.GreenMask = 0xFF00; 60 PixelMask.RedMask = 0xFF0000; 61 PixelMask.ReservedMask = 0; 62 if (RtlEqualMemory(&Mode->PixelInformation, 63 &PixelMask, 64 sizeof(PixelMask))) 65 { 66 Supported = TRUE; 67 } 68 } 69 } 70 71 /* Return if the format was supported */ 72 return Supported; 73 } 74 75 76 NTSTATUS 77 ConsoleEfiGopFindModeFromAllowed ( 78 _In_ EFI_GRAPHICS_OUTPUT_PROTOCOL *GopProtocol, 79 _In_ PBL_DISPLAY_MODE SupportedModes, 80 _In_ ULONG MaximumIndex, 81 _Out_ PULONG SupportedMode 82 ) 83 { 84 return STATUS_NOT_IMPLEMENTED; 85 } 86 87 NTSTATUS 88 ConsoleEfiGopEnable ( 89 _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole 90 ) 91 { 92 PVOID FrameBuffer; 93 UINTN CurrentMode, Dummy; 94 ULONG Mode, PixelDepth; 95 UINTN FrameBufferSize; 96 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInformation; 97 EFI_GRAPHICS_OUTPUT_PROTOCOL* Protocol; 98 NTSTATUS Status; 99 PHYSICAL_ADDRESS FrameBufferPhysical; 100 101 /* Capture the current mode and protocol */ 102 Mode = GraphicsConsole->Mode; 103 Protocol = GraphicsConsole->Protocol; 104 105 /* Get the current mode and its information */ 106 Status = EfiGopGetCurrentMode(Protocol, &CurrentMode, &ModeInformation); 107 if (!NT_SUCCESS(Status)) 108 { 109 return Status; 110 } 111 112 /* Check if we're not in the mode we should be */ 113 if (CurrentMode != Mode) 114 { 115 /* Switch modes */ 116 Status = EfiGopSetMode(Protocol, Mode); 117 if (!NT_SUCCESS(Status)) 118 { 119 return Status; 120 } 121 122 /* Reset the OEM bitmap and get the new more information */ 123 BlDisplayInvalidateOemBitmap(); 124 EfiGopGetCurrentMode(Protocol, &Dummy, &ModeInformation); 125 } 126 127 /* Get the pixel depth for this mode */ 128 Status = ConsoleEfiGopGetGraphicalFormat(&ModeInformation, &PixelDepth); 129 if (NT_SUCCESS(Status)) 130 { 131 /* Get the framebuffer for this mode */ 132 EfiGopGetFrameBuffer(Protocol, &FrameBufferPhysical, &FrameBufferSize); 133 134 /* Map the framebuffer, try as writeback first */ 135 FrameBuffer = NULL; 136 Status = BlMmMapPhysicalAddressEx(&FrameBuffer, 137 BlMemoryWriteBack, 138 FrameBufferSize, 139 FrameBufferPhysical); 140 if (!NT_SUCCESS(Status)) 141 { 142 /* That didn't work, so try uncached next */ 143 Status = BlMmMapPhysicalAddressEx(&FrameBuffer, 144 BlMemoryUncached, 145 FrameBufferSize, 146 FrameBufferPhysical); 147 } 148 } 149 150 /* Check if getting all the required information worked out */ 151 if (NT_SUCCESS(Status)) 152 { 153 /* Capture the resolution, depth, and framebuffer information */ 154 GraphicsConsole->DisplayMode.HRes = ModeInformation.HorizontalResolution; 155 GraphicsConsole->DisplayMode.VRes = ModeInformation.VerticalResolution; 156 GraphicsConsole->DisplayMode.HRes2 = ModeInformation.PixelsPerScanLine; 157 GraphicsConsole->PixelDepth = PixelDepth; 158 GraphicsConsole->FrameBuffer = FrameBuffer; 159 GraphicsConsole->FrameBufferSize = FrameBufferSize; 160 GraphicsConsole->PixelsPerScanLine = ModeInformation.PixelsPerScanLine; 161 162 /* All good */ 163 Status = STATUS_SUCCESS; 164 } 165 else if (CurrentMode != GraphicsConsole->Mode) 166 { 167 /* We failed somewhere, reset the mode and the OEM bitmap back */ 168 EfiGopSetMode(Protocol, CurrentMode); 169 BlDisplayInvalidateOemBitmap(); 170 } 171 172 /* Return back to caller */ 173 return Status; 174 } 175 176 VOID 177 ConsoleEfiGopClose ( 178 _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole 179 ) 180 { 181 ULONG OldMode; 182 183 /* Did we switch modes when we turned on the console? */ 184 OldMode = GraphicsConsole->OldMode; 185 if (GraphicsConsole->Mode != OldMode) 186 { 187 /* Restore the old mode and reset the OEM bitmap in ACPI */ 188 EfiGopSetMode(GraphicsConsole->Protocol, OldMode); 189 BlDisplayInvalidateOemBitmap(); 190 } 191 192 /* Close the GOP protocol */ 193 EfiCloseProtocol(GraphicsConsole->Handle, 194 &EfiGraphicsOutputProtocol); 195 } 196 197 NTSTATUS 198 ConsoleEfiGopOpen ( 199 _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole 200 ) 201 { 202 NTSTATUS Status; 203 EFI_GRAPHICS_OUTPUT_PROTOCOL *GopProtocol; 204 ULONG Mode, PixelDepth; 205 UINTN CurrentMode; 206 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInformation; 207 BOOLEAN CurrentModeOk; 208 209 /* Open a handle to GOP */ 210 Status = EfiOpenProtocol(GraphicsConsole->Handle, 211 &EfiGraphicsOutputProtocol, 212 (PVOID*)&GopProtocol); 213 if (!NT_SUCCESS(Status)) 214 { 215 EfiPrintf(L"GOP OPEN failed: %lx\r\n", Status); 216 return STATUS_NOT_SUPPORTED; 217 } 218 219 /* Get the current mode */ 220 Status = EfiGopGetCurrentMode(GopProtocol, &CurrentMode, &ModeInformation); 221 if (!NT_SUCCESS(Status)) 222 { 223 EfiPrintf(L"GOP mode failed: %lx\r\n", Status); 224 goto Quickie; 225 } 226 227 Mode = CurrentMode; 228 229 /* Check if any custom BCD options were provided */ 230 if (ConsoleGraphicalResolutionListFlags & 231 (BL_DISPLAY_GRAPHICS_FORCED_VIDEO_MODE_FLAG | 232 BL_DISPLAY_GRAPHICS_FORCED_HIGH_RES_MODE_FLAG)) 233 { 234 /* We'll have to find a mode */ 235 CurrentModeOk = FALSE; 236 } 237 else 238 { 239 /* Then we should be in the default mode, check if the pixel format is OK */ 240 CurrentModeOk = ConsoleEfiGopIsPixelFormatSupported(&ModeInformation); 241 } 242 243 /* Is the mode/format OK? */ 244 if (!CurrentModeOk) 245 { 246 /* Nope -- we'll have to go find one */ 247 Status = ConsoleEfiGopFindModeFromAllowed(GopProtocol, 248 ConsoleGraphicalResolutionList, 249 ConsoleGraphicalResolutionListSize, 250 &Mode); 251 if (!NT_SUCCESS(Status)) 252 { 253 goto Quickie; 254 } 255 } 256 257 /* Store mode information */ 258 GraphicsConsole->Protocol = GopProtocol; 259 GraphicsConsole->Mode = Mode; 260 GraphicsConsole->OldMode = CurrentMode; 261 262 /* Get format information */ 263 Status = ConsoleEfiGopGetGraphicalFormat(&ModeInformation, &PixelDepth); 264 if (NT_SUCCESS(Status)) 265 { 266 /* Store it */ 267 GraphicsConsole->OldDisplayMode.HRes = ModeInformation.HorizontalResolution; 268 GraphicsConsole->OldDisplayMode.VRes = ModeInformation.VerticalResolution; 269 GraphicsConsole->OldDisplayMode.HRes2 = ModeInformation.PixelsPerScanLine; 270 GraphicsConsole->PixelDepth = PixelDepth; 271 return STATUS_SUCCESS; 272 } 273 274 Quickie: 275 /* We failed, close the protocol and return the failure code */ 276 EfiPrintf(L"Get format failed: %lx\r\n", Status); 277 EfiCloseProtocol(GraphicsConsole->Handle, &EfiGraphicsOutputProtocol); 278 return Status; 279 } 280 281