From: Stefan Herbrechtsmeier Date: Wed, 30 Apr 2025 07:55:21 +0000 (+0200) Subject: hostname: add hardware version X-Git-Tag: v258-rc1~514^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=29a352e8c14c51983ba661cb5f4ce51e2bc8664b;p=thirdparty%2Fsystemd.git 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. --- diff --git a/hwdb.d/20-dmi-id.hwdb b/hwdb.d/20-dmi-id.hwdb index 014f05dc5bf..c37036d0082 100644 --- a/hwdb.d/20-dmi-id.hwdb +++ b/hwdb.d/20-dmi-id.hwdb @@ -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:* diff --git a/man/machine-info.xml b/man/machine-info.xml index 4d913ef6124..c766db2708d 100644 --- a/man/machine-info.xml +++ b/man/machine-info.xml @@ -163,6 +163,15 @@ + + + HARDWARE_VERSION= + + Specifies the hardware version. If unspecified, the hardware version set in DMI + will be used. + + + diff --git a/man/org.freedesktop.hostname1.xml b/man/org.freedesktop.hostname1.xml index 720065bcc82..620ae83516d 100644 --- a/man/org.freedesktop.hostname1.xml +++ b/man/org.freedesktop.hostname1.xml @@ -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 { + + @@ -310,11 +314,12 @@ node /org/freedesktop/hostname1 { to the IMAGE_ID= and IMAGE_VERSION= fields of the os-release file. - HardwareVendor, HardwareModel, and HardwareSKU - 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. + HardwareVendor, HardwareModel, HardwareSKU, + and HardwareVersion 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. FirmwareVersion and FirmwareVendor 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 { MachineID, BootID and VSockCID were added in version 256. ChassisAssetTag, OperatingSystemImageID, - OperatingSystemImageVersion, and HardwareSKU - were added in version 258. + OperatingSystemImageVersion, HardwareSKU, and + HardwareVersion were added in version 258. diff --git a/rules.d/60-dmi-id.rules b/rules.d/60-dmi-id.rules index 9712402a389..10b1fe000ca 100644 --- a/rules.d/60-dmi-id.rules +++ b/rules.d/60-dmi-id.rules @@ -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}" diff --git a/src/hostname/hostnamectl.c b/src/hostname/hostnamectl.c index 8862be137e1..c3d20682379 100644 --- a/src/hostname/hostnamectl.c +++ b/src/hostname/hostnamectl.c @@ -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) }, diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 1ecfd50cd34..245126ff927 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -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), diff --git a/src/shared/varlink-io.systemd.Hostname.c b/src/shared/varlink-io.systemd.Hostname.c index e2593861a2c..556a7920d47 100644 --- a/src/shared/varlink-io.systemd.Hostname.c +++ b/src/shared/varlink-io.systemd.Hostname.c @@ -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),