2 * Copyright 2012 <James.Bottomley@HansenPartnership.com>
3 * Copyright 2013 Red Hat Inc. <pjones@redhat.com>
8 #include <efi/efilib.h>
13 static int min(int a
, int b
)
21 count_lines(CHAR16
*str_arr
[])
31 SetMem16(CHAR16
*dst
, UINT32 n
, CHAR16 c
)
35 for (i
= 0; i
< n
/2; i
++) {
41 console_get_keystroke(void)
46 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1, &ST
->ConIn
->WaitForKey
, &EventIndex
);
47 uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2, ST
->ConIn
, &key
);
53 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
)
56 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
63 uefi_call_wrapper(co
->QueryMode
, 4, co
, co
->Mode
->Mode
, &cols
, &rows
);
65 /* last row on screen is unusable without scrolling, so ignore it */
69 size_rows
= rows
+ size_rows
+ 1;
71 size_cols
= cols
+ size_cols
+ 1;
74 start_col
= (cols
+ start_col
+ 2)/2;
76 start_row
= (rows
+ start_row
+ 2)/2;
82 if (start_col
> cols
|| start_row
> rows
) {
83 Print(L
"Starting Position (%d,%d) is off screen\n",
84 start_col
, start_row
);
87 if (size_cols
+ start_col
> cols
)
88 size_cols
= cols
- start_col
;
89 if (size_rows
+ start_row
> rows
)
90 size_rows
= rows
- start_row
;
92 if (lines
> size_rows
- 2)
93 lines
= size_rows
- 2;
95 Line
= AllocatePool((size_cols
+1)*sizeof(CHAR16
));
97 Print(L
"Failed Allocation\n");
101 SetMem16 (Line
, size_cols
* 2, BOXDRAW_HORIZONTAL
);
103 Line
[0] = BOXDRAW_DOWN_RIGHT
;
104 Line
[size_cols
- 1] = BOXDRAW_DOWN_LEFT
;
105 Line
[size_cols
] = L
'\0';
106 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, start_row
);
107 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
112 start
= (size_rows
- lines
)/2 + start_row
+ offset
;
115 start
= start_row
+ size_rows
- lines
+ offset
- 1;
118 start
= start_row
+ offset
;
121 for (i
= start_row
+ 1; i
< size_rows
+ start_row
- 1; i
++) {
122 int line
= i
- start
;
124 SetMem16 (Line
, size_cols
*2, L
' ');
125 Line
[0] = BOXDRAW_VERTICAL
;
126 Line
[size_cols
- 1] = BOXDRAW_VERTICAL
;
127 Line
[size_cols
] = L
'\0';
128 if (line
>= 0 && line
< lines
) {
129 CHAR16
*s
= str_arr
[line
];
131 int col
= (size_cols
- 2 - len
)/2;
136 CopyMem(Line
+ col
+ 1, s
, min(len
, size_cols
- 2)*2);
138 if (line
>= 0 && line
== highlight
)
139 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLACK
);
140 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, i
);
141 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
142 if (line
>= 0 && line
== highlight
)
143 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
146 SetMem16 (Line
, size_cols
* 2, BOXDRAW_HORIZONTAL
);
147 Line
[0] = BOXDRAW_UP_RIGHT
;
148 Line
[size_cols
- 1] = BOXDRAW_UP_LEFT
;
149 Line
[size_cols
] = L
'\0';
150 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, start_col
, i
);
151 uefi_call_wrapper(co
->OutputString
, 2, co
, Line
);
158 console_print_box(CHAR16
*str_arr
[], int highlight
)
160 SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode
;
161 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
162 CopyMem(&SavedConsoleMode
, co
->Mode
, sizeof(SavedConsoleMode
));
163 uefi_call_wrapper(co
->EnableCursor
, 2, co
, FALSE
);
164 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
166 console_print_box_at(str_arr
, highlight
, 0, 0, -1, -1, 0,
167 count_lines(str_arr
));
169 console_get_keystroke();
171 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
173 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
174 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, SavedConsoleMode
.CursorColumn
, SavedConsoleMode
.CursorRow
);
175 uefi_call_wrapper(co
->SetAttribute
, 2, co
, SavedConsoleMode
.Attribute
);
179 console_select(CHAR16
*title
[], CHAR16
* selectors
[], int start
)
181 SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode
;
182 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
185 int selector_lines
= count_lines(selectors
);
186 int selector_max_cols
= 0;
187 int i
, offs_col
, offs_row
, size_cols
, size_rows
, lines
;
191 uefi_call_wrapper(co
->QueryMode
, 4, co
, co
->Mode
->Mode
, &cols
, &rows
);
193 for (i
= 0; i
< selector_lines
; i
++) {
194 int len
= StrLen(selectors
[i
]);
196 if (len
> selector_max_cols
)
197 selector_max_cols
= len
;
202 if (start
>= selector_lines
)
203 start
= selector_lines
- 1;
205 offs_col
= - selector_max_cols
- 4;
206 size_cols
= selector_max_cols
+ 4;
208 if (selector_lines
> rows
- 10) {
209 int title_lines
= count_lines(title
);
210 offs_row
= title_lines
+ 1;
211 size_rows
= rows
- 3 - title_lines
;
212 lines
= size_rows
- 2;
214 offs_row
= - selector_lines
- 4;
215 size_rows
= selector_lines
+ 2;
216 lines
= selector_lines
;
221 selector_offset
= start
- lines
;
227 CopyMem(&SavedConsoleMode
, co
->Mode
, sizeof(SavedConsoleMode
));
228 uefi_call_wrapper(co
->EnableCursor
, 2, co
, FALSE
);
229 uefi_call_wrapper(co
->SetAttribute
, 2, co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
231 console_print_box_at(title
, -1, 0, 0, -1, -1, 1, count_lines(title
));
233 console_print_box_at(selectors
, selector
, offs_col
, offs_row
,
234 size_cols
, size_rows
, 0, lines
);
237 k
= console_get_keystroke();
239 if (k
.ScanCode
== SCAN_ESC
) {
244 if (k
.ScanCode
== SCAN_UP
) {
247 else if (selector_offset
> 0)
249 } else if (k
.ScanCode
== SCAN_DOWN
) {
250 if (selector
< lines
- 1)
252 else if (selector_offset
< (selector_lines
- lines
))
256 console_print_box_at(&selectors
[selector_offset
], selector
,
258 size_cols
, size_rows
, 0, lines
);
259 } while (!(k
.ScanCode
== SCAN_NULL
260 && k
.UnicodeChar
== CHAR_CARRIAGE_RETURN
));
262 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
264 uefi_call_wrapper(co
->EnableCursor
, 2, co
, SavedConsoleMode
.CursorVisible
);
265 uefi_call_wrapper(co
->SetCursorPosition
, 3, co
, SavedConsoleMode
.CursorColumn
, SavedConsoleMode
.CursorRow
);
266 uefi_call_wrapper(co
->SetAttribute
, 2, co
, SavedConsoleMode
.Attribute
);
271 return selector
+ selector_offset
;
276 console_yes_no(CHAR16
*str_arr
[])
278 return console_select(str_arr
, (CHAR16
*[]){ L
"No", L
"Yes", NULL
}, 0);
282 console_alertbox(CHAR16
**title
)
284 console_select(title
, (CHAR16
*[]){ L
"OK", 0 }, 0);
288 console_errorbox(CHAR16
*err
)
290 CHAR16
**err_arr
= (CHAR16
*[]){
299 console_alertbox(err_arr
);
303 console_notify(CHAR16
*string
)
305 CHAR16
**str_arr
= (CHAR16
*[]){
312 console_alertbox(str_arr
);
315 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
317 /* Copy of gnu-efi-3.0 with the added secure boot strings */
322 { EFI_SUCCESS
, L
"Success"},
323 { EFI_LOAD_ERROR
, L
"Load Error"},
324 { EFI_INVALID_PARAMETER
, L
"Invalid Parameter"},
325 { EFI_UNSUPPORTED
, L
"Unsupported"},
326 { EFI_BAD_BUFFER_SIZE
, L
"Bad Buffer Size"},
327 { EFI_BUFFER_TOO_SMALL
, L
"Buffer Too Small"},
328 { EFI_NOT_READY
, L
"Not Ready"},
329 { EFI_DEVICE_ERROR
, L
"Device Error"},
330 { EFI_WRITE_PROTECTED
, L
"Write Protected"},
331 { EFI_OUT_OF_RESOURCES
, L
"Out of Resources"},
332 { EFI_VOLUME_CORRUPTED
, L
"Volume Corrupt"},
333 { EFI_VOLUME_FULL
, L
"Volume Full"},
334 { EFI_NO_MEDIA
, L
"No Media"},
335 { EFI_MEDIA_CHANGED
, L
"Media changed"},
336 { EFI_NOT_FOUND
, L
"Not Found"},
337 { EFI_ACCESS_DENIED
, L
"Access Denied"},
338 { EFI_NO_RESPONSE
, L
"No Response"},
339 { EFI_NO_MAPPING
, L
"No mapping"},
340 { EFI_TIMEOUT
, L
"Time out"},
341 { EFI_NOT_STARTED
, L
"Not started"},
342 { EFI_ALREADY_STARTED
, L
"Already started"},
343 { EFI_ABORTED
, L
"Aborted"},
344 { EFI_ICMP_ERROR
, L
"ICMP Error"},
345 { EFI_TFTP_ERROR
, L
"TFTP Error"},
346 { EFI_PROTOCOL_ERROR
, L
"Protocol Error"},
347 { EFI_INCOMPATIBLE_VERSION
, L
"Incompatible Version"},
348 { EFI_SECURITY_VIOLATION
, L
"Security Violation"},
351 { EFI_WARN_UNKOWN_GLYPH
, L
"Warning Unknown Glyph"},
352 { EFI_WARN_DELETE_FAILURE
, L
"Warning Delete Failure"},
353 { EFI_WARN_WRITE_FAILURE
, L
"Warning Write Failure"},
354 { EFI_WARN_BUFFER_TOO_SMALL
, L
"Warning Buffer Too Small"},
366 for (Index
= 0; error_table
[Index
].Desc
; Index
+=1) {
367 if (error_table
[Index
].Code
== Status
) {
368 return error_table
[Index
].Desc
;
377 console_error(CHAR16
*err
, EFI_STATUS status
)
379 CHAR16
**err_arr
= (CHAR16
*[]){
387 SPrint(str
, sizeof(str
), L
"%s: (%d) %s", err
, status
, err_string(status
));
391 console_alertbox(err_arr
);
397 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
399 uefi_call_wrapper(co
->Reset
, 2, co
, TRUE
);
400 /* set mode 0 - required to be 80x25 */
401 uefi_call_wrapper(co
->SetMode
, 2, co
, 0);
402 uefi_call_wrapper(co
->ClearScreen
, 1, co
);
405 VOID
setup_console (int text
)
408 EFI_GUID console_control_guid
= EFI_CONSOLE_CONTROL_PROTOCOL_GUID
;
409 EFI_CONSOLE_CONTROL_PROTOCOL
*concon
;
410 static EFI_CONSOLE_CONTROL_SCREEN_MODE mode
=
411 EfiConsoleControlScreenGraphics
;
412 EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode
;
414 status
= LibLocateProtocol(&console_control_guid
, (VOID
**)&concon
);
415 if (status
!= EFI_SUCCESS
)
419 new_mode
= EfiConsoleControlScreenText
;
421 status
= uefi_call_wrapper(concon
->GetMode
, 4, concon
, &mode
,
423 /* If that didn't work, assume it's graphics */
424 if (status
!= EFI_SUCCESS
)
425 mode
= EfiConsoleControlScreenGraphics
;
430 uefi_call_wrapper(concon
->SetMode
, 2, concon
, new_mode
);