Compare commits

...

2 Commits

Author SHA1 Message Date
herbrechtsmeier 9565573761
Merge f0a31c0d30 into b01f00e9c5 2025-04-15 02:22:18 +00:00
Stefan Herbrechtsmeier f0a31c0d30 hostname: add hardware family, sku and version
Add support for the hardware family, SKU (Stock-Keeping Unit) and
version. The values are read from the file /etc/machine-info or DMI as
fallback.

The entries are useful to provide an unified interface to collect detail
hardware information. The /etc/machine-info entries enable embedded
devices without UEFI support to provide the information via a common
interface.
2025-04-02 16:09:54 +02:00
5 changed files with 167 additions and 8 deletions

View File

@ -154,6 +154,33 @@
<xi:include href="version-info.xml" xpointer="v251"/></listitem> <xi:include href="version-info.xml" xpointer="v251"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>HARDWARE_FAMILY=</varname></term>
<listitem><para>Specifies the hardware family. If unspecified, the hardware family set in DMI
will be used.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>HARDWARE_SKU=</varname></term>
<listitem><para>Specifies the hardware SKU (Stock-Keeping Unit). If unspecified, the hardware
SKU set in DMI will be used.</para>
<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> </variablelist>
</refsect1> </refsect1>

View File

@ -107,6 +107,12 @@ node /org/freedesktop/hostname1 {
readonly u VSockCID = ...; readonly u VSockCID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ChassisAssetTag = '...'; readonly s ChassisAssetTag = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s HardwareFamily = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s HardwareSKU = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s HardwareVersion = '...';
}; };
interface org.freedesktop.DBus.Peer { ... }; interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... }; interface org.freedesktop.DBus.Introspectable { ... };
@ -194,6 +200,12 @@ node /org/freedesktop/hostname1 {
<variablelist class="dbus-property" generated="True" extra-ref="ChassisAssetTag"/> <variablelist class="dbus-property" generated="True" extra-ref="ChassisAssetTag"/>
<variablelist class="dbus-property" generated="True" extra-ref="HardwareFamily"/>
<variablelist class="dbus-property" generated="True" extra-ref="HardwareSKU"/>
<variablelist class="dbus-property" generated="True" extra-ref="HardwareVersion"/>
<!--End of Autogenerated section--> <!--End of Autogenerated section-->
<para>Whenever the hostname or other metadata is changed via the daemon, <para>Whenever the hostname or other metadata is changed via the daemon,
@ -306,9 +318,10 @@ node /org/freedesktop/hostname1 {
to the <varname>IMAGE_ID=</varname> and <varname>IMAGE_VERSION=</varname> fields of the to the <varname>IMAGE_ID=</varname> and <varname>IMAGE_VERSION=</varname> fields of the
<filename>os-release</filename> file.</para> <filename>os-release</filename> file.</para>
<para><varname>HardwareVendor</varname> and <varname>HardwareModel</varname> expose information about the <para><varname>HardwareVendor</varname>, <varname>HardwareModel</varname>,
vendor of the hardware of the system. If no such information can be determined these properties are set <varname>HardwareFamily</varname>, <varname>HardwareSKU</varname> and <varname>HardwareVersion</varname>
to empty strings.</para> expose information about the vendor of the hardware of the system. 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 <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 the system's firmware, i.e. a version string and a vendor name. If no such information can be determined
@ -475,6 +488,9 @@ node /org/freedesktop/hostname1 {
<varname>VSockCID</varname> were added in version 256.</para> <varname>VSockCID</varname> were added in version 256.</para>
<para><varname>ChassisAssetTag</varname>, <varname>OperatingSystemImageID</varname> and <para><varname>ChassisAssetTag</varname>, <varname>OperatingSystemImageID</varname> and
<varname>OperatingSystemImageVersion</varname> were added in version 258.</para> <varname>OperatingSystemImageVersion</varname> were added in version 258.</para>
<para><varname>HardwareFamily</varname>,
<varname>HardwareSKU</varname>, and
<varname>HardwareVersion</varname> were added in version v258.</para>
</refsect2> </refsect2>
</refsect1> </refsect1>

View File

@ -66,6 +66,9 @@ typedef struct StatusInfo {
const char *hardware_serial; const char *hardware_serial;
sd_id128_t product_uuid; sd_id128_t product_uuid;
uint32_t vsock_cid; uint32_t vsock_cid;
const char *hardware_family;
const char *hardware_sku;
const char *hardware_version;
} StatusInfo; } StatusInfo;
static const char* chassis_string_to_glyph(const char *chassis) { static const char* chassis_string_to_glyph(const char *chassis) {
@ -320,6 +323,30 @@ static int print_status_info(StatusInfo *i) {
return table_log_add_error(r); return table_log_add_error(r);
} }
if (!isempty(i->hardware_family)) {
r = table_add_many(table,
TABLE_FIELD, "Hardware Family",
TABLE_STRING, i->hardware_family);
if (r < 0)
return table_log_add_error(r);
}
if (!isempty(i->hardware_sku)) {
r = table_add_many(table,
TABLE_FIELD, "Hardware SKU",
TABLE_STRING, i->hardware_sku);
if (r < 0)
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)) { if (!isempty(i->firmware_version)) {
r = table_add_many(table, r = table_add_many(table,
TABLE_FIELD, "Firmware Version", TABLE_FIELD, "Firmware Version",
@ -413,6 +440,9 @@ static int show_all_names(sd_bus *bus) {
{ "HomeURL", "s", NULL, offsetof(StatusInfo, home_url) }, { "HomeURL", "s", NULL, offsetof(StatusInfo, home_url) },
{ "HardwareVendor", "s", NULL, offsetof(StatusInfo, hardware_vendor) }, { "HardwareVendor", "s", NULL, offsetof(StatusInfo, hardware_vendor) },
{ "HardwareModel", "s", NULL, offsetof(StatusInfo, hardware_model) }, { "HardwareModel", "s", NULL, offsetof(StatusInfo, hardware_model) },
{ "HardwareFamily", "s", NULL, offsetof(StatusInfo, hardware_family) },
{ "HardwareSKU", "s", NULL, offsetof(StatusInfo, hardware_sku) },
{ "HardwareVersion", "s", NULL, offsetof(StatusInfo, hardware_version) },
{ "FirmwareVersion", "s", NULL, offsetof(StatusInfo, firmware_version) }, { "FirmwareVersion", "s", NULL, offsetof(StatusInfo, firmware_version) },
{ "FirmwareDate", "t", NULL, offsetof(StatusInfo, firmware_date) }, { "FirmwareDate", "t", NULL, offsetof(StatusInfo, firmware_date) },
{ "MachineID", "ay", bus_map_id128, offsetof(StatusInfo, machine_id) }, { "MachineID", "ay", bus_map_id128, offsetof(StatusInfo, machine_id) },

View File

@ -62,6 +62,9 @@ typedef enum {
PROP_LOCATION, PROP_LOCATION,
PROP_HARDWARE_VENDOR, PROP_HARDWARE_VENDOR,
PROP_HARDWARE_MODEL, PROP_HARDWARE_MODEL,
PROP_HARDWARE_FAMILY,
PROP_HARDWARE_SKU,
PROP_HARDWARE_VERSION,
/* Read from /etc/os-release (or /usr/lib/os-release) */ /* Read from /etc/os-release (or /usr/lib/os-release) */
PROP_OS_PRETTY_NAME, PROP_OS_PRETTY_NAME,
@ -166,7 +169,10 @@ static void context_read_machine_info(Context *c) {
(UINT64_C(1) << PROP_DEPLOYMENT) | (UINT64_C(1) << PROP_DEPLOYMENT) |
(UINT64_C(1) << PROP_LOCATION) | (UINT64_C(1) << PROP_LOCATION) |
(UINT64_C(1) << PROP_HARDWARE_VENDOR) | (UINT64_C(1) << PROP_HARDWARE_VENDOR) |
(UINT64_C(1) << PROP_HARDWARE_MODEL)); (UINT64_C(1) << PROP_HARDWARE_MODEL) |
(UINT64_C(1) << PROP_HARDWARE_FAMILY) |
(UINT64_C(1) << PROP_HARDWARE_SKU) |
(UINT64_C(1) << PROP_HARDWARE_VERSION));
r = parse_env_file(NULL, "/etc/machine-info", r = parse_env_file(NULL, "/etc/machine-info",
"PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME], "PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME],
@ -175,7 +181,10 @@ static void context_read_machine_info(Context *c) {
"DEPLOYMENT", &c->data[PROP_DEPLOYMENT], "DEPLOYMENT", &c->data[PROP_DEPLOYMENT],
"LOCATION", &c->data[PROP_LOCATION], "LOCATION", &c->data[PROP_LOCATION],
"HARDWARE_VENDOR", &c->data[PROP_HARDWARE_VENDOR], "HARDWARE_VENDOR", &c->data[PROP_HARDWARE_VENDOR],
"HARDWARE_MODEL", &c->data[PROP_HARDWARE_MODEL]); "HARDWARE_MODEL", &c->data[PROP_HARDWARE_MODEL],
"HARDWARE_FAMILY", &c->data[PROP_HARDWARE_FAMILY],
"HARDWARE_SKU", &c->data[PROP_HARDWARE_SKU],
"HARDWARE_VERSION", &c->data[PROP_HARDWARE_VERSION]);
if (r < 0 && r != -ENOENT) if (r < 0 && r != -ENOENT)
log_warning_errno(r, "Failed to read /etc/machine-info, ignoring: %m"); log_warning_errno(r, "Failed to read /etc/machine-info, ignoring: %m");
@ -395,6 +404,29 @@ static int get_hardware_serial(Context *c, char **ret) {
return get_device_tree_sysattr(c, "serial-number", ret); return get_device_tree_sysattr(c, "serial-number", ret);
} }
static int get_hardware_version(Context *c, char **ret) {
int r = -ENOENT;
assert(c);
assert(ret);
FOREACH_STRING(attr, "product_version", "board_version") {
r = get_dmi_sysattr(c, attr, ret);
if (r >= 0 || !ERRNO_IS_NEG_DEVICE_ABSENT(r))
return r;
}
return r;
}
static int get_hardware_family(Context *c, char **ret) {
return get_dmi_sysattr(c, "product_family", ret);
}
static int get_hardware_sku(Context *c, char **ret) {
return get_dmi_sysattr(c, "product_sku", ret);
}
static int get_firmware_version(Context *c, char **ret) { static int get_firmware_version(Context *c, char **ret) {
return get_dmi_sysattr(c, "bios_version", ret); return get_dmi_sysattr(c, "bios_version", ret);
} }
@ -820,7 +852,9 @@ static int property_get_hardware_property(
assert(reply); assert(reply);
assert(c); assert(c);
assert(IN_SET(prop, PROP_HARDWARE_VENDOR, PROP_HARDWARE_MODEL)); assert(IN_SET(prop, PROP_HARDWARE_VENDOR, PROP_HARDWARE_MODEL,
PROP_HARDWARE_FAMILY, PROP_HARDWARE_SKU,
PROP_HARDWARE_VERSION));
assert(getter); assert(getter);
context_read_machine_info(c); context_read_machine_info(c);
@ -855,6 +889,42 @@ static int property_get_hardware_model(
return property_get_hardware_property(reply, userdata, PROP_HARDWARE_MODEL, get_hardware_model); return property_get_hardware_property(reply, userdata, PROP_HARDWARE_MODEL, get_hardware_model);
} }
static int property_get_hardware_family(
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_FAMILY, get_hardware_family);
}
static int property_get_hardware_sku(
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_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( static int property_get_firmware_version(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,
@ -1535,7 +1605,8 @@ 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) { static int build_describe_response(Context *c, bool privileged, sd_json_variant **ret) {
_cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL, _cleanup_free_ char *hn = NULL, *dhn = NULL, *in = NULL,
*chassis = NULL, *vendor = NULL, *model = NULL, *serial = NULL, *firmware_version = NULL, *chassis = NULL, *vendor = NULL, *model = NULL, *serial = NULL, *firmware_version = NULL,
*firmware_vendor = NULL, *chassis_asset_tag = NULL; *firmware_vendor = NULL, *chassis_asset_tag = NULL, *family = NULL, *sku = NULL,
*version = NULL;
_cleanup_strv_free_ char **os_release_pairs = NULL, **machine_info_pairs = NULL; _cleanup_strv_free_ char **os_release_pairs = NULL, **machine_info_pairs = NULL;
usec_t firmware_date = USEC_INFINITY, eol = USEC_INFINITY; usec_t firmware_date = USEC_INFINITY, eol = USEC_INFINITY;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
@ -1571,6 +1642,12 @@ static int build_describe_response(Context *c, bool privileged, sd_json_variant
(void) get_hardware_vendor(c, &vendor); (void) get_hardware_vendor(c, &vendor);
if (isempty(c->data[PROP_HARDWARE_MODEL])) if (isempty(c->data[PROP_HARDWARE_MODEL]))
(void) get_hardware_model(c, &model); (void) get_hardware_model(c, &model);
if (isempty(c->data[PROP_HARDWARE_FAMILY]))
(void) get_hardware_family(c, &family);
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, &version);
if (privileged) { if (privileged) {
/* The product UUID and hardware serial is only available to privileged clients */ /* The product UUID and hardware serial is only available to privileged clients */
@ -1624,6 +1701,9 @@ static int build_describe_response(Context *c, bool privileged, sd_json_variant
SD_JSON_BUILD_PAIR_STRING("HardwareVendor", vendor ?: c->data[PROP_HARDWARE_VENDOR]), SD_JSON_BUILD_PAIR_STRING("HardwareVendor", vendor ?: c->data[PROP_HARDWARE_VENDOR]),
SD_JSON_BUILD_PAIR_STRING("HardwareModel", model ?: c->data[PROP_HARDWARE_MODEL]), SD_JSON_BUILD_PAIR_STRING("HardwareModel", model ?: c->data[PROP_HARDWARE_MODEL]),
SD_JSON_BUILD_PAIR_STRING("HardwareSerial", serial), SD_JSON_BUILD_PAIR_STRING("HardwareSerial", serial),
SD_JSON_BUILD_PAIR_STRING("HardwareFamily", family ?: c->data[PROP_HARDWARE_FAMILY]),
SD_JSON_BUILD_PAIR_STRING("HardwareSKU", sku ?: c->data[PROP_HARDWARE_SKU]),
SD_JSON_BUILD_PAIR_STRING("HardwareVersion", version ?: c->data[PROP_HARDWARE_VERSION]),
SD_JSON_BUILD_PAIR_STRING("FirmwareVersion", firmware_version), SD_JSON_BUILD_PAIR_STRING("FirmwareVersion", firmware_version),
SD_JSON_BUILD_PAIR_STRING("FirmwareVendor", firmware_vendor), SD_JSON_BUILD_PAIR_STRING("FirmwareVendor", firmware_vendor),
JSON_BUILD_PAIR_FINITE_USEC("FirmwareDate", firmware_date), JSON_BUILD_PAIR_FINITE_USEC("FirmwareDate", firmware_date),
@ -1702,6 +1782,9 @@ static const sd_bus_vtable hostname_vtable[] = {
SD_BUS_PROPERTY("BootID", "ay", property_get_boot_id, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("BootID", "ay", property_get_boot_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("VSockCID", "u", property_get_vsock_cid, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("VSockCID", "u", property_get_vsock_cid, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ChassisAssetTag", "s", property_get_chassis_asset_tag, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ChassisAssetTag", "s", property_get_chassis_asset_tag, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HardwareFamily", "s", property_get_hardware_family, 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_METHOD_WITH_ARGS("SetHostname", SD_BUS_METHOD_WITH_ARGS("SetHostname",
SD_BUS_ARGS("s", hostname, "b", interactive), SD_BUS_ARGS("s", hostname, "b", interactive),

View File

@ -35,7 +35,10 @@ static SD_VARLINK_DEFINE_METHOD(
SD_VARLINK_DEFINE_OUTPUT(ProductUUID, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), SD_VARLINK_DEFINE_OUTPUT(ProductUUID, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(VSockCID, SD_VARLINK_INT, SD_VARLINK_NULLABLE), SD_VARLINK_DEFINE_OUTPUT(VSockCID, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("An unique identifier of the system chassis."), SD_VARLINK_FIELD_COMMENT("An unique identifier of the system chassis."),
SD_VARLINK_DEFINE_OUTPUT(ChassisAssetTag, SD_VARLINK_STRING, SD_VARLINK_NULLABLE)); SD_VARLINK_DEFINE_OUTPUT(ChassisAssetTag, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_DEFINE_OUTPUT(HardwareFamily, 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_INTERFACE( SD_VARLINK_DEFINE_INTERFACE(
io_systemd_Hostname, io_systemd_Hostname,