From patchwork Mon Sep 11 14:04:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rob Clark X-Patchwork-Id: 812392 X-Patchwork-Delegate: trini@ti.com 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="KEToZjEO"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xrV6M6rgzz9s4s for ; Tue, 12 Sep 2017 00:04:26 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 5B629C21D76; Mon, 11 Sep 2017 14:04:18 +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_DNSWL_NONE, 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 838E6C21D09; Mon, 11 Sep 2017 14:04:15 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id B6499C21D09; Mon, 11 Sep 2017 14:04:14 +0000 (UTC) Received: from mail-qt0-f196.google.com (mail-qt0-f196.google.com [209.85.216.196]) by lists.denx.de (Postfix) with ESMTPS id 2E06FC21C4C for ; Mon, 11 Sep 2017 14:04:14 +0000 (UTC) Received: by mail-qt0-f196.google.com with SMTP id b1so3275721qtc.0 for ; Mon, 11 Sep 2017 07:04:14 -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; bh=JoEpAayfWOwh92qutH163bAUJkt0TB6CwIkntvDE0Lo=; b=KEToZjEOOtekg52xJV1gyJ/K5P1+6MD6kLXraEK5U4d/uZhVjoO+ia+QuJDrrqR9TM INM9lx3oeqca7cQYqpoiFzDykJ4RhFr9jKHD29s5HhBImWDM0aeYNkDMLPVL+xx7BDac H4bpjrc9LYkAi/nTRAg2RdTnaPNnZ4+IY5cnioScJcHxgIDJY8PL2Yye/wBzngMjw7ex 3UCU/HNF/NBYbks6opZ2s1Lhzq3Leb8LWei++GENJj+TQV2YGR431a1DbCKHBUwuXf6Z HbcR+yR+b8tEtXjlwL5vf40TSo8qWAUG4DA/WHbNcgPLIWz4V59M0feNmzWUNHvWW4sm kSAA== 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; bh=JoEpAayfWOwh92qutH163bAUJkt0TB6CwIkntvDE0Lo=; b=frdhvdFWmUoiBxvlOjnG5ERpmn/o/YF0o0vLsFmk+4XsldRWT2lDgAiY+kUBVCriNd KwJgoACXCy4V8Uk56K95PybzcdeiTRgVVmBrMfRtf/j2Al0abeuI+G7YvNEsoEqX+FLP 65TdQnSlER5fhkJgCuFgGpJ/w4NtqV0Z5bUDBelj1ncHyydnJnTbhXiUtT5GQFC1ok5h Qewb1Fmh/8ib904WFnfyMhbK42lS4ijWsMQw9ocSlmGINYG7HfTThapxYS+jUYMlIZ0w ppAxsWNphbfaJTKripux1zQ3qiyJBHdbsIIWZg7RxewMoHtE3mYTkbB9z+vYRmgslb88 1QLw== X-Gm-Message-State: AHPjjUhUkt2QMtUAG9/ZmEn1YCbuKUNZZyjUucaVQfz51SqDwvGER2Om 7MqWREPIpcemOEa5Cpk= X-Google-Smtp-Source: AOwi7QAlB9snan3erVY6MRUHvb2YtBi60OLyoIqsBLDEPSXxxTYISldGjzs385xG3w7LLidPm2lsVg== X-Received: by 10.200.26.249 with SMTP id h54mr14124342qtk.41.1505138652187; Mon, 11 Sep 2017 07:04:12 -0700 (PDT) Received: from localhost ([144.121.20.162]) by smtp.gmail.com with ESMTPSA id b27sm6279501qtc.78.2017.09.11.07.04.10 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 11 Sep 2017 07:04:11 -0700 (PDT) From: Rob Clark To: U-Boot Mailing List Date: Mon, 11 Sep 2017 10:04:05 -0400 Message-Id: <20170911140407.7273-1-robdclark@gmail.com> X-Mailer: git-send-email 2.13.5 Subject: [U-Boot] [PATCH] 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. Signed-off-by: Rob Clark --- 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) {