]>
Commit | Line | Data |
---|---|---|
031e5cce | 1 | // SPDX-License-Identifier: BSD-2-Clause-Patent |
17857eb8 MG |
2 | /* |
3 | * Copyright 2012 <James.Bottomley@HansenPartnership.com> | |
417077f8 | 4 | * Copyright 2013 Red Hat Inc. <pjones@redhat.com> |
17857eb8 | 5 | */ |
f892ac66 | 6 | #include "shim.h" |
29d9c7c3 | 7 | |
f892ac66 | 8 | static UINT8 console_text_mode = 0; |
17857eb8 MG |
9 | |
10 | static int | |
11 | count_lines(CHAR16 *str_arr[]) | |
12 | { | |
13 | int i = 0; | |
14 | ||
15 | while (str_arr[i]) | |
16 | i++; | |
17 | return i; | |
18 | } | |
19 | ||
20 | static void | |
21 | SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c) | |
22 | { | |
d3819813 | 23 | unsigned int i; |
17857eb8 MG |
24 | |
25 | for (i = 0; i < n/2; i++) { | |
26 | dst[i] = c; | |
27 | } | |
28 | } | |
29 | ||
dcc52381 GCPL |
30 | EFI_STATUS |
31 | console_get_keystroke(EFI_INPUT_KEY *key) | |
17857eb8 | 32 | { |
f892ac66 | 33 | SIMPLE_INPUT_INTERFACE *ci = ST->ConIn; |
17857eb8 | 34 | UINTN EventIndex; |
f892ac66 | 35 | EFI_STATUS efi_status; |
17857eb8 | 36 | |
8529e0f7 SM |
37 | if (!ci) |
38 | return EFI_UNSUPPORTED; | |
39 | ||
dcc52381 | 40 | do { |
8529e0f7 | 41 | BS->WaitForEvent(1, &ci->WaitForKey, &EventIndex); |
f892ac66 MTL |
42 | efi_status = ci->ReadKeyStroke(ci, key); |
43 | } while (efi_status == EFI_NOT_READY); | |
44 | ||
45 | return efi_status; | |
46 | } | |
47 | ||
48 | static VOID setup_console (int text) | |
49 | { | |
50 | EFI_STATUS efi_status; | |
51 | EFI_CONSOLE_CONTROL_PROTOCOL *concon; | |
52 | static EFI_CONSOLE_CONTROL_SCREEN_MODE mode = | |
53 | EfiConsoleControlScreenGraphics; | |
54 | EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode; | |
55 | ||
56 | efi_status = LibLocateProtocol(&EFI_CONSOLE_CONTROL_GUID, | |
57 | (VOID **)&concon); | |
58 | if (EFI_ERROR(efi_status)) | |
59 | return; | |
60 | ||
61 | if (text) { | |
62 | new_mode = EfiConsoleControlScreenText; | |
63 | ||
64 | efi_status = concon->GetMode(concon, &mode, 0, 0); | |
65 | /* If that didn't work, assume it's graphics */ | |
66 | if (EFI_ERROR(efi_status)) | |
67 | mode = EfiConsoleControlScreenGraphics; | |
68 | if (text < 0) { | |
69 | if (mode == EfiConsoleControlScreenGraphics) | |
70 | console_text_mode = 0; | |
71 | else | |
72 | console_text_mode = 1; | |
73 | return; | |
74 | } | |
75 | } else { | |
76 | new_mode = mode; | |
77 | } | |
78 | ||
79 | concon->SetMode(concon, new_mode); | |
80 | console_text_mode = text; | |
81 | } | |
82 | ||
83 | VOID console_fini(VOID) | |
84 | { | |
85 | if (console_text_mode) | |
86 | setup_console(0); | |
87 | } | |
88 | ||
031e5cce | 89 | UINTN EFIAPI |
f892ac66 MTL |
90 | console_print(const CHAR16 *fmt, ...) |
91 | { | |
031e5cce | 92 | ms_va_list args; |
f892ac66 MTL |
93 | UINTN ret; |
94 | ||
95 | if (!console_text_mode) | |
96 | setup_console(1); | |
97 | ||
031e5cce | 98 | ms_va_start(args, fmt); |
f892ac66 | 99 | ret = VPrint(fmt, args); |
031e5cce | 100 | ms_va_end(args); |
f892ac66 MTL |
101 | |
102 | return ret; | |
103 | } | |
104 | ||
031e5cce | 105 | UINTN EFIAPI |
f892ac66 MTL |
106 | console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...) |
107 | { | |
108 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
031e5cce | 109 | ms_va_list args; |
f892ac66 MTL |
110 | UINTN ret; |
111 | ||
112 | if (!console_text_mode) | |
113 | setup_console(1); | |
17857eb8 | 114 | |
8529e0f7 SM |
115 | if (co) |
116 | co->SetCursorPosition(co, col, row); | |
f892ac66 | 117 | |
031e5cce | 118 | ms_va_start(args, fmt); |
f892ac66 | 119 | ret = VPrint(fmt, args); |
031e5cce | 120 | ms_va_end(args); |
f892ac66 MTL |
121 | |
122 | return ret; | |
17857eb8 MG |
123 | } |
124 | ||
e6ace38a SM |
125 | static struct { |
126 | CHAR16 up_left; | |
127 | CHAR16 up_right; | |
128 | CHAR16 down_left; | |
129 | CHAR16 down_right; | |
130 | CHAR16 horizontal; | |
131 | CHAR16 vertical; | |
132 | } boxdraw[2] = { | |
133 | { | |
134 | BOXDRAW_UP_LEFT, | |
135 | BOXDRAW_UP_RIGHT, | |
136 | BOXDRAW_DOWN_LEFT, | |
137 | BOXDRAW_DOWN_RIGHT, | |
138 | BOXDRAW_HORIZONTAL, | |
139 | BOXDRAW_VERTICAL | |
140 | }, { | |
141 | '+', | |
142 | '+', | |
143 | '+', | |
144 | '+', | |
145 | '-', | |
146 | '|' | |
147 | } | |
148 | }; | |
f892ac66 | 149 | |
17857eb8 | 150 | void |
d3819813 MTL |
151 | console_print_box_at(CHAR16 *str_arr[], int highlight, |
152 | int start_col, int start_row, | |
153 | int size_cols, int size_rows, | |
154 | int offset, int lines) | |
17857eb8 MG |
155 | { |
156 | int i; | |
157 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
158 | UINTN rows, cols; | |
159 | CHAR16 *Line; | |
e6ace38a | 160 | bool char_set; |
17857eb8 MG |
161 | |
162 | if (lines == 0) | |
163 | return; | |
164 | ||
f892ac66 MTL |
165 | if (!console_text_mode) |
166 | setup_console(1); | |
167 | ||
8529e0f7 SM |
168 | if (!co) |
169 | return; | |
170 | ||
f892ac66 | 171 | co->QueryMode(co, co->Mode->Mode, &cols, &rows); |
17857eb8 MG |
172 | |
173 | /* last row on screen is unusable without scrolling, so ignore it */ | |
174 | rows--; | |
175 | ||
176 | if (size_rows < 0) | |
177 | size_rows = rows + size_rows + 1; | |
178 | if (size_cols < 0) | |
179 | size_cols = cols + size_cols + 1; | |
180 | ||
181 | if (start_col < 0) | |
182 | start_col = (cols + start_col + 2)/2; | |
183 | if (start_row < 0) | |
184 | start_row = (rows + start_row + 2)/2; | |
185 | if (start_col < 0) | |
186 | start_col = 0; | |
187 | if (start_row < 0) | |
188 | start_row = 0; | |
189 | ||
d3819813 | 190 | if (start_col > (int)cols || start_row > (int)rows) { |
f892ac66 MTL |
191 | console_print(L"Starting Position (%d,%d) is off screen\n", |
192 | start_col, start_row); | |
17857eb8 MG |
193 | return; |
194 | } | |
d3819813 | 195 | if (size_cols + start_col > (int)cols) |
17857eb8 | 196 | size_cols = cols - start_col; |
d3819813 | 197 | if (size_rows + start_row > (int)rows) |
17857eb8 | 198 | size_rows = rows - start_row; |
d3819813 | 199 | |
17857eb8 MG |
200 | if (lines > size_rows - 2) |
201 | lines = size_rows - 2; | |
202 | ||
203 | Line = AllocatePool((size_cols+1)*sizeof(CHAR16)); | |
204 | if (!Line) { | |
f892ac66 | 205 | console_print(L"Failed Allocation\n"); |
17857eb8 MG |
206 | return; |
207 | } | |
208 | ||
e6ace38a SM |
209 | /* test if boxdraw characters work */ |
210 | co->SetCursorPosition(co, start_col, start_row); | |
211 | Line[0] = boxdraw[0].up_left; | |
212 | Line[1] = L'\0'; | |
213 | char_set = co->OutputString(co, Line) == 0 ? 0 : 1; | |
214 | ||
215 | SetMem16 (Line, size_cols * 2, boxdraw[char_set].horizontal); | |
17857eb8 | 216 | |
e6ace38a SM |
217 | Line[0] = boxdraw[char_set].down_right; |
218 | Line[size_cols - 1] = boxdraw[char_set].down_left; | |
17857eb8 | 219 | Line[size_cols] = L'\0'; |
f892ac66 MTL |
220 | co->SetCursorPosition(co, start_col, start_row); |
221 | co->OutputString(co, Line); | |
17857eb8 MG |
222 | |
223 | int start; | |
224 | if (offset == 0) | |
225 | /* middle */ | |
226 | start = (size_rows - lines)/2 + start_row + offset; | |
227 | else if (offset < 0) | |
228 | /* from bottom */ | |
229 | start = start_row + size_rows - lines + offset - 1; | |
230 | else | |
231 | /* from top */ | |
232 | start = start_row + offset; | |
17857eb8 MG |
233 | |
234 | for (i = start_row + 1; i < size_rows + start_row - 1; i++) { | |
235 | int line = i - start; | |
236 | ||
237 | SetMem16 (Line, size_cols*2, L' '); | |
e6ace38a SM |
238 | Line[0] = boxdraw[char_set].vertical; |
239 | Line[size_cols - 1] = boxdraw[char_set].vertical; | |
17857eb8 MG |
240 | Line[size_cols] = L'\0'; |
241 | if (line >= 0 && line < lines) { | |
242 | CHAR16 *s = str_arr[line]; | |
243 | int len = StrLen(s); | |
244 | int col = (size_cols - 2 - len)/2; | |
245 | ||
246 | if (col < 0) | |
247 | col = 0; | |
248 | ||
031e5cce | 249 | CopyMem(Line + col + 1, s, MIN(len, size_cols - 2)*2); |
17857eb8 | 250 | } |
d3819813 | 251 | if (line >= 0 && line == highlight) |
f892ac66 MTL |
252 | co->SetAttribute(co, EFI_LIGHTGRAY | |
253 | EFI_BACKGROUND_BLACK); | |
254 | co->SetCursorPosition(co, start_col, i); | |
255 | co->OutputString(co, Line); | |
d3819813 | 256 | if (line >= 0 && line == highlight) |
f892ac66 MTL |
257 | co->SetAttribute(co, EFI_LIGHTGRAY | |
258 | EFI_BACKGROUND_BLUE); | |
17857eb8 MG |
259 | |
260 | } | |
e6ace38a SM |
261 | SetMem16 (Line, size_cols * 2, boxdraw[char_set].horizontal); |
262 | Line[0] = boxdraw[char_set].up_right; | |
263 | Line[size_cols - 1] = boxdraw[char_set].up_left; | |
17857eb8 | 264 | Line[size_cols] = L'\0'; |
f892ac66 MTL |
265 | co->SetCursorPosition(co, start_col, i); |
266 | co->OutputString(co, Line); | |
17857eb8 MG |
267 | |
268 | FreePool (Line); | |
269 | ||
270 | } | |
271 | ||
272 | void | |
273 | console_print_box(CHAR16 *str_arr[], int highlight) | |
274 | { | |
275 | SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; | |
276 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
dcc52381 GCPL |
277 | EFI_INPUT_KEY key; |
278 | ||
f892ac66 MTL |
279 | if (!console_text_mode) |
280 | setup_console(1); | |
281 | ||
8529e0f7 SM |
282 | if (!co) |
283 | return; | |
284 | ||
17857eb8 | 285 | CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode)); |
f892ac66 MTL |
286 | co->EnableCursor(co, FALSE); |
287 | co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); | |
17857eb8 MG |
288 | |
289 | console_print_box_at(str_arr, highlight, 0, 0, -1, -1, 0, | |
290 | count_lines(str_arr)); | |
291 | ||
dcc52381 | 292 | console_get_keystroke(&key); |
17857eb8 | 293 | |
f892ac66 MTL |
294 | co->EnableCursor(co, SavedConsoleMode.CursorVisible); |
295 | co->SetCursorPosition(co, SavedConsoleMode.CursorColumn, | |
296 | SavedConsoleMode.CursorRow); | |
297 | co->SetAttribute(co, SavedConsoleMode.Attribute); | |
17857eb8 MG |
298 | } |
299 | ||
300 | int | |
d3819813 | 301 | console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start) |
17857eb8 MG |
302 | { |
303 | SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; | |
304 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
305 | EFI_INPUT_KEY k; | |
f892ac66 | 306 | EFI_STATUS efi_status; |
17857eb8 | 307 | int selector; |
d3819813 | 308 | unsigned int selector_lines = count_lines(selectors); |
17857eb8 | 309 | int selector_max_cols = 0; |
d3819813 MTL |
310 | unsigned int i; |
311 | int offs_col, offs_row, size_cols, size_rows, lines; | |
312 | unsigned int selector_offset; | |
17857eb8 MG |
313 | UINTN cols, rows; |
314 | ||
f892ac66 MTL |
315 | if (!console_text_mode) |
316 | setup_console(1); | |
317 | ||
8529e0f7 SM |
318 | if (!co) |
319 | return -1; | |
320 | ||
f892ac66 | 321 | co->QueryMode(co, co->Mode->Mode, &cols, &rows); |
17857eb8 MG |
322 | |
323 | for (i = 0; i < selector_lines; i++) { | |
324 | int len = StrLen(selectors[i]); | |
325 | ||
326 | if (len > selector_max_cols) | |
327 | selector_max_cols = len; | |
328 | } | |
329 | ||
17857eb8 MG |
330 | if (start >= selector_lines) |
331 | start = selector_lines - 1; | |
332 | ||
333 | offs_col = - selector_max_cols - 4; | |
334 | size_cols = selector_max_cols + 4; | |
335 | ||
336 | if (selector_lines > rows - 10) { | |
337 | int title_lines = count_lines(title); | |
338 | offs_row = title_lines + 1; | |
339 | size_rows = rows - 3 - title_lines; | |
340 | lines = size_rows - 2; | |
341 | } else { | |
342 | offs_row = - selector_lines - 4; | |
343 | size_rows = selector_lines + 2; | |
344 | lines = selector_lines; | |
345 | } | |
346 | ||
d3819813 | 347 | if (start > (unsigned)lines) { |
17857eb8 MG |
348 | selector = lines; |
349 | selector_offset = start - lines; | |
350 | } else { | |
351 | selector = start; | |
352 | selector_offset = 0; | |
353 | } | |
354 | ||
355 | CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode)); | |
f892ac66 MTL |
356 | co->EnableCursor(co, FALSE); |
357 | co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); | |
17857eb8 MG |
358 | |
359 | console_print_box_at(title, -1, 0, 0, -1, -1, 1, count_lines(title)); | |
360 | ||
361 | console_print_box_at(selectors, selector, offs_col, offs_row, | |
362 | size_cols, size_rows, 0, lines); | |
363 | ||
364 | do { | |
f892ac66 MTL |
365 | efi_status = console_get_keystroke(&k); |
366 | if (EFI_ERROR (efi_status)) { | |
367 | console_print(L"Failed to read the keystroke: %r", | |
368 | efi_status); | |
dcc52381 GCPL |
369 | selector = -1; |
370 | break; | |
371 | } | |
17857eb8 MG |
372 | |
373 | if (k.ScanCode == SCAN_ESC) { | |
374 | selector = -1; | |
375 | break; | |
376 | } | |
377 | ||
378 | if (k.ScanCode == SCAN_UP) { | |
379 | if (selector > 0) | |
380 | selector--; | |
381 | else if (selector_offset > 0) | |
382 | selector_offset--; | |
383 | } else if (k.ScanCode == SCAN_DOWN) { | |
384 | if (selector < lines - 1) | |
385 | selector++; | |
386 | else if (selector_offset < (selector_lines - lines)) | |
387 | selector_offset++; | |
388 | } | |
389 | ||
390 | console_print_box_at(&selectors[selector_offset], selector, | |
391 | offs_col, offs_row, | |
392 | size_cols, size_rows, 0, lines); | |
393 | } while (!(k.ScanCode == SCAN_NULL | |
394 | && k.UnicodeChar == CHAR_CARRIAGE_RETURN)); | |
395 | ||
f892ac66 MTL |
396 | co->EnableCursor(co, SavedConsoleMode.CursorVisible); |
397 | co->SetCursorPosition(co, SavedConsoleMode.CursorColumn, | |
398 | SavedConsoleMode.CursorRow); | |
399 | co->SetAttribute(co, SavedConsoleMode.Attribute); | |
17857eb8 MG |
400 | |
401 | if (selector < 0) | |
402 | /* ESC pressed */ | |
403 | return selector; | |
404 | return selector + selector_offset; | |
405 | } | |
406 | ||
407 | ||
408 | int | |
409 | console_yes_no(CHAR16 *str_arr[]) | |
410 | { | |
f892ac66 MTL |
411 | CHAR16 *yes_no[] = { L"No", L"Yes", NULL }; |
412 | return console_select(str_arr, yes_no, 0); | |
17857eb8 MG |
413 | } |
414 | ||
415 | void | |
416 | console_alertbox(CHAR16 **title) | |
417 | { | |
f892ac66 MTL |
418 | CHAR16 *okay[] = { L"OK", NULL }; |
419 | console_select(title, okay, 0); | |
17857eb8 MG |
420 | } |
421 | ||
422 | void | |
423 | console_errorbox(CHAR16 *err) | |
424 | { | |
425 | CHAR16 **err_arr = (CHAR16 *[]){ | |
426 | L"ERROR", | |
427 | L"", | |
428 | 0, | |
429 | 0, | |
430 | }; | |
431 | ||
432 | err_arr[2] = err; | |
433 | ||
51d5bbcb | 434 | console_alertbox(err_arr); |
17857eb8 MG |
435 | } |
436 | ||
437 | void | |
438 | console_notify(CHAR16 *string) | |
439 | { | |
440 | CHAR16 **str_arr = (CHAR16 *[]){ | |
441 | 0, | |
442 | 0, | |
443 | }; | |
444 | ||
445 | str_arr[0] = string; | |
446 | ||
51d5bbcb | 447 | console_alertbox(str_arr); |
17857eb8 MG |
448 | } |
449 | ||
031e5cce SM |
450 | void |
451 | console_save_and_set_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode) | |
452 | { | |
453 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
454 | ||
455 | if (!SavedMode) { | |
456 | console_print(L"Invalid parameter: SavedMode\n"); | |
457 | return; | |
458 | } | |
459 | ||
8529e0f7 SM |
460 | if (!co) |
461 | return; | |
462 | ||
031e5cce SM |
463 | CopyMem(SavedMode, co->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE)); |
464 | co->EnableCursor(co, FALSE); | |
465 | co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); | |
466 | } | |
467 | ||
468 | void | |
469 | console_restore_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode) | |
470 | { | |
471 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
472 | ||
8529e0f7 SM |
473 | if (!co) |
474 | return; | |
475 | ||
031e5cce SM |
476 | co->EnableCursor(co, SavedMode->CursorVisible); |
477 | co->SetCursorPosition(co, SavedMode->CursorColumn, | |
478 | SavedMode->CursorRow); | |
479 | co->SetAttribute(co, SavedMode->Attribute); | |
480 | } | |
481 | ||
482 | int | |
483 | console_countdown(CHAR16* title, const CHAR16* message, int timeout) | |
484 | { | |
485 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
486 | SIMPLE_INPUT_INTERFACE *ci = ST->ConIn; | |
487 | SIMPLE_TEXT_OUTPUT_MODE SavedMode; | |
488 | EFI_INPUT_KEY key; | |
489 | EFI_STATUS efi_status; | |
490 | UINTN cols, rows; | |
491 | CHAR16 *titles[2]; | |
492 | int wait = 10000000; | |
493 | ||
8529e0f7 SM |
494 | if (!co || !ci) |
495 | return -1; | |
496 | ||
031e5cce SM |
497 | console_save_and_set_mode(&SavedMode); |
498 | ||
499 | titles[0] = title; | |
500 | titles[1] = NULL; | |
501 | ||
502 | console_print_box_at(titles, -1, 0, 0, -1, -1, 1, 1); | |
503 | ||
504 | co->QueryMode(co, co->Mode->Mode, &cols, &rows); | |
505 | ||
506 | console_print_at((cols - StrLen(message)) / 2, rows / 2, message); | |
507 | while (1) { | |
508 | if (timeout > 1) | |
509 | console_print_at(2, rows - 3, | |
510 | L"Booting in %d seconds ", | |
511 | timeout); | |
512 | else if (timeout) | |
513 | console_print_at(2, rows - 3, | |
514 | L"Booting in %d second ", | |
515 | timeout); | |
516 | ||
517 | efi_status = WaitForSingleEvent(ci->WaitForKey, wait); | |
518 | if (efi_status != EFI_TIMEOUT) { | |
519 | /* Clear the key in the queue */ | |
520 | ci->ReadKeyStroke(ci, &key); | |
521 | break; | |
522 | } | |
523 | ||
524 | timeout--; | |
525 | if (!timeout) | |
526 | break; | |
527 | } | |
528 | ||
529 | console_restore_mode(&SavedMode); | |
530 | ||
531 | return timeout; | |
532 | } | |
533 | ||
534 | #define HORIZONTAL_MAX_OK 1920 | |
535 | #define VERTICAL_MAX_OK 1080 | |
536 | #define COLUMNS_MAX_OK 200 | |
537 | #define ROWS_MAX_OK 100 | |
538 | ||
539 | void | |
540 | console_mode_handle(VOID) | |
541 | { | |
542 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
543 | EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; | |
544 | EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; | |
545 | EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; | |
546 | ||
547 | UINTN mode_set; | |
548 | UINTN rows = 0, columns = 0; | |
549 | EFI_STATUS efi_status = EFI_SUCCESS; | |
550 | ||
8529e0f7 SM |
551 | if (!co) |
552 | return; | |
553 | ||
554 | efi_status = BS->LocateProtocol(&gop_guid, NULL, (void **)&gop); | |
031e5cce | 555 | if (EFI_ERROR(efi_status)) { |
031e5cce SM |
556 | return; |
557 | } | |
558 | ||
559 | Info = gop->Mode->Info; | |
560 | ||
561 | /* | |
562 | * Start verifying if we are in a resolution larger than Full HD | |
563 | * (1920x1080). If we're not, assume we're in a good mode and do not | |
564 | * try to change it. | |
565 | */ | |
566 | if (Info->HorizontalResolution <= HORIZONTAL_MAX_OK && | |
567 | Info->VerticalResolution <= VERTICAL_MAX_OK) { | |
568 | /* keep original mode and return */ | |
569 | return; | |
570 | } | |
571 | ||
572 | efi_status = co->QueryMode(co, co->Mode->Mode, &columns, &rows); | |
573 | if (EFI_ERROR(efi_status)) { | |
574 | console_error(L"Console query mode fail", efi_status); | |
575 | return; | |
576 | } | |
577 | ||
578 | /* | |
579 | * Verify current console output to check if the character columns and | |
580 | * rows in a good mode. | |
581 | */ | |
582 | if (columns <= COLUMNS_MAX_OK && rows <= ROWS_MAX_OK) { | |
583 | /* keep original mode and return */ | |
584 | return; | |
585 | } | |
586 | ||
587 | if (!console_text_mode) | |
588 | setup_console(1); | |
589 | ||
590 | co->Reset(co, TRUE); | |
591 | ||
592 | /* | |
593 | * If we reached here, then we have a high resolution screen and the | |
594 | * text too small. Try to switch to a better mode. Mode number 2 is | |
595 | * first non standard mode, which is provided by the device | |
596 | * manufacturer, so it should be a good mode. | |
597 | */ | |
598 | if (co->Mode->MaxMode > 2) | |
599 | mode_set = 2; | |
600 | else | |
601 | mode_set = 0; | |
602 | ||
603 | efi_status = co->SetMode(co, mode_set); | |
604 | if (EFI_ERROR(efi_status) && mode_set != 0) { | |
605 | /* | |
606 | * Set to 0 mode which is required that all output devices | |
607 | * support at least 80x25 text mode. | |
608 | */ | |
609 | mode_set = 0; | |
610 | efi_status = co->SetMode(co, mode_set); | |
611 | } | |
612 | ||
8529e0f7 | 613 | clear_screen(); |
031e5cce SM |
614 | |
615 | if (EFI_ERROR(efi_status)) { | |
616 | console_error(L"Console set mode fail", efi_status); | |
617 | } | |
618 | ||
619 | return; | |
620 | } | |
17857eb8 MG |
621 | |
622 | /* Copy of gnu-efi-3.0 with the added secure boot strings */ | |
623 | static struct { | |
624 | EFI_STATUS Code; | |
031e5cce | 625 | CHAR16 *Desc; |
17857eb8 MG |
626 | } error_table[] = { |
627 | { EFI_SUCCESS, L"Success"}, | |
628 | { EFI_LOAD_ERROR, L"Load Error"}, | |
629 | { EFI_INVALID_PARAMETER, L"Invalid Parameter"}, | |
630 | { EFI_UNSUPPORTED, L"Unsupported"}, | |
631 | { EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size"}, | |
632 | { EFI_BUFFER_TOO_SMALL, L"Buffer Too Small"}, | |
633 | { EFI_NOT_READY, L"Not Ready"}, | |
634 | { EFI_DEVICE_ERROR, L"Device Error"}, | |
635 | { EFI_WRITE_PROTECTED, L"Write Protected"}, | |
636 | { EFI_OUT_OF_RESOURCES, L"Out of Resources"}, | |
637 | { EFI_VOLUME_CORRUPTED, L"Volume Corrupt"}, | |
638 | { EFI_VOLUME_FULL, L"Volume Full"}, | |
639 | { EFI_NO_MEDIA, L"No Media"}, | |
640 | { EFI_MEDIA_CHANGED, L"Media changed"}, | |
641 | { EFI_NOT_FOUND, L"Not Found"}, | |
642 | { EFI_ACCESS_DENIED, L"Access Denied"}, | |
643 | { EFI_NO_RESPONSE, L"No Response"}, | |
644 | { EFI_NO_MAPPING, L"No mapping"}, | |
645 | { EFI_TIMEOUT, L"Time out"}, | |
646 | { EFI_NOT_STARTED, L"Not started"}, | |
647 | { EFI_ALREADY_STARTED, L"Already started"}, | |
648 | { EFI_ABORTED, L"Aborted"}, | |
649 | { EFI_ICMP_ERROR, L"ICMP Error"}, | |
650 | { EFI_TFTP_ERROR, L"TFTP Error"}, | |
651 | { EFI_PROTOCOL_ERROR, L"Protocol Error"}, | |
652 | { EFI_INCOMPATIBLE_VERSION, L"Incompatible Version"}, | |
653 | { EFI_SECURITY_VIOLATION, L"Security Violation"}, | |
654 | ||
655 | // warnings | |
031e5cce | 656 | { EFI_WARN_UNKNOWN_GLYPH, L"Warning Unknown Glyph"}, |
17857eb8 MG |
657 | { EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure"}, |
658 | { EFI_WARN_WRITE_FAILURE, L"Warning Write Failure"}, | |
659 | { EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small"}, | |
660 | { 0, NULL} | |
661 | } ; | |
662 | ||
663 | ||
664 | static CHAR16 * | |
665 | err_string ( | |
f892ac66 | 666 | IN EFI_STATUS efi_status |
17857eb8 MG |
667 | ) |
668 | { | |
669 | UINTN Index; | |
670 | ||
671 | for (Index = 0; error_table[Index].Desc; Index +=1) { | |
f892ac66 | 672 | if (error_table[Index].Code == efi_status) { |
17857eb8 MG |
673 | return error_table[Index].Desc; |
674 | } | |
675 | } | |
676 | ||
677 | return L""; | |
678 | } | |
17857eb8 MG |
679 | |
680 | void | |
f892ac66 | 681 | console_error(CHAR16 *err, EFI_STATUS efi_status) |
17857eb8 MG |
682 | { |
683 | CHAR16 **err_arr = (CHAR16 *[]){ | |
684 | L"ERROR", | |
685 | L"", | |
686 | 0, | |
687 | 0, | |
688 | }; | |
689 | CHAR16 str[512]; | |
690 | ||
f892ac66 MTL |
691 | SPrint(str, sizeof(str), L"%s: (0x%x) %s", err, efi_status, |
692 | err_string(efi_status)); | |
17857eb8 MG |
693 | |
694 | err_arr[2] = str; | |
695 | ||
51d5bbcb | 696 | console_alertbox(err_arr); |
17857eb8 MG |
697 | } |
698 | ||
699 | void | |
700 | console_reset(void) | |
701 | { | |
702 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
703 | ||
f892ac66 MTL |
704 | if (!console_text_mode) |
705 | setup_console(1); | |
706 | ||
8529e0f7 SM |
707 | if (!co) |
708 | return; | |
709 | ||
f892ac66 | 710 | co->Reset(co, TRUE); |
17857eb8 | 711 | /* set mode 0 - required to be 80x25 */ |
f892ac66 MTL |
712 | co->SetMode(co, 0); |
713 | co->ClearScreen(co); | |
17857eb8 | 714 | } |
417077f8 | 715 | |
8529e0f7 SM |
716 | void |
717 | clear_screen(void) | |
718 | { | |
719 | SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; | |
720 | ||
721 | if (!co) | |
722 | return; | |
723 | ||
724 | co->ClearScreen(co); | |
725 | } | |
4ab978a3 PJ |
726 | |
727 | VOID | |
728 | setup_verbosity(VOID) | |
729 | { | |
f892ac66 MTL |
730 | EFI_STATUS efi_status; |
731 | UINT8 *verbose_check_ptr = NULL; | |
4ab978a3 PJ |
732 | UINTN verbose_check_size; |
733 | ||
f892ac66 | 734 | verbose_check_size = sizeof(verbose); |
e6ace38a | 735 | efi_status = get_variable(VERBOSE_VAR_NAME, &verbose_check_ptr, |
f892ac66 MTL |
736 | &verbose_check_size, SHIM_LOCK_GUID); |
737 | if (!EFI_ERROR(efi_status)) { | |
738 | verbose = *(__typeof__(verbose) *)verbose_check_ptr; | |
739 | verbose &= (1ULL << (8 * verbose_check_size)) - 1ULL; | |
740 | FreePool(verbose_check_ptr); | |
417077f8 PJ |
741 | } |
742 | ||
f892ac66 | 743 | setup_console(-1); |
417077f8 | 744 | } |
b6f94dbe | 745 | |
fd2d9f03 | 746 | #ifndef SHIM_UNIT_TEST |
b6f94dbe | 747 | VOID |
fd2d9f03 | 748 | usleep(unsigned long usecs) |
b6f94dbe | 749 | { |
fd2d9f03 | 750 | BS->Stall(usecs); |
b6f94dbe | 751 | } |
fd2d9f03 | 752 | #endif |
f892ac66 MTL |
753 | |
754 | /* This is used in various things to determine if we should print to the | |
755 | * console */ | |
756 | UINT8 in_protocol = 0; |