This adds a command for turning a AM62L SoC from HS-FS (High Security -
Field Securable) to HS-SE (High Security - Security Enforced) mode.

Signed-off-by: Sascha Hauer <[email protected]>
---
 commands/Kconfig                |   8 +
 commands/Makefile               |   1 +
 commands/k3-keywriter.c         | 172 +++++++++++++++++++
 common/Kconfig                  |   6 +
 common/Makefile                 |   1 +
 common/k3-keywriter-lite.c      | 293 ++++++++++++++++++++++++++++++++
 include/soc/k3/keywriter-lite.h | 177 +++++++++++++++++++
 7 files changed, 658 insertions(+)
 create mode 100644 commands/k3-keywriter.c
 create mode 100644 common/k3-keywriter-lite.c
 create mode 100644 include/soc/k3/keywriter-lite.h

diff --git a/commands/Kconfig b/commands/Kconfig
index 78b1e69dd3..4188405e3b 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -2307,6 +2307,14 @@ config CMD_HAB
        depends on HAB
        prompt "High Assurance boot (hab)"
 
+config CMD_K3_KEYWRITER
+       bool
+       depends on MACH_AM62LX
+       select K3_KEYWRITER_LITE
+       prompt "K3 keywriter support"
+       help
+         The K3 keywriter command provides support for fusing TI AM62Lx SoCs
+
 # end Hardware manipulation commands
 endmenu
 
diff --git a/commands/Makefile b/commands/Makefile
index 858e0c257e..85ba357708 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -110,6 +110,7 @@ obj-$(CONFIG_CMD_DMESG)             += dmesg.o
 obj-$(CONFIG_CMD_BLOBGEN)      += blobgen.o
 obj-$(CONFIG_CMD_BASENAME)     += basename.o
 obj-$(CONFIG_CMD_HAB)          += hab.o
+obj-$(CONFIG_CMD_K3_KEYWRITER) += k3-keywriter.o
 obj-$(CONFIG_CMD_DIRNAME)      += dirname.o
 obj-$(CONFIG_CMD_READLINK)     += readlink.o
 obj-$(CONFIG_CMD_LET)          += let.o
diff --git a/commands/k3-keywriter.c b/commands/k3-keywriter.c
new file mode 100644
index 0000000000..5243d8a11e
--- /dev/null
+++ b/commands/k3-keywriter.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <stdio.h>
+#include <malloc.h>
+#include <command.h>
+#include <getopt.h>
+#include <libfile.h>
+#include <linux/kstrtox.h>
+#include <soc/k3/keywriter-lite.h>
+
+static void *read_sha512(const char *filename)
+{
+       size_t size;
+       int ret;
+       void *hash;
+
+       ret = read_file_2(filename, &size, &hash, SHA512_DIGEST_SIZE + 1);
+       if (ret) {
+               printf("Cannot read %s: %pe\n", filename, ERR_PTR(ret));
+               return NULL;
+       }
+
+       if (size != SHA512_DIGEST_SIZE) {
+               printf("unexpected file size in hash file. Should be %u\n",
+                      SHA512_DIGEST_SIZE);
+               free(hash);
+               return NULL;
+       }
+
+       return hash;
+}
+
+static int do_k3_keywriter(int argc, char *argv[])
+{
+       struct keywriter_lite_packet p;
+       struct keywriter_lite_blob *blob;
+       int opt, ret;
+       const char *smpkh_file = NULL;
+       const char *bmpkh_file = NULL;
+       const char *outfile = NULL;
+       int key_count = -1;
+       int key_rev = -1;
+       bool doit = false;
+
+       blob = &p.blob;
+
+       while ((opt = getopt(argc, argv, "s:b:o:c:r:x")) > 0) {
+               switch (opt) {
+               case 's':
+                       smpkh_file = optarg;
+                       break;
+               case 'b':
+                       bmpkh_file = optarg;
+                       break;
+               case 'o':
+                       outfile = optarg;
+                       break;
+               case 'c':
+                       ret = kstrtouint(optarg, 0, &key_count);
+                       if (ret)
+                               goto err;
+                       break;
+               case 'r':
+                       ret = kstrtouint(optarg, 0, &key_rev);
+                       if (ret)
+                               goto err;
+                       break;
+               case 'x':
+                       doit = true;
+                       break;
+               }
+       }
+
+       k3_kwl_prepare(&p);
+
+       if (smpkh_file) {
+               unsigned char *hash = read_sha512(smpkh_file);
+
+               if (!hash) {
+                       ret = COMMAND_ERROR;
+                       goto err;
+               }
+
+               k3_kwl_set_smpkh(&blob->payload.smpkh, hash, FLAG_ACTIVE);
+               free(hash);
+       }
+
+       if (bmpkh_file) {
+               unsigned char *hash = read_sha512(bmpkh_file);
+
+               if (!hash) {
+                       ret = COMMAND_ERROR;
+                       goto err;
+               }
+
+               k3_kwl_set_bmpkh(&blob->payload.bmpkh, hash, FLAG_ACTIVE);
+               free(hash);
+       }
+
+       if (key_count >= 0) {
+               ret = k3_kwl_set_keycnt(&blob->payload.key_count, key_count,
+                                       FLAG_ACTIVE);
+               if (ret)
+                       goto err;
+       }
+
+       if (key_rev >= 0) {
+               ret = k3_kwl_set_key_revision(&blob->payload.key_revision, 
key_rev,
+                                             FLAG_ACTIVE);
+               if (ret)
+                       goto err;
+       }
+
+       ret = k3_kwl_finalize(&p);
+       if (ret) {
+               ret = COMMAND_ERROR;
+               printf("Cannot finalize keywriter lite structure: %pe\n", 
ERR_PTR(ret));
+               goto err;
+       }
+
+       if (outfile) {
+               ret = write_file(outfile, &p, sizeof(p));
+               if (ret) {
+                       ret = COMMAND_ERROR;
+                       printf("Failed to write %s: %pe\n", outfile, 
ERR_PTR(ret));
+                       goto err;
+               }
+       }
+
+       if (!smpkh_file && !bmpkh_file && key_count < 0 && key_rev < 0) {
+               printf("Nothing to do\n");
+               ret = COMMAND_ERROR_USAGE;
+       }
+
+       if (doit) {
+               printf("Writing fuses...\n");
+               ret = k3_kwl_fuse_writebuff(&p);
+               if (ret) {
+                       printf("Failed to write fuses: %pe\n", ERR_PTR(ret));
+                       goto err;
+               } else {
+                       printf("Fuses written successfully\n");
+               }
+       } else {
+               printf("Not writing fuses as requested. "
+                      "Pass -x to actually write fuses\n");
+               ret = 0;
+       }
+
+err:
+       return ret;
+}
+
+BAREBOX_CMD_HELP_START(k3_keywriter)
+BAREBOX_CMD_HELP_TEXT("K3 keywriter support")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-s <FILE>", "Read SMPK hash from <FILE>")
+BAREBOX_CMD_HELP_OPT ("-b <FILE>", "Read BMPK hash from <FILE>")
+BAREBOX_CMD_HELP_OPT ("-o <FILE>", "write data structure for ROM to <FILE> 
(for debug)")
+BAREBOX_CMD_HELP_OPT ("-c <NKEYS>","set key count to <NKEYS>")
+BAREBOX_CMD_HELP_OPT ("-r <REV>",  "set key revision to <REV>")
+BAREBOX_CMD_HELP_OPT ("-x",        "Do it! actually write fuses")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(k3_keywriter)
+       .cmd = do_k3_keywriter,
+       BAREBOX_CMD_DESC("K3 keywriter support")
+       BAREBOX_CMD_OPTS("-sbocrx")
+       BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+       BAREBOX_CMD_HELP(cmd_k3_keywriter_help)
+BAREBOX_CMD_END
diff --git a/common/Kconfig b/common/Kconfig
index d923d4c4b6..59fafb462a 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1327,3 +1327,9 @@ source "common/Kconfig.debug"
 config DDR_SPD
        bool
        select CRC_ITU_T
+
+config K3_KEYWRITER_LITE
+       bool
+       select DIGEST
+       select DIGEST_SHA512_GENERIC
+       depends on MACH_AM62LX
diff --git a/common/Makefile b/common/Makefile
index d501a6a275..8769d04d04 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_SERIAL_DEV_BUS)  += serdev.o
 obj-$(CONFIG_USB_GADGET)       += usbgadget.o
 obj-$(CONFIG_FASTBOOT_BASE)    += fastboot.o
 obj-$(CONFIG_CDEV_ALIAS)       += cdev-alias.o
+obj-$(CONFIG_K3_KEYWRITER_LITE)        += k3-keywriter-lite.o
 
 # dependencies on generated files need to be listed explicitly
 $(obj)/version.o: include/generated/compile.h
diff --git a/common/k3-keywriter-lite.c b/common/k3-keywriter-lite.c
new file mode 100644
index 0000000000..0919372c1b
--- /dev/null
+++ b/common/k3-keywriter-lite.c
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#define pr_fmt(fmt) "k3-keywriter: " fmt
+
+#include <digest.h>
+#include <string.h>
+#include <stdio.h>
+#include <dma.h>
+#include <memory.h>
+#include <linux/arm-smccc.h>
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <crypto/sha.h>
+#include <soc/k3/keywriter-lite.h>
+
+/* from 
https://software-dl.ti.com/tisci/esd/latest/6_topic_user_guides/key_writer_lite.html
 */
+
+#define PROGRAMMING_MODE_ONESHOT       0 /* all supported fields at once */
+#define PROGRAMMING_MODE_MULTISHOT     1 /* a subset of supported fields at 
once */
+#define PROGRAMMING_MODE_SMPKH         2 /* ust SMPKH */
+#define PROGRAMMING_MODE_BMPKH                 3 /* just BMPKH */
+#define PROGRAMMING_MODE_KEY_COUNT     4 /* just key count */
+#define PROGRAMMING_MODE_KEY_REVISION  5 /* just key revision */
+#define PROGRAMMING_MODE_SBL_SWREV     6 /* just SBL swrev */
+#define PROGRAMMING_MODE_SYSFW_SWREV   7 /* just SYSFW swrev */
+#define PROGRAMMING_MODE_BRDCFG_SWREV  8 /* just BRDCFG swrev */
+#define PROGRAMMING_MODE_MSV           9 /* just MSV */
+#define PROGRAMMING_MODE_JTAG          10 /* just JTAG unlock disable */
+#define PROGRAMMING_MODE_BOOT_MODE     11 /* just efuse boot modes */
+#define PROGRAMMING_MODE_EXTENDED_OTP  12 /* just extended otp */
+
+/*
+ * action_flags
+ * see gen_keywr_cert_helpers.sh:
+ * 16#${wp_flag}${rp_flag}${ovrd_flag}${active_flag}
+ */
+#define ACTION_FLAG_ENABLE 0x5a
+#define ACTION_FLAG_DISABLE 0xa5
+
+#define ACTION_FLAG_WP         GENMASK(31, 24)
+#define ACTION_FLAG_RP         GENMASK(23, 16)
+#define ACTION_FLAG_OVRD       GENMASK(15, 8)
+#define ACTION_FLAG_ACTIVE     GENMASK(7, 0)
+
+static unsigned int k3_kwl_set_flags(unsigned int f)
+{
+       unsigned int en = ACTION_FLAG_ENABLE;
+       unsigned int dis = ACTION_FLAG_DISABLE;
+
+       return FIELD_PREP(ACTION_FLAG_WP, f & FLAG_WP ? en : dis) |
+               FIELD_PREP(ACTION_FLAG_RP, f & FLAG_RP ? en : dis) |
+               FIELD_PREP(ACTION_FLAG_OVRD, f & FLAG_OVRD ? en : dis) |
+               FIELD_PREP(ACTION_FLAG_ACTIVE, f & FLAG_ACTIVE ? en : dis);
+}
+
+int k3_kwl_set_smpkh(struct mpkh *mpkh, const char *sha, unsigned int flags)
+{
+       mpkh->field_header = SMPKH_MAGIC;
+       mpkh->action_flags = k3_kwl_set_flags(flags);
+       memcpy(mpkh->mpkh, sha, SHA512_DIGEST_SIZE);
+
+       return 0;
+}
+
+int k3_kwl_set_bmpkh(struct mpkh *mpkh, const char *sha, unsigned int flags)
+{
+       mpkh->field_header = BMPKH_MAGIC;
+       mpkh->action_flags = k3_kwl_set_flags(flags);
+       memcpy(mpkh->mpkh, sha, SHA512_DIGEST_SIZE);
+
+       return 0;
+}
+
+int k3_kwl_set_keycnt(struct key_cnt *k, unsigned int count, unsigned int 
flags)
+{
+       if (count < 1 || count > 2) {
+               pr_err("Only 1 or 2 allowed for key count\n");
+               return -EINVAL;
+       }
+
+       k->field_header = KEY_CNT_MAGIC;
+       k->action_flags = k3_kwl_set_flags(flags);
+       k->count = BIT(count) - 1;
+
+       return 0;
+}
+
+int k3_kwl_set_key_revision(struct key_revision *k, unsigned int revision,
+                          unsigned int flags)
+{
+       if (revision < 1 || revision > 2) {
+               pr_err("Only 1 or 2 allowed for key revision\n");
+               return -EINVAL;
+       }
+
+       k->field_header = KEY_REVISION_MAGIC;
+       k->action_flags = k3_kwl_set_flags(flags);
+       k->revision = BIT(revision) - 1;
+
+       return 0;
+}
+
+int k3_kwl_set_sbl_revision(struct sbl_revision *k, unsigned int revision,
+                          unsigned int flags)
+{
+       k->field_header = SBL_REVISION_MAGIC;
+       k->action_flags = k3_kwl_set_flags(flags);
+       k->revision = BIT(revision) - 1;
+
+       return 0;
+}
+
+int k3_kwl_set_brdcfg_revision(struct brdcfg_revision *k, unsigned int 
revision,
+                          unsigned int flags)
+{
+       k->field_header = BRDCFG_REVISION_MAGIC;
+       k->action_flags = k3_kwl_set_flags(flags);
+       k->revision = BIT(revision) - 1;
+
+       return 0;
+}
+
+int k3_kwl_set_msv(struct msv *k, unsigned int msv, unsigned int flags)
+{
+       k->field_header = MSV_MAGIC;
+       k->action_flags = k3_kwl_set_flags(flags);
+       k->msv = msv;
+
+       return 0;
+}
+
+int k3_kwl_set_jtag_disable(struct jtag_disable *k, unsigned int jtag,
+                                unsigned int flags)
+{
+       k->field_header = JTAG_DISABLE_MAGIC;
+       k->action_flags = k3_kwl_set_flags(flags);
+       k->jtag = jtag;
+
+       return 0;
+}
+
+int k3_kwl_set_bootmode(struct boot_mode *k, unsigned int fuse_id,
+                                unsigned int boot_mode, unsigned int flags)
+{
+       if (fuse_id < 1 || fuse_id > 2) {
+               pr_err("Only 1 or 2 allowed for fuse_id\n");
+               return -EINVAL;
+       }
+
+       k->field_header = BOOT_MODE_MAGIC;
+       k->action_flags = k3_kwl_set_flags(flags);
+       k->fuse_id = fuse_id;
+       k->boot_mode = boot_mode;
+
+       return 0;
+}
+
+int k3_kwl_set_ext_otp(struct ext_otp *k, unsigned int bits, unsigned int 
index,
+                           uint8_t *wprp, uint8_t *otp, unsigned int flags)
+{
+       k->field_header = EXT_OTP_MAGIC;
+       k->action_flags = k3_kwl_set_flags(flags);
+       k->size = bits;
+       k->index = index;
+       memcpy(k->wprp, wprp, sizeof(k->wprp));
+       memcpy(k->otp, otp, sizeof(k->otp));
+
+       return 0;
+}
+
+#define FD FIELD_PREP_CONST(ACTION_FLAG_ACTIVE, ACTION_FLAG_DISABLE)
+
+static struct keywriter_lite_packet keywrite_lite_template = {
+       .tisci_id = TISCI_MSG_KEY_WRITER_LITE,
+       .blob = {
+               .hdr = {
+                       .magic = KEYWRITER_LITE_HEADER_MAGIC,
+                       .size = sizeof(struct keywriter_lite_payload),
+                       .abi_major = 0x0,
+                       .abi_minor = 0x1,
+                       .cmd_id = PROGRAMMING_MODE_MULTISHOT,
+               },
+
+               .payload = {
+                       .mpk_options = {
+                               .field_header = MPK_OPTS_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .smpkh = {
+                               .field_header = SMPKH_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .bmpkh = {
+                               .field_header = BMPKH_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .key_count = {
+                               .field_header = KEY_CNT_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .key_revision = {
+                               .field_header = KEY_REVISION_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .sbl_rev = {
+                               .field_header = SBL_REVISION_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .sysfw_rev = {
+                               .field_header = SYSFW_REVISION_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .brdcfg_rev = {
+                               .field_header = BRDCFG_REVISION_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .msv_val = {
+                               .field_header = MSV_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .jtag_disable = {
+                               .field_header = JTAG_DISABLE_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .boot_mode = {
+                               .field_header = BOOT_MODE_MAGIC,
+                               .action_flags = FD,
+                       },
+                       .ext_otp = {
+                               .field_header = EXT_OTP_MAGIC,
+                               .action_flags = FD,
+                       },
+               },
+       },
+};
+#undef FD
+
+void k3_kwl_prepare(struct keywriter_lite_packet *p)
+{
+       memcpy(p, &keywrite_lite_template, sizeof(keywrite_lite_template));
+}
+
+int k3_kwl_finalize(struct keywriter_lite_packet *p)
+{
+       struct digest *sha512;
+       int ret;
+
+       sha512 = digest_alloc("sha512");
+       if (!sha512)
+               return -ENOENT;
+
+       ret = digest_digest(sha512, &p->blob, offsetof(typeof(p->blob), hash),
+                           p->blob.hash);
+       if (ret)
+               return ret;
+
+       digest_free(sha512);
+
+       return 0;
+}
+
+#define K3_SIP_OTP_WRITEBUFF 0xC2000000
+
+int k3_kwl_fuse_writebuff(struct keywriter_lite_packet *p)
+{
+       struct resource *resource;
+       unsigned long keywriter_lite_data = 0x82000000;
+       struct arm_smccc_res res;
+
+       resource = request_sdram_region("keywriter-lite", keywriter_lite_data,
+                                       4096, MEMTYPE_LOADER_DATA, MEMATTRS_RW);
+       if (!resource)
+               return -ENOMEM;
+
+       /*
+        * Yes, we are passing the memory address of the buffer along with
+        * the SMC call, but TF-A will crash when it is different from this
+        * address on AM62L.
+        */
+
+       memcpy((void *)keywriter_lite_data, p, sizeof(keywrite_lite_template));
+
+       /* Make SiP SMC call and send the addr in the parameter register */
+       arm_smccc_smc(K3_SIP_OTP_WRITEBUFF, (unsigned long)keywriter_lite_data,
+                     0, 0, 0, 0, 0, 0, &res);
+
+       if (res.a0 != 0)
+               printf("SMC call failed: Error code %ld\n", res.a0);
+
+       release_sdram_region(resource);
+
+       return res.a0;
+}
diff --git a/include/soc/k3/keywriter-lite.h b/include/soc/k3/keywriter-lite.h
new file mode 100644
index 0000000000..4bf3788ee4
--- /dev/null
+++ b/include/soc/k3/keywriter-lite.h
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#ifndef __SOC_K3_KEYWRITER_LITE_H
+#define __SOC_K3_KEYWRITER_LITE_H
+
+#include <crypto/sha.h>
+
+/*
+ * structure layout and magic values are from:
+ * 
https://software-dl.ti.com/tisci/esd/latest/6_topic_user_guides/key_writer_lite.html
+ * with corrections from:
+ * 
https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1578568/am62l-am62l-secure-boot-keywriter-lite
+ */
+
+#define KEYWRITER_LITE_HEADER_MAGIC    0x9012
+struct keywriter_lite_header {
+       uint16_t magic;
+       uint16_t size;
+       uint8_t abi_major;      /* 0x00 */
+       uint8_t abi_minor;      /* 0x01 */
+       uint16_t reserved0;
+       uint32_t cmd_id;        /* PROGRAMMING_MODE_* */
+       uint32_t reserved1[2];
+} __attribute__((packed));
+
+#define MPK_OPTS_MAGIC 0x4a7e
+struct mpk_opts {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint16_t options;       /* 0x0 */
+       uint8_t resv_field[2];  /* 0x0 */
+       uint32_t reserved[2];   /* 0x0 */
+} __attribute__((packed));
+
+#define SMPKH_MAGIC    0x1234
+#define BMPKH_MAGIC    0x9FFC
+struct mpkh {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint8_t mpkh[64];
+       uint32_t reserved[2];
+} __attribute__((packed));
+
+#define KEY_CNT_MAGIC  0x5678
+struct key_cnt {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint32_t count;
+       uint32_t reserved[2];
+} __attribute__((packed));
+
+#define KEY_REVISION_MAGIC     0x62c8
+struct key_revision {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint32_t revision; /* The key revision value encoded in bit-position 
format */
+       uint32_t reserved[2];
+} __attribute__((packed));
+
+#define SBL_REVISION_MAGIC     0x8bad
+struct sbl_revision {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint64_t revision; /* The SBL software revision value encoded in 
bit-position format */
+       uint32_t reserved[3];
+} __attribute__((packed));
+
+#define SYSFW_REVISION_MAGIC   0x45a9  /* must be typo: same as in struct 
sbl_revision */
+struct sysfw_revision {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint64_t revision; /* The SYSFW software revision value encoded in 
bit-position format */
+       uint32_t reserved[3];
+} __attribute__((packed));
+
+#define BRDCFG_REVISION_MAGIC  0x98dc
+struct brdcfg_revision {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint64_t revision; /* The BRDCFG software revision value encoded in 
bit-position format */
+       uint32_t reserved[4];
+} __attribute__((packed));
+
+#define MSV_MAGIC              0x1337
+struct msv {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint32_t msv;           /* The 20-bit MSV value */
+       uint32_t reserved[2];
+} __attribute__((packed));
+
+#define JTAG_DISABLE_MAGIC     0x7421
+struct jtag_disable {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint32_t jtag;          /* The 4-bit jtag unlock disable value */
+       uint32_t reserved[2];
+} __attribute__((packed));
+
+#define BOOT_MODE_MAGIC                0xa1b2
+struct boot_mode {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint32_t fuse_id;       /* The index of the fuse to program currently 
accepts only 1,2 */
+       uint32_t boot_mode;     /* The 25-bit boot mode value to program */
+       uint32_t reserved[2];
+} __attribute__((packed));
+
+#define EXT_OTP_MAGIC          0xd0e5
+struct ext_otp {
+       uint32_t field_header;
+       uint32_t action_flags;
+       uint16_t size;          /* The number of bits to program */
+       uint16_t index;         /* The index in the 1024-bits space to start 
programming from */
+       uint8_t wprp[16];       /* Read protect/write protect array */
+       uint8_t otp[128];       /* The 1024 bits extended otp data */
+       uint32_t reserved[4];
+} __attribute__((packed));
+
+struct keywriter_lite_payload {
+       struct mpk_opts mpk_options;
+       struct mpkh smpkh;
+       struct mpkh bmpkh;
+       struct key_cnt key_count;
+       struct key_revision key_revision;
+       struct sbl_revision sbl_rev;
+       struct sysfw_revision sysfw_rev;
+       struct brdcfg_revision brdcfg_rev;
+       struct msv msv_val;
+       struct jtag_disable jtag_disable;
+       struct boot_mode boot_mode;
+       struct ext_otp ext_otp;
+} __attribute__((packed));
+
+#define TISCI_MSG_KEY_WRITER_LITE 0x9045
+
+struct keywriter_lite_blob {
+       struct keywriter_lite_header hdr;
+       struct keywriter_lite_payload payload;
+       unsigned char hash[SHA512_DIGEST_SIZE];
+} __attribute__((packed));
+
+struct keywriter_lite_packet {
+       uint32_t ver_info_unused;
+       uint32_t tisci_id;
+       struct keywriter_lite_blob blob;
+};
+
+enum action_flags {
+       FLAG_WP =       BIT(0),
+       FLAG_RP =       BIT(1),
+       FLAG_OVRD =     BIT(2),
+       FLAG_ACTIVE =   BIT(3),
+};
+
+int k3_kwl_set_smpkh(struct mpkh *mpkh, const char *sha, unsigned int flags);
+int k3_kwl_set_bmpkh(struct mpkh *mpkh, const char *sha, unsigned int flags);
+int k3_kwl_set_keycnt(struct key_cnt *k, unsigned int count, unsigned int 
flags);
+int k3_kwl_set_key_revision(struct key_revision *k, unsigned int revision,
+                          unsigned int flags);
+int k3_kwl_set_sbl_revision(struct sbl_revision *k, unsigned int revision,
+                          unsigned int flags);
+int k3_kwl_set_brdcfg_revision(struct brdcfg_revision *k, unsigned int 
revision,
+                          unsigned int flags);
+int k3_kwl_set_msv(struct msv *k, unsigned int msv, unsigned int flags);
+int k3_kwl_set_jtag_disable(struct jtag_disable *k, unsigned int jtag,
+                                unsigned int flags);
+int k3_kwl_set_bootmode(struct boot_mode *k, unsigned int fuse_id,
+                                unsigned int boot_mode, unsigned int flags);
+int k3_kwl_set_ext_otp(struct ext_otp *k, unsigned int bits, unsigned int 
index,
+                           uint8_t *wprp, uint8_t *otp, unsigned int flags);
+
+void k3_kwl_prepare(struct keywriter_lite_packet *p);
+int k3_kwl_finalize(struct keywriter_lite_packet *p);
+int k3_kwl_fuse_writebuff(struct keywriter_lite_packet *p);
+
+
+#endif /* __SOC_K3_KEYWRITER_LITE_H */
-- 
2.47.3


Reply via email to