u-boot/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
Sean Anderson bcc85b96b5 cmd: source: Support specifying config name
As discussed previously [1,2], the source command is not safe to use with
verified boot unless there is a key with required = "images" (which has its
own problems). This is because if such a key is absent, signatures are
verified but not required. It is assumed that configuration nodes will
provide the signature. Because the source command does not use
configurations to determine the image to source, effectively no
verification takes place.

To address this, allow specifying configuration nodes. We use the same
syntax as the bootm command (helpfully provided for us by fit_parse_conf).
By default, we first try the default config and then the default image. To
force using a config, # must be present in the command (e.g. `source
$loadaddr#my-conf`). For convenience, the config may be omitted, just like
the address may be (e.g. `source \#`). This also works for images
(`source :` behaves exactly like `source` currently does).

[1] https://lore.kernel.org/u-boot/7d711133-d513-5bcb-52f2-a9dbaa9eeded@prevas.dk/
[2] https://lore.kernel.org/u-boot/042dcb34-f85f-351e-1b0e-513f89005fdd@gmail.com/

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
2022-12-31 13:35:19 -05:00

199 lines
4.4 KiB
C

// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2020, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <command.h>
#include <dfu.h>
#include <image.h>
#include <asm/arch/stm32prog.h>
#include "stm32prog.h"
struct stm32prog_data *stm32prog_data;
static void enable_vidconsole(void)
{
char *stdname;
char buf[64];
stdname = env_get("stdout");
if (!stdname || !strstr(stdname, "vidconsole")) {
if (!stdname)
snprintf(buf, sizeof(buf), "serial,vidconsole");
else
snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
env_set("stdout", buf);
}
stdname = env_get("stderr");
if (!stdname || !strstr(stdname, "vidconsole")) {
if (!stdname)
snprintf(buf, sizeof(buf), "serial,vidconsole");
else
snprintf(buf, sizeof(buf), "%s,vidconsole", stdname);
env_set("stderr", buf);
}
}
static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
char * const argv[])
{
ulong addr, size;
int dev, ret;
enum stm32prog_link_t link = LINK_UNDEFINED;
bool reset = false;
struct image_header_s header;
struct stm32prog_data *data;
if (argc < 3 || argc > 5)
return CMD_RET_USAGE;
if (IS_ENABLED(CONFIG_CMD_STM32PROG_USB) && !strcmp(argv[1], "usb"))
link = LINK_USB;
else if (IS_ENABLED(CONFIG_CMD_STM32PROG_SERIAL) && !strcmp(argv[1], "serial"))
link = LINK_SERIAL;
if (link == LINK_UNDEFINED) {
log_err("not supported link=%s\n", argv[1]);
return CMD_RET_USAGE;
}
dev = (int)dectoul(argv[2], NULL);
addr = CONFIG_SYS_LOAD_ADDR;
size = 0;
if (argc > 3) {
addr = hextoul(argv[3], NULL);
if (!addr)
return CMD_RET_FAILURE;
}
if (argc > 4)
size = hextoul(argv[4], NULL);
/* check STM32IMAGE presence */
if (size == 0) {
stm32prog_header_check(addr, &header);
if (header.type == HEADER_STM32IMAGE) {
size = header.image_length + header.length;
}
}
if (IS_ENABLED(CONFIG_VIDEO))
enable_vidconsole();
data = (struct stm32prog_data *)malloc(sizeof(*data));
if (!data) {
log_err("Alloc failed.");
return CMD_RET_FAILURE;
}
stm32prog_data = data;
ret = stm32prog_init(data, addr, size);
if (ret)
log_debug("Invalid or missing layout file at 0x%lx.\n", addr);
/* prepare DFU for device read/write */
ret = stm32prog_dfu_init(data);
if (ret)
goto cleanup;
switch (link) {
case LINK_SERIAL:
ret = stm32prog_serial_init(data, dev);
if (ret)
goto cleanup;
reset = stm32prog_serial_loop(data);
break;
case LINK_USB:
reset = stm32prog_usb_loop(data, dev);
break;
default:
goto cleanup;
}
stm32prog_clean(data);
free(stm32prog_data);
stm32prog_data = NULL;
puts("Download done\n");
if (data->uimage) {
char boot_addr_start[20];
char dtb_addr[20];
char initrd_addr[40];
char *bootm_argv[5] = {
"bootm", boot_addr_start, "-", dtb_addr, NULL
};
const void *uimage = (void *)data->uimage;
const void *dtb = (void *)data->dtb;
const void *initrd = (void *)data->initrd;
if (!dtb)
bootm_argv[3] = env_get("fdtcontroladdr");
else
snprintf(dtb_addr, sizeof(dtb_addr) - 1,
"0x%p", dtb);
snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
"0x%p", uimage);
if (initrd) {
snprintf(initrd_addr, sizeof(initrd_addr) - 1, "0x%p:0x%zx",
initrd, data->initrd_size);
bootm_argv[2] = initrd_addr;
}
printf("Booting kernel at %s %s %s...\n\n\n",
boot_addr_start, bootm_argv[2], bootm_argv[3]);
/* Try bootm for legacy and FIT format image */
if (genimg_get_format(uimage) != IMAGE_FORMAT_INVALID)
do_bootm(cmdtp, 0, 4, bootm_argv);
else if (CONFIG_IS_ENABLED(CMD_BOOTZ))
do_bootz(cmdtp, 0, 4, bootm_argv);
}
if (data->script)
image_source_script(data->script, NULL, NULL);
if (reset) {
puts("Reset...\n");
run_command("reset", 0);
}
return CMD_RET_SUCCESS;
cleanup:
stm32prog_clean(data);
free(stm32prog_data);
stm32prog_data = NULL;
return CMD_RET_FAILURE;
}
U_BOOT_CMD(stm32prog, 5, 0, do_stm32prog,
"start communication with tools STM32Cubeprogrammer",
"<link> <dev> [<addr>] [<size>]\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"
);
#ifdef CONFIG_STM32MP15x_STM32IMAGE
bool stm32prog_get_tee_partitions(void)
{
if (stm32prog_data)
return stm32prog_data->tee_detected;
return false;
}
#endif
bool stm32prog_get_fsbl_nor(void)
{
if (stm32prog_data)
return stm32prog_data->fsbl_nor_detected;
return false;
}