Files
u-boot/tools/sfspl.c
Simon Glass 1a9f81779e mkimage: Use a consistent parameter for struct imgtool *
Use the same 'itl' (for image-tool) whenever this parameter is passed
around. This makes it easier to recognise. Move away from using the word
'parameters', since it contains essentially all of the info about the
tool, not just parameters. Use 'info' instead.

Signed-off-by: Simon Glass <sjg@chromium.org>
2025-08-01 13:20:42 +12:00

175 lines
4.6 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
*
* The StarFive JH7110 requires to prepend a header to u-boot-spl.bin describing
* the payload length and CRC32.
*
* This module implements support in mkimage and dumpimage for this file format.
*
* StarFive's spl_tool available under GPL-2.0-and-later at
* https://github.com/starfive-tech/Tools implements writing the same file
* format and served as a reference.
*/
#include <compiler.h>
#include <fcntl.h>
#include <u-boot/crc.h>
#include <unistd.h>
#include "imagetool.h"
#define DEFAULT_VERSION 0x01010101
#define DEFAULT_BACKUP 0x200000U
#define DEFAULT_OFFSET 0x240
/**
* struct spl_hdr - header for SPL on JH7110
*
* All fields are low-endian.
*/
struct spl_hdr {
/** @offset: offset to SPL header (0x240) */
unsigned int offset;
/** @bkp_offs: address of backup SPL, defaults to DEFAULT_BACKUP */
unsigned int bkp_offs;
/** @zero1: set to zero */
unsigned int zero1[159];
/** @version: header version, defaults to DEFAULT_VERSION */
unsigned int version;
/** @file_size: file size */
unsigned int file_size;
/** @hdr_size: size of the file header (0x400) */
unsigned int hdr_size;
/** @crc32: CRC32 */
unsigned int crc32;
/** @zero2: set to zero */
unsigned int zero2[91];
};
static int sfspl_check_params(struct imgtool *itl)
{
/* Only the RISC-V architecture is supported */
if (itl->Aflag && itl->arch != IH_ARCH_RISCV)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
static int sfspl_verify_header(unsigned char *buf, int size,
struct imgtool *itl)
{
struct spl_hdr *hdr = (void *)buf;
unsigned int hdr_size = le32_to_cpu(hdr->hdr_size);
unsigned int file_size = le32_to_cpu(hdr->file_size);
unsigned int crc = le32_to_cpu(hdr->crc32);
unsigned int crc_check;
if (size < 0 ||
(size_t)size < sizeof(struct spl_hdr) ||
(size_t)size < hdr_size + file_size) {
printf("Truncated file\n");
return EXIT_FAILURE;
}
if ((size_t)size > hdr_size + file_size)
printf("File too long, expected %u bytes\n",
hdr_size + file_size);
if (hdr->version != DEFAULT_VERSION) {
printf("Unknown file format version\n");
return EXIT_FAILURE;
}
crc_check = crc32(0, &buf[hdr_size], file_size);
if (crc_check != crc) {
printf("Incorrect CRC32\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static void sfspl_print_header(const void *buf, struct imgtool *itl)
{
struct spl_hdr *hdr = (void *)buf;
unsigned int hdr_size = le32_to_cpu(hdr->hdr_size);
unsigned int file_size = le32_to_cpu(hdr->file_size);
printf("Header size: %u\n", hdr_size);
printf("Payload size: %u\n", file_size);
}
static int sfspl_image_extract_subimage(void *ptr, struct imgtool *itl)
{
struct spl_hdr *hdr = (void *)ptr;
unsigned char *buf = ptr;
int fd, ret = EXIT_SUCCESS;
unsigned int hdr_size = le32_to_cpu(hdr->hdr_size);
unsigned int file_size = le32_to_cpu(hdr->file_size);
if (itl->pflag) {
printf("Invalid image index %d\n", itl->pflag);
return EXIT_FAILURE;
}
fd = open(itl->outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("Cannot open file");
return EXIT_FAILURE;
}
if (write(fd, &buf[hdr_size], file_size) != file_size) {
perror("Cannot write file");
ret = EXIT_FAILURE;
}
close(fd);
return ret;
}
static int sfspl_check_image_type(uint8_t type)
{
if (type == IH_TYPE_STARFIVE_SPL)
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
static void sfspl_set_header(void *buf, struct stat *sbuf, int infd,
struct imgtool *itl)
{
struct spl_hdr *hdr = buf;
unsigned int file_size;
unsigned int crc;
file_size = itl->file_size - sizeof(struct spl_hdr);
crc = crc32(0, &((unsigned char *)buf)[sizeof(struct spl_hdr)],
file_size);
hdr->offset = cpu_to_le32(DEFAULT_OFFSET);
hdr->bkp_offs = cpu_to_le32(DEFAULT_BACKUP);
hdr->version = cpu_to_le32(DEFAULT_VERSION);
hdr->file_size = cpu_to_le32(file_size);
hdr->hdr_size = cpu_to_le32(sizeof(struct spl_hdr));
hdr->crc32 = cpu_to_le32(crc);
}
static int sfspl_vrec_header(struct imgtool *itl, struct imgtool_funcs *tparams)
{
tparams->hdr = calloc(sizeof(struct spl_hdr), 1);
/* No padding */
return 0;
}
U_BOOT_IMAGE_TYPE(
sfspl, /* id */
"StarFive SPL Image", /* name */
sizeof(struct spl_hdr), /* header_size */
NULL, /* header */
sfspl_check_params, /* check_params */
sfspl_verify_header, /* verify header */
sfspl_print_header, /* print header */
sfspl_set_header, /* set header */
sfspl_image_extract_subimage, /* extract_subimage */
sfspl_check_image_type, /* check_image_type */
NULL, /* fflag_handle */
sfspl_vrec_header /* vrec_header */
);