From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1a2xnK-0001sN-Qh for mharc-grub-devel@gnu.org; Sun, 29 Nov 2015 03:57:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34211) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a2xnH-0001s6-Rm for grub-devel@gnu.org; Sun, 29 Nov 2015 03:57:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a2xnE-00039S-Hm for grub-devel@gnu.org; Sun, 29 Nov 2015 03:57:15 -0500 Received: from mail-lf0-x232.google.com ([2a00:1450:4010:c07::232]:35706) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a2xnE-00039C-7Y for grub-devel@gnu.org; Sun, 29 Nov 2015 03:57:12 -0500 Received: by lfdl133 with SMTP id l133so164994208lfd.2 for ; Sun, 29 Nov 2015 00:57:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-type:content-transfer-encoding; bh=w+ItrlkWt6SrIaImAAHwj56xAnrHVtT50V4e6zKEq3I=; b=Uwrrp1VtmPC6KP4p4B3G6MWYqyTYTfXFxQSgEMH2ge97cIUmOM2bAw1HkOsvzF2UYM mvHxeNlze9enLrgw96owviGl7xX2e4E7BMvCVp61LtFquCv94/uViCRUGj7clAAy1yyk Nw32z3jkWR3gBm+mV+Pf+gwZJE3eo9Alo9pG1dAKWWMwg1yfsjs3ch1sGIpwrJLnYUJP 3r4arTGEXmPIjUJFwrCjlyLChKaR6ImL0V0C381ZxPQ/Awosi5lrukkxVa3pnQER8SXd MrS2Y67vRvRe2BCzai4BStEFDSXM8CICoN8fucky8rErqpii6Ks3OpO+ySbZbE8K+2Ea U8yA== X-Received: by 10.25.148.202 with SMTP id w193mr23683095lfd.130.1448787431162; Sun, 29 Nov 2015 00:57:11 -0800 (PST) Received: from [192.168.1.41] (ppp91-76-25-247.pppoe.mtu-net.ru. [91.76.25.247]) by smtp.gmail.com with ESMTPSA id qp7sm6291717lbc.24.2015.11.29.00.57.10 for (version=TLSv1/SSLv3 cipher=OTHER); Sun, 29 Nov 2015 00:57:10 -0800 (PST) Subject: Re: Grub get and set efi variables To: The development of GNU GRUB References: <563999B9.7020108@gmail.com> <5643845E.9060204@gmail.com> <5646B275.5040707@gmail.com> From: Andrei Borzenkov X-Enigmail-Draft-Status: N1110 Message-ID: <565ABDE5.1030300@gmail.com> Date: Sun, 29 Nov 2015 11:57:09 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:4010:c07::232 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 29 Nov 2015 08:57:17 -0000 17.11.2015 14:48, Ignat Korchagin пишет: > Please, see updated patch below. I tried to reuse GRUB hexdump > function, so as a result dump will not work with setting vatiables - > just dumping to stdout. But it doesn't make sense to assign dump to a > variable anyway. > > diff --git a/grub-core/commands/efi/efivar.c b/grub-core/commands/efi/efivar.c > new file mode 100644 > index 0000000..3ffd5ca > --- /dev/null > +++ b/grub-core/commands/efi/efivar.c > @@ -0,0 +1,253 @@ > +/* efivar.c - Read EFI global variables. */ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2015 Free Software Foundation, Inc. > + * Copyright (C) 2015 CloudFlare, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see . > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +GRUB_MOD_LICENSE ("GPLv3+"); > + > +static const struct grub_arg_option options[] = { > + {"format", 'f', GRUB_ARG_OPTION_OPTIONAL, N_("Parse EFI_VAR in > specific format (hex, uint8, ascii, raw, dump). Default: hex."), > N_("FORMAT"), ARG_TYPE_STRING}, > + {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Save parsed result to > environment variable (does not work with dump)."), N_("ENV_VAR"), > ARG_TYPE_STRING}, > + {0, 0, 0, 0, 0, 0} > +}; > + > +enum efi_var_type > + { > + EFI_VAR_ASCII = 0, > + EFI_VAR_RAW, > + EFI_VAR_UINT8, > + EFI_VAR_HEX, > + EFI_VAR_DUMP, > + EFI_VAR_INVALID = -1 > + }; > + > +static enum efi_var_type > +parse_efi_var_type (const char *type) > +{ > + if (!grub_strncmp (type, "ascii", sizeof("ascii"))) > + return EFI_VAR_ASCII; > + > + if (!grub_strncmp (type, "raw", sizeof("raw"))) > + return EFI_VAR_ASCII; > + > + if (!grub_strncmp (type, "uint8", sizeof("uint8"))) > + return EFI_VAR_UINT8; > + > + if (!grub_strncmp (type, "hex", sizeof("hex"))) > + return EFI_VAR_HEX; > + > + if (!grub_strncmp (type, "dump", sizeof("dump"))) > + return EFI_VAR_DUMP; > + Should not this be strcmp, not str*n*cmp? > + return EFI_VAR_INVALID; > +} > + > +static int > +grub_print_ascii (char *str, char c) > +{ > + if (grub_iscntrl (c)) > + { > + switch (c) > + { > + case '\0': > + str[0] = '\\'; > + str[1] = '0'; > + return 2; > + > + case '\a': > + str[0] = '\\'; > + str[1] = 'a'; > + return 2; > + > + case '\b': > + str[0] = '\\'; > + str[1] = 'b'; > + return 2; > + > + case '\f': > + str[0] = '\\'; > + str[1] = 'f'; > + return 2; > + > + case '\n': > + str[0] = '\\'; > + str[1] = 'n'; > + return 2; > + > + case '\r': > + str[0] = '\\'; > + str[1] = 'r'; > + return 2; > + > + case '\t': > + str[0] = '\\'; > + str[1] = 't'; > + return 2; > + > + case '\v': > + str[0] = '\\'; > + str[1] = 'v'; > + return 2; > + > + default: > + str[0] = '.'; /* as in hexdump -C */ > + return 1; > + } > + } > + > + str[0] = c; > + return 1; > +} > + > +static grub_err_t > +grub_cmd_get_efi_var (struct grub_extcmd_context *ctxt, > + int argc, char **args) > +{ > + struct grub_arg_list *state = ctxt->state; > + grub_err_t status; > + void *efi_var = NULL; > + grub_size_t efi_var_size = 0; > + enum efi_var_type efi_type = EFI_VAR_HEX; > + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; > + char *env_var = NULL; > + grub_size_t i; > + char *ptr; > + > + if (1 != argc) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); One argument expected > + > + if (state[0].set) > + efi_type = parse_efi_var_type (state[0].arg); > + > + if (EFI_VAR_INVALID == efi_type) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid format specifier")); > + > + efi_var = grub_efi_get_variable (args[0], &global, &efi_var_size); > + if (!efi_var || !efi_var_size) > + { > + status = grub_error (GRUB_ERR_READ_ERROR, N_("cannot read variable")); > + goto err; > + } > + > + switch (efi_type) > + { > + case EFI_VAR_ASCII: > + env_var = grub_malloc (efi_var_size * 2 + 1); > + if (!env_var) > + { > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); > + break; > + } > + > + ptr = env_var; > + > + for (i = 0; i < efi_var_size; i++) > + ptr += grub_print_ascii (ptr, ((const char *)efi_var)[i]); > + *ptr = '\0'; > + break; > + > + case EFI_VAR_RAW: > + env_var = grub_malloc (efi_var_size + 1); > + if (!env_var) > + { > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); > + break; > + } > + grub_memcpy (env_var, efi_var, efi_var_size); > + env_var[efi_var_size] = '\0'; That would be wrong ("raw" implies no modification) but I am not keen on keeping "raw" as was discussed. > + break; > + > + case EFI_VAR_UINT8: > + env_var = grub_malloc (4); > + if (!env_var) > + { > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); > + break; > + } > + grub_snprintf (env_var, 4, "%u", *((grub_uint8_t *)efi_var)); > + break; > + > + case EFI_VAR_HEX: > + env_var = grub_malloc (efi_var_size * 2 + 1); > + if (!env_var) > + { > + status = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); > + break; > + } > + for (i = 0; i < efi_var_size; i++) > + grub_snprintf (env_var + (i * 2), 3, "%02x", ((grub_uint8_t > *)efi_var)[i]); > + break; > + > + case EFI_VAR_DUMP: > + if (state[1].set) > + status = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot set > variable with dump format specifier")); > + else > + { > + hexdump (0, (char *)efi_var, efi_var_size); > + status = GRUB_ERR_NONE; > + } > + break; > + > + default: > + status = grub_error (GRUB_ERR_BUG, N_("should not happen (bug > in module?)")); > + } > + > + if (efi_type != EFI_VAR_DUMP) > + { > + if (state[1].set) > + status = grub_env_set (state[1].arg, env_var); > + else > + { > + grub_printf ("%s\n", (const char *)env_var); > + status = GRUB_ERR_NONE; > + } > + } > + > +err: > + > + if (env_var) > + grub_free (env_var); > + > + if (efi_var) > + grub_free (efi_var); > + > + return status; > +} > + > +static grub_extcmd_t cmd = NULL; > + > +GRUB_MOD_INIT (efivar) > +{ > + cmd = grub_register_extcmd ("get_efivar", grub_cmd_get_efi_var, 0, > N_("[-f FORMAT] [-s ENV_VAR] EFI_VAR"), > + N_("Read EFI variable and print it or save its contents to > environment variable."), options); > +} > + > +GRUB_MOD_FINI (efivar) > +{ > + if (cmd) > + grub_unregister_extcmd (cmd); > +} > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index a6101de..2c8f023 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -728,6 +728,12 @@ > }; > > module = { > + name = efivar; > + efi = commands/efi/efivar.c; > + enable = efi; > +}; > + > +module = { > name = blocklist; > common = commands/blocklist.c; > }; > > On Sat, Nov 14, 2015 at 4:03 AM, Andrei Borzenkov wrote: >> 13.11.2015 22:42, Ignat Korchagin пишет: >>>>>> >>>>>> +static enum efi_var_type >>>>>> +parse_efi_var_type (const char *type) >>>>>> +{ >>>>>> + if (!grub_strncmp (type, "string", sizeof("string"))) >>>>>> + return EFI_VAR_STRING; >>>>>> + >>>>> >>>>> >>>>> >>>>> I think this should be "ascii" or "utf8". "string" is too ambiguous in >>>>> UEFI >>>>> environment, it can also mean sequence of UCS-2 characters. >>>> >>>> I'm still not sure how exactly GRUB + UEFI interprets "raw buffers" >>>> when printing. Maybe, to avoid confusion, it might be better to >>>> completely remove this option. Basically, you do not want to interpret >>>> raw buffers as strings. For best compatibility "hex" mode should be >>>> promoted, I guess. What do you think? >>> >>> Checked again the UEFI spec. For globally defined variables which are >>> strings they specify ASCII. So if we leave this option, ascii is the >>> best name. >>> >> >> What about >> >> - ascii - print ASCII characters verbatim, escape non-ASCII in usual way >> (similar to "od -c") >> >> - raw - simply put raw variable without any interpretation. >> >> This is better aligned with argument describing output formatting rather >> than attempting to "type" variable. >> >> Alternative (or in addition to) ascii - dump which prints usual pretty hex >> dump of content (hexdump -C). This is handy to interactively look at >> variable content. >> >> Or, and change name from --type to --format :) >> >> >> _______________________________________________ >> Grub-devel mailing list >> Grub-devel@gnu.org >> https://lists.gnu.org/mailman/listinfo/grub-devel > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel >