]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hostname: add hardware version 36956/head
authorStefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
Wed, 30 Apr 2025 07:55:21 +0000 (09:55 +0200)
committerStefan Herbrechtsmeier <stefan.herbrechtsmeier@weidmueller.com>
Thu, 22 May 2025 07:00:14 +0000 (09:00 +0200)
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.

hwdb.d/20-dmi-id.hwdb
man/machine-info.xml
man/org.freedesktop.hostname1.xml
rules.d/60-dmi-id.rules
src/hostname/hostnamectl.c
src/hostname/hostnamed.c
src/shared/varlink-io.systemd.Hostname.c

index 014f05dc5bff68d2acbd4b1b5921fedf04401370..c37036d0082fa210dda441502d287140a84ee6b9 100644 (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:*
index 4d913ef6124222d3dbf20b15fd29082016963cef..c766db2708d28a432f83e0bf3059707a9528b443 100644 (file)
 
         <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>
 
index 720065bcc82971de3695c983c399cea77ea3548d..620ae83516d7ee68d9962848647fdf943d550d90 100644 (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>
 
index 9712402a389735403b23ae6209c307f58be92bb0..10b1fe000ca18af47da8abf8c24341a6030593ad 100644 (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}"
index 8862be137e12c6bb2334cb01246aa56203e5c738..c3d20682379a4709b112316c57d952d1cd69d290 100644 (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)       },
index 1ecfd50cd342ea3350cf7c36f1116a9cef44a41f..245126ff927f1b6d21327f7a8a84099d355179e3 100644 (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),
index e2593861a2c5f7ece8693aeb50fef98f0d743c56..556a7920d47dfaf236786b287fbc4fb69787df31 100644 (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),