diff --git a/hwdb.d/20-dmi-id.hwdb b/hwdb.d/20-dmi-id.hwdb
index 014f05dc5b..c37036d008 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 4d913ef612..c766db2708 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 720065bcc8..620ae83516 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 9712402a38..10b1fe000c 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 8862be137e..c3d2068237 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 1ecfd50cd3..245126ff92 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 e2593861a2..556a7920d4 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),