stm32mp: stm32prog: add FIP header support

Add support of TF-A FIP header in command stm32prog for all the boot
partition and not only the STM32IMAGE.

This patch is a preliminary patch to support FIP as second boot stage
after TF-A BL2 when CONFIG_TFABOOT is activated for trusted boot chain.

The FIP is archive binary loaded by TF-A BL2, which contains the secure OS
= OP-TEE and the non secure firmware and device tree = U-Boot.

Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
This commit is contained in:
Patrick Delaunay 2021-04-02 14:05:17 +02:00 committed by Patrice Chotard
parent 0441b48570
commit 4fb7b3e108
4 changed files with 63 additions and 36 deletions

View File

@ -73,15 +73,16 @@ static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc,
size = simple_strtoul(argv[4], NULL, 16); size = simple_strtoul(argv[4], NULL, 16);
/* check STM32IMAGE presence */ /* check STM32IMAGE presence */
if (size == 0 && if (size == 0) {
!stm32prog_header_check((struct raw_header_s *)addr, &header)) { stm32prog_header_check((struct raw_header_s *)addr, &header);
size = header.image_length + BL_HEADER_SIZE; if (header.type == HEADER_STM32IMAGE) {
size = header.image_length + BL_HEADER_SIZE;
/* uImage detected in STM32IMAGE, execute the script */ /* uImage detected in STM32IMAGE, execute the script */
if (IMAGE_FORMAT_LEGACY == if (IMAGE_FORMAT_LEGACY ==
genimg_get_format((void *)(addr + BL_HEADER_SIZE))) genimg_get_format((void *)(addr + BL_HEADER_SIZE)))
return image_source_script(addr + BL_HEADER_SIZE, return image_source_script(addr + BL_HEADER_SIZE, "script@1");
"script@1"); }
} }
if (IS_ENABLED(CONFIG_DM_VIDEO)) if (IS_ENABLED(CONFIG_DM_VIDEO))

View File

@ -60,8 +60,6 @@ static const efi_guid_t uuid_mmc[3] = {
ROOTFS_MMC2_UUID ROOTFS_MMC2_UUID
}; };
DECLARE_GLOBAL_DATA_PTR;
/* order of column in flash layout file */ /* order of column in flash layout file */
enum stm32prog_col_t { enum stm32prog_col_t {
COL_OPTION, COL_OPTION,
@ -73,6 +71,16 @@ enum stm32prog_col_t {
COL_NB_STM32 COL_NB_STM32
}; };
#define FIP_TOC_HEADER_NAME 0xAA640001
struct fip_toc_header {
u32 name;
u32 serial_number;
u64 flags;
};
DECLARE_GLOBAL_DATA_PTR;
/* partition handling routines : CONFIG_CMD_MTDPARTS */ /* partition handling routines : CONFIG_CMD_MTDPARTS */
int mtdparts_init(void); int mtdparts_init(void);
int find_dev_and_part(const char *id, struct mtd_device **dev, int find_dev_and_part(const char *id, struct mtd_device **dev,
@ -88,46 +96,57 @@ char *stm32prog_get_error(struct stm32prog_data *data)
return data->error; return data->error;
} }
u8 stm32prog_header_check(struct raw_header_s *raw_header, static bool stm32prog_is_fip_header(struct fip_toc_header *header)
struct image_header_s *header) {
return (header->name == FIP_TOC_HEADER_NAME) && header->serial_number;
}
void stm32prog_header_check(struct raw_header_s *raw_header,
struct image_header_s *header)
{ {
unsigned int i; unsigned int i;
header->present = 0; if (!raw_header || !header) {
log_debug("%s:no header data\n", __func__);
return;
}
header->type = HEADER_NONE;
header->image_checksum = 0x0; header->image_checksum = 0x0;
header->image_length = 0x0; header->image_length = 0x0;
if (!raw_header || !header) { if (stm32prog_is_fip_header((struct fip_toc_header *)raw_header)) {
log_debug("%s:no header data\n", __func__); header->type = HEADER_FIP;
return -1; return;
} }
if (raw_header->magic_number != if (raw_header->magic_number !=
(('S' << 0) | ('T' << 8) | ('M' << 16) | (0x32 << 24))) { (('S' << 0) | ('T' << 8) | ('M' << 16) | (0x32 << 24))) {
log_debug("%s:invalid magic number : 0x%x\n", log_debug("%s:invalid magic number : 0x%x\n",
__func__, raw_header->magic_number); __func__, raw_header->magic_number);
return -2; return;
} }
/* only header v1.0 supported */ /* only header v1.0 supported */
if (raw_header->header_version != 0x00010000) { if (raw_header->header_version != 0x00010000) {
log_debug("%s:invalid header version : 0x%x\n", log_debug("%s:invalid header version : 0x%x\n",
__func__, raw_header->header_version); __func__, raw_header->header_version);
return -3; return;
} }
if (raw_header->reserved1 != 0x0 || raw_header->reserved2) { if (raw_header->reserved1 != 0x0 || raw_header->reserved2) {
log_debug("%s:invalid reserved field\n", __func__); log_debug("%s:invalid reserved field\n", __func__);
return -4; return;
} }
for (i = 0; i < (sizeof(raw_header->padding) / 4); i++) { for (i = 0; i < (sizeof(raw_header->padding) / 4); i++) {
if (raw_header->padding[i] != 0) { if (raw_header->padding[i] != 0) {
log_debug("%s:invalid padding field\n", __func__); log_debug("%s:invalid padding field\n", __func__);
return -5; return;
} }
} }
header->present = 1; header->type = HEADER_STM32IMAGE;
header->image_checksum = le32_to_cpu(raw_header->image_checksum); header->image_checksum = le32_to_cpu(raw_header->image_checksum);
header->image_length = le32_to_cpu(raw_header->image_length); header->image_length = le32_to_cpu(raw_header->image_length);
return 0; return;
} }
static u32 stm32prog_header_checksum(u32 addr, struct image_header_s *header) static u32 stm32prog_header_checksum(u32 addr, struct image_header_s *header)
@ -356,8 +375,8 @@ static int parse_flash_layout(struct stm32prog_data *data,
data->part_nb = 0; data->part_nb = 0;
/* check if STM32image is detected */ /* check if STM32image is detected */
if (!stm32prog_header_check((struct raw_header_s *)addr, stm32prog_header_check((struct raw_header_s *)addr, &data->header);
&data->header)) { if (data->header.type == HEADER_STM32IMAGE) {
u32 checksum; u32 checksum;
addr = addr + BL_HEADER_SIZE; addr = addr + BL_HEADER_SIZE;
@ -1410,7 +1429,7 @@ static int stm32prog_copy_fsbl(struct stm32prog_part_t *part)
if (part->target != STM32PROG_NAND && if (part->target != STM32PROG_NAND &&
part->target != STM32PROG_SPI_NAND) part->target != STM32PROG_SPI_NAND)
return -1; return -EINVAL;
dfu = dfu_get_entity(part->alt_id); dfu = dfu_get_entity(part->alt_id);
@ -1420,8 +1439,10 @@ static int stm32prog_copy_fsbl(struct stm32prog_part_t *part)
ret = dfu->read_medium(dfu, 0, (void *)&raw_header, &size); ret = dfu->read_medium(dfu, 0, (void *)&raw_header, &size);
if (ret) if (ret)
return ret; return ret;
if (stm32prog_header_check(&raw_header, &header))
return -1; stm32prog_header_check(&raw_header, &header);
if (header.type != HEADER_STM32IMAGE)
return -ENOENT;
/* read header + payload */ /* read header + payload */
size = header.image_length + BL_HEADER_SIZE; size = header.image_length + BL_HEADER_SIZE;

View File

@ -37,8 +37,14 @@ enum stm32prog_link_t {
LINK_UNDEFINED, LINK_UNDEFINED,
}; };
enum stm32prog_header_t {
HEADER_NONE,
HEADER_STM32IMAGE,
HEADER_FIP,
};
struct image_header_s { struct image_header_s {
bool present; enum stm32prog_header_t type;
u32 image_checksum; u32 image_checksum;
u32 image_length; u32 image_length;
}; };
@ -160,8 +166,8 @@ int stm32prog_pmic_read(struct stm32prog_data *data, u32 offset,
int stm32prog_pmic_start(struct stm32prog_data *data); int stm32prog_pmic_start(struct stm32prog_data *data);
/* generic part*/ /* generic part*/
u8 stm32prog_header_check(struct raw_header_s *raw_header, void stm32prog_header_check(struct raw_header_s *raw_header,
struct image_header_s *header); struct image_header_s *header);
int stm32prog_dfu_init(struct stm32prog_data *data); int stm32prog_dfu_init(struct stm32prog_data *data);
void stm32prog_next_phase(struct stm32prog_data *data); void stm32prog_next_phase(struct stm32prog_data *data);
void stm32prog_do_reset(struct stm32prog_data *data); void stm32prog_do_reset(struct stm32prog_data *data);

View File

@ -309,11 +309,10 @@ static u8 stm32prog_header(struct stm32prog_data *data)
/* force cleanup to avoid issue with previous read */ /* force cleanup to avoid issue with previous read */
dfu_transaction_cleanup(dfu_entity); dfu_transaction_cleanup(dfu_entity);
ret = stm32prog_header_check(data->header_data, stm32prog_header_check(data->header_data, &data->header);
&data->header);
/* no header : max size is partition size */ /* no stm32 image header : max size is partition size */
if (ret) { if (data->header.type != HEADER_STM32IMAGE) {
dfu_entity->get_medium_size(dfu_entity, &size); dfu_entity->get_medium_size(dfu_entity, &size);
data->header.image_length = size; data->header.image_length = size;
} }
@ -389,7 +388,7 @@ static u8 stm32prog_start(struct stm32prog_data *data, u32 address)
data->dfu_seq = 0; data->dfu_seq = 0;
printf("\n received length = 0x%x\n", data->cursor); printf("\n received length = 0x%x\n", data->cursor);
if (data->header.present) { if (data->header.type == HEADER_STM32IMAGE) {
if (data->cursor != if (data->cursor !=
(data->header.image_length + BL_HEADER_SIZE)) { (data->header.image_length + BL_HEADER_SIZE)) {
stm32prog_err("transmission interrupted (length=0x%x expected=0x%x)", stm32prog_err("transmission interrupted (length=0x%x expected=0x%x)",
@ -789,7 +788,7 @@ static void download_command(struct stm32prog_data *data)
} }
} }
if (image_header->present) { if (data->header.type == HEADER_STM32IMAGE) {
if (data->cursor <= BL_HEADER_SIZE) if (data->cursor <= BL_HEADER_SIZE)
goto end; goto end;
/* compute checksum on payload */ /* compute checksum on payload */