Files
uboot-st/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
Patrick Delaunay 6bf602057b stm32mp: stm32prog: add support of RAM target
Add support of RAM target in flashlayout to load kernel image
("system") and device tree ("filesystem") in DDR with DFU and
start these images.

The flashlayout.tsv is:

-	0x01	fsbl		Binary		none	0x00000000	tf-a.stm32
-	0x03	ssbl		Binary		none	0x00000000	u-boot.stm32
P	0x10	kernel		System		ram0	0xC2000000	uImage.bin
P	0x11	dtb		FileSystem	ram0	0xC4000000	dtb.bin

Cover-letter:
stm32mp1: add command stm32prog

Add a specific command stm32prog for STM32MP soc family
witch allows to update the devices on the board with the
STMicroelectronics tool STM32CubeProgrammer
(http://www.st.com/STM32CubeProg).

This command use the same UART STM32 protocol than MCU STM32
with or USB with DFU protocol v1.1 (MCU ST extension are no supported).

The executed actions are based on a tab separated value file
with a stm32 header (see
https://wiki.st.com/stm32mpu/wiki/STM32CubeProgrammer_flashlayout).

This FlashLayout file is loaded in DDR by TF-A during during a
serial boot or in a virtual device by stm32prog command
and is parsed by U-Boot (see "AN5275: USB DFU/USART protocols used
in STM32MP1 Series bootloaders" for details).

Regards
Patrick

END

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
2020-04-09 15:40:59 +02:00

192 lines
4.1 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)
{
#ifdef CONFIG_DM_VIDEO
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);
}
#endif
}
static int do_stm32prog(cmd_tbl_t *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;
u32 uimage, dtb;
if (argc < 3 || argc > 5)
return CMD_RET_USAGE;
if (!strcmp(argv[1], "usb"))
link = LINK_USB;
else if (!strcmp(argv[1], "serial"))
link = LINK_SERIAL;
if (link == LINK_UNDEFINED) {
pr_err("not supported link=%s\n", argv[1]);
return CMD_RET_USAGE;
}
dev = (int)simple_strtoul(argv[2], NULL, 10);
addr = STM32_DDR_BASE;
size = 0;
if (argc > 3) {
addr = simple_strtoul(argv[3], NULL, 16);
if (!addr)
return CMD_RET_FAILURE;
}
if (argc > 4)
size = simple_strtoul(argv[4], NULL, 16);
/* check STM32IMAGE presence */
if (size == 0 &&
!stm32prog_header_check((struct raw_header_s *)addr, &header)) {
size = header.image_length + BL_HEADER_SIZE;
/* uImage detected in STM32IMAGE, execute the script */
if (IMAGE_FORMAT_LEGACY ==
genimg_get_format((void *)(addr + BL_HEADER_SIZE)))
return source(addr + BL_HEADER_SIZE, "script@1");
}
enable_vidconsole();
data = (struct stm32prog_data *)malloc(sizeof(*data));
if (!data) {
pr_err("Alloc failed.");
return CMD_RET_FAILURE;
}
stm32prog_data = data;
ret = stm32prog_init(data, addr, size);
if (ret)
printf("Invalid or missing layout file.");
/* 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;
}
uimage = data->uimage;
dtb = data->dtb;
stm32prog_clean(data);
free(stm32prog_data);
stm32prog_data = NULL;
puts("Download done\n");
if (uimage) {
char boot_addr_start[20];
char dtb_addr[20];
char *bootm_argv[5] = {
"bootm", boot_addr_start, "-", dtb_addr, NULL
};
if (!dtb)
bootm_argv[3] = env_get("fdtcontroladdr");
else
snprintf(dtb_addr, sizeof(dtb_addr) - 1,
"0x%x", dtb);
snprintf(boot_addr_start, sizeof(boot_addr_start) - 1,
"0x%x", uimage);
printf("Booting kernel at %s - %s...\n\n\n",
boot_addr_start, bootm_argv[3]);
/* Try bootm for legacy and FIT format image */
if (genimg_get_format((void *)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 (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,
"<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"
);
bool stm32prog_get_tee_partitions(void)
{
if (stm32prog_data)
return stm32prog_data->tee_detected;
return false;
}
bool stm32prog_get_fsbl_nor(void)
{
if (stm32prog_data)
return stm32prog_data->fsbl_nor_detected;
return false;
}