[U-Boot] [PATCH] efi_loader: Decouple EFI input/output from stdin/stdout

In some cases, it is quite useful to have (for example) EFI on screen but u-boot on serial port.
Signed-off-by: Rob Clark robdclark@gmail.com --- Applies on top of my previous efi_loader patchset.
lib/efi_loader/efi_console.c | 104 +++++++++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 24 deletions(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 139f7ea55b..e2b1b88ecf 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -47,6 +47,38 @@ static struct cout_mode efi_cout_modes[] = {
const efi_guid_t efi_guid_console_control = CONSOLE_CONTROL_GUID;
+static struct stdio_dev *efiin, *efiout; + +static int efi_tstc(void) +{ + return efiin->tstc(efiin); +} + +static int efi_getc(void) +{ + return efiin->getc(efiin); +} + +static int efi_printf(const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CONFIG_SYS_PBSIZE]; + + va_start(args, fmt); + + /* + * For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args); + va_end(args); + + /* Print the string */ + efiout->puts(efiout, printbuffer); + return i; +} + #define cESC '\x1b' #define ESC "\x1b"
@@ -111,16 +143,16 @@ static int term_read_reply(int *n, int maxnum, char end_char) char c; int i = 0;
- c = getc(); + c = efi_getc(); if (c != cESC) return -1; - c = getc(); + c = efi_getc(); if (c != '[') return -1;
n[0] = 0; while (1) { - c = getc(); + c = efi_getc(); if (c == ';') { i++; if (i >= maxnum) @@ -164,7 +196,7 @@ static efi_status_t EFIAPI efi_cout_output_string(
*utf16_to_utf8((u8 *)buf, string, n16) = '\0';
- fputs(stdout, buf); + efiout->puts(efiout, buf);
for (p = buf; *p; p++) { switch (*p) { @@ -217,14 +249,14 @@ static int query_console_serial(int *rows, int *cols) u64 timeout;
/* Empty input buffer */ - while (tstc()) - getc(); + while (efi_tstc()) + efi_getc();
- printf(ESC"[18t"); + efi_printf(ESC"[18t");
/* Check if we have a terminal that understands */ timeout = timer_get_us() + 1000000; - while (!tstc()) + while (!efi_tstc()) if (timer_get_us() > timeout) return -1;
@@ -348,9 +380,9 @@ static efi_status_t EFIAPI efi_cout_set_attribute( EFI_ENTRY("%p, %lx", this, attribute);
if (attribute) - printf(ESC"[%u;%um", color[fg].fg, color[bg].bg); + efi_printf(ESC"[%u;%um", color[fg].fg, color[bg].bg); else - printf(ESC"[37;40m"); + efi_printf(ESC"[37;40m");
/* Just ignore attributes (colors) for now */ return EFI_EXIT(EFI_UNSUPPORTED); @@ -361,7 +393,7 @@ static efi_status_t EFIAPI efi_cout_clear_screen( { EFI_ENTRY("%p", this);
- printf(ESC"[2J"); + efi_printf(ESC"[2J");
return EFI_EXIT(EFI_SUCCESS); } @@ -372,7 +404,7 @@ static efi_status_t EFIAPI efi_cout_set_cursor_position( { EFI_ENTRY("%p, %ld, %ld", this, column, row);
- printf(ESC"[%d;%df", (int)row, (int)column); + efi_printf(ESC"[%d;%df", (int)row, (int)column); efi_con_mode.cursor_column = column; efi_con_mode.cursor_row = row;
@@ -385,7 +417,7 @@ static efi_status_t EFIAPI efi_cout_enable_cursor( { EFI_ENTRY("%p, %d", this, enable);
- printf(ESC"[?25%c", enable ? 'h' : 'l'); + efi_printf(ESC"[?25%c", enable ? 'h' : 'l');
return EFI_EXIT(EFI_SUCCESS); } @@ -427,27 +459,27 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) /* We don't do interrupts, so check for timers cooperatively */ efi_timer_check();
- if (!tstc()) { + if (!efi_tstc()) { /* No key pressed */ return EFI_NOT_READY; }
- ch = getc(); + ch = efi_getc(); if (ch == cESC) { /* Escape Sequence */ - ch = getc(); + ch = efi_getc(); switch (ch) { case cESC: /* ESC */ pressed_key.scan_code = 23; break; case 'O': /* F1 - F4 */ - pressed_key.scan_code = getc() - 'P' + 11; + pressed_key.scan_code = efi_getc() - 'P' + 11; break; case 'a'...'z': ch = ch - 'a'; break; case '[': - ch = getc(); + ch = efi_getc(); switch (ch) { case 'A'...'D': /* up, down right, left */ pressed_key.scan_code = ch - 'A' + 1; @@ -459,16 +491,16 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) pressed_key.scan_code = 5; break; case '1': /* F5 - F8 */ - pressed_key.scan_code = getc() - '0' + 11; - getc(); + pressed_key.scan_code = efi_getc() - '0' + 11; + efi_getc(); break; case '2': /* F9 - F12 */ - pressed_key.scan_code = getc() - '0' + 19; - getc(); + pressed_key.scan_code = efi_getc() - '0' + 19; + efi_getc(); break; case '3': /* DEL */ pressed_key.scan_code = 8; - getc(); + efi_getc(); break; } break; @@ -521,7 +553,7 @@ static void EFIAPI efi_console_timer_notify(struct efi_event *event, void *context) { EFI_ENTRY("%p, %p", event, context); - if (tstc()) + if (efi_tstc()) efi_signal_event(efi_con_in.wait_for_key); EFI_EXIT(EFI_SUCCESS); } @@ -604,6 +636,27 @@ struct efi_object efi_console_input_obj = { .handle = &efi_console_input_obj, };
+static struct stdio_dev *get_stdio_dev(const char *envname, int default_dev) +{ + const char *name; + struct stdio_dev *dev = NULL; + + name = env_get(envname); + if (name) { + dev = stdio_get_by_name(name); + if (dev && dev->start) { + int ret = dev->start(dev); + if (ret < 0) + dev = NULL; + } + } + + if (!dev) + dev = stdio_devices[default_dev]; + + return dev; +} + /* This gets called from do_bootefi_exec(). */ int efi_console_register(void) { @@ -614,6 +667,9 @@ int efi_console_register(void) list_add_tail(&efi_console_output_obj.link, &efi_obj_list); list_add_tail(&efi_console_input_obj.link, &efi_obj_list);
+ efiout = get_stdio_dev("efiout", stdout); + efiin = get_stdio_dev("efiin", stdin); + r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify, NULL, &efi_con_in.wait_for_key); if (r != EFI_SUCCESS) {

On Mon, Sep 11, 2017 at 10:04 AM, Rob Clark robdclark@gmail.com wrote:
In some cases, it is quite useful to have (for example) EFI on screen but u-boot on serial port.
Signed-off-by: Rob Clark robdclark@gmail.com
Applies on top of my previous efi_loader patchset.
lib/efi_loader/efi_console.c | 104 +++++++++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 24 deletions(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 139f7ea55b..e2b1b88ecf 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -47,6 +47,38 @@ static struct cout_mode efi_cout_modes[] = {
const efi_guid_t efi_guid_console_control = CONSOLE_CONTROL_GUID;
+static struct stdio_dev *efiin, *efiout;
+static int efi_tstc(void) +{
return efiin->tstc(efiin);
+}
+static int efi_getc(void) +{
return efiin->getc(efiin);
+}
+static int efi_printf(const char *fmt, ...) +{
va_list args;
uint i;
char printbuffer[CONFIG_SYS_PBSIZE];
va_start(args, fmt);
/*
* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
va_end(args);
/* Print the string */
efiout->puts(efiout, printbuffer);
return i;
+}
#define cESC '\x1b' #define ESC "\x1b"
@@ -111,16 +143,16 @@ static int term_read_reply(int *n, int maxnum, char end_char) char c; int i = 0;
c = getc();
c = efi_getc(); if (c != cESC) return -1;
c = getc();
c = efi_getc(); if (c != '[') return -1; n[0] = 0; while (1) {
c = getc();
c = efi_getc(); if (c == ';') { i++; if (i >= maxnum)
@@ -164,7 +196,7 @@ static efi_status_t EFIAPI efi_cout_output_string(
*utf16_to_utf8((u8 *)buf, string, n16) = '\0';
fputs(stdout, buf);
efiout->puts(efiout, buf); for (p = buf; *p; p++) { switch (*p) {
@@ -217,14 +249,14 @@ static int query_console_serial(int *rows, int *cols) u64 timeout;
/* Empty input buffer */
while (tstc())
getc();
while (efi_tstc())
efi_getc();
printf(ESC"[18t");
efi_printf(ESC"[18t"); /* Check if we have a terminal that understands */ timeout = timer_get_us() + 1000000;
while (!tstc())
while (!efi_tstc()) if (timer_get_us() > timeout) return -1;
@@ -348,9 +380,9 @@ static efi_status_t EFIAPI efi_cout_set_attribute( EFI_ENTRY("%p, %lx", this, attribute);
if (attribute)
printf(ESC"[%u;%um", color[fg].fg, color[bg].bg);
efi_printf(ESC"[%u;%um", color[fg].fg, color[bg].bg); else
printf(ESC"[37;40m");
efi_printf(ESC"[37;40m"); /* Just ignore attributes (colors) for now */ return EFI_EXIT(EFI_UNSUPPORTED);
@@ -361,7 +393,7 @@ static efi_status_t EFIAPI efi_cout_clear_screen( { EFI_ENTRY("%p", this);
printf(ESC"[2J");
efi_printf(ESC"[2J"); return EFI_EXIT(EFI_SUCCESS);
} @@ -372,7 +404,7 @@ static efi_status_t EFIAPI efi_cout_set_cursor_position( { EFI_ENTRY("%p, %ld, %ld", this, column, row);
printf(ESC"[%d;%df", (int)row, (int)column);
efi_printf(ESC"[%d;%df", (int)row, (int)column); efi_con_mode.cursor_column = column; efi_con_mode.cursor_row = row;
@@ -385,7 +417,7 @@ static efi_status_t EFIAPI efi_cout_enable_cursor( { EFI_ENTRY("%p, %d", this, enable);
printf(ESC"[?25%c", enable ? 'h' : 'l');
efi_printf(ESC"[?25%c", enable ? 'h' : 'l'); return EFI_EXIT(EFI_SUCCESS);
} @@ -427,27 +459,27 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) /* We don't do interrupts, so check for timers cooperatively */ efi_timer_check();
if (!tstc()) {
if (!efi_tstc()) { /* No key pressed */ return EFI_NOT_READY; }
ch = getc();
ch = efi_getc(); if (ch == cESC) { /* Escape Sequence */
ch = getc();
ch = efi_getc(); switch (ch) { case cESC: /* ESC */ pressed_key.scan_code = 23; break; case 'O': /* F1 - F4 */
pressed_key.scan_code = getc() - 'P' + 11;
pressed_key.scan_code = efi_getc() - 'P' + 11; break; case 'a'...'z': ch = ch - 'a'; break; case '[':
ch = getc();
ch = efi_getc(); switch (ch) { case 'A'...'D': /* up, down right, left */ pressed_key.scan_code = ch - 'A' + 1;
@@ -459,16 +491,16 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) pressed_key.scan_code = 5; break; case '1': /* F5 - F8 */
pressed_key.scan_code = getc() - '0' + 11;
getc();
pressed_key.scan_code = efi_getc() - '0' + 11;
efi_getc(); break; case '2': /* F9 - F12 */
pressed_key.scan_code = getc() - '0' + 19;
getc();
pressed_key.scan_code = efi_getc() - '0' + 19;
efi_getc(); break; case '3': /* DEL */ pressed_key.scan_code = 8;
getc();
efi_getc(); break; } break;
@@ -521,7 +553,7 @@ static void EFIAPI efi_console_timer_notify(struct efi_event *event, void *context) { EFI_ENTRY("%p, %p", event, context);
if (tstc())
if (efi_tstc()) efi_signal_event(efi_con_in.wait_for_key); EFI_EXIT(EFI_SUCCESS);
} @@ -604,6 +636,27 @@ struct efi_object efi_console_input_obj = { .handle = &efi_console_input_obj, };
+static struct stdio_dev *get_stdio_dev(const char *envname, int default_dev) +{
const char *name;
struct stdio_dev *dev = NULL;
name = env_get(envname);
if (name) {
dev = stdio_get_by_name(name);
if (dev && dev->start) {
int ret = dev->start(dev);
if (ret < 0)
dev = NULL;
}
}
if (!dev)
dev = stdio_devices[default_dev];
btw, the one thing remaining holding up re-sending the efi_loader patches to get Shell.efi working is this one.. it isn't so much a problem with this patch, as much as that on the qemu-x86 target, printf() != fprintf(stdout), which breaks 'bootefi hello'.. I'm not quite sure yet what to do about that.
somehow stdio_devices[stdio] is vidconsole but printf() goes to serial, which the test is expecting. We could perhaps explicitly set 'stdout' env var somewhere. Although I suspect we should probably also fix puts() to be the same thing as fputs(stdout) and fix the various boards where that accidentally working before :-/
suggestions welcome.. I could drop this patch for now, since not strictly required, but I think we should somehow fix the root problem.
BR, -R
return dev;
+}
/* This gets called from do_bootefi_exec(). */ int efi_console_register(void) { @@ -614,6 +667,9 @@ int efi_console_register(void) list_add_tail(&efi_console_output_obj.link, &efi_obj_list); list_add_tail(&efi_console_input_obj.link, &efi_obj_list);
efiout = get_stdio_dev("efiout", stdout);
efiin = get_stdio_dev("efiin", stdin);
r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify, NULL, &efi_con_in.wait_for_key); if (r != EFI_SUCCESS) {
-- 2.13.5

On 10.10.17 02:27, Rob Clark wrote:
On Mon, Sep 11, 2017 at 10:04 AM, Rob Clark robdclark@gmail.com wrote:
In some cases, it is quite useful to have (for example) EFI on screen but u-boot on serial port.
Signed-off-by: Rob Clark robdclark@gmail.com
Applies on top of my previous efi_loader patchset.
lib/efi_loader/efi_console.c | 104 +++++++++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 24 deletions(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 139f7ea55b..e2b1b88ecf 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -47,6 +47,38 @@ static struct cout_mode efi_cout_modes[] = {
const efi_guid_t efi_guid_console_control = CONSOLE_CONTROL_GUID;
+static struct stdio_dev *efiin, *efiout;
+static int efi_tstc(void) +{
return efiin->tstc(efiin);
+}
+static int efi_getc(void) +{
return efiin->getc(efiin);
+}
+static int efi_printf(const char *fmt, ...) +{
va_list args;
uint i;
char printbuffer[CONFIG_SYS_PBSIZE];
va_start(args, fmt);
/*
* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
va_end(args);
/* Print the string */
efiout->puts(efiout, printbuffer);
return i;
+}
#define cESC '\x1b' #define ESC "\x1b"
@@ -111,16 +143,16 @@ static int term_read_reply(int *n, int maxnum, char end_char) char c; int i = 0;
c = getc();
c = efi_getc(); if (c != cESC) return -1;
c = getc();
c = efi_getc(); if (c != '[') return -1; n[0] = 0; while (1) {
c = getc();
c = efi_getc(); if (c == ';') { i++; if (i >= maxnum)
@@ -164,7 +196,7 @@ static efi_status_t EFIAPI efi_cout_output_string(
*utf16_to_utf8((u8 *)buf, string, n16) = '\0';
fputs(stdout, buf);
efiout->puts(efiout, buf); for (p = buf; *p; p++) { switch (*p) {
@@ -217,14 +249,14 @@ static int query_console_serial(int *rows, int *cols) u64 timeout;
/* Empty input buffer */
while (tstc())
getc();
while (efi_tstc())
efi_getc();
printf(ESC"[18t");
efi_printf(ESC"[18t"); /* Check if we have a terminal that understands */ timeout = timer_get_us() + 1000000;
while (!tstc())
while (!efi_tstc()) if (timer_get_us() > timeout) return -1;
@@ -348,9 +380,9 @@ static efi_status_t EFIAPI efi_cout_set_attribute( EFI_ENTRY("%p, %lx", this, attribute);
if (attribute)
printf(ESC"[%u;%um", color[fg].fg, color[bg].bg);
efi_printf(ESC"[%u;%um", color[fg].fg, color[bg].bg); else
printf(ESC"[37;40m");
efi_printf(ESC"[37;40m"); /* Just ignore attributes (colors) for now */ return EFI_EXIT(EFI_UNSUPPORTED);
@@ -361,7 +393,7 @@ static efi_status_t EFIAPI efi_cout_clear_screen( { EFI_ENTRY("%p", this);
printf(ESC"[2J");
efi_printf(ESC"[2J"); return EFI_EXIT(EFI_SUCCESS);
} @@ -372,7 +404,7 @@ static efi_status_t EFIAPI efi_cout_set_cursor_position( { EFI_ENTRY("%p, %ld, %ld", this, column, row);
printf(ESC"[%d;%df", (int)row, (int)column);
efi_printf(ESC"[%d;%df", (int)row, (int)column); efi_con_mode.cursor_column = column; efi_con_mode.cursor_row = row;
@@ -385,7 +417,7 @@ static efi_status_t EFIAPI efi_cout_enable_cursor( { EFI_ENTRY("%p, %d", this, enable);
printf(ESC"[?25%c", enable ? 'h' : 'l');
efi_printf(ESC"[?25%c", enable ? 'h' : 'l'); return EFI_EXIT(EFI_SUCCESS);
} @@ -427,27 +459,27 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) /* We don't do interrupts, so check for timers cooperatively */ efi_timer_check();
if (!tstc()) {
if (!efi_tstc()) { /* No key pressed */ return EFI_NOT_READY; }
ch = getc();
ch = efi_getc(); if (ch == cESC) { /* Escape Sequence */
ch = getc();
ch = efi_getc(); switch (ch) { case cESC: /* ESC */ pressed_key.scan_code = 23; break; case 'O': /* F1 - F4 */
pressed_key.scan_code = getc() - 'P' + 11;
pressed_key.scan_code = efi_getc() - 'P' + 11; break; case 'a'...'z': ch = ch - 'a'; break; case '[':
ch = getc();
ch = efi_getc(); switch (ch) { case 'A'...'D': /* up, down right, left */ pressed_key.scan_code = ch - 'A' + 1;
@@ -459,16 +491,16 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) pressed_key.scan_code = 5; break; case '1': /* F5 - F8 */
pressed_key.scan_code = getc() - '0' + 11;
getc();
pressed_key.scan_code = efi_getc() - '0' + 11;
efi_getc(); break; case '2': /* F9 - F12 */
pressed_key.scan_code = getc() - '0' + 19;
getc();
pressed_key.scan_code = efi_getc() - '0' + 19;
efi_getc(); break; case '3': /* DEL */ pressed_key.scan_code = 8;
getc();
efi_getc(); break; } break;
@@ -521,7 +553,7 @@ static void EFIAPI efi_console_timer_notify(struct efi_event *event, void *context) { EFI_ENTRY("%p, %p", event, context);
if (tstc())
if (efi_tstc()) efi_signal_event(efi_con_in.wait_for_key); EFI_EXIT(EFI_SUCCESS);
} @@ -604,6 +636,27 @@ struct efi_object efi_console_input_obj = { .handle = &efi_console_input_obj, };
+static struct stdio_dev *get_stdio_dev(const char *envname, int default_dev) +{
const char *name;
struct stdio_dev *dev = NULL;
name = env_get(envname);
if (name) {
dev = stdio_get_by_name(name);
if (dev && dev->start) {
int ret = dev->start(dev);
if (ret < 0)
dev = NULL;
}
}
if (!dev)
dev = stdio_devices[default_dev];
btw, the one thing remaining holding up re-sending the efi_loader patches to get Shell.efi working is this one.. it isn't so much a problem with this patch, as much as that on the qemu-x86 target, printf() != fprintf(stdout), which breaks 'bootefi hello'.. I'm not quite sure yet what to do about that.
Let's ask Bin and Simon :). There's a lot of magic in the putc() code to account for cases where device initialization didn't happen yet. Maybe the serial driver just wasn't probed properly yet?
Alex
somehow stdio_devices[stdio] is vidconsole but printf() goes to serial, which the test is expecting. We could perhaps explicitly set 'stdout' env var somewhere. Although I suspect we should probably also fix puts() to be the same thing as fputs(stdout) and fix the various boards where that accidentally working before :-/
suggestions welcome.. I could drop this patch for now, since not strictly required, but I think we should somehow fix the root problem.
BR, -R
return dev;
+}
/* This gets called from do_bootefi_exec(). */ int efi_console_register(void) { @@ -614,6 +667,9 @@ int efi_console_register(void) list_add_tail(&efi_console_output_obj.link, &efi_obj_list); list_add_tail(&efi_console_input_obj.link, &efi_obj_list);
efiout = get_stdio_dev("efiout", stdout);
efiin = get_stdio_dev("efiin", stdin);
r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify, NULL, &efi_con_in.wait_for_key); if (r != EFI_SUCCESS) {
-- 2.13.5

Hi,
On 10 October 2017 at 10:12, Alexander Graf agraf@suse.de wrote:
On 10.10.17 02:27, Rob Clark wrote:
On Mon, Sep 11, 2017 at 10:04 AM, Rob Clark robdclark@gmail.com wrote:
In some cases, it is quite useful to have (for example) EFI on screen but u-boot on serial port.
Signed-off-by: Rob Clark robdclark@gmail.com
Applies on top of my previous efi_loader patchset.
lib/efi_loader/efi_console.c | 104 +++++++++++++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 24 deletions(-)
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 139f7ea55b..e2b1b88ecf 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -47,6 +47,38 @@ static struct cout_mode efi_cout_modes[] = {
const efi_guid_t efi_guid_console_control = CONSOLE_CONTROL_GUID;
+static struct stdio_dev *efiin, *efiout;
+static int efi_tstc(void) +{
return efiin->tstc(efiin);
+}
+static int efi_getc(void) +{
return efiin->getc(efiin);
+}
+static int efi_printf(const char *fmt, ...) +{
va_list args;
uint i;
char printbuffer[CONFIG_SYS_PBSIZE];
va_start(args, fmt);
/*
* For this to work, printbuffer must be larger than
* anything we ever want to print.
*/
i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args);
va_end(args);
/* Print the string */
efiout->puts(efiout, printbuffer);
return i;
+}
#define cESC '\x1b' #define ESC "\x1b"
@@ -111,16 +143,16 @@ static int term_read_reply(int *n, int maxnum, char end_char) char c; int i = 0;
c = getc();
c = efi_getc(); if (c != cESC) return -1;
c = getc();
c = efi_getc(); if (c != '[') return -1; n[0] = 0; while (1) {
c = getc();
c = efi_getc(); if (c == ';') { i++; if (i >= maxnum)
@@ -164,7 +196,7 @@ static efi_status_t EFIAPI efi_cout_output_string(
*utf16_to_utf8((u8 *)buf, string, n16) = '\0';
fputs(stdout, buf);
efiout->puts(efiout, buf); for (p = buf; *p; p++) { switch (*p) {
@@ -217,14 +249,14 @@ static int query_console_serial(int *rows, int *cols) u64 timeout;
/* Empty input buffer */
while (tstc())
getc();
while (efi_tstc())
efi_getc();
printf(ESC"[18t");
efi_printf(ESC"[18t"); /* Check if we have a terminal that understands */ timeout = timer_get_us() + 1000000;
while (!tstc())
while (!efi_tstc()) if (timer_get_us() > timeout) return -1;
@@ -348,9 +380,9 @@ static efi_status_t EFIAPI efi_cout_set_attribute( EFI_ENTRY("%p, %lx", this, attribute);
if (attribute)
printf(ESC"[%u;%um", color[fg].fg, color[bg].bg);
efi_printf(ESC"[%u;%um", color[fg].fg, color[bg].bg); else
printf(ESC"[37;40m");
efi_printf(ESC"[37;40m"); /* Just ignore attributes (colors) for now */ return EFI_EXIT(EFI_UNSUPPORTED);
@@ -361,7 +393,7 @@ static efi_status_t EFIAPI efi_cout_clear_screen( { EFI_ENTRY("%p", this);
printf(ESC"[2J");
efi_printf(ESC"[2J"); return EFI_EXIT(EFI_SUCCESS);
} @@ -372,7 +404,7 @@ static efi_status_t EFIAPI efi_cout_set_cursor_position( { EFI_ENTRY("%p, %ld, %ld", this, column, row);
printf(ESC"[%d;%df", (int)row, (int)column);
efi_printf(ESC"[%d;%df", (int)row, (int)column); efi_con_mode.cursor_column = column; efi_con_mode.cursor_row = row;
@@ -385,7 +417,7 @@ static efi_status_t EFIAPI efi_cout_enable_cursor( { EFI_ENTRY("%p, %d", this, enable);
printf(ESC"[?25%c", enable ? 'h' : 'l');
efi_printf(ESC"[?25%c", enable ? 'h' : 'l'); return EFI_EXIT(EFI_SUCCESS);
} @@ -427,27 +459,27 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) /* We don't do interrupts, so check for timers cooperatively */ efi_timer_check();
if (!tstc()) {
if (!efi_tstc()) { /* No key pressed */ return EFI_NOT_READY; }
ch = getc();
ch = efi_getc(); if (ch == cESC) { /* Escape Sequence */
ch = getc();
ch = efi_getc(); switch (ch) { case cESC: /* ESC */ pressed_key.scan_code = 23; break; case 'O': /* F1 - F4 */
pressed_key.scan_code = getc() - 'P' + 11;
pressed_key.scan_code = efi_getc() - 'P' + 11; break; case 'a'...'z': ch = ch - 'a'; break; case '[':
ch = getc();
ch = efi_getc(); switch (ch) { case 'A'...'D': /* up, down right, left */ pressed_key.scan_code = ch - 'A' + 1;
@@ -459,16 +491,16 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) pressed_key.scan_code = 5; break; case '1': /* F5 - F8 */
pressed_key.scan_code = getc() - '0' + 11;
getc();
pressed_key.scan_code = efi_getc() - '0' + 11;
efi_getc(); break; case '2': /* F9 - F12 */
pressed_key.scan_code = getc() - '0' + 19;
getc();
pressed_key.scan_code = efi_getc() - '0' + 19;
efi_getc(); break; case '3': /* DEL */ pressed_key.scan_code = 8;
getc();
efi_getc(); break; } break;
@@ -521,7 +553,7 @@ static void EFIAPI efi_console_timer_notify(struct efi_event *event, void *context) { EFI_ENTRY("%p, %p", event, context);
if (tstc())
if (efi_tstc()) efi_signal_event(efi_con_in.wait_for_key); EFI_EXIT(EFI_SUCCESS);
} @@ -604,6 +636,27 @@ struct efi_object efi_console_input_obj = { .handle = &efi_console_input_obj, };
+static struct stdio_dev *get_stdio_dev(const char *envname, int default_dev) +{
const char *name;
struct stdio_dev *dev = NULL;
name = env_get(envname);
if (name) {
dev = stdio_get_by_name(name);
if (dev && dev->start) {
int ret = dev->start(dev);
if (ret < 0)
dev = NULL;
}
}
if (!dev)
dev = stdio_devices[default_dev];
btw, the one thing remaining holding up re-sending the efi_loader patches to get Shell.efi working is this one.. it isn't so much a problem with this patch, as much as that on the qemu-x86 target, printf() != fprintf(stdout), which breaks 'bootefi hello'.. I'm not quite sure yet what to do about that.
Let's ask Bin and Simon :). There's a lot of magic in the putc() code to account for cases where device initialization didn't happen yet. Maybe the serial driver just wasn't probed properly yet?
That magic should be ignored for EFI - once console_init_r() is called we are in a 'normal' state.
It's funny that (in that state) you see that inconsistency. I cannot think of a reason for it, but more study might perhaps provide an explanation.
Regards, Simon
participants (3)
-
Alexander Graf
-
Rob Clark
-
Simon Glass