Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
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);
	}
}
Пример #9
0
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;
}
Пример #10
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");
}
Пример #11
0
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");
	}
}
Пример #12
0
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;
}