diff --git a/man/systemd-gpt-auto-generator.xml b/man/systemd-gpt-auto-generator.xml index e267fc9528..6494a79d22 100644 --- a/man/systemd-gpt-auto-generator.xml +++ b/man/systemd-gpt-auto-generator.xml @@ -75,6 +75,13 @@ discovery based on the boot loader reported ESP which is also enabled if no root= parameter is specified at all. (The latter relies on systemd-udevd.service's /dev/gpt-auto-root block device symlink generation). + + It will also generate a unit file mounting the EFI System Partition (ESP) to + /sysefi/, if applicable. Unlike the file systems mentioned above this mount is not + activated by default however, but can be pulled in by services requiring ESP access from within the + initrd. Note that this mount point is initrd-specific and does not make use of autofs. The ESP is + typically mounted at a different place and via autofs once the system transitions out of the + initrd. @@ -179,7 +186,7 @@ SD_GPT_ESP c12a7328-f81f-11d2-ba4b-00a0c93ec93b EFI System Partition (ESP) - /efi/ or /boot/ + /efi/ or /boot/ once the system transitioned out of the initrd, /sysefi/ before The first partition with this type UUID located on the same disk as the root partition is mounted to /boot/ or /efi/, see below. @@ -259,7 +266,9 @@ The ESP is mounted to /boot/ if that directory exists and is not used for XBOOTLDR, and otherwise to /efi/. Same as for /boot/, an - automount unit is used. The mount point will be created if necessary. + automount unit is used. The mount point will be created if necessary. These apply once the system + transitioned out of the initrd phase. Before that, if components in the initrd require ESP access, it + will be mounted to /sysefi/. No configuration is created for mount points that are configured in fstab5 or when diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index 4fd92a6057..a87b514080 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -307,7 +307,8 @@ static int add_mount( MountPointFlags flags, const char *options, const char *description, - const char *post) { + const char *post, + const char *conflicts) { _cleanup_free_ char *unit = NULL, *crypto_what = NULL, *opts_filtered = NULL; _cleanup_fclose_ FILE *f = NULL; @@ -377,6 +378,12 @@ static int add_mount( if (r < 0) return r; + if (conflicts) + fprintf(f, + "Conflicts=%1$s\n" + "Before=%1$s\n", + conflicts); + fprintf(f, "\n" "[Mount]\n" @@ -493,7 +500,8 @@ static int add_partition_mount( (STR_IN_SET(id, "root", "var") ? MOUNT_MEASURE : 0), /* by default measure rootfs and /var, since they contain the "identity" of the system */ options, description, - SPECIAL_LOCAL_FS_TARGET); + SPECIAL_LOCAL_FS_TARGET, + /* conflicts= */ NULL); } static int add_partition_swap(DissectedPartition *p) { @@ -582,7 +590,8 @@ static int add_automount( flags, options, description, - /* post= */ NULL); + /* post= */ NULL, + /* conflicts= */ NULL); if (r < 0) return r; @@ -919,7 +928,8 @@ static int add_root_mount(void) { MOUNT_MEASURE, options, "Root Partition", - in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET); + in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET, + /* conflicts= */ NULL); #else return 0; #endif @@ -995,7 +1005,8 @@ static int add_usr_mount(void) { /* flags= */ 0, options, "/usr/ Partition", - in_initrd() ? SPECIAL_INITRD_USR_FS_TARGET : SPECIAL_LOCAL_FS_TARGET); + in_initrd() ? SPECIAL_INITRD_USR_FS_TARGET : SPECIAL_LOCAL_FS_TARGET, + /* conflicts= */ NULL); if (r < 0) return r; @@ -1009,7 +1020,8 @@ static int add_usr_mount(void) { MOUNT_VALIDATEFS, "bind", "/usr/ Partition (Final)", - SPECIAL_INITRD_FS_TARGET); + SPECIAL_INITRD_FS_TARGET, + /* conflicts= */ NULL); if (r < 0) return r; } @@ -1017,6 +1029,49 @@ static int add_usr_mount(void) { return 0; } +static int add_early_esp_mount(void) { + int r; + + /* Early ESP discovery is a bit different than the other mounts here: it's purely about the initrd, + * and goes away during the transition to the host (where it might likely be mounted again, but then + * via autofs, hence lazily). Moreover, the location is fixed → /sysefi/, i.e. we do not bother with + * XBOOTLDR vs. ESP for this. Also, the mount is not pulled in by default, but is expected to be + * pulled in by the component that uses it. + * + * The initial usecase for this is software TPM that needs a place to store its state before the root + * file system can be mounted. + * + * Or in other words: this is much simpler, more focussed on a short-lived boot-time operation than + * the regular logic during later boot. */ + + if (!in_initrd()) + return 0; + + if (!is_efi_boot()) + return 0; + + _cleanup_free_ char *options = NULL; + r = partition_pick_mount_options( + PARTITION_ESP, + "vfat", + /* rw= */ true, + /* discard= */ false, + &options, + /* ret_ms_flags= */ NULL); + if (r < 0) + return log_error_errno(r, "Failed to pick ESP mount options: %m"); + + return add_mount("esp", + "/dev/disk/by-designator/esp", + "/sysefi/", + "vfat", + MOUNT_RW, + options, + "EFI System Partition (Early)", + /* post= */ NULL, + /* conflicts= */ "initrd-switch-root.target"); +} + static int process_loader_partitions(DissectedPartition *esp, DissectedPartition *xbootldr) { sd_id128_t loader_uuid; int r; @@ -1190,7 +1245,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat return 0; /* Disable root disk logic if there's a root= value specified (unless it happens to be - * "gpt-auto" or "gpt-auto-force") */ + * "gpt-auto", "gpt-auto-force", "dissect", "dissect-force") */ arg_auto_root = parse_gpt_auto_root("root=", value); assert(arg_auto_root >= 0); @@ -1244,9 +1299,6 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (proc_cmdline_value_missing(key, value)) return 0; - /* Disable root disk logic if there's a root= value specified (unless it happens to be - * "gpt-auto" or "gpt-auto-force") */ - arg_auto_usr = parse_gpt_auto_root("mount.usr=", value); assert(arg_auto_usr >= 0); @@ -1325,6 +1377,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) r = 0; RET_GATHER(r, add_root_mount()); RET_GATHER(r, add_usr_mount()); + RET_GATHER(r, add_early_esp_mount()); RET_GATHER(r, add_mounts()); return r;