summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
Diffstat (limited to 'board')
-rw-r--r--board/gardena/smart-gateway-mt7688/board.c269
-rw-r--r--board/gdsys/a38x/controlcenterdc.c25
-rw-r--r--board/gdsys/a38x/hre.c66
-rw-r--r--board/gdsys/a38x/hre.h2
-rw-r--r--board/gdsys/a38x/keyprogram.c12
-rw-r--r--board/gdsys/a38x/keyprogram.h4
-rw-r--r--board/gdsys/p1022/controlcenterd-id.c117
7 files changed, 412 insertions, 83 deletions
diff --git a/board/gardena/smart-gateway-mt7688/board.c b/board/gardena/smart-gateway-mt7688/board.c
index 3a1838e44a..6e11077977 100644
--- a/board/gardena/smart-gateway-mt7688/board.c
+++ b/board/gardena/smart-gateway-mt7688/board.c
@@ -4,11 +4,44 @@
*/
#include <common.h>
+#include <environment.h>
#include <led.h>
+#include <net.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <uuid.h>
+#include <linux/ctype.h>
#include <linux/io.h>
#define MT76XX_AGPIO_CFG 0x1000003c
+#define FACTORY_DATA_OFFS 0xc0000
+#define FACTORY_DATA_SECT_SIZE 0x10000
+#if ((CONFIG_ENV_OFFSET_REDUND + CONFIG_ENV_SIZE_REDUND) > FACTORY_DATA_OFFS)
+#error "U-Boot image with environment too big (overlapping with factory-data)!"
+#endif
+#define FACTORY_DATA_USER_OFFS 0x140
+#define FACTORY_DATA_SIZE 0x1f0
+#define FACTORY_DATA_CRC_LEN (FACTORY_DATA_SIZE - \
+ FACTORY_DATA_USER_OFFS - sizeof(u32))
+
+#define FACTORY_DATA_MAGIC 0xCAFEBABE
+
+struct factory_data_values {
+ u8 pad_1[4];
+ u8 wifi_mac[6]; /* offs: 0x004: binary value */
+ u8 pad_2[30];
+ u8 eth_mac[6]; /* offs: 0x028: binary value */
+ u8 pad_3[FACTORY_DATA_USER_OFFS - 4 - 6 - 30 - 6];
+ /* User values start here at offset 0x140 */
+ u32 crc;
+ u32 magic;
+ u32 version;
+ char ipr_id[UUID_STR_LEN]; /* UUID as string w/o ending \0 */
+ char hqv_id[UUID_STR_LEN]; /* UUID as string w/o ending \0 */
+ char unielec_id[UUID_STR_LEN]; /* UUID as string w/o ending \0 */
+};
+
int board_early_init_f(void)
{
void __iomem *gpio_mode;
@@ -20,10 +53,246 @@ int board_early_init_f(void)
return 0;
}
+static bool prepare_uuid_var(const char *fd_ptr, const char *env_var_name,
+ char errorchar)
+{
+ char str[UUID_STR_LEN + 1] = { 0 }; /* Enough for UUID stuff */
+ bool env_updated = false;
+ char *env;
+ int i;
+
+ memcpy(str, fd_ptr, UUID_STR_LEN);
+
+ /* Convert non-ascii character to 'X' */
+ for (i = 0; i < UUID_STR_LEN; i++) {
+ if (!(isascii(str[i]) && isprint(str[i])))
+ str[i] = errorchar;
+ }
+
+ env = env_get(env_var_name);
+ if (strcmp(env, str)) {
+ env_set(env_var_name, str);
+ env_updated = true;
+ }
+
+ return env_updated;
+}
+
+static void factory_data_env_config(void)
+{
+ struct factory_data_values *fd;
+ struct spi_flash *sf;
+ int env_updated = 0;
+ char str[UUID_STR_LEN + 1]; /* Enough for UUID stuff */
+ char *env;
+ u8 *buf;
+ u32 crc;
+ int ret;
+ u8 *ptr;
+
+ buf = malloc(FACTORY_DATA_SIZE);
+ if (!buf) {
+ printf("F-Data:Unable to allocate buffer\n");
+ return;
+ }
+
+ /*
+ * Get values from factory-data area in SPI NOR
+ */
+ sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+ CONFIG_SF_DEFAULT_CS,
+ CONFIG_SF_DEFAULT_SPEED,
+ CONFIG_SF_DEFAULT_MODE);
+ if (!sf) {
+ printf("F-Data:Unable to access SPI NOR flash\n");
+ goto err_free;
+ }
+
+ ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SIZE,
+ (void *)buf);
+ if (ret) {
+ printf("F-Data:Unable to read factory-data from SPI NOR\n");
+ goto err_spi_flash;
+ }
+
+ fd = (struct factory_data_values *)buf;
+
+ if (fd->magic != FACTORY_DATA_MAGIC)
+ printf("F-Data:Magic value not correct\n");
+
+ crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+ if (crc != fd->crc)
+ printf("F-Data:CRC not correct\n");
+ else
+ printf("F-Data:factory-data version %x detected\n",
+ fd->version);
+
+ /* Handle wifi_mac env variable */
+ ptr = fd->wifi_mac;
+ sprintf(str, "%pM", ptr);
+ if (!is_valid_ethaddr(ptr))
+ printf("F-Data:Invalid MAC addr: wifi_mac %s\n", str);
+
+ env = env_get("wifiaddr");
+ if (strcmp(env, str)) {
+ env_set("wifiaddr", str);
+ env_updated = 1;
+ }
+
+ /* Handle eth_mac env variable */
+ ptr = fd->eth_mac;
+ sprintf(str, "%pM", ptr);
+ if (!is_valid_ethaddr(ptr))
+ printf("F-Data:Invalid MAC addr: eth_mac %s\n", str);
+
+ env = env_get("ethaddr");
+ if (strcmp(env, str)) {
+ env_set("ethaddr", str);
+ env_updated = 1;
+ }
+
+ /* Handle UUID env variables */
+ env_updated |= prepare_uuid_var(fd->ipr_id, "linuxmoduleid", 'X');
+ env_updated |= prepare_uuid_var(fd->hqv_id, "linuxmodulehqvid", '\0');
+ env_updated |= prepare_uuid_var(fd->unielec_id,
+ "linuxmoduleunielecid", '\0');
+
+ /* Check if the environment was updated and needs to get stored */
+ if (env_updated != 0) {
+ printf("F-Data:Values don't match env values -> saving\n");
+ env_save();
+ } else {
+ debug("F-Data:Values match current env values\n");
+ }
+
+err_spi_flash:
+ spi_flash_free(sf);
+
+err_free:
+ free(buf);
+}
+
int board_late_init(void)
{
if (IS_ENABLED(CONFIG_LED))
led_default_state();
+ factory_data_env_config();
+
return 0;
}
+
+static void copy_or_generate_uuid(char *fd_ptr, const char *env_var_name)
+{
+ char str[UUID_STR_LEN + 1] = { 0 }; /* Enough for UUID stuff */
+ char *env;
+
+ /* Don't use the UUID dest place, as the \0 char won't fit */
+ env = env_get(env_var_name);
+ if (env)
+ strncpy(str, env, UUID_STR_LEN);
+ else
+ gen_rand_uuid_str(str, UUID_STR_FORMAT_STD);
+
+ memcpy(fd_ptr, str, UUID_STR_LEN);
+}
+
+/*
+ * Helper function to provide some sane factory-data values for testing
+ * purpose, when these values are not programmed correctly
+ */
+int do_fd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ struct factory_data_values *fd;
+ struct spi_flash *sf;
+ u8 *buf;
+ int ret = CMD_RET_FAILURE;
+
+ buf = malloc(FACTORY_DATA_SECT_SIZE);
+ if (!buf) {
+ printf("F-Data:Unable to allocate buffer\n");
+ return CMD_RET_FAILURE;
+ }
+
+ sf = spi_flash_probe(CONFIG_SF_DEFAULT_BUS,
+ CONFIG_SF_DEFAULT_CS,
+ CONFIG_SF_DEFAULT_SPEED,
+ CONFIG_SF_DEFAULT_MODE);
+ if (!sf) {
+ printf("F-Data:Unable to access SPI NOR flash\n");
+ goto err_free;
+ }
+
+ /* Generate the factory-data struct */
+
+ /* Fist read complete sector into buffer */
+ ret = spi_flash_read(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+ (void *)buf);
+ if (ret) {
+ printf("F-Data:spi_flash_read failed (%d)\n", ret);
+ goto err_spi_flash;
+ }
+
+ fd = (struct factory_data_values *)buf;
+ fd->magic = FACTORY_DATA_MAGIC;
+ fd->version = 0x1;
+
+ /* Use existing MAC and UUID values or generate some random ones */
+ if (!eth_env_get_enetaddr("wifiaddr", fd->wifi_mac)) {
+ net_random_ethaddr(fd->wifi_mac);
+ /* to get a different seed value for the MAC address */
+ mdelay(10);
+ }
+
+ if (!eth_env_get_enetaddr("ethaddr", fd->eth_mac))
+ net_random_ethaddr(fd->eth_mac);
+
+ copy_or_generate_uuid(fd->ipr_id, "linuxmoduleid");
+ copy_or_generate_uuid(fd->hqv_id, "linuxmodulehqvid");
+ copy_or_generate_uuid(fd->unielec_id, "linuxmoduleunielecid");
+
+ printf("New factory-data values:\n");
+ printf("wifiaddr=%pM\n", fd->wifi_mac);
+ printf("ethaddr=%pM\n", fd->eth_mac);
+
+ /*
+ * We don't have the \0 char at the end, so we need to specify the
+ * length in the printf format instead
+ */
+ printf("linuxmoduleid=%." __stringify(UUID_STR_LEN) "s\n", fd->ipr_id);
+ printf("linuxmodulehqvid=%." __stringify(UUID_STR_LEN) "s\n",
+ fd->hqv_id);
+ printf("linuxmoduleunielecid=%." __stringify(UUID_STR_LEN) "s\n",
+ fd->unielec_id);
+
+ fd->crc = crc32(0, (u8 *)&fd->magic, FACTORY_DATA_CRC_LEN);
+
+ ret = spi_flash_erase(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE);
+ if (ret) {
+ printf("F-Data:spi_flash_erase failed (%d)\n", ret);
+ goto err_spi_flash;
+ }
+
+ ret = spi_flash_write(sf, FACTORY_DATA_OFFS, FACTORY_DATA_SECT_SIZE,
+ buf);
+ if (ret) {
+ printf("F-Data:spi_flash_write failed (%d)\n", ret);
+ goto err_spi_flash;
+ }
+
+ printf("F-Data:factory-data values written to SPI NOR flash\n");
+
+err_spi_flash:
+ spi_flash_free(sf);
+
+err_free:
+ free(buf);
+
+ return ret;
+}
+
+U_BOOT_CMD(
+ fd_write, 1, 0, do_fd_write,
+ "Write test factory-data values to SPI NOR",
+ "\n"
+);
diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c
index 824a08f12a..dd4c083fbd 100644
--- a/board/gdsys/a38x/controlcenterdc.c
+++ b/board/gdsys/a38x/controlcenterdc.c
@@ -34,6 +34,19 @@ DECLARE_GLOBAL_DATA_PTR;
#define DB_GP_88F68XX_GPP_POL_LOW 0x0
#define DB_GP_88F68XX_GPP_POL_MID 0x0
+static int get_tpm(struct udevice **devp)
+{
+ int rc;
+
+ rc = uclass_first_device_err(UCLASS_TPM, devp);
+ if (rc) {
+ printf("Could not find TPM (ret=%d)\n", rc);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
/*
* Define the DDR layout / topology here in the board file. This will
* be used by the DDR3 init code in the SPL U-Boot version to configure
@@ -266,18 +279,22 @@ int board_fix_fdt(void *rw_fdt_blob)
int last_stage_init(void)
{
+ struct udevice *tpm;
+ int ret;
+
#ifndef CONFIG_SPL_BUILD
ccdc_eth_init();
#endif
- if (tpm_init() || tpm_startup(TPM_ST_CLEAR) ||
- tpm_continue_self_test()) {
+ ret = get_tpm(&tpm);
+ if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR) ||
+ tpm_continue_self_test(tpm)) {
return 1;
}
mdelay(37);
- flush_keys();
- load_and_run_keyprog();
+ flush_keys(tpm);
+ load_and_run_keyprog(tpm);
return 0;
}
diff --git a/board/gdsys/a38x/hre.c b/board/gdsys/a38x/hre.c
index 34c4df71b2..82b84284ef 100644
--- a/board/gdsys/a38x/hre.c
+++ b/board/gdsys/a38x/hre.c
@@ -93,19 +93,20 @@ static const uint8_t vendor[] = "Guntermann & Drunck";
/**
* @brief get the size of a given (TPM) NV area
+ * @param tpm TPM device
* @param index NV index of the area to get size for
* @param size pointer to the size
* @return 0 on success, != 0 on error
*/
-static int get_tpm_nv_size(uint32_t index, uint32_t *size)
+static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size)
{
uint32_t err;
uint8_t info[72];
uint8_t *ptr;
uint16_t v16;
- err = tpm_get_capability(TPM_CAP_NV_INDEX, index,
- info, sizeof(info));
+ err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
+ info, sizeof(info));
if (err) {
printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
index, err);
@@ -128,13 +129,14 @@ static int get_tpm_nv_size(uint32_t index, uint32_t *size)
/**
* @brief search for a key by usage auth and pub key hash.
+ * @param tpm TPM device
* @param auth usage auth of the key to search for
* @param pubkey_digest (SHA1) hash of the pub key structure of the key
* @param[out] handle the handle of the key iff found
* @return 0 if key was found in TPM; != 0 if not.
*/
-static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
- uint32_t *handle)
+static int find_key(struct udevice *tpm, const uint8_t auth[20],
+ const uint8_t pubkey_digest[20], uint32_t *handle)
{
uint16_t key_count;
uint32_t key_handles[10];
@@ -146,7 +148,8 @@ static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
unsigned int i;
/* fetch list of already loaded keys in the TPM */
- err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+ err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+ sizeof(buf));
if (err)
return -1;
key_count = get_unaligned_be16(buf);
@@ -157,7 +160,8 @@ static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
/* now search a(/ the) key which we can access with the given auth */
for (i = 0; i < key_count; ++i) {
buf_len = sizeof(buf);
- err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+ err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
+ &buf_len);
if (err && err != TPM_AUTHFAIL)
return -1;
if (err)
@@ -173,20 +177,21 @@ static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
/**
* @brief read CCDM common data from TPM NV
+ * @param tpm TPM device
* @return 0 if CCDM common data was found and read, !=0 if something failed.
*/
-static int read_common_data(void)
+static int read_common_data(struct udevice *tpm)
{
uint32_t size = 0;
uint32_t err;
uint8_t buf[256];
sha1_context ctx;
- if (get_tpm_nv_size(NV_COMMON_DATA_INDEX, &size) ||
+ if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
size < NV_COMMON_DATA_MIN_SIZE)
return 1;
- err = tpm_nv_read_value(NV_COMMON_DATA_INDEX,
- buf, min(sizeof(buf), size));
+ err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
+ buf, min(sizeof(buf), size));
if (err) {
printf("tpm_nv_read_value() failed: %u\n", err);
return 1;
@@ -235,6 +240,7 @@ static struct h_reg *get_hreg(uint8_t spec)
/**
* @brief get pointer of a hash register by specification and usage.
+ * @param tpm TPM device
* @param spec specification of a hash register
* @param mode access mode (read or write or read/write)
* @return pointer to hash register if found and valid; NULL else.
@@ -244,7 +250,8 @@ static struct h_reg *get_hreg(uint8_t spec)
* The value of automatic registers (PCR register and fixed registers) is
* loaded or computed on read access.
*/
-static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode)
+static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec,
+ enum access_mode mode)
{
struct h_reg *result;
@@ -261,13 +268,13 @@ static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode)
if (mode & HREG_RD) {
if (!result->valid) {
if (IS_PCR_HREG(spec)) {
- hre_tpm_err = tpm_pcr_read(HREG_IDX(spec),
+ hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
result->digest, 20);
result->valid = (hre_tpm_err == TPM_SUCCESS);
} else if (IS_FIX_HREG(spec)) {
switch (HREG_IDX(spec)) {
case FIX_HREG_DEVICE_ID_HASH:
- read_common_data();
+ read_common_data(tpm);
break;
case FIX_HREG_VENDOR:
memcpy(result->digest, vendor, 20);
@@ -337,18 +344,19 @@ static void *compute_extend(void *_dst, const void *_src, size_t n)
return _dst;
}
-static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg,
- const void *key, size_t key_size)
+static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg,
+ struct h_reg *dst_reg, const void *key,
+ size_t key_size)
{
uint32_t parent_handle;
uint32_t key_handle;
if (!src_reg || !dst_reg || !src_reg->valid || !dst_reg->valid)
return -1;
- if (find_key(src_reg->digest, dst_reg->digest, &parent_handle))
+ if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
return -1;
- hre_tpm_err = tpm_load_key2_oiap(parent_handle, key, key_size,
- src_reg->digest, &key_handle);
+ hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
+ src_reg->digest, &key_handle);
if (hre_tpm_err) {
hre_err = HRE_E_TPM_FAILURE;
return -1;
@@ -359,11 +367,13 @@ static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg,
/**
* @brief executes the next opcode on the hash register engine.
+ * @param tpm TPM device
* @param[in,out] ip pointer to the opcode (instruction pointer)
* @param[in,out] code_size (remaining) size of the code
* @return new instruction pointer on success, NULL on error.
*/
-static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size)
+static const uint8_t *hre_execute_op(struct udevice *tpm, const uint8_t **ip,
+ size_t *code_size)
{
bool dst_modified = false;
uint32_t ins;
@@ -394,10 +404,11 @@ static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size)
if ((opcode & 0x80) && (data_size + 4) > *code_size)
return NULL;
- src_reg = access_hreg(src_spec, HREG_RD);
+ src_reg = access_hreg(tpm, src_spec, HREG_RD);
if (hre_err || hre_tpm_err)
return NULL;
- dst_reg = access_hreg(dst_spec, (opcode & 0x40) ? HREG_RDWR : HREG_WR);
+ dst_reg = access_hreg(tpm, dst_spec,
+ (opcode & 0x40) ? HREG_RDWR : HREG_WR);
if (hre_err || hre_tpm_err)
return NULL;
@@ -453,7 +464,7 @@ do_bin_func:
dst_modified = true;
break;
case HRE_LOADKEY:
- if (hre_op_loadkey(src_reg, dst_reg, data, data_size))
+ if (hre_op_loadkey(tpm, src_reg, dst_reg, data, data_size))
return NULL;
break;
default:
@@ -461,8 +472,8 @@ do_bin_func:
}
if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
- hre_tpm_err = tpm_extend(HREG_IDX(dst_spec), dst_reg->digest,
- dst_reg->digest);
+ hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
+ dst_reg->digest, dst_reg->digest);
if (hre_tpm_err) {
hre_err = HRE_E_TPM_FAILURE;
return NULL;
@@ -481,11 +492,12 @@ end:
/**
* @brief runs a program on the hash register engine.
+ * @param tpm TPM device
* @param code pointer to the (HRE) code.
* @param code_size size of the code (in bytes).
* @return 0 on success, != 0 on failure.
*/
-int hre_run_program(const uint8_t *code, size_t code_size)
+int hre_run_program(struct udevice *tpm, const uint8_t *code, size_t code_size)
{
size_t code_left;
const uint8_t *ip = code;
@@ -494,7 +506,7 @@ int hre_run_program(const uint8_t *code, size_t code_size)
hre_tpm_err = 0;
hre_err = HRE_E_OK;
while (code_left > 0)
- if (!hre_execute_op(&ip, &code_left))
+ if (!hre_execute_op(tpm, &ip, &code_left))
return -1;
return hre_err;
diff --git a/board/gdsys/a38x/hre.h b/board/gdsys/a38x/hre.h
index b562928a64..da983aa452 100644
--- a/board/gdsys/a38x/hre.h
+++ b/board/gdsys/a38x/hre.h
@@ -32,6 +32,6 @@ enum {
};
int hre_verify_program(struct key_program *prg);
-int hre_run_program(const uint8_t *code, size_t code_size);
+int hre_run_program(struct udevice *tpm, const uint8_t *code, size_t code_size);
#endif /* __HRE_H */
diff --git a/board/gdsys/a38x/keyprogram.c b/board/gdsys/a38x/keyprogram.c
index 1fb5306b50..291edc340d 100644
--- a/board/gdsys/a38x/keyprogram.c
+++ b/board/gdsys/a38x/keyprogram.c
@@ -12,7 +12,7 @@
#include "hre.h"
-int flush_keys(void)
+int flush_keys(struct udevice *tpm)
{
u16 key_count;
u8 buf[288];
@@ -21,13 +21,15 @@ int flush_keys(void)
uint i;
/* fetch list of already loaded keys in the TPM */
- err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+ err = tpm_get_capability(tpm, 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);
+ err = tpm_flush_specific(tpm, get_unaligned_be32(ptr),
+ TPM_RT_KEY);
if (err && err != TPM_KEY_OWNER_CONTROL)
return err;
}
@@ -121,7 +123,7 @@ struct key_program *parse_and_check_keyprog(u8 *progdata)
return result;
}
-int load_and_run_keyprog(void)
+int load_and_run_keyprog(struct udevice *tpm)
{
char *cmd = NULL;
u8 *binprog = NULL;
@@ -144,7 +146,7 @@ int load_and_run_keyprog(void)
if (!prog)
return 1;
- if (hre_run_program(prog->code, prog->code_size)) {
+ if (hre_run_program(tpm, prog->code, prog->code_size)) {
free(prog);
return 1;
}
diff --git a/board/gdsys/a38x/keyprogram.h b/board/gdsys/a38x/keyprogram.h
index a4877c73a8..06889c67e4 100644
--- a/board/gdsys/a38x/keyprogram.h
+++ b/board/gdsys/a38x/keyprogram.h
@@ -7,7 +7,7 @@
#ifndef __KEYPROGRAM_H
#define __KEYPROGRAM_H
-int load_and_run_keyprog(void);
-int flush_keys(void);
+int load_and_run_keyprog(struct udevice *tpm);
+int flush_keys(struct udevice *tpm);
#endif /* __KEYPROGRAM_H */
diff --git a/board/gdsys/p1022/controlcenterd-id.c b/board/gdsys/p1022/controlcenterd-id.c
index 7e082dff05..6ac956caca 100644
--- a/board/gdsys/p1022/controlcenterd-id.c
+++ b/board/gdsys/p1022/controlcenterd-id.c
@@ -11,6 +11,7 @@
#endif
#include <common.h>
+#include <dm.h>
#include <malloc.h>
#include <fs.h>
#include <i2c.h>
@@ -141,6 +142,19 @@ static int hre_err = HRE_E_OK;
#define IS_VAR_HREG(spec) (((spec) & 0x38) == 0x10)
#define HREG_IDX(spec) ((spec) & (IS_PCR_HREG(spec) ? 0x1f : 0x7))
+static int get_tpm(struct udevice **devp)
+{
+ int rc;
+
+ rc = uclass_first_device_err(UCLASS_TPM, devp);
+ if (rc) {
+ printf("Could not find TPM (ret=%d)\n", rc);
+ return CMD_RET_FAILURE;
+ }
+
+ return 0;
+}
+
static const uint8_t vendor[] = "Guntermann & Drunck";
/**
@@ -245,15 +259,15 @@ static u8 *get_image_location(void)
* @param size pointer to the size
* @return 0 on success, != 0 on error
*/
-static int get_tpm_nv_size(uint32_t index, uint32_t *size)
+static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size)
{
uint32_t err;
uint8_t info[72];
uint8_t *ptr;
uint16_t v16;
- err = tpm_get_capability(TPM_CAP_NV_INDEX, index,
- info, sizeof(info));
+ err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
+ info, sizeof(info));
if (err) {
printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
index, err);
@@ -281,8 +295,8 @@ static int get_tpm_nv_size(uint32_t index, uint32_t *size)
* @param[out] handle the handle of the key iff found
* @return 0 if key was found in TPM; != 0 if not.
*/
-static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
- uint32_t *handle)
+static int find_key(struct udevice *tpm, const uint8_t auth[20],
+ const uint8_t pubkey_digest[20], uint32_t *handle)
{
uint16_t key_count;
uint32_t key_handles[10];
@@ -294,7 +308,8 @@ static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
unsigned int i;
/* fetch list of already loaded keys in the TPM */
- err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+ err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
+ sizeof(buf));
if (err)
return -1;
key_count = get_unaligned_be16(buf);
@@ -305,7 +320,8 @@ static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
/* now search a(/ the) key which we can access with the given auth */
for (i = 0; i < key_count; ++i) {
buf_len = sizeof(buf);
- err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+ err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
+ &buf_len);
if (err && err != TPM_AUTHFAIL)
return -1;
if (err)
@@ -323,18 +339,18 @@ static int find_key(const uint8_t auth[20], const uint8_t pubkey_digest[20],
* @brief read CCDM common data from TPM NV
* @return 0 if CCDM common data was found and read, !=0 if something failed.
*/
-static int read_common_data(void)
+static int read_common_data(struct udevice *tpm)
{
uint32_t size;
uint32_t err;
uint8_t buf[256];
sha1_context ctx;
- if (get_tpm_nv_size(NV_COMMON_DATA_INDEX, &size) ||
+ if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
size < NV_COMMON_DATA_MIN_SIZE)
return 1;
- err = tpm_nv_read_value(NV_COMMON_DATA_INDEX,
- buf, min(sizeof(buf), size));
+ err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
+ buf, min(sizeof(buf), size));
if (err) {
printf("tpm_nv_read_value() failed: %u\n", err);
return 1;
@@ -467,7 +483,8 @@ static struct h_reg *get_hreg(uint8_t spec)
* The value of automatic registers (PCR register and fixed registers) is
* loaded or computed on read access.
*/
-static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode)
+static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec,
+ enum access_mode mode)
{
struct h_reg *result;
@@ -484,13 +501,13 @@ static struct h_reg *access_hreg(uint8_t spec, enum access_mode mode)
if (mode & HREG_RD) {
if (!result->valid) {
if (IS_PCR_HREG(spec)) {
- hre_tpm_err = tpm_pcr_read(HREG_IDX(spec),
+ hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
result->digest, 20);
result->valid = (hre_tpm_err == TPM_SUCCESS);
} else if (IS_FIX_HREG(spec)) {
switch (HREG_IDX(spec)) {
case FIX_HREG_DEVICE_ID_HASH:
- read_common_data();
+ read_common_data(tpm);
break;
case FIX_HREG_SELF_HASH:
ccdm_compute_self_hash();
@@ -566,18 +583,19 @@ static void *compute_extend(void *_dst, const void *_src, size_t n)
return _dst;
}
-static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg,
- const void *key, size_t key_size)
+static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg,
+ struct h_reg *dst_reg, const void *key,
+ size_t key_size)
{
uint32_t parent_handle;
uint32_t key_handle;
if (!src_reg || !dst_reg || !src_reg->valid || !dst_reg->valid)
return -1;
- if (find_key(src_reg->digest, dst_reg->digest, &parent_handle))
+ if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
return -1;
- hre_tpm_err = tpm_load_key2_oiap(parent_handle, key, key_size,
- src_reg->digest, &key_handle);
+ hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
+ src_reg->digest, &key_handle);
if (hre_tpm_err) {
hre_err = HRE_E_TPM_FAILURE;
return -1;
@@ -593,7 +611,8 @@ static int hre_op_loadkey(struct h_reg *src_reg, struct h_reg *dst_reg,
* @param[in,out] code_size (remaining) size of the code
* @return new instruction pointer on success, NULL on error.
*/
-static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size)
+static const uint8_t *hre_execute_op(struct udevice *tpm, const uint8_t **ip,
+ size_t *code_size)
{
bool dst_modified = false;
uint32_t ins;
@@ -624,10 +643,11 @@ static const uint8_t *hre_execute_op(const uint8_t **ip, size_t *code_size)
if ((opcode & 0x80) && (data_size + 4) > *code_size)
return NULL;
- src_reg = access_hreg(src_spec, HREG_RD);
+ src_reg = access_hreg(tpm, src_spec, HREG_RD);
if (hre_err || hre_tpm_err)
return NULL;
- dst_reg = access_hreg(dst_spec, (opcode & 0x40) ? HREG_RDWR : HREG_WR);
+ dst_reg = access_hreg(tpm, dst_spec,
+ (opcode & 0x40) ? HREG_RDWR : HREG_WR);
if (hre_err || hre_tpm_err)
return NULL;
@@ -683,7 +703,7 @@ do_bin_func:
dst_modified = true;
break;
case HRE_LOADKEY:
- if (hre_op_loadkey(src_reg, dst_reg, data, data_size))
+ if (hre_op_loadkey(tpm, src_reg, dst_reg, data, data_size))
return NULL;
break;
default:
@@ -691,8 +711,8 @@ do_bin_func:
}
if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
- hre_tpm_err = tpm_extend(HREG_IDX(dst_spec), dst_reg->digest,
- dst_reg->digest);
+ hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
+ dst_reg->digest, dst_reg->digest);
if (hre_tpm_err) {
hre_err = HRE_E_TPM_FAILURE;
return NULL;
@@ -715,7 +735,8 @@ end:
* @param code_size size of the code (in bytes).
* @return 0 on success, != 0 on failure.
*/
-static int hre_run_program(const uint8_t *code, size_t code_size)
+static int hre_run_program(struct udevice *tpm, const uint8_t *code,
+ size_t code_size)
{
size_t code_left;
const uint8_t *ip = code;
@@ -724,7 +745,7 @@ static int hre_run_program(const uint8_t *code, size_t code_size)
hre_tpm_err = 0;
hre_err = HRE_E_OK;
while (code_left > 0)
- if (!hre_execute_op(&ip, &code_left))
+ if (!hre_execute_op(tpm, &ip, &code_left))
return -1;
return hre_err;
@@ -929,26 +950,27 @@ static const uint8_t prg_stage1_prepare[] = {
0x81, 0x2e, 0x30, 0x00, /* opcode: LOAD PCR3, f3 */
};
-static int first_stage_actions(void)
+static int first_stage_actions(struct udevice *tpm)
{
int result = 0;
struct key_program *sd_prg = NULL;
puts("CCDM S1: start actions\n");
#ifndef CCDM_SECOND_STAGE
- if (tpm_continue_self_test())
+ if (tpm_continue_self_test(tpm))
goto failure;
#else
- tpm_continue_self_test();
+ tpm_continue_self_test(tpm);
#endif
mdelay(37);
- if (hre_run_program(prg_stage1_prepare, sizeof(prg_stage1_prepare)))
+ if (hre_run_program(tpm, prg_stage1_prepare,
+ sizeof(prg_stage1_prepare)))
goto failure;
sd_prg = load_sd_key_program();
if (sd_prg) {
- if (hre_run_program(sd_prg->code, sd_prg->code_size))
+ if (hre_run_program(tpm, sd_prg->code, sd_prg->code_size))
goto failure;
puts("SD code run successfully\n");
} else {
@@ -969,19 +991,22 @@ end:
#ifdef CCDM_FIRST_STAGE
static int first_stage_init(void)
{
- int res = 0;
+ struct udevice *tpm;
+ int ret;
+
puts("CCDM S1\n");
- if (tpm_init() || tpm_startup(TPM_ST_CLEAR))
+ ret = get_tpm(&tpm);
+ if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR))
return 1;
- res = first_stage_actions();
+ ret = first_stage_actions(tpm);
#ifndef CCDM_SECOND_STAGE
- if (!res) {
+ if (!ret) {
if (bl2_entry)
(*bl2_entry)();
- res = 1;
+ ret = 1;
}
#endif
- return res;
+ return ret;
}
#endif
@@ -1021,24 +1046,28 @@ static int second_stage_init(void)
char *mac_path = NULL;
ulong image_addr;
loff_t image_size;
+ struct udevice *tpm;
uint32_t err;
+ int ret;
printf("CCDM S2\n");
- if (tpm_init())
+ ret = get_tpm(&tpm);
+ if (ret || tpm_init(tpm))
return 1;
- err = tpm_startup(TPM_ST_CLEAR);
+ err = tpm_startup(tpm, TPM_ST_CLEAR);
if (err != TPM_INVALID_POSTINIT)
did_first_stage_run = false;
#ifdef CCDM_AUTO_FIRST_STAGE
- if (!did_first_stage_run && first_stage_actions())
+ if (!did_first_stage_run && first_stage_actions(tpm))
goto failure;
#else
if (!did_first_stage_run)
goto failure;
#endif
- if (hre_run_program(prg_stage2_prepare, sizeof(prg_stage2_prepare)))
+ if (hre_run_program(tpm, prg_stage2_prepare,
+ sizeof(prg_stage2_prepare)))
goto failure;
/* run "prepboot" from env to get "mmcdev" set */
@@ -1083,12 +1112,12 @@ static int second_stage_init(void)
}
puts("CCDM image OK\n");
- hre_run_program(prg_stage2_success, sizeof(prg_stage2_success));
+ hre_run_program(tpm, prg_stage2_success, sizeof(prg_stage2_success));
goto end;
failure:
result = 1;
- hre_run_program(prg_stage_fail, sizeof(prg_stage_fail));
+ hre_run_program(tpm, prg_stage_fail, sizeof(prg_stage_fail));
end:
if (hmac_blob)
free(hmac_blob);