1 /* 2 * COPYRIGHT: See COPYING.ARM in the top level directory 3 * PROJECT: ReactOS UEFI Boot Library 4 * FILE: boot/environ/lib/io/display/guicons.c 5 * PURPOSE: Boot Library GUI Console Routines 6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "bl.h" 12 13 /* DATA VARIABLES ************************************************************/ 14 15 BL_GRAPHICS_CONSOLE_VTABLE ConsoleGraphicalVtbl = 16 { 17 { 18 (PCONSOLE_DESTRUCT)ConsoleGraphicalDestruct, 19 (PCONSOLE_REINITIALIZE)ConsoleGraphicalReinitialize, 20 ConsoleTextBaseGetTextState, 21 (PCONSOLE_SET_TEXT_STATE)ConsoleGraphicalSetTextState, 22 NULL, // GetTextResolution 23 NULL, // SetTextResolution 24 (PCONSOLE_CLEAR_TEXT)ConsoleGraphicalClearText 25 }, 26 ConsoleGraphicalIsEnabled, 27 ConsoleGraphicalEnable, 28 NULL, 29 ConsoleGraphicalGetGraphicalResolution, 30 ConsoleGraphicalGetOriginalResolution, 31 NULL, 32 }; 33 34 /* FUNCTIONS *****************************************************************/ 35 36 NTSTATUS 37 ConsoleGraphicalSetTextState ( 38 _In_ PBL_GRAPHICS_CONSOLE Console, 39 _In_ ULONG Mask, 40 _In_ PBL_DISPLAY_STATE TextState 41 ) 42 { 43 /* Is the text console active? */ 44 if (Console->TextConsole.Active) 45 { 46 /* Let it handle that */ 47 return ConsoleFirmwareTextSetState(&Console->TextConsole, 48 Mask, 49 TextState); 50 } 51 52 /* Not yet */ 53 EfiPrintf(L"FFX set not implemented\r\n"); 54 return STATUS_NOT_IMPLEMENTED; 55 } 56 57 NTSTATUS 58 ConsoleGraphicalConstruct ( 59 _In_ PBL_GRAPHICS_CONSOLE GraphicsConsole 60 ) 61 { 62 NTSTATUS Status; 63 64 /* Create a text console */ 65 Status = ConsoleTextLocalConstruct(&GraphicsConsole->TextConsole, FALSE); 66 if (!NT_SUCCESS(Status)) 67 { 68 EfiPrintf(L"Text failed: %lx\r\n", Status); 69 return Status; 70 } 71 72 /* But overwrite its callbacks with ours */ 73 GraphicsConsole->TextConsole.Callbacks = &ConsoleGraphicalVtbl.Text; 74 75 /* Try to create a GOP console */ 76 Status = ConsoleEfiGraphicalOpenProtocol(GraphicsConsole, BlGopConsole); 77 if (!NT_SUCCESS(Status)) 78 { 79 /* That failed, try an older EFI 1.02 UGA console */ 80 EfiPrintf(L"GOP open failed!\r\n", Status); 81 Status = ConsoleEfiGraphicalOpenProtocol(GraphicsConsole, BlUgaConsole); 82 if (!NT_SUCCESS(Status)) 83 { 84 /* That failed too, give up */ 85 EfiPrintf(L"UGA failed!\r\n", Status); 86 ConsoleTextLocalDestruct(&GraphicsConsole->TextConsole); 87 return STATUS_UNSUCCESSFUL; 88 } 89 } 90 91 /* Enable the console */ 92 Status = ConsoleFirmwareGraphicalEnable(GraphicsConsole); 93 if (!NT_SUCCESS(Status)) 94 { 95 /* Failed to enable it, undo everything */ 96 EfiPrintf(L"Enable failed\r\n"); 97 ConsoleFirmwareGraphicalClose(GraphicsConsole); 98 ConsoleTextLocalDestruct(&GraphicsConsole->TextConsole); 99 return STATUS_UNSUCCESSFUL; 100 } 101 102 /* Save the graphics text color from the text mode text color */ 103 GraphicsConsole->FgColor = GraphicsConsole->TextConsole.State.FgColor; 104 GraphicsConsole->BgColor = GraphicsConsole->TextConsole.State.BgColor; 105 return STATUS_SUCCESS; 106 } 107 108 VOID 109 ConsolepClearBuffer ( 110 _In_ PUCHAR FrameBuffer, 111 _In_ ULONG Width, 112 _In_ PUCHAR FillColor, 113 _In_ ULONG Height, 114 _In_ ULONG ScanlineWidth, 115 _In_ ULONG PixelDepth 116 ) 117 { 118 PUCHAR Scanline, Current, FrameBufferEnd, LineEnd; 119 ULONG LineBytes, WidthBytes, BytesPerPixel; 120 121 /* Get the BPP */ 122 BytesPerPixel = PixelDepth / 8; 123 124 /* Using that, calculate the size of a scan line */ 125 LineBytes = ScanlineWidth * BytesPerPixel; 126 127 /* And the size of line we'll have to clear */ 128 WidthBytes = Width * BytesPerPixel; 129 130 /* Allocate a scanline */ 131 Scanline = BlMmAllocateHeap(WidthBytes); 132 if (Scanline) 133 { 134 /* For each remaining pixel on the scanline */ 135 Current = Scanline; 136 while (Width--) 137 { 138 /* Copy in the fill color */ 139 RtlCopyMemory(Current, FillColor, BytesPerPixel); 140 Current += BytesPerPixel; 141 } 142 143 /* For each scanline in the frame buffer */ 144 while (Height--) 145 { 146 /* Copy our constructed scanline */ 147 RtlCopyMemory(FrameBuffer, Scanline, WidthBytes); 148 FrameBuffer += LineBytes; 149 } 150 } 151 else 152 { 153 FrameBufferEnd = FrameBuffer + Height * LineBytes; 154 ScanlineWidth = BytesPerPixel * (ScanlineWidth - Width); 155 while (FrameBuffer != FrameBufferEnd) 156 { 157 if (FrameBuffer != (FrameBuffer + WidthBytes)) 158 { 159 LineEnd = FrameBuffer + WidthBytes; 160 do 161 { 162 RtlCopyMemory(FrameBuffer, FillColor, BytesPerPixel); 163 FrameBuffer += BytesPerPixel; 164 } 165 while (FrameBuffer != LineEnd); 166 } 167 168 FrameBuffer += ScanlineWidth; 169 } 170 } 171 } 172 173 NTSTATUS 174 ConsolepConvertColorToPixel ( 175 _In_ BL_COLOR Color, 176 _Out_ PUCHAR Pixel 177 ) 178 { 179 NTSTATUS Status; 180 181 /* Assume success */ 182 Status = STATUS_SUCCESS; 183 184 /* Convert the color to a pixel value */ 185 switch (Color) 186 { 187 case Black: 188 Pixel[1] = 0; 189 Pixel[2] = 0; 190 Pixel[0] = 0; 191 break; 192 case Blue: 193 Pixel[1] = 0; 194 Pixel[2] = 0; 195 Pixel[0] = 0x7F; 196 break; 197 case Green: 198 Pixel[1] = 0x7F; 199 Pixel[2] = 0; 200 Pixel[0] = 0; 201 break; 202 case Cyan: 203 Pixel[1] = 0x7F; 204 Pixel[2] = 0; 205 Pixel[0] = 0x7F; 206 break; 207 case Red: 208 Pixel[1] = 0; 209 Pixel[2] = 0x7F; 210 Pixel[0] = 0x7F; 211 break; 212 case Magenta: 213 Pixel[1] = 0; 214 Pixel[2] = 0x7F; 215 Pixel[0] = 0x7F; 216 break; 217 case Brown: 218 Pixel[1] = 0x3F; 219 Pixel[2] = 0x7F; 220 Pixel[0] = 0; 221 break; 222 case LtGray: 223 Pixel[1] = 0xBFu; 224 Pixel[2] = 0xBFu; 225 *Pixel = 0xBFu; 226 break; 227 case Gray: 228 Pixel[1] = 0x7F; 229 Pixel[2] = 0x7F; 230 Pixel[0] = 0x7F; 231 break; 232 case LtBlue: 233 Pixel[1] = 0; 234 Pixel[2] = 0; 235 Pixel[0] = 0xFF; 236 break; 237 case LtGreen: 238 Pixel[1] = 0xFF; 239 Pixel[2] = 0; 240 Pixel[0] = 0; 241 break; 242 case LtCyan: 243 Pixel[1] = 0xFF; 244 Pixel[2] = 0; 245 Pixel[0] = 0xFF; 246 break; 247 case LtRed: 248 Pixel[1] = 0; 249 Pixel[2] = 0xFF; 250 Pixel[0] = 0; 251 break; 252 case LtMagenta: 253 Pixel[1] = 0; 254 Pixel[2] = 0xFF; 255 Pixel[0] = 0xFF; 256 break; 257 case Yellow: 258 Pixel[1] = 0xFF; 259 Pixel[2] = 0xFF; 260 Pixel[0] = 0; 261 break; 262 case White: 263 Pixel[1] = 0xFF; 264 Pixel[2] = 0xFF; 265 Pixel[0] = 0xFF; 266 break; 267 default: 268 Status = STATUS_INVALID_PARAMETER; 269 break; 270 } 271 return Status; 272 } 273 274 NTSTATUS 275 ConsoleGraphicalClearPixels ( 276 _In_ PBL_GRAPHICS_CONSOLE Console, 277 _In_ ULONG Color 278 ) 279 { 280 NTSTATUS Status; 281 282 /* Check if the text console is active */ 283 if (Console->TextConsole.Active) 284 { 285 /* We shouldn't be here */ 286 Status = STATUS_UNSUCCESSFUL; 287 } 288 else 289 { 290 /* Clear it in graphics mode */ 291 Status = ConsoleFirmwareGraphicalClear(Console, Color); 292 } 293 294 /* All good */ 295 return Status; 296 } 297 298 NTSTATUS 299 ConsoleGraphicalClearText ( 300 _In_ PBL_GRAPHICS_CONSOLE Console, 301 _In_ BOOLEAN LineOnly 302 ) 303 { 304 /* Is the text console active? */ 305 if (Console->TextConsole.Active) 306 { 307 /* Let firmware clear do it */ 308 return ConsoleFirmwareTextClear(&Console->TextConsole, LineOnly); 309 } 310 311 /* Are we clearing a line only? */ 312 if (LineOnly) 313 { 314 return BfClearToEndOfLine(Console); 315 } 316 317 /* Nope -- the whole screen */ 318 return BfClearScreen(Console); 319 } 320 321 BOOLEAN 322 ConsoleGraphicalIsEnabled ( 323 _In_ PBL_GRAPHICS_CONSOLE Console 324 ) 325 { 326 /* Is the text console active? If so, the graphics console isn't */ 327 return !Console->TextConsole.Active; 328 } 329 330 VOID 331 ConsoleGraphicalDestruct ( 332 _In_ PBL_GRAPHICS_CONSOLE Console 333 ) 334 { 335 /* Is the text console active? */ 336 if (Console->TextConsole.Active) 337 { 338 /* Disable it */ 339 ConsoleFirmwareGraphicalDisable(Console); 340 } 341 342 /* Close the firmware protocols */ 343 ConsoleFirmwareGraphicalClose(Console); 344 345 /* Destroy the console object */ 346 ConsoleTextLocalDestruct(&Console->TextConsole); 347 } 348 349 NTSTATUS 350 ConsoleGraphicalReinitialize ( 351 _In_ PBL_GRAPHICS_CONSOLE Console 352 ) 353 { 354 /* Is the text console active? */ 355 if (Console->TextConsole.Active) 356 { 357 /* Reinitialize it */ 358 ConsoleTextLocalReinitialize(&Console->TextConsole); 359 } 360 361 /* Disable the graphics console */ 362 ConsoleFirmwareGraphicalDisable(Console); 363 364 /* Then bring it back again */ 365 return ConsoleFirmwareGraphicalEnable(Console); 366 } 367 368 NTSTATUS 369 ConsoleGraphicalEnable ( 370 _In_ PBL_GRAPHICS_CONSOLE Console, 371 _In_ BOOLEAN Enable 372 ) 373 { 374 BOOLEAN Active; 375 NTSTATUS Status; 376 377 /* The text mode console state should be the opposite of what we want to do */ 378 Active = Console->TextConsole.Active; 379 if (Active == Enable) 380 { 381 /* Are we trying to enable graphics? */ 382 if (Enable) 383 { 384 /* Enable the console */ 385 Status = ConsoleFirmwareGraphicalEnable(Console); 386 if (NT_SUCCESS(Status)) 387 { 388 return Status; 389 } 390 391 /* Is the text console active? */ 392 if (Console->TextConsole.Active) 393 { 394 /* Turn it off */ 395 ConsoleFirmwareTextClose(&Console->TextConsole); 396 Console->TextConsole.Active = FALSE; 397 } 398 399 /* Preserve the text colors */ 400 Console->FgColor = Console->TextConsole.State.FgColor; 401 Console->BgColor = Console->TextConsole.State.BgColor; 402 } 403 else 404 { 405 /* We are turning off graphics -- is the text console active? */ 406 if (Active != TRUE) 407 { 408 /* It isn't, so let's turn it on */ 409 Status = ConsoleFirmwareTextOpen(&Console->TextConsole); 410 if (!NT_SUCCESS(Status)) 411 { 412 return Status; 413 } 414 415 /* Remember that it's on */ 416 Console->TextConsole.Active = TRUE; 417 } 418 419 /* Disable the graphics console */ 420 ConsoleFirmwareGraphicalDisable(Console); 421 } 422 } 423 424 /* All good */ 425 return STATUS_SUCCESS; 426 } 427 428 NTSTATUS 429 ConsoleGraphicalGetGraphicalResolution ( 430 _In_ PBL_GRAPHICS_CONSOLE Console, 431 _In_ PBL_DISPLAY_MODE DisplayMode 432 ) 433 { 434 /* Is the text console active? */ 435 if (Console->TextConsole.Active) 436 { 437 /* There's no graphics resolution then */ 438 return STATUS_UNSUCCESSFUL; 439 } 440 441 /* Return the current display mode */ 442 *DisplayMode = Console->DisplayMode; 443 return STATUS_SUCCESS; 444 } 445 446 NTSTATUS 447 ConsoleGraphicalGetOriginalResolution ( 448 _In_ PBL_GRAPHICS_CONSOLE Console, 449 _In_ PBL_DISPLAY_MODE DisplayMode 450 ) 451 { 452 /* Is the text console active? */ 453 if (Console->TextConsole.Active) 454 { 455 /* There's no graphics resolution then */ 456 return STATUS_UNSUCCESSFUL; 457 } 458 459 /* Return the current display mode */ 460 *DisplayMode = Console->OldDisplayMode; 461 return STATUS_SUCCESS; 462 } 463