From patchwork Tue Oct 10 12:23:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 823808 X-Patchwork-Delegate: agraf@suse.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ExqjMlTu"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3yBGYn3NfNz9tY3 for ; Tue, 10 Oct 2017 23:26:21 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 25913C21D84; Tue, 10 Oct 2017 12:25:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 6EE21C21C50; Tue, 10 Oct 2017 12:24:25 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 7A3F3C21DB2; Tue, 10 Oct 2017 12:23:45 +0000 (UTC) Received: from mail-qt0-f195.google.com (mail-qt0-f195.google.com [209.85.216.195]) by lists.denx.de (Postfix) with ESMTPS id 4B482C21D55 for ; Tue, 10 Oct 2017 12:23:40 +0000 (UTC) Received: by mail-qt0-f195.google.com with SMTP id o52so50482399qtc.9 for ; Tue, 10 Oct 2017 05:23:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=UYfX2VWcD7h3DKmirYp5QVObzmGqacbV80y0TG19/vs=; b=ExqjMlTuzE1MFFrwW3U9pnTAlpoqDl26uCwRgUeUlOai7uTeAi7QYBLSKhyZhLS0p0 pSQdNUqmFQEcrNtxywo4apQ6du57DprNSD5oFrUP+fYwxITRswxe6zTk0nBNKy2Gf5Y2 2DAhiIxXoFU2J6Kctl1t+eowpYysqTsHtNMUL7S6Jn8dKmLzDhboS4/Xya6lE8Fh/NTP Iyoiys6QjBPJOYcUP75uQmK23WDSJIcg70tkDUcU6IzWYo0cq5iWtPcRwvOipfmBwsnQ FlVHWRyHiXFf1Uhfm0/GhSofhH7KymEYJ30WvcOKVYYRzlkfM3vSFFJPOmodm6fwlRa6 rc+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=UYfX2VWcD7h3DKmirYp5QVObzmGqacbV80y0TG19/vs=; b=udXrpWnHLBWHg3uD11SncsRjha5pW8VGv443yRvdiIW6v6zLVM9ckBjE8DB7sNF3tw M1pzqWlCZo//2g5/LZcuHhMKtGKyS20EIkKTrCYMyQKaRv5VCbEl6pXZL5nwVZ/flqAq 9cuYpQLTOdX9V08yn0drdylkXoIwn1OSdOQ/e9R3rx7yVHHfqlGFPvF640dgLW1sLFuw 8CATBZoKbgZn57Tk6jfOQBAydhlbaopLHIFmG5AbInOqL03o41vSgSiGckFBpL4Ic7pn SN+86U1PeBRyrqWuERr5xUPOIftn2iu4OUdN6OV2PZgdEPFYZ351VdmMWEhyFy/iMtFo PddQ== X-Gm-Message-State: AMCzsaUoBbb2e4LHQfrSmeYWZB3WUERJ2xJMx0LD6hXPAbc87fwdStbB gTC27O8jYephG1w+lPlWNG7NM3cr X-Google-Smtp-Source: AOwi7QB9ThYRLNWmFurJAZWNKYy6RuapQDRdSg6FhLzOb3yTWyp+xOym/AOBJ/E8Or0X4eLa3rFN+A== X-Received: by 10.237.60.249 with SMTP id e54mr19044834qtf.23.1507638218879; Tue, 10 Oct 2017 05:23:38 -0700 (PDT) Received: from localhost ([144.121.20.162]) by smtp.gmail.com with ESMTPSA id i92sm6330660qtb.65.2017.10.10.05.23.37 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 10 Oct 2017 05:23:37 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Tue, 10 Oct 2017 08:23:02 -0400 Message-Id: <20171010122309.25313-7-robdclark@gmail.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20171010122309.25313-1-robdclark@gmail.com> References: <20171010122309.25313-1-robdclark@gmail.com> Cc: Heinrich Schuchardt , Leif Lindholm Subject: [U-Boot] [PATCH 06/11] efi_loader: Decouple EFI input/output from stdin/stdout X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" In some cases, it is quite useful to have (for example) EFI on screen but u-boot on serial port. This adds two new optional environment variables, "efiin" and "efiout", which can be used to set EFI console input/output independently of u-boot's input/output. If unset, EFI console will default to stdin/ stdout as before. Signed-off-by: Rob Clark --- As mentioned yesterday, this triggers some problems w/ qemu + 'bootefi hello' since puts() != fputs(stdout). So you can hold off applying this one for now if you want until we figure out a solution. It is not strictly required, only nice-to-have (and nice for enabling debug traces on serial without interfering with Shell.efi output on screen) lib/efi_loader/efi_console.c | 111 ++++++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 29 deletions(-) diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index c25d6b16f2..1333f9cb71 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; @@ -246,16 +278,13 @@ static efi_status_t EFIAPI efi_cout_query_mode( EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows); if (!console_size_queried) { - const char *stdout_name = env_get("stdout"); int rows, cols; console_size_queried = true; - if (stdout_name && !strcmp(stdout_name, "vidconsole") && + if (!strcmp(efiout->name, "vidconsole") && IS_ENABLED(CONFIG_DM_VIDEO)) { - struct stdio_dev *stdout_dev = - stdio_get_by_name("vidconsole"); - struct udevice *dev = stdout_dev->priv; + struct udevice *dev = efiout->priv; struct vidconsole_priv *priv = dev_get_uclass_priv(dev); rows = priv->rows; @@ -342,9 +371,9 @@ static efi_status_t EFIAPI efi_cout_set_attribute( EFI_ENTRY("%p, %lx", this, attribute); if (attribute) - printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg); + efi_printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg); else - printf(ESC"[0;37;40m"); + efi_printf(ESC"[0;37;40m"); return EFI_EXIT(EFI_SUCCESS); } @@ -354,7 +383,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); } @@ -365,7 +394,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; @@ -378,7 +407,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); } @@ -464,28 +493,28 @@ static efi_status_t read_key_stroke(struct efi_key_data *key_data) }; char ch; - 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': key_state.key_shift_state = EFI_SHIFT_STATE_VALID | EFI_EFI_LEFT_ALT_PRESSED; break; case '[': - ch = getc(); + ch = efi_getc(); switch (ch) { case 'A'...'D': /* up, down right, left */ pressed_key.scan_code = ch - 'A' + 1; @@ -497,16 +526,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; @@ -584,7 +613,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()) { read_keys(); efi_con_in.wait_for_key->is_signaled = true; efi_signal_event(efi_con_in.wait_for_key); @@ -723,6 +752,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) { @@ -733,6 +783,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) {