chiark / gitweb /
efi: add efi boot generator that automatically mounts the ESP to /boot
authorLennart Poettering <lennart@poettering.net>
Mon, 21 Jan 2013 00:02:53 +0000 (01:02 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 21 Jan 2013 00:04:16 +0000 (01:04 +0100)
.gitignore
Makefile.am
src/efi-boot-generator/Makefile [new symlink]
src/efi-boot-generator/efi-boot-generator.c [new file with mode: 0644]
src/shared/efivars.c
src/shared/efivars.h

index 23c1b59799b1d044e1e0019ce6b009e5e7c0698b..03ed5543b1d554c3e062e94640bca76b9c3e3bfb 100644 (file)
@@ -36,6 +36,7 @@
 /systemd-cryptsetup-generator
 /systemd-delta
 /systemd-detect-virt
+/systemd-efi-boot-generator
 /systemd-fsck
 /systemd-fstab-generator
 /systemd-getty-generator
index 2631748f617dce077e2f5d5b27b5a916aceb08c7..7d5bd5a8035ed5b68aa34f6fc6a9796a26b9d5f7 100644 (file)
@@ -219,7 +219,8 @@ endif
 systemgenerator_PROGRAMS = \
        systemd-getty-generator \
        systemd-fstab-generator \
-       systemd-system-update-generator
+       systemd-system-update-generator \
+       systemd-efi-boot-generator
 
 dist_bin_SCRIPTS = \
        src/analyze/systemd-analyze
@@ -1545,6 +1546,14 @@ systemd_system_update_generator_LDADD = \
        libsystemd-label.la \
        libsystemd-shared.la
 
+# ------------------------------------------------------------------------------
+systemd_efi_boot_generator_SOURCES = \
+       src/efi-boot-generator/efi-boot-generator.c
+
+systemd_efi_boot_generator_LDADD = \
+       libsystemd-label.la \
+       libsystemd-shared.la
+
 # ------------------------------------------------------------------------------
 systemd_rc_local_generator_SOURCES = \
        src/rc-local-generator/rc-local-generator.c
diff --git a/src/efi-boot-generator/Makefile b/src/efi-boot-generator/Makefile
new file mode 120000 (symlink)
index 0000000..d0b0e8e
--- /dev/null
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file
diff --git a/src/efi-boot-generator/efi-boot-generator.c b/src/efi-boot-generator/efi-boot-generator.c
new file mode 100644 (file)
index 0000000..ee6ec31
--- /dev/null
@@ -0,0 +1,117 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "efivars.h"
+#include "path-util.h"
+#include "util.h"
+
+static const char *arg_dest = NULL;
+
+int main(int argc, char *argv[]) {
+        int r = EXIT_SUCCESS;
+        sd_id128_t id;
+        _cleanup_free_ char *name = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+
+        if (argc > 1 && argc != 4) {
+                log_error("This program takes three or no arguments.");
+                return EXIT_FAILURE;
+        }
+
+        if (argc > 1)
+                arg_dest = argv[3];
+
+        log_set_target(LOG_TARGET_SAFE);
+        log_parse_environment();
+        log_open();
+
+        umask(0022);
+
+        if (!is_efiboot())
+                return EXIT_SUCCESS;
+
+        if (dir_is_empty("/boot") <= 0)
+                return EXIT_SUCCESS;
+
+        r = efi_get_loader_device_part_uuid(&id);
+        if (r == -ENOENT)
+                return EXIT_SUCCESS;
+        if (r < 0) {
+                log_error("Failed to read ESP partition UUID: %s", strerror(-r));
+                return EXIT_FAILURE;
+        }
+
+        name = strjoin(arg_dest, "/boot.mount", NULL);
+        if (!name) {
+                log_oom();
+                return EXIT_FAILURE;
+        }
+
+        f = fopen(name, "wxe");
+        if (!f) {
+                log_error("Failed to create mount unit file %s: %m", name);
+                return EXIT_FAILURE;
+        }
+
+        fprintf(f,
+                "# Automatially generated by systemd-efi-boot-generator\n\n"
+                "[Mount]\n"
+                "Where=/boot\n"
+                "What=/dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n"
+                "Options=umask=0077\n",
+                SD_ID128_FORMAT_VAL(id));
+
+        free(name);
+        name = strjoin(arg_dest, "/boot.automount", NULL);
+        if (!name) {
+                log_oom();
+                return EXIT_FAILURE;
+        }
+
+        fclose(f);
+        f = fopen(name, "wxe");
+        if (!f) {
+                log_error("Failed to create automount unit file %s: %m", name);
+                return EXIT_FAILURE;
+        }
+
+        fprintf(f,
+                "# Automatially generated by systemd-efi-boot-generator\n\n"
+                "[Automount]\n"
+                "Where=/boot\n");
+
+        free(name);
+        name = strjoin(arg_dest, "/local-fs.target.wants/boot.automount", NULL);
+        if (!name) {
+                log_oom();
+                return EXIT_FAILURE;
+        }
+
+        if (symlink("../boot.automount", name) < 0) {
+                log_error("Failed to create symlink: %m");
+                return EXIT_FAILURE;
+        }
+
+        return 0;
+}
index 784ff364d9802c621774f256527f205e1c13ce12..183d33c7726cdb95302c5c181656caf54565a904 100644 (file)
@@ -235,3 +235,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;
+}
index 120f3c7a6a59b068ac02b39d593b41b2a440f47e..d5cfb4fa0dec57cb7ee170299d17959eea01dd80 100644 (file)
 
 #include <sys/types.h>
 #include <inttypes.h>
+#include <stdbool.h>
 
 #include "sd-id128.h"
+#include "time-util.h"
 
 bool is_efiboot(void);
 
 int efi_get_variable(sd_id128_t vendor, const char *name, uint32_t *attribute, void **value, size_t *size);
 
 int efi_get_boot_timestamps(const dual_timestamp *n, dual_timestamp *firmware, dual_timestamp *loader);
+
+int efi_get_loader_device_part_uuid(sd_id128_t *u);