X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fefivars.c;h=4fb77428f22a2b94d79f1ca349a225b40d898582;hb=9f26c90cb50c45d4549c4dd569917b4ac143b94d;hp=70b6ce1cc707c7b8c7768ca4bd6e35dd4d9b1301;hpb=8d6167101696a28b7ac61b48fd2c1920564c4e90;p=elogind.git diff --git a/src/shared/efivars.c b/src/shared/efivars.c index 70b6ce1cc..4fb77428f 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -28,10 +28,42 @@ #include "utf8.h" #include "efivars.h" +#ifdef ENABLE_EFI + bool is_efi_boot(void) { return access("/sys/firmware/efi", F_OK) >= 0; } +static int read_flag(const char *varname) { + int r; + void *v; + size_t s; + uint8_t b; + + r = efi_get_variable(EFI_VENDOR_GLOBAL, varname, NULL, &v, &s); + if (r < 0) + return r; + + if (s != 1) { + r = -EINVAL; + goto finish; + } + + b = *(uint8_t *)v; + r = b > 0; +finish: + free(v); + return r; +} + +int is_efi_secure_boot(void) { + return read_flag("SecureBoot"); +} + +int is_efi_secure_boot_setup_mode(void) { + return read_flag("SetupMode"); +} + int efi_get_variable( sd_id128_t vendor, const char *name, @@ -288,11 +320,32 @@ int efi_get_boot_order(uint16_t **order) { return (int) (l / sizeof(uint16_t)); } +static int boot_id_hex(const char s[4]) { + int i; + int id = 0; + + for (i = 0; i < 4; i++) + if (s[i] >= '0' && s[i] <= '9') + id |= (s[i] - '0') << (3 - i) * 4; + else if (s[i] >= 'A' && s[i] <= 'F') + id |= (s[i] - 'A' + 10) << (3 - i) * 4; + else + return -1; + + return id; +} + +static int cmp_uint16(const void *_a, const void *_b) { + const uint16_t *a = _a, *b = _b; + + return (int)*a - (int)*b; +} + int efi_get_boot_options(uint16_t **options) { _cleanup_closedir_ DIR *dir = NULL; struct dirent *de; uint16_t *list = NULL; - int count = 0; + int count = 0, r; assert(options); @@ -300,62 +353,55 @@ int efi_get_boot_options(uint16_t **options) { if (!dir) return -errno; - while ((de = readdir(dir))) { - size_t n; - int a, b, c, d; + FOREACH_DIRENT(de, dir, r = -errno; goto fail) { + int id; uint16_t *t; if (strncmp(de->d_name, "Boot", 4) != 0) continue; - n = strlen(de->d_name); - if (n != 45) + if (strlen(de->d_name) != 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)) + id = boot_id_hex(de->d_name + 4); + if (id < 0) continue; t = realloc(list, (count + 1) * sizeof(uint16_t)); if (!t) { - free(list); - return -ENOMEM; + r = -ENOMEM; + goto fail; } list = t; - list[count ++] = (a - '0') * 1000 + (b - '0') * 100 + (c - '0') * 10 + (d - '0'); - + list[count ++] = id; } + qsort(list, count, sizeof(uint16_t), cmp_uint16); + *options = list; return count; + +fail: + free(list); + return r; } 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); + r = efi_get_variable_string(EFI_VENDOR_LOADER, name, &j); 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; @@ -428,22 +474,16 @@ int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, d } 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); + r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderDevicePartUUID", &p); 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], @@ -456,3 +496,5 @@ int efi_get_loader_device_part_uuid(sd_id128_t *u) { return 0; } + +#endif