1
0
mirror of https://github.com/systemd/systemd synced 2025-10-06 00:13:24 +02:00

hostname: add hardware version

Add support for the hardware version. The version describes a distinct
version of compatibility hardware. The value is read from the file
/etc/machine-info or DMI as fallback.

The integration provides an unified interface to collect detail hardware
information. The /etc/machine-info entry enables embedded devices
without UEFI support to read the information from a custom store.
This commit is contained in:
Stefan Herbrechtsmeier
2025-04-30 09:55:21 +02:00
parent 79e9fb68a3
commit 29a352e8c1
7 changed files with 107 additions and 11 deletions

View File

@@ -23,6 +23,26 @@ dmi:*:pnTobefilledbyO.E.M.:*
dmi:*:pnToBeFilledByO.E.M.:*
ID_PRODUCT_NAME_IS_RUBBISH=1
dmi:*:pvrDefaultstring:*
dmi:*:pvrDefault string:*
dmi:*:pvrN/A:*
dmi:*:pvrO.E.M.:*
dmi:*:pvrOEM:*
dmi:*:pvrTobefilledbyO.E.M.:*
dmi:*:pvrToBeFilledByO.E.M.:*
dmi:*:pvrTo Be Filled By O.E.M.:*
ID_PRODUCT_VERSION_IS_RUBBISH=1
dmi:*:rvrDefaultstring:*
dmi:*:rvrDefault string:*
dmi:*:rvrN/A:*
dmi:*:rvrO.E.M.:*
dmi:*:rvrOEM:*
dmi:*:rvrTobefilledbyO.E.M.:*
dmi:*:rvrToBeFilledByO.E.M.:*
dmi:*:rvrTo Be Filled By O.E.M.:*
ID_BOARD_VERSION_IS_RUBBISH=1
dmi:*:skuDefaultstring:*
dmi:*:skuDefault string:*
dmi:*:skuN/A:*

View File

@@ -163,6 +163,15 @@
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>HARDWARE_VERSION=</varname></term>
<listitem><para>Specifies the hardware version. If unspecified, the hardware version set in DMI
will be used.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@@ -96,6 +96,8 @@ node /org/freedesktop/hostname1 {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s HardwareSKU = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s HardwareVersion = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s FirmwareVersion = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s FirmwareVendor = '...';
@@ -184,6 +186,8 @@ node /org/freedesktop/hostname1 {
<variablelist class="dbus-property" generated="True" extra-ref="HardwareSKU"/>
<variablelist class="dbus-property" generated="True" extra-ref="HardwareVersion"/>
<variablelist class="dbus-property" generated="True" extra-ref="FirmwareVersion"/>
<variablelist class="dbus-property" generated="True" extra-ref="FirmwareVendor"/>
@@ -310,11 +314,12 @@ node /org/freedesktop/hostname1 {
to the <varname>IMAGE_ID=</varname> and <varname>IMAGE_VERSION=</varname> fields of the
<filename>os-release</filename> file.</para>
<para><varname>HardwareVendor</varname>, <varname>HardwareModel</varname>, and <varname>HardwareSKU</varname>
expose vendor information about the hardware of the system. The stock keeping unit (SKU) describes a
distinct type of hardware for sale, purchase or inventory management. The SKU is only available if it
deviates from the model. If no such information can be determined these properties are set to empty
strings.</para>
<para><varname>HardwareVendor</varname>, <varname>HardwareModel</varname>, <varname>HardwareSKU</varname>,
and <varname>HardwareVersion</varname> expose vendor information about the hardware of the system. The
stock keeping unit (SKU) describes a distinct type of hardware for sale, purchase or inventory management.
The SKU and version are only available if they deviate from the model and among each other. Thereby the
version is more specific and only available if it differs from the model and SKU. If no such information
can be determined these properties are set to empty strings.</para>
<para><varname>FirmwareVersion</varname> and <varname>FirmwareVendor</varname> expose information about
the system's firmware, i.e. a version string and a vendor name. If no such information can be determined
@@ -480,8 +485,8 @@ node /org/freedesktop/hostname1 {
<para><varname>MachineID</varname>, <varname>BootID</varname> and
<varname>VSockCID</varname> were added in version 256.</para>
<para><varname>ChassisAssetTag</varname>, <varname>OperatingSystemImageID</varname>,
<varname>OperatingSystemImageVersion</varname>, and <varname>HardwareSKU</varname>
were added in version 258.</para>
<varname>OperatingSystemImageVersion</varname>, <varname>HardwareSKU</varname>, and
<varname>HardwareVersion</varname> were added in version 258.</para>
</refsect2>
</refsect1>

View File

@@ -14,6 +14,10 @@ ENV{ID_MODEL}=="", ENV{ID_MODEL}="$attr{board_name}"
# stock keeping unit
ENV{ID_PRODUCT_SKU_IS_RUBBISH}!="1", ENV{ID_SKU}="$attr{product_sku}"
# hardware version
ENV{ID_PRODUCT_VERSION_IS_RUBBISH}!="1", ENV{ID_HARDWARE_VERSION}="$attr{product_version}"
ENV{ID_HARDWARE_VERSION}=="", ENV{ID_BOARD_VERSION_IS_RUBBISH}!="1", ENV{ID_HARDWARE_VERSION}="$attr{board_version}"
# chassis asset tag
ENV{MODALIAS}!="", ATTR{chassis_asset_tag}!="", IMPORT{builtin}="hwdb '$attr{modalias}cat$attr{chassis_asset_tag}:'"
ENV{ID_CHASSIS_ASSET_TAG_IS_RUBBISH}!="1", ENV{ID_CHASSIS_ASSET_TAG}="$attr{chassis_asset_tag}"

View File

@@ -67,6 +67,7 @@ typedef struct StatusInfo {
sd_id128_t product_uuid;
uint32_t vsock_cid;
const char *hardware_sku;
const char *hardware_version;
} StatusInfo;
static const char* chassis_string_to_glyph(const char *chassis) {
@@ -329,6 +330,14 @@ static int print_status_info(StatusInfo *i) {
return table_log_add_error(r);
}
if (!isempty(i->hardware_version)) {
r = table_add_many(table,
TABLE_FIELD, "Hardware Version",
TABLE_STRING, i->hardware_version);
if (r < 0)
return table_log_add_error(r);
}
if (!isempty(i->firmware_version)) {
r = table_add_many(table,
TABLE_FIELD, "Firmware Version",
@@ -423,6 +432,7 @@ static int show_all_names(sd_bus *bus) {
{ "HardwareVendor", "s", NULL, offsetof(StatusInfo, hardware_vendor) },
{ "HardwareModel", "s", NULL, offsetof(StatusInfo, hardware_model) },
{ "HardwareSKU", "s", NULL, offsetof(StatusInfo, hardware_sku) },
{ "HardwareVersion", "s", NULL, offsetof(StatusInfo, hardware_version) },
{ "FirmwareVersion", "s", NULL, offsetof(StatusInfo, firmware_version) },
{ "FirmwareDate", "t", NULL, offsetof(StatusInfo, firmware_date) },
{ "MachineID", "ay", bus_map_id128, offsetof(StatusInfo, machine_id) },

View File

@@ -67,6 +67,7 @@ typedef enum {
PROP_HARDWARE_VENDOR,
PROP_HARDWARE_MODEL,
PROP_HARDWARE_SKU,
PROP_HARDWARE_VERSION,
/* Read from /etc/os-release (or /usr/lib/os-release) */
PROP_OS_PRETTY_NAME,
@@ -172,7 +173,8 @@ static void context_read_machine_info(Context *c) {
(UINT64_C(1) << PROP_LOCATION) |
(UINT64_C(1) << PROP_HARDWARE_VENDOR) |
(UINT64_C(1) << PROP_HARDWARE_MODEL) |
(UINT64_C(1) << PROP_HARDWARE_SKU));
(UINT64_C(1) << PROP_HARDWARE_SKU) |
(UINT64_C(1) << PROP_HARDWARE_VERSION));
r = parse_env_file(NULL, "/etc/machine-info",
"PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME],
@@ -182,7 +184,8 @@ static void context_read_machine_info(Context *c) {
"LOCATION", &c->data[PROP_LOCATION],
"HARDWARE_VENDOR", &c->data[PROP_HARDWARE_VENDOR],
"HARDWARE_MODEL", &c->data[PROP_HARDWARE_MODEL],
"HARDWARE_SKU", &c->data[PROP_HARDWARE_SKU]);
"HARDWARE_SKU", &c->data[PROP_HARDWARE_SKU],
"HARDWARE_VERSION", &c->data[PROP_HARDWARE_VERSION]);
if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read /etc/machine-info, ignoring: %m");
@@ -380,6 +383,34 @@ static int get_hardware_sku(Context *c, char **ret) {
return 0;
}
static int get_hardware_version(Context *c, char **ret) {
_cleanup_free_ char *version = NULL;
int r;
r = get_dmi_property(c, "ID_HARDWARE_VERSION", &version);
if (r < 0)
return r;
/* Suppress reporting the version field, if it's the same string as the
* model or sku field, which it appears to be on various systems */
for (int i = 0; i < 2; i++) {
_cleanup_free_ char *value = NULL;
if (i == 0)
r = get_hardware_model(c, &value);
else
r = get_hardware_sku(c, &value);
if (r < 0) {
if (r != -ENOENT)
return r;
} else if (streq_ptr(version, value))
return -ENOENT;
}
*ret = TAKE_PTR(version);
return 0;
}
static int get_sysattr(sd_device *device, const char *key, char **ret) {
const char *s;
int r;
@@ -849,7 +880,7 @@ static int property_get_hardware_property(
assert(reply);
assert(c);
assert(IN_SET(prop, PROP_HARDWARE_VENDOR, PROP_HARDWARE_MODEL,
PROP_HARDWARE_SKU));
PROP_HARDWARE_SKU, PROP_HARDWARE_VERSION));
assert(getter);
context_read_machine_info(c);
@@ -896,6 +927,18 @@ static int property_get_hardware_sku(
return property_get_hardware_property(reply, userdata, PROP_HARDWARE_SKU, get_hardware_sku);
}
static int property_get_hardware_version(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
return property_get_hardware_property(reply, userdata, PROP_HARDWARE_VERSION, get_hardware_version);
}
static int property_get_firmware_version(
sd_bus *bus,
const char *path,
@@ -1576,7 +1619,7 @@ static int method_get_hardware_serial(sd_bus_message *m, void *userdata, sd_bus_
static int build_describe_response(Context *c, bool privileged, sd_json_variant **ret) {
_cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL,
*chassis = NULL, *vendor = NULL, *model = NULL, *serial = NULL, *firmware_version = NULL,
*firmware_vendor = NULL, *chassis_asset_tag = NULL, *sku = NULL;
*firmware_vendor = NULL, *chassis_asset_tag = NULL, *sku = NULL, *hardware_version = NULL;
_cleanup_strv_free_ char **os_release_pairs = NULL, **machine_info_pairs = NULL;
usec_t firmware_date = USEC_INFINITY, eol = USEC_INFINITY;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
@@ -1614,6 +1657,8 @@ static int build_describe_response(Context *c, bool privileged, sd_json_variant
(void) get_hardware_model(c, &model);
if (isempty(c->data[PROP_HARDWARE_SKU]))
(void) get_hardware_sku(c, &sku);
if (isempty(c->data[PROP_HARDWARE_VERSION]))
(void) get_hardware_version(c, &hardware_version);
if (privileged) {
/* The product UUID and hardware serial is only available to privileged clients */
@@ -1668,6 +1713,7 @@ static int build_describe_response(Context *c, bool privileged, sd_json_variant
SD_JSON_BUILD_PAIR_STRING("HardwareModel", model ?: c->data[PROP_HARDWARE_MODEL]),
SD_JSON_BUILD_PAIR_STRING("HardwareSerial", serial),
SD_JSON_BUILD_PAIR_STRING("HardwareSKU", sku ?: c->data[PROP_HARDWARE_SKU]),
SD_JSON_BUILD_PAIR_STRING("HardwareVersion", hardware_version ?: c->data[PROP_HARDWARE_VERSION]),
SD_JSON_BUILD_PAIR_STRING("FirmwareVersion", firmware_version),
SD_JSON_BUILD_PAIR_STRING("FirmwareVendor", firmware_vendor),
JSON_BUILD_PAIR_FINITE_USEC("FirmwareDate", firmware_date),
@@ -1740,6 +1786,7 @@ static const sd_bus_vtable hostname_vtable[] = {
SD_BUS_PROPERTY("HardwareVendor", "s", property_get_hardware_vendor, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HardwareModel", "s", property_get_hardware_model, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HardwareSKU", "s", property_get_hardware_sku, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HardwareVersion", "s", property_get_hardware_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FirmwareVersion", "s", property_get_firmware_version, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FirmwareVendor", "s", property_get_firmware_vendor, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("FirmwareDate", "t", property_get_firmware_date, 0, SD_BUS_VTABLE_PROPERTY_CONST),

View File

@@ -28,6 +28,7 @@ static SD_VARLINK_DEFINE_METHOD(
SD_VARLINK_DEFINE_OUTPUT(HardwareModel, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(HardwareSerial, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(HardwareSKU, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(HardwareVersion, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(FirmwareVersion, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(FirmwareVendor, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(FirmwareDate, SD_VARLINK_INT, SD_VARLINK_NULLABLE),