mirror of
https://github.com/systemd/systemd
synced 2026-04-24 16:04:51 +02:00
Compare commits
19 Commits
2df5a7d3f1
...
c0da575a0e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0da575a0e | ||
|
|
197be5324e | ||
|
|
598e431500 | ||
|
|
18a02561f1 | ||
|
|
3e3c49cbe7 | ||
|
|
2cf120f7cf | ||
|
|
42ac3bf1a3 | ||
|
|
c7749367e3 | ||
|
|
b1d723228e | ||
|
|
901fa9a4c9 | ||
|
|
04d1fbd564 | ||
|
|
20742f92c1 | ||
|
|
e12335ba60 | ||
|
|
db9eabd675 | ||
|
|
8214758bd5 | ||
|
|
5672bdd341 | ||
|
|
61ec7beaf5 | ||
|
|
036a8d503f | ||
|
|
957b242319 |
38
TODO
38
TODO
@ -78,6 +78,44 @@ Janitorial Clean-ups:
|
|||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
|
* systemd creds hookup with qemu fw_cfg. (Quite possibly might not need any
|
||||||
|
code at all, given the fw_cfg stuff are just files, but we should then
|
||||||
|
document how to use it). Goal: provide symmetric ways to pass creds to nspawn
|
||||||
|
containers and qemu VMs. (maybe also pick up env vars from fw_cfg?)
|
||||||
|
|
||||||
|
* beef up sd_notify() to support AV_VSOCK in $NOTIFY_SOCKET, so that VM
|
||||||
|
managers can get ready notifications from VMs, just like container managers
|
||||||
|
from their payload. Also pick up address from qemu/fw_cfg if set there.
|
||||||
|
(which has benefits, given SecureBoot and kernel cmdline are not necessarily
|
||||||
|
friends.)
|
||||||
|
|
||||||
|
* mirroring this: maybe support binding to AV_VSOCK in Type=notify services,
|
||||||
|
then passing $NOTIFY_SOCKET and $NOTIFY_GUESTCID with PID1's cid (typically
|
||||||
|
fixed to "2", i.e. the official host cid) and the expected guest cid, for the
|
||||||
|
two sides of the channe. The latter env var could then be used in an
|
||||||
|
appropriate qemu cmdline. That way qemu payloads could talk sd_notify()
|
||||||
|
directly to host service manager.
|
||||||
|
|
||||||
|
* maybe write a tool that binds an AF_VFSOCK socket, then invokes qemu,
|
||||||
|
extending the command line to enable vsock on the VM, and using fw_cfg to
|
||||||
|
configure socket address.
|
||||||
|
|
||||||
|
* sd-boot: rework random seed handling following recent kernel changes: always
|
||||||
|
pass seed to kernel, but credit only if secure boot is used
|
||||||
|
|
||||||
|
* sd-boot: hash data from GetNextHighMonotonicCount() into updated random seed,
|
||||||
|
so that we might even open up up the random seed logic to non-SecureBoot
|
||||||
|
systems?
|
||||||
|
|
||||||
|
* sd-boot: add menu item for shutdown? or hotkey?
|
||||||
|
|
||||||
|
* sd-device has an API to create an sd_device object from a device id, but has
|
||||||
|
no api to query the device id
|
||||||
|
|
||||||
|
* sd-device should return the devnum type (i.e. 'b' or 'c') via some API for an
|
||||||
|
sd_device object, so that data passed into sd_device_new_from_devnum() can
|
||||||
|
also be queried.
|
||||||
|
|
||||||
* udevadm: a new "tree" verb that shows tree of devices as syspath hierarchy,
|
* udevadm: a new "tree" verb that shows tree of devices as syspath hierarchy,
|
||||||
along with their properties. uninitialized devices should be greyed out.
|
along with their properties. uninitialized devices should be greyed out.
|
||||||
|
|
||||||
|
|||||||
169
man/bootctl.xml
169
man/bootctl.xml
@ -46,33 +46,35 @@
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>status</option></term>
|
<term><option>status</option></term>
|
||||||
|
|
||||||
<listitem><para>Shows brief information about the system firmware, the boot loader that was used to boot the
|
<listitem><para>Shows brief information about the system firmware, the boot loader that was used to
|
||||||
system, the boot loaders currently available in the ESP, the boot loaders listed in the firmware's list of boot
|
boot the system, the boot loaders currently available in the ESP, the boot loaders listed in the
|
||||||
loaders and the current default boot loader entry. If no command is specified, this is the implied
|
firmware's list of boot loaders and the current default boot loader entry. If no command is
|
||||||
default.</para></listitem>
|
specified, this is the implied default.</para>
|
||||||
|
|
||||||
|
<para>See the example below for details of the output.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>reboot-to-firmware</option> <optional><replaceable>BOOL</replaceable></optional></term>
|
||||||
|
|
||||||
|
<listitem><para>Query or set the "Reboot-Into-Firmware-Setup" flag of the EFI firmware. Takes a
|
||||||
|
boolean argument which controls whether to show the firmware setup on next system reboot. If the
|
||||||
|
argument is omitted shows the current status of the flag, or whether the flag is supported. This
|
||||||
|
controls the same flag as <command>systemctl reboot --firmware-setup</command>, but is more low-level
|
||||||
|
and allows setting the flag independently from actually requesting a reboot.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>systemd-efi-options</option> <optional><replaceable>STRING</replaceable></optional></term>
|
||||||
|
|
||||||
|
<listitem><para>When called without the optional argument, prints the current value of the
|
||||||
|
<literal>SystemdOptions</literal> EFI variable. When called with an argument, sets the variable to
|
||||||
|
that value. See
|
||||||
|
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> for the
|
||||||
|
meaning of that variable.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>reboot-to-firmware</option> <optional><replaceable>BOOL</replaceable></optional></term>
|
|
||||||
|
|
||||||
<listitem><para>Query or set the "Reboot-Into-Firmware-Setup" flag of the EFI firmware. Takes a
|
|
||||||
boolean argument which controls whether to show the firmware setup on next system reboot. If the
|
|
||||||
argument is omitted shows the current status of the flag, or whether the flag is supported. This
|
|
||||||
controls the same flag as <command>systemctl reboot --firmware-setup</command>, but is more
|
|
||||||
low-level and allows setting the flag independently from actually requesting a
|
|
||||||
reboot.</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>systemd-efi-options</option> <optional><replaceable>STRING</replaceable></optional></term>
|
|
||||||
|
|
||||||
<listitem><para>When called without the optional argument, prints the current value of the
|
|
||||||
<literal>SystemdOptions</literal> EFI variable. When called with an argument, sets the
|
|
||||||
variable to that value. See
|
|
||||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
|
||||||
for the meaning of that variable.</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@ -84,17 +86,16 @@
|
|||||||
<command>systemd-boot</command>.</para>
|
<command>systemd-boot</command>.</para>
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>list</option></term>
|
<term><option>list</option></term>
|
||||||
|
|
||||||
<listitem><para>Shows all available boot loader entries implementing the <ulink
|
<listitem><para>Shows all available boot loader entries implementing the <ulink
|
||||||
url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink>, as well as any
|
url="https://systemd.io/BOOT_LOADER_SPECIFICATION">Boot Loader Specification</ulink>, as well as any
|
||||||
other entries discovered or automatically generated by a boot loader implementing the <ulink
|
other entries discovered or automatically generated by a boot loader implementing the <ulink
|
||||||
url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader
|
url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>.
|
||||||
Interface</ulink>.</para>
|
JSON output may be requested with <option>--json=</option>.</para>
|
||||||
|
|
||||||
<para>JSON output may be requested with <option>--json=</option>.</para>
|
<para>See the example below for details of the output.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@ -104,9 +105,9 @@
|
|||||||
|
|
||||||
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string or a glob
|
<listitem><para>Sets the default boot loader entry. Takes a single boot loader entry ID string or a glob
|
||||||
pattern as argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
|
pattern as argument. The <option>set-oneshot</option> command will set the default entry only for the next boot,
|
||||||
the <option>set-default</option> will set it persistently for all future boots.</para></listitem>
|
the <option>set-default</option> will set it persistently for all future boots.</para>
|
||||||
|
|
||||||
<listitem><para>Optionally, the boot loader entry ID may be specified as one of: <option>@default</option>,
|
<para>Optionally, the boot loader entry ID may be specified as one of: <option>@default</option>,
|
||||||
<option>@oneshot</option> or <option>@current</option>, which correspond to the current default boot loader
|
<option>@oneshot</option> or <option>@current</option>, which correspond to the current default boot loader
|
||||||
entry for all future boots, the current default boot loader entry for the next boot, and the currently booted
|
entry for all future boots, the current default boot loader entry for the next boot, and the currently booted
|
||||||
boot loader entry. These special IDs are resolved to the current values of the EFI variables
|
boot loader entry. These special IDs are resolved to the current values of the EFI variables
|
||||||
@ -137,7 +138,6 @@
|
|||||||
disables the timeout while always showing the menu. When an empty string ("") is specified the
|
disables the timeout while always showing the menu. When an empty string ("") is specified the
|
||||||
bootloader will revert to its default menu timeout.</para></listitem>
|
bootloader will revert to its default menu timeout.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@ -347,6 +347,111 @@
|
|||||||
the Extended Boot Loader partition.</para>
|
the Extended Boot Loader partition.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Examples</title>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
<title>Output from <command>status</command> and <command>list</command></title>
|
||||||
|
|
||||||
|
<programlisting>$ <command>bootctl status</command>
|
||||||
|
System:
|
||||||
|
Firmware: UEFI 2.40 (<replaceable>firmware-version</replaceable>) ← firmware vendor and version
|
||||||
|
Secure Boot: disabled (setup) ← secure boot status
|
||||||
|
TPM2 Support: yes
|
||||||
|
Boot into FW: supported ← does the firmware support booting into itself
|
||||||
|
|
||||||
|
Current Boot Loader: ← details about sd-boot or another boot loader
|
||||||
|
Product: systemd-boot <replaceable>version</replaceable> implementing the <ulink
|
||||||
|
url="https://systemd.io/BOOT_LOADER_INTERFACE">Boot Loader Interface</ulink>
|
||||||
|
Features: ✓ Boot counting
|
||||||
|
✓ Menu timeout control
|
||||||
|
✓ One-shot menu timeout control
|
||||||
|
✓ Default entry control
|
||||||
|
✓ One-shot entry control
|
||||||
|
✓ Support for XBOOTLDR partition
|
||||||
|
✓ Support for passing random seed to OS
|
||||||
|
✓ Load drop-in drivers
|
||||||
|
✓ Boot loader sets ESP information
|
||||||
|
ESP: /dev/disk/by-partuuid/01234567-89ab-cdef-dead-beef00000000
|
||||||
|
File: └─/EFI/systemd/systemd-bootx64.efi
|
||||||
|
|
||||||
|
Random Seed: ← random seed used for entropy in early boot
|
||||||
|
Passed to OS: yes
|
||||||
|
System Token: set
|
||||||
|
Exists: yes
|
||||||
|
|
||||||
|
Available Boot Loaders on ESP:
|
||||||
|
ESP: /boot/efi (/dev/disk/by-partuuid/01234567-89ab-cdef-dead-beef00000000)
|
||||||
|
File: └─/EFI/systemd/systemd-bootx64.efi (systemd-boot 251
|
||||||
|
File: └─/EFI/BOOT/BOOTX64.EFI (systemd-boot 251
|
||||||
|
|
||||||
|
Boot Loaders Listed in EFI Variables:
|
||||||
|
Title: Linux Boot Manager
|
||||||
|
ID: 0x0001
|
||||||
|
Status: active, boot-order
|
||||||
|
Partition: /dev/disk/by-partuuid/…
|
||||||
|
File: └─/EFI/systemd/systemd-bootx64.efi
|
||||||
|
|
||||||
|
Title: Fedora
|
||||||
|
ID: 0x0000
|
||||||
|
Status: active, boot-order
|
||||||
|
Partition: /dev/disk/by-partuuid/…
|
||||||
|
File: └─/EFI/fedora/shimx64.efi
|
||||||
|
|
||||||
|
Title: Linux-Firmware-Updater
|
||||||
|
ID: 0x0002
|
||||||
|
Status: active, boot-order
|
||||||
|
Partition: /dev/disk/by-partuuid/…
|
||||||
|
File: └─/EFI/fedora/fwupdx64.efi
|
||||||
|
|
||||||
|
Boot Loader Entries:
|
||||||
|
$BOOT: /boot/efi (/dev/disk/by-partuuid/01234567-89ab-cdef-dead-beef00000000)
|
||||||
|
|
||||||
|
Default Boot Loader Entry:
|
||||||
|
type: Boot Loader Specification Type #1 (.conf)
|
||||||
|
title: Fedora Linux 36 (Workstation Edition)
|
||||||
|
id: …
|
||||||
|
source: /boot/efi/loader/entries/<replaceable>entry-token</replaceable>-<replaceable>kernel-version</replaceable>.conf
|
||||||
|
version: <replaceable>kernel-version</replaceable>
|
||||||
|
machine-id: …
|
||||||
|
linux: /<replaceable>entry-token</replaceable>/<replaceable>kernel-version</replaceable>/linux
|
||||||
|
initrd: /<replaceable>entry-token</replaceable>/<replaceable>kernel-version</replaceable>/initrd
|
||||||
|
options: root=…
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
<programlisting>$ <command>bootctl list</command>
|
||||||
|
Boot Loader Entries:
|
||||||
|
type: Boot Loader Specification Type #1 (.conf)
|
||||||
|
title: Fedora Linux 36 (Workstation Edition) (default) (selected)
|
||||||
|
id: …
|
||||||
|
source: /boot/efi/loader/entries/<replaceable>entry-token</replaceable>-<replaceable>kernel-version</replaceable>.conf
|
||||||
|
version: <replaceable>kernel-version</replaceable>
|
||||||
|
machine-id: …
|
||||||
|
linux: /<replaceable>entry-token</replaceable>/<replaceable>kernel-version</replaceable>/linux
|
||||||
|
initrd: /<replaceable>entry-token</replaceable>/<replaceable>kernel-version</replaceable>/initrd
|
||||||
|
options: root=…
|
||||||
|
|
||||||
|
type: Boot Loader Specification Type #2 (.efi)
|
||||||
|
title: Fedora Linux 35 (Workstation Edition)
|
||||||
|
id: …
|
||||||
|
source: /boot/efi/EFI/Linux/fedora-<replaceable>kernel-version</replaceable>.efi
|
||||||
|
version: <replaceable>kernel-version</replaceable>
|
||||||
|
machine-id: …
|
||||||
|
linux: /EFI/Linux/fedora-<replaceable>kernel-version</replaceable>.efi
|
||||||
|
options: root=…
|
||||||
|
|
||||||
|
type: Automatic
|
||||||
|
title: Reboot Into Firmware Interface
|
||||||
|
id: auto-reboot-to-firmware-setup
|
||||||
|
source: /sys/firmware/efi/efivars/LoaderEntries-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
<para>In the listing, <literal>(default)</literal> specifies the entry that will be
|
||||||
|
used by default, and <literal>(selected)</literal> specifies the entry that was
|
||||||
|
selected the last time (i.e. is currently running).</para>
|
||||||
|
</example>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>See Also</title>
|
<title>See Also</title>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@ -115,7 +115,7 @@ static int acquire_esp(
|
|||||||
free_and_replace(arg_esp_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_esp_path);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acquire_xbootldr(
|
static int acquire_xbootldr(
|
||||||
@ -583,6 +583,35 @@ static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = {
|
|||||||
|
|
||||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
|
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
|
||||||
|
|
||||||
|
static int boot_config_load_and_select(
|
||||||
|
BootConfig *config,
|
||||||
|
const char *esp_path,
|
||||||
|
dev_t esp_devid,
|
||||||
|
const char *xbootldr_path,
|
||||||
|
dev_t xbootldr_devid) {
|
||||||
|
|
||||||
|
_cleanup_strv_free_ char **efi_entries = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would
|
||||||
|
* find the same entries twice. */
|
||||||
|
bool same = esp_path && xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
|
||||||
|
|
||||||
|
r = boot_config_load(config, esp_path, same ? NULL : xbootldr_path);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static int boot_entry_show(
|
static int boot_entry_show(
|
||||||
const BootEntry *e,
|
const BootEntry *e,
|
||||||
bool show_as_default,
|
bool show_as_default,
|
||||||
@ -682,16 +711,17 @@ static int boot_entry_show(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int status_entries(
|
static int status_entries(
|
||||||
|
const BootConfig *config,
|
||||||
const char *esp_path,
|
const char *esp_path,
|
||||||
sd_id128_t esp_partition_uuid,
|
sd_id128_t esp_partition_uuid,
|
||||||
const char *xbootldr_path,
|
const char *xbootldr_path,
|
||||||
sd_id128_t xbootldr_partition_uuid) {
|
sd_id128_t xbootldr_partition_uuid) {
|
||||||
|
|
||||||
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
|
|
||||||
sd_id128_t dollar_boot_partition_uuid;
|
sd_id128_t dollar_boot_partition_uuid;
|
||||||
const char *dollar_boot_path;
|
const char *dollar_boot_path;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(config);
|
||||||
assert(esp_path || xbootldr_path);
|
assert(esp_path || xbootldr_path);
|
||||||
|
|
||||||
if (xbootldr_path) {
|
if (xbootldr_path) {
|
||||||
@ -709,21 +739,13 @@ static int status_entries(
|
|||||||
SD_ID128_FORMAT_VAL(dollar_boot_partition_uuid));
|
SD_ID128_FORMAT_VAL(dollar_boot_partition_uuid));
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
|
|
||||||
r = boot_config_load(&config, esp_path, xbootldr_path);
|
if (config->default_entry < 0)
|
||||||
if (r < 0)
|
printf("%zu entries, no entry could be determined as default.\n", config->n_entries);
|
||||||
return r;
|
|
||||||
|
|
||||||
r = boot_config_select_special_entries(&config);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (config.default_entry < 0)
|
|
||||||
printf("%zu entries, no entry could be determined as default.\n", config.n_entries);
|
|
||||||
else {
|
else {
|
||||||
printf("Default Boot Loader Entry:\n");
|
printf("Default Boot Loader Entry:\n");
|
||||||
|
|
||||||
r = boot_entry_show(
|
r = boot_entry_show(
|
||||||
boot_config_default_entry(&config),
|
boot_config_default_entry(config),
|
||||||
/* show_as_default= */ false,
|
/* show_as_default= */ false,
|
||||||
/* show_as_selected= */ false,
|
/* show_as_selected= */ false,
|
||||||
/* show_discovered= */ false);
|
/* show_discovered= */ false);
|
||||||
@ -1593,13 +1615,9 @@ static void print_yes_no_line(bool first, bool good, const char *name) {
|
|||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int are_we_installed(void) {
|
static int are_we_installed(const char *esp_path) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
/* Tests whether systemd-boot is installed. It's not obvious what to use as check here: we could
|
/* Tests whether systemd-boot is installed. It's not obvious what to use as check here: we could
|
||||||
* check EFI variables, we could check what binary /EFI/BOOT/BOOT*.EFI points to, or whether the
|
* check EFI variables, we could check what binary /EFI/BOOT/BOOT*.EFI points to, or whether the
|
||||||
* loader entries directory exists. Here we opted to check whether /EFI/systemd/ is non-empty, which
|
* loader entries directory exists. Here we opted to check whether /EFI/systemd/ is non-empty, which
|
||||||
@ -1614,7 +1632,7 @@ static int are_we_installed(void) {
|
|||||||
* → It specifically checks for systemd-boot, not for other boot loaders (which a check for
|
* → It specifically checks for systemd-boot, not for other boot loaders (which a check for
|
||||||
* /boot/loader/entries would do). */
|
* /boot/loader/entries would do). */
|
||||||
|
|
||||||
_cleanup_free_ char *p = path_join(arg_esp_path, "/EFI/systemd/");
|
_cleanup_free_ char *p = path_join(esp_path, "/EFI/systemd/");
|
||||||
if (!p)
|
if (!p)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
@ -1645,7 +1663,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid, &xbootldr_devid);
|
r = acquire_xbootldr(/* unprivileged_mode= */ geteuid() != 0, &xbootldr_uuid, &xbootldr_devid);
|
||||||
if (arg_print_dollar_boot_path) {
|
if (arg_print_dollar_boot_path) {
|
||||||
if (r == -EACCES)
|
if (r == -EACCES)
|
||||||
return log_error_errno(r, "Failed to determine XBOOTLDR location: %m");
|
return log_error_errno(r, "Failed to determine XBOOTLDR partition: %m");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1659,8 +1677,8 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
if (arg_print_esp_path || arg_print_dollar_boot_path)
|
if (arg_print_esp_path || arg_print_dollar_boot_path)
|
||||||
return 0;
|
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
|
||||||
* can show */
|
* show what we can show */
|
||||||
|
|
||||||
pager_open(arg_pager_flags);
|
pager_open(arg_pager_flags);
|
||||||
|
|
||||||
@ -1776,16 +1794,20 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arg_esp_path || arg_xbootldr_path) {
|
if (arg_esp_path || arg_xbootldr_path) {
|
||||||
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */
|
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
|
||||||
bool same = arg_esp_path && arg_xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
|
|
||||||
|
|
||||||
k = status_entries(
|
k = boot_config_load_and_select(&config,
|
||||||
arg_esp_path,
|
arg_esp_path, esp_devid,
|
||||||
esp_uuid,
|
arg_xbootldr_path, xbootldr_devid);
|
||||||
same ? NULL : arg_xbootldr_path,
|
|
||||||
same ? SD_ID128_NULL : xbootldr_uuid);
|
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
r = k;
|
r = k;
|
||||||
|
else {
|
||||||
|
k = status_entries(&config,
|
||||||
|
arg_esp_path, esp_uuid,
|
||||||
|
arg_xbootldr_path, xbootldr_uuid);
|
||||||
|
if (k < 0)
|
||||||
|
r = k;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@ -1793,17 +1815,17 @@ 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 = BOOT_CONFIG_NULL;
|
_cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
|
||||||
_cleanup_strv_free_ char **efi_entries = NULL;
|
|
||||||
dev_t esp_devid = 0, xbootldr_devid = 0;
|
dev_t esp_devid = 0, xbootldr_devid = 0;
|
||||||
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
|
||||||
* off logging about access errors and turn off potentially privileged device probing. Here we're interested in
|
* things: turn off logging about access errors and turn off potentially privileged device probing.
|
||||||
* the latter but not the former, hence request the mode, and log about EACCES. */
|
* Here we're interested in the latter but not the former, hence request the mode, and log about
|
||||||
|
* EACCES. */
|
||||||
|
|
||||||
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, NULL, &esp_devid);
|
r = acquire_esp(/* unprivileged_mode= */ geteuid() != 0, /* graceful= */ false, NULL, NULL, NULL, NULL, &esp_devid);
|
||||||
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 location: %m");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -1813,22 +1835,7 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* If XBOOTLDR and ESP actually refer to the same block device, suppress XBOOTLDR, since it would find the same entries twice */
|
r = boot_config_load_and_select(&config, arg_esp_path, esp_devid, arg_xbootldr_path, xbootldr_devid);
|
||||||
bool same = arg_esp_path && arg_xbootldr_path && devid_set_and_equal(esp_devid, xbootldr_devid);
|
|
||||||
|
|
||||||
r = boot_config_load(&config, arg_esp_path, same ? NULL : arg_xbootldr_path);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
r = boot_config_select_special_entries(&config);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -2063,7 +2070,7 @@ static int verb_install(int argc, char *argv[], void *userdata) {
|
|||||||
|
|
||||||
if (!install) {
|
if (!install) {
|
||||||
/* If we are updating, don't do anything if sd-boot wasn't actually installed. */
|
/* If we are updating, don't do anything if sd-boot wasn't actually installed. */
|
||||||
r = are_we_installed();
|
r = are_we_installed(arg_esp_path);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -2209,7 +2216,11 @@ static int verb_remove(int argc, char *argv[], void *userdata) {
|
|||||||
static int verb_is_installed(int argc, char *argv[], void *userdata) {
|
static int verb_is_installed(int argc, char *argv[], void *userdata) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = are_we_installed();
|
r = acquire_esp(/* privileged_mode= */ false, /* graceful= */ false, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = are_we_installed(arg_esp_path);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@ -17,14 +17,18 @@
|
|||||||
|
|
||||||
static void test_sd_device_one(sd_device *d) {
|
static void test_sd_device_one(sd_device *d) {
|
||||||
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
_cleanup_(sd_device_unrefp) sd_device *dev = NULL;
|
||||||
const char *syspath, *sysname, *subsystem = NULL, *id, *devname, *val;
|
const char *syspath, *sysname, *subsystem = NULL, *devname, *val;
|
||||||
bool is_block = false;
|
bool is_block = false;
|
||||||
dev_t devnum;
|
dev_t devnum;
|
||||||
usec_t usec;
|
usec_t usec;
|
||||||
int i, r;
|
int ifindex, r;
|
||||||
|
|
||||||
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
|
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
|
||||||
assert_se(path_startswith(syspath, "/sys"));
|
assert_se(path_startswith(syspath, "/sys"));
|
||||||
|
assert_se(sd_device_get_sysname(d, &sysname) >= 0);
|
||||||
|
|
||||||
|
log_info("%s(%s)", __func__, syspath);
|
||||||
|
|
||||||
assert_se(sd_device_new_from_syspath(&dev, syspath) >= 0);
|
assert_se(sd_device_new_from_syspath(&dev, syspath) >= 0);
|
||||||
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
||||||
assert_se(streq(syspath, val));
|
assert_se(streq(syspath, val));
|
||||||
@ -35,10 +39,34 @@ static void test_sd_device_one(sd_device *d) {
|
|||||||
assert_se(streq(syspath, val));
|
assert_se(streq(syspath, val));
|
||||||
dev = sd_device_unref(dev);
|
dev = sd_device_unref(dev);
|
||||||
|
|
||||||
assert_se(sd_device_get_sysname(d, &sysname) >= 0);
|
r = sd_device_get_ifindex(d, &ifindex);
|
||||||
|
if (r >= 0) {
|
||||||
|
assert_se(ifindex > 0);
|
||||||
|
|
||||||
|
r = sd_device_new_from_ifindex(&dev, ifindex);
|
||||||
|
if (r == -ENODEV)
|
||||||
|
log_device_warning_errno(d, r,
|
||||||
|
"Failed to create sd-device object from ifindex %i. "
|
||||||
|
"Maybe running on a non-host network namespace.", ifindex);
|
||||||
|
else {
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
||||||
|
assert_se(streq(syspath, val));
|
||||||
|
dev = sd_device_unref(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This does not require the interface really exists on the network namespace.
|
||||||
|
* Hence, this should always succeed. */
|
||||||
|
assert_se(sd_device_new_from_ifname(&dev, sysname) >= 0);
|
||||||
|
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
||||||
|
assert_se(streq(syspath, val));
|
||||||
|
dev = sd_device_unref(dev);
|
||||||
|
} else
|
||||||
|
assert_se(r == -ENOENT);
|
||||||
|
|
||||||
r = sd_device_get_subsystem(d, &subsystem);
|
r = sd_device_get_subsystem(d, &subsystem);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
const char *name;
|
const char *name, *id;
|
||||||
|
|
||||||
if (streq(subsystem, "drivers"))
|
if (streq(subsystem, "drivers"))
|
||||||
name = strjoina(d->driver_subsystem, ":", sysname);
|
name = strjoina(d->driver_subsystem, ":", sysname);
|
||||||
@ -48,6 +76,31 @@ static void test_sd_device_one(sd_device *d) {
|
|||||||
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
||||||
assert_se(streq(syspath, val));
|
assert_se(streq(syspath, val));
|
||||||
dev = sd_device_unref(dev);
|
dev = sd_device_unref(dev);
|
||||||
|
|
||||||
|
/* The device ID depends on subsystem. */
|
||||||
|
assert_se(device_get_device_id(d, &id) >= 0);
|
||||||
|
r = sd_device_new_from_device_id(&dev, id);
|
||||||
|
if (r == -ENODEV && ifindex > 0)
|
||||||
|
log_device_warning_errno(d, r,
|
||||||
|
"Failed to create sd-device object from device ID \"%s\". "
|
||||||
|
"Maybe running on a non-host network namespace.", id);
|
||||||
|
else {
|
||||||
|
assert_se(r >= 0);
|
||||||
|
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
||||||
|
assert_se(streq(syspath, val));
|
||||||
|
dev = sd_device_unref(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* These require udev database, and reading database requires device ID. */
|
||||||
|
r = sd_device_get_is_initialized(d);
|
||||||
|
if (r > 0) {
|
||||||
|
r = sd_device_get_usec_since_initialized(d, &usec);
|
||||||
|
assert_se((r >= 0 && usec > 0) || r == -ENODATA);
|
||||||
|
} else
|
||||||
|
assert(r == 0);
|
||||||
|
|
||||||
|
r = sd_device_get_property_value(d, "ID_NET_DRIVER", &val);
|
||||||
|
assert_se(r >= 0 || r == -ENOENT);
|
||||||
} else
|
} else
|
||||||
assert_se(r == -ENOENT);
|
assert_se(r == -ENOENT);
|
||||||
|
|
||||||
@ -101,22 +154,6 @@ static void test_sd_device_one(sd_device *d) {
|
|||||||
} else
|
} else
|
||||||
assert_se(r == -ENOENT);
|
assert_se(r == -ENOENT);
|
||||||
|
|
||||||
r = sd_device_get_ifindex(d, &i);
|
|
||||||
if (r >= 0) {
|
|
||||||
assert_se(i > 0);
|
|
||||||
|
|
||||||
assert_se(sd_device_new_from_ifindex(&dev, i) >= 0);
|
|
||||||
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
|
||||||
assert_se(streq(syspath, val));
|
|
||||||
dev = sd_device_unref(dev);
|
|
||||||
|
|
||||||
assert_se(sd_device_new_from_ifname(&dev, sysname) >= 0);
|
|
||||||
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
|
||||||
assert_se(streq(syspath, val));
|
|
||||||
dev = sd_device_unref(dev);
|
|
||||||
} else
|
|
||||||
assert_se(r == -ENOENT);
|
|
||||||
|
|
||||||
assert_se(sd_device_get_devpath(d, &val) >= 0);
|
assert_se(sd_device_get_devpath(d, &val) >= 0);
|
||||||
|
|
||||||
r = sd_device_get_devtype(d, &val);
|
r = sd_device_get_devtype(d, &val);
|
||||||
@ -128,25 +165,8 @@ static void test_sd_device_one(sd_device *d) {
|
|||||||
r = sd_device_get_sysnum(d, &val);
|
r = sd_device_get_sysnum(d, &val);
|
||||||
assert_se(r >= 0 || r == -ENOENT);
|
assert_se(r >= 0 || r == -ENOENT);
|
||||||
|
|
||||||
r = sd_device_get_is_initialized(d);
|
|
||||||
if (r > 0) {
|
|
||||||
r = sd_device_get_usec_since_initialized(d, &usec);
|
|
||||||
assert_se((r >= 0 && usec > 0) || r == -ENODATA);
|
|
||||||
} else
|
|
||||||
assert(r == 0);
|
|
||||||
|
|
||||||
r = sd_device_get_sysattr_value(d, "name_assign_type", &val);
|
r = sd_device_get_sysattr_value(d, "name_assign_type", &val);
|
||||||
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || IN_SET(r, -ENOENT, -EINVAL));
|
assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || IN_SET(r, -ENOENT, -EINVAL));
|
||||||
|
|
||||||
r = sd_device_get_property_value(d, "ID_NET_DRIVER", &val);
|
|
||||||
assert_se(r >= 0 || r == -ENOENT);
|
|
||||||
|
|
||||||
assert_se(device_get_device_id(d, &id) >= 0);
|
|
||||||
assert_se(sd_device_new_from_device_id(&dev, id) >= 0);
|
|
||||||
assert_se(sd_device_get_syspath(dev, &val) >= 0);
|
|
||||||
assert_se(streq(syspath, val));
|
|
||||||
|
|
||||||
log_info("syspath:%s subsystem:%s id:%s initialized:%s", syspath, strna(subsystem), id, yes_no(i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(sd_device_enumerator_devices) {
|
TEST(sd_device_enumerator_devices) {
|
||||||
@ -169,39 +189,54 @@ TEST(sd_device_enumerator_subsystems) {
|
|||||||
test_sd_device_one(d);
|
test_sd_device_one(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned test_sd_device_enumerator_filter_subsystem_one(const char *subsystem, Hashmap *h) {
|
static void test_sd_device_enumerator_filter_subsystem_one(
|
||||||
|
const char *subsystem,
|
||||||
|
Hashmap *h,
|
||||||
|
unsigned *ret_n_new_dev,
|
||||||
|
unsigned *ret_n_removed_dev) {
|
||||||
|
|
||||||
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
||||||
sd_device *d, *t;
|
unsigned n_new_dev = 0, n_removed_dev = 0;
|
||||||
unsigned n_new_dev = 0;
|
sd_device *d;
|
||||||
|
|
||||||
assert_se(sd_device_enumerator_new(&e) >= 0);
|
assert_se(sd_device_enumerator_new(&e) >= 0);
|
||||||
assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, true) >= 0);
|
assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, true) >= 0);
|
||||||
|
|
||||||
FOREACH_DEVICE(e, d) {
|
FOREACH_DEVICE(e, d) {
|
||||||
const char *syspath;
|
const char *syspath;
|
||||||
|
sd_device *t;
|
||||||
|
|
||||||
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
|
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
|
||||||
t = hashmap_remove(h, syspath);
|
t = hashmap_remove(h, syspath);
|
||||||
assert_se(!sd_device_unref(t));
|
|
||||||
|
|
||||||
if (t)
|
if (!t) {
|
||||||
log_debug("Removed subsystem:%s syspath:%s", subsystem, syspath);
|
|
||||||
else {
|
|
||||||
log_warning("New device found: subsystem:%s syspath:%s", subsystem, syspath);
|
log_warning("New device found: subsystem:%s syspath:%s", subsystem, syspath);
|
||||||
n_new_dev++;
|
n_new_dev++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_se(!sd_device_unref(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assume no device is unplugged. */
|
HASHMAP_FOREACH(d, h) {
|
||||||
assert_se(hashmap_isempty(h));
|
const char *syspath;
|
||||||
|
|
||||||
return n_new_dev;
|
assert_se(sd_device_get_syspath(d, &syspath) >= 0);
|
||||||
|
log_warning("Device removed: subsystem:%s syspath:%s", subsystem, syspath);
|
||||||
|
n_removed_dev++;
|
||||||
|
|
||||||
|
assert_se(!sd_device_unref(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
hashmap_free(h);
|
||||||
|
|
||||||
|
*ret_n_new_dev = n_new_dev;
|
||||||
|
*ret_n_removed_dev = n_removed_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(sd_device_enumerator_filter_subsystem) {
|
TEST(sd_device_enumerator_filter_subsystem) {
|
||||||
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
||||||
_cleanup_(hashmap_freep) Hashmap *subsystems;
|
_cleanup_(hashmap_freep) Hashmap *subsystems;
|
||||||
unsigned n_new_dev = 0;
|
unsigned n_new_dev = 0, n_removed_dev = 0;
|
||||||
sd_device *d;
|
sd_device *d;
|
||||||
Hashmap *h;
|
Hashmap *h;
|
||||||
char *s;
|
char *s;
|
||||||
@ -235,16 +270,22 @@ TEST(sd_device_enumerator_filter_subsystem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((h = hashmap_steal_first_key_and_value(subsystems, (void**) &s))) {
|
while ((h = hashmap_steal_first_key_and_value(subsystems, (void**) &s))) {
|
||||||
n_new_dev += test_sd_device_enumerator_filter_subsystem_one(s, h);
|
unsigned n, m;
|
||||||
hashmap_free(h);
|
|
||||||
|
test_sd_device_enumerator_filter_subsystem_one(s, TAKE_PTR(h), &n, &m);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
|
n_new_dev += n;
|
||||||
|
n_removed_dev += m;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_new_dev > 0)
|
if (n_new_dev > 0)
|
||||||
log_warning("%u new device is found in re-scan", n_new_dev);
|
log_warning("%u new devices are found in re-scan", n_new_dev);
|
||||||
|
if (n_removed_dev > 0)
|
||||||
|
log_warning("%u devices removed in re-scan", n_removed_dev);
|
||||||
|
|
||||||
/* Assume that not so many devices are plugged. */
|
/* Assume that not so many devices are plugged or unplugged. */
|
||||||
assert_se(n_new_dev <= 10);
|
assert_se(n_new_dev + n_removed_dev <= 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(sd_device_new_from_nulstr) {
|
TEST(sd_device_new_from_nulstr) {
|
||||||
|
|||||||
@ -749,10 +749,8 @@ int netdev_load_one(Manager *manager, const char *filename) {
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
|
|
||||||
r = null_or_empty_path(filename);
|
r = null_or_empty_path(filename);
|
||||||
if (r == -ENOENT)
|
|
||||||
return 0;
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
log_debug("Skipping empty file: %s", filename);
|
log_debug("Skipping empty file: %s", filename);
|
||||||
return 0;
|
return 0;
|
||||||
@ -777,7 +775,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
|
|||||||
netdev_raw,
|
netdev_raw,
|
||||||
NULL);
|
NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* config_parse_many() logs internally. */
|
||||||
|
|
||||||
/* skip out early if configuration does not match the environment */
|
/* skip out early if configuration does not match the environment */
|
||||||
if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL)) {
|
if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL)) {
|
||||||
@ -785,15 +783,11 @@ int netdev_load_one(Manager *manager, const char *filename) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netdev_raw->kind == _NETDEV_KIND_INVALID) {
|
if (netdev_raw->kind == _NETDEV_KIND_INVALID)
|
||||||
log_warning("NetDev has no Kind= configured in %s. Ignoring", filename);
|
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "NetDev has no Kind= configured in \"%s\", ignoring.", filename);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!netdev_raw->ifname) {
|
if (!netdev_raw->ifname)
|
||||||
log_warning("NetDev without Name= configured in %s. Ignoring", filename);
|
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "NetDev without Name= configured in \"%s\", ignoring.", filename);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size);
|
netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size);
|
||||||
if (!netdev)
|
if (!netdev)
|
||||||
@ -815,13 +809,13 @@ int netdev_load_one(Manager *manager, const char *filename) {
|
|||||||
CONFIG_PARSE_WARN,
|
CONFIG_PARSE_WARN,
|
||||||
netdev, NULL);
|
netdev, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* config_parse_many() logs internally. */
|
||||||
|
|
||||||
/* verify configuration */
|
/* verify configuration */
|
||||||
if (NETDEV_VTABLE(netdev)->config_verify) {
|
if (NETDEV_VTABLE(netdev)->config_verify) {
|
||||||
r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename);
|
r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return 0;
|
return r; /* config_verify() logs internally. */
|
||||||
}
|
}
|
||||||
|
|
||||||
netdev->filename = strdup(filename);
|
netdev->filename = strdup(filename);
|
||||||
@ -837,22 +831,21 @@ int netdev_load_one(Manager *manager, const char *filename) {
|
|||||||
assert(n);
|
assert(n);
|
||||||
if (!streq(netdev->filename, n->filename))
|
if (!streq(netdev->filename, n->filename))
|
||||||
log_netdev_warning_errno(netdev, r,
|
log_netdev_warning_errno(netdev, r,
|
||||||
"Device was already configured by file %s, ignoring %s.",
|
"Device was already configured by \"%s\", ignoring %s.",
|
||||||
n->filename, netdev->filename);
|
n->filename, netdev->filename);
|
||||||
|
|
||||||
/* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is
|
/* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is
|
||||||
* removed from the hashmap 'manager->netdevs'. */
|
* removed from the hashmap 'manager->netdevs'. */
|
||||||
netdev->ifname = mfree(netdev->ifname);
|
netdev->ifname = mfree(netdev->ifname);
|
||||||
return 0;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
if (r < 0)
|
assert(r > 0);
|
||||||
return r;
|
|
||||||
|
|
||||||
log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
|
log_netdev_debug(netdev, "loaded \"%s\"", netdev_kind_to_string(netdev->kind));
|
||||||
|
|
||||||
r = netdev_request_to_create(netdev);
|
r = netdev_request_to_create(netdev);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* netdev_request_to_create() logs internally. */
|
||||||
|
|
||||||
TAKE_PTR(netdev);
|
TAKE_PTR(netdev);
|
||||||
return 0;
|
return 0;
|
||||||
@ -871,11 +864,8 @@ int netdev_load(Manager *manager, bool reload) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to enumerate netdev files: %m");
|
return log_error_errno(r, "Failed to enumerate netdev files: %m");
|
||||||
|
|
||||||
STRV_FOREACH(f, files) {
|
STRV_FOREACH(f, files)
|
||||||
r = netdev_load_one(manager, *f);
|
(void) netdev_load_one(manager, *f);
|
||||||
if (r < 0)
|
|
||||||
log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -313,7 +313,7 @@ int network_verify(Network *network) {
|
|||||||
|
|
||||||
r = network_drop_invalid_addresses(network);
|
r = network_drop_invalid_addresses(network);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* network_drop_invalid_addresses() logs internally. */
|
||||||
network_drop_invalid_routes(network);
|
network_drop_invalid_routes(network);
|
||||||
network_drop_invalid_nexthops(network);
|
network_drop_invalid_nexthops(network);
|
||||||
network_drop_invalid_bridge_fdb_entries(network);
|
network_drop_invalid_bridge_fdb_entries(network);
|
||||||
@ -327,7 +327,7 @@ int network_verify(Network *network) {
|
|||||||
network_drop_invalid_tclass(network);
|
network_drop_invalid_tclass(network);
|
||||||
r = sr_iov_drop_invalid_sections(UINT32_MAX, network->sr_iov_by_section);
|
r = sr_iov_drop_invalid_sections(UINT32_MAX, network->sr_iov_by_section);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* sr_iov_drop_invalid_sections() logs internally. */
|
||||||
network_drop_invalid_static_leases(network);
|
network_drop_invalid_static_leases(network);
|
||||||
|
|
||||||
network_adjust_dhcp_server(network);
|
network_adjust_dhcp_server(network);
|
||||||
@ -346,10 +346,8 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
|
|
||||||
r = null_or_empty_path(filename);
|
r = null_or_empty_path(filename);
|
||||||
if (r == -ENOENT)
|
|
||||||
return 0;
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
log_debug("Skipping empty file: %s", filename);
|
log_debug("Skipping empty file: %s", filename);
|
||||||
return 0;
|
return 0;
|
||||||
@ -365,7 +363,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||||||
|
|
||||||
d = strrchr(name, '.');
|
d = strrchr(name, '.');
|
||||||
if (!d)
|
if (!d)
|
||||||
return -EINVAL;
|
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid file name: %s", filename);
|
||||||
|
|
||||||
*d = '\0';
|
*d = '\0';
|
||||||
|
|
||||||
@ -552,7 +550,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||||||
network,
|
network,
|
||||||
&network->stats_by_path);
|
&network->stats_by_path);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* config_parse_many() logs internally. */
|
||||||
|
|
||||||
r = network_add_ipv4ll_route(network);
|
r = network_add_ipv4ll_route(network);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -564,15 +562,12 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||||||
network->filename);
|
network->filename);
|
||||||
|
|
||||||
r = network_verify(network);
|
r = network_verify(network);
|
||||||
if (r == -ENOMEM)
|
|
||||||
return r;
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
/* Ignore .network files that do not match the conditions. */
|
return r; /* network_verify() logs internally. */
|
||||||
return 0;
|
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
|
r = ordered_hashmap_ensure_put(networks, &string_hash_ops, network->name, network);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_warning_errno(r, "%s: Failed to store configuration into hashmap: %m", filename);
|
||||||
|
|
||||||
TAKE_PTR(network);
|
TAKE_PTR(network);
|
||||||
return 0;
|
return 0;
|
||||||
@ -590,11 +585,8 @@ int network_load(Manager *manager, OrderedHashmap **networks) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to enumerate network files: %m");
|
return log_error_errno(r, "Failed to enumerate network files: %m");
|
||||||
|
|
||||||
STRV_FOREACH(f, files) {
|
STRV_FOREACH(f, files)
|
||||||
r = network_load_one(manager, networks, *f);
|
(void) network_load_one(manager, networks, *f);
|
||||||
if (r < 0)
|
|
||||||
return log_error_errno(r, "Failed to load %s: %m", *f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,7 +71,7 @@ typedef struct BootConfig {
|
|||||||
|
|
||||||
BootEntry* boot_config_find_entry(BootConfig *config, const char *id);
|
BootEntry* boot_config_find_entry(BootConfig *config, const char *id);
|
||||||
|
|
||||||
static inline BootEntry* boot_config_default_entry(BootConfig *config) {
|
static inline const BootEntry* boot_config_default_entry(const BootConfig *config) {
|
||||||
assert(config);
|
assert(config);
|
||||||
|
|
||||||
if (config->default_entry < 0)
|
if (config->default_entry < 0)
|
||||||
|
|||||||
@ -218,10 +218,8 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
|
|||||||
assert(filename);
|
assert(filename);
|
||||||
|
|
||||||
r = null_or_empty_path(filename);
|
r = null_or_empty_path(filename);
|
||||||
if (r == -ENOENT)
|
|
||||||
return 0;
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
log_debug("Skipping empty file: %s", filename);
|
log_debug("Skipping empty file: %s", filename);
|
||||||
return 0;
|
return 0;
|
||||||
@ -229,11 +227,11 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
|
|||||||
|
|
||||||
name = strdup(filename);
|
name = strdup(filename);
|
||||||
if (!name)
|
if (!name)
|
||||||
return -ENOMEM;
|
return log_oom();
|
||||||
|
|
||||||
config = new(LinkConfig, 1);
|
config = new(LinkConfig, 1);
|
||||||
if (!config)
|
if (!config)
|
||||||
return -ENOMEM;
|
return log_oom();
|
||||||
|
|
||||||
*config = (LinkConfig) {
|
*config = (LinkConfig) {
|
||||||
.filename = TAKE_PTR(name),
|
.filename = TAKE_PTR(name),
|
||||||
@ -266,7 +264,7 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
|
|||||||
config_item_perf_lookup, link_config_gperf_lookup,
|
config_item_perf_lookup, link_config_gperf_lookup,
|
||||||
CONFIG_PARSE_WARN, config, NULL);
|
CONFIG_PARSE_WARN, config, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* config_parse_many() logs internally. */
|
||||||
|
|
||||||
if (net_match_is_empty(&config->match) && !config->conditions) {
|
if (net_match_is_empty(&config->match) && !config->conditions) {
|
||||||
log_warning("%s: No valid settings found in the [Match] section, ignoring file. "
|
log_warning("%s: No valid settings found in the [Match] section, ignoring file. "
|
||||||
@ -288,13 +286,13 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
|
|||||||
|
|
||||||
r = link_adjust_wol_options(config);
|
r = link_adjust_wol_options(config);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* link_adjust_wol_options() logs internally. */
|
||||||
|
|
||||||
r = sr_iov_drop_invalid_sections(config->sr_iov_num_vfs, config->sr_iov_by_section);
|
r = sr_iov_drop_invalid_sections(config->sr_iov_num_vfs, config->sr_iov_by_section);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r; /* sr_iov_drop_invalid_sections() logs internally. */
|
||||||
|
|
||||||
log_debug("Parsed configuration file %s", filename);
|
log_debug("Parsed configuration file \"%s\"", filename);
|
||||||
|
|
||||||
LIST_PREPEND(configs, ctx->configs, TAKE_PTR(config));
|
LIST_PREPEND(configs, ctx->configs, TAKE_PTR(config));
|
||||||
return 0;
|
return 0;
|
||||||
@ -340,11 +338,8 @@ int link_config_load(LinkConfigContext *ctx) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "failed to enumerate link files: %m");
|
return log_error_errno(r, "failed to enumerate link files: %m");
|
||||||
|
|
||||||
STRV_FOREACH_BACKWARDS(f, files) {
|
STRV_FOREACH_BACKWARDS(f, files)
|
||||||
r = link_load_one(ctx, *f);
|
(void) link_load_one(ctx, *f);
|
||||||
if (r < 0)
|
|
||||||
log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user