crypto: ccp - Add support for displaying PSP firmware versions
authorMario Limonciello <mario.limonciello@amd.com>
Fri, 23 Jun 2023 13:49:52 +0000 (08:49 -0500)
committerHerbert Xu <herbert@gondor.apana.org.au>
Thu, 20 Jul 2023 10:13:16 +0000 (22:13 +1200)
As it's not always obvious what PSP bootloader or TEE version are
present in OEM systems, add the ability to get this information from
sysfs for supported platforms.

Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Documentation/ABI/testing/sysfs-driver-ccp
drivers/crypto/ccp/sp-dev.h
drivers/crypto/ccp/sp-pci.c

index 7aded9b7555350297cd29bd9d10d57f35810676d..ee6b787eee7a0332e6071143bd618feec3d3b4ce 100644 (file)
@@ -85,3 +85,21 @@ Description:
                Possible values:
                0: Not enforced
                1: Enforced
+
+What:          /sys/bus/pci/devices/<BDF>/bootloader_version
+Date:          June 2023
+KernelVersion: 6.4
+Contact:       mario.limonciello@amd.com
+Description:
+               The /sys/bus/pci/devices/<BDF>/bootloader_version
+               file reports the firmware version of the AMD AGESA
+               bootloader.
+
+What:          /sys/bus/pci/devices/<BDF>/tee_version
+Date:          June 2023
+KernelVersion: 6.4
+Contact:       mario.limonciello@amd.com
+Description:
+               The /sys/bus/pci/devices/<BDF>/tee_version
+               file reports the firmware version of the AMD Trusted
+               Execution Environment (TEE).
index 1253a021798580432048b5928558113c40e2a982..76c32ee6bd657968cd6f48706ef98e9c51450ba8 100644 (file)
@@ -51,6 +51,7 @@ struct tee_vdata {
        const unsigned int cmdbuff_addr_hi_reg;
        const unsigned int ring_wptr_reg;
        const unsigned int ring_rptr_reg;
+       const unsigned int info_reg;
 };
 
 struct platform_access_vdata {
@@ -69,6 +70,7 @@ struct psp_vdata {
        const unsigned int feature_reg;
        const unsigned int inten_reg;
        const unsigned int intsts_reg;
+       const unsigned int bootloader_info_reg;
 };
 
 /* Structure to hold SP device data */
index c8f075a7f49f8f000300f8fd4d5bd9cf6c5d9bed..6c93577950c7b15f06616c3cf4d6d2aa05516f30 100644 (file)
@@ -8,6 +8,7 @@
  * Author: Gary R Hook <gary.hook@amd.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include "ccp-dev.h"
 #include "psp-dev.h"
 
+/* used for version string AA.BB.CC.DD */
+#define AA                             GENMASK(31, 24)
+#define BB                             GENMASK(23, 16)
+#define CC                             GENMASK(15, 8)
+#define DD                             GENMASK(7, 0)
+
 #define MSIX_VECTORS                   2
 
 struct sp_pci {
@@ -88,8 +95,65 @@ static struct attribute_group psp_security_attr_group = {
        .is_visible = psp_security_is_visible,
 };
 
+#define version_attribute_show(name, _offset)                                  \
+static ssize_t name##_show(struct device *d, struct device_attribute *attr,    \
+                          char *buf)                                           \
+{                                                                              \
+       struct sp_device *sp = dev_get_drvdata(d);                              \
+       struct psp_device *psp = sp->psp_data;                                  \
+       unsigned int val = ioread32(psp->io_regs + _offset);                    \
+       return sysfs_emit(buf, "%02lx.%02lx.%02lx.%02lx\n",                     \
+                         FIELD_GET(AA, val),                   \
+                         FIELD_GET(BB, val),                   \
+                         FIELD_GET(CC, val),                   \
+                         FIELD_GET(DD, val));                  \
+}
+
+version_attribute_show(bootloader_version, psp->vdata->bootloader_info_reg)
+static DEVICE_ATTR_RO(bootloader_version);
+version_attribute_show(tee_version, psp->vdata->tee->info_reg)
+static DEVICE_ATTR_RO(tee_version);
+
+static struct attribute *psp_firmware_attrs[] = {
+       &dev_attr_bootloader_version.attr,
+       &dev_attr_tee_version.attr,
+       NULL,
+};
+
+static umode_t psp_firmware_is_visible(struct kobject *kobj, struct attribute *attr, int idx)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct sp_device *sp = dev_get_drvdata(dev);
+       struct psp_device *psp = sp->psp_data;
+       unsigned int val = 0xffffffff;
+
+       if (!psp)
+               return 0;
+
+       if (attr == &dev_attr_bootloader_version.attr &&
+           psp->vdata->bootloader_info_reg)
+               val = ioread32(psp->io_regs + psp->vdata->bootloader_info_reg);
+
+       if (attr == &dev_attr_tee_version.attr &&
+           psp->capability & PSP_CAPABILITY_TEE &&
+           psp->vdata->tee->info_reg)
+               val = ioread32(psp->io_regs + psp->vdata->tee->info_reg);
+
+       /* If platform disallows accessing this register it will be all f's */
+       if (val != 0xffffffff)
+               return 0444;
+
+       return 0;
+}
+
+static struct attribute_group psp_firmware_attr_group = {
+       .attrs = psp_firmware_attrs,
+       .is_visible = psp_firmware_is_visible,
+};
+
 static const struct attribute_group *psp_groups[] = {
        &psp_security_attr_group,
+       &psp_firmware_attr_group,
        NULL,
 };