2 * libefivar - library for the manipulation of EFI variables
3 * Copyright 2012 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; either version 2.1 of the
8 * License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "fix_coverity.h"
30 #include <sys/types.h>
38 extern int optind, opterr, optopt;
40 #include <efivar/efivar.h>
43 #define ACTION_LIST 0x1
44 #define ACTION_PRINT 0x2
45 #define ACTION_APPEND 0x4
46 #define ACTION_LIST_GUIDS 0x8
47 #define ACTION_WRITE 0x10
48 #define ACTION_PRINT_DEC 0x20
53 #define SHOW_VERBOSE 0
54 #define SHOW_DECIMAL 1
56 static const char *attribute_names[] = {
58 "Boot Service Access",
59 "Runtime Service Access",
60 "Hardware Error Record",
61 "Authenticated Write Access",
62 "Time-Based Authenticated Write Access",
67 static int verbose_errors = 0;
77 printf("Error trace:\n");
78 for (int i = 0; rc > 0; i++) {
79 char *filename = NULL;
80 char *function = NULL;
85 rc = efi_error_get(i, &filename, &function, &line, &message,
88 err(1, "error fetching trace value");
91 printf(" %s:%d %s(): %s: %s", filename, line, function,
92 strerror(error), message);
97 list_all_variables(void)
99 efi_guid_t *guid = NULL;
102 while ((rc = efi_get_next_variable_name(&guid, &name)) > 0)
103 printf(GUID_FORMAT "-%s\n",
104 guid->a, guid->b, guid->c, bswap_16(guid->d),
105 guid->e[0], guid->e[1], guid->e[2], guid->e[3],
106 guid->e[4], guid->e[5], name);
109 fprintf(stderr, "efivar: error listing variables: %m\n");
116 parse_name(const char *guid_name, char **name, efi_guid_t *guid)
118 unsigned int guid_len = sizeof("84be9c3e-8a32-42c0-891c-4cd3b072becc");
119 char guid_buf[guid_len + 2];
123 const char *left, *right;
125 left = strchr(guid_name, '{');
126 right = strchr(guid_name, '}');
128 if (right[1] != '-' || right[2] == '\0') {
131 fprintf(stderr, "efivar: invalid name \"%s\"\n",
136 name_pos = right + 1 - guid_name;
138 strncpy(guid_buf, guid_name, name_pos);
139 guid_buf[name_pos++] = '\0';
141 rc = efi_id_guid_to_guid(guid_buf, guid);
145 /* it has to be at least the length of the guid, a dash, and
146 * one more character */
147 if (strlen(guid_name) < guid_len + 2)
149 name_pos = guid_len - 1;
151 if (guid_name[name_pos] != '-' || guid_name[name_pos+1] == '\0')
155 memset(guid_buf, 0, sizeof(guid_buf));
156 strncpy(guid_buf, guid_name, guid_len - 1);
158 rc = text_to_guid(guid_buf, guid);
163 char *name_buf = NULL;
165 name_len = strlen(guid_name + name_pos) + 1;
166 name_buf = calloc(1, name_len);
168 fprintf(stderr, "efivar: %m\n");
171 strcpy(name_buf, guid_name + name_pos);
176 show_variable(char *guid_name, int display_type)
178 efi_guid_t guid = efi_guid_empty;
182 uint8_t *data = NULL;
183 size_t data_size = 0;
186 parse_name(guid_name, &name, &guid);
187 if (!name || efi_guid_is_empty(&guid)) {
188 fprintf(stderr, "efivar: could not parse variable name.\n");
194 rc = efi_get_variable(guid, name, &data, &data_size, &attributes);
196 fprintf(stderr, "efivar: show variable: %m\n");
201 if (display_type == SHOW_VERBOSE) {
202 printf("GUID: "GUID_FORMAT "\n",
203 guid.a, guid.b, guid.c, bswap_16(guid.d),
204 guid.e[0], guid.e[1], guid.e[2], guid.e[3],
205 guid.e[4], guid.e[5]);
206 printf("Name: \"%s\"\n", name);
207 printf("Attributes:\n");
208 for (int i = 0; attribute_names[i][0] != '\0'; i++) {
209 if(attributes & (1 << i))
210 printf("\t%s\n", attribute_names[i]);
215 while (index < data_size) {
216 char charbuf[] = "................";
217 printf("%08x ", index);
218 /* print the hex values, and render the ascii bits into
220 while (index < data_size) {
221 printf("%02x ", data[index]);
224 if (isprint(data[index]))
225 charbuf[index % 16] = data[index];
231 /* If we're above data_size, finish out the line with
232 * space, and also finish out charbuf with space */
233 while (index >= data_size && index % 16 != 0) {
237 charbuf[index % 16] = ' ';
243 printf("|%s|\n", charbuf);
245 } else if (display_type == SHOW_DECIMAL) {
247 while (index < data_size) {
248 // print the dec values
249 while (index < data_size) {
250 printf("%d ", data[index]);
267 edit_variable(const char *guid_name, void *data, size_t data_size,
268 uint32_t attrib, int edit_type)
270 efi_guid_t guid = efi_guid_empty;
273 uint8_t *old_data = NULL;
274 size_t old_data_size = 0;
275 uint32_t old_attributes = 0;
277 parse_name(guid_name, &name, &guid);
278 if (!name || efi_guid_is_empty(&guid)) {
279 fprintf(stderr, "efivar: could not parse variable name.\n");
284 rc = efi_get_variable(guid, name, &old_data, &old_data_size,
286 if (rc < 0 && edit_type != EDIT_WRITE) {
287 fprintf(stderr, "efivar: %m\n");
293 old_attributes = attrib;
297 rc = efi_append_variable(guid, name, data, data_size,
301 rc = efi_set_variable(guid, name, data, data_size,
302 old_attributes, 0644);
311 fprintf(stderr, "efivar: %m\n");
318 validate_name(const char *name)
321 fprintf(stderr, "Invalid variable name\n");
328 prepare_data(const char *filename, void **data, size_t *data_size)
336 if (filename == NULL) {
337 fprintf(stderr, "Input filename must be provided.\n");
341 fd = open(filename, O_RDONLY);
345 memset(&statbuf, '\0', sizeof (statbuf));
346 rc = fstat(fd, &statbuf);
350 buflen = statbuf.st_size;
351 buf = mmap(NULL, buflen, PROT_READ, MAP_PRIVATE|MAP_POPULATE, fd, 0);
363 fprintf(stderr, "Could not use \"%s\": %m\n", filename);
368 usage(const char *progname)
370 printf("Usage: %s [OPTION...]\n", basename(progname));
371 printf(" -l, --list list current variables\n");
372 printf(" -p, --print print variable specified by --name\n");
373 printf(" -d, --print-decimal print variable in decimal values specified\n");
374 printf(" by --name\n");
375 printf(" -n, --name=<guid-name> variable to manipulate, in the form\n");
376 printf(" 8be4df61-93ca-11d2-aa0d-00e098032b8c-Boot0000\n");
377 printf(" -a, --append append to variable specified by --name\n");
378 printf(" -f, --fromfile=<file> use data from <file>\n");
379 printf(" -t, --attributes=<attributes> attributes to use on append\n");
380 printf(" -L, --list-guids show internal guid list\n");
381 printf(" -w, --write write to variable specified by --name\n\n");
382 printf("Help options:\n");
383 printf(" -?, --help Show this help message\n");
384 printf(" --usage Display brief usage message\n");
388 int main(int argc, char *argv[])
394 size_t data_size = 0;
397 uint32_t attributes = 0;
398 char *sopts = "lpdn:af:t:Lw?";
399 struct option lopts[] =
400 { {"list", no_argument, 0, 'l'},
401 {"print", no_argument, 0, 'p'},
402 {"print-decimal", no_argument, 0, 'd'},
403 {"name", required_argument, 0, 'n'},
404 {"append", no_argument, 0, 'a'},
405 {"fromfile", required_argument, 0, 'f'},
406 {"attributes", required_argument, 0, 't'},
407 {"list-guids", no_argument, 0, 'L'},
408 {"write", no_argument, 0, 'w'},
409 {"help", no_argument, 0, '?'},
410 {"usage", no_argument, 0, 0},
414 while ((c = getopt_long(argc, argv, sopts, lopts, &i)) != -1) {
417 action |= ACTION_LIST;
420 action |= ACTION_PRINT;
423 action |= ACTION_PRINT_DEC;
429 action |= ACTION_APPEND;
435 attributes = strtoul(optarg, NULL, 10);
436 if (errno == ERANGE || errno == EINVAL) {
437 fprintf(stderr, "invalid argument for -t: %s: %s\n", optarg, strerror(errno));
442 action |= ACTION_LIST_GUIDS;
445 action |= ACTION_WRITE;
451 if (strcmp(lopts[i].name, "usage")) {
460 action |= ACTION_PRINT;
464 list_all_variables();
468 show_variable(name, SHOW_VERBOSE);
470 case ACTION_PRINT_DEC | ACTION_PRINT:
472 show_variable(name, SHOW_DECIMAL);
474 case ACTION_APPEND | ACTION_PRINT:
476 prepare_data(file, &data, &data_size);
477 edit_variable(name, data, data_size, attributes,
480 case ACTION_WRITE | ACTION_PRINT:
482 prepare_data(file, &data, &data_size);
483 edit_variable(name, data, data_size, attributes,
486 case ACTION_LIST_GUIDS: {
487 efi_guid_t sentinal = {0xffffffff,0xffff,0xffff,0xffff,
488 {0xff,0xff,0xff,0xff,0xff,0xff}};
489 extern struct guidname efi_well_known_guids[];
490 extern struct guidname *efi_well_known_guids_end;
491 intptr_t start = (intptr_t)&efi_well_known_guids;
492 intptr_t end = (intptr_t)&efi_well_known_guids_end;
495 struct guidname *guid = &efi_well_known_guids[0];
496 for (i = 0; i < (end-start) / sizeof(*guid); i++) {
497 if (!efi_guid_cmp(&sentinal, &guid[i].guid))
499 printf("{"GUID_FORMAT"} {%s} %s %s\n",
500 guid[i].guid.a, guid[i].guid.b,
501 guid[i].guid.c, bswap_16(guid[i].guid.d),
502 guid[i].guid.e[0], guid[i].guid.e[1],
503 guid[i].guid.e[2], guid[i].guid.e[3],
504 guid[i].guid.e[4], guid[i].guid.e[5],
505 guid[i].symbol + strlen("efi_guid_"),
506 guid[i].symbol, guid[i].name);