Compare commits
12 Commits
a61f5f4fa7
...
a8c1edfc34
Author | SHA1 | Date |
---|---|---|
nkraetzschmar | a8c1edfc34 | |
Lennart Poettering | 92033d8fba | |
Lennart Poettering | 209a9e7bf3 | |
Luca Boccassi | 0abaa5be10 | |
Zbigniew Jędrzejewski-Szmek | ef20d06da6 | |
Adrian Vovk | f2751d757f | |
Adrian Vovk | ef370a3c30 | |
Adrian Vovk | e2501a851e | |
Adrian Vovk | 5a10a9a3bb | |
anonymix007 | 098e44d03c | |
anonymix007 | cf331f1c9b | |
nkraetzschmar | 76e563900e |
3
TODO
3
TODO
|
@ -129,6 +129,9 @@ Deprecations and removals:
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
|
* our logging tools should look for $DEBUG_INVOCATION and consider equivalent
|
||||||
|
to $SYSTEMD_LOG_LEVEL=debug
|
||||||
|
|
||||||
* Teach systemd-ssh-generator to generated an /run/issue.d/ drop-in telling
|
* Teach systemd-ssh-generator to generated an /run/issue.d/ drop-in telling
|
||||||
users how to connect to the system via the AF_VSOCK, as per:
|
users how to connect to the system via the AF_VSOCK, as per:
|
||||||
https://github.com/systemd/systemd/issues/35071#issuecomment-2462803142
|
https://github.com/systemd/systemd/issues/35071#issuecomment-2462803142
|
||||||
|
|
|
@ -399,6 +399,14 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>reboot-on-error</term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean argument. Enable or disable (the default) auto reboot in case the selected entry fails to start.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,9 @@
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Options</title>
|
<title>Options</title>
|
||||||
|
|
||||||
<para>All options are configured in the
|
<para>All options are configured in the [Manager] section:</para>
|
||||||
[Manager] section:</para>
|
|
||||||
|
|
||||||
<variablelist class='config-directives'>
|
<variablelist class='config-directives'>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>LogColor=</varname></term>
|
<term><varname>LogColor=</varname></term>
|
||||||
<term><varname>LogLevel=</varname></term>
|
<term><varname>LogLevel=</varname></term>
|
||||||
|
@ -105,6 +103,65 @@
|
||||||
<xi:include href="version-info.xml" xpointer="v232"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v232"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>StatusUnitFormat=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes <option>name</option>, <option>description</option> or
|
||||||
|
<option>combined</option> as the value. If <option>name</option>, the system manager will use unit
|
||||||
|
names in status messages (e.g. <literal>systemd-journald.service</literal>), instead of the longer
|
||||||
|
and more informative descriptions set with <varname>Description=</varname> (e.g. <literal>Journal
|
||||||
|
Logging Service</literal>). If <option>combined</option>, the system manager will use both unit names
|
||||||
|
and descriptions in status messages (e.g. <literal>systemd-journald.service - Journal Logging
|
||||||
|
Service</literal>).</para>
|
||||||
|
|
||||||
|
<para>See
|
||||||
|
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||||
|
details about unit names and <varname>Description=</varname>.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v243"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>DefaultTimerAccuracySec=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Sets the default accuracy of timer units. This
|
||||||
|
controls the global default for the
|
||||||
|
<varname>AccuracySec=</varname> setting of timer units, see
|
||||||
|
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
for details. <varname>AccuracySec=</varname> set in individual
|
||||||
|
units override the global default for the specific unit.
|
||||||
|
Defaults to 1min. Note that the accuracy of timer units is
|
||||||
|
also affected by the configured timer slack for PID 1, see
|
||||||
|
<varname>TimerSlackNSec=</varname> above.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v212"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Resource Management</title>
|
||||||
|
|
||||||
|
<variablelist class='config-directives'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>TimerSlackNSec=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Sets the timer slack in nanoseconds for PID 1,
|
||||||
|
which is inherited by all executed processes, unless
|
||||||
|
overridden individually, for example with the
|
||||||
|
<varname>TimerSlackNSec=</varname> setting in service units
|
||||||
|
(for details see
|
||||||
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||||
|
The timer slack controls the accuracy of wake-ups triggered by
|
||||||
|
system timers. See
|
||||||
|
<citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||||
|
for more information. Note that in contrast to most other time
|
||||||
|
span definitions this parameter takes an integer value in
|
||||||
|
nano-seconds if no unit is specified. The usual time units are
|
||||||
|
understood too.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v198"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>CPUAffinity=</varname></term>
|
<term><varname>CPUAffinity=</varname></term>
|
||||||
|
|
||||||
|
@ -143,355 +200,6 @@
|
||||||
<xi:include href="version-info.xml" xpointer="v243"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v243"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>RuntimeWatchdogSec=</varname></term>
|
|
||||||
<term><varname>RebootWatchdogSec=</varname></term>
|
|
||||||
<term><varname>KExecWatchdogSec=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configure the hardware watchdog at runtime and at reboot. Takes a timeout value in
|
|
||||||
seconds (or in other time units if suffixed with <literal>ms</literal>, <literal>min</literal>,
|
|
||||||
<literal>h</literal>, <literal>d</literal>, <literal>w</literal>), or the special strings
|
|
||||||
<literal>off</literal> or <literal>default</literal>. If set to <literal>off</literal>
|
|
||||||
(alternatively: <literal>0</literal>) the watchdog logic is disabled: no watchdog device is opened,
|
|
||||||
configured, or pinged. If set to the special string <literal>default</literal> the watchdog is opened
|
|
||||||
and pinged in regular intervals, but the timeout is not changed from the default. If set to any other
|
|
||||||
time value the watchdog timeout is configured to the specified value (or a value close to it,
|
|
||||||
depending on hardware capabilities).</para>
|
|
||||||
|
|
||||||
<para>If <varname>RuntimeWatchdogSec=</varname> is set to a non-zero value, the watchdog hardware
|
|
||||||
(<filename>/dev/watchdog0</filename> or the path specified with <varname>WatchdogDevice=</varname> or
|
|
||||||
the kernel option <varname>systemd.watchdog-device=</varname>) will be programmed to automatically
|
|
||||||
reboot the system if it is not contacted within the specified timeout interval. The system manager
|
|
||||||
will ensure to contact it at least once in half the specified timeout interval. This feature requires
|
|
||||||
a hardware watchdog device to be present, as it is commonly the case in embedded and server
|
|
||||||
systems. Not all hardware watchdogs allow configuration of all possible reboot timeout values, in
|
|
||||||
which case the closest available timeout is picked.</para>
|
|
||||||
|
|
||||||
<para><varname>RebootWatchdogSec=</varname> may be used to configure the hardware watchdog when the
|
|
||||||
system is asked to reboot. It works as a safety net to ensure that the reboot takes place even if a
|
|
||||||
clean reboot attempt times out. Note that the <varname>RebootWatchdogSec=</varname> timeout applies
|
|
||||||
only to the second phase of the reboot, i.e. after all regular services are already terminated, and
|
|
||||||
after the system and service manager process (PID 1) got replaced by the
|
|
||||||
<filename>systemd-shutdown</filename> binary, see system
|
|
||||||
<citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
|
||||||
details. During the first phase of the shutdown operation the system and service manager remains
|
|
||||||
running and hence <varname>RuntimeWatchdogSec=</varname> is still honoured. In order to define a
|
|
||||||
timeout on this first phase of system shutdown, configure <varname>JobTimeoutSec=</varname> and
|
|
||||||
<varname>JobTimeoutAction=</varname> in the [Unit] section of the
|
|
||||||
<filename>shutdown.target</filename> unit. By default <varname>RuntimeWatchdogSec=</varname> defaults
|
|
||||||
to 0 (off), and <varname>RebootWatchdogSec=</varname> to 10min.</para>
|
|
||||||
|
|
||||||
<para><varname>KExecWatchdogSec=</varname> may be used to additionally enable the watchdog when kexec
|
|
||||||
is being executed rather than when rebooting. Note that if the kernel does not reset the watchdog on
|
|
||||||
kexec (depending on the specific hardware and/or driver), in this case the watchdog might not get
|
|
||||||
disabled after kexec succeeds and thus the system might get rebooted, unless
|
|
||||||
<varname>RuntimeWatchdogSec=</varname> is also enabled at the same time. For this reason it is
|
|
||||||
recommended to enable <varname>KExecWatchdogSec=</varname> only if
|
|
||||||
<varname>RuntimeWatchdogSec=</varname> is also enabled.</para>
|
|
||||||
|
|
||||||
<para>These settings have no effect if a hardware watchdog is not available.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v198"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>RuntimeWatchdogPreSec=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configure the hardware watchdog device pre-timeout value.
|
|
||||||
Takes a timeout value in seconds (or in other time units similar to
|
|
||||||
<varname>RuntimeWatchdogSec=</varname>). A watchdog pre-timeout is a
|
|
||||||
notification generated by the watchdog before the watchdog reset might
|
|
||||||
occur in the event the watchdog has not been serviced. This notification
|
|
||||||
is handled by the kernel and can be configured to take an action (i.e.
|
|
||||||
generate a kernel panic) using <varname>RuntimeWatchdogPreGovernor=</varname>.
|
|
||||||
Not all watchdog hardware or drivers support generating a pre-timeout and
|
|
||||||
depending on the state of the system, the kernel may be unable to take the
|
|
||||||
configured action before the watchdog reboot. The watchdog will be configured
|
|
||||||
to generate the pre-timeout event at the amount of time specified by
|
|
||||||
<varname>RuntimeWatchdogPreSec=</varname> before the runtime watchdog timeout
|
|
||||||
(set by <varname>RuntimeWatchdogSec=</varname>). For example, if the we have
|
|
||||||
<varname>RuntimeWatchdogSec=30</varname> and
|
|
||||||
<varname>RuntimeWatchdogPreSec=10</varname>, then the pre-timeout event
|
|
||||||
will occur if the watchdog has not pinged for 20s (10s before the
|
|
||||||
watchdog would fire). By default, <varname>RuntimeWatchdogPreSec=</varname>
|
|
||||||
defaults to 0 (off). The value set for <varname>RuntimeWatchdogPreSec=</varname>
|
|
||||||
must be smaller than the timeout value for <varname>RuntimeWatchdogSec=</varname>.
|
|
||||||
This setting has no effect if a hardware watchdog is not available or the
|
|
||||||
hardware watchdog does not support a pre-timeout and will be ignored by the
|
|
||||||
kernel if the setting is greater than the actual watchdog timeout.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>RuntimeWatchdogPreGovernor=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configure the action taken by the hardware watchdog device
|
|
||||||
when the pre-timeout expires. The default action for the pre-timeout event
|
|
||||||
depends on the kernel configuration, but it is usually to log a kernel
|
|
||||||
message. For a list of valid actions available for a given watchdog device,
|
|
||||||
check the content of the
|
|
||||||
<filename>/sys/class/watchdog/watchdog<replaceable>X</replaceable>/pretimeout_available_governors</filename>
|
|
||||||
file. Typically, available governor types are <varname>noop</varname> and <varname>panic</varname>.
|
|
||||||
Availability, names and functionality might vary depending on the specific device driver
|
|
||||||
in use. If the <filename>pretimeout_available_governors</filename> sysfs file is empty,
|
|
||||||
the governor might be built as a kernel module and might need to be manually loaded
|
|
||||||
(e.g. <varname>pretimeout_noop.ko</varname>), or the watchdog device might not support
|
|
||||||
pre-timeouts.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>WatchdogDevice=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configure the hardware watchdog device that the
|
|
||||||
runtime and shutdown watchdog timers will open and use. Defaults
|
|
||||||
to <filename>/dev/watchdog0</filename>. This setting has no
|
|
||||||
effect if a hardware watchdog is not available.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v236"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>CapabilityBoundingSet=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Controls which capabilities to include in the
|
|
||||||
capability bounding set for PID 1 and its children. See
|
|
||||||
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
|
||||||
for details. Takes a whitespace-separated list of capability
|
|
||||||
names as read by
|
|
||||||
<citerefentry project='mankier'><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
|
||||||
Capabilities listed will be included in the bounding set, all
|
|
||||||
others are removed. If the list of capabilities is prefixed
|
|
||||||
with ~, all but the listed capabilities will be included, the
|
|
||||||
effect of the assignment inverted. Note that this option also
|
|
||||||
affects the respective capabilities in the effective,
|
|
||||||
permitted and inheritable capability sets. The capability
|
|
||||||
bounding set may also be individually configured for units
|
|
||||||
using the <varname>CapabilityBoundingSet=</varname> directive
|
|
||||||
for units, but note that capabilities dropped for PID 1 cannot
|
|
||||||
be regained in individual units, they are lost for
|
|
||||||
good.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v198"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>NoNewPrivileges=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Takes a boolean argument. If true, ensures that PID 1
|
|
||||||
and all its children can never gain new privileges through
|
|
||||||
<citerefentry project='man-pages'><refentrytitle>execve</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
|
||||||
(e.g. via setuid or setgid bits, or filesystem capabilities).
|
|
||||||
Defaults to false. General purpose distributions commonly rely
|
|
||||||
on executables with setuid or setgid bits and will thus not
|
|
||||||
function properly with this option enabled. Individual units
|
|
||||||
cannot disable this option.
|
|
||||||
Also see <ulink url="https://docs.kernel.org/userspace-api/no_new_privs.html">No New Privileges Flag</ulink>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v239"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>ProtectSystem=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Takes a boolean argument or the string <literal>auto</literal>. If set to true this
|
|
||||||
will remount <filename>/usr/</filename> read-only. If set to <literal>auto</literal> (the default)
|
|
||||||
and running in an initrd equivalent to true, otherwise false. This implements a restricted subset of
|
|
||||||
the per-unit setting of the same name, see
|
|
||||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
|
||||||
details: currently, the <literal>full</literal> or <literal>strict</literal> values are not
|
|
||||||
supported.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>SystemCallArchitectures=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Takes a space-separated list of architecture
|
|
||||||
identifiers. Selects from which architectures system calls may
|
|
||||||
be invoked on this system. This may be used as an effective
|
|
||||||
way to disable invocation of non-native binaries system-wide,
|
|
||||||
for example to prohibit execution of 32-bit x86 binaries on
|
|
||||||
64-bit x86-64 systems. This option operates system-wide, and
|
|
||||||
acts similar to the
|
|
||||||
<varname>SystemCallArchitectures=</varname> setting of unit
|
|
||||||
files, see
|
|
||||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
||||||
for details. This setting defaults to the empty list, in which
|
|
||||||
case no filtering of system calls based on architecture is
|
|
||||||
applied. Known architecture identifiers are
|
|
||||||
<literal>x86</literal>, <literal>x86-64</literal>,
|
|
||||||
<literal>x32</literal>, <literal>arm</literal> and the special
|
|
||||||
identifier <literal>native</literal>. The latter implicitly
|
|
||||||
maps to the native architecture of the system (or more
|
|
||||||
specifically, the architecture the system manager was compiled
|
|
||||||
for). Set this setting to <literal>native</literal> to
|
|
||||||
prohibit execution of any non-native binaries. When a binary
|
|
||||||
executes a system call of an architecture that is not listed
|
|
||||||
in this setting, it will be immediately terminated with the
|
|
||||||
SIGSYS signal.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v209"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>TimerSlackNSec=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Sets the timer slack in nanoseconds for PID 1,
|
|
||||||
which is inherited by all executed processes, unless
|
|
||||||
overridden individually, for example with the
|
|
||||||
<varname>TimerSlackNSec=</varname> setting in service units
|
|
||||||
(for details see
|
|
||||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
|
||||||
The timer slack controls the accuracy of wake-ups triggered by
|
|
||||||
system timers. See
|
|
||||||
<citerefentry><refentrytitle>prctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
|
||||||
for more information. Note that in contrast to most other time
|
|
||||||
span definitions this parameter takes an integer value in
|
|
||||||
nano-seconds if no unit is specified. The usual time units are
|
|
||||||
understood too.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v198"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>StatusUnitFormat=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Takes <option>name</option>, <option>description</option> or
|
|
||||||
<option>combined</option> as the value. If <option>name</option>, the system manager will use unit
|
|
||||||
names in status messages (e.g. <literal>systemd-journald.service</literal>), instead of the longer
|
|
||||||
and more informative descriptions set with <varname>Description=</varname> (e.g. <literal>Journal
|
|
||||||
Logging Service</literal>). If <option>combined</option>, the system manager will use both unit names
|
|
||||||
and descriptions in status messages (e.g. <literal>systemd-journald.service - Journal Logging
|
|
||||||
Service</literal>).</para>
|
|
||||||
|
|
||||||
<para>See
|
|
||||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
|
||||||
details about unit names and <varname>Description=</varname>.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v243"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>DefaultTimerAccuracySec=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Sets the default accuracy of timer units. This
|
|
||||||
controls the global default for the
|
|
||||||
<varname>AccuracySec=</varname> setting of timer units, see
|
|
||||||
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
||||||
for details. <varname>AccuracySec=</varname> set in individual
|
|
||||||
units override the global default for the specific unit.
|
|
||||||
Defaults to 1min. Note that the accuracy of timer units is
|
|
||||||
also affected by the configured timer slack for PID 1, see
|
|
||||||
<varname>TimerSlackNSec=</varname> above.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v212"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>DefaultTimeoutStartSec=</varname></term>
|
|
||||||
<term><varname>DefaultTimeoutStopSec=</varname></term>
|
|
||||||
<term><varname>DefaultTimeoutAbortSec=</varname></term>
|
|
||||||
<term><varname>DefaultRestartSec=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configures the default timeouts for starting, stopping and aborting of units, as well
|
|
||||||
as the default time to sleep between automatic restarts of units, as configured per-unit in
|
|
||||||
<varname>TimeoutStartSec=</varname>, <varname>TimeoutStopSec=</varname>,
|
|
||||||
<varname>TimeoutAbortSec=</varname> and <varname>RestartSec=</varname> (for services, see
|
|
||||||
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
||||||
for details on the per-unit settings). For non-service units,
|
|
||||||
<varname>DefaultTimeoutStartSec=</varname> sets the default <varname>TimeoutSec=</varname> value.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para><varname>DefaultTimeoutStartSec=</varname> and <varname>DefaultTimeoutStopSec=</varname>
|
|
||||||
default to &DEFAULT_TIMEOUT; in the system manager and &DEFAULT_USER_TIMEOUT; in the user manager.
|
|
||||||
<varname>DefaultTimeoutAbortSec=</varname> is not set by default so that all units fall back to
|
|
||||||
<varname>TimeoutStopSec=</varname>. <varname>DefaultRestartSec=</varname> defaults to 100 ms.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v209"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>DefaultDeviceTimeoutSec=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configures the default timeout for waiting for devices. It can be changed per
|
|
||||||
device via the <varname>x-systemd.device-timeout=</varname> option in <filename>/etc/fstab</filename>
|
|
||||||
and <filename>/etc/crypttab</filename> (see
|
|
||||||
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
|
||||||
<citerefentry><refentrytitle>crypttab</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
|
||||||
Defaults to &DEFAULT_TIMEOUT; in the system manager and &DEFAULT_USER_TIMEOUT; in the user manager.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>DefaultStartLimitIntervalSec=</varname></term>
|
|
||||||
<term><varname>DefaultStartLimitBurst=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configure the default unit start rate
|
|
||||||
limiting, as configured per-service by
|
|
||||||
<varname>StartLimitIntervalSec=</varname> and
|
|
||||||
<varname>StartLimitBurst=</varname>. See
|
|
||||||
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
|
||||||
for details on the per-service settings.
|
|
||||||
<varname>DefaultStartLimitIntervalSec=</varname> defaults to
|
|
||||||
10s. <varname>DefaultStartLimitBurst=</varname> defaults to
|
|
||||||
5.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v209"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>DefaultEnvironment=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configures environment variables passed to all executed processes. Takes a
|
|
||||||
space-separated list of variable assignments. See <citerefentry
|
|
||||||
project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
|
||||||
details about environment variables.</para>
|
|
||||||
|
|
||||||
<para>Simple <literal>%</literal>-specifier expansion is supported, see below for a list of supported
|
|
||||||
specifiers.</para>
|
|
||||||
|
|
||||||
<para>Example:
|
|
||||||
|
|
||||||
<programlisting>DefaultEnvironment="VAR1=word1 word2" VAR2=word3 "VAR3=word 5 6"</programlisting>
|
|
||||||
|
|
||||||
Sets three variables
|
|
||||||
<literal>VAR1</literal>,
|
|
||||||
<literal>VAR2</literal>,
|
|
||||||
<literal>VAR3</literal>.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v205"/></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>ManagerEnvironment=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Takes the same arguments as <varname>DefaultEnvironment=</varname>, see above. Sets
|
|
||||||
environment variables for the manager process itself. These variables are inherited by processes
|
|
||||||
spawned by user managers, but not the system manager - use <varname>DefaultEnvironment=</varname>
|
|
||||||
for that. Note that these variables are merged into the existing environment block. In particular, in
|
|
||||||
case of the system manager, this includes variables set by the kernel based on the kernel command line.
|
|
||||||
As with <varname>DefaultEnvironment=</varname>, this environment block is internal, and changes are not
|
|
||||||
reflected in the manager's <filename>/proc/PID/environ</filename>.</para>
|
|
||||||
|
|
||||||
<para>Setting environment variables for the manager process may be useful to modify its behaviour.
|
|
||||||
See <ulink url="https://systemd.io/ENVIRONMENT">Known Environment Variables</ulink> for a
|
|
||||||
descriptions of some variables understood by <command>systemd</command>.</para>
|
|
||||||
|
|
||||||
<para>Simple <literal>%</literal>-specifier expansion is supported, see below for a list of supported
|
|
||||||
specifiers.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v248"/>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>DefaultCPUAccounting=</varname></term>
|
<term><varname>DefaultCPUAccounting=</varname></term>
|
||||||
<term><varname>DefaultMemoryAccounting=</varname></term>
|
<term><varname>DefaultMemoryAccounting=</varname></term>
|
||||||
|
@ -608,6 +316,227 @@
|
||||||
<xi:include href="version-info.xml" xpointer="v250"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v250"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>DefaultMemoryPressureWatch=</varname></term>
|
||||||
|
<term><varname>DefaultMemoryPressureThresholdSec=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Configures the default settings for the per-unit
|
||||||
|
<varname>MemoryPressureWatch=</varname> and <varname>MemoryPressureThresholdSec=</varname>
|
||||||
|
settings. See
|
||||||
|
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
for details. Defaults to <literal>auto</literal> and <literal>200ms</literal>, respectively. This
|
||||||
|
also sets the memory pressure monitoring threshold for the service manager itself.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Hardware Watchdog</title>
|
||||||
|
|
||||||
|
<variablelist class='config-directives'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>RuntimeWatchdogSec=</varname></term>
|
||||||
|
<term><varname>RebootWatchdogSec=</varname></term>
|
||||||
|
<term><varname>KExecWatchdogSec=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Configure the hardware watchdog at runtime and at reboot. Takes a timeout value in
|
||||||
|
seconds (or in other time units if suffixed with <literal>ms</literal>, <literal>min</literal>,
|
||||||
|
<literal>h</literal>, <literal>d</literal>, <literal>w</literal>), or the special strings
|
||||||
|
<literal>off</literal> or <literal>default</literal>. If set to <literal>off</literal>
|
||||||
|
(alternatively: <literal>0</literal>) the watchdog logic is disabled: no watchdog device is opened,
|
||||||
|
configured, or pinged. If set to the special string <literal>default</literal> the watchdog is opened
|
||||||
|
and pinged in regular intervals, but the timeout is not changed from the default. If set to any other
|
||||||
|
time value the watchdog timeout is configured to the specified value (or a value close to it,
|
||||||
|
depending on hardware capabilities).</para>
|
||||||
|
|
||||||
|
<para>If <varname>RuntimeWatchdogSec=</varname> is set to a non-zero value, the watchdog hardware
|
||||||
|
(<filename>/dev/watchdog0</filename> or the path specified with <varname>WatchdogDevice=</varname> or
|
||||||
|
the kernel option <varname>systemd.watchdog-device=</varname>) will be programmed to automatically
|
||||||
|
reboot the system if it is not contacted within the specified timeout interval. The system manager
|
||||||
|
will ensure to contact it at least once in half the specified timeout interval. This feature requires
|
||||||
|
a hardware watchdog device to be present, as it is commonly the case in embedded and server
|
||||||
|
systems. Not all hardware watchdogs allow configuration of all possible reboot timeout values, in
|
||||||
|
which case the closest available timeout is picked.</para>
|
||||||
|
|
||||||
|
<para><varname>RebootWatchdogSec=</varname> may be used to configure the hardware watchdog when the
|
||||||
|
system is asked to reboot. It works as a safety net to ensure that the reboot takes place even if a
|
||||||
|
clean reboot attempt times out. Note that the <varname>RebootWatchdogSec=</varname> timeout applies
|
||||||
|
only to the second phase of the reboot, i.e. after all regular services are already terminated, and
|
||||||
|
after the system and service manager process (PID 1) got replaced by the
|
||||||
|
<filename>systemd-shutdown</filename> binary, see system
|
||||||
|
<citerefentry><refentrytitle>bootup</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||||
|
details. During the first phase of the shutdown operation the system and service manager remains
|
||||||
|
running and hence <varname>RuntimeWatchdogSec=</varname> is still honoured. In order to define a
|
||||||
|
timeout on this first phase of system shutdown, configure <varname>JobTimeoutSec=</varname> and
|
||||||
|
<varname>JobTimeoutAction=</varname> in the [Unit] section of the
|
||||||
|
<filename>shutdown.target</filename> unit. By default <varname>RuntimeWatchdogSec=</varname> defaults
|
||||||
|
to 0 (off), and <varname>RebootWatchdogSec=</varname> to 10min.</para>
|
||||||
|
|
||||||
|
<para><varname>KExecWatchdogSec=</varname> may be used to additionally enable the watchdog when kexec
|
||||||
|
is being executed rather than when rebooting. Note that if the kernel does not reset the watchdog on
|
||||||
|
kexec (depending on the specific hardware and/or driver), in this case the watchdog might not get
|
||||||
|
disabled after kexec succeeds and thus the system might get rebooted, unless
|
||||||
|
<varname>RuntimeWatchdogSec=</varname> is also enabled at the same time. For this reason it is
|
||||||
|
recommended to enable <varname>KExecWatchdogSec=</varname> only if
|
||||||
|
<varname>RuntimeWatchdogSec=</varname> is also enabled.</para>
|
||||||
|
|
||||||
|
<para>These settings have no effect if a hardware watchdog is not available.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v198"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>RuntimeWatchdogPreSec=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Configure the hardware watchdog device pre-timeout value.
|
||||||
|
Takes a timeout value in seconds (or in other time units similar to
|
||||||
|
<varname>RuntimeWatchdogSec=</varname>). A watchdog pre-timeout is a
|
||||||
|
notification generated by the watchdog before the watchdog reset might
|
||||||
|
occur in the event the watchdog has not been serviced. This notification
|
||||||
|
is handled by the kernel and can be configured to take an action (i.e.
|
||||||
|
generate a kernel panic) using <varname>RuntimeWatchdogPreGovernor=</varname>.
|
||||||
|
Not all watchdog hardware or drivers support generating a pre-timeout and
|
||||||
|
depending on the state of the system, the kernel may be unable to take the
|
||||||
|
configured action before the watchdog reboot. The watchdog will be configured
|
||||||
|
to generate the pre-timeout event at the amount of time specified by
|
||||||
|
<varname>RuntimeWatchdogPreSec=</varname> before the runtime watchdog timeout
|
||||||
|
(set by <varname>RuntimeWatchdogSec=</varname>). For example, if the we have
|
||||||
|
<varname>RuntimeWatchdogSec=30</varname> and
|
||||||
|
<varname>RuntimeWatchdogPreSec=10</varname>, then the pre-timeout event
|
||||||
|
will occur if the watchdog has not pinged for 20s (10s before the
|
||||||
|
watchdog would fire). By default, <varname>RuntimeWatchdogPreSec=</varname>
|
||||||
|
defaults to 0 (off). The value set for <varname>RuntimeWatchdogPreSec=</varname>
|
||||||
|
must be smaller than the timeout value for <varname>RuntimeWatchdogSec=</varname>.
|
||||||
|
This setting has no effect if a hardware watchdog is not available or the
|
||||||
|
hardware watchdog does not support a pre-timeout and will be ignored by the
|
||||||
|
kernel if the setting is greater than the actual watchdog timeout.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>RuntimeWatchdogPreGovernor=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Configure the action taken by the hardware watchdog device
|
||||||
|
when the pre-timeout expires. The default action for the pre-timeout event
|
||||||
|
depends on the kernel configuration, but it is usually to log a kernel
|
||||||
|
message. For a list of valid actions available for a given watchdog device,
|
||||||
|
check the content of the
|
||||||
|
<filename>/sys/class/watchdog/watchdog<replaceable>X</replaceable>/pretimeout_available_governors</filename>
|
||||||
|
file. Typically, available governor types are <varname>noop</varname> and <varname>panic</varname>.
|
||||||
|
Availability, names and functionality might vary depending on the specific device driver
|
||||||
|
in use. If the <filename>pretimeout_available_governors</filename> sysfs file is empty,
|
||||||
|
the governor might be built as a kernel module and might need to be manually loaded
|
||||||
|
(e.g. <varname>pretimeout_noop.ko</varname>), or the watchdog device might not support
|
||||||
|
pre-timeouts.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v251"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>WatchdogDevice=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Configure the hardware watchdog device that the
|
||||||
|
runtime and shutdown watchdog timers will open and use. Defaults
|
||||||
|
to <filename>/dev/watchdog0</filename>. This setting has no
|
||||||
|
effect if a hardware watchdog is not available.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v236"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Security</title>
|
||||||
|
|
||||||
|
<variablelist class='config-directives'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>CapabilityBoundingSet=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Controls which capabilities to include in the
|
||||||
|
capability bounding set for PID 1 and its children. See
|
||||||
|
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||||
|
for details. Takes a whitespace-separated list of capability
|
||||||
|
names as read by
|
||||||
|
<citerefentry project='mankier'><refentrytitle>cap_from_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||||
|
Capabilities listed will be included in the bounding set, all
|
||||||
|
others are removed. If the list of capabilities is prefixed
|
||||||
|
with ~, all but the listed capabilities will be included, the
|
||||||
|
effect of the assignment inverted. Note that this option also
|
||||||
|
affects the respective capabilities in the effective,
|
||||||
|
permitted and inheritable capability sets. The capability
|
||||||
|
bounding set may also be individually configured for units
|
||||||
|
using the <varname>CapabilityBoundingSet=</varname> directive
|
||||||
|
for units, but note that capabilities dropped for PID 1 cannot
|
||||||
|
be regained in individual units, they are lost for
|
||||||
|
good.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v198"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>NoNewPrivileges=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean argument. If true, ensures that PID 1
|
||||||
|
and all its children can never gain new privileges through
|
||||||
|
<citerefentry project='man-pages'><refentrytitle>execve</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||||
|
(e.g. via setuid or setgid bits, or filesystem capabilities).
|
||||||
|
Defaults to false. General purpose distributions commonly rely
|
||||||
|
on executables with setuid or setgid bits and will thus not
|
||||||
|
function properly with this option enabled. Individual units
|
||||||
|
cannot disable this option.
|
||||||
|
Also see <ulink url="https://docs.kernel.org/userspace-api/no_new_privs.html">No New Privileges Flag</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v239"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>ProtectSystem=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean argument or the string <literal>auto</literal>. If set to true this
|
||||||
|
will remount <filename>/usr/</filename> read-only. If set to <literal>auto</literal> (the default)
|
||||||
|
and running in an initrd equivalent to true, otherwise false. This implements a restricted subset of
|
||||||
|
the per-unit setting of the same name, see
|
||||||
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||||
|
details: currently, the <literal>full</literal> or <literal>strict</literal> values are not
|
||||||
|
supported.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>SystemCallArchitectures=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a space-separated list of architecture
|
||||||
|
identifiers. Selects from which architectures system calls may
|
||||||
|
be invoked on this system. This may be used as an effective
|
||||||
|
way to disable invocation of non-native binaries system-wide,
|
||||||
|
for example to prohibit execution of 32-bit x86 binaries on
|
||||||
|
64-bit x86-64 systems. This option operates system-wide, and
|
||||||
|
acts similar to the
|
||||||
|
<varname>SystemCallArchitectures=</varname> setting of unit
|
||||||
|
files, see
|
||||||
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
for details. This setting defaults to the empty list, in which
|
||||||
|
case no filtering of system calls based on architecture is
|
||||||
|
applied. Known architecture identifiers are
|
||||||
|
<literal>x86</literal>, <literal>x86-64</literal>,
|
||||||
|
<literal>x32</literal>, <literal>arm</literal> and the special
|
||||||
|
identifier <literal>native</literal>. The latter implicitly
|
||||||
|
maps to the native architecture of the system (or more
|
||||||
|
specifically, the architecture the system manager was compiled
|
||||||
|
for). Set this setting to <literal>native</literal> to
|
||||||
|
prohibit execution of any non-native binaries. When a binary
|
||||||
|
executes a system call of an architecture that is not listed
|
||||||
|
in this setting, it will be immediately terminated with the
|
||||||
|
SIGSYS signal.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v209"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>DefaultSmackProcessLabel=</varname></term>
|
<term><varname>DefaultSmackProcessLabel=</varname></term>
|
||||||
|
|
||||||
|
@ -621,6 +550,67 @@
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Timeouts and Rate Limits</title>
|
||||||
|
|
||||||
|
<variablelist class='config-directives'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>DefaultTimeoutStartSec=</varname></term>
|
||||||
|
<term><varname>DefaultTimeoutStopSec=</varname></term>
|
||||||
|
<term><varname>DefaultTimeoutAbortSec=</varname></term>
|
||||||
|
<term><varname>DefaultRestartSec=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Configures the default timeouts for starting, stopping and aborting of units, as well
|
||||||
|
as the default time to sleep between automatic restarts of units, as configured per-unit in
|
||||||
|
<varname>TimeoutStartSec=</varname>, <varname>TimeoutStopSec=</varname>,
|
||||||
|
<varname>TimeoutAbortSec=</varname> and <varname>RestartSec=</varname> (for services, see
|
||||||
|
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
for details on the per-unit settings). For non-service units,
|
||||||
|
<varname>DefaultTimeoutStartSec=</varname> sets the default <varname>TimeoutSec=</varname> value.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para><varname>DefaultTimeoutStartSec=</varname> and <varname>DefaultTimeoutStopSec=</varname>
|
||||||
|
default to &DEFAULT_TIMEOUT; in the system manager and &DEFAULT_USER_TIMEOUT; in the user manager.
|
||||||
|
<varname>DefaultTimeoutAbortSec=</varname> is not set by default so that all units fall back to
|
||||||
|
<varname>TimeoutStopSec=</varname>. <varname>DefaultRestartSec=</varname> defaults to 100 ms.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v209"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>DefaultDeviceTimeoutSec=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Configures the default timeout for waiting for devices. It can be changed per
|
||||||
|
device via the <varname>x-systemd.device-timeout=</varname> option in <filename>/etc/fstab</filename>
|
||||||
|
and <filename>/etc/crypttab</filename> (see
|
||||||
|
<citerefentry><refentrytitle>systemd.mount</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||||
|
<citerefentry><refentrytitle>crypttab</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||||
|
Defaults to &DEFAULT_TIMEOUT; in the system manager and &DEFAULT_USER_TIMEOUT; in the user manager.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v252"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>DefaultStartLimitIntervalSec=</varname></term>
|
||||||
|
<term><varname>DefaultStartLimitBurst=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Configure the default unit start rate
|
||||||
|
limiting, as configured per-service by
|
||||||
|
<varname>StartLimitIntervalSec=</varname> and
|
||||||
|
<varname>StartLimitBurst=</varname>. See
|
||||||
|
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||||
|
for details on the per-service settings.
|
||||||
|
<varname>DefaultStartLimitIntervalSec=</varname> defaults to
|
||||||
|
10s. <varname>DefaultStartLimitBurst=</varname> defaults to
|
||||||
|
5.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v209"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>ReloadLimitIntervalSec=</varname></term>
|
<term><varname>ReloadLimitIntervalSec=</varname></term>
|
||||||
|
@ -635,19 +625,56 @@
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Environment</title>
|
||||||
|
|
||||||
|
<variablelist class='config-directives'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>ManagerEnvironment=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes the same arguments as <varname>DefaultEnvironment=</varname>, see above. Sets
|
||||||
|
environment variables for the manager process itself. These variables are inherited by processes
|
||||||
|
spawned by user managers, but not the system manager - use <varname>DefaultEnvironment=</varname>
|
||||||
|
for that. Note that these variables are merged into the existing environment block. In particular, in
|
||||||
|
case of the system manager, this includes variables set by the kernel based on the kernel command line.
|
||||||
|
As with <varname>DefaultEnvironment=</varname>, this environment block is internal, and changes are not
|
||||||
|
reflected in the manager's <filename>/proc/PID/environ</filename>.</para>
|
||||||
|
|
||||||
|
<para>Setting environment variables for the manager process may be useful to modify its behaviour.
|
||||||
|
See <ulink url="https://systemd.io/ENVIRONMENT">Known Environment Variables</ulink> for a
|
||||||
|
descriptions of some variables understood by <command>systemd</command>.</para>
|
||||||
|
|
||||||
|
<para>Simple <literal>%</literal>-specifier expansion is supported, see below for a list of supported
|
||||||
|
specifiers.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v248"/>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>DefaultMemoryPressureWatch=</varname></term>
|
<term><varname>DefaultEnvironment=</varname></term>
|
||||||
<term><varname>DefaultMemoryPressureThresholdSec=</varname></term>
|
|
||||||
|
|
||||||
<listitem><para>Configures the default settings for the per-unit
|
<listitem><para>Configures environment variables passed to all executed processes. Takes a
|
||||||
<varname>MemoryPressureWatch=</varname> and <varname>MemoryPressureThresholdSec=</varname>
|
space-separated list of variable assignments. See <citerefentry
|
||||||
settings. See
|
project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||||
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
details about environment variables.</para>
|
||||||
for details. Defaults to <literal>auto</literal> and <literal>200ms</literal>, respectively. This
|
|
||||||
also sets the memory pressure monitoring threshold for the service manager itself.</para>
|
|
||||||
|
|
||||||
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
|
<para>Simple <literal>%</literal>-specifier expansion is supported, see below for a list of supported
|
||||||
|
specifiers.</para>
|
||||||
|
|
||||||
|
<para>Example:
|
||||||
|
|
||||||
|
<programlisting>DefaultEnvironment="VAR1=word1 word2" VAR2=word3 "VAR3=word 5 6"</programlisting>
|
||||||
|
|
||||||
|
Sets three variables
|
||||||
|
<literal>VAR1</literal>,
|
||||||
|
<literal>VAR2</literal>,
|
||||||
|
<literal>VAR3</literal>.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v205"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
|
@ -71,6 +71,8 @@
|
||||||
<varname>Cmdline=</varname>/<option>--cmdline=</option>,
|
<varname>Cmdline=</varname>/<option>--cmdline=</option>,
|
||||||
<varname>OSRelease=</varname>/<option>--os-release=</option>,
|
<varname>OSRelease=</varname>/<option>--os-release=</option>,
|
||||||
<varname>DeviceTree=</varname>/<option>--devicetree=</option>,
|
<varname>DeviceTree=</varname>/<option>--devicetree=</option>,
|
||||||
|
<varname>DeviceTreeAuto=</varname>/<option>--devicetree-auto=</option>,
|
||||||
|
<varname>HWIDs=</varname>/<option>--hwids=</option>,
|
||||||
<varname>Splash=</varname>/<option>--splash=</option>,
|
<varname>Splash=</varname>/<option>--splash=</option>,
|
||||||
<varname>PCRPKey=</varname>/<option>--pcrpkey=</option>,
|
<varname>PCRPKey=</varname>/<option>--pcrpkey=</option>,
|
||||||
<varname>Uname=</varname>/<option>--uname=</option>,
|
<varname>Uname=</varname>/<option>--uname=</option>,
|
||||||
|
@ -374,6 +376,35 @@
|
||||||
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>DeviceTreeAuto=<replaceable>PATH</replaceable>...</varname></term>
|
||||||
|
<term><option>--devicetree-auto=<replaceable>PATH</replaceable></option></term>
|
||||||
|
|
||||||
|
<listitem><para>Zero or more automatically selectable DeviceTree files. In the configuration file, items are separated by
|
||||||
|
whitespace. Each DeviceTree will be in a separate <literal>.dtbauto</literal> section.</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>HWIDs=<replaceable>PATH</replaceable></varname></term>
|
||||||
|
<term><option>--hwids=<replaceable>PATH</replaceable></option></term>
|
||||||
|
|
||||||
|
<listitem><para>The hardware ID device table (the <literal>.hwids</literal> section). The argument is a
|
||||||
|
path to a directory with JSON HWID device description files. Each file needs to contain a single JSON object with a <literal>name</literal>, <literal>compatible</literal> and <literal>hwids</literal> keys. The <literal>name</literal> and <literal>compatible</literal> keys must have string values and the <literal>hwids</literal> key must have a list of strings as value, where the strings must be valid UUIDs that represent CHIDs/HWIDs.
|
||||||
|
Example:
|
||||||
|
<programlisting><xi:include href="ukify_hwid.json.example" parse="text" /></programlisting>
|
||||||
|
Here <literal>Example Laptop 16 Gen 7</literal> is the device <literal>name</literal> (as defined by the manufacturer),
|
||||||
|
<literal>example,laptop-16-g7</literal> is the <literal>compatible</literal> (as defined by the kernel) and <literal>hwids</literal>
|
||||||
|
is an array of CHIDs/HWIDs (extracted i.e. from <command>fwupdtool hwids</command> output).
|
||||||
|
If not specified, the section will not be present. It is recommended to specify this parameter if automatically
|
||||||
|
selectable DeviceTrees are to be used.
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>Uname=<replaceable>VERSION</replaceable></varname></term>
|
<term><varname>Uname=<replaceable>VERSION</replaceable></varname></term>
|
||||||
<term><option>--uname=<replaceable>VERSION</replaceable></option></term>
|
<term><option>--uname=<replaceable>VERSION</replaceable></option></term>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "Example Laptop 16 Gen 7",
|
||||||
|
"compatible": "example,laptop-16-g7",
|
||||||
|
"hwids": [
|
||||||
|
"5dc05bf4-01f6-4089-b464-a08c47ea9295",
|
||||||
|
"3e3f8f3c-2003-46f2-811c-85554f7d5952"
|
||||||
|
]
|
||||||
|
}
|
|
@ -97,6 +97,7 @@ typedef struct {
|
||||||
bool auto_poweroff;
|
bool auto_poweroff;
|
||||||
bool auto_reboot;
|
bool auto_reboot;
|
||||||
bool reboot_for_bitlocker;
|
bool reboot_for_bitlocker;
|
||||||
|
bool reboot_on_err;
|
||||||
secure_boot_enroll secure_boot_enroll;
|
secure_boot_enroll secure_boot_enroll;
|
||||||
bool force_menu;
|
bool force_menu;
|
||||||
bool use_saved_entry;
|
bool use_saved_entry;
|
||||||
|
@ -538,6 +539,7 @@ static void print_status(Config *config, char16_t *loaded_image_path) {
|
||||||
printf(" auto-reboot: %ls\n", yes_no(config->auto_reboot));
|
printf(" auto-reboot: %ls\n", yes_no(config->auto_reboot));
|
||||||
printf(" beep: %ls\n", yes_no(config->beep));
|
printf(" beep: %ls\n", yes_no(config->beep));
|
||||||
printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker));
|
printf(" reboot-for-bitlocker: %ls\n", yes_no(config->reboot_for_bitlocker));
|
||||||
|
printf(" reboot-on-error: %ls\n", yes_no(config->reboot_on_err));
|
||||||
|
|
||||||
switch (config->secure_boot_enroll) {
|
switch (config->secure_boot_enroll) {
|
||||||
case ENROLL_OFF:
|
case ENROLL_OFF:
|
||||||
|
@ -1276,6 +1278,10 @@ static void config_defaults_load_from_file(Config *config, char *content) {
|
||||||
log_error("Error parsing 'reboot-for-bitlocker' config option, ignoring: %s",
|
log_error("Error parsing 'reboot-for-bitlocker' config option, ignoring: %s",
|
||||||
value);
|
value);
|
||||||
|
|
||||||
|
} else if (streq8(key, "reboot-on-error")) {
|
||||||
|
if (!parse_boolean(value, &config->reboot_on_err))
|
||||||
|
log_error("Error parsing 'reboot-on-error' config option, ignoring: %s", value);
|
||||||
|
|
||||||
} else if (streq8(key, "secure-boot-enroll")) {
|
} else if (streq8(key, "secure-boot-enroll")) {
|
||||||
if (streq8(value, "manual"))
|
if (streq8(value, "manual"))
|
||||||
config->secure_boot_enroll = ENROLL_MANUAL;
|
config->secure_boot_enroll = ENROLL_MANUAL;
|
||||||
|
@ -2946,8 +2952,12 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||||
(void) process_random_seed(root_dir);
|
(void) process_random_seed(root_dir);
|
||||||
|
|
||||||
err = image_start(image, entry);
|
err = image_start(image, entry);
|
||||||
if (err != EFI_SUCCESS)
|
if (err != EFI_SUCCESS) {
|
||||||
|
if (config.reboot_on_err)
|
||||||
|
reboot_system();
|
||||||
|
else
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
menu = true;
|
menu = true;
|
||||||
config.timeout_sec = 0;
|
config.timeout_sec = 0;
|
||||||
|
|
|
@ -858,7 +858,7 @@ static void generate_sidecar_initrds(
|
||||||
/* access_mode= */ 0444,
|
/* access_mode= */ 0444,
|
||||||
/* tpm_pcr= */ TPM2_PCR_SYSEXTS,
|
/* tpm_pcr= */ TPM2_PCR_SYSEXTS,
|
||||||
u"System extension initrd",
|
u"System extension initrd",
|
||||||
initrds + INITRD_CONFEXT,
|
initrds + INITRD_SYSEXT,
|
||||||
&m) == EFI_SUCCESS)
|
&m) == EFI_SUCCESS)
|
||||||
combine_measured_flag(sysext_measured, m);
|
combine_measured_flag(sysext_measured, m);
|
||||||
|
|
||||||
|
@ -871,7 +871,7 @@ static void generate_sidecar_initrds(
|
||||||
/* access_mode= */ 0444,
|
/* access_mode= */ 0444,
|
||||||
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
|
/* tpm_pcr= */ TPM2_PCR_KERNEL_CONFIG,
|
||||||
u"Configuration extension initrd",
|
u"Configuration extension initrd",
|
||||||
initrds + INITRD_SYSEXT,
|
initrds + INITRD_CONFEXT,
|
||||||
&m) == EFI_SUCCESS)
|
&m) == EFI_SUCCESS)
|
||||||
combine_measured_flag(confext_measured, m);
|
combine_measured_flag(confext_measured, m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,6 @@ static int status_entries(
|
||||||
|
|
||||||
r = show_boot_entry(
|
r = show_boot_entry(
|
||||||
boot_config_default_entry(config),
|
boot_config_default_entry(config),
|
||||||
&config->global_addons,
|
|
||||||
/* show_as_default= */ false,
|
/* show_as_default= */ false,
|
||||||
/* show_as_selected= */ false,
|
/* show_as_selected= */ false,
|
||||||
/* show_discovered= */ false);
|
/* show_discovered= */ false);
|
||||||
|
|
|
@ -55,7 +55,7 @@ static int json_dispatch_entries(const char *name, sd_json_variant *variant, sd_
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
assert_se(f = data_to_file((const uint8_t*) data, len));
|
assert_se(f = data_to_file((const uint8_t*) data, len));
|
||||||
|
|
||||||
assert_se(boot_config_load_type1(config, f, "/", "/entries", id) != -ENOMEM);
|
assert_se(boot_config_load_type1(config, f, "/", BOOT_ENTRY_ESP, "/entries", id) != -ENOMEM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,22 @@ static const char* const boot_entry_type_json_table[_BOOT_ENTRY_TYPE_MAX] = {
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type_json, BootEntryType);
|
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type_json, BootEntryType);
|
||||||
|
|
||||||
|
static const char* const boot_entry_source_table[_BOOT_ENTRY_SOURCE_MAX] = {
|
||||||
|
[BOOT_ENTRY_ESP] = "EFI System Partition",
|
||||||
|
[BOOT_ENTRY_XBOOTLDR] = "Extended Boot Loader Partition",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_source, BootEntrySource);
|
||||||
|
|
||||||
|
static const char* const boot_entry_source_json_table[_BOOT_ENTRY_SOURCE_MAX] = {
|
||||||
|
[BOOT_ENTRY_ESP] = "esp",
|
||||||
|
[BOOT_ENTRY_XBOOTLDR] = "xbootldr",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_source_json, BootEntrySource);
|
||||||
|
|
||||||
|
static void boot_entry_addons_done(BootEntryAddons *addons);
|
||||||
|
|
||||||
static void boot_entry_free(BootEntry *entry) {
|
static void boot_entry_free(BootEntry *entry) {
|
||||||
assert(entry);
|
assert(entry);
|
||||||
|
|
||||||
|
@ -59,7 +75,7 @@ static void boot_entry_free(BootEntry *entry) {
|
||||||
free(entry->machine_id);
|
free(entry->machine_id);
|
||||||
free(entry->architecture);
|
free(entry->architecture);
|
||||||
strv_free(entry->options);
|
strv_free(entry->options);
|
||||||
free(entry->local_addons.items);
|
boot_entry_addons_done(&entry->local_addons);
|
||||||
free(entry->kernel);
|
free(entry->kernel);
|
||||||
free(entry->efi);
|
free(entry->efi);
|
||||||
strv_free(entry->initrd);
|
strv_free(entry->initrd);
|
||||||
|
@ -283,11 +299,12 @@ nothing:
|
||||||
static int boot_entry_load_type1(
|
static int boot_entry_load_type1(
|
||||||
FILE *f,
|
FILE *f,
|
||||||
const char *root,
|
const char *root,
|
||||||
|
const BootEntrySource source,
|
||||||
const char *dir,
|
const char *dir,
|
||||||
const char *fname,
|
const char *fname,
|
||||||
BootEntry *entry) {
|
BootEntry *entry) {
|
||||||
|
|
||||||
_cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_CONF);
|
_cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_CONF, source);
|
||||||
char *c;
|
char *c;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -393,6 +410,7 @@ int boot_config_load_type1(
|
||||||
BootConfig *config,
|
BootConfig *config,
|
||||||
FILE *f,
|
FILE *f,
|
||||||
const char *root,
|
const char *root,
|
||||||
|
const BootEntrySource source,
|
||||||
const char *dir,
|
const char *dir,
|
||||||
const char *fname) {
|
const char *fname) {
|
||||||
int r;
|
int r;
|
||||||
|
@ -406,10 +424,14 @@ int boot_config_load_type1(
|
||||||
if (!GREEDY_REALLOC0(config->entries, config->n_entries + 1))
|
if (!GREEDY_REALLOC0(config->entries, config->n_entries + 1))
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = boot_entry_load_type1(f, root, dir, fname, config->entries + config->n_entries);
|
BootEntry *entry = config->entries + config->n_entries;
|
||||||
|
|
||||||
|
r = boot_entry_load_type1(f, root, source, dir, fname, entry);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
entry->global_addons = &config->global_addons[source];
|
||||||
|
|
||||||
config->n_entries++;
|
config->n_entries++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -426,7 +448,9 @@ void boot_config_free(BootConfig *config) {
|
||||||
FOREACH_ARRAY(i, config->entries, config->n_entries)
|
FOREACH_ARRAY(i, config->entries, config->n_entries)
|
||||||
boot_entry_free(i);
|
boot_entry_free(i);
|
||||||
free(config->entries);
|
free(config->entries);
|
||||||
free(config->global_addons.items);
|
|
||||||
|
FOREACH_ARRAY(i, config->global_addons, _BOOT_ENTRY_SOURCE_MAX)
|
||||||
|
boot_entry_addons_done(i);
|
||||||
|
|
||||||
set_free(config->inodes_seen);
|
set_free(config->inodes_seen);
|
||||||
}
|
}
|
||||||
|
@ -592,6 +616,7 @@ static int config_check_inode_relevant_and_unseen(BootConfig *config, int fd, co
|
||||||
static int boot_entries_find_type1(
|
static int boot_entries_find_type1(
|
||||||
BootConfig *config,
|
BootConfig *config,
|
||||||
const char *root,
|
const char *root,
|
||||||
|
const BootEntrySource source,
|
||||||
const char *dir) {
|
const char *dir) {
|
||||||
|
|
||||||
_cleanup_free_ DirectoryEntries *dentries = NULL;
|
_cleanup_free_ DirectoryEntries *dentries = NULL;
|
||||||
|
@ -635,7 +660,7 @@ static int boot_entries_find_type1(
|
||||||
if (r == 0) /* inode already seen or otherwise not relevant */
|
if (r == 0) /* inode already seen or otherwise not relevant */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
r = boot_config_load_type1(config, f, root, full, de->d_name);
|
r = boot_config_load_type1(config, f, root, source, full, de->d_name);
|
||||||
if (r == -ENOMEM) /* ignore all other errors */
|
if (r == -ENOMEM) /* ignore all other errors */
|
||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
@ -645,6 +670,7 @@ static int boot_entries_find_type1(
|
||||||
|
|
||||||
static int boot_entry_load_unified(
|
static int boot_entry_load_unified(
|
||||||
const char *root,
|
const char *root,
|
||||||
|
const BootEntrySource source,
|
||||||
const char *path,
|
const char *path,
|
||||||
unsigned profile,
|
unsigned profile,
|
||||||
const char *osrelease_text,
|
const char *osrelease_text,
|
||||||
|
@ -717,7 +743,7 @@ static int boot_entry_load_unified(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to extract file name from '%s': %m", path);
|
return log_error_errno(r, "Failed to extract file name from '%s': %m", path);
|
||||||
|
|
||||||
_cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_UNIFIED);
|
_cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_UNIFIED, source);
|
||||||
|
|
||||||
r = boot_filename_extract_tries(fname, &tmp.id, &tmp.tries_left, &tmp.tries_done);
|
r = boot_filename_extract_tries(fname, &tmp.id, &tmp.tries_left, &tmp.tries_done);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -1130,18 +1156,21 @@ static int boot_entries_find_unified_addons(
|
||||||
static int boot_entries_find_unified_global_addons(
|
static int boot_entries_find_unified_global_addons(
|
||||||
BootConfig *config,
|
BootConfig *config,
|
||||||
const char *root,
|
const char *root,
|
||||||
const char *d_name) {
|
const char *d_name,
|
||||||
|
BootEntryAddons *ret_addons) {
|
||||||
|
|
||||||
int r;
|
int r;
|
||||||
_cleanup_closedir_ DIR *d = NULL;
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
|
|
||||||
|
assert(ret_addons);
|
||||||
|
|
||||||
r = chase_and_opendir(root, NULL, CHASE_PROHIBIT_SYMLINKS, NULL, &d);
|
r = chase_and_opendir(root, NULL, CHASE_PROHIBIT_SYMLINKS, NULL, &d);
|
||||||
if (r == -ENOENT)
|
if (r == -ENOENT)
|
||||||
return 0;
|
return 0;
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to open '%s/%s': %m", root, d_name);
|
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, &config->global_addons);
|
return boot_entries_find_unified_addons(config, dirfd(d), d_name, root, ret_addons);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int boot_entries_find_unified_local_addons(
|
static int boot_entries_find_unified_local_addons(
|
||||||
|
@ -1165,6 +1194,7 @@ static int boot_entries_find_unified_local_addons(
|
||||||
static int boot_entries_find_unified(
|
static int boot_entries_find_unified(
|
||||||
BootConfig *config,
|
BootConfig *config,
|
||||||
const char *root,
|
const char *root,
|
||||||
|
BootEntrySource source,
|
||||||
const char *dir) {
|
const char *dir) {
|
||||||
|
|
||||||
_cleanup_closedir_ DIR *d = NULL;
|
_cleanup_closedir_ DIR *d = NULL;
|
||||||
|
@ -1212,16 +1242,21 @@ static int boot_entries_find_unified(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!GREEDY_REALLOC0(config->entries, config->n_entries + 2))
|
if (!GREEDY_REALLOC0(config->entries, config->n_entries + 1))
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
if (boot_entry_load_unified(root, j, p, osrelease, profile, cmdline, config->entries + config->n_entries) < 0)
|
BootEntry *entry = config->entries + config->n_entries;
|
||||||
|
|
||||||
|
if (boot_entry_load_unified(root, source, j, p, osrelease, profile, cmdline, config->entries + config->n_entries) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
config->n_entries++;
|
|
||||||
|
|
||||||
/* look for .efi.extra.d */
|
/* look for .efi.extra.d */
|
||||||
(void) boot_entries_find_unified_local_addons(config, dirfd(d), de->d_name, full, config->entries + config->n_entries);
|
(void) boot_entries_find_unified_local_addons(config, dirfd(d), de->d_name, full, entry);
|
||||||
|
|
||||||
|
/* Set up the backpointer, so that we can find the global addons */
|
||||||
|
entry->global_addons = &config->global_addons[source];
|
||||||
|
|
||||||
|
config->n_entries++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1438,32 +1473,37 @@ int boot_config_load(
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(config);
|
assert(config);
|
||||||
config->global_addons = (BootEntryAddons) {};
|
|
||||||
|
|
||||||
if (esp_path) {
|
if (esp_path) {
|
||||||
r = boot_loader_read_conf_path(config, esp_path, "/loader/loader.conf");
|
r = boot_loader_read_conf_path(config, esp_path, "/loader/loader.conf");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = boot_entries_find_type1(config, esp_path, "/loader/entries");
|
r = boot_entries_find_type1(config, esp_path, BOOT_ENTRY_ESP, "/loader/entries");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = boot_entries_find_unified(config, esp_path, "/EFI/Linux/");
|
r = boot_entries_find_unified(config, esp_path, BOOT_ENTRY_ESP, "/EFI/Linux/");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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/addons/",
|
||||||
|
&config->global_addons[BOOT_ENTRY_ESP]);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xbootldr_path) {
|
if (xbootldr_path) {
|
||||||
r = boot_entries_find_type1(config, xbootldr_path, "/loader/entries");
|
r = boot_entries_find_type1(config, xbootldr_path, BOOT_ENTRY_XBOOTLDR, "/loader/entries");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = boot_entries_find_unified(config, xbootldr_path, "/EFI/Linux/");
|
r = boot_entries_find_unified(config, xbootldr_path, BOOT_ENTRY_XBOOTLDR, "/EFI/Linux/");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = boot_entries_find_unified_global_addons(config, xbootldr_path, "/loader/addons/",
|
||||||
|
&config->global_addons[BOOT_ENTRY_XBOOTLDR]);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1518,6 +1558,7 @@ int boot_config_augment_from_loader(
|
||||||
char **found_by_loader,
|
char **found_by_loader,
|
||||||
bool only_auto) {
|
bool only_auto) {
|
||||||
|
|
||||||
|
static const BootEntryAddons no_addons = (BootEntryAddons) {};
|
||||||
static const char *const title_table[] = {
|
static const char *const title_table[] = {
|
||||||
/* Pretty names for a few well-known automatically discovered entries. */
|
/* Pretty names for a few well-known automatically discovered entries. */
|
||||||
"auto-osx", "macOS",
|
"auto-osx", "macOS",
|
||||||
|
@ -1575,6 +1616,7 @@ int boot_config_augment_from_loader(
|
||||||
.reported_by_loader = true,
|
.reported_by_loader = true,
|
||||||
.tries_left = UINT_MAX,
|
.tries_left = UINT_MAX,
|
||||||
.tries_done = UINT_MAX,
|
.tries_done = UINT_MAX,
|
||||||
|
.global_addons = &no_addons,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1646,9 +1688,7 @@ static int indent_embedded_newlines(char *cmdline, char **ret_cmdline) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int print_cmdline(
|
static int print_cmdline(const BootEntry *e) {
|
||||||
const BootEntry *e,
|
|
||||||
const BootEntryAddons *global_arr) {
|
|
||||||
|
|
||||||
_cleanup_free_ char *options = NULL, *combined_cmdline = NULL, *t2 = NULL;
|
_cleanup_free_ char *options = NULL, *combined_cmdline = NULL, *t2 = NULL;
|
||||||
|
|
||||||
|
@ -1670,7 +1710,7 @@ static int print_cmdline(
|
||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_ARRAY(addon, global_arr->items, global_arr->n_items) {
|
FOREACH_ARRAY(addon, e->global_addons->items, e->global_addons->n_items) {
|
||||||
print_addon(addon, "global-addon");
|
print_addon(addon, "global-addon");
|
||||||
if (!strextend(&t2, " ", addon->cmdline))
|
if (!strextend(&t2, " ", addon->cmdline))
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
@ -1718,7 +1758,6 @@ static int json_addon(
|
||||||
|
|
||||||
static int json_cmdline(
|
static int json_cmdline(
|
||||||
const BootEntry *e,
|
const BootEntry *e,
|
||||||
const BootEntryAddons *global_arr,
|
|
||||||
const char *def_cmdline,
|
const char *def_cmdline,
|
||||||
sd_json_variant **v) {
|
sd_json_variant **v) {
|
||||||
|
|
||||||
|
@ -1734,7 +1773,7 @@ static int json_cmdline(
|
||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
|
||||||
FOREACH_ARRAY(addon, global_arr->items, global_arr->n_items) {
|
FOREACH_ARRAY(addon, e->global_addons->items, e->global_addons->n_items) {
|
||||||
r = json_addon(addon, "globalAddon", &addons_array);
|
r = json_addon(addon, "globalAddon", &addons_array);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -1761,7 +1800,6 @@ static int json_cmdline(
|
||||||
|
|
||||||
int show_boot_entry(
|
int show_boot_entry(
|
||||||
const BootEntry *e,
|
const BootEntry *e,
|
||||||
const BootEntryAddons *global_addons,
|
|
||||||
bool show_as_default,
|
bool show_as_default,
|
||||||
bool show_as_selected,
|
bool show_as_selected,
|
||||||
bool show_reported) {
|
bool show_reported) {
|
||||||
|
@ -1821,7 +1859,9 @@ int show_boot_entry(
|
||||||
if (e->type == BOOT_ENTRY_CONF)
|
if (e->type == BOOT_ENTRY_CONF)
|
||||||
(void) terminal_urlify_path(e->path, text, &link);
|
(void) terminal_urlify_path(e->path, text, &link);
|
||||||
|
|
||||||
printf(" source: %s\n", link ?: text ?: e->path);
|
printf(" source: %s (on the %s)\n",
|
||||||
|
link ?: text ?: e->path,
|
||||||
|
boot_entry_source_to_string(e->source));
|
||||||
}
|
}
|
||||||
if (e->tries_left != UINT_MAX) {
|
if (e->tries_left != UINT_MAX) {
|
||||||
printf(" tries: %u left", e->tries_left);
|
printf(" tries: %u left", e->tries_left);
|
||||||
|
@ -1851,7 +1891,7 @@ int show_boot_entry(
|
||||||
*s,
|
*s,
|
||||||
&status);
|
&status);
|
||||||
|
|
||||||
r = print_cmdline(e, global_addons);
|
r = print_cmdline(e);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -1892,6 +1932,7 @@ int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret) {
|
||||||
r = sd_json_variant_merge_objectbo(
|
r = sd_json_variant_merge_objectbo(
|
||||||
&v,
|
&v,
|
||||||
SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(boot_entry_type_json_to_string(e->type))),
|
SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(boot_entry_type_json_to_string(e->type))),
|
||||||
|
SD_JSON_BUILD_PAIR("source", SD_JSON_BUILD_STRING(boot_entry_source_json_to_string(e->source))),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!e->id, "id", SD_JSON_BUILD_STRING(e->id)),
|
SD_JSON_BUILD_PAIR_CONDITION(!!e->id, "id", SD_JSON_BUILD_STRING(e->id)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!e->path, "path", SD_JSON_BUILD_STRING(e->path)),
|
SD_JSON_BUILD_PAIR_CONDITION(!!e->path, "path", SD_JSON_BUILD_STRING(e->path)),
|
||||||
SD_JSON_BUILD_PAIR_CONDITION(!!e->root, "root", SD_JSON_BUILD_STRING(e->root)),
|
SD_JSON_BUILD_PAIR_CONDITION(!!e->root, "root", SD_JSON_BUILD_STRING(e->root)),
|
||||||
|
@ -1923,7 +1964,7 @@ int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
r = json_cmdline(e, &c->global_addons, opts, &v);
|
r = json_cmdline(e, opts, &v);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
|
@ -1956,7 +1997,6 @@ int show_boot_entries(const BootConfig *config, sd_json_format_flags_t json_form
|
||||||
for (size_t n = 0; n < config->n_entries; n++) {
|
for (size_t n = 0; n < config->n_entries; n++) {
|
||||||
r = show_boot_entry(
|
r = show_boot_entry(
|
||||||
config->entries + n,
|
config->entries + n,
|
||||||
&config->global_addons,
|
|
||||||
/* show_as_default= */ n == (size_t) config->default_entry,
|
/* show_as_default= */ n == (size_t) config->default_entry,
|
||||||
/* show_as_selected= */ n == (size_t) config->selected_entry,
|
/* show_as_selected= */ n == (size_t) config->selected_entry,
|
||||||
/* show_discovered= */ true);
|
/* show_discovered= */ true);
|
||||||
|
|
|
@ -21,6 +21,13 @@ typedef enum BootEntryType {
|
||||||
_BOOT_ENTRY_TYPE_INVALID = -EINVAL,
|
_BOOT_ENTRY_TYPE_INVALID = -EINVAL,
|
||||||
} BootEntryType;
|
} BootEntryType;
|
||||||
|
|
||||||
|
typedef enum BootEntrySource {
|
||||||
|
BOOT_ENTRY_ESP,
|
||||||
|
BOOT_ENTRY_XBOOTLDR,
|
||||||
|
_BOOT_ENTRY_SOURCE_MAX,
|
||||||
|
_BOOT_ENTRY_SOURCE_INVALID = -EINVAL,
|
||||||
|
} BootEntrySource;
|
||||||
|
|
||||||
typedef struct BootEntryAddon {
|
typedef struct BootEntryAddon {
|
||||||
char *location;
|
char *location;
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
|
@ -31,10 +38,9 @@ typedef struct BootEntryAddons {
|
||||||
size_t n_items;
|
size_t n_items;
|
||||||
} BootEntryAddons;
|
} BootEntryAddons;
|
||||||
|
|
||||||
BootEntryAddon* boot_entry_addon_free(BootEntryAddon *t);
|
|
||||||
|
|
||||||
typedef struct BootEntry {
|
typedef struct BootEntry {
|
||||||
BootEntryType type;
|
BootEntryType type;
|
||||||
|
BootEntrySource source;
|
||||||
bool reported_by_loader;
|
bool reported_by_loader;
|
||||||
char *id; /* This is the file basename (including extension!) */
|
char *id; /* This is the file basename (including extension!) */
|
||||||
char *id_old; /* Old-style ID, for deduplication purposes. */
|
char *id_old; /* Old-style ID, for deduplication purposes. */
|
||||||
|
@ -49,6 +55,7 @@ typedef struct BootEntry {
|
||||||
char *architecture;
|
char *architecture;
|
||||||
char **options;
|
char **options;
|
||||||
BootEntryAddons local_addons;
|
BootEntryAddons local_addons;
|
||||||
|
const BootEntryAddons *global_addons; /* Backpointer into the BootConfig; we don't own this here */
|
||||||
char *kernel; /* linux is #defined to 1, yikes! */
|
char *kernel; /* linux is #defined to 1, yikes! */
|
||||||
char *efi;
|
char *efi;
|
||||||
char **initrd;
|
char **initrd;
|
||||||
|
@ -59,9 +66,10 @@ typedef struct BootEntry {
|
||||||
unsigned profile;
|
unsigned profile;
|
||||||
} BootEntry;
|
} BootEntry;
|
||||||
|
|
||||||
#define BOOT_ENTRY_INIT(t) \
|
#define BOOT_ENTRY_INIT(t, s) \
|
||||||
{ \
|
{ \
|
||||||
.type = (t), \
|
.type = (t), \
|
||||||
|
.source = (s), \
|
||||||
.tries_left = UINT_MAX, \
|
.tries_left = UINT_MAX, \
|
||||||
.tries_done = UINT_MAX, \
|
.tries_done = UINT_MAX, \
|
||||||
}
|
}
|
||||||
|
@ -76,7 +84,7 @@ typedef struct BootConfig {
|
||||||
BootEntry *entries;
|
BootEntry *entries;
|
||||||
size_t n_entries;
|
size_t n_entries;
|
||||||
|
|
||||||
BootEntryAddons global_addons;
|
BootEntryAddons global_addons[_BOOT_ENTRY_SOURCE_MAX];
|
||||||
|
|
||||||
ssize_t default_entry;
|
ssize_t default_entry;
|
||||||
ssize_t selected_entry;
|
ssize_t selected_entry;
|
||||||
|
@ -93,6 +101,9 @@ typedef struct BootConfig {
|
||||||
const char* boot_entry_type_to_string(BootEntryType);
|
const char* boot_entry_type_to_string(BootEntryType);
|
||||||
const char* boot_entry_type_json_to_string(BootEntryType);
|
const char* boot_entry_type_json_to_string(BootEntryType);
|
||||||
|
|
||||||
|
const char* boot_entry_source_to_string(BootEntrySource);
|
||||||
|
const char* boot_entry_source_json_to_string(BootEntrySource);
|
||||||
|
|
||||||
BootEntry* boot_config_find_entry(BootConfig *config, const char *id);
|
BootEntry* boot_config_find_entry(BootConfig *config, const char *id);
|
||||||
|
|
||||||
static inline const BootEntry* boot_config_default_entry(const BootConfig *config) {
|
static inline const BootEntry* boot_config_default_entry(const BootConfig *config) {
|
||||||
|
@ -113,6 +124,7 @@ int boot_config_load_type1(
|
||||||
BootConfig *config,
|
BootConfig *config,
|
||||||
FILE *f,
|
FILE *f,
|
||||||
const char *root,
|
const char *root,
|
||||||
|
const BootEntrySource source,
|
||||||
const char *dir,
|
const char *dir,
|
||||||
const char *id);
|
const char *id);
|
||||||
|
|
||||||
|
@ -131,7 +143,6 @@ static inline const char* boot_entry_title(const BootEntry *entry) {
|
||||||
|
|
||||||
int show_boot_entry(
|
int show_boot_entry(
|
||||||
const BootEntry *e,
|
const BootEntry *e,
|
||||||
const BootEntryAddons *global_addons,
|
|
||||||
bool show_as_default,
|
bool show_as_default,
|
||||||
bool show_as_selected,
|
bool show_as_selected,
|
||||||
bool show_reported);
|
bool show_reported);
|
||||||
|
|
|
@ -42,6 +42,7 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import textwrap
|
import textwrap
|
||||||
|
import uuid
|
||||||
from collections.abc import Iterable, Iterator, Sequence
|
from collections.abc import Iterable, Iterator, Sequence
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -1013,14 +1014,9 @@ def merge_sbat(input_pe: list[Path], input_text: list[str]) -> str:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Keep in sync with EFI_GUID (src/boot/efi.h)
|
|
||||||
# uint32_t Data1, uint16_t Data2, uint16_t Data3, uint8_t Data4[8]
|
|
||||||
EFI_GUID = tuple[int, int, int, tuple[int, int, int, int, int, int, int, int]]
|
|
||||||
EFI_GUID_STRUCT_SIZE = 4 + 2 + 2 + 1 * 8
|
|
||||||
|
|
||||||
# Keep in sync with Device (DEVICE_TYPE_DEVICETREE) from src/boot/chid.h
|
# Keep in sync with Device (DEVICE_TYPE_DEVICETREE) from src/boot/chid.h
|
||||||
# uint32_t descriptor, EFI_GUID chid, uint32_t name_offset, uint32_t compatible_offset
|
# uint32_t descriptor, EFI_GUID chid, uint32_t name_offset, uint32_t compatible_offset
|
||||||
DEVICE_STRUCT_SIZE = 4 + EFI_GUID_STRUCT_SIZE + 4 + 4
|
DEVICE_STRUCT_SIZE = 4 + 16 + 4 + 4
|
||||||
NULL_DEVICE = b'\0' * DEVICE_STRUCT_SIZE
|
NULL_DEVICE = b'\0' * DEVICE_STRUCT_SIZE
|
||||||
DEVICE_TYPE_DEVICETREE = 1
|
DEVICE_TYPE_DEVICETREE = 1
|
||||||
|
|
||||||
|
@ -1029,29 +1025,21 @@ def device_make_descriptor(device_type: int, size: int) -> int:
|
||||||
return (size) | (device_type << 28)
|
return (size) | (device_type << 28)
|
||||||
|
|
||||||
|
|
||||||
def pack_device(offsets: dict[str, int], name: str, compatible: str, chids: list[EFI_GUID]) -> bytes:
|
DEVICETREE_DESCRIPTOR = device_make_descriptor(DEVICE_TYPE_DEVICETREE, DEVICE_STRUCT_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
def pack_device(offsets: dict[str, int], name: str, compatible: str, chids: set[uuid.UUID]) -> bytes:
|
||||||
data = b''
|
data = b''
|
||||||
|
|
||||||
for data1, data2, data3, data4 in chids:
|
for chid in sorted(chids):
|
||||||
data += struct.pack(
|
data += struct.pack('<I', DEVICETREE_DESCRIPTOR)
|
||||||
'<IIHH8BII',
|
data += chid.bytes_le
|
||||||
device_make_descriptor(DEVICE_TYPE_DEVICETREE, DEVICE_STRUCT_SIZE),
|
data += struct.pack('<II', offsets[name], offsets[compatible])
|
||||||
data1,
|
|
||||||
data2,
|
|
||||||
data3,
|
|
||||||
*data4,
|
|
||||||
offsets[name],
|
|
||||||
offsets[compatible],
|
|
||||||
)
|
|
||||||
|
|
||||||
assert len(data) == DEVICE_STRUCT_SIZE * len(chids)
|
assert len(data) == DEVICE_STRUCT_SIZE * len(chids)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def hex_pairs_list(string: str) -> list[int]:
|
|
||||||
return [int(string[i : i + 2], 16) for i in range(0, len(string), 2)]
|
|
||||||
|
|
||||||
|
|
||||||
def pack_strings(strings: set[str], base: int) -> tuple[bytes, dict[str, int]]:
|
def pack_strings(strings: set[str], base: int) -> tuple[bytes, dict[str, int]]:
|
||||||
blob = b''
|
blob = b''
|
||||||
offsets = {}
|
offsets = {}
|
||||||
|
@ -1064,56 +1052,22 @@ def pack_strings(strings: set[str], base: int) -> tuple[bytes, dict[str, int]]:
|
||||||
|
|
||||||
|
|
||||||
def parse_hwid_dir(path: Path) -> bytes:
|
def parse_hwid_dir(path: Path) -> bytes:
|
||||||
hwid_files = path.rglob('*.txt')
|
hwid_files = path.rglob('*.json')
|
||||||
|
|
||||||
strings: set[str] = set()
|
strings: set[str] = set()
|
||||||
devices: collections.defaultdict[tuple[str, str], list[EFI_GUID]] = collections.defaultdict(list)
|
devices: collections.defaultdict[tuple[str, str], set[uuid.UUID]] = collections.defaultdict(set)
|
||||||
|
|
||||||
uuid_regexp = re.compile(
|
|
||||||
r'\{[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}\}', re.I
|
|
||||||
)
|
|
||||||
|
|
||||||
for hwid_file in hwid_files:
|
for hwid_file in hwid_files:
|
||||||
content = hwid_file.open().readlines()
|
data = json.loads(hwid_file.read_text(encoding='UTF-8'))
|
||||||
|
|
||||||
data: dict[str, str] = {
|
for k in ['name', 'compatible', 'hwids']:
|
||||||
'Manufacturer': '',
|
if k not in data:
|
||||||
'Family': '',
|
|
||||||
'Compatible': '',
|
|
||||||
}
|
|
||||||
uuids: list[EFI_GUID] = []
|
|
||||||
|
|
||||||
for line in content:
|
|
||||||
for k in data:
|
|
||||||
if line.startswith(k):
|
|
||||||
data[k] = line.split(':')[1].strip()
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
uuid = uuid_regexp.match(line)
|
|
||||||
if uuid is not None:
|
|
||||||
d1, d2, d3, d4, d5 = uuid.group(0)[1:-1].split('-')
|
|
||||||
|
|
||||||
data1 = int(d1, 16)
|
|
||||||
data2 = int(d2, 16)
|
|
||||||
data3 = int(d3, 16)
|
|
||||||
data4 = cast(
|
|
||||||
tuple[int, int, int, int, int, int, int, int],
|
|
||||||
tuple(hex_pairs_list(d4) + hex_pairs_list(d5)),
|
|
||||||
)
|
|
||||||
|
|
||||||
uuids.append((data1, data2, data3, data4))
|
|
||||||
|
|
||||||
for k, v in data.items():
|
|
||||||
if not v:
|
|
||||||
raise ValueError(f'hwid description file "{hwid_file}" does not contain "{k}"')
|
raise ValueError(f'hwid description file "{hwid_file}" does not contain "{k}"')
|
||||||
|
|
||||||
name = data['Manufacturer'] + ' ' + data['Family']
|
strings |= {data['name'], data['compatible']}
|
||||||
compatible = data['Compatible']
|
|
||||||
|
|
||||||
strings |= set([name, compatible])
|
# (name, compatible) pair uniquely identifies the device
|
||||||
|
devices[(data['name'], data['compatible'])] |= {uuid.UUID(u) for u in data['hwids']}
|
||||||
# (compatible, name) pair uniquely identifies the device
|
|
||||||
devices[(compatible, name)] += uuids
|
|
||||||
|
|
||||||
total_device_structs = 1
|
total_device_structs = 1
|
||||||
for dev, uuids in devices.items():
|
for dev, uuids in devices.items():
|
||||||
|
@ -1122,7 +1076,7 @@ def parse_hwid_dir(path: Path) -> bytes:
|
||||||
strings_blob, offsets = pack_strings(strings, total_device_structs * DEVICE_STRUCT_SIZE)
|
strings_blob, offsets = pack_strings(strings, total_device_structs * DEVICE_STRUCT_SIZE)
|
||||||
|
|
||||||
devices_blob = b''
|
devices_blob = b''
|
||||||
for (compatible, name), uuids in devices.items():
|
for (name, compatible), uuids in devices.items():
|
||||||
devices_blob += pack_device(offsets, name, compatible, uuids)
|
devices_blob += pack_device(offsets, name, compatible, uuids)
|
||||||
|
|
||||||
devices_blob += NULL_DEVICE
|
devices_blob += NULL_DEVICE
|
||||||
|
|
Loading…
Reference in New Issue