svn commit: r313042 - in head/sys/boot: efi/include efi/libefi efi/loader forth

Michal Meloun melounmichal at gmail.com
Fri Feb 3 04:36:08 UTC 2017



On 01.02.2017 9:46, Toomas Soome wrote:
> Author: tsoome
> Date: Wed Feb  1 08:46:59 2017
> New Revision: 313042
> URL: https://svnweb.freebsd.org/changeset/base/313042
> 
> Log:
>   loader.efi environment related cleanups
>   
>   Since we have dedicated libefi/env.c file for variable support, the following
>   changes are done:
>   
>   Simple cstyle changes in env.c
>   Moved efi variable related commands from loader/main.c to libefi/env.c
>   Did create function to set "efi-version" environment variable in env.c.
>   
>   This function does serve two purposes: for first a  small clean up of the
>   loader main(), and for second, it does replace the otherwise unused
>   efi_variable_support hack.
>   A bit of cleanup of ficl backend functions. The TEST_MAIN has no meaning,
>   and removed few memory leaks.
>   
>   The forth code is updated to use "efi-version" variable, instead of ficl
>   environment check.
>   
>   Reviewed by:	imp
>   Approved by:	imp (mentor)
>   Differential Revision:	https://reviews.freebsd.org/D9165
> 
> Added:
>   head/sys/boot/efi/libefi/wchar.c   (contents, props changed)
> Modified:
>   head/sys/boot/efi/include/efilib.h
>   head/sys/boot/efi/libefi/Makefile
>   head/sys/boot/efi/libefi/env.c
>   head/sys/boot/efi/loader/main.c
>   head/sys/boot/forth/loader.4th
>

This breaks armv6 buildworld:

/usr/src/sys/boot/efi/libefi/env.c:97:50: error: format specifies type
'unsigned long' but the argument has type 'EFI_STATUS' (aka 'unsigned
int') [-Werror,-Wformat]
                printf("Can't get the variable: error %#lx\n", status);
                                                      ~~~~     ^~~~~~
                                                      %#x
/usr/src/sys/boot/efi/libefi/env.c:104:50: error: format specifies type
'unsigned long' but the argument has type 'EFI_STATUS' (aka 'unsigned
int') [-Werror,-Wformat]
                printf("Can't get the variable: error %#lx\n", status);
                                                      ~~~~     ^~~~~~
                                                      %#x
/usr/src/sys/boot/efi/libefi/env.c:109:35: error: format specifies type
'wchar_t *' (aka 'unsigned int *') but the argument has type 'CHAR16 *'
(aka 'unsigned short *') [-Werror,-Wformat]
                printf("%s 0x%x %S", str, attr, varnamearg);
                                ~~              ^~~~~~~~~~
/usr/src/sys/boot/efi/libefi/env.c:111:36: error: format specifies type
'wchar_t *' (aka 'unsigned int *') but the argument has type 'CHAR16 *'
(aka 'unsigned short *') [-Werror,-Wformat]
                printf("%s 0x%x %S=", str, attr, varnamearg);
                                ~~               ^~~~~~~~~~

Michal


> Modified: head/sys/boot/efi/include/efilib.h
> ==============================================================================
> --- head/sys/boot/efi/include/efilib.h	Wed Feb  1 05:24:17 2017	(r313041)
> +++ head/sys/boot/efi/include/efilib.h	Wed Feb  1 08:46:59 2017	(r313042)
> @@ -65,4 +65,12 @@ EFI_STATUS main(int argc, CHAR16 *argv[]
>  void exit(EFI_STATUS status);
>  void delay(int usecs);
>  
> +/* EFI environment initialization. */
> +void efi_init_environment(void);
> +
> +/* CHAR16 utility functions. */
> +int wcscmp(CHAR16 *, CHAR16 *);
> +void cpy8to16(const char *, CHAR16 *, size_t);
> +void cpy16to8(const CHAR16 *, char *, size_t);
> +
>  #endif	/* _LOADER_EFILIB_H */
> 
> Modified: head/sys/boot/efi/libefi/Makefile
> ==============================================================================
> --- head/sys/boot/efi/libefi/Makefile	Wed Feb  1 05:24:17 2017	(r313041)
> +++ head/sys/boot/efi/libefi/Makefile	Wed Feb  1 08:46:59 2017	(r313042)
> @@ -3,6 +3,7 @@
>  .include <src.opts.mk>
>  
>  .if ${MK_FORTH} != "no"
> +CFLAGS+= -DBOOT_FORTH
>  .include "${.CURDIR}/../../Makefile.ficl"
>  .endif
>  
> @@ -10,17 +11,14 @@ LIB=	efi
>  INTERNALLIB=
>  WARNS?=	2
>  
> -SRCS=	delay.c devpath.c efi_console.c efinet.c efipart.c errno.c \
> -	handles.c libefi.c
> +SRCS=	delay.c devpath.c efi_console.c efinet.c efipart.c env.c errno.c \
> +	handles.c wchar.c libefi.c
>  
>  .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
>  SRCS+=	time.c
>  .elif ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
>  SRCS+=	time_event.c
>  .endif
> -.if ${MK_FORTH} != "no"
> -SRCS+=	env.c
> -.endif
>  
>  # We implement a slightly non-standard %S in that it always takes a
>  # CHAR16 that's common in UEFI-land instead of a wchar_t. This only
> 
> Modified: head/sys/boot/efi/libefi/env.c
> ==============================================================================
> --- head/sys/boot/efi/libefi/env.c	Wed Feb  1 05:24:17 2017	(r313041)
> +++ head/sys/boot/efi/libefi/env.c	Wed Feb  1 08:46:59 2017	(r313042)
> @@ -26,15 +26,17 @@
>  #include <sys/cdefs.h>
>  __FBSDID("$FreeBSD$");
>  
> +#include <sys/param.h>
>  #include <stand.h>
>  #include <string.h>
>  #include <efi.h>
>  #include <efilib.h>
>  #include <uuid.h>
> +#include <stdbool.h>
>  #include "bootstrap.h"
> +#ifdef BOOT_FORTH
>  #include "ficl.h"
> -
> -int efi_variable_support = 1;
> +#endif
>  
>  /*
>   * Simple wrappers to the underlying UEFI functions.
> @@ -42,36 +44,348 @@ int efi_variable_support = 1;
>   * for details.
>   */
>  EFI_STATUS
> -efi_get_next_variable_name(UINTN *variable_name_size, CHAR16 *variable_name, EFI_GUID *vendor_guid)
> +efi_get_next_variable_name(UINTN *variable_name_size, CHAR16 *variable_name,
> +    EFI_GUID *vendor_guid)
>  {
> -	return RS->GetNextVariableName(variable_name_size, variable_name, vendor_guid);
> +	return (RS->GetNextVariableName(variable_name_size, variable_name,
> +	    vendor_guid));
>  }
>  
>  EFI_STATUS
> -efi_get_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid, UINT32 *attributes, UINTN *data_size,
> -    void *data)
> +efi_get_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid,
> +    UINT32 *attributes, UINTN *data_size, void *data)
>  {
> -	return RS->GetVariable(variable_name, vendor_guid, attributes, data_size, data);
> +	return (RS->GetVariable(variable_name, vendor_guid, attributes,
> +	    data_size, data));
>  }
>  
>  EFI_STATUS
> -efi_set_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid, UINT32 attributes, UINTN data_size,
> -    void *data)
> +efi_set_variable(CHAR16 *variable_name, EFI_GUID *vendor_guid,
> +    UINT32 attributes, UINTN data_size, void *data)
> +{
> +	return (RS->SetVariable(variable_name, vendor_guid, attributes,
> +	    data_size, data));
> +}
> +
> +void
> +efi_init_environment(void)
> +{
> +	char var[128];
> +
> +	snprintf(var, sizeof(var), "%d.%02d", ST->Hdr.Revision >> 16,
> +	    ST->Hdr.Revision & 0xffff);
> +	env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset);
> +}
> +
> +COMMAND_SET(efishow, "efi-show", "print some or all EFI variables", command_efi_show);
> +
> +static int
> +efi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag)
>  {
> -	return RS->SetVariable(variable_name, vendor_guid, attributes, data_size, data);
> +	UINTN		datasz, i;
> +	EFI_STATUS	status;
> +	UINT32		attr;
> +	CHAR16		*data;
> +	char		*str;
> +	uint32_t	uuid_status;
> +	int		is_ascii;
> +
> +	datasz = 0;
> +	status = RS->GetVariable(varnamearg, matchguid, &attr,
> +	    &datasz, NULL);
> +	if (status != EFI_BUFFER_TOO_SMALL) {
> +		printf("Can't get the variable: error %#lx\n", status);
> +		return (CMD_ERROR);
> +	}
> +	data = malloc(datasz);
> +	status = RS->GetVariable(varnamearg, matchguid, &attr,
> +	    &datasz, data);
> +	if (status != EFI_SUCCESS) {
> +		printf("Can't get the variable: error %#lx\n", status);
> +		return (CMD_ERROR);
> +	}
> +	uuid_to_string((uuid_t *)matchguid, &str, &uuid_status);
> +	if (lflag) {
> +		printf("%s 0x%x %S", str, attr, varnamearg);
> +	} else {
> +		printf("%s 0x%x %S=", str, attr, varnamearg);
> +		is_ascii = 1;
> +		free(str);
> +		str = (char *)data;
> +		for (i = 0; i < datasz - 1; i++) {
> +			/* Quick hack to see if this ascii-ish string printable range plus tab, cr and lf */
> +			if ((str[i] < 32 || str[i] > 126) && str[i] != 9 && str[i] != 10 && str[i] != 13) {
> +				is_ascii = 0;
> +				break;
> +			}
> +		}
> +		if (str[datasz - 1] != '\0')
> +			is_ascii = 0;
> +		if (is_ascii)
> +			printf("%s", str);
> +		else {
> +			for (i = 0; i < datasz / 2; i++) {
> +				if (isalnum(data[i]) || isspace(data[i]))
> +					printf("%c", data[i]);
> +				else
> +					printf("\\x%02x", data[i]);
> +			}
> +		}
> +	}
> +	free(data);
> +	if (pager_output("\n"))
> +		return (CMD_WARN);
> +	return (CMD_OK);
>  }
>  
> +static int
> +command_efi_show(int argc, char *argv[])
> +{
> +	/*
> +	 * efi-show [-a]
> +	 *	print all the env
> +	 * efi-show -u UUID
> +	 *	print all the env vars tagged with UUID
> +	 * efi-show -v var
> +	 *	search all the env vars and print the ones matching var
> +	 * eif-show -u UUID -v var
> +	 * eif-show UUID var
> +	 *	print all the env vars that match UUID and var
> +	 */
> +	/* NB: We assume EFI_GUID is the same as uuid_t */
> +	int		aflag = 0, gflag = 0, lflag = 0, vflag = 0;
> +	int		ch, rv;
> +	unsigned	i;
> +	EFI_STATUS	status;
> +	EFI_GUID	varguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
> +	EFI_GUID	matchguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
> +	uint32_t	uuid_status;
> +	CHAR16		*varname;
> +	CHAR16		*newnm;
> +	CHAR16		varnamearg[128];
> +	UINTN		varalloc;
> +	UINTN		varsz;
> +
> +	while ((ch = getopt(argc, argv, "ag:lv:")) != -1) {
> +		switch (ch) {
> +		case 'a':
> +			aflag = 1;
> +			break;
> +		case 'g':
> +			gflag = 1;
> +			uuid_from_string(optarg, (uuid_t *)&matchguid,
> +			    &uuid_status);
> +			if (uuid_status != uuid_s_ok) {
> +				printf("uid %s could not be parsed\n", optarg);
> +				return (CMD_ERROR);
> +			}
> +			break;
> +		case 'l':
> +			lflag = 1;
> +			break;
> +		case 'v':
> +			vflag = 1;
> +			if (strlen(optarg) >= nitems(varnamearg)) {
> +				printf("Variable %s is longer than %zd characters\n",
> +				    optarg, nitems(varnamearg));
> +				return (CMD_ERROR);
> +			}
> +			for (i = 0; i < strlen(optarg); i++)
> +				varnamearg[i] = optarg[i];
> +			varnamearg[i] = 0;
> +			break;
> +		default:
> +			printf("Invalid argument %c\n", ch);
> +			return (CMD_ERROR);
> +		}
> +	}
> +
> +	if (aflag && (gflag || vflag)) {
> +		printf("-a isn't compatible with -v or -u\n");
> +		return (CMD_ERROR);
> +	}
> +
> +	if (aflag && optind < argc) {
> +		printf("-a doesn't take any args\n");
> +		return (CMD_ERROR);
> +	}
> +
> +	if (optind == argc)
> +		aflag = 1;
> +
> +	argc -= optind;
> +	argv += optind;
> +
> +	pager_open();
> +	if (vflag && gflag) {
> +		rv = efi_print_var(varnamearg, &matchguid, lflag);
> +		pager_close();
> +		return (rv);
> +	}
> +
> +	if (argc == 2) {
> +		optarg = argv[0];
> +		if (strlen(optarg) >= nitems(varnamearg)) {
> +			printf("Variable %s is longer than %zd characters\n",
> +			    optarg, nitems(varnamearg));
> +			pager_close();
> +			return (CMD_ERROR);
> +		}
> +		for (i = 0; i < strlen(optarg); i++)
> +			varnamearg[i] = optarg[i];
> +		varnamearg[i] = 0;
> +		optarg = argv[1];
> +		uuid_from_string(optarg, (uuid_t *)&matchguid,
> +		    &uuid_status);
> +		if (uuid_status != uuid_s_ok) {
> +			printf("uid %s could not be parsed\n", optarg);
> +			pager_close();
> +			return (CMD_ERROR);
> +		}
> +		rv = efi_print_var(varnamearg, &matchguid, lflag);
> +		pager_close();
> +		return (rv);
> +	}
> +
> +	if (argc > 0) {
> +		printf("Too many args %d\n", argc);
> +		pager_close();
> +		return (CMD_ERROR);
> +	}
> +
> +	/*
> +	 * Initiate the search -- note the standard takes pain
> +	 * to specify the initial call must be a poiner to a NULL
> +	 * character.
> +	 */
> +	varalloc = 1024;
> +	varname = malloc(varalloc);
> +	if (varname == NULL) {
> +		printf("Can't allocate memory to get variables\n");
> +		pager_close();
> +		return (CMD_ERROR);
> +	}
> +	varname[0] = 0;
> +	while (1) {
> +		varsz = varalloc;
> +		status = RS->GetNextVariableName(&varsz, varname, &varguid);
> +		if (status == EFI_BUFFER_TOO_SMALL) {
> +			varalloc = varsz;
> +			newnm = realloc(varname, varalloc);
> +			if (newnm == NULL) {
> +				printf("Can't allocate memory to get variables\n");
> +				free(varname);
> +				pager_close();
> +				return (CMD_ERROR);
> +			}
> +			varname = newnm;
> +			continue; /* Try again with bigger buffer */
> +		}
> +		if (status != EFI_SUCCESS)
> +			break;
> +		if (aflag) {
> +			if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
> +				break;
> +			continue;
> +		}
> +		if (vflag) {
> +			if (wcscmp(varnamearg, varname) == 0) {
> +				if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
> +					break;
> +				continue;
> +			}
> +		}
> +		if (gflag) {
> +			if (memcmp(&varguid, &matchguid, sizeof(varguid)) == 0) {
> +				if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
> +					break;
> +				continue;
> +			}
> +		}
> +	}
> +	free(varname);
> +	pager_close();
> +
> +	return (CMD_OK);
> +}
> +
> +COMMAND_SET(efiset, "efi-set", "set EFI variables", command_efi_set);
> +
> +static int
> +command_efi_set(int argc, char *argv[])
> +{
> +	char *uuid, *var, *val;
> +	CHAR16 wvar[128];
> +	EFI_GUID guid;
> +	uint32_t status;
> +	EFI_STATUS err;
> +
> +	if (argc != 4) {
> +		printf("efi-set uuid var new-value\n");
> +		return (CMD_ERROR);
> +	}
> +	uuid = argv[1];
> +	var = argv[2];
> +	val = argv[3];
> +	uuid_from_string(uuid, (uuid_t *)&guid, &status);
> +	if (status != uuid_s_ok) {
> +		printf("Invalid uuid %s %d\n", uuid, status);
> +		return (CMD_ERROR);
> +	}
> +	cpy8to16(var, wvar, sizeof(wvar));
> +	err = RS->SetVariable(wvar, &guid,
> +	    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
> +	    strlen(val) + 1, val);
> +	if (EFI_ERROR(err)) {
> +		printf("Failed to set variable: error %lu\n", EFI_ERROR_CODE(err));
> +		return (CMD_ERROR);
> +	}
> +	return (CMD_OK);
> +}
> +
> +COMMAND_SET(efiunset, "efi-unset", "delete / unset EFI variables", command_efi_unset);
> +
> +static int
> +command_efi_unset(int argc, char *argv[])
> +{
> +	char *uuid, *var;
> +	CHAR16 wvar[128];
> +	EFI_GUID guid;
> +	uint32_t status;
> +	EFI_STATUS err;
> +
> +	if (argc != 3) {
> +		printf("efi-unset uuid var\n");
> +		return (CMD_ERROR);
> +	}
> +	uuid = argv[1];
> +	var = argv[2];
> +	uuid_from_string(uuid, (uuid_t *)&guid, &status);
> +	if (status != uuid_s_ok) {
> +		printf("Invalid uuid %s\n", uuid);
> +		return (CMD_ERROR);
> +	}
> +	cpy8to16(var, wvar, sizeof(wvar));
> +	err = RS->SetVariable(wvar, &guid, 0, 0, NULL);
> +	if (EFI_ERROR(err)) {
> +		printf("Failed to unset variable: error %lu\n", EFI_ERROR_CODE(err));
> +		return (CMD_ERROR);
> +	}
> +	return (CMD_OK);
> +}
> +
> +#ifdef BOOT_FORTH
>  /*
> - *		FreeBSD's loader interaction words and extras
> + * FreeBSD's loader interaction words and extras
>   *
> - * 		efi-setenv  ( value n name n guid n attr -- 0 | -1)
> - * 		efi-getenv  ( guid n addr n -- addr' n' | -1 )
> - * 		efi-unsetenv ( name n guid n'' -- )
> + *	efi-setenv  ( value n name n guid n attr -- 0 | -1)
> + * 	efi-getenv  ( guid n addr n -- addr' n' | -1 )
> + * 	efi-unsetenv ( name n guid n'' -- )
>   */
>  
>  /*
>   * efi-setenv
> - * 		efi-setenv  ( value n name n guid n attr -- 0 | -1)
> + * 	efi-setenv  ( value n name n guid n attr -- 0 | -1)
>   *
>   * Set environment variables using the SetVariable EFI runtime service.
>   *
> @@ -87,19 +401,18 @@ efi_set_variable(CHAR16 *variable_name, 
>   *	4	Run time access
>   * (corresponding to the same bits in the UEFI spec).
>   */
> -void
> +static void
>  ficlEfiSetenv(FICL_VM *pVM)
>  {
> -#ifndef TESTMAIN
>  	char	*value = NULL, *guid = NULL;
>  	CHAR16	*name = NULL;
>  	int	i;
> -#endif
>  	char	*namep, *valuep, *guidp;
>  	int	names, values, guids, attr;
> -	int	status;
> +	EFI_STATUS status;
>  	uuid_t	u;
>  	uint32_t ustatus;
> +	bool	error = true;
>  
>  #if FICL_ROBUST > 1
>  	vmCheckStack(pVM, 6, 0);
> @@ -112,10 +425,9 @@ ficlEfiSetenv(FICL_VM *pVM)
>  	values = stackPopINT(pVM->pStack);
>  	valuep = (char*)stackPopPtr(pVM->pStack);
>  
> -#ifndef TESTMAIN
>  	guid = (char*)ficlMalloc(guids);
>  	if (guid == NULL)
> -		vmThrowErr(pVM, "Error: out of memory");
> +		goto out;
>  	memcpy(guid, guidp, guids);
>  	uuid_from_string(guid, &u, &ustatus);
>  	if (ustatus != uuid_s_ok) {
> @@ -123,16 +435,16 @@ ficlEfiSetenv(FICL_VM *pVM)
>  		goto out;
>  	}
>  
> -	name = (CHAR16 *)ficlMalloc((names + 1) * sizeof(CHAR16));
> +	name = ficlMalloc((names + 1) * sizeof(CHAR16));
>  	if (name == NULL)
> -		vmThrowErr(pVM, "Error: out of memory");
> +		goto out;
>  	for (i = 0; i < names; i++)
>  		name[i] = namep[i];
> -	name[names] = (CHAR16)0;
> +	name[names] = 0;
>  
> -	value = (char*)ficlMalloc(values + 1);
> +	value = ficlMalloc(values + 1);
>  	if (value == NULL)
> -		vmThrowErr(pVM, "Error: out of memory");
> +		goto out;
>  	memcpy(value, valuep, values);
>  
>  	status = efi_set_variable(name, (EFI_GUID *)&u, attr, values, value);
> @@ -140,21 +452,20 @@ ficlEfiSetenv(FICL_VM *pVM)
>  		stackPushINT(pVM->pStack, 0);
>  	else
>  		stackPushINT(pVM->pStack, -1);
> +	error = false;
>  out:
>  	ficlFree(name);
>  	ficlFree(value);
>  	ficlFree(guid);
> -#endif
>  
> -	return;
> +	if (error == true)
> +		vmThrowErr(pVM, "Error: out of memory");
>  }
>  
> -void
> +static void
>  ficlEfiGetenv(FICL_VM *pVM)
>  {
> -#ifndef TESTMAIN
>  	char	*name, *value;
> -#endif
>  	char	*namep;
>  	int	names;
>  
> @@ -164,7 +475,6 @@ ficlEfiGetenv(FICL_VM *pVM)
>  	names = stackPopINT(pVM->pStack);
>  	namep = (char*) stackPopPtr(pVM->pStack);
>  
> -#ifndef TESTMAIN
>  	name = (char*) ficlMalloc(names+1);
>  	if (name == NULL)
>  		vmThrowErr(pVM, "Error: out of memory");
> @@ -178,18 +488,13 @@ ficlEfiGetenv(FICL_VM *pVM)
>  		stackPushPtr(pVM->pStack, value);
>  		stackPushINT(pVM->pStack, strlen(value));
>  	} else
> -#endif
>  		stackPushINT(pVM->pStack, -1);
> -
> -	return;
>  }
>  
> -void
> +static void
>  ficlEfiUnsetenv(FICL_VM *pVM)
>  {
> -#ifndef TESTMAIN
>  	char	*name;
> -#endif
>  	char	*namep;
>  	int	names;
>  
> @@ -199,7 +504,6 @@ ficlEfiUnsetenv(FICL_VM *pVM)
>  	names = stackPopINT(pVM->pStack);
>  	namep = (char*) stackPopPtr(pVM->pStack);
>  
> -#ifndef TESTMAIN
>  	name = (char*) ficlMalloc(names+1);
>  	if (name == NULL)
>  		vmThrowErr(pVM, "Error: out of memory");
> @@ -208,9 +512,6 @@ ficlEfiUnsetenv(FICL_VM *pVM)
>  
>  	unsetenv(name);
>  	ficlFree(name);
> -#endif
> -
> -	return;
>  }
>  
>  /**************************************************************************
> @@ -218,17 +519,14 @@ ficlEfiUnsetenv(FICL_VM *pVM)
>  **************************************************************************/
>  void ficlEfiCompilePlatform(FICL_SYSTEM *pSys)
>  {
> -    FICL_DICT *dp = pSys->dp;
> -    assert (dp);
> -
> -    dictAppendWord(dp, "efi-setenv",    ficlEfiSetenv,	    FW_DEFAULT);
> -    dictAppendWord(dp, "efi-getenv",    ficlEfiGetenv,	    FW_DEFAULT);
> -    dictAppendWord(dp, "efi-unsetenv",  ficlEfiUnsetenv,    FW_DEFAULT);
> +	FICL_DICT *dp = pSys->dp;
> +	assert (dp);
>  
> -    /* Would like to export the EFI version, but this will do for now */
> -    ficlSetEnv(pSys, "efi-boot", 1);
> -
> -    return;
> +	dictAppendWord(dp, "efi-setenv",    ficlEfiSetenv,	FW_DEFAULT);
> +	dictAppendWord(dp, "efi-getenv",    ficlEfiGetenv,	FW_DEFAULT);
> +	dictAppendWord(dp, "efi-unsetenv",  ficlEfiUnsetenv,    FW_DEFAULT);
>  }
>  
>  FICL_COMPILE_SET(ficlEfiCompilePlatform);
> +
> +#endif	/* BOOT_FORTH */
> 
> Added: head/sys/boot/efi/libefi/wchar.c
> ==============================================================================
> --- /dev/null	00:00:00 1970	(empty, because file is newly added)
> +++ head/sys/boot/efi/libefi/wchar.c	Wed Feb  1 08:46:59 2017	(r313042)
> @@ -0,0 +1,73 @@
> +/*-
> + * Copyright 2016 Netflix, Inc. All Rights Reserved.
> + *
> + * 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 <efi.h>
> +#include <efilib.h>
> +
> +/*
> + * CHAR16 related functions moved from loader.
> + * Perhaps we should move those to libstand afterall, but they are
> + * needed only by UEFI.
> + */
> +
> +int
> +wcscmp(CHAR16 *a, CHAR16 *b)
> +{
> +
> +	while (*a && *b && *a == *b) {
> +		a++;
> +		b++;
> +	}
> +	return *a - *b;
> +}
> +
> +/*
> + * cpy8to16 copies a traditional C string into a CHAR16 string and
> + * 0 terminates it. len is the size of *dst in bytes.
> + */
> +void
> +cpy8to16(const char *src, CHAR16 *dst, size_t len)
> +{
> +	len <<= 1;		/* Assume CHAR16 is 2 bytes */
> +	while (len > 0 && *src) {
> +		*dst++ = *src++;
> +		len--;
> +	}
> +	*dst++ = (CHAR16)0;
> +}
> +
> +void
> +cpy16to8(const CHAR16 *src, char *dst, size_t len)
> +{
> +	size_t i;
> +
> +	for (i = 0; i < len && src[i]; i++)
> +		dst[i] = (char)src[i];
> +	if (i < len)
> +		dst[i] = '\0';
> +}
> 
> Modified: head/sys/boot/efi/loader/main.c
> ==============================================================================
> --- head/sys/boot/efi/loader/main.c	Wed Feb  1 05:24:17 2017	(r313041)
> +++ head/sys/boot/efi/loader/main.c	Wed Feb  1 08:46:59 2017	(r313042)
> @@ -52,22 +52,6 @@ __FBSDID("$FreeBSD$");
>  
>  extern char bootprog_info[];
>  
> -#ifdef BOOT_FORTH
> -/*
> - * Normally, efi.o from libefi.a would be brought in due to a function we call
> - * there that's defined there.  However, none of its functions are callable from
> - * here since it just adds words to the FORTH environment or implement those
> - * words. So, add a reference to a symbol in efi.o to force it to be be brought
> - * in so the init function there gets added to the "compile" linker set happens
> - * correctly.
> - *
> - * This assumes there's no global analysys that notices dummy1 isn't used
> - * anywhere and tries to eliminate it.
> - */
> -extern int efi_variable_support;
> -int *dummy1 = &efi_variable_support;
> -#endif
> -
>  struct arch_switch archsw;	/* MI/MD interface boundary */
>  
>  EFI_GUID acpi = ACPI_TABLE_GUID;
> @@ -88,32 +72,6 @@ EFI_GUID inputid = SIMPLE_TEXT_INPUT_PRO
>  static void efi_zfs_probe(void);
>  #endif
>  
> -/*
> - * cpy8to16 copies a traditional C string into a CHAR16 string and
> - * 0 terminates it. len is the size of *dst in bytes.
> - */
> -static void
> -cpy8to16(const char *src, CHAR16 *dst, size_t len)
> -{
> -	len <<= 1;		/* Assume CHAR16 is 2 bytes */
> -	while (len > 0 && *src) {
> -		*dst++ = *src++;
> -		len--;
> -	}
> -	*dst++ = (CHAR16)0;
> -}
> -
> -static void
> -cpy16to8(const CHAR16 *src, char *dst, size_t len)
> -{
> -	size_t i;
> -
> -	for (i = 0; i < len && src[i]; i++)
> -		dst[i] = (char)src[i];
> -	if (i < len)
> -		dst[i] = '\0';
> -}
> -
>  static int
>  has_keyboard(void)
>  {
> @@ -455,9 +413,7 @@ main(int argc, CHAR16 *argv[])
>  	}
>  	}
>  
> -	snprintf(var, sizeof(var), "%d.%02d", ST->Hdr.Revision >> 16,
> -	    ST->Hdr.Revision & 0xffff);
> -	env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset);
> +	efi_init_environment();
>  	setenv("LINES", "24", 1);	/* optional */
>  
>  	for (k = 0; k < ST->NumberOfTableEntries; k++) {
> @@ -476,19 +432,6 @@ main(int argc, CHAR16 *argv[])
>  	return (EFI_SUCCESS);		/* keep compiler happy */
>  }
>  
> -/* XXX move to lib stand ? */
> -static int
> -wcscmp(CHAR16 *a, CHAR16 *b)
> -{
> -
> -	while (*a && *b && *a == *b) {
> -		a++;
> -		b++;
> -	}
> -	return *a - *b;
> -}
> -
> -
>  COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
>  
>  static int
> @@ -770,305 +713,6 @@ command_reloadbe(int argc, char *argv[])
>  }
>  #endif
>  
> -COMMAND_SET(efishow, "efi-show", "print some or all EFI variables", command_efi_show);
> -
> -static int
> -efi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag)
> -{
> -	UINTN		datasz, i;
> -	EFI_STATUS	status;
> -	UINT32		attr;
> -	CHAR16		*data;
> -	char		*str;
> -	uint32_t	uuid_status;
> -	int		is_ascii;
> -
> -	datasz = 0;
> -	status = RS->GetVariable(varnamearg, matchguid, &attr,
> -	    &datasz, NULL);
> -	if (status != EFI_BUFFER_TOO_SMALL) {
> -		printf("Can't get the variable: error %#lx\n", status);
> -		return (CMD_ERROR);
> -	}
> -	data = malloc(datasz);
> -	status = RS->GetVariable(varnamearg, matchguid, &attr,
> -	    &datasz, data);
> -	if (status != EFI_SUCCESS) {
> -		printf("Can't get the variable: error %#lx\n", status);
> -		return (CMD_ERROR);
> -	}
> -	uuid_to_string((uuid_t *)matchguid, &str, &uuid_status);
> -	if (lflag) {
> -		printf("%s 0x%x %S", str, attr, varnamearg);
> -	} else {
> -		printf("%s 0x%x %S=", str, attr, varnamearg);
> -		is_ascii = 1;
> -		free(str);
> -		str = (char *)data;
> -		for (i = 0; i < datasz - 1; i++) {
> -			/* Quick hack to see if this ascii-ish string printable range plus tab, cr and lf */
> -			if ((str[i] < 32 || str[i] > 126) && str[i] != 9 && str[i] != 10 && str[i] != 13) {
> -				is_ascii = 0;
> -				break;
> -			}
> -		}
> -		if (str[datasz - 1] != '\0')
> -			is_ascii = 0;
> -		if (is_ascii)
> -			printf("%s", str);
> -		else {
> -			for (i = 0; i < datasz / 2; i++) {
> -				if (isalnum(data[i]) || isspace(data[i]))
> -					printf("%c", data[i]);
> -				else
> -					printf("\\x%02x", data[i]);
> -			}
> -		}
> -	}
> -	free(data);
> -	if (pager_output("\n"))
> -		return (CMD_WARN);
> -	return (CMD_OK);
> -}
> -
> -static int
> -command_efi_show(int argc, char *argv[])
> -{
> -	/*
> -	 * efi-show [-a]
> -	 *	print all the env
> -	 * efi-show -u UUID
> -	 *	print all the env vars tagged with UUID
> -	 * efi-show -v var
> -	 *	search all the env vars and print the ones matching var
> -	 * eif-show -u UUID -v var
> -	 * eif-show UUID var
> -	 *	print all the env vars that match UUID and var
> -	 */
> -	/* NB: We assume EFI_GUID is the same as uuid_t */
> -	int		aflag = 0, gflag = 0, lflag = 0, vflag = 0;
> -	int		ch, rv;
> -	unsigned	i;
> -	EFI_STATUS	status;
> -	EFI_GUID	varguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
> -	EFI_GUID	matchguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
> -	uint32_t	uuid_status;
> -	CHAR16		*varname;
> -	CHAR16		*newnm;
> -	CHAR16		varnamearg[128];
> -	UINTN		varalloc;
> -	UINTN		varsz;
> -
> -	while ((ch = getopt(argc, argv, "ag:lv:")) != -1) {
> -		switch (ch) {
> -		case 'a':
> -			aflag = 1;
> -			break;
> -		case 'g':
> -			gflag = 1;
> -			uuid_from_string(optarg, (uuid_t *)&matchguid,
> -			    &uuid_status);
> -			if (uuid_status != uuid_s_ok) {
> -				printf("uid %s could not be parsed\n", optarg);
> -				return (CMD_ERROR);
> -			}
> -			break;
> -		case 'l':
> -			lflag = 1;
> -			break;
> -		case 'v':
> -			vflag = 1;
> -			if (strlen(optarg) >= nitems(varnamearg)) {
> -				printf("Variable %s is longer than %zd characters\n",
> -				    optarg, nitems(varnamearg));
> -				return (CMD_ERROR);
> -			}
> -			for (i = 0; i < strlen(optarg); i++)
> -				varnamearg[i] = optarg[i];
> -			varnamearg[i] = 0;
> -			break;
> -		default:
> -			printf("Invalid argument %c\n", ch);
> -			return (CMD_ERROR);
> -		}
> -	}
> -
> -	if (aflag && (gflag || vflag)) {
> -		printf("-a isn't compatible with -v or -u\n");
> -		return (CMD_ERROR);
> -	}
> -
> -	if (aflag && optind < argc) {
> -		printf("-a doesn't take any args");
> -		return (CMD_ERROR);
> -	}
> -
> -	if (optind == argc)
> -		aflag = 1;
> -
> -	argc -= optind;
> -	argv += optind;
> -
> -	pager_open();
> -	if (vflag && gflag) {
> -		rv = efi_print_var(varnamearg, &matchguid, lflag);
> -		pager_close();
> -		return (rv);
> -	}
> -
> -	if (argc == 2) {
> -		optarg = argv[0];
> -		if (strlen(optarg) >= nitems(varnamearg)) {
> -			printf("Variable %s is longer than %zd characters\n",
> -			    optarg, nitems(varnamearg));
> -			pager_close();
> -			return (CMD_ERROR);
> -		}
> -		for (i = 0; i < strlen(optarg); i++)
> -			varnamearg[i] = optarg[i];
> -		varnamearg[i] = 0;
> -		optarg = argv[1];
> -		uuid_from_string(optarg, (uuid_t *)&matchguid,
> -		    &uuid_status);
> -		if (uuid_status != uuid_s_ok) {
> -			printf("uid %s could not be parsed\n", optarg);
> -			pager_close();
> -			return (CMD_ERROR);
> -		}
> -		rv = efi_print_var(varnamearg, &matchguid, lflag);
> -		pager_close();
> -		return (rv);
> -	}
> -
> -	if (argc > 0) {
> -		printf("Too many args %d\n", argc);
> -		pager_close();
> -		return (CMD_ERROR);
> -	}
> -
> -	/*
> -	 * Initiate the search -- note the standard takes pain
> -	 * to specify the initial call must be a poiner to a NULL
> -	 * character.
> -	 */
> -	varalloc = 1024;
> -	varname = malloc(varalloc);
> -	if (varname == NULL) {
> -		printf("Can't allocate memory to get variables\n");
> -		pager_close();
> -		return (CMD_ERROR);
> -	}
> -	varname[0] = 0;
> -	while (1) {
> -		varsz = varalloc;
> -		status = RS->GetNextVariableName(&varsz, varname, &varguid);
> -		if (status == EFI_BUFFER_TOO_SMALL) {
> -			varalloc = varsz;
> -			newnm = malloc(varalloc);
> -			if (newnm == NULL) {
> -				printf("Can't allocate memory to get variables\n");
> -				free(varname);
> -				pager_close();
> -				return (CMD_ERROR);
> -			}
> -			memcpy(newnm, varname, varsz);
> -			free(varname);
> -			varname = newnm;
> -			continue; /* Try again with bigger buffer */
> -		}
> -		if (status != EFI_SUCCESS)
> -			break;
> -		if (aflag) {
> -			if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
> -				break;
> -			continue;
> -		}
> -		if (vflag) {
> -			if (wcscmp(varnamearg, varname) == 0) {
> -				if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
> -					break;
> -				continue;
> -			}
> -		}
> -		if (gflag) {
> -			if (memcmp(&varguid, &matchguid, sizeof(varguid)) == 0) {
> -				if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
> -					break;
> -				continue;
> -			}
> -		}
> -	}
> -	free(varname);
> -	pager_close();
> -
> -	return (CMD_OK);
> -}
> -
> -COMMAND_SET(efiset, "efi-set", "set EFI variables", command_efi_set);
> -
> -static int
> -command_efi_set(int argc, char *argv[])
> -{
> -	char *uuid, *var, *val;
> -	CHAR16 wvar[128];
> -	EFI_GUID guid;
> -	uint32_t status;
> -	EFI_STATUS err;
> -
> -	if (argc != 4) {
> -		printf("efi-set uuid var new-value\n");
> -		return (CMD_ERROR);
> 
> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
> 


More information about the svn-src-head mailing list