u-boot/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
Patrick Delaunay d68e53b279 stm32mp: stm32prog: add support of initrd in flashlayout
Add the support in command stm32prog of kernel load and start
with initrd file, identify by the partition Type "Binary" in
the flashlayout.tsv, for example:

- 0x01 fsbl	Binary none 0x0 tfa.stm32
- 0x03 fip	Binary none 0x0 fip.bin
P 0x10 kernel System ram0 0xC2000000 uImage.bin
P 0x11 dtb FileSystem ram0 0xC4000000 board.dtb
P 0x12 initrd Binary ram0 0xC4400000 <initrd>

The <initrd> file can be a legacy image "uInitrd", generated
with mkimage, or a RAW initrd image "initrd.gz".

After a DFU detach the bootm command with be executed
with the associated address, for example:

$> bootm 0xC2000000 0xC4400000:<size> 0xC4000000

When the "Binary" partition type is absent, the 'bootm'
command starts the kernel without ramdisk, for example:

$> bootm 0xC2000000 - 0xC4000000

With this paths, it is no more mandatory to generate FIT
including the kernel, DT and initrd:

- 0x01 fsbl Binary none 0x0 tfa.stm32
- 0x03 fip Binary none 0x0 fip.bin
P 0x10 fit System ram0 0xC2000000 fit.bin

Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
2021-06-18 10:09:41 +02:00

201 lines
4.5 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)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);
if (header.type == HEADER_STM32IMAGE) {
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 image_source_script(addr + BL_HEADER_SIZE, "script@1");
}
}
if (IS_ENABLED(CONFIG_DM_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)
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;
}
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
};
u32 uimage = data->uimage;
u32 dtb = data->dtb;
u32 initrd = data->initrd;
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);
if (initrd) {
snprintf(initrd_addr, sizeof(initrd_addr) - 1, "0x%x:0x%x",
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((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;
}