Skip to content

Commit ac0cba6

Browse files
lixuzhaJiri Kosina
authored andcommitted
HID: intel-ish-hid: Add firmware version sysfs attributes
Introduce sysfs attributes to the intel-ish-ipc driver to expose the base and project firmware versions for ISH devices that load firmware from the host. The build tool embeds these versions into the ISH global manifest within the firmware binary during the firmware build process. The driver, upon loading the firmware, extracts this version information from the manifest and makes it accessible via sysfs. The base version corresponds to the firmware version provided in Intel's Firmware Development Kit (FDK), while the project version reflects the vendor-customized firmware derived from the FDK. These attributes provide userspace tools and applications with the ability to easily query the firmware versions, which is essential for firmware validation and troubleshooting. Example usages: $ cat /sys/devices/pci0000\:00/0000\:00\:12.0/firmware/base_version 5.8.0.7716 $ cat /sys/devices/pci0000\:00/0000\:00\:12.0/firmware/project_version 5.8.0.12472 Signed-off-by: Zhang Lixu <lixu.zhang@intel.com> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
1 parent 63cafaf commit ac0cba6

4 files changed

Lines changed: 125 additions & 1 deletion

File tree

drivers/hid/intel-ish-hid/ipc/pci-ish.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,58 @@ static int __maybe_unused ish_resume(struct device *device)
381381

382382
static SIMPLE_DEV_PM_OPS(ish_pm_ops, ish_suspend, ish_resume);
383383

384+
static ssize_t base_version_show(struct device *cdev,
385+
struct device_attribute *attr, char *buf)
386+
{
387+
struct ishtp_device *dev = dev_get_drvdata(cdev);
388+
389+
return sysfs_emit(buf, "%u.%u.%u.%u\n", dev->base_ver.major,
390+
dev->base_ver.minor, dev->base_ver.hotfix,
391+
dev->base_ver.build);
392+
}
393+
static DEVICE_ATTR_RO(base_version);
394+
395+
static ssize_t project_version_show(struct device *cdev,
396+
struct device_attribute *attr, char *buf)
397+
{
398+
struct ishtp_device *dev = dev_get_drvdata(cdev);
399+
400+
return sysfs_emit(buf, "%u.%u.%u.%u\n", dev->prj_ver.major,
401+
dev->prj_ver.minor, dev->prj_ver.hotfix,
402+
dev->prj_ver.build);
403+
}
404+
static DEVICE_ATTR_RO(project_version);
405+
406+
static struct attribute *ish_firmware_attrs[] = {
407+
&dev_attr_base_version.attr,
408+
&dev_attr_project_version.attr,
409+
NULL
410+
};
411+
412+
static umode_t firmware_is_visible(struct kobject *kobj, struct attribute *attr,
413+
int i)
414+
{
415+
struct ishtp_device *dev = dev_get_drvdata(kobj_to_dev(kobj));
416+
417+
return dev->driver_data->fw_generation ? attr->mode : 0;
418+
}
419+
420+
static const struct attribute_group ish_firmware_group = {
421+
.name = "firmware",
422+
.attrs = ish_firmware_attrs,
423+
.is_visible = firmware_is_visible,
424+
};
425+
426+
__ATTRIBUTE_GROUPS(ish_firmware);
427+
384428
static struct pci_driver ish_driver = {
385429
.name = KBUILD_MODNAME,
386430
.id_table = ish_pci_tbl,
387431
.probe = ish_probe,
388432
.remove = ish_remove,
389433
.shutdown = ish_shutdown,
390434
.driver.pm = &ish_pm_ops,
435+
.dev_groups = ish_firmware_groups,
391436
};
392437

393438
module_pci_driver(ish_driver);

drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ struct ishtp_driver_data {
140140
char *fw_generation;
141141
};
142142

143+
struct ish_version {
144+
u16 major;
145+
u16 minor;
146+
u16 hotfix;
147+
u16 build;
148+
};
149+
143150
/**
144151
* struct ishtp_device - ISHTP private device struct
145152
*/
@@ -236,6 +243,11 @@ struct ishtp_device {
236243
/* Dump to trace buffers if enabled*/
237244
ishtp_print_log print_log;
238245

246+
/* Base version of Intel's released firmware */
247+
struct ish_version base_ver;
248+
/* Vendor-customized project version */
249+
struct ish_version prj_ver;
250+
239251
/* Debug stats */
240252
unsigned int ipc_rx_cnt;
241253
unsigned long long ipc_rx_bytes_cnt;

drivers/hid/intel-ish-hid/ishtp/loader.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,28 @@ static int request_ish_firmware(const struct firmware **firmware_p,
308308
return _request_ish_firmware(firmware_p, filename, dev);
309309
}
310310

311+
static int copy_manifest(const struct firmware *fw, struct ish_global_manifest *manifest)
312+
{
313+
u32 offset;
314+
315+
for (offset = 0; offset + sizeof(*manifest) < fw->size; offset += ISH_MANIFEST_ALIGNMENT) {
316+
memcpy(manifest, fw->data + offset, sizeof(*manifest));
317+
318+
if (le32_to_cpu(manifest->sig_fourcc) == ISH_GLOBAL_SIG)
319+
return 0;
320+
}
321+
322+
return -1;
323+
}
324+
325+
static void copy_ish_version(struct version_in_manifest *src, struct ish_version *dst)
326+
{
327+
dst->major = le16_to_cpu(src->major);
328+
dst->minor = le16_to_cpu(src->minor);
329+
dst->hotfix = le16_to_cpu(src->hotfix);
330+
dst->build = le16_to_cpu(src->build);
331+
}
332+
311333
/**
312334
* ishtp_loader_work() - Load the ISHTP firmware
313335
* @work: The work structure
@@ -336,6 +358,7 @@ void ishtp_loader_work(struct work_struct *work)
336358
struct loader_xfer_query query = { .header = cpu_to_le32(query_hdr.val32), };
337359
struct loader_start start = { .header = cpu_to_le32(start_hdr.val32), };
338360
union loader_recv_message recv_msg;
361+
struct ish_global_manifest manifest;
339362
const struct firmware *ish_fw;
340363
void *dma_bufs[FRAGMENT_MAX_NUM] = {};
341364
u32 fragment_size;
@@ -372,7 +395,7 @@ void ishtp_loader_work(struct work_struct *work)
372395
if (rv)
373396
continue; /* try again if failed */
374397

375-
dev_dbg(dev->devc, "ISH Version %u.%u.%u.%u\n",
398+
dev_dbg(dev->devc, "ISH Bootloader Version %u.%u.%u.%u\n",
376399
recv_msg.query_ack.version_major,
377400
recv_msg.query_ack.version_minor,
378401
recv_msg.query_ack.version_hotfix,
@@ -390,6 +413,16 @@ void ishtp_loader_work(struct work_struct *work)
390413
continue; /* try again if failed */
391414

392415
dev_info(dev->devc, "firmware loaded. size:%zu\n", ish_fw->size);
416+
if (!copy_manifest(ish_fw, &manifest)) {
417+
copy_ish_version(&manifest.base_ver, &dev->base_ver);
418+
copy_ish_version(&manifest.prj_ver, &dev->prj_ver);
419+
dev_info(dev->devc, "FW base version: %u.%u.%u.%u\n",
420+
dev->base_ver.major, dev->base_ver.minor,
421+
dev->base_ver.hotfix, dev->base_ver.build);
422+
dev_info(dev->devc, "FW project version: %u.%u.%u.%u\n",
423+
dev->prj_ver.major, dev->prj_ver.minor,
424+
dev->prj_ver.hotfix, dev->prj_ver.build);
425+
}
393426
break;
394427
} while (--retry);
395428

drivers/hid/intel-ish-hid/ishtp/loader.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <linux/bits.h>
1212
#include <linux/jiffies.h>
13+
#include <linux/sizes.h>
1314
#include <linux/types.h>
1415

1516
#include "ishtp-dev.h"
@@ -228,4 +229,37 @@ struct ish_firmware_variant {
228229
*/
229230
void ishtp_loader_work(struct work_struct *work);
230231

232+
/* ISH Manifest alignment in binary is 4KB aligned */
233+
#define ISH_MANIFEST_ALIGNMENT SZ_4K
234+
235+
/* Signature for ISH global manifest */
236+
#define ISH_GLOBAL_SIG 0x47485349 /* FourCC 'I', 'S', 'H', 'G' */
237+
238+
struct version_in_manifest {
239+
__le16 major;
240+
__le16 minor;
241+
__le16 hotfix;
242+
__le16 build;
243+
};
244+
245+
/**
246+
* struct ish_global_manifest - global manifest for ISH
247+
* @sig_fourcc: Signature FourCC, should be 'I', 'S', 'H', 'G'.
248+
* @len: Length of the manifest.
249+
* @header_version: Version of the manifest header.
250+
* @flags: Flags for additional information.
251+
* @base_ver: Base version of Intel's released firmware.
252+
* @reserved: Reserved space for future use.
253+
* @prj_ver: Vendor-customized project version.
254+
*/
255+
struct ish_global_manifest {
256+
__le32 sig_fourcc;
257+
__le32 len;
258+
__le32 header_version;
259+
__le32 flags;
260+
struct version_in_manifest base_ver;
261+
__le32 reserved[13];
262+
struct version_in_manifest prj_ver;
263+
};
264+
231265
#endif /* _ISHTP_LOADER_H_ */

0 commit comments

Comments
 (0)