mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
Add support for conditions on the machines firmware
This allows to limit units to machines that run on a certain firmware type. For device tree defined machines checking against the machine's compatible is also possible.
This commit is contained in:
parent
192a9d95ea
commit
cbcdcaaa0e
@ -68,6 +68,7 @@ Most generic unit settings are available for transient units.
|
||||
✓ ConditionKernelCommandLine=
|
||||
✓ ConditionKernelVersion=
|
||||
✓ ConditionArchitecture=
|
||||
✓ ConditionFirmware=
|
||||
✓ ConditionVirtualization=
|
||||
✓ ConditionSecurity=
|
||||
✓ ConditionCapability=
|
||||
|
@ -222,6 +222,18 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id='firmware'>
|
||||
<term><varname>Firmware=</varname></term>
|
||||
<listitem>
|
||||
<para>Checks whether the system is running on a machine with the specified firmware. See
|
||||
<varname>ConditionFirmware=</varname> in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. When prefixed with an exclamation mark (<literal>!</literal>), the result is negated.
|
||||
If an empty string is assigned, then previously assigned value is cleared.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</refsect1>
|
||||
|
@ -258,6 +258,17 @@
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Firmware=</varname></term>
|
||||
<listitem>
|
||||
<para>Checks whether the system is running on a machine with the specified firmware. See
|
||||
<literal>ConditionFirmware=</literal> in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details. When prefixed with an exclamation mark (<literal>!</literal>), the result is negated.
|
||||
If an empty string is assigned, then previously assigned value is cleared.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -1172,6 +1172,16 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ConditionFirmware=</varname></term>
|
||||
|
||||
<listitem><para>Check whether the system's firmware is of a certain type. Possible values are:
|
||||
<literal>uefi</literal> (for systems with EFI),
|
||||
<literal>device-tree</literal> (for systems with a device tree) and
|
||||
<literal>device-tree-compatible(xyz)</literal> (for systems with a device tree that is compatible to <literal>xyz</literal>).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ConditionVirtualization=</varname></term>
|
||||
|
||||
|
@ -297,6 +297,7 @@ Unit.ConditionFileIsExecutable, config_parse_unit_condition_path,
|
||||
Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions)
|
||||
Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions)
|
||||
Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions)
|
||||
Unit.ConditionFirmware, config_parse_unit_condition_string, CONDITION_FIRMWARE, offsetof(Unit, conditions)
|
||||
Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions)
|
||||
Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions)
|
||||
Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions)
|
||||
|
@ -44,6 +44,7 @@ Match.Virtualization, config_parse_net_condition,
|
||||
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, conditions)
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(NetDev, conditions)
|
||||
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(NetDev, conditions)
|
||||
Match.Firmware, config_parse_net_condition, CONDITION_FIRMWARE, offsetof(NetDev, conditions)
|
||||
NetDev.Description, config_parse_string, 0, offsetof(NetDev, description)
|
||||
NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname)
|
||||
NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind)
|
||||
|
@ -56,6 +56,7 @@ Match.Virtualization, config_parse_net_condition,
|
||||
Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, conditions)
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(Network, conditions)
|
||||
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, conditions)
|
||||
Match.Firmware, config_parse_net_condition, CONDITION_FIRMWARE, offsetof(Network, conditions)
|
||||
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
|
||||
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(Network, mtu)
|
||||
Link.Group, config_parse_uint32, 0, offsetof(Network, group)
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <fnmatch.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <time.h>
|
||||
@ -450,6 +451,81 @@ static int condition_test_architecture(Condition *c, char **env) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
#define DTCOMPAT_FILE "/sys/firmware/devicetree/base/compatible"
|
||||
static int condition_test_firmware_devicetree_compatible(const char *dtcarg) {
|
||||
int r;
|
||||
_cleanup_free_ char *dtcompat = NULL;
|
||||
_cleanup_strv_free_ char **dtcompatlist = NULL;
|
||||
size_t size;
|
||||
|
||||
r = read_full_virtual_file(DTCOMPAT_FILE, &dtcompat, &size);
|
||||
if (r < 0) {
|
||||
/* if the path doesn't exist it is incompatible */
|
||||
if (r != -ENOENT)
|
||||
log_debug_errno(r, "Failed to open() '%s', assuming machine is incompatible: %m", DTCOMPAT_FILE);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Not sure this can happen, but play safe. */
|
||||
if (size == 0) {
|
||||
log_debug("%s has zero length, assuming machine is incompatible", DTCOMPAT_FILE);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* /sys/firmware/devicetree/base/compatible consists of one or more
|
||||
* strings, each ending in '\0'. So the last character in dtcompat must
|
||||
* be a '\0'.
|
||||
*/
|
||||
if (dtcompat[size - 1] != '\0') {
|
||||
log_debug("%s is in an unknown format, assuming machine is incompatible", DTCOMPAT_FILE);
|
||||
return false;
|
||||
}
|
||||
|
||||
dtcompatlist = strv_parse_nulstr(dtcompat, size);
|
||||
if (!dtcompatlist)
|
||||
return -ENOMEM;
|
||||
|
||||
return strv_contains(dtcompatlist, dtcarg);
|
||||
}
|
||||
|
||||
static int condition_test_firmware(Condition *c, char **env) {
|
||||
sd_char *dtc;
|
||||
|
||||
assert(c);
|
||||
assert(c->parameter);
|
||||
assert(c->type == CONDITION_FIRMWARE);
|
||||
|
||||
if (streq(c->parameter, "device-tree")) {
|
||||
if (access("/sys/firmware/device-tree/", F_OK) < 0) {
|
||||
if (errno != ENOENT)
|
||||
log_debug_errno(errno, "Unexpected error when checking for /sys/firmware/device-tree/: %m");
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
} else if ((dtc = startswith(c->parameter, "device-tree-compatible("))) {
|
||||
_cleanup_free_ char *dtcarg = NULL;
|
||||
char *end;
|
||||
|
||||
end = strchr(dtc, ')');
|
||||
if (!end || *(end + 1) != '\0') {
|
||||
log_debug("Malformed Firmware condition \"%s\"", c->parameter);
|
||||
return false;
|
||||
}
|
||||
|
||||
dtcarg = strndup(dtc, end - dtc);
|
||||
if (!dtcarg)
|
||||
return -ENOMEM;
|
||||
|
||||
return condition_test_firmware_devicetree_compatible(dtcarg);
|
||||
} else if (streq(c->parameter, "uefi"))
|
||||
return is_efi_boot();
|
||||
else {
|
||||
log_debug("Unsupported Firmware condition \"%s\"", c->parameter);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int condition_test_host(Condition *c, char **env) {
|
||||
_cleanup_free_ char *h = NULL;
|
||||
sd_id128_t x, y;
|
||||
@ -843,6 +919,7 @@ int condition_test(Condition *c, char **env) {
|
||||
[CONDITION_HOST] = condition_test_host,
|
||||
[CONDITION_AC_POWER] = condition_test_ac_power,
|
||||
[CONDITION_ARCHITECTURE] = condition_test_architecture,
|
||||
[CONDITION_FIRMWARE] = condition_test_firmware,
|
||||
[CONDITION_NEEDS_UPDATE] = condition_test_needs_update,
|
||||
[CONDITION_FIRST_BOOT] = condition_test_first_boot,
|
||||
[CONDITION_USER] = condition_test_user,
|
||||
@ -949,6 +1026,7 @@ void condition_dump_list(Condition *first, FILE *f, const char *prefix, conditio
|
||||
|
||||
static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {
|
||||
[CONDITION_ARCHITECTURE] = "ConditionArchitecture",
|
||||
[CONDITION_FIRMWARE] = "ConditionFirmware",
|
||||
[CONDITION_VIRTUALIZATION] = "ConditionVirtualization",
|
||||
[CONDITION_HOST] = "ConditionHost",
|
||||
[CONDITION_KERNEL_COMMAND_LINE] = "ConditionKernelCommandLine",
|
||||
@ -981,6 +1059,7 @@ DEFINE_STRING_TABLE_LOOKUP(condition_type, ConditionType);
|
||||
|
||||
static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {
|
||||
[CONDITION_ARCHITECTURE] = "AssertArchitecture",
|
||||
[CONDITION_FIRMWARE] = "AssertFirmware",
|
||||
[CONDITION_VIRTUALIZATION] = "AssertVirtualization",
|
||||
[CONDITION_HOST] = "AssertHost",
|
||||
[CONDITION_KERNEL_COMMAND_LINE] = "AssertKernelCommandLine",
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
typedef enum ConditionType {
|
||||
CONDITION_ARCHITECTURE,
|
||||
CONDITION_FIRMWARE,
|
||||
CONDITION_VIRTUALIZATION,
|
||||
CONDITION_HOST,
|
||||
CONDITION_KERNEL_COMMAND_LINE,
|
||||
|
@ -22,6 +22,7 @@ Mode=
|
||||
SourceMACAddress=
|
||||
[Match]
|
||||
Architecture=
|
||||
Firmware=
|
||||
Host=
|
||||
KernelVersion=
|
||||
Virtualization=
|
||||
|
@ -18,6 +18,7 @@ KernelVersion=
|
||||
Type=
|
||||
Driver=
|
||||
Architecture=
|
||||
Firmware=
|
||||
Path=
|
||||
WLANInterfaceType=
|
||||
SSID=
|
||||
|
@ -36,6 +36,7 @@ CollectMode=
|
||||
ConditionACPower=
|
||||
ConditionArchitecture=
|
||||
ConditionCPUs=
|
||||
ConditionFirmware=
|
||||
ConditionCapability=
|
||||
ConditionControlGroupController=
|
||||
ConditionDirectoryNotEmpty=
|
||||
|
Loading…
Reference in New Issue
Block a user