summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch213
1 files changed, 213 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch
new file mode 100644
index 000000000..f366287f1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0104-Add-chip-unique-id-reading-interface.patch
@@ -0,0 +1,213 @@
+From 61fd1c976a0867deec8607183849969e2d96aef7 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Fri, 27 Mar 2020 14:42:05 -0700
+Subject: [PATCH] Add chip unique id reading interface
+
+This commit adds an interface for reading chip unique id value.
+Optionally, the id can be encrypted using a dts-supplied hash data.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
+---
+ drivers/soc/aspeed/aspeed-bmc-misc.c | 118 ++++++++++++++++++++++++---
+ 1 file changed, 105 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/soc/aspeed/aspeed-bmc-misc.c b/drivers/soc/aspeed/aspeed-bmc-misc.c
+index 04d97ab17274..c80b2e71f254 100644
+--- a/drivers/soc/aspeed/aspeed-bmc-misc.c
++++ b/drivers/soc/aspeed/aspeed-bmc-misc.c
+@@ -7,15 +7,18 @@
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
+ #include <linux/mfd/syscon.h>
++#include <crypto/hash.h>
+
+ #define DEVICE_NAME "aspeed-bmc-misc"
+
+ struct aspeed_bmc_ctrl {
+ const char *name;
+ u32 offset;
+- u32 mask;
++ u64 mask;
+ u32 shift;
+ bool read_only;
++ u32 reg_width;
++ const char *hash_data;
+ struct regmap *map;
+ struct kobj_attribute attr;
+ };
+@@ -31,6 +34,7 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+ struct aspeed_bmc_ctrl *ctrl)
+ {
+ int rc;
++ u32 mask;
+
+ /* Example child:
+ *
+@@ -38,6 +42,7 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+ * offset = <0x80>;
+ * bit-mask = <0x1>;
+ * bit-shift = <6>;
++ * reg-width = <64>;
+ * label = "foo";
+ * }
+ */
+@@ -48,9 +53,22 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+ if (rc < 0)
+ return rc;
+
+- rc = of_property_read_u32(child, "bit-mask", &ctrl->mask);
+- if (rc < 0)
+- return rc;
++ /* optional reg-width, default to 32 */
++ rc = of_property_read_u32(child, "reg-width", &ctrl->reg_width);
++ if (rc < 0 || ctrl->reg_width != 64)
++ ctrl->reg_width = 32;
++
++ if (ctrl->reg_width == 32) {
++ rc = of_property_read_u32(child, "bit-mask", &mask);
++ if (rc < 0)
++ return rc;
++ ctrl->mask = mask;
++ } else {
++ rc = of_property_read_u64(child, "bit-mask", &ctrl->mask);
++ if (rc < 0)
++ return rc;
++ }
++ ctrl->mask <<= ctrl->shift;
+
+ rc = of_property_read_u32(child, "bit-shift", &ctrl->shift);
+ if (rc < 0)
+@@ -58,7 +76,9 @@ static int aspeed_bmc_misc_parse_dt_child(struct device_node *child,
+
+ ctrl->read_only = of_property_read_bool(child, "read-only");
+
+- ctrl->mask <<= ctrl->shift;
++ /* optional hash_data for obfuscating reads */
++ if (of_property_read_string(child, "hash-data", &ctrl->hash_data))
++ ctrl->hash_data = NULL;
+
+ return 0;
+ }
+@@ -88,22 +108,94 @@ static int aspeed_bmc_misc_parse_dt(struct aspeed_bmc_misc *bmc,
+ return 0;
+ }
+
++#define SHA256_DIGEST_LEN 32
++static int hmac_sha256(u8 *key, u8 ksize, const char *plaintext, u8 psize,
++ u8 *output)
++{
++ struct crypto_shash *tfm;
++ struct shash_desc *shash;
++ int ret;
++
++ if (!ksize)
++ return -EINVAL;
++
++ tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
++ if (IS_ERR(tfm)) {
++ return -ENOMEM;
++ }
++
++ ret = crypto_shash_setkey(tfm, key, ksize);
++ if (ret)
++ goto failed;
++
++ shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm), GFP_KERNEL);
++ if (!shash) {
++ ret = -ENOMEM;
++ goto failed;
++ }
++
++ shash->tfm = tfm;
++ ret = crypto_shash_digest(shash, plaintext, psize, output);
++
++ kfree(shash);
++
++failed:
++ crypto_free_shash(tfm);
++ return ret;
++}
++
+ static ssize_t aspeed_bmc_misc_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+ {
+ struct aspeed_bmc_ctrl *ctrl;
+- unsigned int val;
++ u32 val;
++ u64 val64;
+ int rc;
++ u8 *binbuf;
++ size_t buf_len;
++ u8 hashbuf[SHA256_DIGEST_LEN];
+
+ ctrl = container_of(attr, struct aspeed_bmc_ctrl, attr);
++
++ if (ctrl->reg_width == 32) {
++ rc = regmap_read(ctrl->map, ctrl->offset, &val);
++ if (rc)
++ return rc;
++ val &= (u32)ctrl->mask;
++ val >>= ctrl->shift;
++
++ return sprintf(buf, "%u\n", val);
++ }
+ rc = regmap_read(ctrl->map, ctrl->offset, &val);
+ if (rc)
+ return rc;
++ val64 = val;
++ rc = regmap_read(ctrl->map, ctrl->offset + sizeof(u32), &val);
++ if (rc)
++ return rc;
++ /* aspeed puts 64-bit regs as L, H in address space */
++ val64 |= (u64)val << 32;
++ val64 &= ctrl->mask;
++ val64 >>= ctrl->shift;
++ buf_len = sizeof(val64);
++
++ if (ctrl->hash_data) {
++ rc = hmac_sha256((u8*)&val64, buf_len, ctrl->hash_data,
++ strlen(ctrl->hash_data), hashbuf);
++ if (rc)
++ return rc;
++ buf_len = SHA256_DIGEST_LEN;
++ binbuf = hashbuf;
++ } else {
++ binbuf = (u8*)&val64;
++ buf_len = sizeof(val64);
++ }
++ bin2hex(buf, binbuf, buf_len);
++ buf[buf_len * 2] = '\n';
++ rc = buf_len * 2 + 1;
+
+- val &= ctrl->mask;
+- val >>= ctrl->shift;
++ return rc;
+
+- return sprintf(buf, "%u\n", val);
+ }
+
+ static ssize_t aspeed_bmc_misc_store(struct kobject *kobj,
+@@ -114,15 +206,15 @@ static ssize_t aspeed_bmc_misc_store(struct kobject *kobj,
+ long val;
+ int rc;
+
+- rc = kstrtol(buf, 0, &val);
+- if (rc)
+- return rc;
+-
+ ctrl = container_of(attr, struct aspeed_bmc_ctrl, attr);
+
+ if (ctrl->read_only)
+ return -EROFS;
+
++ rc = kstrtol(buf, 0, &val);
++ if (rc)
++ return rc;
++
+ val <<= ctrl->shift;
+ rc = regmap_update_bits(ctrl->map, ctrl->offset, ctrl->mask, val);
+
+--
+2.17.1
+