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
ConsoleGraphicalSetTextState(_In_ PBL_GRAPHICS_CONSOLE Console,_In_ ULONG Mask,_In_ PBL_DISPLAY_STATE TextState)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
ConsoleGraphicalConstruct(_In_ PBL_GRAPHICS_CONSOLE GraphicsConsole)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
ConsolepClearBuffer(_In_ PUCHAR FrameBuffer,_In_ ULONG Width,_In_ PUCHAR FillColor,_In_ ULONG Height,_In_ ULONG ScanlineWidth,_In_ ULONG PixelDepth)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
ConsolepConvertColorToPixel(_In_ BL_COLOR Color,_Out_ PUCHAR Pixel)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
ConsoleGraphicalClearPixels(_In_ PBL_GRAPHICS_CONSOLE Console,_In_ ULONG Color)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
ConsoleGraphicalClearText(_In_ PBL_GRAPHICS_CONSOLE Console,_In_ BOOLEAN LineOnly)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
ConsoleGraphicalIsEnabled(_In_ PBL_GRAPHICS_CONSOLE Console)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
ConsoleGraphicalDestruct(_In_ PBL_GRAPHICS_CONSOLE Console)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
ConsoleGraphicalReinitialize(_In_ PBL_GRAPHICS_CONSOLE Console)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
ConsoleGraphicalEnable(_In_ PBL_GRAPHICS_CONSOLE Console,_In_ BOOLEAN Enable)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
ConsoleGraphicalGetGraphicalResolution(_In_ PBL_GRAPHICS_CONSOLE Console,_In_ PBL_DISPLAY_MODE DisplayMode)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
ConsoleGraphicalGetOriginalResolution(_In_ PBL_GRAPHICS_CONSOLE Console,_In_ PBL_DISPLAY_MODE DisplayMode)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