2 * Copyright 2012 <James.Bottomley@HansenPartnership.com>
3 * Copyright 2013 Red Hat Inc. <pjones@redhat.com>
8 #include <efi/efilib.h>
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(void)
49 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1, &ST
->ConIn
->WaitForKey
, &EventIndex
);
50 uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2, ST
->ConIn
, &key
);
56 console_print_box_at(CHAR16
*str_arr
[], int highlight
, int start_col
, int start_row
, int size_cols
, int size_rows
, int offset
, int lines
)
59 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
66 uefi_call_wrapper(co
->QueryMode
, 4, co
, co
->Mode
->Mode
, &cols
, &rows
);
68 /* last row on screen is unusable without scrolling, so ignore it */
72 size_rows
= rows
+ size_rows
+ 1;
74 size_cols
= cols
+ size_cols
+ 1;
77 start_col
= (cols
+ start_col
+ 2)/2;
79 start_row
= (rows
+ start_row
+ 2)/2;
85 if (start_col
> cols
|| start_row
> rows
) {
86 Print(L
"Starting Position (%d,%d) is off screen\n",
87 start_col
, start_row
);
90 if (size_cols
+ start_col
> cols
)
91 size_cols
= cols
- start_col
;
92 if (size_rows
+ start_row
> rows
)
93 size_rows
= rows
- start_row
;
95 if (lines
> size_rows
- 2)
96 lines
= size_rows
- 2;
98 Line
= AllocatePool((size_cols
+1)*sizeof(CHAR16
));
100 Print(L
"Failed Allocation\n");
104 SetMem16 (Line
, size_cols
* 2, BOXDRAW_HORIZONTAL
);
106 Line
[0] = BOXDRAW_DOWN_RIGHT
;
107 Line
[size_cols
- 1] = BOXDRAW_DOWN_LEFT
;
108 Line
[size_cols
] = L
'\0';
109 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, start_row
);
110 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
115 start
= (size_rows
- lines
)/2 + start_row
+ offset
;
118 start
= start_row
+ size_rows
- lines
+ offset
- 1;
121 start
= start_row
+ offset
;
124 for (i
= start_row
+ 1; i
< size_rows
+ start_row
- 1; i
++) {
125 int line
= i
- start
;
127 SetMem16 (Line
, size_cols
*2, L
' ');
128 Line
[0] = BOXDRAW_VERTICAL
;
129 Line
[size_cols
- 1] = BOXDRAW_VERTICAL
;
130 Line
[size_cols
] = L
'\0';
131 if (line
>= 0 && line
< lines
) {
132 CHAR16
*s
= str_arr
[line
];
134 int col
= (size_cols
- 2 - len
)/2;
139 CopyMem(Line
+ col
+ 1, s
, min(len
, size_cols
- 2)*2);
141 if (line
>= 0 && line
== highlight
)
142 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLACK
);
143 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, i
);
144 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
145 if (line
>= 0 && line
== highlight
)
146 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
149 SetMem16 (Line
, size_cols
* 2, BOXDRAW_HORIZONTAL
);
150 Line
[0] = BOXDRAW_UP_RIGHT
;
151 Line
[size_cols
- 1] = BOXDRAW_UP_LEFT
;
152 Line
[size_cols
] = L
'\0';
153 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, i
);
154 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
161 console_print_box(CHAR16
*str_arr
[], int highlight
)
163 SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode
;
164 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
165 CopyMem(&SavedConsoleMode
, co
->Mode
, sizeof(SavedConsoleMode
));
166 uefi_call_wrapper(co
->EnableCursor
, 2, co
, FALSE
);
167 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
169 console_print_box_at(str_arr
, highlight
, 0, 0, -1, -1, 0,
170 count_lines(str_arr
));
172 console_get_keystroke();
174 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
176 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
177 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, SavedConsoleMode
.CursorColumn
, SavedConsoleMode
.CursorRow
);
178 uefi_call_wrapper(co
->SetAttribute
, 2, co
, SavedConsoleMode
.Attribute
);
182 console_select(CHAR16
*title
[], CHAR16
* selectors
[], int start
)
184 SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode
;
185 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
188 int selector_lines
= count_lines(selectors
);
189 int selector_max_cols
= 0;
190 int i
, offs_col
, offs_row
, size_cols
, size_rows
, lines
;
194 uefi_call_wrapper(co
->QueryMode
, 4, co
, co
->Mode
->Mode
, &cols
, &rows
);
196 for (i
= 0; i
< selector_lines
; i
++) {
197 int len
= StrLen(selectors
[i
]);
199 if (len
> selector_max_cols
)
200 selector_max_cols
= len
;
205 if (start
>= selector_lines
)
206 start
= selector_lines
- 1;
208 offs_col
= - selector_max_cols
- 4;
209 size_cols
= selector_max_cols
+ 4;
211 if (selector_lines
> rows
- 10) {
212 int title_lines
= count_lines(title
);
213 offs_row
= title_lines
+ 1;
214 size_rows
= rows
- 3 - title_lines
;
215 lines
= size_rows
- 2;
217 offs_row
= - selector_lines
- 4;
218 size_rows
= selector_lines
+ 2;
219 lines
= selector_lines
;
224 selector_offset
= start
- lines
;
230 CopyMem(&SavedConsoleMode
, co
->Mode
, sizeof(SavedConsoleMode
));
231 uefi_call_wrapper(co
->EnableCursor
, 2, co
, FALSE
);
232 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
234 console_print_box_at(title
, -1, 0, 0, -1, -1, 1, count_lines(title
));
236 console_print_box_at(selectors
, selector
, offs_col
, offs_row
,
237 size_cols
, size_rows
, 0, lines
);
240 k
= console_get_keystroke();
242 if (k
.ScanCode
== SCAN_ESC
) {
247 if (k
.ScanCode
== SCAN_UP
) {
250 else if (selector_offset
> 0)
252 } else if (k
.ScanCode
== SCAN_DOWN
) {
253 if (selector
< lines
- 1)
255 else if (selector_offset
< (selector_lines
- lines
))
259 console_print_box_at(&selectors
[selector_offset
], selector
,
261 size_cols
, size_rows
, 0, lines
);
262 } while (!(k
.ScanCode
== SCAN_NULL
263 && k
.UnicodeChar
== CHAR_CARRIAGE_RETURN
));
265 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
267 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
268 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, SavedConsoleMode
.CursorColumn
, SavedConsoleMode
.CursorRow
);
269 uefi_call_wrapper(co
->SetAttribute
, 2, co
, SavedConsoleMode
.Attribute
);
274 return selector
+ selector_offset
;
279 console_yes_no(CHAR16
*str_arr
[])
281 return console_select(str_arr
, (CHAR16
*[]){ L
"No", L
"Yes", NULL
}, 0);
285 console_alertbox(CHAR16
**title
)
287 console_select(title
, (CHAR16
*[]){ L
"OK", 0 }, 0);
291 console_errorbox(CHAR16
*err
)
293 CHAR16
**err_arr
= (CHAR16
*[]){
302 console_alertbox(err_arr
);
306 console_notify(CHAR16
*string
)
308 CHAR16
**str_arr
= (CHAR16
*[]){
315 console_alertbox(str_arr
);
318 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
320 /* Copy of gnu-efi-3.0 with the added secure boot strings */
325 { EFI_SUCCESS
, L
"Success"},
326 { EFI_LOAD_ERROR
, L
"Load Error"},
327 { EFI_INVALID_PARAMETER
, L
"Invalid Parameter"},
328 { EFI_UNSUPPORTED
, L
"Unsupported"},
329 { EFI_BAD_BUFFER_SIZE
, L
"Bad Buffer Size"},
330 { EFI_BUFFER_TOO_SMALL
, L
"Buffer Too Small"},
331 { EFI_NOT_READY
, L
"Not Ready"},
332 { EFI_DEVICE_ERROR
, L
"Device Error"},
333 { EFI_WRITE_PROTECTED
, L
"Write Protected"},
334 { EFI_OUT_OF_RESOURCES
, L
"Out of Resources"},
335 { EFI_VOLUME_CORRUPTED
, L
"Volume Corrupt"},
336 { EFI_VOLUME_FULL
, L
"Volume Full"},
337 { EFI_NO_MEDIA
, L
"No Media"},
338 { EFI_MEDIA_CHANGED
, L
"Media changed"},
339 { EFI_NOT_FOUND
, L
"Not Found"},
340 { EFI_ACCESS_DENIED
, L
"Access Denied"},
341 { EFI_NO_RESPONSE
, L
"No Response"},
342 { EFI_NO_MAPPING
, L
"No mapping"},
343 { EFI_TIMEOUT
, L
"Time out"},
344 { EFI_NOT_STARTED
, L
"Not started"},
345 { EFI_ALREADY_STARTED
, L
"Already started"},
346 { EFI_ABORTED
, L
"Aborted"},
347 { EFI_ICMP_ERROR
, L
"ICMP Error"},
348 { EFI_TFTP_ERROR
, L
"TFTP Error"},
349 { EFI_PROTOCOL_ERROR
, L
"Protocol Error"},
350 { EFI_INCOMPATIBLE_VERSION
, L
"Incompatible Version"},
351 { EFI_SECURITY_VIOLATION
, L
"Security Violation"},
354 { EFI_WARN_UNKOWN_GLYPH
, L
"Warning Unknown Glyph"},
355 { EFI_WARN_DELETE_FAILURE
, L
"Warning Delete Failure"},
356 { EFI_WARN_WRITE_FAILURE
, L
"Warning Write Failure"},
357 { EFI_WARN_BUFFER_TOO_SMALL
, L
"Warning Buffer Too Small"},
369 for (Index
= 0; error_table
[Index
].Desc
; Index
+=1) {
370 if (error_table
[Index
].Code
== Status
) {
371 return error_table
[Index
].Desc
;
380 console_error(CHAR16
*err
, EFI_STATUS status
)
382 CHAR16
**err_arr
= (CHAR16
*[]){
390 SPrint(str
, sizeof(str
), L
"%s: (%d) %s", err
, status
, err_string(status
));
394 console_alertbox(err_arr
);
400 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
402 uefi_call_wrapper(co
->Reset
, 2, co
, TRUE
);
403 /* set mode 0 - required to be 80x25 */
404 uefi_call_wrapper(co
->SetMode
, 2, co
, 0);
405 uefi_call_wrapper(co
->ClearScreen
, 1, co
);
411 setup_verbosity(VOID
)
414 EFI_GUID guid
= SHIM_LOCK_GUID
;
416 UINTN verbose_check_size
;
418 verbose_check_size
= 1;
419 status
= get_variable(L
"SHIM_VERBOSE", (void *)&verbose_check
,
420 &verbose_check_size
, guid
);
422 if (!EFI_ERROR(status
))
423 verbose
= verbose_check
;
426 VOID
setup_console (int text
)
429 EFI_GUID console_control_guid
= EFI_CONSOLE_CONTROL_PROTOCOL_GUID
;
430 EFI_CONSOLE_CONTROL_PROTOCOL
*concon
;
431 static EFI_CONSOLE_CONTROL_SCREEN_MODE mode
=
432 EfiConsoleControlScreenGraphics
;
433 EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode
;
435 status
= LibLocateProtocol(&console_control_guid
, (VOID
**)&concon
);
436 if (status
!= EFI_SUCCESS
)
440 new_mode
= EfiConsoleControlScreenText
;
442 status
= uefi_call_wrapper(concon
->GetMode
, 4, concon
, &mode
,
444 /* If that didn't work, assume it's graphics */
445 if (status
!= EFI_SUCCESS
)
446 mode
= EfiConsoleControlScreenGraphics
;
451 uefi_call_wrapper(concon
->SetMode
, 2, concon
, new_mode
);