chiark / gitweb /
efi: fix returned length of efi_get_variable()
[elogind.git] / src / shared / efivars.c
index 3bd47b8868d4f93bc445e26e0b30dbb9e8e3b90d..09af44a2fe6a6764d3b4417b6ff320c6fa5c3b27 100644 (file)
 
 #define EFI_VENDOR_LOADER SD_ID128_MAKE(4a,67,b0,82,0a,4c,41,cf,b6,c7,44,0b,29,bb,8c,4f)
 
+bool is_efiboot(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) {
         _cleanup_close_ int fd = -1;
         _cleanup_free_ char *p = NULL;
@@ -81,7 +85,7 @@ int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, v
         ((char*) r)[st.st_size - 4 + 1] = 0;
 
         *value = r;
-        *size = (size_t) st.st_size;
+        *size = (size_t) st.st_size - 4;
 
         if (attribute)
                 *attribute = a;
@@ -89,45 +93,7 @@ int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, v
         return 0;
 }
 
-static int read_bogomips(unsigned long *u) {
-        _cleanup_fclose_ FILE *f = NULL;
-
-        f = fopen("/proc/cpuinfo", "re");
-        if (!f)
-                return -errno;
-
-        while (!feof(f)) {
-                char line[LINE_MAX];
-                char *x;
-                unsigned long a, b;
-
-                if (!fgets(line, sizeof(line), f))
-                        return -EIO;
-
-                char_array_0(line);
-                truncate_nl(line);
-
-                if (!startswith(line, "bogomips"))
-                        continue;
-
-                x = line + 8;
-                x += strspn(x, WHITESPACE);
-                if (*x != ':')
-                        continue;
-                x++;
-                x += strspn(x, WHITESPACE);
-
-                if (sscanf(x, "%lu.%lu", &a, &b) != 2)
-                        continue;
-
-                *u = a * 1000000L + b * 10000L;
-                return 0;
-        }
-
-        return -EIO;
-}
-
-static int read_ticks(sd_id128_t vendor, const char *name, unsigned long speed, usec_t *u) {
+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;
@@ -149,38 +115,22 @@ static int read_ticks(sd_id128_t vendor, const char *name, unsigned long speed,
         if (r < 0)
                 return r;
 
-        *u = USEC_PER_SEC * x / speed;
+        *u = x;
         return 0;
 }
 
 static int get_boot_usec(usec_t *firmware, usec_t *loader) {
         uint64_t x, y;
         int r;
-        unsigned long bogomips;
 
         assert(firmware);
         assert(loader);
 
-        /* Returns the usec after the CPU was turned on. The two
-         * timestamps are: the firmware finished, and the boot loader
-         * finished. */
-
-        /* We assume that the kernel's bogomips value is calibrated to
-         * twice the CPU frequency, and use this to convert the TSC
-         * ticks into usec. Of course, bogomips are only vaguely
-         * defined. If this breaks one day we can come up with
-         * something better. However, for now this saves us from doing
-         * a local calibration loop. */
-
-        r = read_bogomips(&bogomips);
+        r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x);
         if (r < 0)
                 return r;
 
-        r = read_ticks(EFI_VENDOR_LOADER, "LoaderTicksInit", bogomips / 2, &x);
-        if (r < 0)
-                return r;
-
-        r = read_ticks(EFI_VENDOR_LOADER, "LoaderTicksExec", bogomips / 2, &y);
+        r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y);
         if (r < 0)
                 return r;
 
@@ -231,3 +181,33 @@ int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, d
 
         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;
+}