mirror of
https://github.com/systemd/systemd.git
synced 2025-03-19 22:50:17 +03:00
Merge d57f81660f93a8a78594727b7d568dc88d85be8b into fdab24bf6acc62d3011f9b5abdf834b4886642b2
This commit is contained in:
commit
b3125f503b
@ -56,6 +56,14 @@ Specifically, the following concepts are available:
|
||||
and adds `factory-reset-now.target` to the boot transaction, already in the
|
||||
initial RAM disk (initrd).
|
||||
|
||||
* The
|
||||
[`systemd-factory-reset-esp.service`](https://www.freedesktop.org/software/systemd/man/latest/systemd-factory-reset-esp.service.html)
|
||||
unit is invoked via `factory-reset-now.target`, and deletes non-vendor system
|
||||
extension images, UKI addons, and credentials from the EFI System and Extended
|
||||
Bootloader Partitions. See the
|
||||
[`systemd-stub(7)`](https://www.freedesktop.org/software/systemd/man/latest/systemd-stub.html)
|
||||
man page.
|
||||
|
||||
* The
|
||||
[`systemd-factory-reset-complete.service`](https://www.freedesktop.org/software/systemd/man/latest/systemd-factory-reset-complete.service.html)
|
||||
unit is invoked after `factory-reset-now.target` and marks the factory reset
|
||||
@ -118,8 +126,9 @@ order to execute the reset operation.
|
||||
## Support for Resetting other Resources than Partitions + TPM
|
||||
|
||||
By default a factory reset implemented with systemd's tools can reset/erase
|
||||
partitions (via `systemd-repart`, see above) and reset the TPM (via
|
||||
`systemd-tpm2-clear.service`, see above).
|
||||
partitions (via `systemd-repart`, see above), reset the TPM (via
|
||||
`systemd-tpm2-clear.service`, see above), and delete non-vendor resources from
|
||||
the ESP (via `systemd-factory-reset-esp.service`, see above).
|
||||
|
||||
In some cases other resources shall be reset/erased too. To support that,
|
||||
define your own service and plug it into `factory-reset-now.target`, ensuring
|
||||
|
@ -942,6 +942,7 @@ manpages = [
|
||||
['30-systemd-environment-d-generator'],
|
||||
'ENABLE_ENVIRONMENT_D'],
|
||||
['systemd-escape', '1', [], ''],
|
||||
['systemd-factory-reset-esp.service', '8', [], ''],
|
||||
['systemd-factory-reset-generator', '8', [], ''],
|
||||
['systemd-factory-reset',
|
||||
'8',
|
||||
|
50
man/systemd-factory-reset-esp.xml
Normal file
50
man/systemd-factory-reset-esp.xml
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--*-nxml-*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
|
||||
<refentry id="systemd-factory-reset"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
|
||||
<refentryinfo>
|
||||
<title>systemd-factory-reset-esp.service</title>
|
||||
<productname>systemd</productname>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>systemd-factory-reset-esp.service</refentrytitle>
|
||||
<manvolnum>8</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>systemd-factory-reset-esp.service</refname>
|
||||
<refpurpose>Delete non-vendor content from the ESP and XBOOTLDR</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>/usr/lib/systemd/systemd-factory-reset-esp</filename></para>
|
||||
<para><filename>systemd-factory-reset-esp.service</filename></para>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><filename>systemd-factory-reset-esp.service</filename> is a part of systemd's factory reset logic,
|
||||
which deletes non-vendor system extension images, UKI addons, and credentials from the EFI System and
|
||||
Extended Bootloader Partitions. The vendor and non-vendor versions of these resources are stored in
|
||||
different directories, as described in <member><citerefentry><refentrytitle>systemd-stub</refentrytitle>
|
||||
<manvolnum>7</manvolnum></citerefentry></member>.</para>
|
||||
|
||||
<para>See <ulink url="https://systemd.io/FACTORY_RESET">Factory Reset</ulink> for an overview of the
|
||||
factory reset logic.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
<para><simplelist type="inline">
|
||||
<member><citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry></member>
|
||||
<member><citerefentry><refentrytitle>systemd-factory-reset</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||
<member><ulink url="https://systemd.io/FACTORY_RESET">Factory Reset</ulink></member>
|
||||
</simplelist></para>
|
||||
</refsect1>
|
||||
</refentry>
|
@ -207,10 +207,17 @@
|
||||
details on system extension images. The generated <command>cpio</command> archive containing these
|
||||
system extension images is measured into TPM PCR 13 (if a TPM is present).</para></listitem>
|
||||
|
||||
<!-- Note: the actual suffix we look for for sysexts is just *.raw (not *.sysext.raw), for
|
||||
<!-- Note: the actual suffix we look for for non-vendor sysexts is just *.raw (not *.sysext.raw), for
|
||||
compatibility reasons with old versions. But we want people to name their system extensions
|
||||
properly, hence we document the *.sysext.raw suffix only. -->
|
||||
|
||||
<listitem><para>Similarly, files
|
||||
<filename><replaceable>foo</replaceable>.efi.extra.vendor.d/*.sysext.raw</filename> are packed up in a
|
||||
<command>cpio</command> archive and placed in the <filename>/.extra/sysext/</filename> directory in the
|
||||
initrd file heirarchy. This alternate directory exists for OS vendors to ship system extension
|
||||
images that shall persist across an OS factory reset. This archive is similarly measured into TPM
|
||||
PCR 13 (if a TPM is present).</para></listitem>
|
||||
|
||||
<listitem><para>Similarly, files
|
||||
<filename><replaceable>foo</replaceable>.efi.extra.d/*.confext.raw</filename> are packed up in a
|
||||
<command>cpio</command> archive and placed in the <filename>/.extra/confext/</filename> directory in
|
||||
@ -221,13 +228,23 @@
|
||||
these configuration extension images is measured into TPM PCR 12 (if a TPM is present).</para></listitem>
|
||||
|
||||
<listitem><para>Similarly, files
|
||||
<filename><replaceable>foo</replaceable>.efi.extra.d/*.addon.efi</filename> are loaded and verified as
|
||||
PE binaries and specific sections are loaded from them. Addons are used to pass additional kernel
|
||||
command line parameters (<literal>.cmdline</literal> section), or DeviceTree blobs
|
||||
<filename><replaceable>foo</replaceable>.efi.extra.vendor.d/*.confext.raw</filename> are packed up in a
|
||||
<command>cpio</command> archive and placed in the <filename>/.extra/confext/</filename> directory in
|
||||
the initrd file heirarchy. This archive is similarly measured into TPM PCR 12 (if a TPM is present).
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Similarly, files
|
||||
<filename><replaceable>foo</replaceable>.efi.extra.d/*.addon.efi</filename>,
|
||||
<filename><replaceable>foo</replaceable>.efi.extra.vendor.d/*.addon.efi</filename>,
|
||||
<filename>/loader/addons/*.addon.efi</filename>, and
|
||||
<filename>/loader/vendor-addons/*.addon.efi</filename> are loaded and
|
||||
verified as PE binaries and specific sections are loaded from them. Addons are used to pass additional
|
||||
kernel command line parameters (<literal>.cmdline</literal> section), or Devicetree blobs
|
||||
(<literal>.dtb</literal> section), additional initrds (<literal>.initrd</literal> section),
|
||||
and microcode updates (<literal>.ucode</literal> section). Addons allow those resources to be passed
|
||||
regardless of the kernel version being booted, for example allowing platform vendors to ship
|
||||
platform-specific configuration.</para>
|
||||
and microcode updates (<literal>.ucode</literal> section). The addons found under
|
||||
<filename>/loader/addons/</filename> or <filename>/loader/vendor-addons/</filename> allow those
|
||||
resources to be passed regardless of the kernel version being booted, for example allowing platform
|
||||
vendors to ship platform-specific configuration.</para>
|
||||
|
||||
<para>In case Secure Boot is enabled, these files will be validated using keys in UEFI DB, Shim's DB or
|
||||
Shim's MOK, and only loaded if the check passes. Additionally, if both the addon and the UKI contain a
|
||||
@ -239,8 +256,8 @@
|
||||
<ulink url="https://github.com/rhboot/shim/blob/main/SBAT.md">Shim documentation</ulink>.</para>
|
||||
|
||||
<para>Addon files are sorted, loaded, and measured into TPM PCR 12 (if a TPM is present) and appended
|
||||
to the kernel command line. UKI command line options are listed first, then options from addons in
|
||||
<filename>/loader/addons/*.addon.efi</filename>, and finally UKI-specific addons. Device tree blobs are
|
||||
to the kernel command line. UKI command line options are listed first, then options from global addons in
|
||||
<filename>/loader/addons/</filename> and others, and finally UKI-specific addons. Device tree blobs are
|
||||
loaded and measured following the same algorithm. Microcode addons are passed to the kernel in inverse
|
||||
order (UKI specific addons, global addons, UKI embedded section). This is because the microcode update
|
||||
driver stops on the first matching filename. Addons are always loaded in the same order based on
|
||||
@ -252,17 +269,11 @@
|
||||
an attestation service so that improper use of your signed addons can be detected and dealt with using
|
||||
one of the aforementioned revocation mechanisms.</para></listitem>
|
||||
|
||||
<listitem><para>Files <filename>/loader/credentials/*.cred</filename> are packed up in a
|
||||
<listitem><para>Similarly, files <filename>/loader/credentials/*.cred</filename> are packed up in a
|
||||
<command>cpio</command> archive and placed in the <filename>/.extra/global_credentials/</filename>
|
||||
directory of the initrd file hierarchy. This is supposed to be used to pass additional credentials to
|
||||
the initrd, regardless of the kernel version being booted. The generated <command>cpio</command>
|
||||
archive is measured into TPM PCR 12 (if a TPM is present).</para></listitem>
|
||||
|
||||
<listitem><para>Additionally, files <filename>/loader/addons/*.addon.efi</filename> are loaded and
|
||||
verified as PE binaries, and <literal>.cmdline</literal>, <literal>.dtb</literal>,
|
||||
<literal>.initrd</literal>, and <literal>.ucode</literal> sections are parsed from them.
|
||||
This is supposed to be used to pass additional command line parameters, DeviceTree blobs, initrds,
|
||||
and microcode updates to the kernel, regardless of the kernel version being booted.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>These mechanisms may be used to parameterize and extend trusted (i.e. signed), immutable initrd
|
||||
|
@ -316,7 +316,6 @@ EFI_STATUS pack_cpio(
|
||||
|
||||
_cleanup_file_close_ EFI_FILE *root = NULL, *extra_dir = NULL;
|
||||
size_t dirent_size = 0, buffer_size = 0, n_items = 0, n_allocated = 0;
|
||||
_cleanup_free_ char16_t *rel_dropin_dir = NULL;
|
||||
_cleanup_free_ EFI_FILE_INFO *dirent = NULL;
|
||||
_cleanup_strv_free_ char16_t **items = NULL;
|
||||
_cleanup_free_ void *buffer = NULL;
|
||||
@ -330,6 +329,9 @@ EFI_STATUS pack_cpio(
|
||||
if (!loaded_image->DeviceHandle)
|
||||
goto nothing;
|
||||
|
||||
if (!dropin_dir)
|
||||
goto nothing;
|
||||
|
||||
err = open_volume(loaded_image->DeviceHandle, &root);
|
||||
if (err == EFI_UNSUPPORTED)
|
||||
/* Error will be unsupported if the bootloader doesn't implement the file system protocol on
|
||||
@ -338,12 +340,6 @@ EFI_STATUS pack_cpio(
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Unable to open root directory: %m");
|
||||
|
||||
if (!dropin_dir) {
|
||||
dropin_dir = rel_dropin_dir = get_extra_dir(loaded_image->FilePath);
|
||||
if (!dropin_dir)
|
||||
goto nothing;
|
||||
}
|
||||
|
||||
err = open_directory(root, dropin_dir, &extra_dir);
|
||||
if (err == EFI_NOT_FOUND)
|
||||
/* No extra subdir, that's totally OK */
|
||||
|
@ -37,7 +37,9 @@ enum {
|
||||
INITRD_CREDENTIAL = _INITRD_DYNAMIC_FIRST,
|
||||
INITRD_GLOBAL_CREDENTIAL,
|
||||
INITRD_SYSEXT,
|
||||
INITRD_VENDOR_SYSEXT,
|
||||
INITRD_CONFEXT,
|
||||
INITRD_VENDOR_CONFEXT,
|
||||
INITRD_PCRSIG,
|
||||
INITRD_PCRPKEY,
|
||||
INITRD_OSREL,
|
||||
@ -821,6 +823,7 @@ static void generate_sidecar_initrds(
|
||||
int *sysext_measured,
|
||||
int *confext_measured) {
|
||||
|
||||
_cleanup_free_ char16_t *dropin_dir = NULL, *vendor_dropin_dir = NULL;
|
||||
bool m;
|
||||
|
||||
assert(loaded_image);
|
||||
@ -829,8 +832,13 @@ static void generate_sidecar_initrds(
|
||||
assert(sysext_measured);
|
||||
assert(confext_measured);
|
||||
|
||||
|
||||
dropin_dir = get_extra_dir(".extra.d", loaded_image->FilePath);
|
||||
vendor_dropin_dir = get_extra_dir(".extra.vendor.d", loaded_image->FilePath);
|
||||
/* Note: Either of these may be NULL, but that's handled by pack_cpio */
|
||||
|
||||
if (pack_cpio(loaded_image,
|
||||
/* dropin_dir= */ NULL,
|
||||
dropin_dir,
|
||||
u".cred",
|
||||
/* exclude_suffix= */ NULL,
|
||||
".extra/credentials",
|
||||
@ -856,7 +864,7 @@ static void generate_sidecar_initrds(
|
||||
combine_measured_flag(parameters_measured, m);
|
||||
|
||||
if (pack_cpio(loaded_image,
|
||||
/* dropin_dir= */ NULL,
|
||||
dropin_dir,
|
||||
u".raw", /* ideally we'd pick up only *.sysext.raw here, but for compat we pick up *.raw instead … */
|
||||
u".confext.raw", /* … but then exclude *.confext.raw again */
|
||||
".extra/sysext",
|
||||
@ -869,7 +877,20 @@ static void generate_sidecar_initrds(
|
||||
combine_measured_flag(sysext_measured, m);
|
||||
|
||||
if (pack_cpio(loaded_image,
|
||||
/* dropin_dir= */ NULL,
|
||||
vendor_dropin_dir,
|
||||
u".sysext.raw", /* No compatibility to worry about in the new .vendor.d dirs */
|
||||
/* exclude_suffix= */ NULL,
|
||||
".extra/sysext",
|
||||
/* dir_mode= */ 0555,
|
||||
/* access_mode= */ 0444,
|
||||
/* tpm_pcr= */ TPM2_PCR_SYSEXTS,
|
||||
u"Vendor system extension initrd",
|
||||
initrds + INITRD_VENDOR_SYSEXT,
|
||||
&m) == EFI_SUCCESS)
|
||||
combine_measured_flag(sysext_measured, m);
|
||||
|
||||
if (pack_cpio(loaded_image,
|
||||
dropin_dir,
|
||||
u".confext.raw",
|
||||
/* exclude_suffix= */ NULL,
|
||||
".extra/confext",
|
||||
@ -880,6 +901,19 @@ static void generate_sidecar_initrds(
|
||||
initrds + INITRD_CONFEXT,
|
||||
&m) == EFI_SUCCESS)
|
||||
combine_measured_flag(confext_measured, m);
|
||||
|
||||
if (pack_cpio(loaded_image,
|
||||
vendor_dropin_dir,
|
||||
u".confext.raw",
|
||||
/* exclude_suffix= */ NULL,
|
||||
".extra/confext",
|
||||
/* dir_mode= */ 0555,
|
||||
/* access_mode= */ 0444,
|
||||
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
|
||||
u"Vendor configuration extension initrd",
|
||||
initrds + INITRD_VENDOR_CONFEXT,
|
||||
&m) == EFI_SUCCESS)
|
||||
combine_measured_flag(confext_measured, m);
|
||||
}
|
||||
|
||||
static void generate_embedded_initrds(
|
||||
@ -1042,8 +1076,23 @@ static void load_all_addons(
|
||||
if (err != EFI_SUCCESS)
|
||||
log_error_status(err, "Error loading global addons, ignoring: %m");
|
||||
|
||||
err = load_addons(
|
||||
image,
|
||||
loaded_image,
|
||||
u"\\loader\\vendor-addons",
|
||||
uname,
|
||||
cmdline_addons,
|
||||
dt_addons,
|
||||
n_dt_addons,
|
||||
initrd_addons,
|
||||
n_initrd_addons,
|
||||
ucode_addons,
|
||||
n_ucode_addons);
|
||||
if (err != EFI_SUCCESS)
|
||||
log_error_status(err, "Error loading global vendor addons, ignoring: %m");
|
||||
|
||||
/* Some bootloaders always pass NULL in FilePath, so we need to check for it here. */
|
||||
_cleanup_free_ char16_t *dropin_dir = get_extra_dir(loaded_image->FilePath);
|
||||
_cleanup_free_ char16_t *dropin_dir = get_extra_dir(".extra.d", loaded_image->FilePath);
|
||||
if (!dropin_dir)
|
||||
return;
|
||||
|
||||
@ -1061,6 +1110,26 @@ static void load_all_addons(
|
||||
n_ucode_addons);
|
||||
if (err != EFI_SUCCESS)
|
||||
log_error_status(err, "Error loading UKI-specific addons, ignoring: %m");
|
||||
|
||||
_cleanup_free_ char16_t *vendor_dropin_dir =
|
||||
get_extra_dir(".extra.vendor.d", loaded_image->FilePath);
|
||||
if (!vendor_dropin_dir)
|
||||
return;
|
||||
|
||||
err = load_addons(
|
||||
image,
|
||||
loaded_image,
|
||||
vendor_dropin_dir,
|
||||
uname,
|
||||
cmdline_addons,
|
||||
dt_addons,
|
||||
n_dt_addons,
|
||||
initrd_addons,
|
||||
n_initrd_addons,
|
||||
ucode_addons,
|
||||
n_ucode_addons);
|
||||
if (err != EFI_SUCCESS)
|
||||
log_error_status(err, "Error loading UKI-specific vendor addons, ignoring: %m");
|
||||
}
|
||||
|
||||
static void display_splash(
|
||||
|
@ -462,7 +462,7 @@ static void remove_boot_count(char16_t *path) {
|
||||
strcpy16(prefix_end, tail);
|
||||
}
|
||||
|
||||
char16_t *get_extra_dir(const EFI_DEVICE_PATH *file_path) {
|
||||
char16_t *get_extra_dir(const char *suffix, const EFI_DEVICE_PATH *file_path) {
|
||||
if (!file_path)
|
||||
return NULL;
|
||||
|
||||
@ -483,7 +483,7 @@ char16_t *get_extra_dir(const EFI_DEVICE_PATH *file_path) {
|
||||
|
||||
convert_efi_path(file_path_str);
|
||||
remove_boot_count(file_path_str);
|
||||
return xasprintf("%ls.extra.d", file_path_str);
|
||||
return xasprintf("%ls%s", file_path_str, suffix);
|
||||
}
|
||||
|
||||
void *xmalloc(size_t size) {
|
||||
|
@ -239,7 +239,7 @@ static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) {
|
||||
|
||||
void *find_configuration_table(const EFI_GUID *guid);
|
||||
|
||||
char16_t *get_extra_dir(const EFI_DEVICE_PATH *file_path);
|
||||
char16_t *get_extra_dir(const char *suffix, const EFI_DEVICE_PATH *file_path);
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define be32toh(x) __builtin_bswap32(x)
|
||||
|
95
src/factory-reset/factory-reset-esp.c
Normal file
95
src/factory-reset/factory-reset-esp.c
Normal file
@ -0,0 +1,95 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include "ansi-color.h"
|
||||
#include "bootspec.h"
|
||||
#include "find-esp.h"
|
||||
#include "main-func.h"
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
|
||||
r = terminal_urlify_man("systemd-factory-reset-esp.service", "8", &link);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
printf("%1$s [OPTIONS...]\n"
|
||||
"\n%5$sDelete non-vendor contents from ESP and XBOOTLDR.%6$s\n"
|
||||
"\n%3$sOptions:%4$s\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Print version\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
program_invocation_short_name,
|
||||
link,
|
||||
ansi_underline(),
|
||||
ansi_normal(),
|
||||
ansi_highlight(),
|
||||
ansi_normal());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{}
|
||||
};
|
||||
|
||||
int r, c;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
int r;
|
||||
|
||||
log_setup();
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
FactoryResetMode f = factory_reset_mode();
|
||||
if (f < 0)
|
||||
return log_error_errno(f, "Failed to determine factory reset mode: %m");
|
||||
if (f != FACTORY_RESET_ON)
|
||||
return log_error("We are not currently in factory reset mode. Refusing operation.");
|
||||
|
||||
|
||||
_cleanup_(boot_config_free) BootConfig bc = BOOT_CONFIG_NULL;
|
||||
r = boot_config_load_auto(&bc, NULL, NULL);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to load boot config: %m");
|
||||
|
||||
// TODO: Walk the ESP and XBOOTLDR, and delete the non-vendor stuff!
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_MAIN_FUNCTION(run);
|
@ -5,6 +5,10 @@ executables += [
|
||||
'name' : 'systemd-factory-reset',
|
||||
'sources' : files('factory-reset-tool.c'),
|
||||
},
|
||||
libexec_template + {
|
||||
'name' : 'systemd-factory-reset-esp',
|
||||
'sources' : files('factory-reset-esp.c'),
|
||||
},
|
||||
generator_template + {
|
||||
'name' : 'systemd-factory-reset-generator',
|
||||
'sources' : files('factory-reset-generator.c'),
|
||||
|
@ -1090,14 +1090,13 @@ static int boot_entries_find_unified_addons(
|
||||
int d_fd,
|
||||
const char *addon_dir,
|
||||
const char *root,
|
||||
BootEntryAddons *ret_addons) {
|
||||
BootEntryAddons *addons) {
|
||||
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
_cleanup_free_ char *full = NULL;
|
||||
_cleanup_(boot_entry_addons_done) BootEntryAddons addons = {};
|
||||
int r;
|
||||
|
||||
assert(ret_addons);
|
||||
assert(addons);
|
||||
assert(config);
|
||||
|
||||
r = chase_and_opendirat(d_fd, addon_dir, CHASE_AT_RESOLVE_IN_ROOT, &full, &d);
|
||||
@ -1139,15 +1138,13 @@ static int boot_entries_find_unified_addons(
|
||||
if (!location)
|
||||
return log_oom();
|
||||
|
||||
r = insert_boot_entry_addon(&addons, location, cmdline);
|
||||
r = insert_boot_entry_addon(addons, location, cmdline);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_PTR(location);
|
||||
TAKE_PTR(cmdline);
|
||||
}
|
||||
|
||||
*ret_addons = TAKE_STRUCT(addons);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1158,17 +1155,28 @@ static int boot_entries_find_unified_global_addons(
|
||||
BootEntryAddons *ret_addons) {
|
||||
|
||||
int r;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
_cleanup_(boot_entry_addons_done) BootEntryAddons addons = {};
|
||||
|
||||
assert(ret_addons);
|
||||
|
||||
r = chase_and_opendir(root, NULL, CHASE_PROHIBIT_SYMLINKS, NULL, &d);
|
||||
r = chase_and_opendir(d_name, root, CHASE_PROHIBIT_SYMLINKS, &p, &d);
|
||||
if (r == -ENOENT)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open '%s/%s': %m", root, d_name);
|
||||
|
||||
return boot_entries_find_unified_addons(config, dirfd(d), d_name, root, ret_addons);
|
||||
r = boot_entries_find_unified_addons(config, dirfd(d), "addons", p, &addons);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = boot_entries_find_unified_addons(config, dirfd(d), "vendor-addons", p, &addons);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_addons = TAKE_STRUCT(addons);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boot_entries_find_unified_local_addons(
|
||||
@ -1178,7 +1186,8 @@ static int boot_entries_find_unified_local_addons(
|
||||
const char *root,
|
||||
BootEntry *ret) {
|
||||
|
||||
_cleanup_free_ char *addon_dir = NULL;
|
||||
_cleanup_free_ char *addon_dir = NULL, *vendor_addon_dir = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
@ -1186,7 +1195,15 @@ static int boot_entries_find_unified_local_addons(
|
||||
if (!addon_dir)
|
||||
return log_oom();
|
||||
|
||||
return boot_entries_find_unified_addons(config, d_fd, addon_dir, root, &ret->local_addons);
|
||||
vendor_addon_dir = strjoin(d_name, ".extra.vendor.d");
|
||||
if (!vendor_addon_dir)
|
||||
return log_oom();
|
||||
|
||||
r = boot_entries_find_unified_addons(config, d_fd, addon_dir, root, &ret->local_addons);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return boot_entries_find_unified_addons(config, d_fd, vendor_addon_dir, root, &ret->local_addons);
|
||||
}
|
||||
|
||||
static int boot_entries_find_unified(
|
||||
@ -1485,7 +1502,7 @@ int boot_config_load(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = boot_entries_find_unified_global_addons(config, esp_path, "/loader/addons/",
|
||||
r = boot_entries_find_unified_global_addons(config, esp_path, "/loader",
|
||||
&config->global_addons[BOOT_ENTRY_ESP]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1500,7 +1517,7 @@ int boot_config_load(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = boot_entries_find_unified_global_addons(config, xbootldr_path, "/loader/addons/",
|
||||
r = boot_entries_find_unified_global_addons(config, xbootldr_path, "/loader",
|
||||
&config->global_addons[BOOT_ENTRY_XBOOTLDR]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -329,6 +329,7 @@ units = [
|
||||
'symlinks' : ['sockets.target.wants/'],
|
||||
},
|
||||
{ 'file' : 'systemd-factory-reset-complete.service.in' },
|
||||
{ 'file' : 'systemd-factory-reset-esp.service' },
|
||||
{ 'file' : 'systemd-factory-reset-reboot.service' },
|
||||
{
|
||||
'file' : 'systemd-factory-reset-request.service.in',
|
||||
|
28
units/systemd-factory-reset-esp.service.in
Normal file
28
units/systemd-factory-reset-esp.service.in
Normal file
@ -0,0 +1,28 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# systemd is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation; either version 2.1 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
##########################################################################################
|
||||
# TODO: Edit this!
|
||||
##########################################################################################
|
||||
|
||||
[Unit]
|
||||
Description=Delete non-vendor content from the ESP and XBOOTLDR
|
||||
Documentation=man:systemd-factory-reset-esp.service(8)
|
||||
DefaultDependencies=no
|
||||
Requires=factory-reset-now.target
|
||||
After=factory-reset-now.target
|
||||
Conflicts=shutdown.target
|
||||
Before=shutdown.target
|
||||
RefuseManualStart=yes
|
||||
RefuseManualStop=yes
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart={{LIBEXECDIR}}/systemd-factory-reset complete --retrigger
|
Loading…
x
Reference in New Issue
Block a user