diff options
Diffstat (limited to 'arch/arm/mach-stm32mp')
-rw-r--r-- | arch/arm/mach-stm32mp/Kconfig | 4 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32key.c | 239 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/cpu.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/include/mach/stm32.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-stm32mp/syscon.c | 14 |
9 files changed, 249 insertions, 47 deletions
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig index 7c25266f33..0e59931679 100644 --- a/arch/arm/mach-stm32mp/Kconfig +++ b/arch/arm/mach-stm32mp/Kconfig @@ -174,10 +174,12 @@ config STM32_ETZPC config CMD_STM32KEY bool "command stm32key to fuse public key hash" - default y + default n help fuse public key hash in corresponding fuse used to authenticate binary. + This command is used to evaluate the secure boot on stm32mp SOC, + it is deactivated by default in real products. config PRE_CON_BUF_ADDR default 0xC02FF000 diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c index 42fdc11238..50840b0f38 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32key.c +++ b/arch/arm/mach-stm32mp/cmd_stm32key.c @@ -11,13 +11,30 @@ #include <dm/device.h> #include <dm/uclass.h> -#define STM32_OTP_HASH_KEY_START 24 -#define STM32_OTP_HASH_KEY_SIZE 8 +/* Closed device : bit 6 of OPT0*/ +#define STM32_OTP_CLOSE_ID 0 +#define STM32_OTP_CLOSE_MASK BIT(6) + +/* HASH of key: 8 OTPs, starting with OTP24) */ +#define STM32_OTP_HASH_KEY_START 24 +#define STM32_OTP_HASH_KEY_SIZE 8 + +static int get_misc_dev(struct udevice **dev) +{ + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(stm32mp_bsec), dev); + if (ret) + log_err("Can't find stm32mp_bsec driver\n"); + + return ret; +} static void read_hash_value(u32 addr) { int i; + printf("Read KEY at 0x%x\n", addr); for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) { printf("OTP value %i: %x\n", STM32_OTP_HASH_KEY_START + i, __be32_to_cpu(*(u32 *)addr)); @@ -25,32 +42,101 @@ static void read_hash_value(u32 addr) } } -static void fuse_hash_value(u32 addr, bool print) +static int read_hash_otp(bool print, bool *locked, bool *closed) { struct udevice *dev; - u32 word, val; - int i, ret; + int i, word, ret; + int nb_invalid = 0, nb_zero = 0, nb_lock = 0; + u32 val, lock; + bool status; - ret = uclass_get_device_by_driver(UCLASS_MISC, - DM_DRIVER_GET(stm32mp_bsec), - &dev); - if (ret) { - log_err("Can't find stm32mp_bsec driver\n"); - return; + ret = get_misc_dev(&dev); + if (ret) + return ret; + + for (i = 0, word = STM32_OTP_HASH_KEY_START; i < STM32_OTP_HASH_KEY_SIZE; i++, word++) { + ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); + if (ret != 4) + val = ~0x0; + ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); + if (ret != 4) + lock = -1; + if (print) + printf("OTP HASH %i: %x lock : %d\n", word, val, lock); + if (val == ~0x0) + nb_invalid++; + else if (val == 0x0) + nb_zero++; + if (lock == 1) + nb_lock++; } - for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) { + word = STM32_OTP_CLOSE_ID; + ret = misc_read(dev, STM32_BSEC_OTP(word), &val, 4); + if (ret != 4) + val = 0x0; + ret = misc_read(dev, STM32_BSEC_LOCK(word), &lock, 4); + if (ret != 4) + lock = -1; + + status = (val & STM32_OTP_CLOSE_MASK) == STM32_OTP_CLOSE_MASK; + if (closed) + *closed = status; + if (print) + printf("OTP %d: closed status: %d lock : %d\n", word, status, lock); + + status = (nb_lock == STM32_OTP_HASH_KEY_SIZE); + if (locked) + *locked = status; + if (!status && print) + printf("Hash of key is not locked!\n"); + + if (nb_invalid == STM32_OTP_HASH_KEY_SIZE) { if (print) - printf("Fuse OTP %i : %x\n", - STM32_OTP_HASH_KEY_START + i, - __be32_to_cpu(*(u32 *)addr)); + printf("Hash of key is invalid!\n"); + return -EINVAL; + } + if (nb_zero == STM32_OTP_HASH_KEY_SIZE) { + if (print) + printf("Hash of key is free!\n"); + return -ENOENT; + } + + return 0; +} - word = STM32_OTP_HASH_KEY_START + i; +static int fuse_hash_value(u32 addr, bool print) +{ + struct udevice *dev; + u32 word, val; + int i, ret; + + ret = get_misc_dev(&dev); + if (ret) + return ret; + + for (i = 0, word = STM32_OTP_HASH_KEY_START; + i < STM32_OTP_HASH_KEY_SIZE; + i++, word++, addr += 4) { val = __be32_to_cpu(*(u32 *)addr); - misc_write(dev, STM32_BSEC_OTP(word), &val, 4); + if (print) + printf("Fuse OTP %i : %x\n", word, val); - addr += 4; + ret = misc_write(dev, STM32_BSEC_OTP(word), &val, 4); + if (ret != 4) { + log_err("Fuse OTP %i failed\n", word); + return ret; + } + /* on success, lock the OTP for HASH key */ + val = 1; + ret = misc_write(dev, STM32_BSEC_LOCK(word), &val, 4); + if (ret != 4) { + log_err("Lock OTP %i failed\n", word); + return ret; + } } + + return 0; } static int confirm_prog(void) @@ -67,36 +153,117 @@ static int confirm_prog(void) return 0; } -static int do_stm32key(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +static int do_stm32key_read(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { u32 addr; - const char *op = argc >= 2 ? argv[1] : NULL; - int confirmed = argc > 3 && !strcmp(argv[2], "-y"); - argc -= 2 + confirmed; - argv += 2 + confirmed; + if (argc == 1) { + read_hash_otp(true, NULL, NULL); + return CMD_RET_SUCCESS; + } + + addr = simple_strtoul(argv[1], NULL, 16); + if (!addr) + return CMD_RET_USAGE; + + read_hash_value(addr); + + return CMD_RET_SUCCESS; +} + +static int do_stm32key_fuse(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + u32 addr; + bool yes = false, lock, closed; - if (argc < 1) + if (argc < 2) return CMD_RET_USAGE; - addr = simple_strtoul(argv[0], NULL, 16); + if (argc == 3) { + if (strcmp(argv[1], "-y")) + return CMD_RET_USAGE; + yes = true; + } + + addr = simple_strtoul(argv[argc - 1], NULL, 16); if (!addr) return CMD_RET_USAGE; - if (!strcmp(op, "read")) - read_hash_value(addr); + if (read_hash_otp(!yes, &lock, &closed) != -ENOENT) { + printf("Error: can't fuse again the OTP\n"); + return CMD_RET_FAILURE; + } - if (!strcmp(op, "fuse")) { - if (!confirmed && !confirm_prog()) - return CMD_RET_FAILURE; - fuse_hash_value(addr, !confirmed); + if (lock || closed) { + printf("Error: invalid OTP configuration (lock=%d, closed=%d)\n", lock, closed); + return CMD_RET_FAILURE; } + if (!yes && !confirm_prog()) + return CMD_RET_FAILURE; + + if (fuse_hash_value(addr, !yes)) + return CMD_RET_FAILURE; + + printf("Hash key updated !\n"); + return CMD_RET_SUCCESS; } -U_BOOT_CMD(stm32key, 4, 1, do_stm32key, - "Fuse ST Hash key", - "read <addr>: Read the hash store at addr in memory\n" - "stm32key fuse [-y] <addr> : Fuse hash store at addr in otp\n"); +static int do_stm32key_close(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + bool yes, lock, closed; + struct udevice *dev; + u32 val; + int ret; + + yes = false; + if (argc == 2) { + if (strcmp(argv[1], "-y")) + return CMD_RET_USAGE; + yes = true; + } + + ret = read_hash_otp(!yes, &lock, &closed); + if (ret) { + if (ret == -ENOENT) + printf("Error: OTP not programmed!\n"); + return CMD_RET_FAILURE; + } + + if (closed) { + printf("Error: already closed!\n"); + return CMD_RET_FAILURE; + } + + if (!lock) + printf("Warning: OTP not locked!\n"); + + if (!yes && !confirm_prog()) + return CMD_RET_FAILURE; + + ret = get_misc_dev(&dev); + if (ret) + return CMD_RET_FAILURE; + + val = STM32_OTP_CLOSE_MASK; + ret = misc_write(dev, STM32_BSEC_OTP(STM32_OTP_CLOSE_ID), &val, 4); + if (ret != 4) { + printf("Error: can't update OTP\n"); + return CMD_RET_FAILURE; + } + + printf("Device is closed !\n"); + + return CMD_RET_SUCCESS; +} + +static char stm32key_help_text[] = + "read [<addr>]: Read the hash stored at addr in memory or in OTP\n" + "stm32key fuse [-y] <addr> : Fuse hash stored at addr in OTP\n" + "stm32key close [-y] : Close the device, the hash stored in OTP\n"; + +U_BOOT_CMD_WITH_SUBCMDS(stm32key, "Fuse ST Hash key", stm32key_help_text, + U_BOOT_SUBCMD_MKENT(read, 2, 0, do_stm32key_read), + U_BOOT_SUBCMD_MKENT(fuse, 3, 0, do_stm32key_fuse), + U_BOOT_SUBCMD_MKENT(close, 2, 0, do_stm32key_close)); diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c index feff73c79e..064f51b2c7 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c @@ -177,12 +177,12 @@ cleanup: } U_BOOT_CMD(stm32prog, 5, 0, do_stm32prog, + "start communication with tools STM32Cubeprogrammer", "<link> <dev> [<addr>] [<size>]\n" - "start communication with tools STM32Cubeprogrammer on <link> with Flashlayout at <addr>", - "<link> = serial|usb\n" - "<dev> = device instance\n" - "<addr> = address of flashlayout\n" - "<size> = size of flashlayout\n" + " <link> = serial|usb\n" + " <dev> = device instance\n" + " <addr> = address of flashlayout\n" + " <size> = size of flashlayout (optional for image with STM32 header)\n" ); bool stm32prog_get_tee_partitions(void) diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c index f7c93a1298..96ebc6d978 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c @@ -1199,13 +1199,13 @@ static int dfu_init_entities(struct stm32prog_data *data) } if (!ret) - ret = stm32prog_alt_add_virt(dfu, "virtual", PHASE_CMD, 512); + ret = stm32prog_alt_add_virt(dfu, "virtual", PHASE_CMD, CMD_SIZE); if (!ret) - ret = stm32prog_alt_add_virt(dfu, "OTP", PHASE_OTP, 512); + ret = stm32prog_alt_add_virt(dfu, "OTP", PHASE_OTP, OTP_SIZE); if (!ret && CONFIG_IS_ENABLED(DM_PMIC)) - ret = stm32prog_alt_add_virt(dfu, "PMIC", PHASE_PMIC, 8); + ret = stm32prog_alt_add_virt(dfu, "PMIC", PHASE_PMIC, PMIC_SIZE); if (ret) stm32prog_err("dfu init failed: %d", ret); diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h index efb51a3022..9d58cf0e2d 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.h @@ -19,6 +19,7 @@ #define DEFAULT_ADDRESS 0xFFFFFFFF +#define CMD_SIZE 512 #define OTP_SIZE 1024 #define PMIC_SIZE 8 diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c index d4a3f7ea16..e8acc302f9 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog_usb.c @@ -178,7 +178,7 @@ int stm32prog_get_medium_size_virt(struct dfu_entity *dfu, u64 *size) switch (dfu->data.virt.dev_num) { case PHASE_CMD: - *size = 512; + *size = CMD_SIZE; break; case PHASE_OTP: *size = OTP_SIZE; diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index 592bfd413d..f6ed2ce0e4 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -483,6 +483,11 @@ static void setup_boot_mode(void) STM32_UART7_BASE, STM32_UART8_BASE }; + const u32 sdmmc_addr[] = { + STM32_SDMMC1_BASE, + STM32_SDMMC2_BASE, + STM32_SDMMC3_BASE + }; char cmd[60]; u32 boot_ctx = readl(TAMP_BOOT_CONTEXT); u32 boot_mode = @@ -525,7 +530,16 @@ static void setup_boot_mode(void) break; case BOOT_FLASH_SD: case BOOT_FLASH_EMMC: - sprintf(cmd, "%d", instance); + if (instance > ARRAY_SIZE(sdmmc_addr)) + break; + /* search associated sdmmc node in devicetree */ + sprintf(cmd, "mmc@%x", sdmmc_addr[instance]); + if (uclass_get_device_by_name(UCLASS_MMC, cmd, &dev)) { + printf("mmc%d = %s not found in device tree!\n", + instance, cmd); + break; + } + sprintf(cmd, "%d", dev_seq(dev)); env_set("boot_device", "mmc"); env_set("boot_instance", cmd); break; diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index 5fdb893b0e..c11a9903f2 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -32,6 +32,10 @@ #define STM32_UART7_BASE 0x40018000 #define STM32_UART8_BASE 0x40019000 +#define STM32_SDMMC1_BASE 0x58005000 +#define STM32_SDMMC2_BASE 0x58007000 +#define STM32_SDMMC3_BASE 0x48004000 + #define STM32_SYSRAM_BASE 0x2FFC0000 #define STM32_SYSRAM_SIZE SZ_256K diff --git a/arch/arm/mach-stm32mp/syscon.c b/arch/arm/mach-stm32mp/syscon.c index 3e61ce4097..a0e8e1dfdc 100644 --- a/arch/arm/mach-stm32mp/syscon.c +++ b/arch/arm/mach-stm32mp/syscon.c @@ -4,6 +4,7 @@ */ #include <common.h> +#include <clk.h> #include <dm.h> #include <syscon.h> #include <asm/arch/stm32.h> @@ -14,9 +15,22 @@ static const struct udevice_id stm32mp_syscon_ids[] = { { } }; +static int stm32mp_syscon_probe(struct udevice *dev) +{ + struct clk_bulk clk_bulk; + int ret; + + ret = clk_get_bulk(dev, &clk_bulk); + if (!ret) + clk_enable_bulk(&clk_bulk); + + return 0; +} + U_BOOT_DRIVER(syscon_stm32mp) = { .name = "stmp32mp_syscon", .id = UCLASS_SYSCON, .of_match = stm32mp_syscon_ids, .bind = dm_scan_fdt_dev, + .probe = stm32mp_syscon_probe, }; |