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