]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
efi-loader: split efi-api.[ch] from efi-loader.[ch] 22840/head
authorLennart Poettering <lennart@poettering.net>
Wed, 23 Mar 2022 11:07:06 +0000 (12:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 24 Mar 2022 14:21:09 +0000 (15:21 +0100)
Some refactoring: split efi-loader.[ch] in two: isolate the calls that
implement out boot loader interface spec, and those which implement
access to upstream UEFI firmware features.

They are quite different in nature and behaviour, and even semantically
it makes to keep these two separate. At the very least because the
previous name "efi-loader.[ch]" suggests all was about loader-specific
APIs, but much of it is generic uefi stuff...

While we are at it, I renamed a bunch of return parameters to follow our
usual ret_xyz naming. But besides renaming no real code changes.

src/boot/bless-boot.c
src/boot/bootctl.c
src/cryptsetup/cryptsetup.c
src/login/logind-dbus.c
src/shared/condition.c
src/shared/efi-api.c [new file with mode: 0644]
src/shared/efi-api.h [new file with mode: 0644]
src/shared/efi-loader.c
src/shared/efi-loader.h
src/shared/meson.build

index 259ae33bb5626218914b8b98038e78b649926241..c8bc205d1b03dae8aae232f65c5f01b2f081eb5f 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "alloc-util.h"
 #include "bootspec.h"
+#include "efi-api.h"
 #include "efi-loader.h"
 #include "efivars.h"
 #include "fd-util.h"
index 5dd92a6ca0f2a9abdfee02232221760cb1fe3b00..cc79f51655f257a093ac3726c36b1d5340dfb0df 100644 (file)
@@ -17,6 +17,7 @@
 #include "bootspec.h"
 #include "copy.h"
 #include "dirent-util.h"
+#include "efi-api.h"
 #include "efi-loader.h"
 #include "efivars.h"
 #include "env-file.h"
index bdb381eecf40c001bcf59453989299fa0abc3aa8..22c91c3ffc65f6c573afeedce4b6f51a749a9c6e 100644 (file)
@@ -17,7 +17,7 @@
 #include "cryptsetup-tpm2.h"
 #include "cryptsetup-util.h"
 #include "device-util.h"
-#include "efi-loader.h"
+#include "efi-api.h"
 #include "env-util.h"
 #include "escape.h"
 #include "fileio.h"
index a1c7d0a8836e407b25fb419eebfec5fb95acf333..7767096619929026fc1d1bac2edfd6bc308beb62 100644 (file)
@@ -20,6 +20,7 @@
 #include "cgroup-util.h"
 #include "device-util.h"
 #include "dirent-util.h"
+#include "efi-api.h"
 #include "efi-loader.h"
 #include "efivars.h"
 #include "env-file.h"
index 0a4072c9bef58bb645657d40df19d1aae9d60aaa..b9fca7bf0b6245655f26b60e95e5b4da841b683f 100644 (file)
@@ -22,7 +22,7 @@
 #include "cgroup-util.h"
 #include "condition.h"
 #include "cpu-set-util.h"
-#include "efi-loader.h"
+#include "efi-api.h"
 #include "env-file.h"
 #include "env-util.h"
 #include "extract-word.h"
diff --git a/src/shared/efi-api.c b/src/shared/efi-api.c
new file mode 100644 (file)
index 0000000..b2c6af8
--- /dev/null
@@ -0,0 +1,556 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <unistd.h>
+
+#include "alloc-util.h"
+#include "dirent-util.h"
+#include "efi-api.h"
+#include "efivars.h"
+#include "fd-util.h"
+#include "sort-util.h"
+#include "stat-util.h"
+#include "stdio-util.h"
+#include "utf8.h"
+
+#if ENABLE_EFI
+
+#define LOAD_OPTION_ACTIVE            0x00000001
+#define MEDIA_DEVICE_PATH                   0x04
+#define MEDIA_HARDDRIVE_DP                  0x01
+#define MEDIA_FILEPATH_DP                   0x04
+#define SIGNATURE_TYPE_GUID                 0x02
+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
+#define END_DEVICE_PATH_TYPE                0x7f
+#define END_ENTIRE_DEVICE_PATH_SUBTYPE      0xff
+
+#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI UINT64_C(0x0000000000000001)
+
+#define boot_option__contents                   \
+        {                                       \
+                uint32_t attr;                  \
+                uint16_t path_len;              \
+                uint16_t title[];               \
+        }
+
+struct boot_option boot_option__contents;
+struct boot_option__packed boot_option__contents _packed_;
+assert_cc(offsetof(struct boot_option, title) == offsetof(struct boot_option__packed, title));
+/* sizeof(struct boot_option) != sizeof(struct boot_option__packed), so
+ * the *size* of the structure should not be used anywhere below. */
+
+struct drive_path {
+        uint32_t part_nr;
+        uint64_t part_start;
+        uint64_t part_size;
+        char signature[16];
+        uint8_t mbr_type;
+        uint8_t signature_type;
+} _packed_;
+
+#define device_path__contents                           \
+        {                                               \
+                uint8_t type;                           \
+                uint8_t sub_type;                       \
+                uint16_t length;                        \
+                union {                                 \
+                        uint16_t path[0];               \
+                        struct drive_path drive;        \
+                };                                      \
+        }
+
+struct device_path device_path__contents;
+struct device_path__packed device_path__contents _packed_;
+assert_cc(sizeof(struct device_path) == sizeof(struct device_path__packed));
+
+int efi_reboot_to_firmware_supported(void) {
+        _cleanup_free_ void *v = NULL;
+        static int cache = -1;
+        uint64_t b;
+        size_t s;
+        int r;
+
+        if (cache > 0)
+                return 0;
+        if (cache == 0)
+                return -EOPNOTSUPP;
+
+        if (!is_efi_boot())
+                goto not_supported;
+
+        r = efi_get_variable(EFI_GLOBAL_VARIABLE(OsIndicationsSupported), NULL, &v, &s);
+        if (r == -ENOENT)
+                goto not_supported; /* variable doesn't exist? it's not supported then */
+        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))
+                goto not_supported; /* bit unset? it's not supported then */
+
+        cache = 1;
+        return 0;
+
+not_supported:
+        cache = 0;
+        return -EOPNOTSUPP;
+}
+
+static int get_os_indications(uint64_t *ret) {
+        static struct stat cache_stat = {};
+        _cleanup_free_ void *v = NULL;
+        static uint64_t cache;
+        struct stat new_stat;
+        size_t s;
+        int r;
+
+        assert(ret);
+
+        /* Let's verify general support first */
+        r = efi_reboot_to_firmware_supported();
+        if (r < 0)
+                return r;
+
+        /* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */
+        if (stat(EFIVAR_PATH(EFI_GLOBAL_VARIABLE(OsIndications)), &new_stat) < 0) {
+                if (errno != ENOENT)
+                        return -errno;
+
+                /* Doesn't exist? Then we can exit early (also see below) */
+                *ret = 0;
+                return 0;
+
+        } else if (stat_inode_unmodified(&new_stat, &cache_stat)) {
+                /* inode didn't change, we can return the cached value */
+                *ret = cache;
+                return 0;
+        }
+
+        r = efi_get_variable(EFI_GLOBAL_VARIABLE(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. */
+                *ret = 0;
+                return 0;
+        }
+        if (r < 0)
+                return r;
+        if (s != sizeof(uint64_t))
+                return -EINVAL;
+
+        cache_stat = new_stat;
+        *ret = cache = *(uint64_t *)v;
+        return 0;
+}
+
+int efi_get_reboot_to_firmware(void) {
+        int r;
+        uint64_t b;
+
+        r = get_os_indications(&b);
+        if (r < 0)
+                return r;
+
+        return !!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
+}
+
+int efi_set_reboot_to_firmware(bool value) {
+        int r;
+        uint64_t b, b_new;
+
+        r = get_os_indications(&b);
+        if (r < 0)
+                return r;
+
+        b_new = UPDATE_FLAG(b, EFI_OS_INDICATIONS_BOOT_TO_FW_UI, value);
+
+        /* Avoid writing to efi vars store if we can due to firmware bugs. */
+        if (b != b_new)
+                return efi_set_variable(EFI_GLOBAL_VARIABLE(OsIndications), &b_new, sizeof(uint64_t));
+
+        return 0;
+}
+
+static ssize_t utf16_size(const uint16_t *s, size_t buf_len_bytes) {
+        size_t l = 0;
+
+        /* Returns the size of the string in bytes without the terminating two zero bytes */
+
+        if (buf_len_bytes % sizeof(uint16_t) != 0)
+                return -EINVAL;
+
+        while (l < buf_len_bytes / sizeof(uint16_t)) {
+                if (s[l] == 0)
+                        return (l + 1) * sizeof(uint16_t);
+                l++;
+        }
+
+        return -EINVAL; /* The terminator was not found */
+}
+
+struct guid {
+        uint32_t u1;
+        uint16_t u2;
+        uint16_t u3;
+        uint8_t u4[8];
+} _packed_;
+
+static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) {
+        uint32_t u1;
+        uint16_t u2, u3;
+        const struct guid *uuid = guid;
+
+        memcpy(&u1, &uuid->u1, sizeof(uint32_t));
+        id128->bytes[0] = (u1 >> 24) & 0xff;
+        id128->bytes[1] = (u1 >> 16) & 0xff;
+        id128->bytes[2] = (u1 >> 8) & 0xff;
+        id128->bytes[3] = u1 & 0xff;
+        memcpy(&u2, &uuid->u2, sizeof(uint16_t));
+        id128->bytes[4] = (u2 >> 8) & 0xff;
+        id128->bytes[5] = u2 & 0xff;
+        memcpy(&u3, &uuid->u3, sizeof(uint16_t));
+        id128->bytes[6] = (u3 >> 8) & 0xff;
+        id128->bytes[7] = u3 & 0xff;
+        memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4));
+}
+
+int efi_get_boot_option(
+                uint16_t id,
+                char **ret_title,
+                sd_id128_t *ret_part_uuid,
+                char **ret_path,
+                bool *ret_active) {
+
+        char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
+        _cleanup_free_ uint8_t *buf = NULL;
+        size_t l;
+        struct boot_option *header;
+        ssize_t title_size;
+        _cleanup_free_ char *s = NULL, *p = NULL;
+        sd_id128_t p_uuid = SD_ID128_NULL;
+        int r;
+
+        if (!is_efi_boot())
+                return -EOPNOTSUPP;
+
+        xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
+        r = efi_get_variable(variable, NULL, (void **)&buf, &l);
+        if (r < 0)
+                return r;
+        if (l < offsetof(struct boot_option, title))
+                return -ENOENT;
+
+        header = (struct boot_option *)buf;
+        title_size = utf16_size(header->title, l - offsetof(struct boot_option, title));
+        if (title_size < 0)
+                return title_size;
+
+        if (ret_title) {
+                s = utf16_to_utf8(header->title, title_size);
+                if (!s)
+                        return -ENOMEM;
+        }
+
+        if (header->path_len > 0) {
+                uint8_t *dbuf;
+                size_t dnext, doff;
+
+                doff = offsetof(struct boot_option, title) + title_size;
+                dbuf = buf + doff;
+                if (header->path_len > l - doff)
+                        return -EINVAL;
+
+                dnext = 0;
+                while (dnext < header->path_len) {
+                        struct device_path *dpath;
+
+                        dpath = (struct device_path *)(dbuf + dnext);
+                        if (dpath->length < 4)
+                                break;
+
+                        /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
+                        if (dpath->type == END_DEVICE_PATH_TYPE && dpath->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE)
+                                break;
+
+                        dnext += dpath->length;
+
+                        /* Type 0x04 – Media Device Path */
+                        if (dpath->type != MEDIA_DEVICE_PATH)
+                                continue;
+
+                        /* Sub-Type 1 – Hard Drive */
+                        if (dpath->sub_type == MEDIA_HARDDRIVE_DP) {
+                                /* 0x02 – GUID Partition Table */
+                                if (dpath->drive.mbr_type != MBR_TYPE_EFI_PARTITION_TABLE_HEADER)
+                                        continue;
+
+                                /* 0x02 – GUID signature */
+                                if (dpath->drive.signature_type != SIGNATURE_TYPE_GUID)
+                                        continue;
+
+                                if (ret_part_uuid)
+                                        efi_guid_to_id128(dpath->drive.signature, &p_uuid);
+                                continue;
+                        }
+
+                        /* Sub-Type 4 – File Path */
+                        if (dpath->sub_type == MEDIA_FILEPATH_DP && !p && ret_path) {
+                                p = utf16_to_utf8(dpath->path, dpath->length-4);
+                                if (!p)
+                                        return  -ENOMEM;
+
+                                efi_tilt_backslashes(p);
+                                continue;
+                        }
+                }
+        }
+
+        if (ret_title)
+                *ret_title = TAKE_PTR(s);
+        if (ret_part_uuid)
+                *ret_part_uuid = p_uuid;
+        if (ret_path)
+                *ret_path = TAKE_PTR(p);
+        if (ret_active)
+                *ret_active = header->attr & LOAD_OPTION_ACTIVE;
+
+        return 0;
+}
+
+static void to_utf16(uint16_t *dest, const char *src) {
+        int i;
+
+        for (i = 0; src[i] != '\0'; i++)
+                dest[i] = src[i];
+        dest[i] = '\0';
+}
+
+static void id128_to_efi_guid(sd_id128_t id, void *guid) {
+        struct guid uuid = {
+                .u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3],
+                .u2 = id.bytes[4] << 8 | id.bytes[5],
+                .u3 = id.bytes[6] << 8 | id.bytes[7],
+        };
+        memcpy(uuid.u4, id.bytes+8, sizeof(uuid.u4));
+        memcpy(guid, &uuid, sizeof(uuid));
+}
+
+static uint16_t *tilt_slashes(uint16_t *s) {
+        for (uint16_t *p = s; *p; p++)
+                if (*p == '/')
+                        *p = '\\';
+
+        return s;
+}
+
+int efi_add_boot_option(
+                uint16_t id,
+                const char *title,
+                uint32_t part,
+                uint64_t pstart,
+                uint64_t psize,
+                sd_id128_t part_uuid,
+                const char *path) {
+
+        size_t size, title_len, path_len;
+        _cleanup_free_ char *buf = NULL;
+        struct boot_option *option;
+        struct device_path *devicep;
+        char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
+
+        if (!is_efi_boot())
+                return -EOPNOTSUPP;
+
+        title_len = (strlen(title)+1) * 2;
+        path_len = (strlen(path)+1) * 2;
+
+        buf = malloc0(offsetof(struct boot_option, title) + title_len +
+                      sizeof(struct drive_path) +
+                      sizeof(struct device_path) + path_len);
+        if (!buf)
+                return -ENOMEM;
+
+        /* header */
+        option = (struct boot_option *)buf;
+        option->attr = LOAD_OPTION_ACTIVE;
+        option->path_len = offsetof(struct device_path, drive) + sizeof(struct drive_path) +
+                           offsetof(struct device_path, path) + path_len +
+                           offsetof(struct device_path, path);
+        to_utf16(option->title, title);
+        size = offsetof(struct boot_option, title) + title_len;
+
+        /* partition info */
+        devicep = (struct device_path *)(buf + size);
+        devicep->type = MEDIA_DEVICE_PATH;
+        devicep->sub_type = MEDIA_HARDDRIVE_DP;
+        devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path);
+        memcpy(&devicep->drive.part_nr, &part, sizeof(uint32_t));
+        memcpy(&devicep->drive.part_start, &pstart, sizeof(uint64_t));
+        memcpy(&devicep->drive.part_size, &psize, sizeof(uint64_t));
+        id128_to_efi_guid(part_uuid, devicep->drive.signature);
+        devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
+        devicep->drive.signature_type = SIGNATURE_TYPE_GUID;
+        size += devicep->length;
+
+        /* path to loader */
+        devicep = (struct device_path *)(buf + size);
+        devicep->type = MEDIA_DEVICE_PATH;
+        devicep->sub_type = MEDIA_FILEPATH_DP;
+        devicep->length = offsetof(struct device_path, path) + path_len;
+        to_utf16(devicep->path, path);
+        tilt_slashes(devicep->path);
+        size += devicep->length;
+
+        /* end of path */
+        devicep = (struct device_path *)(buf + size);
+        devicep->type = END_DEVICE_PATH_TYPE;
+        devicep->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE;
+        devicep->length = offsetof(struct device_path, path);
+        size += devicep->length;
+
+        xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
+        return efi_set_variable(variable, buf, size);
+}
+
+int efi_remove_boot_option(uint16_t id) {
+        char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
+
+        if (!is_efi_boot())
+                return -EOPNOTSUPP;
+
+        xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
+        return efi_set_variable(variable, NULL, 0);
+}
+
+int efi_get_boot_order(uint16_t **ret_order) {
+        _cleanup_free_ void *buf = NULL;
+        size_t l;
+        int r;
+
+        assert(ret_order);
+
+        if (!is_efi_boot())
+                return -EOPNOTSUPP;
+
+        r = efi_get_variable(EFI_GLOBAL_VARIABLE(BootOrder), NULL, &buf, &l);
+        if (r < 0)
+                return r;
+
+        if (l <= 0)
+                return -ENOENT;
+
+        if (l % sizeof(uint16_t) > 0 ||
+            l / sizeof(uint16_t) > INT_MAX)
+                return -EINVAL;
+
+        *ret_order = TAKE_PTR(buf);
+        return (int) (l / sizeof(uint16_t));
+}
+
+int efi_set_boot_order(const uint16_t *order, size_t n) {
+
+        if (!is_efi_boot())
+                return -EOPNOTSUPP;
+
+        return efi_set_variable(EFI_GLOBAL_VARIABLE(BootOrder), order, n * sizeof(uint16_t));
+}
+
+static int boot_id_hex(const char s[static 4]) {
+        int id = 0;
+
+        assert(s);
+
+        for (int 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 -EINVAL;
+
+        return id;
+}
+
+static int cmp_uint16(const uint16_t *a, const uint16_t *b) {
+        return CMP(*a, *b);
+}
+
+int efi_get_boot_options(uint16_t **ret_options) {
+        _cleanup_closedir_ DIR *dir = NULL;
+        _cleanup_free_ uint16_t *list = NULL;
+        int count = 0;
+
+        assert(ret_options);
+
+        if (!is_efi_boot())
+                return -EOPNOTSUPP;
+
+        dir = opendir(EFIVAR_PATH("."));
+        if (!dir)
+                return -errno;
+
+        FOREACH_DIRENT(de, dir, return -errno) {
+                int id;
+
+                if (strncmp(de->d_name, "Boot", 4) != 0)
+                        continue;
+
+                if (strlen(de->d_name) != 45)
+                        continue;
+
+                if (strcmp(de->d_name + 8, EFI_GLOBAL_VARIABLE_STR("")) != 0)  /* generate variable suffix using macro */
+                        continue;
+
+                id = boot_id_hex(de->d_name + 4);
+                if (id < 0)
+                        continue;
+
+                if (!GREEDY_REALLOC(list, count + 1))
+                        return -ENOMEM;
+
+                list[count++] = id;
+        }
+
+        typesafe_qsort(list, count, cmp_uint16);
+
+        *ret_options = TAKE_PTR(list);
+
+        return count;
+}
+
+bool efi_has_tpm2(void) {
+        static int cache = -1;
+
+        /* Returns whether the system has a TPM2 chip which is known to the EFI firmware. */
+
+        if (cache < 0) {
+
+                /* First, check if we are on an EFI boot at all. */
+                if (!is_efi_boot())
+                        cache = false;
+                else {
+                        /* Then, check if the ACPI table "TPM2" exists, which is the TPM2 event log table, see:
+                         * https://trustedcomputinggroup.org/wp-content/uploads/TCG_ACPIGeneralSpecification_v1.20_r8.pdf
+                         * This table exists whenever the firmware is hooked up to TPM2. */
+                        cache = access("/sys/firmware/acpi/tables/TPM2", F_OK) >= 0;
+                        if (!cache && errno != ENOENT)
+                                log_debug_errno(errno, "Unable to test whether /sys/firmware/acpi/tables/TPM2 exists, assuming it doesn't: %m");
+                }
+        }
+
+        return cache;
+}
+
+#endif
+
+char *efi_tilt_backslashes(char *s) {
+        for (char *p = s; *p; p++)
+                if (*p == '\\')
+                        *p = '/';
+
+        return s;
+}
diff --git a/src/shared/efi-api.h b/src/shared/efi-api.h
new file mode 100644 (file)
index 0000000..5acc9e8
--- /dev/null
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efivars-fundamental.h"
+#include "efivars.h"
+
+/* Various calls for interfacing with EFI variables from the official UEFI specs. */
+
+#if ENABLE_EFI
+
+int efi_reboot_to_firmware_supported(void);
+int efi_get_reboot_to_firmware(void);
+int efi_set_reboot_to_firmware(bool value);
+
+int efi_get_boot_option(uint16_t nr, char **ret_title, sd_id128_t *ret_part_uuid, char **ret_path, bool *ret_active);
+int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path);
+int efi_remove_boot_option(uint16_t id);
+int efi_get_boot_order(uint16_t **ret_order);
+int efi_set_boot_order(const uint16_t *order, size_t n);
+int efi_get_boot_options(uint16_t **ret_options);
+
+bool efi_has_tpm2(void);
+
+#else
+
+static inline int efi_reboot_to_firmware_supported(void) {
+        return -EOPNOTSUPP;
+}
+
+static inline int efi_get_reboot_to_firmware(void) {
+        return -EOPNOTSUPP;
+}
+
+static inline int efi_set_reboot_to_firmware(bool value) {
+        return -EOPNOTSUPP;
+}
+
+static inline int efi_get_boot_option(uint16_t nr, char **ret_title, sd_id128_t *ret_part_uuid, char **ret_path, bool *ret_active) {
+        return -EOPNOTSUPP;
+}
+
+static inline int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path) {
+        return -EOPNOTSUPP;
+}
+
+static inline int efi_remove_boot_option(uint16_t id) {
+        return -EOPNOTSUPP;
+}
+
+static inline int efi_get_boot_order(uint16_t **ret_order) {
+        return -EOPNOTSUPP;
+}
+
+static inline int efi_set_boot_order(const uint16_t *order, size_t n) {
+        return -EOPNOTSUPP;
+}
+
+static inline int efi_get_boot_options(uint16_t **ret_options) {
+        return -EOPNOTSUPP;
+}
+
+static inline bool efi_has_tpm2(void) {
+        return false;
+}
+
+#endif
+
+char *efi_tilt_backslashes(char *s);
index b14a2c32aa8ac471d6527c72a34c9b023c34b907..182a1f0222c024fd7b7f6f37c4488984cf88b5f8 100644 (file)
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
 #include "alloc-util.h"
-#include "dirent-util.h"
 #include "efi-loader.h"
-#include "efivars.h"
-#include "fd-util.h"
-#include "io-util.h"
 #include "parse-util.h"
-#include "sort-util.h"
+#include "path-util.h"
 #include "stat-util.h"
-#include "stdio-util.h"
-#include "string-util.h"
+#include "strv.h"
 #include "utf8.h"
-#include "virt.h"
 
 #if ENABLE_EFI
 
-#define LOAD_OPTION_ACTIVE            0x00000001
-#define MEDIA_DEVICE_PATH                   0x04
-#define MEDIA_HARDDRIVE_DP                  0x01
-#define MEDIA_FILEPATH_DP                   0x04
-#define SIGNATURE_TYPE_GUID                 0x02
-#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
-#define END_DEVICE_PATH_TYPE                0x7f
-#define END_ENTIRE_DEVICE_PATH_SUBTYPE      0xff
-#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI    0x0000000000000001
-
-#define boot_option__contents                   \
-        {                                       \
-                uint32_t attr;                  \
-                uint16_t path_len;              \
-                uint16_t title[];               \
-        }
-
-struct boot_option boot_option__contents;
-struct boot_option__packed boot_option__contents _packed_;
-assert_cc(offsetof(struct boot_option, title) == offsetof(struct boot_option__packed, title));
-/* sizeof(struct boot_option) != sizeof(struct boot_option__packed), so
- * the *size* of the structure should not be used anywhere below. */
-
-struct drive_path {
-        uint32_t part_nr;
-        uint64_t part_start;
-        uint64_t part_size;
-        char signature[16];
-        uint8_t mbr_type;
-        uint8_t signature_type;
-} _packed_;
-
-#define device_path__contents                           \
-        {                                               \
-                uint8_t type;                           \
-                uint8_t sub_type;                       \
-                uint16_t length;                        \
-                union {                                 \
-                        uint16_t path[0];               \
-                        struct drive_path drive;        \
-                };                                      \
-        }
-
-struct device_path device_path__contents;
-struct device_path__packed device_path__contents _packed_;
-assert_cc(sizeof(struct device_path) == sizeof(struct device_path__packed));
-
-int efi_reboot_to_firmware_supported(void) {
-        _cleanup_free_ void *v = NULL;
-        static int cache = -1;
-        uint64_t b;
-        size_t s;
-        int r;
-
-        if (cache > 0)
-                return 0;
-        if (cache == 0)
-                return -EOPNOTSUPP;
-
-        if (!is_efi_boot())
-                goto not_supported;
-
-        r = efi_get_variable(EFI_GLOBAL_VARIABLE(OsIndicationsSupported), NULL, &v, &s);
-        if (r == -ENOENT)
-                goto not_supported; /* variable doesn't exist? it's not supported then */
-        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))
-                goto not_supported; /* bit unset? it's not supported then */
-
-        cache = 1;
-        return 0;
-
-not_supported:
-        cache = 0;
-        return -EOPNOTSUPP;
-}
-
-static int get_os_indications(uint64_t *ret) {
-        static struct stat cache_stat = {};
-        _cleanup_free_ void *v = NULL;
-        static uint64_t cache;
-        struct stat new_stat;
-        size_t s;
-        int r;
-
-        assert(ret);
-
-        /* Let's verify general support first */
-        r = efi_reboot_to_firmware_supported();
-        if (r < 0)
-                return r;
-
-        /* stat() the EFI variable, to see if the mtime changed. If it did we need to cache again. */
-        if (stat(EFIVAR_PATH(EFI_GLOBAL_VARIABLE(OsIndications)), &new_stat) < 0) {
-                if (errno != ENOENT)
-                        return -errno;
-
-                /* Doesn't exist? Then we can exit early (also see below) */
-                *ret = 0;
-                return 0;
-
-        } else if (stat_inode_unmodified(&new_stat, &cache_stat)) {
-                /* inode didn't change, we can return the cached value */
-                *ret = cache;
-                return 0;
-        }
-
-        r = efi_get_variable(EFI_GLOBAL_VARIABLE(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. */
-                *ret = 0;
-                return 0;
-        }
-        if (r < 0)
-                return r;
-        if (s != sizeof(uint64_t))
-                return -EINVAL;
-
-        cache_stat = new_stat;
-        *ret = cache = *(uint64_t *)v;
-        return 0;
-}
-
-int efi_get_reboot_to_firmware(void) {
-        int r;
-        uint64_t b;
-
-        r = get_os_indications(&b);
-        if (r < 0)
-                return r;
-
-        return !!(b & EFI_OS_INDICATIONS_BOOT_TO_FW_UI);
-}
-
-int efi_set_reboot_to_firmware(bool value) {
-        int r;
-        uint64_t b, b_new;
-
-        r = get_os_indications(&b);
-        if (r < 0)
-                return r;
-
-        b_new = UPDATE_FLAG(b, EFI_OS_INDICATIONS_BOOT_TO_FW_UI, value);
-
-        /* Avoid writing to efi vars store if we can due to firmware bugs. */
-        if (b != b_new)
-                return efi_set_variable(EFI_GLOBAL_VARIABLE(OsIndications), &b_new, sizeof(uint64_t));
-
-        return 0;
-}
-
-static ssize_t utf16_size(const uint16_t *s, size_t buf_len_bytes) {
-        size_t l = 0;
-
-        /* Returns the size of the string in bytes without the terminating two zero bytes */
-
-        if (buf_len_bytes % sizeof(uint16_t) != 0)
-                return -EINVAL;
-
-        while (l < buf_len_bytes / sizeof(uint16_t)) {
-                if (s[l] == 0)
-                        return (l + 1) * sizeof(uint16_t);
-                l++;
-        }
-
-        return -EINVAL; /* The terminator was not found */
-}
-
-struct guid {
-        uint32_t u1;
-        uint16_t u2;
-        uint16_t u3;
-        uint8_t u4[8];
-} _packed_;
-
-static void efi_guid_to_id128(const void *guid, sd_id128_t *id128) {
-        uint32_t u1;
-        uint16_t u2, u3;
-        const struct guid *uuid = guid;
-
-        memcpy(&u1, &uuid->u1, sizeof(uint32_t));
-        id128->bytes[0] = (u1 >> 24) & 0xff;
-        id128->bytes[1] = (u1 >> 16) & 0xff;
-        id128->bytes[2] = (u1 >> 8) & 0xff;
-        id128->bytes[3] = u1 & 0xff;
-        memcpy(&u2, &uuid->u2, sizeof(uint16_t));
-        id128->bytes[4] = (u2 >> 8) & 0xff;
-        id128->bytes[5] = u2 & 0xff;
-        memcpy(&u3, &uuid->u3, sizeof(uint16_t));
-        id128->bytes[6] = (u3 >> 8) & 0xff;
-        id128->bytes[7] = u3 & 0xff;
-        memcpy(&id128->bytes[8], uuid->u4, sizeof(uuid->u4));
-}
-
-int efi_get_boot_option(
-                uint16_t id,
-                char **title,
-                sd_id128_t *part_uuid,
-                char **path,
-                bool *active) {
-
-        char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
-        _cleanup_free_ uint8_t *buf = NULL;
-        size_t l;
-        struct boot_option *header;
-        ssize_t title_size;
-        _cleanup_free_ char *s = NULL, *p = NULL;
-        sd_id128_t p_uuid = SD_ID128_NULL;
-        int r;
-
-        if (!is_efi_boot())
-                return -EOPNOTSUPP;
-
-        xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
-        r = efi_get_variable(variable, NULL, (void **)&buf, &l);
-        if (r < 0)
-                return r;
-        if (l < offsetof(struct boot_option, title))
-                return -ENOENT;
-
-        header = (struct boot_option *)buf;
-        title_size = utf16_size(header->title, l - offsetof(struct boot_option, title));
-        if (title_size < 0)
-                return title_size;
-
-        if (title) {
-                s = utf16_to_utf8(header->title, title_size);
-                if (!s)
-                        return -ENOMEM;
-        }
-
-        if (header->path_len > 0) {
-                uint8_t *dbuf;
-                size_t dnext, doff;
-
-                doff = offsetof(struct boot_option, title) + title_size;
-                dbuf = buf + doff;
-                if (header->path_len > l - doff)
-                        return -EINVAL;
-
-                dnext = 0;
-                while (dnext < header->path_len) {
-                        struct device_path *dpath;
-
-                        dpath = (struct device_path *)(dbuf + dnext);
-                        if (dpath->length < 4)
-                                break;
-
-                        /* Type 0x7F – End of Hardware Device Path, Sub-Type 0xFF – End Entire Device Path */
-                        if (dpath->type == END_DEVICE_PATH_TYPE && dpath->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE)
-                                break;
-
-                        dnext += dpath->length;
-
-                        /* Type 0x04 – Media Device Path */
-                        if (dpath->type != MEDIA_DEVICE_PATH)
-                                continue;
-
-                        /* Sub-Type 1 – Hard Drive */
-                        if (dpath->sub_type == MEDIA_HARDDRIVE_DP) {
-                                /* 0x02 – GUID Partition Table */
-                                if (dpath->drive.mbr_type != MBR_TYPE_EFI_PARTITION_TABLE_HEADER)
-                                        continue;
-
-                                /* 0x02 – GUID signature */
-                                if (dpath->drive.signature_type != SIGNATURE_TYPE_GUID)
-                                        continue;
-
-                                if (part_uuid)
-                                        efi_guid_to_id128(dpath->drive.signature, &p_uuid);
-                                continue;
-                        }
-
-                        /* Sub-Type 4 – File Path */
-                        if (dpath->sub_type == MEDIA_FILEPATH_DP && !p && path) {
-                                p = utf16_to_utf8(dpath->path, dpath->length-4);
-                                if (!p)
-                                        return  -ENOMEM;
-
-                                efi_tilt_backslashes(p);
-                                continue;
-                        }
-                }
-        }
-
-        if (title)
-                *title = TAKE_PTR(s);
-        if (part_uuid)
-                *part_uuid = p_uuid;
-        if (path)
-                *path = TAKE_PTR(p);
-        if (active)
-                *active = header->attr & LOAD_OPTION_ACTIVE;
-
-        return 0;
-}
-
-static void to_utf16(uint16_t *dest, const char *src) {
-        int i;
-
-        for (i = 0; src[i] != '\0'; i++)
-                dest[i] = src[i];
-        dest[i] = '\0';
-}
-
-static void id128_to_efi_guid(sd_id128_t id, void *guid) {
-        struct guid uuid = {
-                .u1 = id.bytes[0] << 24 | id.bytes[1] << 16 | id.bytes[2] << 8 | id.bytes[3],
-                .u2 = id.bytes[4] << 8 | id.bytes[5],
-                .u3 = id.bytes[6] << 8 | id.bytes[7],
-        };
-        memcpy(uuid.u4, id.bytes+8, sizeof(uuid.u4));
-        memcpy(guid, &uuid, sizeof(uuid));
-}
-
-static uint16_t *tilt_slashes(uint16_t *s) {
-        for (uint16_t *p = s; *p; p++)
-                if (*p == '/')
-                        *p = '\\';
-
-        return s;
-}
-
-int efi_add_boot_option(
-                uint16_t id,
-                const char *title,
-                uint32_t part,
-                uint64_t pstart,
-                uint64_t psize,
-                sd_id128_t part_uuid,
-                const char *path) {
-
-        size_t size, title_len, path_len;
-        _cleanup_free_ char *buf = NULL;
-        struct boot_option *option;
-        struct device_path *devicep;
-        char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
-
-        if (!is_efi_boot())
-                return -EOPNOTSUPP;
-
-        title_len = (strlen(title)+1) * 2;
-        path_len = (strlen(path)+1) * 2;
-
-        buf = malloc0(offsetof(struct boot_option, title) + title_len +
-                      sizeof(struct drive_path) +
-                      sizeof(struct device_path) + path_len);
-        if (!buf)
-                return -ENOMEM;
-
-        /* header */
-        option = (struct boot_option *)buf;
-        option->attr = LOAD_OPTION_ACTIVE;
-        option->path_len = offsetof(struct device_path, drive) + sizeof(struct drive_path) +
-                           offsetof(struct device_path, path) + path_len +
-                           offsetof(struct device_path, path);
-        to_utf16(option->title, title);
-        size = offsetof(struct boot_option, title) + title_len;
-
-        /* partition info */
-        devicep = (struct device_path *)(buf + size);
-        devicep->type = MEDIA_DEVICE_PATH;
-        devicep->sub_type = MEDIA_HARDDRIVE_DP;
-        devicep->length = offsetof(struct device_path, drive) + sizeof(struct drive_path);
-        memcpy(&devicep->drive.part_nr, &part, sizeof(uint32_t));
-        memcpy(&devicep->drive.part_start, &pstart, sizeof(uint64_t));
-        memcpy(&devicep->drive.part_size, &psize, sizeof(uint64_t));
-        id128_to_efi_guid(part_uuid, devicep->drive.signature);
-        devicep->drive.mbr_type = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
-        devicep->drive.signature_type = SIGNATURE_TYPE_GUID;
-        size += devicep->length;
-
-        /* path to loader */
-        devicep = (struct device_path *)(buf + size);
-        devicep->type = MEDIA_DEVICE_PATH;
-        devicep->sub_type = MEDIA_FILEPATH_DP;
-        devicep->length = offsetof(struct device_path, path) + path_len;
-        to_utf16(devicep->path, path);
-        tilt_slashes(devicep->path);
-        size += devicep->length;
-
-        /* end of path */
-        devicep = (struct device_path *)(buf + size);
-        devicep->type = END_DEVICE_PATH_TYPE;
-        devicep->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE;
-        devicep->length = offsetof(struct device_path, path);
-        size += devicep->length;
-
-        xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
-        return efi_set_variable(variable, buf, size);
-}
-
-int efi_remove_boot_option(uint16_t id) {
-        char variable[STRLEN(EFI_GLOBAL_VARIABLE_STR("Boot")) + 4 + 1];
-
-        if (!is_efi_boot())
-                return -EOPNOTSUPP;
-
-        xsprintf(variable, EFI_GLOBAL_VARIABLE_STR("Boot%04X"), id);
-        return efi_set_variable(variable, NULL, 0);
-}
-
-int efi_get_boot_order(uint16_t **order) {
-        _cleanup_free_ void *buf = NULL;
-        size_t l;
-        int r;
-
-        if (!is_efi_boot())
-                return -EOPNOTSUPP;
-
-        r = efi_get_variable(EFI_GLOBAL_VARIABLE(BootOrder), NULL, &buf, &l);
-        if (r < 0)
-                return r;
-
-        if (l <= 0)
-                return -ENOENT;
-
-        if (l % sizeof(uint16_t) > 0 ||
-            l / sizeof(uint16_t) > INT_MAX)
-                return -EINVAL;
-
-        *order = TAKE_PTR(buf);
-        return (int) (l / sizeof(uint16_t));
-}
-
-int efi_set_boot_order(uint16_t *order, size_t n) {
-
-        if (!is_efi_boot())
-                return -EOPNOTSUPP;
-
-        return efi_set_variable(EFI_GLOBAL_VARIABLE(BootOrder), order, n * sizeof(uint16_t));
-}
-
-static int boot_id_hex(const char s[static 4]) {
-        int id = 0;
-
-        assert(s);
-
-        for (int 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 -EINVAL;
-
-        return id;
-}
-
-static int cmp_uint16(const uint16_t *a, const uint16_t *b) {
-        return CMP(*a, *b);
-}
-
-int efi_get_boot_options(uint16_t **options) {
-        _cleanup_closedir_ DIR *dir = NULL;
-        _cleanup_free_ uint16_t *list = NULL;
-        int count = 0;
-
-        assert(options);
-
-        if (!is_efi_boot())
-                return -EOPNOTSUPP;
-
-        dir = opendir(EFIVAR_PATH("."));
-        if (!dir)
-                return -errno;
-
-        FOREACH_DIRENT(de, dir, return -errno) {
-                int id;
-
-                if (strncmp(de->d_name, "Boot", 4) != 0)
-                        continue;
-
-                if (strlen(de->d_name) != 45)
-                        continue;
-
-                if (strcmp(de->d_name + 8, EFI_GLOBAL_VARIABLE_STR("")) != 0)  /* generate variable suffix using macro */
-                        continue;
-
-                id = boot_id_hex(de->d_name + 4);
-                if (id < 0)
-                        continue;
-
-                if (!GREEDY_REALLOC(list, count + 1))
-                        return -ENOMEM;
-
-                list[count++] = id;
-        }
-
-        typesafe_qsort(list, count, cmp_uint16);
-
-        *options = TAKE_PTR(list);
-
-        return count;
-}
-
-static int read_usec(const char *variable, usec_t *u) {
+static int read_usec(const char *variable, usec_t *ret) {
         _cleanup_free_ char *j = NULL;
-        int r;
         uint64_t x = 0;
+        int r;
 
         assert(variable);
-        assert(u);
+        assert(ret);
 
         r = efi_get_variable_string(variable, &j);
         if (r < 0)
@@ -541,16 +26,16 @@ static int read_usec(const char *variable, usec_t *u) {
         if (r < 0)
                 return r;
 
-        *u = x;
+        *ret = x;
         return 0;
 }
 
-int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
+int efi_loader_get_boot_usec(usec_t *ret_firmware, usec_t *ret_loader) {
         uint64_t x, y;
         int r;
 
-        assert(firmware);
-        assert(loader);
+        assert(ret_firmware);
+        assert(ret_loader);
 
         if (!is_efi_boot())
                 return -EOPNOTSUPP;
@@ -568,16 +53,17 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
                                        "Bad LoaderTimeInitUSec=%"PRIu64", LoaderTimeExecUSec=%" PRIu64"; refusing.",
                                        x, y);
 
-        *firmware = x;
-        *loader = y;
-
+        *ret_firmware = x;
+        *ret_loader = y;
         return 0;
 }
 
-int efi_loader_get_device_part_uuid(sd_id128_t *u) {
+int efi_loader_get_device_part_uuid(sd_id128_t *ret) {
         _cleanup_free_ char *p = NULL;
         int r, parsed[16];
 
+        assert(ret);
+
         if (!is_efi_boot())
                 return -EOPNOTSUPP;
 
@@ -592,9 +78,9 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) {
                    &parsed[12], &parsed[13], &parsed[14], &parsed[15]) != 16)
                 return -EIO;
 
-        if (u)
+        if (ret)
                 for (unsigned i = 0; i < ELEMENTSOF(parsed); i++)
-                        u->bytes[i] = parsed[i];
+                        ret->bytes[i] = parsed[i];
 
         return 0;
 }
@@ -657,6 +143,8 @@ int efi_loader_get_features(uint64_t *ret) {
         size_t s;
         int r;
 
+        assert(ret);
+
         if (!is_efi_boot()) {
                 *ret = 0;
                 return 0;
@@ -763,29 +251,6 @@ int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat
         return 0;
 }
 
-bool efi_has_tpm2(void) {
-        static int cache = -1;
-
-        /* Returns whether the system has a TPM2 chip which is known to the EFI firmware. */
-
-        if (cache < 0) {
-
-                /* First, check if we are on an EFI boot at all. */
-                if (!is_efi_boot())
-                        cache = false;
-                else {
-                        /* Then, check if the ACPI table "TPM2" exists, which is the TPM2 event log table, see:
-                         * https://trustedcomputinggroup.org/wp-content/uploads/TCG_ACPIGeneralSpecification_v1.20_r8.pdf
-                         * This table exists whenever the firmware is hooked up to TPM2. */
-                        cache = access("/sys/firmware/acpi/tables/TPM2", F_OK) >= 0;
-                        if (!cache && errno != ENOENT)
-                                log_debug_errno(errno, "Unable to test whether /sys/firmware/acpi/tables/TPM2 exists, assuming it doesn't: %m");
-                }
-        }
-
-        return cache;
-}
-
 #endif
 
 bool efi_loader_entry_name_valid(const char *s) {
@@ -794,11 +259,3 @@ bool efi_loader_entry_name_valid(const char *s) {
 
         return in_charset(s, ALPHANUMERICAL "+-_.");
 }
-
-char *efi_tilt_backslashes(char *s) {
-        for (char *p = s; *p; p++)
-                if (*p == '\\')
-                        *p = '/';
-
-        return s;
-}
index 7a100e5364282efa421e963ecf639fc96c0b72ca..507160e50de60f7261f9e3f1f00c81f7ee7d1e12 100644 (file)
@@ -6,21 +6,12 @@
 #include "efivars-fundamental.h"
 #include "efivars.h"
 
-#if ENABLE_EFI
-
-int efi_reboot_to_firmware_supported(void);
-int efi_get_reboot_to_firmware(void);
-int efi_set_reboot_to_firmware(bool value);
+/* Various calls that interface with EFI variables implementing https://systemd.io/BOOT_LOADER_INTERFACE */
 
-int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active);
-int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path);
-int efi_remove_boot_option(uint16_t id);
-int efi_get_boot_order(uint16_t **order);
-int efi_set_boot_order(uint16_t *order, size_t n);
-int efi_get_boot_options(uint16_t **options);
+#if ENABLE_EFI
 
-int efi_loader_get_device_part_uuid(sd_id128_t *u);
-int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader);
+int efi_loader_get_device_part_uuid(sd_id128_t *ret);
+int efi_loader_get_boot_usec(usec_t *ret_firmware, usec_t *ret_loader);
 
 int efi_loader_get_entries(char ***ret);
 
@@ -29,46 +20,8 @@ int efi_loader_get_features(uint64_t *ret);
 int efi_loader_get_config_timeout_one_shot(usec_t *ret);
 int efi_loader_update_entry_one_shot_cache(char **cache, struct stat *cache_stat);
 
-bool efi_has_tpm2(void);
-
 #else
 
-static inline int efi_reboot_to_firmware_supported(void) {
-        return -EOPNOTSUPP;
-}
-
-static inline int efi_get_reboot_to_firmware(void) {
-        return -EOPNOTSUPP;
-}
-
-static inline int efi_set_reboot_to_firmware(bool value) {
-        return -EOPNOTSUPP;
-}
-
-static inline int efi_get_boot_option(uint16_t nr, char **title, sd_id128_t *part_uuid, char **path, bool *active) {
-        return -EOPNOTSUPP;
-}
-
-static inline int efi_add_boot_option(uint16_t id, const char *title, uint32_t part, uint64_t pstart, uint64_t psize, sd_id128_t part_uuid, const char *path) {
-        return -EOPNOTSUPP;
-}
-
-static inline int efi_remove_boot_option(uint16_t id) {
-        return -EOPNOTSUPP;
-}
-
-static inline int efi_get_boot_order(uint16_t **order) {
-        return -EOPNOTSUPP;
-}
-
-static inline int efi_set_boot_order(uint16_t *order, size_t n) {
-        return -EOPNOTSUPP;
-}
-
-static inline int efi_get_boot_options(uint16_t **options) {
-        return -EOPNOTSUPP;
-}
-
 static inline int efi_loader_get_device_part_uuid(sd_id128_t *u) {
         return -EOPNOTSUPP;
 }
@@ -93,12 +46,6 @@ static inline int efi_loader_update_entry_one_shot_cache(char **cache, struct st
         return -EOPNOTSUPP;
 }
 
-static inline bool efi_has_tpm2(void) {
-        return false;
-}
-
 #endif
 
 bool efi_loader_entry_name_valid(const char *s);
-
-char *efi_tilt_backslashes(char *s);
index 668462f1731965b23c10673d88d93981a3bb51fe..4333c9a0a90b5f6f0c662e9e5079cff5063a5b52 100644 (file)
@@ -105,6 +105,8 @@ shared_sources = files(
         'dns-domain.h',
         'dropin.c',
         'dropin.h',
+        'efi-api.c',
+        'efi-api.h',
         'efi-loader.c',
         'efi-loader.h',
         'elf-util.c',