svn commit: r358989 - in head/stand/efi: libefi loader loader/arch/arm loader/arch/arm64

Toomas Soome tsoome at me.com
Fri Mar 27 15:15:57 UTC 2020



> On 27. Mar 2020, at 16:39, Ruslan Garipov <ruslanngaripov at 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? 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 (msmith at 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-head at freebsd.org mailing list
>> https://lists.freebsd.org/mailman/listinfo/svn-src-head
>> To unsubscribe, send any mail to "svn-src-head-unsubscribe at freebsd.org"
>> 



More information about the svn-src-all mailing list