Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Mar 2020 17:07:43 +0200
From:      Toomas Soome <tsoome@me.com>
To:        Ruslan Garipov <ruslanngaripov@gmail.com>
Cc:        Toomas Soome <tsoome@FreeBSD.org>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r358989 - in head/stand/efi: libefi loader loader/arch/arm loader/arch/arm64
Message-ID:  <35478B22-4EEE-4DE2-B441-7838F676ED68@me.com>
In-Reply-To: <95805806-b577-d81a-c709-7244d3fea4eb@gmail.com>
References:  <202003140636.02E6a3NS020671@repo.freebsd.org> <95805806-b577-d81a-c709-7244d3fea4eb@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help


> On 27. Mar 2020, at 16:39, Ruslan Garipov <ruslanngaripov@gmail.com> =
wrote:
>=20
> 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
>>=20
>> Log:
>>  loader: add comconsole implementation on top of SIO protocol
>>=20
>>  Provide comconsole on top of SIO for arm platforms (x86 does use =
bios version).
>>=20
>> 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
>>=20
>> Modified: head/stand/efi/libefi/efi_console.c
>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
>> --- 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
>> {
>> }
>>=20
>> +/*
>> + * Set up conin/conout/coninex to make sure we have input ready.
>> + */
>> static void
>> efi_cons_probe(struct console *cp)
>> {
>> +	EFI_STATUS status;
>> +
>> +	conout =3D ST->ConOut;
>> +	conin =3D ST->ConIn;
>> +
>> +	status =3D BS->OpenProtocol(ST->ConsoleInHandle, =
&simple_input_ex_guid,
>> +	    (void **)&coninex, IH, NULL, =
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
>> +	if (status !=3D EFI_SUCCESS)
>> +		coninex =3D NULL;
>> +
>> 	cp->c_flags |=3D C_PRESENTIN | C_PRESENTOUT;
>> }
>>=20
>> @@ -889,15 +902,7 @@ efi_cons_init(int arg)
>> 	if (conin !=3D NULL)
>> 		return (0);
>>=20
>> -	conout =3D ST->ConOut;
>> -	conin =3D ST->ConIn;
>> -
>> 	conout->EnableCursor(conout, TRUE);
>> -	status =3D BS->OpenProtocol(ST->ConsoleInHandle, =
&simple_input_ex_guid,
>> -	    (void **)&coninex, IH, NULL, =
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
>> -	if (status !=3D EFI_SUCCESS)
>> -		coninex =3D NULL;
>> -
>> 	if (efi_cons_update_mode())
>> 		return (0);
> Hello, Toomas!
>=20
> I have to return to this revision once again.
>=20
> 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.
>=20
> The loader started to ignore teken.fg_color after r358989.
>=20
> I like to have green text on black console.  Therefore, I have this:
>=20
> teken.fg_color=3D"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.


>=20
> 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:
>=20
> OK show teken.fg_color
> green
>=20
> 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.
>=20
> 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).
>=20
> 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.
>=20
> One more evidence that efi_set_colors() is not called: setting
> teken.fg_color from the loader prompt to something incorrect:
>=20
> OK set teken.fg_color=3Dfoobar
>=20
> doesn't print error message "Allowed values are either ansi color name
> or number from range ..."
>=20
> 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=E2=80=A6

rgds,
toomas


>=20
>>=20
>>=20
>> Modified: head/stand/efi/loader/arch/arm/Makefile.inc
>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
>> --- 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$
>>=20
>> SRCS+=3D	exec.c \
>> +	efiserialio.c \
>> 	start.S
>>=20
>> HAVE_FDT=3Dyes
>>=20
>> Modified: head/stand/efi/loader/arch/arm64/Makefile.inc
>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
>> --- 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=3Dyes
>>=20
>> SRCS+=3D	exec.c \
>> +	efiserialio.c \
>> 	start.S
>>=20
>> .PATH:	${BOOTSRC}/arm64/libarm64
>>=20
>> Modified: head/stand/efi/loader/conf.c
>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
>> --- 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[] =3D {
>> };
>>=20
>> 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
>>=20
>> struct console *consoles[] =3D {
>> 	&efi_console,
>> -#if defined(__amd64__) || defined(__i386__)
>> 	&comconsole,
>> +#if defined(__amd64__) || defined(__i386__)
>> 	&nullconsole,
>> 	&spinconsole,
>> #endif
>>=20
>> Added: head/stand/efi/loader/efiserialio.c
>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
>> --- /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 <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 =3D 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 =3D {
>> +	.c_name =3D "comconsole",
>> +	.c_desc =3D "serial port",
>> +	.c_flags =3D 0,
>> +	.c_probe =3D comc_probe,
>> +	.c_init =3D comc_init,
>> +	.c_out =3D comc_putchar,
>> +	.c_in =3D comc_getchar,
>> +	.c_ready =3D comc_ischar,
>> +};
>> +
>> +static EFI_STATUS
>> +efi_serial_init(EFI_HANDLE **handlep, int *nhandles)
>> +{
>> +	UINTN bufsz =3D 0;
>> +	EFI_STATUS status;
>> +	EFI_HANDLE *handles;
>> +
>> +	/*
>> +	 * get buffer size
>> +	 */
>> +	*nhandles =3D 0;
>> +	handles =3D NULL;
>> +	status =3D BS->LocateHandle(ByProtocol, &serial, NULL, &bufsz, =
handles);
>> +	if (status !=3D EFI_BUFFER_TOO_SMALL)
>> +		return (status);
>> +
>> +	if ((handles =3D malloc(bufsz)) =3D=3D NULL)
>> +		return (ENOMEM);
>> +
>> +	*nhandles =3D (int)(bufsz / sizeof (EFI_HANDLE));
>> +	/*
>> +	 * get handle array
>> +	 */
>> +	status =3D BS->LocateHandle(ByProtocol, &serial, NULL, &bufsz, =
handles);
>> +	if (EFI_ERROR(status)) {
>> +		free(handles);
>> +		*nhandles =3D 0;
>> +	} else
>> +		*handlep =3D 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) =3D=3D MESSAGING_DEVICE_PATH =
&&
>> +		    DevicePathSubType(devpath) =3D=3D MSG_UART_DP)
>> +			return (idx);
>> +
>> +		if (DevicePathType(devpath) =3D=3D ACPI_DEVICE_PATH &&
>> +		    (DevicePathSubType(devpath) =3D=3D ACPI_DP ||
>> +		    DevicePathSubType(devpath) =3D=3D ACPI_EXTENDED_DP)) =
{
>> +
>> +			acpi =3D (ACPI_HID_DEVICE_PATH *)devpath;
>> +			if (acpi->HID =3D=3D EISA_PNP_ID(PNP0501)) {
>> +				return (acpi->UID);
>> +			}
>> +		}
>> +
>> +		devpath =3D 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 =3D=3D -1)
>> +		return (NULL);
>> +
>> +	handles =3D NULL;
>> +	nhandles =3D 0;
>> +	status =3D efi_serial_init(&handles, &nhandles);
>> +	if (EFI_ERROR(status))
>> +		return (NULL);
>> +
>> +	/*
>> +	 * We have console handle, set ioaddr for it.
>> +	 */
>> +	if (condev !=3D NULL) {
>> +		for (index =3D 0; index < nhandles; index++) {
>> +			if (condev =3D=3D handles[index]) {
>> +				devpath =3D efi_lookup_devpath(condev);
>> +				comc_port->ioaddr =3D
>> +				    efi_serial_get_index(devpath, =
index);
>> +				efi_close_devpath(condev);
>> +				free(handles);
>> +				return (condev);
>> +			}
>> +		}
>> +	}
>> +
>> +	handle =3D NULL;
>> +	for (index =3D 0; handle =3D=3D NULL && index < nhandles; =
index++) {
>> +		devpath =3D efi_lookup_devpath(handles[index]);
>> +		if (port =3D=3D efi_serial_get_index(devpath, index))
>> +			handle =3D (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 =3D=3D -1 above.
>> +	 */
>> +	if (port < nhandles && handle =3D=3D NULL)
>> +		handle =3D 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 =3D NULL;
>> +	sz =3D 0;
>> +	status =3D efi_global_getenv(name, buf, &sz);
>> +	if (status =3D=3D EFI_BUFFER_TOO_SMALL) {
>> +		buf =3D malloc(sz);
>> +		if (buf !=3D NULL)
>> +			status =3D efi_global_getenv(name, buf, &sz);
>> +	}
>> +	if (status !=3D EFI_SUCCESS) {
>> +		free(buf);
>> +		return (NULL);
>> +	}
>> +
>> +	ep =3D buf + sz;
>> +	node =3D (EFI_DEVICE_PATH *)buf;
>> +	while ((char *)node < ep) {
>> +		status =3D BS->LocateDevicePath(&serial, &node, =
&handle);
>> +		if (status =3D=3D EFI_SUCCESS) {
>> +			free(buf);
>> +			return (handle);
>> +		}
>> +		if (IsDevicePathEndType(node) &&
>> +		    DevicePathSubType(node) =3D=3D
>> +		    END_INSTANCE_DEVICE_PATH_SUBTYPE) {
>> +			/*
>> +			 * Start of next device path in list.
>> +			 */
>> +			node =3D 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 =3D=3D NULL) {
>> +		comc_port =3D malloc(sizeof (struct serial));
>> +		if (comc_port =3D=3D NULL)
>> +			return;
>> +	}
>> +	comc_port->baudrate =3D COMSPEED;
>> +	comc_port->ioaddr =3D 0;			/* default port =
*/
>> +	comc_port->databits =3D 8;		/* 8,n,1 */
>> +	comc_port->parity =3D NoParity;		/* 8,n,1 */
>> +	comc_port->stopbits =3D OneStopBit;	/* 8,n,1 */
>> +	comc_port->ignore_cd =3D 1;		/* ignore cd */
>> +	comc_port->rtsdtr_off =3D 0;		/* rts-dtr is on */
>> +	comc_port->sio =3D NULL;
>> +
>> +	handle =3D NULL;
>> +	env =3D getenv("efi_com_port");
>> +	if (comc_parse_intval(env, &val) =3D=3D CMD_OK) {
>> +		comc_port->ioaddr =3D 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 =3D comc_get_con_serial_handle("ConOut");
>> +		comc_port->condev =3D handle;
>> +	}
>> +
>> +	handle =3D efi_serial_get_handle(comc_port->ioaddr, handle);
>> +	if (handle !=3D NULL) {
>> +		comc_port->currdev =3D handle;
>> +		status =3D BS->OpenProtocol(handle, &serial,
>> +		    (void**)&comc_port->sio, IH, NULL,
>> +		    EFI_OPEN_PROTOCOL_GET_PROTOCOL);
>> +
>> +		if (EFI_ERROR(status))
>> +			comc_port->sio =3D NULL;
>> +	}
>> +
>> +	if (env !=3D NULL)=20
>> +		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 =3D getenv("efi_com_speed");
>> +	if (comc_parse_intval(env, &val) =3D=3D CMD_OK)
>> +		comc_port->baudrate =3D val;
>> +
>> +	if (env !=3D 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 =3D 0;
>> +	if (comc_setup())
>> +		sc->c_flags =3D C_PRESENTIN | C_PRESENTOUT;
>> +}
>> +
>> +static int
>> +comc_init(int arg __unused)
>> +{
>> +
>> +	if (comc_setup())
>> +		return (CMD_OK);
>> +
>> +	comconsole.c_flags =3D 0;
>> +	return (CMD_ERROR);
>> +}
>> +
>> +static void
>> +comc_putchar(int c)
>> +{
>> +	int wait;
>> +	EFI_STATUS status;
>> +	UINTN bufsz =3D 1;
>> +	char cb =3D c;
>> +
>> +	if (comc_port->sio =3D=3D NULL)
>> +		return;
>> +
>> +	for (wait =3D COMC_TXWAIT; wait > 0; wait--) {
>> +		status =3D comc_port->sio->Write(comc_port->sio, &bufsz, =
&cb);
>> +		if (status !=3D EFI_TIMEOUT)
>> +			break;
>> +	}
>> +}
>> +
>> +static int
>> +comc_getchar(void)
>> +{
>> +	EFI_STATUS status;
>> +	UINTN bufsz =3D 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 =3D=3D comc_port->condev) {
>> +		if ((efi_console.c_flags & C_ACTIVEIN) =3D=3D 0)
>> +			return (efi_console.c_in());
>> +		return (-1);
>> +	}
>> +
>> +	if (comc_port->sio =3D=3D NULL)
>> +		return (-1);
>> +
>> +	status =3D comc_port->sio->Read(comc_port->sio, &bufsz, &c);
>> +	if (EFI_ERROR(status) || bufsz =3D=3D 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 =3D=3D comc_port->condev) {
>> +		if ((efi_console.c_flags & C_ACTIVEIN) =3D=3D 0)
>> +			return (efi_console.c_ready());
>> +		return (0);
>> +	}
>> +
>> +	if (comc_port->sio =3D=3D NULL)
>> +		return (0);
>> +
>> +	status =3D 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 =3D=3D NULL || *value =3D=3D '\0')
>> +		return (CMD_ERROR);
>> +
>> +	errno =3D 0;
>> +	n =3D strtoul(value, &ep, 10);
>> +	if (errno !=3D 0 || *ep !=3D '\0')
>> +		return (CMD_ERROR);
>> +	*valp =3D 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 =3D=3D NULL)
>> +		return (CMD_ERROR);
>> +
>> +	if (comc_parse_intval(value, &port) !=3D CMD_OK)=20
>> +		return (CMD_ERROR);
>> +
>> +	handle =3D efi_serial_get_handle(port, NULL);
>> +	if (handle =3D=3D NULL) {
>> +		printf("no handle\n");
>> +		return (CMD_ERROR);
>> +	}
>> +
>> +	status =3D 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 =3D handle;
>> +	comc_port->ioaddr =3D port;
>> +	comc_port->sio =3D sio;
>> +=09
>> +	(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 =3D=3D NULL)
>> +		return (CMD_ERROR);
>> +
>> +	if (comc_parse_intval(value, &speed) !=3D CMD_OK)=20
>> +		return (CMD_ERROR);
>> +
>> +	comc_port->baudrate =3D 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 =3D=3D NULL)
>> +		return (false);
>> +
>> +	status =3D comc_port->sio->Reset(comc_port->sio);
>> +	if (EFI_ERROR(status))
>> +		return (false);
>> +
>> +	status =3D 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 =3D comc_port->sio->GetControl(comc_port->sio, &control);
>> +	if (EFI_ERROR(status))
>> +		return (false);
>> +	if (comc_port->rtsdtr_off) {
>> +		control &=3D ~(EFI_SERIAL_REQUEST_TO_SEND |
>> +		    EFI_SERIAL_DATA_TERMINAL_READY);
>> +	} else {
>> +		control |=3D EFI_SERIAL_REQUEST_TO_SEND;
>> +	}
>> +	(void) comc_port->sio->SetControl(comc_port->sio, control);
>> +	/* Mark this port usable. */
>> +	comconsole.c_flags |=3D (C_PRESENTIN | C_PRESENTOUT);
>> +	return (true);
>> +}
>>=20
>> Modified: head/stand/efi/loader/main.c
>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
>> --- 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 =3D false;
>> 		if (DevicePathType(node) =3D=3D ACPI_DEVICE_PATH &&
>> -		    DevicePathSubType(node) =3D=3D ACPI_DP) {
>> +		    (DevicePathSubType(node) =3D=3D ACPI_DP ||
>> +		    DevicePathSubType(node) =3D=3D ACPI_EXTENDED_DP)) {
>> 			/* Check for Serial node */
>> 			acpi =3D (void *)node;
>> 			if (EISA_ID_TO_NUM(acpi->HID) =3D=3D 0x501) {
>> @@ -731,7 +732,7 @@ parse_uefi_con_out(void)
>> 			}
>> 		} else if (DevicePathType(node) =3D=3D =
MESSAGING_DEVICE_PATH &&
>> 		    DevicePathSubType(node) =3D=3D MSG_UART_DP) {
>> -
>> +			com_seen =3D ++seen;
>> 			uart =3D (void *)node;
>> 			setenv_int("efi_com_speed", uart->BaudRate);
>> 		} else if (DevicePathType(node) =3D=3D 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 =3D parse_uefi_con_out();
>> +#if defined(__aarch64__) || defined(__arm__)
>> +	if ((uhowto & RB_SERIAL) !=3D 0)
>> +		setenv("console", "comconsole", 1);
>> +#endif
>> 	cons_probe();
>>=20
>> 	/* Init the time source */
>> @@ -930,7 +936,6 @@ main(int argc, CHAR16 *argv[])
>> 	if (!has_kbd && (howto & RB_PROBE))
>> 		howto |=3D RB_SERIAL | RB_MULTIPLE;
>> 	howto &=3D ~RB_PROBE;
>> -	uhowto =3D parse_uefi_con_out();
>>=20
>> 	/*
>> 	 * 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"
>>=20




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?35478B22-4EEE-4DE2-B441-7838F676ED68>