OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcConsoleLib.c
Go to the documentation of this file.
1
16
18#include <Protocol/GraphicsOutput.h>
20#include <Protocol/SimpleTextOut.h>
21
22#include <Library/BaseMemoryLib.h>
23#include <Library/BaseOverflowLib.h>
24#include <Library/BaseLib.h>
25#include <Library/DebugLib.h>
26#include <Library/MemoryAllocationLib.h>
29#include <Library/OcMiscLib.h>
30#include <Library/UefiBootServicesTableLib.h>
31#include <Library/UefiRuntimeServicesTableLib.h>
32
33EFI_STATUS
35 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
36 IN UINT32 Width OPTIONAL,
37 IN UINT32 Height OPTIONAL,
38 IN UINT32 Bpp OPTIONAL
39 )
40{
41 EFI_STATUS Status;
42
43 UINT32 MaxMode;
44 UINT32 ModeIndex;
45 INT64 ModeNumber;
46 UINTN SizeOfInfo;
47 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
48 BOOLEAN SetMax;
49
50 SetMax = Width == 0 && Height == 0;
51
52 DEBUG ((
53 DEBUG_INFO,
54 "OCC: Requesting %ux%u@%u (max: %d) resolution, curr %u, total %u\n",
55 Width,
56 Height,
57 Bpp,
58 SetMax,
59 (UINT32)GraphicsOutput->Mode->Mode,
60 (UINT32)GraphicsOutput->Mode->MaxMode
61 ));
62
63 DEBUG ((
64 DEBUG_INFO,
65 "OCC: Current FB at 0x%LX (0x%X), format %d, res %ux%u scan %u\n",
66 GraphicsOutput->Mode->FrameBufferBase,
67 (UINT32)GraphicsOutput->Mode->FrameBufferSize,
68 GraphicsOutput->Mode->Info != NULL ? GraphicsOutput->Mode->Info->PixelFormat : -1,
69 GraphicsOutput->Mode->Info != NULL ? GraphicsOutput->Mode->Info->HorizontalResolution : 0,
70 GraphicsOutput->Mode->Info != NULL ? GraphicsOutput->Mode->Info->VerticalResolution : 0,
71 GraphicsOutput->Mode->Info != NULL ? GraphicsOutput->Mode->Info->PixelsPerScanLine : 0
72 ));
73
74 //
75 // Find the resolution we need.
76 //
77 ModeNumber = -1;
78 MaxMode = GraphicsOutput->Mode->MaxMode;
79 for (ModeIndex = 0; ModeIndex < MaxMode; ++ModeIndex) {
80 Status = GraphicsOutput->QueryMode (
81 GraphicsOutput,
82 ModeIndex,
83 &SizeOfInfo,
84 &Info
85 );
86
87 if (EFI_ERROR (Status)) {
88 DEBUG ((DEBUG_INFO, "OCC: Mode %u failure - %r\n", ModeIndex, Status));
89 continue;
90 }
91
92 DEBUG ((
93 DEBUG_INFO,
94 "OCC: Mode %u - %ux%u:%u\n",
95 ModeIndex,
96 Info->HorizontalResolution,
97 Info->VerticalResolution,
98 Info->PixelFormat
99 ));
100
101 if (!SetMax) {
102 //
103 // Custom resolution is requested.
104 //
105 if ( (Info->HorizontalResolution == Width)
106 && (Info->VerticalResolution == Height)
107 && ((Bpp == 0) || (Bpp == 24) || (Bpp == 32))
108 && ( (Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor)
109 || (Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor)
110 || ( (Info->PixelFormat == PixelBitMask)
111 && ( (Info->PixelInformation.RedMask == 0xFF000000U)
112 || (Info->PixelInformation.RedMask == 0xFF0000U)
113 || (Info->PixelInformation.RedMask == 0xFF00U)
114 || (Info->PixelInformation.RedMask == 0xFFU)))
115 || (Info->PixelFormat == PixelBltOnly)))
116 {
117 ModeNumber = ModeIndex;
118 FreePool (Info);
119 break;
120 }
121 } else if ( (Info->HorizontalResolution > Width)
122 || ((Info->HorizontalResolution == Width) && (Info->VerticalResolution > Height)))
123 {
124 Width = Info->HorizontalResolution;
125 Height = Info->VerticalResolution;
126 ModeNumber = ModeIndex;
127 }
128
129 FreePool (Info);
130 }
131
132 if (ModeNumber < 0) {
133 DEBUG ((DEBUG_WARN, "OCC: No compatible mode for %ux%u@%u (max: %u) resolution\n", Width, Height, Bpp, SetMax));
134 return EFI_NOT_FOUND;
135 }
136
137 if (ModeNumber == GraphicsOutput->Mode->Mode) {
138 DEBUG ((DEBUG_INFO, "OCC: Current mode matches desired mode %u\n", (UINT32)ModeNumber));
139 return EFI_ALREADY_STARTED;
140 }
141
142 //
143 // Current graphics mode is not set, or is not set to the mode found above.
144 // Set the new graphics mode.
145 //
146 DEBUG ((
147 DEBUG_INFO,
148 "OCC: Setting mode %u with %ux%u resolution\n",
149 (UINT32)ModeNumber,
150 Width,
151 Height
152 ));
153
154 Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32)ModeNumber);
155 if (EFI_ERROR (Status)) {
156 DEBUG ((
157 DEBUG_WARN,
158 "OCC: Failed to set mode %u (prev %u) with %ux%u resolution\n",
159 (UINT32)ModeNumber,
160 (UINT32)GraphicsOutput->Mode->Mode,
161 Width,
162 Height
163 ));
164 return Status;
165 }
166
167 DEBUG ((DEBUG_INFO, "OCC: Changed resolution mode to %u\n", (UINT32)GraphicsOutput->Mode->Mode));
168
169 return Status;
170}
171
172EFI_STATUS
174 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
175 IN UINT32 Width,
176 IN UINT32 Height
177 )
178{
179 EFI_STATUS Status;
180 UINT32 MaxMode;
181 UINT32 ModeIndex;
182 INT64 ModeNumber;
183 UINTN Columns;
184 UINTN Rows;
185 BOOLEAN SetMax;
186
187 SetMax = Width == 0 && Height == 0;
188
189 DEBUG ((
190 DEBUG_INFO,
191 "OCC: Requesting %ux%u (max: %d) console mode, curr %u, max %u\n",
192 Width,
193 Height,
194 SetMax,
195 (UINT32)TextOut->Mode->Mode,
196 (UINT32)TextOut->Mode->MaxMode
197 ));
198
199 //
200 // Find the resolution we need.
201 //
202 ModeNumber = -1;
203 MaxMode = TextOut->Mode->MaxMode;
204 for (ModeIndex = 0; ModeIndex < MaxMode; ++ModeIndex) {
205 Status = TextOut->QueryMode (
206 TextOut,
207 ModeIndex,
208 &Columns,
209 &Rows
210 );
211
212 if (EFI_ERROR (Status)) {
213 continue;
214 }
215
216 DEBUG ((
217 DEBUG_INFO,
218 "OCC: Mode %u - %ux%u\n",
219 ModeIndex,
220 (UINT32)Columns,
221 (UINT32)Rows
222 ));
223
224 if (!SetMax) {
225 //
226 // Custom mode is requested.
227 //
228 if ((Columns == Width) && (Rows == Height)) {
229 ModeNumber = ModeIndex;
230 break;
231 }
232 } else if ( ((UINT32)Columns > Width)
233 || (((UINT32)Columns == Width) && ((UINT32)Rows > Height)))
234 {
235 Width = (UINT32)Columns;
236 Height = (UINT32)Rows;
237 ModeNumber = ModeIndex;
238 }
239 }
240
241 if (ModeNumber < 0) {
242 DEBUG ((DEBUG_WARN, "OCC: No compatible mode for %ux%u (max: %u) console mode\n", Width, Height, SetMax));
243 return EFI_NOT_FOUND;
244 }
245
246 if (ModeNumber == TextOut->Mode->Mode) {
247 //
248 // This does not seem to affect systems anyhow, but for safety reasons
249 // we should refresh console mode after changing GOP resolution.
250 //
251 DEBUG ((
252 DEBUG_INFO,
253 "OCC: Current console mode matches desired mode %u, forcing update\n",
254 (UINT32)ModeNumber
255 ));
256 }
257
258 //
259 // Current graphics mode is not set, or is not set to the mode found above.
260 // Set the new graphics mode.
261 //
262 DEBUG ((
263 DEBUG_INFO,
264 "OCC: Setting mode %u (prev %u) with %ux%u console mode\n",
265 (UINT32)ModeNumber,
266 (UINT32)TextOut->Mode->Mode,
267 Width,
268 Height
269 ));
270
271 Status = TextOut->SetMode (TextOut, (UINTN)ModeNumber);
272 if (EFI_ERROR (Status)) {
273 DEBUG ((
274 DEBUG_WARN,
275 "OCC: Failed to set mode %u with %ux%u console mode\n",
276 (UINT32)ModeNumber,
277 Width,
278 Height
279 ));
280 return Status;
281 }
282
283 DEBUG ((DEBUG_INFO, "OCC: Changed console mode to %u\n", (UINT32)TextOut->Mode->Mode));
284
285 return EFI_SUCCESS;
286}
287
288EFI_STATUS
290 IN UINT32 Width OPTIONAL,
291 IN UINT32 Height OPTIONAL,
292 IN UINT32 Bpp OPTIONAL,
293 IN BOOLEAN Force
294 )
295{
296 EFI_STATUS Result;
297 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
298 OC_FORCE_RESOLUTION_PROTOCOL *OcForceResolution;
299
300 //
301 // Force resolution if specified.
302 //
303 if (Force) {
304 Result = gBS->LocateProtocol (
306 NULL,
307 (VOID **)&OcForceResolution
308 );
309
310 if (!EFI_ERROR (Result)) {
311 Result = OcForceResolution->SetResolution (OcForceResolution, Width, Height);
312 if (EFI_ERROR (Result)) {
313 DEBUG ((DEBUG_WARN, "OCC: Failed to force resolution - %r\n", Result));
314 }
315 } else {
316 DEBUG ((DEBUG_INFO, "OCC: Missing OcForceResolution protocol - %r\n", Result));
317 }
318 }
319
320 #ifdef OC_CONSOLE_CHANGE_ALL_RESOLUTIONS
321 EFI_STATUS Status;
322 UINTN HandleCount;
323 EFI_HANDLE *HandleBuffer;
324 UINTN Index;
325
326 Result = gBS->LocateHandleBuffer (
327 ByProtocol,
329 NULL,
330 &HandleCount,
331 &HandleBuffer
332 );
333
334 if (!EFI_ERROR (Result)) {
335 Result = EFI_NOT_FOUND;
336
337 DEBUG ((DEBUG_INFO, "OCC: Found %u handles with GOP\n", (UINT32)HandleCount));
338
339 for (Index = 0; Index < HandleCount; ++Index) {
340 DEBUG ((DEBUG_INFO, "OCC: Trying handle %u - %p\n", (UINT32)Index, HandleBuffer[Index]));
341
342 Status = gBS->HandleProtocol (
343 HandleBuffer[Index],
345 (VOID **)&GraphicsOutput
346 );
347
348 if (EFI_ERROR (Status)) {
349 DEBUG ((DEBUG_WARN, "OCC: Missing GOP on console - %r\n", Status));
350 continue;
351 }
352
353 Result = OcSetConsoleResolutionForProtocol (GraphicsOutput, Width, Height, Bpp);
354 }
355
356 FreePool (HandleBuffer);
357 } else {
358 DEBUG ((DEBUG_INFO, "OCC: Failed to find handles with GOP - %r\n", Result));
359 }
360
361 #else
362 Result = gBS->HandleProtocol (
363 gST->ConsoleOutHandle,
365 (VOID **)&GraphicsOutput
366 );
367
368 if (EFI_ERROR (Result)) {
369 DEBUG ((DEBUG_WARN, "OCC: Missing GOP on ConOut - %r\n", Result));
370 return Result;
371 }
372
373 Result = OcSetConsoleResolutionForProtocol (GraphicsOutput, Width, Height, Bpp);
374 #endif
375
376 return Result;
377}
378
379EFI_STATUS
381 IN UINT32 Width,
382 IN UINT32 Height
383 )
384{
385 return OcSetConsoleModeForProtocol (gST->ConOut, Width, Height);
386}
387
388VOID
390 IN EFI_CONSOLE_CONTROL_SCREEN_MODE InitialMode,
391 IN OC_CONSOLE_RENDERER Renderer,
392 IN OC_STORAGE_CONTEXT *Storage OPTIONAL,
393 IN CONST CHAR8 *Font OPTIONAL,
394 IN BOOLEAN IgnoreTextOutput,
395 IN BOOLEAN SanitiseClearScreen,
396 IN BOOLEAN ClearScreenOnModeSwitch,
397 IN BOOLEAN ReplaceTabWithSpace,
398 IN UINT32 Width,
399 IN UINT32 Height
400 )
401{
402 if (InitialMode == EfiConsoleControlScreenMaxValue) {
403 InitialMode = OcConsoleControlGetMode ();
404 }
405
406 if (Renderer == OcConsoleRendererBuiltinGraphics) {
407 OcUseBuiltinTextOutput (InitialMode, Storage, Font, EfiConsoleControlScreenGraphics, Width, Height);
408 } else if (Renderer == OcConsoleRendererBuiltinText) {
409 OcUseBuiltinTextOutput (InitialMode, Storage, Font, EfiConsoleControlScreenText, Width, Height);
410 } else {
412 InitialMode,
413 Renderer,
414 IgnoreTextOutput,
415 SanitiseClearScreen,
416 ClearScreenOnModeSwitch,
417 ReplaceTabWithSpace
418 );
419 }
420}
EFI_CONSOLE_CONTROL_SCREEN_MODE
@ EfiConsoleControlScreenGraphics
@ EfiConsoleControlScreenMaxValue
@ EfiConsoleControlScreenText
EFI_SYSTEM_TABLE * gST
EFI_BOOT_SERVICES * gBS
EFI_STATUS OcSetConsoleModeForProtocol(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut, IN UINT32 Width, IN UINT32 Height)
EFI_STATUS OcSetConsoleResolution(IN UINT32 Width OPTIONAL, IN UINT32 Height OPTIONAL, IN UINT32 Bpp OPTIONAL, IN BOOLEAN Force)
EFI_STATUS OcSetConsoleResolutionForProtocol(IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, IN UINT32 Width OPTIONAL, IN UINT32 Height OPTIONAL, IN UINT32 Bpp OPTIONAL)
VOID OcSetupConsole(IN EFI_CONSOLE_CONTROL_SCREEN_MODE InitialMode, IN OC_CONSOLE_RENDERER Renderer, IN OC_STORAGE_CONTEXT *Storage OPTIONAL, IN CONST CHAR8 *Font OPTIONAL, IN BOOLEAN IgnoreTextOutput, IN BOOLEAN SanitiseClearScreen, IN BOOLEAN ClearScreenOnModeSwitch, IN BOOLEAN ReplaceTabWithSpace, IN UINT32 Width, IN UINT32 Height)
EFI_STATUS OcSetConsoleMode(IN UINT32 Width, IN UINT32 Height)
OC_CONSOLE_RENDERER
@ OcConsoleRendererBuiltinText
@ OcConsoleRendererBuiltinGraphics
EFI_CONSOLE_CONTROL_SCREEN_MODE OcConsoleControlGetMode(VOID)
EFI_STATUS OcUseSystemTextOutput(IN EFI_CONSOLE_CONTROL_SCREEN_MODE InitialMode, IN OC_CONSOLE_RENDERER Renderer, IN BOOLEAN IgnoreTextOutput, IN BOOLEAN SanitiseClearScreen, IN BOOLEAN ClearScreenOnModeSwitch, IN BOOLEAN ReplaceTabWithSpace)
EFI_STATUS OcUseBuiltinTextOutput(IN EFI_CONSOLE_CONTROL_SCREEN_MODE InitialMode, IN OC_STORAGE_CONTEXT *Storage OPTIONAL, IN CONST CHAR8 *Font OPTIONAL, IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode, IN UINT32 Width, IN UINT32 Height)
EFI_GUID gOcForceResolutionProtocolGuid
EFI_GUID gEfiGraphicsOutputProtocolGuid