summaryrefslogtreecommitdiff
path: root/board/gdsys/a38x/keyprogram.c
diff options
context:
space:
mode:
authorDirk Eibach <dirk.eibach@gdsys.cc>2017-02-22 16:07:23 +0100
committerStefan Roese <sr@denx.de>2017-03-23 15:48:28 +0100
commit60083261a1b33b492ddb5335c125f1223087068b (patch)
treebf90ef4650b59b3b201909db4e95fefb9b377aaf /board/gdsys/a38x/keyprogram.c
parent2a792753d6a1fe8f2310928ebd5534e4d87a8030 (diff)
arm: mvebu: Add gdsys ControlCenter-Compact board
The gdsys ControlCenter Digital board is based on a Marvell Armada 38x SOC. It boots from SPI-Flash but can be configured to boot from SD-card for factory programming and testing. On board peripherals include: - 2 x GbE - Xilinx Kintex-7 FPGA connected via PCIe - mSATA - USB3 host - Atmel TPM Signed-off-by: Dirk Eibach <dirk.eibach@gdsys.cc> Signed-off-by: Mario Six <mario.six@gdsys.cc> Signed-off-by: Stefan Roese <sr@denx.de>
Diffstat (limited to 'board/gdsys/a38x/keyprogram.c')
-rw-r--r--board/gdsys/a38x/keyprogram.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/board/gdsys/a38x/keyprogram.c b/board/gdsys/a38x/keyprogram.c
new file mode 100644
index 0000000000..a4a6f1cca5
--- /dev/null
+++ b/board/gdsys/a38x/keyprogram.c
@@ -0,0 +1,158 @@
+/*
+ * (C) Copyright 2016
+ * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <tpm.h>
+#include <malloc.h>
+#include <linux/ctype.h>
+#include <asm/unaligned.h>
+
+#include "hre.h"
+
+int flush_keys(void)
+{
+ u16 key_count;
+ u8 buf[288];
+ u8 *ptr;
+ u32 err;
+ uint i;
+
+ /* fetch list of already loaded keys in the TPM */
+ err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+ if (err)
+ return -1;
+ key_count = get_unaligned_be16(buf);
+ ptr = buf + 2;
+ for (i = 0; i < key_count; ++i, ptr += 4) {
+ err = tpm_flush_specific(get_unaligned_be32(ptr), TPM_RT_KEY);
+ if (err && err != TPM_KEY_OWNER_CONTROL)
+ return err;
+ }
+
+ return 0;
+}
+
+int decode_hexstr(char *hexstr, u8 **result)
+{
+ int len = strlen(hexstr);
+ int bytes = len / 2;
+ int i;
+ u8 acc = 0;
+
+ if (len % 2 == 1)
+ return 1;
+
+ *result = (u8 *)malloc(bytes);
+
+ for (i = 0; i < len; i++) {
+ char cur = tolower(hexstr[i]);
+ u8 val;
+
+ if ((cur >= 'a' && cur <= 'f') || (cur >= '0' && cur <= '9')) {
+ val = cur - (cur > '9' ? 87 : 48);
+
+ if (i % 2 == 0)
+ acc = 16 * val;
+ else
+ (*result)[i / 2] = acc + val;
+ } else {
+ free(*result);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int extract_subprogram(u8 **progdata, u32 expected_magic,
+ struct key_program **result)
+{
+ struct key_program *prog = *result;
+ u32 magic, code_crc, code_size;
+
+ magic = get_unaligned_be32(*progdata);
+ code_crc = get_unaligned_be32(*progdata + 4);
+ code_size = get_unaligned_be32(*progdata + 8);
+
+ *progdata += 12;
+
+ if (magic != expected_magic)
+ return -1;
+
+ *result = malloc(sizeof(struct key_program) + code_size);
+
+ if (!*result)
+ return -1;
+
+ prog->magic = magic;
+ prog->code_crc = code_crc;
+ prog->code_size = code_size;
+ memcpy(prog->code, *progdata, code_size);
+
+ *progdata += code_size;
+
+ if (hre_verify_program(prog)) {
+ free(prog);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct key_program *parse_and_check_keyprog(u8 *progdata)
+{
+ struct key_program *result = NULL, *hmac = NULL;
+
+ /* Part 1: Load key program */
+
+ if (extract_subprogram(&progdata, MAGIC_KEY_PROGRAM, &result))
+ return NULL;
+
+ /* Part 2: Load hmac program */
+
+ if (extract_subprogram(&progdata, MAGIC_HMAC, &hmac))
+ return NULL;
+
+ free(hmac);
+
+ return result;
+}
+
+int load_and_run_keyprog(void)
+{
+ char *cmd = NULL;
+ u8 *binprog = NULL;
+ char *hexprog;
+ struct key_program *prog;
+
+ cmd = getenv("loadkeyprogram");
+
+ if (!cmd || run_command(cmd, 0))
+ return 1;
+
+ hexprog = getenv("keyprogram");
+
+ if (decode_hexstr(hexprog, &binprog))
+ return 1;
+
+ prog = parse_and_check_keyprog(binprog);
+ free(binprog);
+
+ if (!prog)
+ return 1;
+
+ if (hre_run_program(prog->code, prog->code_size)) {
+ free(prog);
+ return 1;
+ }
+
+ printf("\nSD code ran successfully\n");
+
+ free(prog);
+
+ return 0;
+}