Date: Fri, 3 Feb 2017 05:36:04 +0100 From: Michal Meloun <melounmichal@gmail.com> To: Toomas Soome <tsoome@FreeBSD.org>, svn-src-head@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r313042 - in head/sys/boot: efi/include efi/libefi efi/loader forth Message-ID: <38c02260-7a34-7820-6507-6f240cf8a18c@freebsd.org> In-Reply-To: <201702010846.v118kxNk070776@repo.freebsd.org> References: <201702010846.v118kxNk070776@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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 *** >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?38c02260-7a34-7820-6507-6f240cf8a18c>