mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-09-14 09:44:48 +03:00
bootctl: teach bootctl the new partition type
This commit is contained in:
@@ -45,12 +45,20 @@
|
|||||||
#include "verbs.h"
|
#include "verbs.h"
|
||||||
#include "virt.h"
|
#include "virt.h"
|
||||||
|
|
||||||
static char *arg_path = NULL;
|
static char *arg_esp_path = NULL;
|
||||||
static bool arg_print_path = false;
|
static char *arg_xbootldr_path = NULL;
|
||||||
|
static bool arg_print_esp_path = false;
|
||||||
|
static bool arg_print_dollar_boot_path = false;
|
||||||
static bool arg_touch_variables = true;
|
static bool arg_touch_variables = true;
|
||||||
static PagerFlags arg_pager_flags = 0;
|
static PagerFlags arg_pager_flags = 0;
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_path, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
|
||||||
|
STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
|
||||||
|
|
||||||
|
static const char *arg_dollar_boot_path(void) {
|
||||||
|
/* $BOOT shall be the XBOOTLDR partition if it exists, and otherwise the ESP */
|
||||||
|
return arg_xbootldr_path ?: arg_esp_path;
|
||||||
|
}
|
||||||
|
|
||||||
static int acquire_esp(
|
static int acquire_esp(
|
||||||
bool unprivileged_mode,
|
bool unprivileged_mode,
|
||||||
@@ -62,24 +70,44 @@ static int acquire_esp(
|
|||||||
char *np;
|
char *np;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Find the ESP, and log about errors. Note that find_esp_and_warn() will log in all error cases on its own,
|
/* Find the ESP, and log about errors. Note that find_esp_and_warn() will log in all error cases on
|
||||||
* except for ENOKEY (which is good, we want to show our own message in that case, suggesting use of --path=)
|
* its own, except for ENOKEY (which is good, we want to show our own message in that case,
|
||||||
* and EACCESS (only when we request unprivileged mode; in this case we simply eat up the error here, so that
|
* suggesting use of --esp-path=) and EACCESS (only when we request unprivileged mode; in this case
|
||||||
* --list and --status work too, without noise about this). */
|
* we simply eat up the error here, so that --list and --status work too, without noise about
|
||||||
|
* this). */
|
||||||
|
|
||||||
r = find_esp_and_warn(arg_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid);
|
r = find_esp_and_warn(arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid);
|
||||||
if (r == -ENOKEY)
|
if (r == -ENOKEY)
|
||||||
return log_error_errno(r,
|
return log_error_errno(r,
|
||||||
"Couldn't find EFI system partition. It is recommended to mount it to /boot or /efi.\n"
|
"Couldn't find EFI system partition. It is recommended to mount it to /boot or /efi.\n"
|
||||||
"Alternatively, use --path= to specify path to mount point.");
|
"Alternatively, use --esp-path= to specify path to mount point.");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
free_and_replace(arg_path, np);
|
free_and_replace(arg_esp_path, np);
|
||||||
|
log_debug("Using EFI System Partition at %s.", arg_esp_path);
|
||||||
|
|
||||||
log_debug("Using EFI System Partition at %s.", arg_path);
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
static int acquire_xbootldr(bool unprivileged_mode, sd_id128_t *ret_uuid) {
|
||||||
|
char *np;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = find_xbootldr_and_warn(arg_xbootldr_path, unprivileged_mode, &np, ret_uuid);
|
||||||
|
if (r == -ENOKEY) {
|
||||||
|
log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
|
||||||
|
if (ret_uuid)
|
||||||
|
*ret_uuid = SD_ID128_NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
free_and_replace(arg_xbootldr_path, np);
|
||||||
|
log_debug("Using XBOOTLDR partition at %s as $BOOT.", arg_xbootldr_path);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
|
/* search for "#### LoaderInfo: systemd-boot 218 ####" string inside the binary */
|
||||||
@@ -134,10 +162,13 @@ finish:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
|
static int enumerate_binaries(const char *esp_path, const char *path, const char *prefix) {
|
||||||
char *p;
|
|
||||||
_cleanup_closedir_ DIR *d = NULL;
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
int r = 0, c = 0;
|
int c = 0, r;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
assert(esp_path);
|
||||||
|
assert(path);
|
||||||
|
|
||||||
p = strjoina(esp_path, "/", path);
|
p = strjoina(esp_path, "/", path);
|
||||||
d = opendir(p);
|
d = opendir(p);
|
||||||
@@ -149,8 +180,8 @@ static int enumerate_binaries(const char *esp_path, const char *path, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_DIRENT(de, d, break) {
|
FOREACH_DIRENT(de, d, break) {
|
||||||
_cleanup_close_ int fd = -1;
|
|
||||||
_cleanup_free_ char *v = NULL;
|
_cleanup_free_ char *v = NULL;
|
||||||
|
_cleanup_close_ int fd = -1;
|
||||||
|
|
||||||
if (!endswith_no_case(de->d_name, ".efi"))
|
if (!endswith_no_case(de->d_name, ".efi"))
|
||||||
continue;
|
continue;
|
||||||
@@ -169,6 +200,7 @@ static int enumerate_binaries(const char *esp_path, const char *path, const char
|
|||||||
printf(" File: %s/%s/%s (%s%s%s)\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path, de->d_name, ansi_highlight(), v, ansi_normal());
|
printf(" File: %s/%s/%s (%s%s%s)\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path, de->d_name, ansi_highlight(), v, ansi_normal());
|
||||||
else
|
else
|
||||||
printf(" File: %s/%s/%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path, de->d_name);
|
printf(" File: %s/%s/%s\n", special_glyph(SPECIAL_GLYPH_TREE_RIGHT), path, de->d_name);
|
||||||
|
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,16 +223,16 @@ static int status_binaries(const char *esp_path, sd_id128_t partition) {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
|
r = enumerate_binaries(esp_path, "EFI/systemd", NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
log_info("systemd-boot not installed in ESP.");
|
log_info("systemd-boot not installed in ESP.");
|
||||||
else if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
r = enumerate_binaries(esp_path, "EFI/BOOT", "boot");
|
r = enumerate_binaries(esp_path, "EFI/BOOT", "boot");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
log_info("No default/fallback boot loader installed in ESP.");
|
log_info("No default/fallback boot loader installed in ESP.");
|
||||||
else if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
@@ -319,11 +351,11 @@ static int boot_entry_show(const BootEntry *e, bool show_as_default) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int status_entries(const char *esp_path, sd_id128_t partition) {
|
static int status_entries(const char *esp_path, const char *xbootldr_path) {
|
||||||
_cleanup_(boot_config_free) BootConfig config = {};
|
_cleanup_(boot_config_free) BootConfig config = {};
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = boot_entries_load_config(esp_path, NULL, &config);
|
r = boot_entries_load_config(esp_path, xbootldr_path, &config);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@@ -469,20 +501,21 @@ static int mkdir_one(const char *prefix, const char *suffix) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *efi_subdirs[] = {
|
static const char *const esp_subdirs[] = {
|
||||||
"EFI",
|
"EFI",
|
||||||
"EFI/systemd",
|
"EFI/systemd",
|
||||||
"EFI/BOOT",
|
"EFI/BOOT",
|
||||||
"loader",
|
"loader",
|
||||||
"loader/entries",
|
/* Note that "/loader/entries" is not listed here, since it should be placed in $BOOT, which might
|
||||||
|
* not necessarily be the ESP */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int create_dirs(const char *esp_path) {
|
static int create_esp_subdirs(const char *esp_path) {
|
||||||
const char **i;
|
const char *const *i;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
STRV_FOREACH(i, efi_subdirs) {
|
STRV_FOREACH(i, esp_subdirs) {
|
||||||
r = mkdir_one(esp_path, *i);
|
r = mkdir_one(esp_path, *i);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@@ -521,17 +554,6 @@ static int install_binaries(const char *esp_path, bool force) {
|
|||||||
_cleanup_closedir_ DIR *d = NULL;
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (force) {
|
|
||||||
/* Don't create any of these directories when we are
|
|
||||||
* just updating. When we update we'll drop-in our
|
|
||||||
* files (unless there are newer ones already), but we
|
|
||||||
* won't create the directories for them in the first
|
|
||||||
* place. */
|
|
||||||
r = create_dirs(esp_path);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
d = opendir(BOOTLIBDIR);
|
d = opendir(BOOTLIBDIR);
|
||||||
if (!d)
|
if (!d)
|
||||||
return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
|
return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
|
||||||
@@ -752,18 +774,36 @@ static int rmdir_one(const char *prefix, const char *suffix) {
|
|||||||
|
|
||||||
p = strjoina(prefix, "/", suffix);
|
p = strjoina(prefix, "/", suffix);
|
||||||
if (rmdir(p) < 0) {
|
if (rmdir(p) < 0) {
|
||||||
if (!IN_SET(errno, ENOENT, ENOTEMPTY))
|
bool ignore = IN_SET(errno, ENOENT, ENOTEMPTY);
|
||||||
return log_error_errno(errno, "Failed to remove \"%s\": %m", p);
|
|
||||||
|
log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, errno,
|
||||||
|
"Failed to remove directory \"%s\": %m", p);
|
||||||
|
if (!ignore)
|
||||||
|
return -errno;
|
||||||
} else
|
} else
|
||||||
log_info("Removed \"%s\".", p);
|
log_info("Removed \"%s\".", p);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int remove_esp_subdirs(const char *esp_path) {
|
||||||
|
size_t i;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
for (i = ELEMENTSOF(esp_subdirs)-1; i > 0; i--) {
|
||||||
|
int q;
|
||||||
|
|
||||||
|
q = rmdir_one(esp_path, esp_subdirs[i-1]);
|
||||||
|
if (q < 0 && r >= 0)
|
||||||
|
r = q;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int remove_binaries(const char *esp_path) {
|
static int remove_binaries(const char *esp_path) {
|
||||||
char *p;
|
char *p;
|
||||||
int r, q;
|
int r, q;
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
p = strjoina(esp_path, "/EFI/systemd");
|
p = strjoina(esp_path, "/EFI/systemd");
|
||||||
r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
|
r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||||
@@ -772,15 +812,31 @@ static int remove_binaries(const char *esp_path) {
|
|||||||
if (q < 0 && r == 0)
|
if (q < 0 && r == 0)
|
||||||
r = q;
|
r = q;
|
||||||
|
|
||||||
for (i = ELEMENTSOF(efi_subdirs)-1; i > 0; i--) {
|
|
||||||
q = rmdir_one(esp_path, efi_subdirs[i-1]);
|
|
||||||
if (q < 0 && r == 0)
|
|
||||||
r = q;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int remove_loader_config(const char *esp_path) {
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
assert(esp_path);
|
||||||
|
|
||||||
|
p = strjoina(esp_path, "/loader/loader.conf");
|
||||||
|
if (unlink(p) < 0) {
|
||||||
|
log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to unlink file \"%s\": %m", p);
|
||||||
|
if (errno != ENOENT)
|
||||||
|
return -errno;
|
||||||
|
} else
|
||||||
|
log_info("Removed \"%s\".", p);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_entries_directory(const char *dollar_boot_path) {
|
||||||
|
assert(dollar_boot_path);
|
||||||
|
|
||||||
|
return rmdir_one(dollar_boot_path, "/loader/entries");
|
||||||
|
}
|
||||||
|
|
||||||
static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
|
static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
|
||||||
uint16_t slot;
|
uint16_t slot;
|
||||||
int r;
|
int r;
|
||||||
@@ -803,7 +859,6 @@ static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int install_loader_config(const char *esp_path) {
|
static int install_loader_config(const char *esp_path) {
|
||||||
|
|
||||||
char machine_string[SD_ID128_STRING_MAX];
|
char machine_string[SD_ID128_STRING_MAX];
|
||||||
_cleanup_(unlink_and_freep) char *t = NULL;
|
_cleanup_(unlink_and_freep) char *t = NULL;
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
@@ -811,15 +866,14 @@ static int install_loader_config(const char *esp_path) {
|
|||||||
const char *p;
|
const char *p;
|
||||||
int r, fd;
|
int r, fd;
|
||||||
|
|
||||||
|
p = strjoina(esp_path, "/loader/loader.conf");
|
||||||
|
if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
|
||||||
|
return 0;
|
||||||
|
|
||||||
r = sd_id128_get_machine(&machine_id);
|
r = sd_id128_get_machine(&machine_id);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to get machine id: %m");
|
return log_error_errno(r, "Failed to get machine id: %m");
|
||||||
|
|
||||||
p = strjoina(esp_path, "/loader/loader.conf");
|
|
||||||
|
|
||||||
if (access(p, F_OK) >= 0) /* Silently skip creation if the file already exists (early check) */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fd = open_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t);
|
fd = open_tmpfile_linkable(p, O_WRONLY|O_CLOEXEC, &t);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return log_error_errno(fd, "Failed to open \"%s\" for writing: %m", p);
|
return log_error_errno(fd, "Failed to open \"%s\" for writing: %m", p);
|
||||||
@@ -845,10 +899,15 @@ static int install_loader_config(const char *esp_path) {
|
|||||||
return log_error_errno(r, "Failed to move \"%s\" into place: %m", p);
|
return log_error_errno(r, "Failed to move \"%s\" into place: %m", p);
|
||||||
|
|
||||||
t = mfree(t);
|
t = mfree(t);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int install_entries_directory(const char *dollar_boot_path) {
|
||||||
|
assert(dollar_boot_path);
|
||||||
|
|
||||||
|
return mkdir_one(dollar_boot_path, "/loader/entries");
|
||||||
|
}
|
||||||
|
|
||||||
static int help(int argc, char *argv[], void *userdata) {
|
static int help(int argc, char *argv[], void *userdata) {
|
||||||
_cleanup_free_ char *link = NULL;
|
_cleanup_free_ char *link = NULL;
|
||||||
int r;
|
int r;
|
||||||
@@ -859,21 +918,23 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||||||
|
|
||||||
printf("%s [COMMAND] [OPTIONS...]\n\n"
|
printf("%s [COMMAND] [OPTIONS...]\n\n"
|
||||||
"Install, update or remove the systemd-boot EFI boot manager.\n\n"
|
"Install, update or remove the systemd-boot EFI boot manager.\n\n"
|
||||||
" -h --help Show this help\n"
|
" -h --help Show this help\n"
|
||||||
" --version Print version\n"
|
" --version Print version\n"
|
||||||
" --path=PATH Path to the EFI System Partition (ESP)\n"
|
" --esp-path=PATH Path to the EFI System Partition (ESP)\n"
|
||||||
" -p --print-path Print path to the EFI partition\n"
|
" --boot-path=PATH Path to the $BOOT partition\n"
|
||||||
" --no-variables Don't touch EFI variables\n"
|
" -p --print-esp-path Print path to the EFI System Partition\n"
|
||||||
" --no-pager Do not pipe output into a pager\n"
|
" --print-boot-path Print path to the $BOOT partition\n"
|
||||||
|
" --no-variables Don't touch EFI variables\n"
|
||||||
|
" --no-pager Do not pipe output into a pager\n"
|
||||||
"\nBoot Loader Commands:\n"
|
"\nBoot Loader Commands:\n"
|
||||||
" status Show status of installed systemd-boot and EFI variables\n"
|
" status Show status of installed systemd-boot and EFI variables\n"
|
||||||
" install Install systemd-boot to the ESP and EFI variables\n"
|
" install Install systemd-boot to the ESP and EFI variables\n"
|
||||||
" update Update systemd-boot in the ESP and EFI variables\n"
|
" update Update systemd-boot in the ESP and EFI variables\n"
|
||||||
" remove Remove systemd-boot from the ESP and EFI variables\n"
|
" remove Remove systemd-boot from the ESP and EFI variables\n"
|
||||||
"\nBoot Loader Entries Commands:\n"
|
"\nBoot Loader Entries Commands:\n"
|
||||||
" list List boot loader entries\n"
|
" list List boot loader entries\n"
|
||||||
" set-default ID Set default boot loader entry\n"
|
" set-default ID Set default boot loader entry\n"
|
||||||
" set-oneshot ID Set default boot loader entry, for next boot only\n"
|
" set-oneshot ID Set default boot loader entry, for next boot only\n"
|
||||||
"\nSee the %s for details.\n"
|
"\nSee the %s for details.\n"
|
||||||
, program_invocation_short_name
|
, program_invocation_short_name
|
||||||
, link);
|
, link);
|
||||||
@@ -883,19 +944,25 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||||||
|
|
||||||
static int parse_argv(int argc, char *argv[]) {
|
static int parse_argv(int argc, char *argv[]) {
|
||||||
enum {
|
enum {
|
||||||
ARG_PATH = 0x100,
|
ARG_ESP_PATH = 0x100,
|
||||||
|
ARG_BOOT_PATH,
|
||||||
|
ARG_PRINT_BOOT_PATH,
|
||||||
ARG_VERSION,
|
ARG_VERSION,
|
||||||
ARG_NO_VARIABLES,
|
ARG_NO_VARIABLES,
|
||||||
ARG_NO_PAGER,
|
ARG_NO_PAGER,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ "version", no_argument, NULL, ARG_VERSION },
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
{ "path", required_argument, NULL, ARG_PATH },
|
{ "esp-path", required_argument, NULL, ARG_ESP_PATH },
|
||||||
{ "print-path", no_argument, NULL, 'p' },
|
{ "path", required_argument, NULL, ARG_ESP_PATH }, /* Compatibility alias */
|
||||||
{ "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
|
{ "boot-path", required_argument, NULL, ARG_BOOT_PATH },
|
||||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
{ "print-esp-path", no_argument, NULL, 'p' },
|
||||||
|
{ "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */
|
||||||
|
{ "print-boot-path", no_argument, NULL, ARG_PRINT_BOOT_PATH },
|
||||||
|
{ "no-variables", no_argument, NULL, ARG_NO_VARIABLES },
|
||||||
|
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -914,14 +981,24 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
case ARG_VERSION:
|
case ARG_VERSION:
|
||||||
return version();
|
return version();
|
||||||
|
|
||||||
case ARG_PATH:
|
case ARG_ESP_PATH:
|
||||||
r = free_and_strdup(&arg_path, optarg);
|
r = free_and_strdup(&arg_esp_path, optarg);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_BOOT_PATH:
|
||||||
|
r = free_and_strdup(&arg_xbootldr_path, optarg);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
arg_print_path = true;
|
arg_print_esp_path = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_PRINT_BOOT_PATH:
|
||||||
|
arg_print_dollar_boot_path = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARG_NO_VARIABLES:
|
case ARG_NO_VARIABLES:
|
||||||
@@ -951,23 +1028,33 @@ static void read_loader_efi_var(const char *name, char **var) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int verb_status(int argc, char *argv[], void *userdata) {
|
static int verb_status(int argc, char *argv[], void *userdata) {
|
||||||
|
sd_id128_t esp_uuid = SD_ID128_NULL, xbootldr_uuid = SD_ID128_NULL;
|
||||||
sd_id128_t uuid = SD_ID128_NULL;
|
|
||||||
int r, k;
|
int r, k;
|
||||||
|
|
||||||
r = acquire_esp(geteuid() != 0, NULL, NULL, NULL, &uuid);
|
r = acquire_esp(geteuid() != 0, NULL, NULL, NULL, &esp_uuid);
|
||||||
|
if (arg_print_esp_path) {
|
||||||
if (arg_print_path) {
|
|
||||||
if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only
|
if (r == -EACCES) /* If we couldn't acquire the ESP path, log about access errors (which is the only
|
||||||
* error the find_esp_and_warn() won't log on its own) */
|
* error the find_esp_and_warn() won't log on its own) */
|
||||||
return log_error_errno(r, "Failed to determine ESP: %m");
|
return log_error_errno(r, "Failed to determine ESP location: %m");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
puts(arg_path);
|
puts(arg_esp_path);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r = acquire_xbootldr(geteuid() != 0, &xbootldr_uuid);
|
||||||
|
if (arg_print_dollar_boot_path) {
|
||||||
|
if (r == -EACCES)
|
||||||
|
return log_error_errno(r, "Failed to determine XBOOTLDR location: %m");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
puts(arg_dollar_boot_path());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg_print_esp_path || arg_print_dollar_boot_path)
|
||||||
|
return 0;
|
||||||
|
|
||||||
r = 0; /* If we couldn't determine the path, then don't consider that a problem from here on, just show what we
|
r = 0; /* If we couldn't determine the path, then don't consider that a problem from here on, just show what we
|
||||||
* can show */
|
* can show */
|
||||||
|
|
||||||
@@ -1038,8 +1125,8 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
} else
|
} else
|
||||||
printf("System:\n Not booted with EFI\n\n");
|
printf("System:\n Not booted with EFI\n\n");
|
||||||
|
|
||||||
if (arg_path) {
|
if (arg_esp_path) {
|
||||||
k = status_binaries(arg_path, uuid);
|
k = status_binaries(arg_esp_path, esp_uuid);
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
r = k;
|
r = k;
|
||||||
}
|
}
|
||||||
@@ -1050,8 +1137,8 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
r = k;
|
r = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_path) {
|
if (arg_esp_path || arg_xbootldr_path) {
|
||||||
k = status_entries(arg_path, uuid);
|
k = status_entries(arg_esp_path, arg_xbootldr_path);
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
r = k;
|
r = k;
|
||||||
}
|
}
|
||||||
@@ -1062,20 +1149,25 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
static int verb_list(int argc, char *argv[], void *userdata) {
|
static int verb_list(int argc, char *argv[], void *userdata) {
|
||||||
_cleanup_(boot_config_free) BootConfig config = {};
|
_cleanup_(boot_config_free) BootConfig config = {};
|
||||||
_cleanup_free_ char **found_by_loader = NULL;
|
_cleanup_free_ char **found_by_loader = NULL;
|
||||||
sd_id128_t uuid = SD_ID128_NULL;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
|
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
|
||||||
* off logging about access errors and turn off potentially privileged device probing. Here we're interested in
|
* off logging about access errors and turn off potentially privileged device probing. Here we're interested in
|
||||||
* the latter but not the former, hence request the mode, and log about EACCES. */
|
* the latter but not the former, hence request the mode, and log about EACCES. */
|
||||||
|
|
||||||
r = acquire_esp(geteuid() != 0, NULL, NULL, NULL, &uuid);
|
r = acquire_esp(geteuid() != 0, NULL, NULL, NULL, NULL);
|
||||||
if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */
|
if (r == -EACCES) /* We really need the ESP path for this call, hence also log about access errors */
|
||||||
return log_error_errno(r, "Failed to determine ESP: %m");
|
return log_error_errno(r, "Failed to determine ESP: %m");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = boot_entries_load_config(arg_path, NULL, &config);
|
r = acquire_xbootldr(geteuid() != 0, NULL);
|
||||||
|
if (r == -EACCES)
|
||||||
|
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = boot_entries_load_config(arg_esp_path, arg_xbootldr_path, &config);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@@ -1115,24 +1207,25 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sync_esp(void) {
|
static int sync_everything(void) {
|
||||||
_cleanup_close_ int fd = -1;
|
int ret = 0, k;
|
||||||
|
|
||||||
if (!arg_path)
|
if (arg_esp_path) {
|
||||||
return 0;
|
k = syncfs_path(AT_FDCWD, arg_esp_path);
|
||||||
|
if (k < 0)
|
||||||
|
ret = log_error_errno(k, "Failed to synchronize the ESP '%s': %m", arg_esp_path);
|
||||||
|
}
|
||||||
|
|
||||||
fd = open(arg_path, O_CLOEXEC|O_DIRECTORY|O_RDONLY);
|
if (arg_xbootldr_path) {
|
||||||
if (fd < 0)
|
k = syncfs_path(AT_FDCWD, arg_xbootldr_path);
|
||||||
return log_error_errno(errno, "Couldn't open ESP '%s' for synchronization: %m", arg_path);
|
if (k < 0)
|
||||||
|
ret = log_error_errno(k, "Failed to synchronize $BOOT '%s': %m", arg_xbootldr_path);
|
||||||
|
}
|
||||||
|
|
||||||
if (syncfs(fd) < 0)
|
return ret;
|
||||||
return log_error_errno(errno, "Failed to synchronize the ESP '%s': %m", arg_path);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int verb_install(int argc, char *argv[], void *userdata) {
|
static int verb_install(int argc, char *argv[], void *userdata) {
|
||||||
|
|
||||||
sd_id128_t uuid = SD_ID128_NULL;
|
sd_id128_t uuid = SD_ID128_NULL;
|
||||||
uint64_t pstart = 0, psize = 0;
|
uint64_t pstart = 0, psize = 0;
|
||||||
uint32_t part = 0;
|
uint32_t part = 0;
|
||||||
@@ -1143,24 +1236,41 @@ static int verb_install(int argc, char *argv[], void *userdata) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
r = acquire_xbootldr(false, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
install = streq(argv[0], "install");
|
install = streq(argv[0], "install");
|
||||||
|
|
||||||
RUN_WITH_UMASK(0002) {
|
RUN_WITH_UMASK(0002) {
|
||||||
r = install_binaries(arg_path, install);
|
if (install) {
|
||||||
|
/* Don't create any of these directories when we are just updating. When we update
|
||||||
|
* we'll drop-in our files (unless there are newer ones already), but we won't create
|
||||||
|
* the directories for them in the first place. */
|
||||||
|
r = create_esp_subdirs(arg_esp_path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = install_binaries(arg_esp_path, install);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (install) {
|
if (install) {
|
||||||
r = install_loader_config(arg_path);
|
r = install_loader_config(arg_esp_path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = install_entries_directory(arg_dollar_boot_path());
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) sync_esp();
|
(void) sync_everything();
|
||||||
|
|
||||||
if (arg_touch_variables)
|
if (arg_touch_variables)
|
||||||
r = install_variables(arg_path,
|
r = install_variables(arg_esp_path,
|
||||||
part, pstart, psize, uuid,
|
part, pstart, psize, uuid,
|
||||||
"/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
|
"/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi",
|
||||||
install);
|
install);
|
||||||
@@ -1170,21 +1280,35 @@ static int verb_install(int argc, char *argv[], void *userdata) {
|
|||||||
|
|
||||||
static int verb_remove(int argc, char *argv[], void *userdata) {
|
static int verb_remove(int argc, char *argv[], void *userdata) {
|
||||||
sd_id128_t uuid = SD_ID128_NULL;
|
sd_id128_t uuid = SD_ID128_NULL;
|
||||||
int r;
|
int r, q;
|
||||||
|
|
||||||
r = acquire_esp(false, NULL, NULL, NULL, &uuid);
|
r = acquire_esp(false, NULL, NULL, NULL, &uuid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = remove_binaries(arg_path);
|
r = acquire_xbootldr(false, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
(void) sync_esp();
|
r = remove_binaries(arg_esp_path);
|
||||||
|
|
||||||
|
q = remove_loader_config(arg_esp_path);
|
||||||
|
if (q < 0 && r >= 0)
|
||||||
|
r = q;
|
||||||
|
|
||||||
|
q = remove_entries_directory(arg_dollar_boot_path());
|
||||||
|
if (q < 0 && r >= 0)
|
||||||
|
r = q;
|
||||||
|
|
||||||
|
q = remove_esp_subdirs(arg_esp_path);
|
||||||
|
if (q < 0 && r >= 0)
|
||||||
|
r = q;
|
||||||
|
|
||||||
|
(void) sync_everything();
|
||||||
|
|
||||||
if (arg_touch_variables) {
|
if (arg_touch_variables) {
|
||||||
int q;
|
|
||||||
|
|
||||||
q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
|
q = remove_variables(uuid, "/EFI/systemd/systemd-boot" EFI_MACHINE_TYPE_NAME ".efi", true);
|
||||||
if (q < 0 && r == 0)
|
if (q < 0 && r >= 0)
|
||||||
r = q;
|
r = q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user