From: Lennart Poettering Date: Tue, 12 Feb 2013 23:07:55 +0000 (+0100) Subject: efi: various cleanups X-Git-Tag: v198~287^2~3 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=9cde64ff264c432fc83be638e57d8fd6392793a6 efi: various cleanups --- diff --git a/src/boot/boot-efi.c b/src/boot/boot-efi.c index 32cb973cf..ac5f9c12a 100644 --- a/src/boot/boot-efi.c +++ b/src/boot/boot-efi.c @@ -66,7 +66,7 @@ static int get_boot_entries(struct boot_info *info) { memset(e, 0, sizeof(struct boot_info_entry)); e->order = -1; - err = efi_get_boot_option(id, NULL, &e->title, &e->part_uuid, &e->path, &e->data, &e->data_size); + err = efi_get_boot_option(id, &e->title, &e->part_uuid, &e->path); if (err < 0) break; e->id = id; @@ -103,11 +103,13 @@ static int find_active_entry(struct boot_info *info) { static int get_boot_order(struct boot_info *info) { size_t i, k; - int err; + int r; - err = efi_get_boot_order(&info->fw_entries_order, &info->fw_entries_order_count); - if (err < 0) - return err; + r = efi_get_boot_order(&info->fw_entries_order); + if (r < 0) + return r; + + info->fw_entries_order_count = r; for (i = 0; i < info->fw_entries_order_count; i++) { for (k = 0; k < info->fw_entries_count; k++) { @@ -142,9 +144,9 @@ static int entry_cmp(const void *a, const void *b) { int boot_info_query(struct boot_info *info) { char str[64]; char buf[64]; - char *loader_active; + char *loader_active = NULL; - info->loader = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo"); + efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderInfo", &info->loader); get_boot_entries(info); if (info->fw_entries_count > 0) { @@ -153,19 +155,20 @@ int boot_info_query(struct boot_info *info) { find_active_entry(info); } - info->fw_type = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareType"); - info->fw_info = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareInfo"); - info->loader_image_path = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderImageIdentifier"); + efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareType", &info->fw_type); + efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderFirmwareInfo", &info->fw_info); + efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderImageIdentifier", &info->loader_image_path); efi_get_loader_device_part_uuid(&info->loader_part_uuid); boot_loader_read_entries(info); - loader_active = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntrySelected"); + efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntrySelected", &loader_active); if (loader_active) { boot_loader_find_active_entry(info, loader_active); free(loader_active); } snprintf(str, sizeof(str), "LoaderEntryOptions-%s", sd_id128_to_string(info->machine_id, buf)); - info->loader_options_added = efi_get_variable_string(EFI_VENDOR_LOADER, str); + efi_get_variable_string(EFI_VENDOR_LOADER, str, &info->loader_options_added); + return 0; } diff --git a/src/boot/boot.h b/src/boot/boot.h index 90e45ccd6..febee123d 100644 --- a/src/boot/boot.h +++ b/src/boot/boot.h @@ -38,8 +38,6 @@ struct boot_info_entry { char *title; sd_id128_t part_uuid; char *path; - char *data; - size_t data_size; }; struct boot_info { diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index 5b32474bb..2cd0b60ba 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -78,7 +78,7 @@ static const MountPoint mount_table[] = { { "securityfs", "/sys/kernel/security", "securityfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_NONE }, { "efivarfs", "/sys/firmware/efi/efivars", "efivarfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, - is_efiboot, MNT_NONE }, + is_efi_boot, MNT_NONE }, { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, diff --git a/src/efi-boot-generator/efi-boot-generator.c b/src/efi-boot-generator/efi-boot-generator.c index 1319c7120..88fa220d2 100644 --- a/src/efi-boot-generator/efi-boot-generator.c +++ b/src/efi-boot-generator/efi-boot-generator.c @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) { umask(0022); - if (!is_efiboot()) + if (!is_efi_boot()) return EXIT_SUCCESS; if (dir_is_empty("/boot") <= 0) diff --git a/src/shared/efivars.c b/src/shared/efivars.c index e16c61029..3e59ee5e7 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -27,11 +27,17 @@ #include "utf8.h" #include "efivars.h" -bool is_efiboot(void) { +bool is_efi_boot(void) { return access("/sys/firmware/efi", F_OK) >= 0; } -int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size) { +int efi_get_variable( + sd_id128_t vendor, + const char *name, + uint32_t *attribute, + void **value, + size_t *size) { + _cleanup_close_ int fd = -1; _cleanup_free_ char *p = NULL; uint32_t a; @@ -61,7 +67,7 @@ int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, v n = read(fd, &a, sizeof(a)); if (n < 0) - return (int) n; + return -errno; if (n != sizeof(a)) return -EIO; @@ -92,15 +98,22 @@ int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, v return 0; } -char *efi_get_variable_string(sd_id128_t vendor, const char *name) { +int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p) { _cleanup_free_ void *s = NULL; size_t ss; - int err; + int r; + char *x; - err = efi_get_variable(vendor, name, NULL, &s, &ss); - if (err < 0) - return NULL; - return utf16_to_utf8(s, ss); + 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 size_t utf16_size(const uint16_t *s) { @@ -108,6 +121,7 @@ static size_t utf16_size(const uint16_t *s) { while (s[l] > 0) l++; + return (l+1) * sizeof(uint16_t); } @@ -131,7 +145,12 @@ static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) { memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4)); } -int efi_get_boot_option(uint32_t id, uint32_t *attributes, char **title, sd_id128_t *part_uuid, char **path, char **data, size_t *data_size) { +int efi_get_boot_option( + uint16_t id, + char **title, + sd_id128_t *part_uuid, + char **path) { + struct boot_option { uint32_t attr; uint16_t path_len; @@ -157,23 +176,20 @@ int efi_get_boot_option(uint32_t id, uint32_t *attributes, char **title, sd_id12 }; } _packed_; - char boot_id[32]; - _cleanup_free_ char *buf = NULL; + char boot_id[9]; + _cleanup_free_ uint8_t *buf = NULL; size_t l; struct boot_option *header; size_t title_size; char *s = NULL; char *p = NULL; sd_id128_t p_uuid = SD_ID128_NULL; - char *d = NULL; - size_t d_size = 0; int err; snprintf(boot_id, sizeof(boot_id), "Boot%04X", id); err = efi_get_variable(EFI_VENDOR_GLOBAL, boot_id, NULL, (void **)&buf, &l); if (err < 0) return err; - if (l < sizeof(struct boot_option)) return -ENOENT; @@ -189,7 +205,7 @@ int efi_get_boot_option(uint32_t id, uint32_t *attributes, char **title, sd_id12 } if (header->path_len > 0) { - char *dbuf; + uint8_t *dbuf; size_t dnext; dbuf = buf + offsetof(struct boot_option, title) + title_size; @@ -233,45 +249,92 @@ int efi_get_boot_option(uint32_t id, uint32_t *attributes, char **title, sd_id12 } } - *title = s; + if (title) + *title = s; if (part_uuid) *part_uuid = p_uuid; if (path) *path = p; - if (data) - *data = d; - if (data_size) - *data_size = d_size; + return 0; err: free(s); free(p); - free(d); return err; } -int efi_get_boot_order(uint16_t **order, size_t *count) { +int efi_get_boot_order(uint16_t **order) { void *buf; size_t l; - int err; + int r; - err = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l); - if (err < 0) - return err; + r = efi_get_variable(EFI_VENDOR_GLOBAL, "BootOrder", NULL, &buf, &l); + if (r < 0) + return r; - if (l == 0) { + if (l <= 0) { free(buf); return -ENOENT; } - if ((l % sizeof(uint16_t) > 0)) { + if ((l % sizeof(uint16_t) > 0) || + (l / sizeof(uint16_t) > INT_MAX)) { free(buf); return -EINVAL; } *order = buf; - *count = l / sizeof(uint16_t); - return 0; + return (int) (l / sizeof(uint16_t)); +} + +int efi_get_boot_options(uint16_t **options) { + _cleanup_closedir_ DIR *dir = NULL; + struct dirent *de; + uint16_t *list = NULL; + int count = 0; + + assert(options); + + dir = opendir("/sys/firmware/efi/efivars/"); + if (!dir) + return -errno; + + while ((de = readdir(dir))) { + size_t n; + int a, b, c, d; + uint16_t *t; + + if (strncmp(de->d_name, "Boot", 4) != 0) + continue; + + n = strlen(de->d_name); + if (n != 45) + continue; + + if (strcmp(de->d_name + 8, "-8be4df61-93ca-11d2-aa0d-00e098032b8c") != 0) + continue; + + a = de->d_name[4]; + b = de->d_name[5]; + c = de->d_name[6]; + d = de->d_name[7]; + + if (!isdigit(a) || !isdigit(b) || !isdigit(c) || !isdigit(d)) + continue; + + t = realloc(list, (count + 1) * sizeof(uint16_t)); + if (!t) { + free(list); + return -ENOMEM; + } + + list = t; + list[count ++] = (a - '0') * 1000 + (b - '0') * 100 + (c - '0') * 10 + (d - '0'); + + } + + *options = list; + return count; } static int read_usec(sd_id128_t vendor, const char *name, usec_t *u) { diff --git a/src/shared/efivars.h b/src/shared/efivars.h index d54cc433b..380e038f6 100644 --- a/src/shared/efivars.h +++ b/src/shared/efivars.h @@ -31,13 +31,14 @@ #define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f) #define EFI_VENDOR_GLOBAL SD_ID128_MAKE(8b,e4,df,61,93,ca,11,d2,aa,0d,00,e0,98,03,2b,8c) -bool is_efiboot(void); +bool is_efi_boot(void); int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size); -char *efi_get_variable_string(sd_id128_t vendor, const char *name); +int efi_get_variable_string(sd_id128_t vendor, const char *name, char **p); -int efi_get_boot_option(uint32_t nr, uint32_t *attributes, char **title, sd_id128_t *partuuid, char **path, char **data, size_t *data_size); -int efi_get_boot_order(uint16_t **order, size_t *count); +int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *partuuid, char **path); +int efi_get_boot_order(uint16_t **order); +int efi_get_boot_options(uint16_t **options); int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader);