From owner-svn-src-all@freebsd.org Fri Mar 27 14:40:08 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 01F8F277970; Fri, 27 Mar 2020 14:40:07 +0000 (UTC) (envelope-from ruslanngaripov@gmail.com) Received: from mail-lj1-x242.google.com (mail-lj1-x242.google.com [IPv6:2a00:1450:4864:20::242]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "smtp.gmail.com", Issuer "GTS CA 1O1" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48pkyz3Cvwz40j4; Fri, 27 Mar 2020 14:39:54 +0000 (UTC) (envelope-from ruslanngaripov@gmail.com) Received: by mail-lj1-x242.google.com with SMTP id r7so2797523ljg.13; Fri, 27 Mar 2020 07:39:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:subject:to:references:message-id:date:user-agent:mime-version :in-reply-to:content-language:content-transfer-encoding; bh=rB6E1o7F6AUeM9qfsRwlVXFtMmzW2KKPbQymI3firik=; b=HBKtYQtsYvby/uBYwqa22C6gnXe6dm2nN7bQllgTRVVWx89n6WSLJf3uFmLNVTM7/u uRnUgmjTsg4YXND2f4I38JPbwI2cJuiUcYFpaQs43hwGxoXwTSLCMmQ2RgDP0UNM6hvp K96EGqLTE1CmIIlYWxstvtJukZF0klc7KPSQgvx8IHP6WfGsvxVS5x77+1i2PSx3cxKu oOMwpyeaB11d76uNvLEBRiJ2vNFiyTwrnf0wvdmFhCQC8e44BZAtqN/4Ct+x5wduMvPT nJNuqL6KsUWdZuzdgLU2Sj93aVHmEcgryaDZriIhf/jR9weMNqhr/nDHHsRhMZQuURSS 1WGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:subject:to:references:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=rB6E1o7F6AUeM9qfsRwlVXFtMmzW2KKPbQymI3firik=; b=JY92Hq/IUG/wMmF06RLrEZr3R5ce1aiqlll6O28hQLaSvHpGn/xQasg1rMe7rbf1Mi uvBFlJXKLMQmFi3XGBWXSay2z8vIBJiJteLfg0R+xs+sLxtYxt/44K7kiOj0Q58cJwYt NMSAT8RxDDp4gGsKByXFBjEjwTwc0BiVvR2YSezfEQN6koLGE3uFbYgY6K46zX6P44rJ iVFKlM81GrjlSuaasLcb9gmOdkVM2p1wPwZeyJdfOuYdAwTRv3EnhfBtwrg7Q3RfELEz 5A9fOeBLEY7zfN3+ZNP6eX1SdJ3mZDb7yeGLBxHnpxgS9BNDzeAmZnNOJP+5H3RJoXLG 1aww== X-Gm-Message-State: AGi0PuYskuqveHe38c3Gzpp42WR8X9Bvwqeo4GqHpZe8il96xbOlH54V a/77AwB9cIKtXo+8/bubi9CQeTuEC1A= X-Google-Smtp-Source: ADFU+vtrJtKf3oAHtdx4xAjfg51Z9EH9flCvwhdzaW2lrMeVroAnaBp5sblBfSrcIBmtN8HuE8rjpA== X-Received: by 2002:a2e:95c3:: with SMTP id y3mr8656973ljh.149.1585319984484; Fri, 27 Mar 2020 07:39:44 -0700 (PDT) Received: from [192.168.1.3] ([46.48.69.183]) by smtp.gmail.com with ESMTPSA id 133sm2812377ljj.91.2020.03.27.07.39.43 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 27 Mar 2020 07:39:43 -0700 (PDT) From: Ruslan Garipov Subject: Re: svn commit: r358989 - in head/stand/efi: libefi loader loader/arch/arm loader/arch/arm64 To: Toomas Soome , src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org References: <202003140636.02E6a3NS020671@repo.freebsd.org> Message-ID: <95805806-b577-d81a-c709-7244d3fea4eb@gmail.com> Date: Fri, 27 Mar 2020 19:39:40 +0500 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 In-Reply-To: <202003140636.02E6a3NS020671@repo.freebsd.org> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-Rspamd-Queue-Id: 48pkyz3Cvwz40j4 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org; dkim=pass header.d=gmail.com header.s=20161025 header.b=HBKtYQts; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (mx1.freebsd.org: domain of ruslanngaripov@gmail.com designates 2a00:1450:4864:20::242 as permitted sender) smtp.mailfrom=ruslanngaripov@gmail.com X-Spamd-Result: default: False [-3.00 / 15.00]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; R_DKIM_ALLOW(-0.20)[gmail.com:s=20161025]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_THREE(0.00)[4]; R_SPF_ALLOW(-0.20)[+ip6:2a00:1450:4000::/36]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_GOOD(-0.10)[text/plain]; TO_MATCH_ENVRCPT_ALL(0.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; TO_DN_SOME(0.00)[]; RCVD_COUNT_THREE(0.00)[3]; IP_SCORE(0.00)[ip: (2.82), ipnet: 2a00:1450::/32(-2.38), asn: 15169(-0.47), country: US(-0.05)]; DKIM_TRACE(0.00)[gmail.com:+]; DMARC_POLICY_ALLOW(-0.50)[gmail.com,none]; RCVD_IN_DNSWL_NONE(0.00)[2.4.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.4.6.8.4.0.5.4.1.0.0.a.2.list.dnswl.org : 127.0.5.0]; IP_SCORE_FREEMAIL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; MIME_TRACE(0.00)[0:+]; FREEMAIL_ENVFROM(0.00)[gmail.com]; ASN(0.00)[asn:15169, ipnet:2a00:1450::/32, country:US]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_ALL(0.00)[]; DWL_DNSWL_NONE(0.00)[gmail.com.dwl.dnswl.org : 127.0.5.0] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 27 Mar 2020 14:40:09 -0000 On 3/14/2020 11:36 AM, Toomas Soome wrote: > Author: tsoome > Date: Sat Mar 14 06:36:03 2020 > New Revision: 358989 > URL: https://svnweb.freebsd.org/changeset/base/358989 > > Log: > loader: add comconsole implementation on top of SIO protocol > > Provide comconsole on top of SIO for arm platforms (x86 does use bios version). > > Added: > head/stand/efi/loader/efiserialio.c (contents, props changed) > Modified: > head/stand/efi/libefi/efi_console.c > head/stand/efi/loader/arch/arm/Makefile.inc > head/stand/efi/loader/arch/arm64/Makefile.inc > head/stand/efi/loader/conf.c > head/stand/efi/loader/main.c > > Modified: head/stand/efi/libefi/efi_console.c > ============================================================================== > --- head/stand/efi/libefi/efi_console.c Sat Mar 14 05:57:22 2020 (r358988) > +++ head/stand/efi/libefi/efi_console.c Sat Mar 14 06:36:03 2020 (r358989) > @@ -377,9 +377,22 @@ efi_cons_respond(void *s __unused, const void *buf __u > { > } > > +/* > + * Set up conin/conout/coninex to make sure we have input ready. > + */ > static void > efi_cons_probe(struct console *cp) > { > + EFI_STATUS status; > + > + conout = ST->ConOut; > + conin = ST->ConIn; > + > + status = BS->OpenProtocol(ST->ConsoleInHandle, &simple_input_ex_guid, > + (void **)&coninex, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); > + if (status != EFI_SUCCESS) > + coninex = NULL; > + > cp->c_flags |= C_PRESENTIN | C_PRESENTOUT; > } > > @@ -889,15 +902,7 @@ efi_cons_init(int arg) > if (conin != NULL) > return (0); > > - conout = ST->ConOut; > - conin = ST->ConIn; > - > conout->EnableCursor(conout, TRUE); > - status = BS->OpenProtocol(ST->ConsoleInHandle, &simple_input_ex_guid, > - (void **)&coninex, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); > - if (status != EFI_SUCCESS) > - coninex = NULL; > - > if (efi_cons_update_mode()) > return (0); Hello, Toomas! I have to return to this revision once again. Speaking in advance, the problem I'll describe isn't a fatal one. I want to find a solution/root cause by myself... well, I had tried to do that but failed, therefore, I need some tips from you, if you have free time for that. The loader started to ignore teken.fg_color after r358989. I like to have green text on black console. Therefore, I have this: teken.fg_color="green" in my /boot/loader.conf. Before r358989 everything worked just like I wanted: not only vt(4) had green text on black, but the loader menu also. After r358989 vt(4) still renders greeen text on black, but the loader doesn't. It use default white on black. The variable is assigned but doesn't affect the output: OK show teken.fg_color green That started to happen after the changes from above: when code from the efi_cons_init() was moved to the efi_cons_probe() (stand/efi/libefi/efi_console.c). Therefore, if I revert those only changes, the loader starts to draw green text on black. If I read the sources correctly, the cons_probe() function in stand/common/console.c calls both those functions. Moreover, the efi_cons_probe() is called twice: first time when the cons_probe() probes all available consoles, and then when it searches an "online" console. And then the cons_probe() calls the efi_cons_init(). I see nothing between those calls which may cause the loader to ignore teken.fg_color (or any other variable). I believe that the efi_set_colors() function from stand/efi/libefi/efi_console.c is not call being the hook function for the teken.fg_color variable. The efi_cons_update_mode() sets the efi_set_colors() as the callback for teken.fg_color, but it's never called. The only reason for that, according to code of the env_setenv() in stand/libsa/environment.c, is that teken.fg_color was already created (without the hook function, of course) when the efi_cons_update_mode() tries to assign the efi_set_colors() hook. Or, the efi_cons_update_mode() failed to allocate the buffer, and, therefore, didn't set teken.fg_color at all. And later teken.fg_color is read from /boot/loader.conf. One more evidence that efi_set_colors() is not called: setting teken.fg_color from the loader prompt to something incorrect: OK set teken.fg_color=foobar doesn't print error message "Allowed values are either ansi color name or number from range ..." Thoomas, is ignoring of teken.fg_color by the loader caused by failing to allocate the buffer within the efi_cons_update_mode()? > > > Modified: head/stand/efi/loader/arch/arm/Makefile.inc > ============================================================================== > --- head/stand/efi/loader/arch/arm/Makefile.inc Sat Mar 14 05:57:22 2020 (r358988) > +++ head/stand/efi/loader/arch/arm/Makefile.inc Sat Mar 14 06:36:03 2020 (r358989) > @@ -1,6 +1,7 @@ > # $FreeBSD$ > > SRCS+= exec.c \ > + efiserialio.c \ > start.S > > HAVE_FDT=yes > > Modified: head/stand/efi/loader/arch/arm64/Makefile.inc > ============================================================================== > --- head/stand/efi/loader/arch/arm64/Makefile.inc Sat Mar 14 05:57:22 2020 (r358988) > +++ head/stand/efi/loader/arch/arm64/Makefile.inc Sat Mar 14 06:36:03 2020 (r358989) > @@ -3,6 +3,7 @@ > HAVE_FDT=yes > > SRCS+= exec.c \ > + efiserialio.c \ > start.S > > .PATH: ${BOOTSRC}/arm64/libarm64 > > Modified: head/stand/efi/loader/conf.c > ============================================================================== > --- head/stand/efi/loader/conf.c Sat Mar 14 05:57:22 2020 (r358988) > +++ head/stand/efi/loader/conf.c Sat Mar 14 06:36:03 2020 (r358989) > @@ -73,16 +73,16 @@ struct netif_driver *netif_drivers[] = { > }; > > extern struct console efi_console; > -#if defined(__amd64__) || defined(__i386__) > extern struct console comconsole; > +#if defined(__amd64__) || defined(__i386__) > extern struct console nullconsole; > extern struct console spinconsole; > #endif > > struct console *consoles[] = { > &efi_console, > -#if defined(__amd64__) || defined(__i386__) > &comconsole, > +#if defined(__amd64__) || defined(__i386__) > &nullconsole, > &spinconsole, > #endif > > Added: head/stand/efi/loader/efiserialio.c > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/stand/efi/loader/efiserialio.c Sat Mar 14 06:36:03 2020 (r358989) > @@ -0,0 +1,518 @@ > +/*- > + * Copyright (c) 1998 Michael Smith (msmith@freebsd.org) > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#include > +__FBSDID("$FreeBSD$"); > + > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#include "loader_efi.h" > + > +static EFI_GUID serial = SERIAL_IO_PROTOCOL; > + > +#define COMC_TXWAIT 0x40000 /* transmit timeout */ > + > +#ifndef COMSPEED > +#define COMSPEED 9600 > +#endif > + > +#define PNP0501 0x501 /* 16550A-compatible COM port */ > + > +struct serial { > + uint64_t baudrate; > + uint8_t databits; > + EFI_PARITY_TYPE parity; > + EFI_STOP_BITS_TYPE stopbits; > + uint8_t ignore_cd; /* boolean */ > + uint8_t rtsdtr_off; /* boolean */ > + int ioaddr; /* index in handles array */ > + EFI_HANDLE currdev; /* current serial device */ > + EFI_HANDLE condev; /* EFI Console device */ > + SERIAL_IO_INTERFACE *sio; > +}; > + > +static void comc_probe(struct console *); > +static int comc_init(int); > +static void comc_putchar(int); > +static int comc_getchar(void); > +static int comc_ischar(void); > +static bool comc_setup(void); > +static int comc_parse_intval(const char *, unsigned *); > +static int comc_port_set(struct env_var *, int, const void *); > +static int comc_speed_set(struct env_var *, int, const void *); > + > +static struct serial *comc_port; > +extern struct console efi_console; > + > +struct console comconsole = { > + .c_name = "comconsole", > + .c_desc = "serial port", > + .c_flags = 0, > + .c_probe = comc_probe, > + .c_init = comc_init, > + .c_out = comc_putchar, > + .c_in = comc_getchar, > + .c_ready = comc_ischar, > +}; > + > +static EFI_STATUS > +efi_serial_init(EFI_HANDLE **handlep, int *nhandles) > +{ > + UINTN bufsz = 0; > + EFI_STATUS status; > + EFI_HANDLE *handles; > + > + /* > + * get buffer size > + */ > + *nhandles = 0; > + handles = NULL; > + status = BS->LocateHandle(ByProtocol, &serial, NULL, &bufsz, handles); > + if (status != EFI_BUFFER_TOO_SMALL) > + return (status); > + > + if ((handles = malloc(bufsz)) == NULL) > + return (ENOMEM); > + > + *nhandles = (int)(bufsz / sizeof (EFI_HANDLE)); > + /* > + * get handle array > + */ > + status = BS->LocateHandle(ByProtocol, &serial, NULL, &bufsz, handles); > + if (EFI_ERROR(status)) { > + free(handles); > + *nhandles = 0; > + } else > + *handlep = handles; > + return (status); > +} > + > +/* > + * Find serial device number from device path. > + * Return -1 if not found. > + */ > +static int > +efi_serial_get_index(EFI_DEVICE_PATH *devpath, int idx) > +{ > + ACPI_HID_DEVICE_PATH *acpi; > + CHAR16 *text; > + > + while (!IsDevicePathEnd(devpath)) { > + if (DevicePathType(devpath) == MESSAGING_DEVICE_PATH && > + DevicePathSubType(devpath) == MSG_UART_DP) > + return (idx); > + > + if (DevicePathType(devpath) == ACPI_DEVICE_PATH && > + (DevicePathSubType(devpath) == ACPI_DP || > + DevicePathSubType(devpath) == ACPI_EXTENDED_DP)) { > + > + acpi = (ACPI_HID_DEVICE_PATH *)devpath; > + if (acpi->HID == EISA_PNP_ID(PNP0501)) { > + return (acpi->UID); > + } > + } > + > + devpath = NextDevicePathNode(devpath); > + } > + return (-1); > +} > + > +/* > + * The order of handles from LocateHandle() is not known, we need to > + * iterate handles, pick device path for handle, and check the device > + * number. > + */ > +static EFI_HANDLE > +efi_serial_get_handle(int port, EFI_HANDLE condev) > +{ > + EFI_STATUS status; > + EFI_HANDLE *handles, handle; > + EFI_DEVICE_PATH *devpath; > + int index, nhandles; > + > + if (port == -1) > + return (NULL); > + > + handles = NULL; > + nhandles = 0; > + status = efi_serial_init(&handles, &nhandles); > + if (EFI_ERROR(status)) > + return (NULL); > + > + /* > + * We have console handle, set ioaddr for it. > + */ > + if (condev != NULL) { > + for (index = 0; index < nhandles; index++) { > + if (condev == handles[index]) { > + devpath = efi_lookup_devpath(condev); > + comc_port->ioaddr = > + efi_serial_get_index(devpath, index); > + efi_close_devpath(condev); > + free(handles); > + return (condev); > + } > + } > + } > + > + handle = NULL; > + for (index = 0; handle == NULL && index < nhandles; index++) { > + devpath = efi_lookup_devpath(handles[index]); > + if (port == efi_serial_get_index(devpath, index)) > + handle = (handles[index]); > + efi_close_devpath(handles[index]); > + } > + > + /* > + * In case we did fail to identify the device by path, use port as > + * array index. Note, we did check port == -1 above. > + */ > + if (port < nhandles && handle == NULL) > + handle = handles[port]; > + > + free(handles); > + return (handle); > +} > + > +static EFI_HANDLE > +comc_get_con_serial_handle(const char *name) > +{ > + EFI_HANDLE handle; > + EFI_DEVICE_PATH *node; > + EFI_STATUS status; > + char *buf, *ep; > + size_t sz; > + > + buf = NULL; > + sz = 0; > + status = efi_global_getenv(name, buf, &sz); > + if (status == EFI_BUFFER_TOO_SMALL) { > + buf = malloc(sz); > + if (buf != NULL) > + status = efi_global_getenv(name, buf, &sz); > + } > + if (status != EFI_SUCCESS) { > + free(buf); > + return (NULL); > + } > + > + ep = buf + sz; > + node = (EFI_DEVICE_PATH *)buf; > + while ((char *)node < ep) { > + status = BS->LocateDevicePath(&serial, &node, &handle); > + if (status == EFI_SUCCESS) { > + free(buf); > + return (handle); > + } > + if (IsDevicePathEndType(node) && > + DevicePathSubType(node) == > + END_INSTANCE_DEVICE_PATH_SUBTYPE) { > + /* > + * Start of next device path in list. > + */ > + node = NextDevicePathNode(node); > + continue; > + } > + if (IsDevicePathEnd(node)) > + break; > + } > + free(buf); > + return (NULL); > +} > + > +static void > +comc_probe(struct console *sc) > +{ > + EFI_STATUS status; > + EFI_HANDLE handle; > + char name[20]; > + char value[20]; > + unsigned val; > + char *env, *buf, *ep; > + size_t sz; > + > + if (comc_port == NULL) { > + comc_port = malloc(sizeof (struct serial)); > + if (comc_port == NULL) > + return; > + } > + comc_port->baudrate = COMSPEED; > + comc_port->ioaddr = 0; /* default port */ > + comc_port->databits = 8; /* 8,n,1 */ > + comc_port->parity = NoParity; /* 8,n,1 */ > + comc_port->stopbits = OneStopBit; /* 8,n,1 */ > + comc_port->ignore_cd = 1; /* ignore cd */ > + comc_port->rtsdtr_off = 0; /* rts-dtr is on */ > + comc_port->sio = NULL; > + > + handle = NULL; > + env = getenv("efi_com_port"); > + if (comc_parse_intval(env, &val) == CMD_OK) { > + comc_port->ioaddr = val; > + } else { > + /* > + * efi_com_port is not set, we need to select default. > + * First, we consult ConOut variable to see if > + * we have serial port redirection. If not, we just > + * pick first device. > + */ > + handle = comc_get_con_serial_handle("ConOut"); > + comc_port->condev = handle; > + } > + > + handle = efi_serial_get_handle(comc_port->ioaddr, handle); > + if (handle != NULL) { > + comc_port->currdev = handle; > + status = BS->OpenProtocol(handle, &serial, > + (void**)&comc_port->sio, IH, NULL, > + EFI_OPEN_PROTOCOL_GET_PROTOCOL); > + > + if (EFI_ERROR(status)) > + comc_port->sio = NULL; > + } > + > + if (env != NULL) > + unsetenv("efi_com_port"); > + snprintf(value, sizeof (value), "%u", comc_port->ioaddr); > + env_setenv("efi_com_port", EV_VOLATILE, value, > + comc_port_set, env_nounset); > + > + env = getenv("efi_com_speed"); > + if (comc_parse_intval(env, &val) == CMD_OK) > + comc_port->baudrate = val; > + > + if (env != NULL) > + unsetenv("efi_com_speed"); > + snprintf(value, sizeof (value), "%ju", (uintmax_t)comc_port->baudrate); > + env_setenv("efi_com_speed", EV_VOLATILE, value, > + comc_speed_set, env_nounset); > + > + comconsole.c_flags = 0; > + if (comc_setup()) > + sc->c_flags = C_PRESENTIN | C_PRESENTOUT; > +} > + > +static int > +comc_init(int arg __unused) > +{ > + > + if (comc_setup()) > + return (CMD_OK); > + > + comconsole.c_flags = 0; > + return (CMD_ERROR); > +} > + > +static void > +comc_putchar(int c) > +{ > + int wait; > + EFI_STATUS status; > + UINTN bufsz = 1; > + char cb = c; > + > + if (comc_port->sio == NULL) > + return; > + > + for (wait = COMC_TXWAIT; wait > 0; wait--) { > + status = comc_port->sio->Write(comc_port->sio, &bufsz, &cb); > + if (status != EFI_TIMEOUT) > + break; > + } > +} > + > +static int > +comc_getchar(void) > +{ > + EFI_STATUS status; > + UINTN bufsz = 1; > + char c; > + > + > + /* > + * if this device is also used as ConIn, some firmwares > + * fail to return all input via SIO protocol. > + */ > + if (comc_port->currdev == comc_port->condev) { > + if ((efi_console.c_flags & C_ACTIVEIN) == 0) > + return (efi_console.c_in()); > + return (-1); > + } > + > + if (comc_port->sio == NULL) > + return (-1); > + > + status = comc_port->sio->Read(comc_port->sio, &bufsz, &c); > + if (EFI_ERROR(status) || bufsz == 0) > + return (-1); > + > + return (c); > +} > + > +static int > +comc_ischar(void) > +{ > + EFI_STATUS status; > + uint32_t control; > + > + /* > + * if this device is also used as ConIn, some firmwares > + * fail to return all input via SIO protocol. > + */ > + if (comc_port->currdev == comc_port->condev) { > + if ((efi_console.c_flags & C_ACTIVEIN) == 0) > + return (efi_console.c_ready()); > + return (0); > + } > + > + if (comc_port->sio == NULL) > + return (0); > + > + status = comc_port->sio->GetControl(comc_port->sio, &control); > + if (EFI_ERROR(status)) > + return (0); > + > + return (!(control & EFI_SERIAL_INPUT_BUFFER_EMPTY)); > +} > + > +static int > +comc_parse_intval(const char *value, unsigned *valp) > +{ > + unsigned n; > + char *ep; > + > + if (value == NULL || *value == '\0') > + return (CMD_ERROR); > + > + errno = 0; > + n = strtoul(value, &ep, 10); > + if (errno != 0 || *ep != '\0') > + return (CMD_ERROR); > + *valp = n; > + > + return (CMD_OK); > +} > + > +static int > +comc_port_set(struct env_var *ev, int flags, const void *value) > +{ > + unsigned port; > + SERIAL_IO_INTERFACE *sio; > + EFI_HANDLE handle; > + EFI_STATUS status; > + > + if (value == NULL) > + return (CMD_ERROR); > + > + if (comc_parse_intval(value, &port) != CMD_OK) > + return (CMD_ERROR); > + > + handle = efi_serial_get_handle(port, NULL); > + if (handle == NULL) { > + printf("no handle\n"); > + return (CMD_ERROR); > + } > + > + status = BS->OpenProtocol(handle, &serial, > + (void**)&sio, IH, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); > + > + if (EFI_ERROR(status)) { > + printf("OpenProtocol: %lu\n", EFI_ERROR_CODE(status)); > + return (CMD_ERROR); > + } > + > + comc_port->currdev = handle; > + comc_port->ioaddr = port; > + comc_port->sio = sio; > + > + (void) comc_setup(); > + > + env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); > + return (CMD_OK); > +} > + > +static int > +comc_speed_set(struct env_var *ev, int flags, const void *value) > +{ > + unsigned speed; > + > + if (value == NULL) > + return (CMD_ERROR); > + > + if (comc_parse_intval(value, &speed) != CMD_OK) > + return (CMD_ERROR); > + > + comc_port->baudrate = speed; > + (void) comc_setup(); > + > + env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); > + > + return (CMD_OK); > +} > + > +/* > + * In case of error, we also reset ACTIVE flags, so the console > + * framefork will try alternate consoles. > + */ > +static bool > +comc_setup(void) > +{ > + EFI_STATUS status; > + UINT32 control; > + > + /* port is not usable */ > + if (comc_port->sio == NULL) > + return (false); > + > + status = comc_port->sio->Reset(comc_port->sio); > + if (EFI_ERROR(status)) > + return (false); > + > + status = comc_port->sio->SetAttributes(comc_port->sio, > + comc_port->baudrate, 0, 0, comc_port->parity, > + comc_port->databits, comc_port->stopbits); > + if (EFI_ERROR(status)) > + return (false); > + > + status = comc_port->sio->GetControl(comc_port->sio, &control); > + if (EFI_ERROR(status)) > + return (false); > + if (comc_port->rtsdtr_off) { > + control &= ~(EFI_SERIAL_REQUEST_TO_SEND | > + EFI_SERIAL_DATA_TERMINAL_READY); > + } else { > + control |= EFI_SERIAL_REQUEST_TO_SEND; > + } > + (void) comc_port->sio->SetControl(comc_port->sio, control); > + /* Mark this port usable. */ > + comconsole.c_flags |= (C_PRESENTIN | C_PRESENTOUT); > + return (true); > +} > > Modified: head/stand/efi/loader/main.c > ============================================================================== > --- head/stand/efi/loader/main.c Sat Mar 14 05:57:22 2020 (r358988) > +++ head/stand/efi/loader/main.c Sat Mar 14 06:36:03 2020 (r358989) > @@ -722,7 +722,8 @@ parse_uefi_con_out(void) > while ((char *)node < ep) { > pci_pending = false; > if (DevicePathType(node) == ACPI_DEVICE_PATH && > - DevicePathSubType(node) == ACPI_DP) { > + (DevicePathSubType(node) == ACPI_DP || > + DevicePathSubType(node) == ACPI_EXTENDED_DP)) { > /* Check for Serial node */ > acpi = (void *)node; > if (EISA_ID_TO_NUM(acpi->HID) == 0x501) { > @@ -731,7 +732,7 @@ parse_uefi_con_out(void) > } > } else if (DevicePathType(node) == MESSAGING_DEVICE_PATH && > DevicePathSubType(node) == MSG_UART_DP) { > - > + com_seen = ++seen; > uart = (void *)node; > setenv_int("efi_com_speed", uart->BaudRate); > } else if (DevicePathType(node) == ACPI_DEVICE_PATH && > @@ -897,6 +898,11 @@ main(int argc, CHAR16 *argv[]) > * changes to take effect, regardless of where they come from. > */ > setenv("console", "efi", 1); > + uhowto = parse_uefi_con_out(); > +#if defined(__aarch64__) || defined(__arm__) > + if ((uhowto & RB_SERIAL) != 0) > + setenv("console", "comconsole", 1); > +#endif > cons_probe(); > > /* Init the time source */ > @@ -930,7 +936,6 @@ main(int argc, CHAR16 *argv[]) > if (!has_kbd && (howto & RB_PROBE)) > howto |= RB_SERIAL | RB_MULTIPLE; > howto &= ~RB_PROBE; > - uhowto = parse_uefi_con_out(); > > /* > * Read additional environment variables from the boot device's > _______________________________________________ > svn-src-head@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/svn-src-head > To unsubscribe, send any mail to "svn-src-head-unsubscribe@freebsd.org" >