2 * Copyright 2012 <James.Bottomley@HansenPartnership.com>
3 * Copyright 2013 Red Hat Inc. <pjones@redhat.com>
11 #include <variables.h>
14 static EFI_GUID SHIM_LOCK_GUID
= { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
16 static int min(int a
, int b
)
24 count_lines(CHAR16
*str_arr
[])
34 SetMem16(CHAR16
*dst
, UINT32 n
, CHAR16 c
)
38 for (i
= 0; i
< n
/2; i
++) {
44 console_get_keystroke(EFI_INPUT_KEY
*key
)
50 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1, &ST
->ConIn
->WaitForKey
, &EventIndex
);
51 status
= uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2, ST
->ConIn
, key
);
52 } while (status
== EFI_NOT_READY
);
58 console_print_box_at(CHAR16
*str_arr
[], int highlight
,
59 int start_col
, int start_row
,
60 int size_cols
, int size_rows
,
61 int offset
, int lines
)
64 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
71 uefi_call_wrapper(co
->QueryMode
, 4, co
, co
->Mode
->Mode
, &cols
, &rows
);
73 /* last row on screen is unusable without scrolling, so ignore it */
77 size_rows
= rows
+ size_rows
+ 1;
79 size_cols
= cols
+ size_cols
+ 1;
82 start_col
= (cols
+ start_col
+ 2)/2;
84 start_row
= (rows
+ start_row
+ 2)/2;
90 if (start_col
> (int)cols
|| start_row
> (int)rows
) {
91 Print(L
"Starting Position (%d,%d) is off screen\n",
92 start_col
, start_row
);
95 if (size_cols
+ start_col
> (int)cols
)
96 size_cols
= cols
- start_col
;
97 if (size_rows
+ start_row
> (int)rows
)
98 size_rows
= rows
- start_row
;
100 if (lines
> size_rows
- 2)
101 lines
= size_rows
- 2;
103 Line
= AllocatePool((size_cols
+1)*sizeof(CHAR16
));
105 Print(L
"Failed Allocation\n");
109 SetMem16 (Line
, size_cols
* 2, BOXDRAW_HORIZONTAL
);
111 Line
[0] = BOXDRAW_DOWN_RIGHT
;
112 Line
[size_cols
- 1] = BOXDRAW_DOWN_LEFT
;
113 Line
[size_cols
] = L
'\0';
114 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, start_row
);
115 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
120 start
= (size_rows
- lines
)/2 + start_row
+ offset
;
123 start
= start_row
+ size_rows
- lines
+ offset
- 1;
126 start
= start_row
+ offset
;
128 for (i
= start_row
+ 1; i
< size_rows
+ start_row
- 1; i
++) {
129 int line
= i
- start
;
131 SetMem16 (Line
, size_cols
*2, L
' ');
132 Line
[0] = BOXDRAW_VERTICAL
;
133 Line
[size_cols
- 1] = BOXDRAW_VERTICAL
;
134 Line
[size_cols
] = L
'\0';
135 if (line
>= 0 && line
< lines
) {
136 CHAR16
*s
= str_arr
[line
];
138 int col
= (size_cols
- 2 - len
)/2;
143 CopyMem(Line
+ col
+ 1, s
, min(len
, size_cols
- 2)*2);
145 if (line
>= 0 && line
== highlight
)
146 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLACK
);
147 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, i
);
148 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
149 if (line
>= 0 && line
== highlight
)
150 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
153 SetMem16 (Line
, size_cols
* 2, BOXDRAW_HORIZONTAL
);
154 Line
[0] = BOXDRAW_UP_RIGHT
;
155 Line
[size_cols
- 1] = BOXDRAW_UP_LEFT
;
156 Line
[size_cols
] = L
'\0';
157 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, i
);
158 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
165 console_print_box(CHAR16
*str_arr
[], int highlight
)
167 SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode
;
168 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
171 CopyMem(&SavedConsoleMode
, co
->Mode
, sizeof(SavedConsoleMode
));
172 uefi_call_wrapper(co
->EnableCursor
, 2, co
, FALSE
);
173 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
175 console_print_box_at(str_arr
, highlight
, 0, 0, -1, -1, 0,
176 count_lines(str_arr
));
178 console_get_keystroke(&key
);
180 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
181 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, SavedConsoleMode
.CursorColumn
, SavedConsoleMode
.CursorRow
);
182 uefi_call_wrapper(co
->SetAttribute
, 2, co
, SavedConsoleMode
.Attribute
);
186 console_select(CHAR16
*title
[], CHAR16
* selectors
[], unsigned int start
)
188 SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode
;
189 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
192 unsigned int selector
;
193 unsigned int selector_lines
= count_lines(selectors
);
194 int selector_max_cols
= 0;
195 unsigned int i
, offs_col
, offs_row
, size_cols
, size_rows
, lines
;
196 unsigned int selector_offset
;
199 uefi_call_wrapper(co
->QueryMode
, 4, co
, co
->Mode
->Mode
, &cols
, &rows
);
201 for (i
= 0; i
< selector_lines
; i
++) {
202 int len
= StrLen(selectors
[i
]);
204 if (len
> selector_max_cols
)
205 selector_max_cols
= len
;
210 if (start
>= selector_lines
)
211 start
= selector_lines
- 1;
213 offs_col
= - selector_max_cols
- 4;
214 size_cols
= selector_max_cols
+ 4;
216 if (selector_lines
> rows
- 10) {
217 int title_lines
= count_lines(title
);
218 offs_row
= title_lines
+ 1;
219 size_rows
= rows
- 3 - title_lines
;
220 lines
= size_rows
- 2;
222 offs_row
= - selector_lines
- 4;
223 size_rows
= selector_lines
+ 2;
224 lines
= selector_lines
;
229 selector_offset
= start
- lines
;
235 CopyMem(&SavedConsoleMode
, co
->Mode
, sizeof(SavedConsoleMode
));
236 uefi_call_wrapper(co
->EnableCursor
, 2, co
, FALSE
);
237 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
239 console_print_box_at(title
, -1, 0, 0, -1, -1, 1, count_lines(title
));
241 console_print_box_at(selectors
, selector
, offs_col
, offs_row
,
242 size_cols
, size_rows
, 0, lines
);
245 status
= console_get_keystroke(&k
);
246 if (EFI_ERROR (status
)) {
247 Print(L
"Failed to read the keystroke: %r", status
);
252 if (k
.ScanCode
== SCAN_ESC
) {
257 if (k
.ScanCode
== SCAN_UP
) {
260 else if (selector_offset
> 0)
262 } else if (k
.ScanCode
== SCAN_DOWN
) {
263 if (selector
< lines
- 1)
265 else if (selector_offset
< (selector_lines
- lines
))
269 console_print_box_at(&selectors
[selector_offset
], selector
,
271 size_cols
, size_rows
, 0, lines
);
272 } while (!(k
.ScanCode
== SCAN_NULL
273 && k
.UnicodeChar
== CHAR_CARRIAGE_RETURN
));
275 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
276 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, SavedConsoleMode
.CursorColumn
, SavedConsoleMode
.CursorRow
);
277 uefi_call_wrapper(co
->SetAttribute
, 2, co
, SavedConsoleMode
.Attribute
);
282 return selector
+ selector_offset
;
287 console_yes_no(CHAR16
*str_arr
[])
289 return console_select(str_arr
, (CHAR16
*[]){ L
"No", L
"Yes", NULL
}, 0);
293 console_alertbox(CHAR16
**title
)
295 console_select(title
, (CHAR16
*[]){ L
"OK", 0 }, 0);
299 console_errorbox(CHAR16
*err
)
301 CHAR16
**err_arr
= (CHAR16
*[]){
310 console_alertbox(err_arr
);
314 console_notify(CHAR16
*string
)
316 CHAR16
**str_arr
= (CHAR16
*[]){
323 console_alertbox(str_arr
);
326 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
328 /* Copy of gnu-efi-3.0 with the added secure boot strings */
333 { EFI_SUCCESS
, L
"Success"},
334 { EFI_LOAD_ERROR
, L
"Load Error"},
335 { EFI_INVALID_PARAMETER
, L
"Invalid Parameter"},
336 { EFI_UNSUPPORTED
, L
"Unsupported"},
337 { EFI_BAD_BUFFER_SIZE
, L
"Bad Buffer Size"},
338 { EFI_BUFFER_TOO_SMALL
, L
"Buffer Too Small"},
339 { EFI_NOT_READY
, L
"Not Ready"},
340 { EFI_DEVICE_ERROR
, L
"Device Error"},
341 { EFI_WRITE_PROTECTED
, L
"Write Protected"},
342 { EFI_OUT_OF_RESOURCES
, L
"Out of Resources"},
343 { EFI_VOLUME_CORRUPTED
, L
"Volume Corrupt"},
344 { EFI_VOLUME_FULL
, L
"Volume Full"},
345 { EFI_NO_MEDIA
, L
"No Media"},
346 { EFI_MEDIA_CHANGED
, L
"Media changed"},
347 { EFI_NOT_FOUND
, L
"Not Found"},
348 { EFI_ACCESS_DENIED
, L
"Access Denied"},
349 { EFI_NO_RESPONSE
, L
"No Response"},
350 { EFI_NO_MAPPING
, L
"No mapping"},
351 { EFI_TIMEOUT
, L
"Time out"},
352 { EFI_NOT_STARTED
, L
"Not started"},
353 { EFI_ALREADY_STARTED
, L
"Already started"},
354 { EFI_ABORTED
, L
"Aborted"},
355 { EFI_ICMP_ERROR
, L
"ICMP Error"},
356 { EFI_TFTP_ERROR
, L
"TFTP Error"},
357 { EFI_PROTOCOL_ERROR
, L
"Protocol Error"},
358 { EFI_INCOMPATIBLE_VERSION
, L
"Incompatible Version"},
359 { EFI_SECURITY_VIOLATION
, L
"Security Violation"},
362 { EFI_WARN_UNKOWN_GLYPH
, L
"Warning Unknown Glyph"},
363 { EFI_WARN_DELETE_FAILURE
, L
"Warning Delete Failure"},
364 { EFI_WARN_WRITE_FAILURE
, L
"Warning Write Failure"},
365 { EFI_WARN_BUFFER_TOO_SMALL
, L
"Warning Buffer Too Small"},
377 for (Index
= 0; error_table
[Index
].Desc
; Index
+=1) {
378 if (error_table
[Index
].Code
== Status
) {
379 return error_table
[Index
].Desc
;
388 console_error(CHAR16
*err
, EFI_STATUS status
)
390 CHAR16
**err_arr
= (CHAR16
*[]){
398 SPrint(str
, sizeof(str
), L
"%s: (%d) %s", err
, status
, err_string(status
));
402 console_alertbox(err_arr
);
408 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
410 uefi_call_wrapper(co
->Reset
, 2, co
, TRUE
);
411 /* set mode 0 - required to be 80x25 */
412 uefi_call_wrapper(co
->SetMode
, 2, co
, 0);
413 uefi_call_wrapper(co
->ClearScreen
, 1, co
);
419 setup_verbosity(VOID
)
422 EFI_GUID guid
= SHIM_LOCK_GUID
;
424 UINTN verbose_check_size
;
426 verbose_check_size
= 1;
427 status
= get_variable(L
"SHIM_VERBOSE", (void *)&verbose_check
,
428 &verbose_check_size
, guid
);
430 if (!EFI_ERROR(status
))
431 verbose
= verbose_check
;
434 VOID
setup_console (int text
)
437 EFI_GUID console_control_guid
= EFI_CONSOLE_CONTROL_PROTOCOL_GUID
;
438 EFI_CONSOLE_CONTROL_PROTOCOL
*concon
;
439 static EFI_CONSOLE_CONTROL_SCREEN_MODE mode
=
440 EfiConsoleControlScreenGraphics
;
441 EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode
;
443 status
= LibLocateProtocol(&console_control_guid
, (VOID
**)&concon
);
444 if (status
!= EFI_SUCCESS
)
448 new_mode
= EfiConsoleControlScreenText
;
450 status
= uefi_call_wrapper(concon
->GetMode
, 4, concon
, &mode
,
452 /* If that didn't work, assume it's graphics */
453 if (status
!= EFI_SUCCESS
)
454 mode
= EfiConsoleControlScreenGraphics
;
459 uefi_call_wrapper(concon
->SetMode
, 2, concon
, new_mode
);