mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
bootctl: add --root and --image
Operate on image/directory, and also take files to install from it
This commit is contained in:
parent
99080ed3f0
commit
80a2381d5c
@ -237,6 +237,27 @@
|
|||||||
Loader partition to <filename>/boot/</filename>, if possible.</para></listitem>
|
Loader partition to <filename>/boot/</filename>, if possible.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--root=<replaceable>root</replaceable></option></term>
|
||||||
|
<listitem><para>Takes a directory path as an argument. All
|
||||||
|
paths will be prefixed with the given alternate
|
||||||
|
<replaceable>root</replaceable> path, including config search
|
||||||
|
paths. </para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--image=<replaceable>image</replaceable></option></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a path to a disk image file or block device node. If specified all operations
|
||||||
|
are applied to file system in the indicated disk image. This is similar to <option>--root=</option>
|
||||||
|
but operates on file systems stored in disk images or block devices. The disk image should either
|
||||||
|
contain just a file system or a set of file systems within a GPT partition table, following the
|
||||||
|
<ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions
|
||||||
|
Specification</ulink>. For further information on supported disk images, see
|
||||||
|
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||||
|
switch of the same name.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-p</option></term>
|
<term><option>-p</option></term>
|
||||||
<term><option>--print-esp-path</option></term>
|
<term><option>--print-esp-path</option></term>
|
||||||
|
@ -32,7 +32,7 @@ _bootctl() {
|
|||||||
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
|
local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||||
local -A OPTS=(
|
local -A OPTS=(
|
||||||
[STANDALONE]='-h --help -p --print-esp-path -x --print-boot-path --version --no-variables --no-pager --graceful'
|
[STANDALONE]='-h --help -p --print-esp-path -x --print-boot-path --version --no-variables --no-pager --graceful'
|
||||||
[ARG]='--esp-path --boot-path --make-machine-id-directory'
|
[ARG]='--esp-path --boot-path --make-machine-id-directory --root --image'
|
||||||
)
|
)
|
||||||
|
|
||||||
if __contains_word "$prev" ${OPTS[ARG]}; then
|
if __contains_word "$prev" ${OPTS[ARG]}; then
|
||||||
@ -48,6 +48,10 @@ _bootctl() {
|
|||||||
--make-machine-id-directory)
|
--make-machine-id-directory)
|
||||||
comps="yes no auto"
|
comps="yes no auto"
|
||||||
;;
|
;;
|
||||||
|
--image|--root)
|
||||||
|
compopt -o nospace
|
||||||
|
comps=$( compgen -A file -- "$cur" )
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
|
||||||
return 0
|
return 0
|
||||||
|
@ -73,4 +73,6 @@ _arguments \
|
|||||||
'--no-variables[Do not touch EFI variables]' \
|
'--no-variables[Do not touch EFI variables]' \
|
||||||
'--no-pager[Do not pipe output into a pager]' \
|
'--no-pager[Do not pipe output into a pager]' \
|
||||||
'--graceful[Do not fail when locating ESP or writing fails]' \
|
'--graceful[Do not fail when locating ESP or writing fails]' \
|
||||||
|
'--root=[Operate under the specified directory]:PATH' \
|
||||||
|
'--image=[Operate on the specified image]:PATH' \
|
||||||
'*::bootctl command:_bootctl_commands'
|
'*::bootctl command:_bootctl_commands'
|
||||||
|
@ -108,11 +108,11 @@ static int acquire_path(void) {
|
|||||||
if (!strv_isempty(arg_path))
|
if (!strv_isempty(arg_path))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = find_esp_and_warn(NULL, /* unprivileged_mode= */ false, &esp_path, NULL, NULL, NULL, NULL, &esp_devid);
|
r = find_esp_and_warn(NULL, NULL, /* unprivileged_mode= */ false, &esp_path, NULL, NULL, NULL, NULL, &esp_devid);
|
||||||
if (r < 0 && r != -ENOKEY) /* ENOKEY means not found, and is the only error the function won't log about on its own */
|
if (r < 0 && r != -ENOKEY) /* ENOKEY means not found, and is the only error the function won't log about on its own */
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = find_xbootldr_and_warn(NULL, /* unprivileged_mode= */ false, &xbootldr_path, NULL, &xbootldr_devid);
|
r = find_xbootldr_and_warn(NULL, NULL, /* unprivileged_mode= */ false, &xbootldr_path, NULL, &xbootldr_devid);
|
||||||
if (r < 0 && r != -ENOKEY)
|
if (r < 0 && r != -ENOKEY)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -15,9 +15,11 @@
|
|||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "blkid-util.h"
|
#include "blkid-util.h"
|
||||||
#include "bootspec.h"
|
#include "bootspec.h"
|
||||||
|
#include "chase-symlinks.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
#include "devnum-util.h"
|
#include "devnum-util.h"
|
||||||
#include "dirent-util.h"
|
#include "dirent-util.h"
|
||||||
|
#include "dissect-image.h"
|
||||||
#include "efi-api.h"
|
#include "efi-api.h"
|
||||||
#include "efi-loader.h"
|
#include "efi-loader.h"
|
||||||
#include "efivars.h"
|
#include "efivars.h"
|
||||||
@ -31,6 +33,7 @@
|
|||||||
#include "glyph-util.h"
|
#include "glyph-util.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "mkdir.h"
|
#include "mkdir.h"
|
||||||
|
#include "mount-util.h"
|
||||||
#include "os-util.h"
|
#include "os-util.h"
|
||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
#include "parse-argument.h"
|
#include "parse-argument.h"
|
||||||
@ -75,11 +78,15 @@ static enum {
|
|||||||
static char *arg_entry_token = NULL;
|
static char *arg_entry_token = NULL;
|
||||||
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
|
||||||
static bool arg_arch_all = false;
|
static bool arg_arch_all = false;
|
||||||
|
static char *arg_root = NULL;
|
||||||
|
static char *arg_image = NULL;
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_esp_path, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_xbootldr_path, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_install_layout, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_install_layout, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_entry_token, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_entry_token, freep);
|
||||||
|
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||||
|
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
|
||||||
|
|
||||||
static const char *arg_dollar_boot_path(void) {
|
static const char *arg_dollar_boot_path(void) {
|
||||||
/* $BOOT shall be the XBOOTLDR partition if it exists, and otherwise the ESP */
|
/* $BOOT shall be the XBOOTLDR partition if it exists, and otherwise the ESP */
|
||||||
@ -104,7 +111,7 @@ static int acquire_esp(
|
|||||||
* we simply eat up the error here, so that --list and --status work too, without noise about
|
* we simply eat up the error here, so that --list and --status work too, without noise about
|
||||||
* this). */
|
* this). */
|
||||||
|
|
||||||
r = find_esp_and_warn(arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
|
r = find_esp_and_warn(arg_root, arg_esp_path, unprivileged_mode, &np, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
|
||||||
if (r == -ENOKEY) {
|
if (r == -ENOKEY) {
|
||||||
if (graceful)
|
if (graceful)
|
||||||
return log_full_errno(arg_quiet ? LOG_DEBUG : LOG_INFO, r,
|
return log_full_errno(arg_quiet ? LOG_DEBUG : LOG_INFO, r,
|
||||||
@ -131,7 +138,7 @@ static int acquire_xbootldr(
|
|||||||
char *np;
|
char *np;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = find_xbootldr_and_warn(arg_xbootldr_path, unprivileged_mode, &np, ret_uuid, ret_devid);
|
r = find_xbootldr_and_warn(arg_root, arg_xbootldr_path, unprivileged_mode, &np, ret_uuid, ret_devid);
|
||||||
if (r == -ENOKEY) {
|
if (r == -ENOKEY) {
|
||||||
log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
|
log_debug_errno(r, "Didn't find an XBOOTLDR partition, using the ESP as $BOOT.");
|
||||||
arg_xbootldr_path = mfree(arg_xbootldr_path);
|
arg_xbootldr_path = mfree(arg_xbootldr_path);
|
||||||
@ -596,7 +603,6 @@ static int boot_config_load_and_select(
|
|||||||
const char *xbootldr_path,
|
const char *xbootldr_path,
|
||||||
dev_t xbootldr_devid) {
|
dev_t xbootldr_devid) {
|
||||||
|
|
||||||
_cleanup_strv_free_ char **efi_entries = NULL;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would
|
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would
|
||||||
@ -607,15 +613,19 @@ static int boot_config_load_and_select(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = efi_loader_get_entries(&efi_entries);
|
if (!arg_root) {
|
||||||
if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
|
_cleanup_strv_free_ char **efi_entries = NULL;
|
||||||
log_debug_errno(r, "Boot loader reported no entries.");
|
|
||||||
else if (r < 0)
|
|
||||||
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
|
|
||||||
else
|
|
||||||
(void) boot_config_augment_from_loader(config, efi_entries, /* only_auto= */ false);
|
|
||||||
|
|
||||||
return boot_config_select_special_entries(config);
|
r = efi_loader_get_entries(&efi_entries);
|
||||||
|
if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
|
||||||
|
log_debug_errno(r, "Boot loader reported no entries.");
|
||||||
|
else if (r < 0)
|
||||||
|
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
|
||||||
|
else
|
||||||
|
(void) boot_config_augment_from_loader(config, efi_entries, /* only_auto= */ false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return boot_config_select_special_entries(config, /* skip_efivars= */ !!arg_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int status_entries(
|
static int status_entries(
|
||||||
@ -833,48 +843,74 @@ static int create_subdirs(const char *root, const char * const *subdirs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int copy_one_file(const char *esp_path, const char *name, bool force) {
|
static int copy_one_file(const char *esp_path, const char *name, bool force) {
|
||||||
|
_cleanup_free_ char *source_path = NULL, *dest_path = NULL, *p = NULL, *q = NULL;
|
||||||
const char *e;
|
const char *e;
|
||||||
char *p, *q, *dest_name, *s;
|
char *dest_name, *s;
|
||||||
int r;
|
int r, ret;
|
||||||
|
|
||||||
dest_name = strdupa_safe(name);
|
dest_name = strdupa_safe(name);
|
||||||
s = endswith_no_case(dest_name, ".signed");
|
s = endswith_no_case(dest_name, ".signed");
|
||||||
if (s)
|
if (s)
|
||||||
*s = 0;
|
*s = 0;
|
||||||
|
|
||||||
p = strjoina(BOOTLIBDIR "/", name);
|
p = path_join(BOOTLIBDIR, name);
|
||||||
q = strjoina(esp_path, "/EFI/systemd/", dest_name);
|
if (!p)
|
||||||
r = copy_file_with_version_check(p, q, force);
|
return log_oom();
|
||||||
|
|
||||||
|
r = chase_symlinks(p, arg_root, CHASE_PREFIX_ROOT, &source_path, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r,
|
||||||
|
"Failed to resolve path %s%s%s: %m",
|
||||||
|
p,
|
||||||
|
arg_root ? " under directory " : "",
|
||||||
|
arg_root ? arg_root : "");
|
||||||
|
|
||||||
|
q = path_join("/EFI/systemd/", dest_name);
|
||||||
|
if (!q)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = chase_symlinks(q, esp_path, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, &dest_path, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", q, esp_path);
|
||||||
|
|
||||||
|
/* Note that if this fails we do the second copy anyway, but return this error code,
|
||||||
|
* so we stash it away in a separate variable. */
|
||||||
|
ret = copy_file_with_version_check(source_path, dest_path, force);
|
||||||
|
|
||||||
e = startswith(dest_name, "systemd-boot");
|
e = startswith(dest_name, "systemd-boot");
|
||||||
if (e) {
|
if (e) {
|
||||||
int k;
|
_cleanup_free_ char *default_dest_path = NULL;
|
||||||
char *v;
|
char *v;
|
||||||
|
|
||||||
/* Create the EFI default boot loader name (specified for removable devices) */
|
/* Create the EFI default boot loader name (specified for removable devices) */
|
||||||
v = strjoina(esp_path, "/EFI/BOOT/BOOT", e);
|
v = strjoina("/EFI/BOOT/BOOT", e);
|
||||||
ascii_strupper(strrchr(v, '/') + 1);
|
ascii_strupper(strrchr(v, '/') + 1);
|
||||||
|
|
||||||
k = copy_file_with_version_check(p, v, force);
|
r = chase_symlinks(v, esp_path, CHASE_PREFIX_ROOT | CHASE_NONEXISTENT, &default_dest_path, NULL);
|
||||||
if (k < 0 && r == 0)
|
if (r < 0)
|
||||||
r = k;
|
return log_error_errno(r, "Failed to resolve path %s under directory %s: %m", v, esp_path);
|
||||||
|
|
||||||
|
r = copy_file_with_version_check(source_path, default_dest_path, force);
|
||||||
|
if (r < 0 && ret == 0)
|
||||||
|
ret = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int install_binaries(const char *esp_path, const char *arch, bool force) {
|
static int install_binaries(const char *esp_path, const char *arch, bool force) {
|
||||||
_cleanup_closedir_ DIR *d = NULL;
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
int r = 0;
|
_cleanup_free_ char *path = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
d = opendir(BOOTLIBDIR);
|
r = chase_symlinks_and_opendir(BOOTLIBDIR, arg_root, CHASE_PREFIX_ROOT, &path, &d);
|
||||||
if (!d)
|
if (r < 0)
|
||||||
return log_error_errno(errno, "Failed to open \""BOOTLIBDIR"\": %m");
|
return log_error_errno(r, "Failed to open boot loader directory %s: %m", BOOTLIBDIR);
|
||||||
|
|
||||||
const char *suffix = strjoina(arch, ".efi");
|
const char *suffix = strjoina(arch, ".efi");
|
||||||
const char *suffix_signed = strjoina(arch, ".efi.signed");
|
const char *suffix_signed = strjoina(arch, ".efi.signed");
|
||||||
|
|
||||||
FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read \""BOOTLIBDIR"\": %m")) {
|
FOREACH_DIRENT(de, d, return log_error_errno(errno, "Failed to read \"%s\": %m", path)) {
|
||||||
int k;
|
int k;
|
||||||
|
|
||||||
if (!endswith_no_case(de->d_name, suffix) && !endswith_no_case(de->d_name, suffix_signed))
|
if (!endswith_no_case(de->d_name, suffix) && !endswith_no_case(de->d_name, suffix_signed))
|
||||||
@ -1022,6 +1058,12 @@ static int install_variables(const char *esp_path,
|
|||||||
uint16_t slot;
|
uint16_t slot;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if (arg_root) {
|
||||||
|
log_info("Acting on %s, skipping EFI variable setup.",
|
||||||
|
arg_image ? "image" : "root directory");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_efi_boot()) {
|
if (!is_efi_boot()) {
|
||||||
log_warning("Not booted with EFI, skipping EFI variable setup.");
|
log_warning("Not booted with EFI, skipping EFI variable setup.");
|
||||||
return 0;
|
return 0;
|
||||||
@ -1178,7 +1220,7 @@ static int remove_variables(sd_id128_t uuid, const char *path, bool in_order) {
|
|||||||
uint16_t slot;
|
uint16_t slot;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (!is_efi_boot())
|
if (arg_root || !is_efi_boot())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = find_slot(uuid, path, &slot);
|
r = find_slot(uuid, path, &slot);
|
||||||
@ -1350,6 +1392,8 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||||||
" --version Print version\n"
|
" --version Print version\n"
|
||||||
" --esp-path=PATH Path to the EFI System Partition (ESP)\n"
|
" --esp-path=PATH Path to the EFI System Partition (ESP)\n"
|
||||||
" --boot-path=PATH Path to the $BOOT partition\n"
|
" --boot-path=PATH Path to the $BOOT partition\n"
|
||||||
|
" --root=PATH Operate on an alternate filesystem root\n"
|
||||||
|
" --image=PATH Operate on disk image as filesystem root\n"
|
||||||
" -p --print-esp-path Print path to the EFI System Partition\n"
|
" -p --print-esp-path Print path to the EFI System Partition\n"
|
||||||
" -x --print-boot-path Print path to the $BOOT partition\n"
|
" -x --print-boot-path Print path to the $BOOT partition\n"
|
||||||
" --no-variables Don't touch EFI variables\n"
|
" --no-variables Don't touch EFI variables\n"
|
||||||
@ -1380,6 +1424,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
enum {
|
enum {
|
||||||
ARG_ESP_PATH = 0x100,
|
ARG_ESP_PATH = 0x100,
|
||||||
ARG_BOOT_PATH,
|
ARG_BOOT_PATH,
|
||||||
|
ARG_ROOT,
|
||||||
|
ARG_IMAGE,
|
||||||
ARG_VERSION,
|
ARG_VERSION,
|
||||||
ARG_NO_VARIABLES,
|
ARG_NO_VARIABLES,
|
||||||
ARG_NO_PAGER,
|
ARG_NO_PAGER,
|
||||||
@ -1396,6 +1442,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
{ "esp-path", required_argument, NULL, ARG_ESP_PATH },
|
{ "esp-path", required_argument, NULL, ARG_ESP_PATH },
|
||||||
{ "path", required_argument, NULL, ARG_ESP_PATH }, /* Compatibility alias */
|
{ "path", required_argument, NULL, ARG_ESP_PATH }, /* Compatibility alias */
|
||||||
{ "boot-path", required_argument, NULL, ARG_BOOT_PATH },
|
{ "boot-path", required_argument, NULL, ARG_BOOT_PATH },
|
||||||
|
{ "root", required_argument, NULL, ARG_ROOT },
|
||||||
|
{ "image", required_argument, NULL, ARG_IMAGE },
|
||||||
{ "print-esp-path", no_argument, NULL, 'p' },
|
{ "print-esp-path", no_argument, NULL, 'p' },
|
||||||
{ "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */
|
{ "print-path", no_argument, NULL, 'p' }, /* Compatibility alias */
|
||||||
{ "print-boot-path", no_argument, NULL, 'x' },
|
{ "print-boot-path", no_argument, NULL, 'x' },
|
||||||
@ -1439,6 +1487,18 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_ROOT:
|
||||||
|
r = parse_path_argument(optarg, /* suppress_root= */ true, &arg_root);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_IMAGE:
|
||||||
|
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_image);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if (arg_print_dollar_boot_path)
|
if (arg_print_dollar_boot_path)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
@ -1523,6 +1583,15 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((arg_root || arg_image) && argv[optind] && !STR_IN_SET(argv[optind], "status", "list",
|
||||||
|
"install", "update", "remove", "is-installed", "random-seed"))
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
|
"Options --root= and --image= are not supported with verb %s.",
|
||||||
|
argv[optind]);
|
||||||
|
|
||||||
|
if (arg_root && arg_image)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1608,7 +1677,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
|
|
||||||
pager_open(arg_pager_flags);
|
pager_open(arg_pager_flags);
|
||||||
|
|
||||||
if (is_efi_boot()) {
|
if (!arg_root && is_efi_boot()) {
|
||||||
static const struct {
|
static const struct {
|
||||||
uint64_t flag;
|
uint64_t flag;
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -1722,7 +1791,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
r = k;
|
r = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_efi_boot()) {
|
if (!arg_root && is_efi_boot()) {
|
||||||
k = status_variables();
|
k = status_variables();
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
r = k;
|
r = k;
|
||||||
@ -1846,6 +1915,12 @@ static int install_random_seed(const char *esp) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg_root) {
|
||||||
|
log_warning("Acting on %s, skipping EFI variable setup.",
|
||||||
|
arg_image ? "image" : "root directory");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
r = getenv_bool("SYSTEMD_WRITE_SYSTEM_TOKEN");
|
r = getenv_bool("SYSTEMD_WRITE_SYSTEM_TOKEN");
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (r != -ENXIO)
|
if (r != -ENXIO)
|
||||||
@ -2204,6 +2279,11 @@ static int parse_loader_entry_target_arg(const char *arg1, char16_t **ret_target
|
|||||||
static int verb_set_efivar(int argc, char *argv[], void *userdata) {
|
static int verb_set_efivar(int argc, char *argv[], void *userdata) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if (arg_root)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
|
"Acting on %s, skipping EFI variable setup.",
|
||||||
|
arg_image ? "image" : "root directory");
|
||||||
|
|
||||||
if (!is_efi_boot())
|
if (!is_efi_boot())
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
"Not booted with UEFI.");
|
"Not booted with UEFI.");
|
||||||
@ -2267,7 +2347,7 @@ static int verb_set_efivar(int argc, char *argv[], void *userdata) {
|
|||||||
static int verb_random_seed(int argc, char *argv[], void *userdata) {
|
static int verb_random_seed(int argc, char *argv[], void *userdata) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = find_esp_and_warn(arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL, NULL);
|
r = find_esp_and_warn(arg_root, arg_esp_path, false, &arg_esp_path, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (r == -ENOKEY) {
|
if (r == -ENOKEY) {
|
||||||
/* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
|
/* find_esp_and_warn() doesn't warn about ENOKEY, so let's do that on our own */
|
||||||
if (!arg_graceful)
|
if (!arg_graceful)
|
||||||
@ -2375,6 +2455,9 @@ static int bootctl_main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int run(int argc, char *argv[]) {
|
static int run(int argc, char *argv[]) {
|
||||||
|
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||||
|
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
|
||||||
|
_cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
log_parse_environment();
|
log_parse_environment();
|
||||||
@ -2388,6 +2471,25 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
/* Open up and mount the image */
|
||||||
|
if (arg_image) {
|
||||||
|
assert(!arg_root);
|
||||||
|
|
||||||
|
r = mount_image_privately_interactively(
|
||||||
|
arg_image,
|
||||||
|
DISSECT_IMAGE_GENERIC_ROOT |
|
||||||
|
DISSECT_IMAGE_RELAX_VAR_CHECK,
|
||||||
|
&unlink_dir,
|
||||||
|
&loop_device,
|
||||||
|
&decrypted_image);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
arg_root = strdup(unlink_dir);
|
||||||
|
if (!arg_root)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
return bootctl_main(argc, argv);
|
return bootctl_main(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
|
|
||||||
assert_se(boot_config_finalize(&config) >= 0);
|
assert_se(boot_config_finalize(&config) >= 0);
|
||||||
|
|
||||||
(void) boot_config_select_special_entries(&config);
|
(void) boot_config_select_special_entries(&config, /* skip_efivars= */ false);
|
||||||
|
|
||||||
_cleanup_close_ int orig_stdout_fd = -1;
|
_cleanup_close_ int orig_stdout_fd = -1;
|
||||||
if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) {
|
if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) {
|
||||||
|
@ -840,12 +840,12 @@ static int boot_entries_select_selected(const BootConfig *config) {
|
|||||||
return boot_config_find(config, config->entry_selected);
|
return boot_config_find(config, config->entry_selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int boot_load_efi_entry_pointers(BootConfig *config) {
|
static int boot_load_efi_entry_pointers(BootConfig *config, bool skip_efivars) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(config);
|
assert(config);
|
||||||
|
|
||||||
if (!is_efi_boot())
|
if (skip_efivars || !is_efi_boot())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Loads the three "pointers" to boot loader entries from their EFI variables */
|
/* Loads the three "pointers" to boot loader entries from their EFI variables */
|
||||||
@ -871,12 +871,12 @@ static int boot_load_efi_entry_pointers(BootConfig *config) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int boot_config_select_special_entries(BootConfig *config) {
|
int boot_config_select_special_entries(BootConfig *config, bool skip_efivars) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(config);
|
assert(config);
|
||||||
|
|
||||||
r = boot_load_efi_entry_pointers(config);
|
r = boot_load_efi_entry_pointers(config, skip_efivars);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -967,11 +967,11 @@ int boot_config_load_auto(
|
|||||||
"Failed to determine whether /run/boot-loader-entries/ exists: %m");
|
"Failed to determine whether /run/boot-loader-entries/ exists: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
r = find_esp_and_warn(override_esp_path, /* unprivileged_mode= */ false, &esp_where, NULL, NULL, NULL, NULL, &esp_devid);
|
r = find_esp_and_warn(NULL, override_esp_path, /* unprivileged_mode= */ false, &esp_where, NULL, NULL, NULL, NULL, &esp_devid);
|
||||||
if (r < 0) /* we don't log about ENOKEY here, but propagate it, leaving it to the caller to log */
|
if (r < 0) /* we don't log about ENOKEY here, but propagate it, leaving it to the caller to log */
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = find_xbootldr_and_warn(override_xbootldr_path, /* unprivileged_mode= */ false, &xbootldr_where, NULL, &xbootldr_devid);
|
r = find_xbootldr_and_warn(NULL, override_xbootldr_path, /* unprivileged_mode= */ false, &xbootldr_where, NULL, &xbootldr_devid);
|
||||||
if (r < 0 && r != -ENOKEY)
|
if (r < 0 && r != -ENOKEY)
|
||||||
return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */
|
return r; /* It's fine if the XBOOTLDR partition doesn't exist, hence we ignore ENOKEY here */
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ int boot_config_load(BootConfig *config, const char *esp_path, const char *xboot
|
|||||||
int boot_config_load_auto(BootConfig *config, const char *override_esp_path, const char *override_xbootldr_path);
|
int boot_config_load_auto(BootConfig *config, const char *override_esp_path, const char *override_xbootldr_path);
|
||||||
int boot_config_augment_from_loader(BootConfig *config, char **list, bool only_auto);
|
int boot_config_augment_from_loader(BootConfig *config, char **list, bool only_auto);
|
||||||
|
|
||||||
int boot_config_select_special_entries(BootConfig *config);
|
int boot_config_select_special_entries(BootConfig *config, bool skip_efivars);
|
||||||
|
|
||||||
static inline const char* boot_entry_title(const BootEntry *entry) {
|
static inline const char* boot_entry_title(const BootEntry *entry) {
|
||||||
assert(entry);
|
assert(entry);
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "blkid-util.h"
|
#include "blkid-util.h"
|
||||||
|
#include "chase-symlinks.h"
|
||||||
#include "device-util.h"
|
#include "device-util.h"
|
||||||
#include "devnum-util.h"
|
#include "devnum-util.h"
|
||||||
#include "env-util.h"
|
#include "env-util.h"
|
||||||
@ -20,6 +21,12 @@
|
|||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "virt.h"
|
#include "virt.h"
|
||||||
|
|
||||||
|
typedef enum VerifyESPFlags {
|
||||||
|
VERIFY_ESP_SEARCHING = 1 << 0, /* Downgrade various "not found" logs to debug level */
|
||||||
|
VERIFY_ESP_UNPRIVILEGED_MODE = 1 << 1, /* Call into udev rather than blkid */
|
||||||
|
VERIFY_ESP_RELAX_CHECKS = 1 << 2, /* Do not validate ESP partition */
|
||||||
|
} VerifyESPFlags;
|
||||||
|
|
||||||
static int verify_esp_blkid(
|
static int verify_esp_blkid(
|
||||||
dev_t devid,
|
dev_t devid,
|
||||||
bool searching,
|
bool searching,
|
||||||
@ -298,15 +305,15 @@ static int verify_fsroot_dir(
|
|||||||
|
|
||||||
static int verify_esp(
|
static int verify_esp(
|
||||||
const char *p,
|
const char *p,
|
||||||
bool searching,
|
|
||||||
bool unprivileged_mode,
|
|
||||||
uint32_t *ret_part,
|
uint32_t *ret_part,
|
||||||
uint64_t *ret_pstart,
|
uint64_t *ret_pstart,
|
||||||
uint64_t *ret_psize,
|
uint64_t *ret_psize,
|
||||||
sd_id128_t *ret_uuid,
|
sd_id128_t *ret_uuid,
|
||||||
dev_t *ret_devid) {
|
dev_t *ret_devid,
|
||||||
|
VerifyESPFlags flags) {
|
||||||
|
|
||||||
bool relax_checks;
|
bool relax_checks, searching = FLAGS_SET(flags, VERIFY_ESP_SEARCHING),
|
||||||
|
unprivileged_mode = FLAGS_SET(flags, VERIFY_ESP_UNPRIVILEGED_MODE);
|
||||||
dev_t devid;
|
dev_t devid;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -319,7 +326,7 @@ static int verify_esp(
|
|||||||
* -EACESS → if 'unprivileged_mode' is set, and we have trouble accessing the thing
|
* -EACESS → if 'unprivileged_mode' is set, and we have trouble accessing the thing
|
||||||
*/
|
*/
|
||||||
|
|
||||||
relax_checks = getenv_bool("SYSTEMD_RELAX_ESP_CHECKS") > 0;
|
relax_checks = getenv_bool("SYSTEMD_RELAX_ESP_CHECKS") > 0 || FLAGS_SET(flags, VERIFY_ESP_RELAX_CHECKS);
|
||||||
|
|
||||||
/* Non-root user can only check the status, so if an error occurred in the following, it does not cause any
|
/* Non-root user can only check the status, so if an error occurred in the following, it does not cause any
|
||||||
* issues. Let's also, silence the error messages. */
|
* issues. Let's also, silence the error messages. */
|
||||||
@ -381,6 +388,7 @@ finish:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int find_esp_and_warn(
|
int find_esp_and_warn(
|
||||||
|
const char *root,
|
||||||
const char *path,
|
const char *path,
|
||||||
bool unprivileged_mode,
|
bool unprivileged_mode,
|
||||||
char **ret_path,
|
char **ret_path,
|
||||||
@ -390,6 +398,9 @@ int find_esp_and_warn(
|
|||||||
sd_id128_t *ret_uuid,
|
sd_id128_t *ret_uuid,
|
||||||
dev_t *ret_devid) {
|
dev_t *ret_devid) {
|
||||||
|
|
||||||
|
VerifyESPFlags flags = (unprivileged_mode ? VERIFY_ESP_UNPRIVILEGED_MODE : 0) |
|
||||||
|
(root ? VERIFY_ESP_RELAX_CHECKS : 0);
|
||||||
|
_cleanup_free_ char *p = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* This logs about all errors except:
|
/* This logs about all errors except:
|
||||||
@ -399,7 +410,15 @@ int find_esp_and_warn(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
r = verify_esp(path, /* searching= */ false, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
|
r = chase_symlinks(path, root, CHASE_PREFIX_ROOT, &p, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r,
|
||||||
|
"Failed to resolve path %s%s%s: %m",
|
||||||
|
path,
|
||||||
|
root ? " under directory " : "",
|
||||||
|
root ?: "");
|
||||||
|
|
||||||
|
r = verify_esp(p, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid, flags);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -410,19 +429,27 @@ int find_esp_and_warn(
|
|||||||
if (path) {
|
if (path) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (!path_is_valid(path) || !path_is_absolute(path))
|
r = chase_symlinks(path, root, CHASE_PREFIX_ROOT, &p, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r,
|
||||||
|
"Failed to resolve path %s%s%s: %m",
|
||||||
|
path,
|
||||||
|
root ? " under directory " : "",
|
||||||
|
root ?: "");
|
||||||
|
|
||||||
|
if (!path_is_valid(p) || !path_is_absolute(p))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"$SYSTEMD_ESP_PATH does not refer to absolute path, refusing to use it: %s",
|
"$SYSTEMD_ESP_PATH does not refer to absolute path, refusing to use it: %s",
|
||||||
path);
|
p);
|
||||||
|
|
||||||
/* Note: when the user explicitly configured things with an env var we won't validate the
|
/* Note: when the user explicitly configured things with an env var we won't validate the
|
||||||
* path beyond checking it refers to a directory. After all we want this to be useful for
|
* path beyond checking it refers to a directory. After all we want this to be useful for
|
||||||
* testing. */
|
* testing. */
|
||||||
|
|
||||||
if (stat(path, &st) < 0)
|
if (stat(p, &st) < 0)
|
||||||
return log_error_errno(errno, "Failed to stat '%s': %m", path);
|
return log_error_errno(errno, "Failed to stat '%s': %m", p);
|
||||||
if (!S_ISDIR(st.st_mode))
|
if (!S_ISDIR(st.st_mode))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "ESP path '%s' is not a directory.", path);
|
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "ESP path '%s' is not a directory.", p);
|
||||||
|
|
||||||
if (ret_part)
|
if (ret_part)
|
||||||
*ret_part = 0;
|
*ret_part = 0;
|
||||||
@ -438,29 +465,33 @@ int find_esp_and_warn(
|
|||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_STRING(_path, "/efi", "/boot", "/boot/efi") {
|
FOREACH_STRING(dir, "/efi", "/boot", "/boot/efi") {
|
||||||
path = _path;
|
r = chase_symlinks(dir, root, CHASE_PREFIX_ROOT, &p, NULL);
|
||||||
|
if (r == -ENOENT)
|
||||||
|
continue;
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r,
|
||||||
|
"Failed to resolve path %s%s%s: %m",
|
||||||
|
dir,
|
||||||
|
root ? " under directory " : "",
|
||||||
|
root ?: "");
|
||||||
|
|
||||||
r = verify_esp(path, /* searching= */ true, unprivileged_mode, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid);
|
r = verify_esp(p, ret_part, ret_pstart, ret_psize, ret_uuid, ret_devid,
|
||||||
|
flags | VERIFY_ESP_SEARCHING);
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
goto found;
|
goto found;
|
||||||
if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
|
if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
p = mfree(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No logging here */
|
/* No logging here */
|
||||||
return -ENOKEY;
|
return -ENOKEY;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
if (ret_path) {
|
if (ret_path)
|
||||||
char *c;
|
*ret_path = TAKE_PTR(p);
|
||||||
|
|
||||||
c = strdup(path);
|
|
||||||
if (!c)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
*ret_path = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -662,18 +693,28 @@ finish:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int find_xbootldr_and_warn(
|
int find_xbootldr_and_warn(
|
||||||
|
const char *root,
|
||||||
const char *path,
|
const char *path,
|
||||||
bool unprivileged_mode,
|
bool unprivileged_mode,
|
||||||
char **ret_path,
|
char **ret_path,
|
||||||
sd_id128_t *ret_uuid,
|
sd_id128_t *ret_uuid,
|
||||||
dev_t *ret_devid) {
|
dev_t *ret_devid) {
|
||||||
|
|
||||||
|
_cleanup_free_ char *p = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */
|
/* Similar to find_esp_and_warn(), but finds the XBOOTLDR partition. Returns the same errors. */
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
r = verify_xbootldr(path, /* searching= */ false, unprivileged_mode, ret_uuid, ret_devid);
|
r = chase_symlinks(path, root, CHASE_PREFIX_ROOT, &p, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r,
|
||||||
|
"Failed to resolve path %s%s%s: %m",
|
||||||
|
path,
|
||||||
|
root ? " under directory " : "",
|
||||||
|
root ?: "");
|
||||||
|
|
||||||
|
r = verify_xbootldr(p, /* searching= */ false, unprivileged_mode, ret_uuid, ret_devid);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -684,15 +725,23 @@ int find_xbootldr_and_warn(
|
|||||||
if (path) {
|
if (path) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
if (!path_is_valid(path) || !path_is_absolute(path))
|
r = chase_symlinks(path, root, CHASE_PREFIX_ROOT, &p, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r,
|
||||||
|
"Failed to resolve path %s%s%s: %m",
|
||||||
|
path,
|
||||||
|
root ? " under directory " : "",
|
||||||
|
root ?: "");
|
||||||
|
|
||||||
|
if (!path_is_valid(p) || !path_is_absolute(p))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"$SYSTEMD_XBOOTLDR_PATH does not refer to absolute path, refusing to use it: %s",
|
"$SYSTEMD_XBOOTLDR_PATH does not refer to absolute path, refusing to use it: %s",
|
||||||
path);
|
p);
|
||||||
|
|
||||||
if (stat(path, &st) < 0)
|
if (stat(p, &st) < 0)
|
||||||
return log_error_errno(errno, "Failed to stat '%s': %m", path);
|
return log_error_errno(errno, "Failed to stat '%s': %m", p);
|
||||||
if (!S_ISDIR(st.st_mode))
|
if (!S_ISDIR(st.st_mode))
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "XBOOTLDR path '%s' is not a directory.", path);
|
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "XBOOTLDR path '%s' is not a directory.", p);
|
||||||
|
|
||||||
if (ret_uuid)
|
if (ret_uuid)
|
||||||
*ret_uuid = SD_ID128_NULL;
|
*ret_uuid = SD_ID128_NULL;
|
||||||
@ -702,26 +751,26 @@ int find_xbootldr_and_warn(
|
|||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = verify_xbootldr("/boot", true, unprivileged_mode, ret_uuid, ret_devid);
|
r = chase_symlinks("/boot", root, CHASE_PREFIX_ROOT, &p, NULL);
|
||||||
if (r >= 0) {
|
if (r == -ENOENT)
|
||||||
path = "/boot";
|
return -ENOKEY;
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r,
|
||||||
|
"Failed to resolve path /boot%s%s: %m",
|
||||||
|
root ? " under directory " : "",
|
||||||
|
root ?: "");
|
||||||
|
|
||||||
|
r = verify_xbootldr(p, true, unprivileged_mode, ret_uuid, ret_devid);
|
||||||
|
if (r >= 0)
|
||||||
goto found;
|
goto found;
|
||||||
}
|
|
||||||
if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
|
if (!IN_SET(r, -ENOENT, -EADDRNOTAVAIL)) /* This one is not it */
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return -ENOKEY;
|
return -ENOKEY;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
if (ret_path) {
|
if (ret_path)
|
||||||
char *c;
|
*ret_path = TAKE_PTR(p);
|
||||||
|
|
||||||
c = strdup(path);
|
|
||||||
if (!c)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
*ret_path = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
|
|
||||||
#include "sd-id128.h"
|
#include "sd-id128.h"
|
||||||
|
|
||||||
int find_esp_and_warn(const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
|
int find_esp_and_warn(const char *root, const char *path, bool unprivileged_mode, char **ret_path, uint32_t *ret_part, uint64_t *ret_pstart, uint64_t *ret_psize, sd_id128_t *ret_uuid, dev_t *ret_devid);
|
||||||
int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path, sd_id128_t *ret_uuid, dev_t *ret_devid);
|
int find_xbootldr_and_warn(const char *root, const char *path, bool unprivileged_mode, char **ret_path, sd_id128_t *ret_uuid, dev_t *ret_devid);
|
||||||
|
@ -43,7 +43,7 @@ static int load_kexec_kernel(void) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = boot_config_select_special_entries(&config);
|
r = boot_config_select_special_entries(&config, /* skip_efivars= */ false);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user