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;