factory-reset: revamp infrastructure
This introduces a bunch of facilities: 1. The factory-reset.target unit that requests a factory reset is now complemented by factory-reset-now.target that executes it at next boot. 2. This latter is added to the initial transaction via the new trivial systemd-factory-reset-generator. 3. A tool systemd-factory-reset has been added to query, request, cancel, complete factory reset operations (via EFI variables). Two of these are wrapped into units that are plugged into factory-reset.target and factory-reset-now.target respectively. The tool also provides a simple Varlink API. This should make things a lot cleaner, and both be useful as explicit implementation on UEFI, and as template + hookpoints for alternative implementations on non-UEFI.
This commit is contained in:
@@ -761,6 +761,17 @@
|
|||||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>systemd.factory_reset=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Controls whether to to boot into factory reset mode, implemented by
|
||||||
|
<citerefentry><refentrytitle>systemd-factory-reset-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||||
|
and other tools.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|||||||
@@ -942,6 +942,14 @@ manpages = [
|
|||||||
['30-systemd-environment-d-generator'],
|
['30-systemd-environment-d-generator'],
|
||||||
'ENABLE_ENVIRONMENT_D'],
|
'ENABLE_ENVIRONMENT_D'],
|
||||||
['systemd-escape', '1', [], ''],
|
['systemd-escape', '1', [], ''],
|
||||||
|
['systemd-factory-reset-generator', '8', [], ''],
|
||||||
|
['systemd-factory-reset',
|
||||||
|
'8',
|
||||||
|
['systemd-factory-reset-complete.service',
|
||||||
|
'systemd-factory-reset-request.service',
|
||||||
|
'systemd-factory-reset.socket',
|
||||||
|
'systemd-factory-reset@.service'],
|
||||||
|
''],
|
||||||
['systemd-firstboot', '1', ['systemd-firstboot.service'], 'ENABLE_FIRSTBOOT'],
|
['systemd-firstboot', '1', ['systemd-firstboot.service'], 'ENABLE_FIRSTBOOT'],
|
||||||
['systemd-fsck@.service',
|
['systemd-fsck@.service',
|
||||||
'8',
|
'8',
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?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-generator">
|
||||||
|
|
||||||
|
<refentryinfo>
|
||||||
|
<title>systemd-factory-reset-generator</title>
|
||||||
|
<productname>systemd</productname>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>systemd-factory-reset-generator</refentrytitle>
|
||||||
|
<manvolnum>8</manvolnum>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>systemd-factory-reset-generator</refname>
|
||||||
|
<refpurpose>Pull <filename>factory-reset-now.target</filename> into the initial boot transaction when factory reset has been requested</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<para><filename>/usr/lib/systemd/system-generators/systemd-factory-reset-generator</filename></para>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para><filename>systemd-factory-reset-generator</filename> is a generator that pulls
|
||||||
|
<filename>factory-reset-now.target</filename> into the initial boot transaction when the factory reset
|
||||||
|
operation has been requested, either via the <varname>systemd.factory_reset=</varname> kernel command
|
||||||
|
line option or via the <varname>FactoryResetRequest</varname> EFI variable.</para>
|
||||||
|
|
||||||
|
<para><filename>systemd-factory-reset-generator</filename> implements
|
||||||
|
<citerefentry><refentrytitle>systemd.generator</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</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>
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
<?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</title>
|
||||||
|
<productname>systemd</productname>
|
||||||
|
</refentryinfo>
|
||||||
|
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>systemd-factory-reset</refentrytitle>
|
||||||
|
<manvolnum>8</manvolnum>
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>systemd-factory-reset</refname>
|
||||||
|
<refname>systemd-factory-reset-request.service</refname>
|
||||||
|
<refname>systemd-factory-reset-complete.service</refname>
|
||||||
|
<refname>systemd-factory-reset.socket</refname>
|
||||||
|
<refname>systemd-factory-reset@.service</refname>
|
||||||
|
<refpurpose>Request or complete a factory reset operation, or query current factory reset mode</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<para><filename>/usr/lib/systemd/systemd-factory-reset</filename></para>
|
||||||
|
<para><filename>systemd-factory-reset-request.service</filename></para>
|
||||||
|
<para><filename>systemd-factory-reset-complete.service</filename></para>
|
||||||
|
<para><filename>systemd-factory-reset.socket</filename></para>
|
||||||
|
<para><filename>systemd-factory-reset@.service</filename></para>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para><filename>systemd-factory-reset</filename> is a tool that can query the current factory reset
|
||||||
|
state, request factory request operations or complete them.</para>
|
||||||
|
|
||||||
|
<para>Some of the functionality is also available via the
|
||||||
|
<filename>/run/systemd/io.systemd.FactoryReset</filename> Varlink service (implemented via the
|
||||||
|
<filename>systemd-factory-reset.socket</filename>/<filename>systemd-factory-reset@.service</filename>
|
||||||
|
units.</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>Commands</title>
|
||||||
|
|
||||||
|
<para>The <filename>/usr/lib/systemd/systemd-factory-reset</filename> executable may also be invoked from the
|
||||||
|
command line, taking one of the following command arguments:</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>status</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Report current factory reset state. Reports one of <literal>unsupported</literal> (if
|
||||||
|
the OS does not support a factory reset logic), <literal>unspecified</literal> (if no factory reset
|
||||||
|
was requested, but it wasn't turned off explicitly either), <literal>off</literal> (if the factory
|
||||||
|
reset logic was explicitly turned off via the kernel command line option), <literal>on</literal> (if
|
||||||
|
the factory reset is currently enabled and executed), <literal>complete</literal> (if the factory
|
||||||
|
reset logic ran during the current boot but is complete now), <literal>pending</literal> (if a
|
||||||
|
factory reset has been requested for the next boot).</para>
|
||||||
|
|
||||||
|
<para>Returns with an exit status of 0 if the factory reset mechanism is currently not in effect, 10
|
||||||
|
if a factory reset is currently being executed, or 11 if it is pending for the next boot.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>request</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Request a factory reset operation to be executed on next boot.</para>
|
||||||
|
|
||||||
|
<para>Note that this is a relatively low-level operation. The primary interface for requesting a
|
||||||
|
factory reset operation is by starting the <filename>factory-reset.target</filename>
|
||||||
|
unit.</para>
|
||||||
|
|
||||||
|
<para>This sets the <varname>FactoryResetRequested</varname> EFI variable, see below.</para>
|
||||||
|
|
||||||
|
<para>This operation is executed when the <filename>systemd-factory-reset-request.service</filename>
|
||||||
|
unit is started (which is typically one of the services hooked into
|
||||||
|
and ordered before <filename>factory-reset.target</filename>).</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>cancel</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Cancel any previously requested (but not yet executed) factory reset
|
||||||
|
operation.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>complete</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Mark an ongoing factory reset operation as complete.</para>
|
||||||
|
|
||||||
|
<para>This operation is executed when the <filename>systemd-factory-reset-complete.service</filename>
|
||||||
|
unit is started (which is typically one of the services hooked into and ordered after
|
||||||
|
<filename>factory-reset-now.target</filename>).</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Options</title>
|
||||||
|
|
||||||
|
<para>The following options are understood:</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--retrigger</option></term>
|
||||||
|
|
||||||
|
<listitem><para>When used with the <command>complete</command> command retriggers all block devices,
|
||||||
|
which might result in auto-discovered devices being usable that previously weren't because the factory
|
||||||
|
reset logic was in place.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--quiet</option></term>
|
||||||
|
<term><option>-q</option></term>
|
||||||
|
|
||||||
|
<listitem><para>Suppresses the state output of <command>status</command>, but still sets the exit
|
||||||
|
status as documented.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<xi:include href="standard-options.xml" xpointer="help" />
|
||||||
|
<xi:include href="standard-options.xml" xpointer="version" />
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>EFI Variables</title>
|
||||||
|
|
||||||
|
<para>The following EFI variable is set and read by <command>systemd-factory-reset</command>, under the
|
||||||
|
vendor UUID <literal>8cf2644b-4b0b-428f-9387-6d876050dc67</literal>, for communication between this boot
|
||||||
|
and the next.</para>
|
||||||
|
|
||||||
|
<variablelist class='efi-variables'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>FactoryResetRequest</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Set whenever a factory reset is requested from the next boot, deleted once the
|
||||||
|
factory reset is complete. Contains JSON data describing the requesting OS, in order to avoid
|
||||||
|
confusion in multi-boot systems.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</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-generator</refentrytitle><manvolnum>8</manvolnum></citerefentry></member>
|
||||||
|
<member><citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry></member>
|
||||||
|
<member><ulink url="https://systemd.io/FACTORY_RESET">Factory Reset</ulink></member>
|
||||||
|
</simplelist></para>
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
+21
-1
@@ -34,6 +34,7 @@
|
|||||||
<filename>emergency.target</filename>,
|
<filename>emergency.target</filename>,
|
||||||
<filename>exit.target</filename>,
|
<filename>exit.target</filename>,
|
||||||
<filename>factory-reset.target</filename>,
|
<filename>factory-reset.target</filename>,
|
||||||
|
<filename>factory-reset-now.target</filename>,
|
||||||
<filename>final.target</filename>,
|
<filename>final.target</filename>,
|
||||||
<filename>first-boot-complete.target</filename>,
|
<filename>first-boot-complete.target</filename>,
|
||||||
<filename>getty.target</filename>,
|
<filename>getty.target</filename>,
|
||||||
@@ -304,11 +305,30 @@
|
|||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><filename>factory-reset.target</filename></term>
|
<term><filename>factory-reset.target</filename></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>A special target to trigger a factory reset.</para>
|
<para>A special target to request a factory reset operation. This will typically persistently
|
||||||
|
store a request flag for the next boot and then reboot in order to reset the system to factory
|
||||||
|
state.</para>
|
||||||
|
|
||||||
|
<para>See <ulink url="https://systemd.io/FACTORY_RESET">Factory Reset</ulink> for more
|
||||||
|
information.</para>
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v250"/>
|
<xi:include href="version-info.xml" xpointer="v250"/>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><filename>factory-reset-now.target</filename></term>
|
||||||
|
<listitem>
|
||||||
|
<para>A special target that is started on boots that shall execute a factory reset. It may be
|
||||||
|
used to pull in additional services that shall be invoked during a factory reset operation. It
|
||||||
|
also acts as ordering barrier: once the target is reached the factory reset state is marked as
|
||||||
|
"completed".</para>
|
||||||
|
|
||||||
|
<para>See <ulink url="https://systemd.io/FACTORY_RESET">Factory Reset</ulink> for more
|
||||||
|
information.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v258"/>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><filename>final.target</filename></term>
|
<term><filename>final.target</filename></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
|||||||
@@ -2299,6 +2299,7 @@ subdir('src/detect-virt')
|
|||||||
subdir('src/dissect')
|
subdir('src/dissect')
|
||||||
subdir('src/environment-d-generator')
|
subdir('src/environment-d-generator')
|
||||||
subdir('src/escape')
|
subdir('src/escape')
|
||||||
|
subdir('src/factory-reset')
|
||||||
subdir('src/firstboot')
|
subdir('src/firstboot')
|
||||||
subdir('src/fsck')
|
subdir('src/fsck')
|
||||||
subdir('src/fstab-generator')
|
subdir('src/fstab-generator')
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "factory-reset.h"
|
||||||
|
#include "generator.h"
|
||||||
|
#include "special.h"
|
||||||
|
|
||||||
|
/* This generator pulls factory-reset-now.target into the initial transaction the kernel command line's
|
||||||
|
* systemd.factor_reset= variable, or the FactoryResetRequest EFI variable say so. */
|
||||||
|
|
||||||
|
static int run(const char *dest, const char *dest_early, const char *dest_late) {
|
||||||
|
assert(dest_early);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
log_debug("Not in factory reset mode, skipping.");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("Detected factory reset mode, pulling in factory-reset-now.target.");
|
||||||
|
|
||||||
|
/* We pull this in from basic.target so that it ends up in all "regular" boot ups, but not in
|
||||||
|
* rescue.target or even emergency.target. */
|
||||||
|
return generator_add_symlink(dest_early, SPECIAL_BASIC_TARGET, "wants", "factory-reset-now.target");
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_MAIN_GENERATOR_FUNCTION(run);
|
||||||
@@ -0,0 +1,385 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include "sd-json.h"
|
||||||
|
#include "sd-varlink.h"
|
||||||
|
|
||||||
|
#include "ansi-color.h"
|
||||||
|
#include "build.h"
|
||||||
|
#include "device-util.h"
|
||||||
|
#include "efivars.h"
|
||||||
|
#include "factory-reset.h"
|
||||||
|
#include "fs-util.h"
|
||||||
|
#include "json-util.h"
|
||||||
|
#include "main-func.h"
|
||||||
|
#include "os-util.h"
|
||||||
|
#include "pretty-print.h"
|
||||||
|
#include "udev-util.h"
|
||||||
|
#include "varlink-io.systemd.FactoryReset.h"
|
||||||
|
#include "varlink-util.h"
|
||||||
|
#include "verbs.h"
|
||||||
|
|
||||||
|
static bool arg_retrigger = false;
|
||||||
|
static bool arg_quiet = false;
|
||||||
|
static bool arg_varlink = false;
|
||||||
|
|
||||||
|
static int help(void) {
|
||||||
|
_cleanup_free_ char *link = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = terminal_urlify_man("systemd-factory-reset", "8", &link);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
printf("%1$s [OPTIONS...] COMMAND\n"
|
||||||
|
"\n%5$sQuery, request, cancel factory reset operation.%6$s\n"
|
||||||
|
"\n%3$sCommands:%4$s\n"
|
||||||
|
" status Report current factory reset status\n"
|
||||||
|
" request Request a factory reset on next boot\n"
|
||||||
|
" cancel Cancel a prior factory reset request for next boot\n"
|
||||||
|
" complete Mark a factory reset as complete\n"
|
||||||
|
"\n%3$sOptions:%4$s\n"
|
||||||
|
" -h --help Show this help\n"
|
||||||
|
" --version Print version\n"
|
||||||
|
" --retrigger Retrigger block devices\n"
|
||||||
|
" -q --quiet Suppress output\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,
|
||||||
|
ARG_RETRIGGER,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct option options[] = {
|
||||||
|
{ "help", no_argument, NULL, 'h' },
|
||||||
|
{ "version", no_argument, NULL, ARG_VERSION },
|
||||||
|
{ "retrigger", no_argument, NULL, ARG_RETRIGGER },
|
||||||
|
{ "quiet", no_argument, NULL, 'q' },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
int r, c;
|
||||||
|
|
||||||
|
assert(argc >= 0);
|
||||||
|
assert(argv);
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, "hq", options, NULL)) >= 0)
|
||||||
|
switch (c) {
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
return help();
|
||||||
|
|
||||||
|
case ARG_VERSION:
|
||||||
|
return version();
|
||||||
|
|
||||||
|
case ARG_RETRIGGER:
|
||||||
|
arg_retrigger = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
arg_quiet = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to check if invoked in Varlink mode: %m");
|
||||||
|
if (r > 0)
|
||||||
|
arg_varlink = true;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verb_status(int argc, char *argv[], void *userdata) {
|
||||||
|
static const int exit_status_table[_FACTORY_RESET_MODE_MAX] = {
|
||||||
|
/* Report current mode also as via exit status, but only return a subset of states */
|
||||||
|
[FACTORY_RESET_UNSUPPORTED] = EXIT_SUCCESS,
|
||||||
|
[FACTORY_RESET_UNSPECIFIED] = EXIT_SUCCESS,
|
||||||
|
[FACTORY_RESET_OFF] = EXIT_SUCCESS,
|
||||||
|
[FACTORY_RESET_ON] = 10,
|
||||||
|
[FACTORY_RESET_COMPLETE] = EXIT_SUCCESS,
|
||||||
|
[FACTORY_RESET_PENDING] = 11,
|
||||||
|
};
|
||||||
|
|
||||||
|
FactoryResetMode f = factory_reset_mode();
|
||||||
|
if (f < 0)
|
||||||
|
return log_error_errno(f, "Failed to determine factory reset mode: %m");
|
||||||
|
|
||||||
|
if (!arg_quiet)
|
||||||
|
puts(factory_reset_mode_to_string(f));
|
||||||
|
|
||||||
|
return exit_status_table[f];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verb_request(int argc, char *argv[], void *userdata) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
FactoryResetMode f = factory_reset_mode();
|
||||||
|
if (f < 0)
|
||||||
|
return log_error_errno(f, "Failed to determine current factory reset mode: %m");
|
||||||
|
if (f == FACTORY_RESET_ON)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "System is currently in factory reset mode, refusing to request another one.");
|
||||||
|
if (f == FACTORY_RESET_PENDING) {
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("Factory reset already requested, skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_efi_boot())
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||||
|
"Not an EFI boot, requesting factory reset via EFI variable not supported.");
|
||||||
|
|
||||||
|
_cleanup_free_ char *id = NULL, *image_id = NULL, *version_id = NULL, *image_version = NULL;
|
||||||
|
r = parse_os_release(
|
||||||
|
/* root= */ NULL,
|
||||||
|
"ID", &id,
|
||||||
|
"IMAGE_ID", &image_id,
|
||||||
|
"VERSION_ID", &version_id,
|
||||||
|
"IMAGE_VERSION", &image_version);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse os-release: %m");
|
||||||
|
|
||||||
|
if (!id)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EBADR), "os-release data lacks ID= field, refusing.");
|
||||||
|
|
||||||
|
sd_id128_t boot_id;
|
||||||
|
r = sd_id128_get_boot(&boot_id);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to get boot ID: %m");
|
||||||
|
|
||||||
|
/* NB: we don't really use the version fields for anything on the parsing side, because we want to
|
||||||
|
* allow some flexbility between OS/image versions that request the factory reset and that execute
|
||||||
|
* it. However, we include it nonetheless to make things more clearly debuggable. */
|
||||||
|
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||||
|
r = sd_json_buildo(
|
||||||
|
&v,
|
||||||
|
SD_JSON_BUILD_PAIR_STRING("osReleaseId", id),
|
||||||
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("osReleaseVersionId", version_id),
|
||||||
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("osReleaseImageId", image_id),
|
||||||
|
JSON_BUILD_PAIR_STRING_NON_EMPTY("osReleaseImageVersion", image_version),
|
||||||
|
SD_JSON_BUILD_PAIR_ID128("bootId", boot_id));
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to build JSON object: %m");
|
||||||
|
|
||||||
|
_cleanup_free_ char *formatted = NULL;
|
||||||
|
r = sd_json_variant_format(v, /* flags= */ 0, &formatted);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to format JSON object: %m");
|
||||||
|
|
||||||
|
r = efi_set_variable_string(EFI_SYSTEMD_VARIABLE_STR("FactoryResetRequest"), formatted);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to set EFI variable FactoryResetRequest: %m");
|
||||||
|
|
||||||
|
log_debug("Set EFI variable FactoryResetRequest to '%s'.", formatted);
|
||||||
|
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("Factory reset requested.");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verb_cancel(int argc, char *argv[], void *userdata) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
FactoryResetMode f = factory_reset_mode();
|
||||||
|
if (f < 0)
|
||||||
|
return log_error_errno(f, "Failed to determine current factory reset mode: %m");
|
||||||
|
if (f == FACTORY_RESET_ON)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "System already executing factory reset, cannot cancel.");
|
||||||
|
if (f != FACTORY_RESET_PENDING) {
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("No factory reset has been requested, cannot cancel, skipping.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_efi_boot()) {
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("Not an EFI boot, cannot remove FactoryResetMode EFI variable, not cancelling.");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = efi_set_variable(EFI_SYSTEMD_VARIABLE_STR("FactoryResetRequest"), /* value= */ NULL, /* size= */ 0);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to remove FactoryResetRequest EFI variable: %m");
|
||||||
|
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("Factory reset cancelled.");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int retrigger_block_devices(void) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Let's retrigger block devices after factory reset is complete: it's quite likely that some
|
||||||
|
* partitions went away or got recreated, and will only be considered relevant once factory reset
|
||||||
|
* mode is left. For example, /dev/disk/gpt-auto-root is like that: it is only created once factory
|
||||||
|
* reset mode is complete. */
|
||||||
|
|
||||||
|
if (!udev_available()) {
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("Skipping triggering of block devices, as udev is not available.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
||||||
|
r = sd_device_enumerator_new(&e);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to allocate device enumerator: %m");
|
||||||
|
|
||||||
|
r = sd_device_enumerator_allow_uninitialized(e);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to enable enumeration of uninitialized devices: %m");
|
||||||
|
|
||||||
|
r = sd_device_enumerator_add_match_subsystem(e, "block", /* match = */ true);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to filter device enumeration by 'block' subsystem: %m");
|
||||||
|
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("Retriggering block devices.");
|
||||||
|
|
||||||
|
FOREACH_DEVICE(e, d) {
|
||||||
|
r = sd_device_trigger(d, SD_DEVICE_CHANGE);
|
||||||
|
if (r < 0)
|
||||||
|
/* Devices can appear anytime, let's not loudly log about that. */
|
||||||
|
log_device_full_errno(
|
||||||
|
d,
|
||||||
|
ERRNO_IS_DEVICE_ABSENT(r) ? LOG_DEBUG : LOG_WARNING,
|
||||||
|
r,
|
||||||
|
"Failed to trigger block device, ignoring: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verb_complete(int argc, char *argv[], void *userdata) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
FactoryResetMode f = factory_reset_mode();
|
||||||
|
if (f < 0)
|
||||||
|
return log_error_errno(f, "Failed to dermine factory reset mode: %m");
|
||||||
|
log_debug("Current factory reset mode is: %s", factory_reset_mode_to_string(f));
|
||||||
|
if (f != FACTORY_RESET_ON) {
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("Attempted to leave factory reset mode, even though we are not in factory reset mode. Ignoring.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_efi_boot()) {
|
||||||
|
r = efi_set_variable(EFI_SYSTEMD_VARIABLE_STR("FactoryResetRequest"), /* value= */ NULL, /* size= */ 0);
|
||||||
|
if (r < 0)
|
||||||
|
log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
|
"Failed to remove FactoryResetRequest EFI variable: %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
r = touch("/run/systemd/factory-reset-complete");
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to create /run/systemd/factory-reset-complete file: %m");
|
||||||
|
|
||||||
|
if (!arg_quiet)
|
||||||
|
log_info("Successfully left factory reset mode.");
|
||||||
|
|
||||||
|
if (arg_retrigger)
|
||||||
|
(void) retrigger_block_devices();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vl_method_get_factory_reset_mode(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(parameters);
|
||||||
|
|
||||||
|
r = sd_varlink_dispatch(link, parameters, /* table= */ NULL, /* userdata= */ NULL);
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
FactoryResetMode f = factory_reset_mode();
|
||||||
|
if (f < 0)
|
||||||
|
return f;
|
||||||
|
|
||||||
|
return sd_varlink_replybo(link, SD_JSON_BUILD_PAIR_STRING("mode", factory_reset_mode_to_string(f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vl_method_can_request_factory_reset(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(parameters);
|
||||||
|
|
||||||
|
r = sd_varlink_dispatch(link, parameters, /* table= */ NULL, /* userdata= */ NULL);
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return sd_varlink_replybo(link, SD_JSON_BUILD_PAIR_BOOLEAN("supported", is_efi_boot()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int varlink_service(void) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Invocation as Varlink service */
|
||||||
|
|
||||||
|
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL;
|
||||||
|
r = varlink_server_new(&varlink_server, /* flags= */ 0, /* userdata= */ NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to allocate Varlink server: %m");
|
||||||
|
|
||||||
|
r = sd_varlink_server_add_interface(varlink_server, &vl_interface_io_systemd_FactoryReset);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to add Varlink interface: %m");
|
||||||
|
|
||||||
|
r = sd_varlink_server_bind_method_many(
|
||||||
|
varlink_server,
|
||||||
|
"io.systemd.FactoryReset.GetFactoryResetMode", vl_method_get_factory_reset_mode,
|
||||||
|
"io.systemd.FactoryReset.CanRequestFactoryReset", vl_method_can_request_factory_reset);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to bind Varlink methods: %m");
|
||||||
|
|
||||||
|
r = sd_varlink_server_loop_auto(varlink_server);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to run Varlink event loop: %m");
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run(int argc, char *argv[]) {
|
||||||
|
static const Verb verbs[] = {
|
||||||
|
{ "status", VERB_ANY, 1, VERB_DEFAULT, verb_status },
|
||||||
|
{ "request", VERB_ANY, 1, 0, verb_request },
|
||||||
|
{ "cancel", VERB_ANY, 1, 0, verb_cancel },
|
||||||
|
{ "complete", VERB_ANY, 1, 0, verb_complete },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
log_setup();
|
||||||
|
|
||||||
|
r = parse_argv(argc, argv);
|
||||||
|
if (r <= 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (arg_varlink)
|
||||||
|
return varlink_service();
|
||||||
|
|
||||||
|
return dispatch_verb(argc, argv, verbs, /* userdata= */ NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_MAIN_FUNCTION_WITH_POSITIVE_FAILURE(run);
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
|
executables += [
|
||||||
|
libexec_template + {
|
||||||
|
'name' : 'systemd-factory-reset',
|
||||||
|
'sources' : files('factory-reset-tool.c'),
|
||||||
|
},
|
||||||
|
generator_template + {
|
||||||
|
'name' : 'systemd-factory-reset-generator',
|
||||||
|
'sources' : files('factory-reset-generator.c'),
|
||||||
|
},
|
||||||
|
]
|
||||||
@@ -184,6 +184,7 @@ shared_sources = files(
|
|||||||
'varlink-io.systemd.AskPassword.c',
|
'varlink-io.systemd.AskPassword.c',
|
||||||
'varlink-io.systemd.BootControl.c',
|
'varlink-io.systemd.BootControl.c',
|
||||||
'varlink-io.systemd.Credentials.c',
|
'varlink-io.systemd.Credentials.c',
|
||||||
|
'varlink-io.systemd.FactoryReset.c',
|
||||||
'varlink-io.systemd.Hostname.c',
|
'varlink-io.systemd.Hostname.c',
|
||||||
'varlink-io.systemd.Import.c',
|
'varlink-io.systemd.Import.c',
|
||||||
'varlink-io.systemd.Journal.c',
|
'varlink-io.systemd.Journal.c',
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "varlink-io.systemd.FactoryReset.h"
|
||||||
|
#include "sd-varlink-idl.h"
|
||||||
|
|
||||||
|
static SD_VARLINK_DEFINE_ENUM_TYPE(
|
||||||
|
FactoryResetMode,
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Factory reset is not supported on this OS."),
|
||||||
|
SD_VARLINK_DEFINE_ENUM_VALUE(unsupported),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Factory reset not requested."),
|
||||||
|
SD_VARLINK_DEFINE_ENUM_VALUE(unspecified),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Factory reset explicitly turned off."),
|
||||||
|
SD_VARLINK_DEFINE_ENUM_VALUE(off),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Factory reset is currently being executed."),
|
||||||
|
SD_VARLINK_DEFINE_ENUM_VALUE(on),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Factory reset has been completed during the current boot."),
|
||||||
|
SD_VARLINK_DEFINE_ENUM_VALUE(complete),
|
||||||
|
SD_VARLINK_FIELD_COMMENT("Factory reset has been requested for the next boot."),
|
||||||
|
SD_VARLINK_DEFINE_ENUM_VALUE(pending));
|
||||||
|
|
||||||
|
static SD_VARLINK_DEFINE_METHOD(
|
||||||
|
GetFactoryResetMode,
|
||||||
|
SD_VARLINK_FIELD_COMMENT("The current factory reset mode"),
|
||||||
|
SD_VARLINK_DEFINE_OUTPUT_BY_TYPE(mode, FactoryResetMode, 0));
|
||||||
|
|
||||||
|
static SD_VARLINK_DEFINE_METHOD(
|
||||||
|
CanRequestFactoryReset,
|
||||||
|
SD_VARLINK_DEFINE_OUTPUT(supported, SD_VARLINK_BOOL, 0));
|
||||||
|
|
||||||
|
SD_VARLINK_DEFINE_INTERFACE(
|
||||||
|
io_systemd_FactoryReset,
|
||||||
|
"io.systemd.FactoryReset",
|
||||||
|
SD_VARLINK_INTERFACE_COMMENT("APIs to query factory reset status"),
|
||||||
|
SD_VARLINK_SYMBOL_COMMENT("Encodes the current factory reset status"),
|
||||||
|
&vl_type_FactoryResetMode,
|
||||||
|
SD_VARLINK_SYMBOL_COMMENT("Report the current factory reset status"),
|
||||||
|
&vl_method_GetFactoryResetMode,
|
||||||
|
SD_VARLINK_SYMBOL_COMMENT("Returns whether requesting a factory reset is available (by invoking the factory-reset.target unit)."),
|
||||||
|
&vl_method_CanRequestFactoryReset);
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sd-varlink-idl.h"
|
||||||
|
|
||||||
|
extern const sd_varlink_interface vl_interface_io_systemd_FactoryReset;
|
||||||
@@ -10,9 +10,10 @@
|
|||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
#include "varlink-idl-util.h"
|
#include "varlink-idl-util.h"
|
||||||
#include "varlink-io.systemd.h"
|
#include "varlink-io.systemd.h"
|
||||||
#include "varlink-io.systemd.BootControl.h"
|
|
||||||
#include "varlink-io.systemd.AskPassword.h"
|
#include "varlink-io.systemd.AskPassword.h"
|
||||||
|
#include "varlink-io.systemd.BootControl.h"
|
||||||
#include "varlink-io.systemd.Credentials.h"
|
#include "varlink-io.systemd.Credentials.h"
|
||||||
|
#include "varlink-io.systemd.FactoryReset.h"
|
||||||
#include "varlink-io.systemd.Import.h"
|
#include "varlink-io.systemd.Import.h"
|
||||||
#include "varlink-io.systemd.Journal.h"
|
#include "varlink-io.systemd.Journal.h"
|
||||||
#include "varlink-io.systemd.Login.h"
|
#include "varlink-io.systemd.Login.h"
|
||||||
@@ -203,6 +204,8 @@ TEST(parse_format) {
|
|||||||
print_separator();
|
print_separator();
|
||||||
test_parse_format_one(&vl_interface_io_systemd_Login);
|
test_parse_format_one(&vl_interface_io_systemd_Login);
|
||||||
print_separator();
|
print_separator();
|
||||||
|
test_parse_format_one(&vl_interface_io_systemd_FactoryReset);
|
||||||
|
print_separator();
|
||||||
test_parse_format_one(&vl_interface_xyz_test);
|
test_parse_format_one(&vl_interface_xyz_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Factory Reset Execution
|
||||||
|
Documentation=man:systemd.special(7)
|
||||||
|
Wants=systemd-factory-reset-complete.service
|
||||||
@@ -8,5 +8,7 @@
|
|||||||
# (at your option) any later version.
|
# (at your option) any later version.
|
||||||
|
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Factory Reset
|
Description=Factory Reset Initiation
|
||||||
Documentation=man:systemd.special(7)
|
Documentation=man:systemd.special(7)
|
||||||
|
Wants=systemd-factory-reset-reboot.service
|
||||||
|
Before=systemd-factory-reset-reboot.service
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ units = [
|
|||||||
{ 'file' : 'emergency.target' },
|
{ 'file' : 'emergency.target' },
|
||||||
{ 'file' : 'exit.target' },
|
{ 'file' : 'exit.target' },
|
||||||
{ 'file' : 'factory-reset.target' },
|
{ 'file' : 'factory-reset.target' },
|
||||||
|
{ 'file' : 'factory-reset-now.target' },
|
||||||
{ 'file' : 'final.target' },
|
{ 'file' : 'final.target' },
|
||||||
{ 'file' : 'first-boot-complete.target' },
|
{ 'file' : 'first-boot-complete.target' },
|
||||||
{ 'file' : 'getty-pre.target' },
|
{ 'file' : 'getty-pre.target' },
|
||||||
@@ -322,6 +323,19 @@ units = [
|
|||||||
},
|
},
|
||||||
{ 'file' : 'systemd-creds@.service' },
|
{ 'file' : 'systemd-creds@.service' },
|
||||||
{ 'file' : 'systemd-exit.service' },
|
{ 'file' : 'systemd-exit.service' },
|
||||||
|
{
|
||||||
|
'file' : 'systemd-factory-reset@.service.in',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'file' : 'systemd-factory-reset.socket',
|
||||||
|
'symlinks' : ['sockets.target.wants/'],
|
||||||
|
},
|
||||||
|
{ 'file' : 'systemd-factory-reset-complete.service.in' },
|
||||||
|
{ 'file' : 'systemd-factory-reset-reboot.service' },
|
||||||
|
{
|
||||||
|
'file' : 'systemd-factory-reset-request.service.in',
|
||||||
|
'symlinks' : ['factory-reset.target.wants/'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'file' : 'systemd-firstboot.service',
|
'file' : 'systemd-firstboot.service',
|
||||||
'conditions' : ['ENABLE_FIRSTBOOT'],
|
'conditions' : ['ENABLE_FIRSTBOOT'],
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Mark the Factory Reset as Completed
|
||||||
|
Documentation=man:systemd-factory-reset-complete.service(8)
|
||||||
|
DefaultDependencies=no
|
||||||
|
Requires=factory-reset-now.target
|
||||||
|
After=factory-reset-now.target
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
Before=shutdown.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart={{LIBEXECDIR}}/systemd-factory-reset complete --retrigger
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Reboot to Execute Factory Reset
|
||||||
|
Documentation=man:systemd.special(7)
|
||||||
|
DefaultDependencies=no
|
||||||
|
After=factory-reset.target
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
Before=shutdown.target
|
||||||
|
SuccessAction=reboot
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Request Factory Reset on Next Boot
|
||||||
|
Documentation=man:systemd-factory-reset-request.service(8)
|
||||||
|
DefaultDependencies=no
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
After=systemd-pcrphase-factory-reset.service
|
||||||
|
Before=factory-reset.target shutdown.target
|
||||||
|
ConditionFirmware=uefi
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=yes
|
||||||
|
ExecStart={{LIBEXECDIR}}/systemd-factory-reset request
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Factory Reset Management
|
||||||
|
Documentation=man:systemd-factory-reset.service(8)
|
||||||
|
DefaultDependencies=no
|
||||||
|
Before=sockets.target
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=/run/systemd/io.systemd.FactoryReset
|
||||||
|
FileDescriptorName=varlink
|
||||||
|
SocketMode=0666
|
||||||
|
Accept=yes
|
||||||
|
MaxConnectionsPerSource=16
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Factory Reset Management (Varlink)
|
||||||
|
Documentation=man:systemd-factory-reset@.service(8)
|
||||||
|
DefaultDependencies=no
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
Before=shutdown.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=-{{LIBEXECDIR}}/systemd-factory-reset
|
||||||
@@ -22,7 +22,7 @@ ConditionDirectoryNotEmpty=|/sysusr/usr/local/lib/repart.d
|
|||||||
DefaultDependencies=no
|
DefaultDependencies=no
|
||||||
Wants=modprobe@loop.service modprobe@dm_mod.service
|
Wants=modprobe@loop.service modprobe@dm_mod.service
|
||||||
After=initrd-usr-fs.target modprobe@loop.service modprobe@dm_mod.service systemd-tpm2-setup-early.service
|
After=initrd-usr-fs.target modprobe@loop.service modprobe@dm_mod.service systemd-tpm2-setup-early.service
|
||||||
Before=initrd-root-fs.target
|
Before=initrd-root-fs.target factory-reset-now.target
|
||||||
Conflicts=shutdown.target initrd-switch-root.target
|
Conflicts=shutdown.target initrd-switch-root.target
|
||||||
Before=shutdown.target initrd-switch-root.target
|
Before=shutdown.target initrd-switch-root.target
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user