mirror of
https://github.com/systemd/systemd.git
synced 2025-03-23 10:50:16 +03:00
Merge pull request #3757 from poettering/efi-search
This commit is contained in:
commit
e28973ee18
@ -47,16 +47,16 @@
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg>status</command>
|
||||
<command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> status</command>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg>update</command>
|
||||
<command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> update</command>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg>install</command>
|
||||
<command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> install</command>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg>remove</command>
|
||||
<command>bootctl <arg choice="opt" rep="repeat">OPTIONS</arg> remove</command>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@ -71,19 +71,14 @@
|
||||
currently installed versions of the boot loader binaries and
|
||||
all current EFI boot variables.</para>
|
||||
|
||||
<para><command>bootctl update</command> updates all installed
|
||||
versions of systemd-boot, if the current version is newer than the
|
||||
version installed in the EFI system partition. This also includes
|
||||
the EFI default/fallback loader at /EFI/BOOT/BOOT*.EFI. A
|
||||
systemd-boot entry in the EFI boot variables is created if there
|
||||
is no current entry. The created entry will be added to the end of
|
||||
the boot order list.</para>
|
||||
<para><command>bootctl update</command> updates all installed versions of systemd-boot, if the current version is
|
||||
newer than the version installed in the EFI system partition. This also includes the EFI default/fallback loader at
|
||||
<filename>/EFI/BOOT/BOOT*.EFI</filename>. A systemd-boot entry in the EFI boot variables is created if there is no
|
||||
current entry. The created entry will be added to the end of the boot order list.</para>
|
||||
|
||||
<para><command>bootctl install</command> installs systemd-boot into
|
||||
the EFI system partition. A copy of systemd-boot will be stored as
|
||||
the EFI default/fallback loader at /EFI/BOOT/BOOT*.EFI. A systemd-boot
|
||||
entry in the EFI boot variables is created and added to the top
|
||||
of the boot order list.</para>
|
||||
<para><command>bootctl install</command> installs systemd-boot into the EFI system partition. A copy of
|
||||
systemd-boot will be stored as the EFI default/fallback loader at <filename>/EFI/BOOT/BOOT*.EFI</filename>. A
|
||||
systemd-boot entry in the EFI boot variables is created and added to the top of the boot order list.</para>
|
||||
|
||||
<para><command>bootctl remove</command> removes all installed
|
||||
versions of systemd-boot from the EFI system partition, and removes
|
||||
@ -101,8 +96,10 @@
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
<varlistentry>
|
||||
<term><option>--path</option></term>
|
||||
<listitem><para>Path to the EFI system partition. The default is /boot.</para></listitem>
|
||||
<term><option>--path=</option></term>
|
||||
<listitem><para>Path to the EFI System Partition (ESP). If not specified, <filename>/efi</filename>,
|
||||
<filename>/boot</filename>, and <filename>/boot/efi</filename> are checked in turn. It is recommended to mount
|
||||
the ESP to <filename>/boot</filename>, if possible.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -137,6 +137,11 @@
|
||||
<entry>Swap</entry>
|
||||
<entry>All swap partitions located on the disk the root partition is located on are enabled.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>c12a7328-f81f-11d2-ba4b-00a0c93ec93b</entry>
|
||||
<entry>EFI System Partition (ESP)</entry>
|
||||
<entry>The first ESP located on the disk the root partition is located on is mounted to <filename>/boot</filename> or <filename>/efi</filename>, see below.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
@ -150,16 +155,14 @@
|
||||
<filename>/etc/crypttab</filename> with a different device mapper
|
||||
device name.</para>
|
||||
|
||||
<para>Mount and automount units for the EFI System Partition (ESP),
|
||||
mounting it to <filename>/boot</filename>, are generated on EFI
|
||||
systems where the boot loader communicates the used ESP to the operating
|
||||
system. Since this generator creates an automount unit, the mount will
|
||||
only be activated on-demand, when accessed. On systems where
|
||||
<filename>/boot</filename> is an explicitly configured mount
|
||||
(for example, listed in
|
||||
<citerefentry project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
|
||||
or where the <filename>/boot</filename> mount point is non-empty, no
|
||||
mount units are generated.</para>
|
||||
<para>Mount and automount units for the EFI System Partition (ESP) are generated on EFI systems. The ESP is mounted
|
||||
to <filename>/boot</filename>, unless a mount point directory <filename>/efi</filename> exists, in which case it is
|
||||
mounted there. Since this generator creates an automount unit, the mount will only be activated on-demand, when
|
||||
accessed. On systems where <filename>/boot</filename> (or <filename>/efi</filename> if it exists) is an explicitly
|
||||
configured mount (for example, listed in <citerefentry
|
||||
project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>) or where the
|
||||
<filename>/boot</filename> (or <filename>/efi</filename>) mount point is non-empty, no mount units are
|
||||
generated.</para>
|
||||
|
||||
<para>When using this generator in conjunction with btrfs file
|
||||
systems, make sure to set the correct default subvolumes on them,
|
||||
|
@ -323,6 +323,14 @@ char ascii_tolower(char x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
char ascii_toupper(char x) {
|
||||
|
||||
if (x >= 'a' && x <= 'z')
|
||||
return x - 'a' + 'A';
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
char *ascii_strlower(char *t) {
|
||||
char *p;
|
||||
|
||||
@ -334,6 +342,17 @@ char *ascii_strlower(char *t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
char *ascii_strupper(char *t) {
|
||||
char *p;
|
||||
|
||||
assert(t);
|
||||
|
||||
for (p = t; *p; p++)
|
||||
*p = ascii_toupper(*p);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
char *ascii_strlower_n(char *t, size_t n) {
|
||||
size_t i;
|
||||
|
||||
|
@ -137,6 +137,9 @@ char ascii_tolower(char x);
|
||||
char *ascii_strlower(char *s);
|
||||
char *ascii_strlower_n(char *s, size_t n);
|
||||
|
||||
char ascii_toupper(char x);
|
||||
char *ascii_strupper(char *s);
|
||||
|
||||
int ascii_strcasecmp_n(const char *a, const char *b, size_t n);
|
||||
int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m);
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <ftw.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <linux/magic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -42,22 +43,53 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "locale-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "rm-rf.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "umask-util.h"
|
||||
#include "util.h"
|
||||
#include "verbs.h"
|
||||
#include "virt.h"
|
||||
#include "stat-util.h"
|
||||
|
||||
static char *arg_path = NULL;
|
||||
static bool arg_touch_variables = true;
|
||||
|
||||
static int verify_esp(
|
||||
bool searching,
|
||||
const char *p,
|
||||
uint32_t *ret_part,
|
||||
uint64_t *ret_pstart,
|
||||
uint64_t *ret_psize,
|
||||
sd_id128_t *ret_uuid) {
|
||||
|
||||
static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
|
||||
struct statfs sfs;
|
||||
struct stat st, st2;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
_cleanup_blkid_free_probe_ blkid_probe b = NULL;
|
||||
int r;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
uint64_t pstart = 0, psize = 0;
|
||||
struct stat st, st2;
|
||||
const char *v, *t2;
|
||||
struct statfs sfs;
|
||||
sd_id128_t uuid = SD_ID128_NULL;
|
||||
uint32_t part = 0;
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
|
||||
if (statfs(p, &sfs) < 0) {
|
||||
|
||||
/* If we are searching for the mount point, don't generate a log message if we can't find the path */
|
||||
if (errno == ENOENT && searching)
|
||||
return -ENOENT;
|
||||
|
||||
if (statfs(p, &sfs) < 0)
|
||||
return log_error_errno(errno, "Failed to check file system type of \"%s\": %m", p);
|
||||
}
|
||||
|
||||
if (!F_TYPE_EQUAL(sfs.f_type, MSDOS_SUPER_MAGIC)) {
|
||||
|
||||
if (searching)
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
if (sfs.f_type != 0x4d44) {
|
||||
log_error("File system \"%s\" is not a FAT EFI System Partition (ESP) file system.", p);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -80,6 +112,11 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* In a container we don't have access to block devices, skip this part of the verification, we trust the
|
||||
* container manager set everything up correctly on its own. */
|
||||
if (detect_container() > 0)
|
||||
goto finish;
|
||||
|
||||
r = asprintf(&t, "/dev/block/%u:%u", major(st.st_dev), minor(st.st_dev));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
@ -117,7 +154,6 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t
|
||||
r = errno ? -errno : -EIO;
|
||||
return log_error_errno(r, "Failed to probe file system type \"%s\": %m", p);
|
||||
}
|
||||
|
||||
if (!streq(v, "vfat")) {
|
||||
log_error("File system \"%s\" is not FAT.", p);
|
||||
return -ENODEV;
|
||||
@ -129,7 +165,6 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t
|
||||
r = errno ? -errno : -EIO;
|
||||
return log_error_errno(r, "Failed to probe partition scheme \"%s\": %m", p);
|
||||
}
|
||||
|
||||
if (!streq(v, "gpt")) {
|
||||
log_error("File system \"%s\" is not on a GPT partition table.", p);
|
||||
return -ENODEV;
|
||||
@ -141,7 +176,6 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t
|
||||
r = errno ? -errno : -EIO;
|
||||
return log_error_errno(r, "Failed to probe partition type UUID \"%s\": %m", p);
|
||||
}
|
||||
|
||||
if (!streq(v, "c12a7328-f81f-11d2-ba4b-00a0c93ec93b")) {
|
||||
log_error("File system \"%s\" has wrong type for an EFI System Partition (ESP).", p);
|
||||
return -ENODEV;
|
||||
@ -153,8 +187,7 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t
|
||||
r = errno ? -errno : -EIO;
|
||||
return log_error_errno(r, "Failed to probe partition entry UUID \"%s\": %m", p);
|
||||
}
|
||||
|
||||
r = sd_id128_from_string(v, uuid);
|
||||
r = sd_id128_from_string(v, &uuid);
|
||||
if (r < 0) {
|
||||
log_error("Partition \"%s\" has invalid UUID \"%s\".", p, v);
|
||||
return -EIO;
|
||||
@ -166,7 +199,9 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t
|
||||
r = errno ? -errno : -EIO;
|
||||
return log_error_errno(r, "Failed to probe partition number \"%s\": m", p);
|
||||
}
|
||||
*part = strtoul(v, NULL, 10);
|
||||
r = safe_atou32(v, &part);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse PART_ENTRY_NUMBER field.");
|
||||
|
||||
errno = 0;
|
||||
r = blkid_probe_lookup_value(b, "PART_ENTRY_OFFSET", &v, NULL);
|
||||
@ -174,7 +209,9 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t
|
||||
r = errno ? -errno : -EIO;
|
||||
return log_error_errno(r, "Failed to probe partition offset \"%s\": %m", p);
|
||||
}
|
||||
*pstart = strtoul(v, NULL, 10);
|
||||
r = safe_atou64(v, &pstart);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse PART_ENTRY_OFFSET field.");
|
||||
|
||||
errno = 0;
|
||||
r = blkid_probe_lookup_value(b, "PART_ENTRY_SIZE", &v, NULL);
|
||||
@ -182,11 +219,50 @@ static int verify_esp(const char *p, uint32_t *part, uint64_t *pstart, uint64_t
|
||||
r = errno ? -errno : -EIO;
|
||||
return log_error_errno(r, "Failed to probe partition size \"%s\": %m", p);
|
||||
}
|
||||
*psize = strtoul(v, NULL, 10);
|
||||
r = safe_atou64(v, &psize);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse PART_ENTRY_SIZE field.");
|
||||
|
||||
finish:
|
||||
if (ret_part)
|
||||
*ret_part = part;
|
||||
if (ret_pstart)
|
||||
*ret_pstart = pstart;
|
||||
if (ret_psize)
|
||||
*ret_psize = psize;
|
||||
if (ret_uuid)
|
||||
*ret_uuid = uuid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_esp(uint32_t *part, uint64_t *pstart, uint64_t *psize, sd_id128_t *uuid) {
|
||||
const char *path;
|
||||
int r;
|
||||
|
||||
if (arg_path)
|
||||
return verify_esp(false, arg_path, part, pstart, psize, uuid);
|
||||
|
||||
FOREACH_STRING(path, "/efi", "/boot", "/boot/efi") {
|
||||
|
||||
r = verify_esp(true, path, part, pstart, psize, uuid);
|
||||
if (IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
|
||||
continue;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
arg_path = strdup(path);
|
||||
if (!arg_path)
|
||||
return log_oom();
|
||||
|
||||
log_info("Using EFI System Parition at %s.", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_error("Couldn't find EFI system partition. It is recommended to mount it to /boot. Alternatively, use --path= to specify path to mount point.");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
|
||||
static int get_file_version(int fd, char **v) {
|
||||
struct stat st;
|
||||
@ -199,14 +275,16 @@ static int get_file_version(int fd, char **v) {
|
||||
assert(v);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
return log_error_errno(errno, "Failed to stat EFI binary: %m");
|
||||
|
||||
if (st.st_size < 27)
|
||||
if (st.st_size < 27) {
|
||||
*v = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (buf == MAP_FAILED)
|
||||
return -errno;
|
||||
return log_error_errno(errno, "Failed to memory map EFI binary: %m");
|
||||
|
||||
s = memmem(buf, st.st_size - 8, "#### LoaderInfo: ", 17);
|
||||
if (!s)
|
||||
@ -228,7 +306,7 @@ static int get_file_version(int fd, char **v) {
|
||||
r = 1;
|
||||
|
||||
finish:
|
||||
munmap(buf, st.st_size);
|
||||
(void) munmap(buf, st.st_size);
|
||||
*v = x;
|
||||
return r;
|
||||
}
|
||||
@ -338,9 +416,10 @@ static int status_variables(void) {
|
||||
|
||||
n_options = efi_get_boot_options(&options);
|
||||
if (n_options == -ENOENT)
|
||||
return log_error_errno(ENOENT, "Failed to access EFI variables, efivarfs"
|
||||
return log_error_errno(n_options,
|
||||
"Failed to access EFI variables, efivarfs"
|
||||
" needs to be available at /sys/firmware/efi/efivars/.");
|
||||
else if (n_options < 0)
|
||||
if (n_options < 0)
|
||||
return log_error_errno(n_options, "Failed to read EFI boot entries: %m");
|
||||
|
||||
n_order = efi_get_boot_order(&order);
|
||||
@ -360,11 +439,9 @@ static int status_variables(void) {
|
||||
|
||||
for (j = 0; j < n_order; j++)
|
||||
if (options[i] == order[j])
|
||||
goto next;
|
||||
continue;
|
||||
|
||||
print_efi_option(options[i], false);
|
||||
next:
|
||||
continue;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -523,15 +600,6 @@ error:
|
||||
return r;
|
||||
}
|
||||
|
||||
static char* strupper(char *s) {
|
||||
char *p;
|
||||
|
||||
for (p = s; *p; p++)
|
||||
*p = toupper(*p);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static int mkdir_one(const char *prefix, const char *suffix) {
|
||||
char *p;
|
||||
|
||||
@ -554,11 +622,11 @@ static const char *efi_subdirs[] = {
|
||||
};
|
||||
|
||||
static int create_dirs(const char *esp_path) {
|
||||
const char **i;
|
||||
int r;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(efi_subdirs); i++) {
|
||||
r = mkdir_one(esp_path, efi_subdirs[i]);
|
||||
STRV_FOREACH(i, efi_subdirs) {
|
||||
r = mkdir_one(esp_path, *i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -580,7 +648,7 @@ static int copy_one_file(const char *esp_path, const char *name, bool force) {
|
||||
|
||||
/* Create the EFI default boot loader name (specified for removable devices) */
|
||||
v = strjoina(esp_path, "/EFI/BOOT/BOOT", name + strlen("systemd-boot"));
|
||||
strupper(strrchr(v, '/') + 1);
|
||||
ascii_strupper(strrchr(v, '/') + 1);
|
||||
|
||||
k = copy_file(p, v, force);
|
||||
if (k < 0 && r == 0)
|
||||
@ -751,8 +819,8 @@ static int install_variables(const char *esp_path,
|
||||
if (access(p, F_OK) < 0) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
else
|
||||
return log_error_errno(errno, "Cannot access \"%s\": %m", p);
|
||||
|
||||
return log_error_errno(errno, "Cannot access \"%s\": %m", p);
|
||||
}
|
||||
|
||||
r = find_slot(uuid, path, &slot);
|
||||
@ -762,7 +830,7 @@ static int install_variables(const char *esp_path,
|
||||
"Failed to access EFI variables. Is the \"efivarfs\" filesystem mounted?" :
|
||||
"Failed to determine current boot order: %m");
|
||||
|
||||
if (first || r == false) {
|
||||
if (first || r == 0) {
|
||||
r = efi_add_boot_option(slot, "Linux Boot Manager",
|
||||
part, pstart, psize,
|
||||
uuid, path);
|
||||
@ -872,46 +940,39 @@ static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
|
||||
|
||||
if (in_order)
|
||||
return remove_from_order(slot);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int install_loader_config(const char *esp_path) {
|
||||
char *p;
|
||||
char line[64];
|
||||
char *machine = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL, *g = NULL;
|
||||
|
||||
f = fopen("/etc/machine-id", "re");
|
||||
if (!f)
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
|
||||
if (fgets(line, sizeof(line), f) != NULL) {
|
||||
char *s;
|
||||
|
||||
s = strchr(line, '\n');
|
||||
if (s)
|
||||
s[0] = '\0';
|
||||
if (strlen(line) == 32)
|
||||
machine = line;
|
||||
}
|
||||
|
||||
if (!machine)
|
||||
return -ESRCH;
|
||||
|
||||
p = strjoina(esp_path, "/loader/loader.conf");
|
||||
g = fopen(p, "wxe");
|
||||
if (g) {
|
||||
fprintf(g, "#timeout 3\n");
|
||||
fprintf(g, "default %s-*\n", machine);
|
||||
if (ferror(g))
|
||||
return log_error_errno(EIO, "Failed to write \"%s\": %m", p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int help(void) {
|
||||
static int install_loader_config(const char *esp_path) {
|
||||
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
char machine_string[SD_ID128_STRING_MAX];
|
||||
sd_id128_t machine_id;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
r = sd_id128_get_machine(&machine_id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get machine did: %m");
|
||||
|
||||
p = strjoina(esp_path, "/loader/loader.conf");
|
||||
f = fopen(p, "wxe");
|
||||
if (!f)
|
||||
return log_error_errno(errno, "Failed to open loader.conf for writing: %m");
|
||||
|
||||
fprintf(f, "#timeout 3\n");
|
||||
fprintf(f, "default %s-*\n", sd_id128_to_string(machine_id, machine_string));
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write \"%s\": %m", p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
|
||||
printf("%s [COMMAND] [OPTIONS...]\n"
|
||||
"\n"
|
||||
"Install, update or remove the systemd-boot EFI boot manager.\n\n"
|
||||
@ -930,9 +991,6 @@ static int help(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *arg_path = "/boot";
|
||||
static bool arg_touch_variables = true;
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_PATH = 0x100,
|
||||
@ -948,7 +1006,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
int c;
|
||||
int c, r;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
@ -957,14 +1015,16 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
help();
|
||||
help(0, NULL, NULL);
|
||||
return 0;
|
||||
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case ARG_PATH:
|
||||
arg_path = optarg;
|
||||
r = free_and_strdup(&arg_path, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
break;
|
||||
|
||||
case ARG_NO_VARIABLES:
|
||||
@ -989,149 +1049,170 @@ static void read_loader_efi_var(const char *name, char **var) {
|
||||
log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
|
||||
}
|
||||
|
||||
static int bootctl_main(int argc, char*argv[]) {
|
||||
enum action {
|
||||
ACTION_STATUS,
|
||||
ACTION_INSTALL,
|
||||
ACTION_UPDATE,
|
||||
ACTION_REMOVE
|
||||
} arg_action = ACTION_STATUS;
|
||||
static const struct {
|
||||
const char* verb;
|
||||
enum action action;
|
||||
} verbs[] = {
|
||||
{ "status", ACTION_STATUS },
|
||||
{ "install", ACTION_INSTALL },
|
||||
{ "update", ACTION_UPDATE },
|
||||
{ "remove", ACTION_REMOVE },
|
||||
};
|
||||
static int must_be_root(void) {
|
||||
|
||||
sd_id128_t uuid = {};
|
||||
uint32_t part = 0;
|
||||
uint64_t pstart = 0, psize = 0;
|
||||
int r, q;
|
||||
if (geteuid() == 0)
|
||||
return 0;
|
||||
|
||||
if (argv[optind]) {
|
||||
unsigned i;
|
||||
log_error("Need to be root.");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(verbs); i++) {
|
||||
if (!streq(argv[optind], verbs[i].verb))
|
||||
continue;
|
||||
arg_action = verbs[i].action;
|
||||
break;
|
||||
}
|
||||
if (i >= ELEMENTSOF(verbs)) {
|
||||
log_error("Unknown operation \"%s\"", argv[optind]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
|
||||
if (geteuid() != 0)
|
||||
return log_error_errno(EPERM, "Need to be root.");
|
||||
sd_id128_t uuid = SD_ID128_NULL;
|
||||
int r;
|
||||
|
||||
r = verify_esp(arg_path, &part, &pstart, &psize, &uuid);
|
||||
if (r == -ENODEV && !arg_path)
|
||||
log_notice("You might want to use --path= to indicate the path to your ESP, in case it is not mounted on /boot.");
|
||||
r = must_be_root();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch (arg_action) {
|
||||
case ACTION_STATUS: {
|
||||
_cleanup_free_ char *fw_type = NULL;
|
||||
_cleanup_free_ char *fw_info = NULL;
|
||||
_cleanup_free_ char *loader = NULL;
|
||||
_cleanup_free_ char *loader_path = NULL;
|
||||
sd_id128_t loader_part_uuid = {};
|
||||
r = find_esp(NULL, NULL, NULL, &uuid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (is_efi_boot()) {
|
||||
read_loader_efi_var("LoaderFirmwareType", &fw_type);
|
||||
read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
|
||||
read_loader_efi_var("LoaderInfo", &loader);
|
||||
read_loader_efi_var("LoaderImageIdentifier", &loader_path);
|
||||
if (loader_path)
|
||||
efi_tilt_backslashes(loader_path);
|
||||
r = efi_loader_get_device_part_uuid(&loader_part_uuid);
|
||||
if (r < 0 && r == -ENOENT)
|
||||
log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
|
||||
if (is_efi_boot()) {
|
||||
_cleanup_free_ char *fw_type = NULL, *fw_info = NULL, *loader = NULL, *loader_path = NULL;
|
||||
sd_id128_t loader_part_uuid = SD_ID128_NULL;
|
||||
|
||||
printf("System:\n");
|
||||
printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
|
||||
read_loader_efi_var("LoaderFirmwareType", &fw_type);
|
||||
read_loader_efi_var("LoaderFirmwareInfo", &fw_info);
|
||||
read_loader_efi_var("LoaderInfo", &loader);
|
||||
read_loader_efi_var("LoaderImageIdentifier", &loader_path);
|
||||
|
||||
r = is_efi_secure_boot();
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to query secure boot status: %m");
|
||||
else
|
||||
printf(" Secure Boot: %s\n", r ? "enabled" : "disabled");
|
||||
if (loader_path)
|
||||
efi_tilt_backslashes(loader_path);
|
||||
|
||||
r = is_efi_secure_boot_setup_mode();
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to query secure boot mode: %m");
|
||||
else
|
||||
printf(" Setup Mode: %s\n", r ? "setup" : "user");
|
||||
printf("\n");
|
||||
r = efi_loader_get_device_part_uuid(&loader_part_uuid);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_warning_errno(r, "Failed to read EFI variable LoaderDevicePartUUID: %m");
|
||||
|
||||
printf("Loader:\n");
|
||||
printf(" Product: %s\n", strna(loader));
|
||||
if (!sd_id128_is_null(loader_part_uuid))
|
||||
printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
|
||||
SD_ID128_FORMAT_VAL(loader_part_uuid));
|
||||
else
|
||||
printf(" Partition: n/a\n");
|
||||
printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
|
||||
printf("\n");
|
||||
} else
|
||||
printf("System:\n Not booted with EFI\n");
|
||||
printf("System:\n");
|
||||
printf(" Firmware: %s (%s)\n", strna(fw_type), strna(fw_info));
|
||||
|
||||
r = status_binaries(arg_path, uuid);
|
||||
r = is_efi_secure_boot();
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to query secure boot status: %m");
|
||||
else
|
||||
printf(" Secure Boot: %s\n", r ? "enabled" : "disabled");
|
||||
|
||||
r = is_efi_secure_boot_setup_mode();
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to query secure boot mode: %m");
|
||||
else
|
||||
printf(" Setup Mode: %s\n", r ? "setup" : "user");
|
||||
printf("\n");
|
||||
|
||||
printf("Loader:\n");
|
||||
printf(" Product: %s\n", strna(loader));
|
||||
if (!sd_id128_is_null(loader_part_uuid))
|
||||
printf(" Partition: /dev/disk/by-partuuid/%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
|
||||
SD_ID128_FORMAT_VAL(loader_part_uuid));
|
||||
else
|
||||
printf(" Partition: n/a\n");
|
||||
printf(" File: %s%s\n", special_glyph(TREE_RIGHT), strna(loader_path));
|
||||
printf("\n");
|
||||
} else
|
||||
printf("System:\n Not booted with EFI\n");
|
||||
|
||||
r = status_binaries(arg_path, uuid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_touch_variables)
|
||||
r = status_variables();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int verb_install(int argc, char *argv[], void *userdata) {
|
||||
|
||||
sd_id128_t uuid = SD_ID128_NULL;
|
||||
uint64_t pstart = 0, psize = 0;
|
||||
uint32_t part = 0;
|
||||
bool install;
|
||||
int r;
|
||||
|
||||
r = must_be_root();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = find_esp(&part, &pstart, &psize, &uuid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
install = streq(argv[0], "install");
|
||||
|
||||
RUN_WITH_UMASK(0002) {
|
||||
r = install_binaries(arg_path, install);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_touch_variables)
|
||||
r = status_variables();
|
||||
break;
|
||||
}
|
||||
|
||||
case ACTION_INSTALL:
|
||||
case ACTION_UPDATE:
|
||||
umask(0002);
|
||||
|
||||
r = install_binaries(arg_path, arg_action == ACTION_INSTALL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (arg_action == ACTION_INSTALL) {
|
||||
if (install) {
|
||||
r = install_loader_config(arg_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_touch_variables)
|
||||
r = install_variables(arg_path,
|
||||
part, pstart, psize, uuid,
|
||||
"/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
|
||||
arg_action == ACTION_INSTALL);
|
||||
break;
|
||||
if (arg_touch_variables)
|
||||
r = install_variables(arg_path,
|
||||
part, pstart, psize, uuid,
|
||||
"/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
|
||||
install);
|
||||
|
||||
case ACTION_REMOVE:
|
||||
r = remove_binaries(arg_path);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (arg_touch_variables) {
|
||||
q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
|
||||
if (q < 0 && r == 0)
|
||||
r = q;
|
||||
}
|
||||
break;
|
||||
static int verb_remove(int argc, char *argv[], void *userdata) {
|
||||
sd_id128_t uuid = SD_ID128_NULL;
|
||||
int r;
|
||||
|
||||
r = must_be_root();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = find_esp(NULL, NULL, NULL, &uuid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = remove_binaries(arg_path);
|
||||
|
||||
if (arg_touch_variables) {
|
||||
int q;
|
||||
|
||||
q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
|
||||
if (q < 0 && r == 0)
|
||||
r = q;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int bootctl_main(int argc, char *argv[]) {
|
||||
|
||||
static const Verb verbs[] = {
|
||||
{ "help", VERB_ANY, VERB_ANY, 0, help },
|
||||
{ "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
|
||||
{ "install", VERB_ANY, 1, 0, verb_install },
|
||||
{ "update", VERB_ANY, 1, 0, verb_install },
|
||||
{ "remove", VERB_ANY, 1, 0, verb_remove },
|
||||
{}
|
||||
};
|
||||
|
||||
return dispatch_verb(argc, argv, verbs, NULL);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int r;
|
||||
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
/* If we run in a container, automatically turn of EFI file system access */
|
||||
if (detect_container() > 0)
|
||||
arg_touch_variables = false;
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r <= 0)
|
||||
goto finish;
|
||||
@ -1139,5 +1220,6 @@ int main(int argc, char *argv[]) {
|
||||
r = bootctl_main(argc, argv);
|
||||
|
||||
finish:
|
||||
free(arg_path);
|
||||
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -450,99 +450,101 @@ static int add_automount(
|
||||
}
|
||||
|
||||
static int add_boot(const char *what) {
|
||||
_cleanup_blkid_free_probe_ blkid_probe b = NULL;
|
||||
const char *fstype = NULL, *uuid = NULL;
|
||||
sd_id128_t id, type_id;
|
||||
const char *esp;
|
||||
int r;
|
||||
|
||||
assert(what);
|
||||
|
||||
if (!is_efi_boot()) {
|
||||
log_debug("Not an EFI boot, ignoring /boot.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_initrd()) {
|
||||
log_debug("In initrd, ignoring /boot.");
|
||||
log_debug("In initrd, ignoring the ESP.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (detect_container() > 0) {
|
||||
log_debug("In a container, ignoring /boot.");
|
||||
log_debug("In a container, ignoring the ESP.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If /efi exists we'll use that. Otherwise we'll use /boot, as that's usually the better choice */
|
||||
esp = access("/efi/", F_OK) >= 0 ? "/efi" : "/boot";
|
||||
|
||||
/* We create an .automount which is not overridden by the .mount from the fstab generator. */
|
||||
if (fstab_is_mount_point("/boot")) {
|
||||
log_debug("/boot specified in fstab, ignoring.");
|
||||
if (fstab_is_mount_point(esp)) {
|
||||
log_debug("%s specified in fstab, ignoring.", esp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (path_is_busy("/boot")) {
|
||||
log_debug("/boot already populated, ignoring.");
|
||||
if (path_is_busy(esp)) {
|
||||
log_debug("%s already populated, ignoring.", esp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_loader_get_device_part_uuid(&id);
|
||||
if (r == -ENOENT) {
|
||||
log_debug("EFI loader partition unknown.");
|
||||
return 0;
|
||||
}
|
||||
if (is_efi_boot()) {
|
||||
_cleanup_blkid_free_probe_ blkid_probe b = NULL;
|
||||
const char *fstype = NULL, *uuid_string = NULL;
|
||||
sd_id128_t loader_uuid, part_uuid;
|
||||
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read ESP partition UUID: %m");
|
||||
/* If this is an EFI boot, be extra careful, and only mount the ESP if it was the ESP used for booting. */
|
||||
|
||||
errno = 0;
|
||||
b = blkid_new_probe_from_filename(what);
|
||||
if (!b) {
|
||||
if (errno == 0)
|
||||
return log_oom();
|
||||
return log_error_errno(errno, "Failed to allocate prober: %m");
|
||||
}
|
||||
r = efi_loader_get_device_part_uuid(&loader_uuid);
|
||||
if (r == -ENOENT) {
|
||||
log_debug("EFI loader partition unknown.");
|
||||
return 0;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read ESP partition UUID: %m");
|
||||
|
||||
blkid_probe_enable_partitions(b, 1);
|
||||
blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
|
||||
errno = 0;
|
||||
b = blkid_new_probe_from_filename(what);
|
||||
if (!b) {
|
||||
if (errno == 0)
|
||||
return log_oom();
|
||||
return log_error_errno(errno, "Failed to allocate prober: %m");
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
r = blkid_do_safeprobe(b);
|
||||
if (r == -2 || r == 1) /* no result or uncertain */
|
||||
return 0;
|
||||
else if (r != 0)
|
||||
return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
|
||||
blkid_probe_enable_partitions(b, 1);
|
||||
blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
|
||||
|
||||
(void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
|
||||
if (!streq_ptr(fstype, "vfat")) {
|
||||
log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
errno = 0;
|
||||
r = blkid_do_safeprobe(b);
|
||||
if (r == -2 || r == 1) /* no result or uncertain */
|
||||
return 0;
|
||||
else if (r != 0)
|
||||
return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
|
||||
|
||||
errno = 0;
|
||||
r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL);
|
||||
if (r != 0) {
|
||||
log_debug_errno(errno, "Partition for /boot does not have a UUID, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
(void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
|
||||
if (!streq_ptr(fstype, "vfat")) {
|
||||
log_debug("Partition for %s is not a FAT filesystem, ignoring.", esp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sd_id128_from_string(uuid, &type_id) < 0) {
|
||||
log_debug("Partition for /boot does not have a valid UUID, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
errno = 0;
|
||||
r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid_string, NULL);
|
||||
if (r != 0) {
|
||||
log_debug_errno(errno, "Partition for %s does not have a UUID, ignoring.", esp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sd_id128_equal(type_id, id)) {
|
||||
log_debug("Partition for /boot does not appear to be the partition we are booted from.");
|
||||
return 0;
|
||||
}
|
||||
if (sd_id128_from_string(uuid_string, &part_uuid) < 0) {
|
||||
log_debug("Partition for %s does not have a valid UUID, ignoring.", esp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = add_automount("boot",
|
||||
what,
|
||||
"/boot",
|
||||
"vfat",
|
||||
true,
|
||||
"umask=0077",
|
||||
"EFI System Partition Automount",
|
||||
120 * USEC_PER_SEC);
|
||||
if (!sd_id128_equal(part_uuid, loader_uuid)) {
|
||||
log_debug("Partition for %s does not appear to be the partition we are booted from.", esp);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
log_debug("Not an EFI boot, skipping ESP check.");
|
||||
|
||||
return r;
|
||||
return add_automount("boot",
|
||||
what,
|
||||
esp,
|
||||
"vfat",
|
||||
true,
|
||||
"umask=0077",
|
||||
"EFI System Partition Automount",
|
||||
120 * USEC_PER_SEC);
|
||||
}
|
||||
#else
|
||||
static int add_boot(const char *what) {
|
||||
|
@ -86,10 +86,15 @@ if [[ ! $COMMAND ]] || [[ ! $KERNEL_VERSION ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then
|
||||
if [[ -d /efi/loader/entries ]] || [[ -d /efi/$MACHINE_ID ]]; then
|
||||
BOOT_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
|
||||
elif [[ -d /boot/loader/entries ]] || [[ -d /boot/$MACHINE_ID ]]; then
|
||||
BOOT_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
|
||||
elif [[ -d /boot/efi/loader/entries ]] || [[ -d /boot/efi/$MACHINE_ID ]] \
|
||||
|| mountpoint -q /boot/efi; then
|
||||
elif [[ -d /boot/efi/loader/entries ]] || [[ -d /boot/efi/$MACHINE_ID ]]; then
|
||||
BOOT_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION"
|
||||
elif mountpoint -q /efi; then
|
||||
BOOT_DIR_ABS="/efi/$MACHINE_ID/$KERNEL_VERSION"
|
||||
elif mountpoint -q /boot/efi; then
|
||||
BOOT_DIR_ABS="/boot/efi/$MACHINE_ID/$KERNEL_VERSION"
|
||||
else
|
||||
BOOT_DIR_ABS="/boot/$MACHINE_ID/$KERNEL_VERSION"
|
||||
|
@ -1794,17 +1794,18 @@ static int dissect_image(
|
||||
char **root_device, bool *root_device_rw,
|
||||
char **home_device, bool *home_device_rw,
|
||||
char **srv_device, bool *srv_device_rw,
|
||||
char **esp_device,
|
||||
bool *secondary) {
|
||||
|
||||
#ifdef HAVE_BLKID
|
||||
int home_nr = -1, srv_nr = -1;
|
||||
int home_nr = -1, srv_nr = -1, esp_nr = -1;
|
||||
#ifdef GPT_ROOT_NATIVE
|
||||
int root_nr = -1;
|
||||
#endif
|
||||
#ifdef GPT_ROOT_SECONDARY
|
||||
int secondary_root_nr = -1;
|
||||
#endif
|
||||
_cleanup_free_ char *home = NULL, *root = NULL, *secondary_root = NULL, *srv = NULL, *generic = NULL;
|
||||
_cleanup_free_ char *home = NULL, *root = NULL, *secondary_root = NULL, *srv = NULL, *esp = NULL, *generic = NULL;
|
||||
_cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
|
||||
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
|
||||
_cleanup_blkid_free_probe_ blkid_probe b = NULL;
|
||||
@ -1822,6 +1823,7 @@ static int dissect_image(
|
||||
assert(root_device);
|
||||
assert(home_device);
|
||||
assert(srv_device);
|
||||
assert(esp_device);
|
||||
assert(secondary);
|
||||
assert(arg_image);
|
||||
|
||||
@ -2035,6 +2037,16 @@ static int dissect_image(
|
||||
r = free_and_strdup(&srv, node);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
} else if (sd_id128_equal(type_id, GPT_ESP)) {
|
||||
|
||||
if (esp && nr >= esp_nr)
|
||||
continue;
|
||||
|
||||
esp_nr = nr;
|
||||
|
||||
r = free_and_strdup(&esp, node);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
#ifdef GPT_ROOT_NATIVE
|
||||
else if (sd_id128_equal(type_id, GPT_ROOT_NATIVE)) {
|
||||
@ -2152,6 +2164,11 @@ static int dissect_image(
|
||||
*srv_device_rw = srv_rw;
|
||||
}
|
||||
|
||||
if (esp) {
|
||||
*esp_device = esp;
|
||||
esp = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
log_error("--image= is not supported, compiled without blkid support.");
|
||||
@ -2284,7 +2301,8 @@ static int mount_devices(
|
||||
const char *where,
|
||||
const char *root_device, bool root_device_rw,
|
||||
const char *home_device, bool home_device_rw,
|
||||
const char *srv_device, bool srv_device_rw) {
|
||||
const char *srv_device, bool srv_device_rw,
|
||||
const char *esp_device) {
|
||||
int r;
|
||||
|
||||
assert(where);
|
||||
@ -2307,6 +2325,27 @@ static int mount_devices(
|
||||
return log_error_errno(r, "Failed to mount server data directory: %m");
|
||||
}
|
||||
|
||||
if (esp_device) {
|
||||
const char *mp, *x;
|
||||
|
||||
/* Mount the ESP to /efi if it exists and is empty. If it doesn't exist, use /boot instead. */
|
||||
|
||||
mp = "/efi";
|
||||
x = strjoina(arg_directory, mp);
|
||||
r = dir_is_empty(x);
|
||||
if (r == -ENOENT) {
|
||||
mp = "/boot";
|
||||
x = strjoina(arg_directory, mp);
|
||||
r = dir_is_empty(x);
|
||||
}
|
||||
|
||||
if (r > 0) {
|
||||
r = mount_device(esp_device, arg_directory, mp, true);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mount ESP: %m");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2795,6 +2834,7 @@ static int outer_child(
|
||||
const char *root_device, bool root_device_rw,
|
||||
const char *home_device, bool home_device_rw,
|
||||
const char *srv_device, bool srv_device_rw,
|
||||
const char *esp_device,
|
||||
bool interactive,
|
||||
bool secondary,
|
||||
int pid_socket,
|
||||
@ -2856,7 +2896,8 @@ static int outer_child(
|
||||
r = mount_devices(directory,
|
||||
root_device, root_device_rw,
|
||||
home_device, home_device_rw,
|
||||
srv_device, srv_device_rw);
|
||||
srv_device, srv_device_rw,
|
||||
esp_device);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -3461,7 +3502,7 @@ static int load_settings(void) {
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
_cleanup_free_ char *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL, *console = NULL;
|
||||
_cleanup_free_ char *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL, *esp_device = NULL, *console = NULL;
|
||||
bool root_device_rw = true, home_device_rw = true, srv_device_rw = true;
|
||||
_cleanup_close_ int master = -1, image_fd = -1;
|
||||
_cleanup_fdset_free_ FDSet *fds = NULL;
|
||||
@ -3643,6 +3684,7 @@ int main(int argc, char *argv[]) {
|
||||
&root_device, &root_device_rw,
|
||||
&home_device, &home_device_rw,
|
||||
&srv_device, &srv_device_rw,
|
||||
&esp_device,
|
||||
&secondary);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
@ -3817,6 +3859,7 @@ int main(int argc, char *argv[]) {
|
||||
root_device, root_device_rw,
|
||||
home_device, home_device_rw,
|
||||
srv_device, srv_device_rw,
|
||||
esp_device,
|
||||
interactive,
|
||||
secondary,
|
||||
pid_socket_pair[1],
|
||||
|
Loading…
x
Reference in New Issue
Block a user