diff options
Diffstat (limited to 'board')
-rw-r--r-- | board/gardena/smart-gateway-mt7688/board.c | 269 | ||||
-rw-r--r-- | board/gdsys/a38x/controlcenterdc.c | 25 | ||||
-rw-r--r-- | board/gdsys/a38x/hre.c | 66 | ||||
-rw-r--r-- | board/gdsys/a38x/hre.h | 2 | ||||
-rw-r--r-- | board/gdsys/a38x/keyprogram.c | 12 | ||||
-rw-r--r-- | board/gdsys/a38x/keyprogram.h | 4 | ||||
-rw-r--r-- | board/gdsys/p1022/controlcenterd-id.c | 117 |
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); |