static int get_os_indications(uint64_t *os_indication) { _cleanup_free_ void *v = NULL; size_t s; int r; /* Let's verify general support first */ r = efi_reboot_to_firmware_supported(); if (r < 0) return r; r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndications", NULL, &v, &s); if (r == -ENOENT) { /* Some firmware implementations that do support OsIndications and report that with * OsIndicationsSupported will remove the OsIndications variable when it is unset. Let's pretend it's 0 * then, to hide this implementation detail. Note that this call will return -ENOENT then only if the * support for OsIndications is missing entirely, as determined by efi_reboot_to_firmware_supported() * above. */ *os_indication = 0; return 0; } else if (r < 0) return r; else if (s != sizeof(uint64_t)) return -EINVAL; *os_indication = *(uint64_t *)v; return 0; }
static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) { _cleanup_free_ void *i = NULL; _cleanup_free_ char *j = NULL; size_t is; int r; uint64_t x; assert(name); assert(u); r = efi_get_variable(EFI_VENDOR_LOADER, name, NULL, &i, &is); if (r < 0) return r; j = utf16_to_utf8(i, is); if (!j) return -ENOMEM; r = safe_atou64(j, &x); if (r < 0) return r; *u = x; return 0; }
int efi_get_loader_device_part_uuid(sd_id128_t *u) { _cleanup_free_ void *s = NULL; _cleanup_free_ char *p = NULL; size_t ss; int r, parsed[16]; unsigned i; assert(u); r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", NULL, &s, &ss); if (r < 0) return r; p = utf16_to_utf8(s, ss); if (!p) return -ENOMEM; if (sscanf(p, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", &parsed[0], &parsed[1], &parsed[2], &parsed[3], &parsed[4], &parsed[5], &parsed[6], &parsed[7], &parsed[8], &parsed[9], &parsed[10], &parsed[11], &parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16) return -EIO; for (i = 0; i < ELEMENTSOF(parsed); i++) u->bytes[i] = parsed[i]; return 0; }
int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { _cleanup_free_ void *s = NULL; size_t ss = 0; int r; char *x; r = efi_get_variable(vendor, name, NULL, &s, &ss); if (r < 0) return r; x = utf16_to_utf8(s, ss); if (!x) return -ENOMEM; *p = x; return 0; }
static int vars_get_variable_attributes(efi_guid_t guid, const char *name, uint32_t *attributes) { int ret = -1; uint8_t *data; size_t data_size; uint32_t attribs; ret = efi_get_variable(guid, name, &data, &data_size, &attribs); if (ret < 0) return ret; *attributes = attribs; if (data) free(data); return ret; }
static int read_flag(const char *varname) { _cleanup_free_ void *v = NULL; uint8_t b; size_t s; int r; if (!is_efi_boot()) /* If this is not an EFI boot, assume the queried flags are zero */ return 0; r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, NULL, &v, &s); if (r < 0) return r; if (s != 1) return -EINVAL; b = *(uint8_t *)v; return !!b; }
static int find_active_entry(struct boot_info *info) { uint16_t boot_cur; void *buf; size_t l; size_t i; int err; err = efi_get_variable(EFI_VENDOR_GLOBAL, "BootCurrent", NULL, &buf, &l); if (err < 0) return err; memcpy(&boot_cur, buf, sizeof(uint16_t)); for (i = 0; i < info->fw_entries_count; i++) { if (info->fw_entries[i].id != boot_cur) continue; info->fw_entry_active = i; err = 0; break; } free(buf); return err; }
static void edit_variable(const char *guid_name, void *data, size_t data_size, int attrib, int edit_type) { efi_guid_t guid; char *name = NULL; int rc; uint8_t *old_data = NULL; size_t old_data_size = 0; uint32_t old_attributes = 0; parse_name(guid_name, &name, &guid); rc = efi_get_variable(guid, name, &old_data, &old_data_size, &old_attributes); if (rc < 0) { fprintf(stderr, "efivar: %m\n"); exit(1); } if (attrib != 0) old_attributes = attrib; switch (edit_type){ case EDIT_APPEND: rc = efi_append_variable(guid, name, data, data_size, old_attributes); break; case EDIT_WRITE: rc = efi_set_variable(guid, name, data, data_size, old_attributes, 0644); break; } if (rc < 0) { fprintf(stderr, "efivar: %m\n"); exit(1); } }
int efi_reboot_to_firmware_supported(void) { _cleanup_free_ void *v = NULL; uint64_t b; size_t s; int r; if (!is_efi_boot()) return -EOPNOTSUPP; r = efi_get_variable(EFI_VENDOR_GLOBAL, "OsIndicationsSupported", NULL, &v, &s); if (r == -ENOENT) /* variable doesn't exist? it's not supported then */ return -EOPNOTSUPP; if (r < 0) return r; if (s != sizeof(uint64_t)) return -EINVAL; b = *(uint64_t*) v; if (!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI)) return -EOPNOTSUPP; /* bit unset? it's not supported then */ return 0; }
static void print_var(efi_guid_t *guid, char *name) { uint32_t att; uint8_t *data; size_t datalen; char *gname; int rv; pretty_guid(guid, &gname); if (pflag) { rv = efi_get_variable(*guid, name, &data, &datalen, &att); if (rv < 0) err(1, "%s-%s", gname, name); if (!Nflag) printf("%s-%s\n", gname, name); if (load_opt_flag) efi_print_load_option(data, datalen, Aflag, bflag, uflag); else if (Aflag) asciidump(data, datalen); else if (uflag) utf8dump(data, datalen); else if (bflag) bindump(data, datalen); else if (dflag) devpath_dump(data, datalen); else hexdump(data, datalen); } else { printf("%s-%s", gname, name); } free(gname); if (!Nflag) printf("\n"); }
static void show_variable(char *guid_name, int display_type) { efi_guid_t guid; char *name = NULL; int rc; uint8_t *data = NULL; size_t data_size = 0; uint32_t attributes; parse_name(guid_name, &name, &guid); errno = 0; rc = efi_get_variable(guid, name, &data, &data_size, &attributes); if (rc < 0) { fprintf(stderr, "efivar: show variable: %m\n"); exit(1); } if (display_type == SHOW_VERBOSE) { printf("GUID: "GUID_FORMAT "\n", guid.a, guid.b, guid.c, bswap_16(guid.d), guid.e[0], guid.e[1], guid.e[2], guid.e[3], guid.e[4], guid.e[5]); printf("Name: \"%s\"\n", name); printf("Attributes:\n"); for (int i = 0; attribute_names[i][0] != '\0'; i++) { if(attributes & (1 << i)) printf("\t%s\n", attribute_names[i]); } printf("Value:\n"); uint32_t index = 0; while (index < data_size) { char charbuf[] = "................"; printf("%08x ", index); /* print the hex values, and render the ascii bits into * charbuf */ while (index < data_size) { printf("%02x ", data[index]); if (index % 8 == 7) printf(" "); if (isprint(data[index])) charbuf[index % 16] = data[index]; index++; if (index % 16 == 0) break; } /* If we're above data_size, finish out the line with * space, and also finish out charbuf with space */ while (index >= data_size && index % 16 != 0) { if (index % 8 == 7) printf(" "); printf(" "); charbuf[index % 16] = ' '; index++; if (index % 16 == 0) break; } printf("|%s|\n", charbuf); } } else if (display_type == SHOW_DECIMAL) { uint32_t index = 0; while (index < data_size) { // print the dec values while (index < data_size) { printf("%d ", data[index]); if (index % 8 == 7) printf(" "); index++; if (index % 16 == 0) break; } } printf("\n"); } }
static int get_info(efi_guid_t *guid, uint64_t hw_inst, update_info **info) { efi_guid_t varguid = FWUPDATE_GUID; char *varname = NULL; char *guidstr = NULL; int rc; update_info *local; int error; rc = efi_guid_to_str(guid, &guidstr); if (rc < 0) return -1; guidstr = onstack(guidstr, strlen(guidstr)+1); rc = asprintf(&varname, "fwupdate-%s-%"PRIx64, guidstr, hw_inst); if (rc < 0) return -1; varname = onstack(varname, strlen(varname)+1); uint8_t *data = NULL; size_t data_size = 0; uint32_t attributes; rc = efi_get_variable(varguid, varname, &data, &data_size, &attributes); if (rc < 0) { if (errno != ENOENT) return -1; local = calloc(1, sizeof (*local)); if (!local) return -1; local->update_info_version = UPDATE_INFO_VERSION; local->guid = *guid; local->hw_inst = hw_inst; local->dp_ptr = calloc(1, 1024); if (!local->dp_ptr) { alloc_err: error = errno; free_info(local); errno = error; return -1; } ssize_t sz; sz = efidp_make_end_entire((uint8_t *)local->dp_ptr, 1024); if (sz < 0) { rc = sz; goto alloc_err; } *info = local; return 0; } /* If our size is wrong, or our data is otherwise bad, try to delete * the variable and create a new one. */ if (data_size < sizeof (*local) || !data) { if (data) free(data); get_err: rc = efi_del_variable(varguid, varname); if (rc < 0) return -1; return get_info(guid, hw_inst, info); } local = (update_info *)data; if (local->update_info_version != UPDATE_INFO_VERSION) goto get_err; ssize_t sz = efidp_size((efidp)local->dp); if (sz < 0) { free(data); errno = EINVAL; return -1; } efidp_header *dp = malloc((size_t)sz); if (!dp) { free(data); errno = ENOMEM; return -1; } memcpy(dp, local->dp, (size_t)sz); local->dp_ptr = dp; *info = local; return 0; }