]> git.proxmox.com Git - efi-boot-shim.git/blame - lib/console.c
New upstream version 15.8
[efi-boot-shim.git] / lib / console.c
CommitLineData
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 8static UINT8 console_text_mode = 0;
17857eb8
MG
9
10static int
11count_lines(CHAR16 *str_arr[])
12{
13 int i = 0;
14
15 while (str_arr[i])
16 i++;
17 return i;
18}
19
20static void
21SetMem16(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
30EFI_STATUS
31console_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
48static 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
83VOID console_fini(VOID)
84{
85 if (console_text_mode)
86 setup_console(0);
87}
88
031e5cce 89UINTN EFIAPI
f892ac66
MTL
90console_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 105UINTN EFIAPI
f892ac66
MTL
106console_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
125static 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 150void
d3819813
MTL
151console_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
272void
273console_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
300int
d3819813 301console_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
408int
409console_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
415void
416console_alertbox(CHAR16 **title)
417{
f892ac66
MTL
418 CHAR16 *okay[] = { L"OK", NULL };
419 console_select(title, okay, 0);
17857eb8
MG
420}
421
422void
423console_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
437void
438console_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
450void
451console_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
468void
469console_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
482int
483console_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
539void
540console_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 */
623static 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
664static CHAR16 *
665err_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
680void
f892ac66 681console_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
699void
700console_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
716void
717clear_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
727VOID
728setup_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 747VOID
fd2d9f03 748usleep(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 */
756UINT8 in_protocol = 0;