2 * Copyright (c) 2015 Netflix, Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
29 #include <sys/param.h>
36 #include "bootstrap.h"
39 efi_init_environment(void)
43 snprintf(var, sizeof(var), "%d.%02d", ST->Hdr.Revision >> 16,
44 ST->Hdr.Revision & 0xffff);
45 env_setenv("efi-version", EV_VOLATILE, var, env_noset, env_nounset);
48 COMMAND_SET(efishow, "efi-show", "print some or all EFI variables", command_efi_show);
51 efi_print_var(CHAR16 *varnamearg, EFI_GUID *matchguid, int lflag)
62 status = RS->GetVariable(varnamearg, matchguid, &attr,
64 if (status != EFI_BUFFER_TOO_SMALL) {
65 printf("Can't get the variable: error %#lx\n",
66 EFI_ERROR_CODE(status));
69 data = malloc(datasz);
70 status = RS->GetVariable(varnamearg, matchguid, &attr,
72 if (status != EFI_SUCCESS) {
73 printf("Can't get the variable: error %#lx\n",
74 EFI_ERROR_CODE(status));
77 uuid_to_string((uuid_t *)matchguid, &str, &uuid_status);
79 printf("%s 0x%x %S", str, attr, varnamearg);
81 printf("%s 0x%x %S=", str, attr, varnamearg);
85 for (i = 0; i < datasz - 1; i++) {
86 /* Quick hack to see if this ascii-ish string printable range plus tab, cr and lf */
87 if ((str[i] < 32 || str[i] > 126) && str[i] != 9 && str[i] != 10 && str[i] != 13) {
92 if (str[datasz - 1] != '\0')
97 for (i = 0; i < datasz / 2; i++) {
98 if (isalnum(data[i]) || isspace(data[i]))
99 printf("%c", data[i]);
101 printf("\\x%02x", data[i]);
106 if (pager_output("\n"))
112 command_efi_show(int argc, char *argv[])
118 * print all the env vars tagged with UUID
120 * search all the env vars and print the ones matching var
121 * efi-show -g UUID -v var
123 * print all the env vars that match UUID and var
125 /* NB: We assume EFI_GUID is the same as uuid_t */
126 int aflag = 0, gflag = 0, lflag = 0, vflag = 0;
130 EFI_GUID varguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
131 EFI_GUID matchguid = { 0,0,0,{0,0,0,0,0,0,0,0} };
132 uint32_t uuid_status;
135 CHAR16 varnamearg[128];
139 while ((ch = getopt(argc, argv, "ag:lv:")) != -1) {
146 uuid_from_string(optarg, (uuid_t *)&matchguid,
148 if (uuid_status != uuid_s_ok) {
149 printf("uid %s could not be parsed\n", optarg);
158 if (strlen(optarg) >= nitems(varnamearg)) {
159 printf("Variable %s is longer than %zd characters\n",
160 optarg, nitems(varnamearg));
163 for (i = 0; i < strlen(optarg); i++)
164 varnamearg[i] = optarg[i];
168 printf("Invalid argument %c\n", ch);
173 if (aflag && (gflag || vflag)) {
174 printf("-a isn't compatible with -v or -u\n");
178 if (aflag && optind < argc) {
179 printf("-a doesn't take any args\n");
190 if (vflag && gflag) {
191 rv = efi_print_var(varnamearg, &matchguid, lflag);
198 if (strlen(optarg) >= nitems(varnamearg)) {
199 printf("Variable %s is longer than %zd characters\n",
200 optarg, nitems(varnamearg));
204 for (i = 0; i < strlen(optarg); i++)
205 varnamearg[i] = optarg[i];
208 uuid_from_string(optarg, (uuid_t *)&matchguid,
210 if (uuid_status != uuid_s_ok) {
211 printf("uid %s could not be parsed\n", optarg);
215 rv = efi_print_var(varnamearg, &matchguid, lflag);
221 printf("Too many args %d\n", argc);
227 * Initiate the search -- note the standard takes pain
228 * to specify the initial call must be a poiner to a NULL
232 varname = malloc(varalloc);
233 if (varname == NULL) {
234 printf("Can't allocate memory to get variables\n");
241 status = RS->GetNextVariableName(&varsz, varname, &varguid);
242 if (status == EFI_BUFFER_TOO_SMALL) {
244 newnm = realloc(varname, varalloc);
246 printf("Can't allocate memory to get variables\n");
252 continue; /* Try again with bigger buffer */
254 if (status != EFI_SUCCESS)
257 if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
262 if (wcscmp(varnamearg, varname) == 0) {
263 if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
269 if (memcmp(&varguid, &matchguid, sizeof(varguid)) == 0) {
270 if (efi_print_var(varname, &varguid, lflag) != CMD_OK)
282 COMMAND_SET(efiset, "efi-set", "set EFI variables", command_efi_set);
285 command_efi_set(int argc, char *argv[])
287 char *uuid, *var, *val;
294 printf("efi-set uuid var new-value\n");
300 uuid_from_string(uuid, (uuid_t *)&guid, &status);
301 if (status != uuid_s_ok) {
302 printf("Invalid uuid %s %d\n", uuid, status);
305 cpy8to16(var, wvar, sizeof(wvar));
306 err = RS->SetVariable(wvar, &guid,
307 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
308 strlen(val) + 1, val);
309 if (EFI_ERROR(err)) {
310 printf("Failed to set variable: error %lu\n", EFI_ERROR_CODE(err));
316 COMMAND_SET(efiunset, "efi-unset", "delete / unset EFI variables", command_efi_unset);
319 command_efi_unset(int argc, char *argv[])
328 printf("efi-unset uuid var\n");
333 uuid_from_string(uuid, (uuid_t *)&guid, &status);
334 if (status != uuid_s_ok) {
335 printf("Invalid uuid %s\n", uuid);
338 cpy8to16(var, wvar, sizeof(wvar));
339 err = RS->SetVariable(wvar, &guid, 0, 0, NULL);
340 if (EFI_ERROR(err)) {
341 printf("Failed to unset variable: error %lu\n", EFI_ERROR_CODE(err));