On 3/27/2020 8:07 PM, Toomas Soome wrote:
> 
> 
>> On 27. Mar 2020, at 16:39, Ruslan Garipov <ruslanngari...@gmail.com> wrote:
>>
>> 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"
> 
> 
> Oh cool, at least it is useful for someone:)
> 
> I am sorry, yes this is my bug, I somehow missed the second probe and assumed 
> we do probe only once.. And yes, your analysis is correct, the environment 
> with callback should be treated carefully.
> 
> What probe must do is to set up conin/coninex so the efiserial can use 
> workaround for buggy SIO, the rest is not that important.
> 
> 
>>
>> 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()?
> 
> That definitely can be the case. If you do not set any custom values, missing 
> tem.* variables would confirm that.
> 
> Now, there is still an question, why in your system that allocation does fail?
Is there a way I can help you to figure that out?  I'm afraid I will not
have an access to my systems during the following week, but even so.

> ou, I found I haven't pushed the workaround for buggy Mode information…
> 
> rgds,
> toomas
> 
> 
>>
>>>
>>>
>>> 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 (msm...@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 <sys/cdefs.h>
>>> +__FBSDID("$FreeBSD$");
>>> +
>>> +#include <stand.h>
>>> +#include <sys/errno.h>
>>> +#include <bootstrap.h>
>>> +#include <stdbool.h>
>>> +
>>> +#include <efi.h>
>>> +#include <efilib.h>
>>> +
>>> +#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-h...@freebsd.org mailing list
>>> https://lists.freebsd.org/mailman/listinfo/svn-src-head
>>> To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"
>>>
> 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to