diff --git a/arch/riscv/dts/k3-u-boot.dtsi b/arch/riscv/dts/k3-u-boot.dtsi new file mode 100644 index 00000000000..d0ba780098e --- /dev/null +++ b/arch/riscv/dts/k3-u-boot.dtsi @@ -0,0 +1,26 @@ +&binman { + bootinfo_nor { + filename = "bootinfo_nor.bin"; + + mkimage { + args = "-s -T spacemit-binfo"; + }; + }; + + spl { + filename = "spacemit-spl-unsigned.bin"; + + mkimage { + args = "-T spacemit-spl"; + offset = <0xFE0>; + + section { + // Use a section to pad SPL at 32B align-size, before passing to mkimage + blob { + align-size = <32>; + filename = "spl/u-boot-spl.bin"; + }; + }; + }; + }; +}; diff --git a/boot/image.c b/boot/image.c index abac2c7034b..f10f81f20d5 100644 --- a/boot/image.c +++ b/boot/image.c @@ -185,6 +185,8 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_STARFIVE_SPL, "sfspl", "StarFive SPL Image" }, { IH_TYPE_TFA_BL31, "tfa-bl31", "TFA BL31 Image", }, { IH_TYPE_STM32IMAGE_V2, "stm32imagev2", "STMicroelectronics STM32 Image V2.0" }, + { IH_TYPE_SPACEMIT_BOOTINFO, "spacemit-binfo", "SpacemiT BootInfo Binary Header" }, + { IH_TYPE_SPACEMIT_SPL, "spacemit-spl", "SpacemiT BootROM loadable Image" }, { -1, "", "", }, }; diff --git a/include/image.h b/include/image.h index 9a1c828416d..e9d5a468fcb 100644 --- a/include/image.h +++ b/include/image.h @@ -234,6 +234,8 @@ enum image_type_t { IH_TYPE_STARFIVE_SPL, /* StarFive SPL image */ IH_TYPE_TFA_BL31, /* TFA BL31 image */ IH_TYPE_STM32IMAGE_V2, /* STMicroelectronics STM32 Image V2.0 */ + IH_TYPE_SPACEMIT_BOOTINFO, /* SpacemiT BootInfo Binary Header */ + IH_TYPE_SPACEMIT_SPL, /* SpacemiT BootROM loadable Image */ IH_TYPE_COUNT, /* Number of image types */ }; diff --git a/tools/Makefile b/tools/Makefile index ae6a3052646..33fda492a47 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -108,6 +108,8 @@ KWB_IMAGE_OBJS-$(CONFIG_TOOLS_LIBCRYPTO) := kwbimage.o ROCKCHIP_OBS = generated/lib/rc4.o rkcommon.o rkimage.o rksd.o rkspi.o +SPACEMIT_OBJS = spacemit-boot.o spacemit-spl.o + # common objs for dumpimage and mkimage dumpimage-mkimage-objs := aisimage.o \ atmelimage.o \ @@ -140,6 +142,7 @@ dumpimage-mkimage-objs := aisimage.o \ stm32image.o \ $(ROCKCHIP_OBS) \ socfpgaimage.o \ + $(SPACEMIT_OBJS) \ sunxi_egon.o \ generated/lib/crc16-ccitt.o \ generated/lib/hash-checksum.o \ diff --git a/tools/spacemit-boot.c b/tools/spacemit-boot.c new file mode 100644 index 00000000000..e60c62ff94c --- /dev/null +++ b/tools/spacemit-boot.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2026 Hangfan Li + */ + + +#include "imagetool.h" + +struct bootinfo_hdr { + struct { + /** @magic: MAGIC value, always 0xB00714F0 */ + uint32_t magic; + /** @version: ???*/ + uint32_t version; + /** @flash_type: oneof "NORF", "BLCK" */ + uint32_t flash_type; + /** @mid: ???*/ + uint8_t mid; + uint8_t _reserved_0[1]; + /** @did: ???*/ + uint16_t did; + /** @page_size: ???*/ + uint32_t page_size; + /** @block_size: ???*/ + uint32_t block_size; + /** @total_size: ???*/ + uint32_t total_size; + /** @multi_plane: ???*/ + uint8_t multi_plane; + uint8_t _reserved_1[3]; + /** @spl0_offset: Offset to primary SPL image */ + uint32_t spl0_offset; + /** @spl1_offset: Offset to backup SPL image */ + uint32_t spl1_offset; + /** @spl_size_limit: Max size of SPL image */ + uint32_t spl_size_limit; + /** @partitiontable0_offset: ??? */ + uint32_t partitiontable0_offset; + /** @partitiontable1_offset: ??? */ + uint32_t partitiontable1_offset; + uint8_t _reserved_2[12]; + } data; + struct { + /** @crc32: crc32 of data */ + uint32_t crc32; + uint8_t _reserved_0[12]; + } checksum; +}; + +static int spacemit_bootinfo_check_params(struct image_tool_params *params) +{ + /* Only the RISC-V architecture is supported */ + if (params->Aflag && params->arch != IH_ARCH_RISCV) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static int spacemit_bootinfo_verify_header(unsigned char *buf, int size, + struct image_tool_params *params) +{ + printf("spacemit_bootinfo_verify_header\n"); + return EXIT_SUCCESS; +} + +static void spacemit_bootinfo_print_header(const void *buf, + struct image_tool_params *params) +{ + printf("spacemit_bootinfo_print_header\n"); +} + +static void spacemit_bootinfo_set_header(void *buf, struct stat *sbuf, int infd, + struct image_tool_params *params) +{ + printf("spacemit_bootinfo_set_header\n"); +} + +static int spacemit_bootinfo_check_image_type(uint8_t type) +{ + if (type == IH_TYPE_SPACEMIT_BOOTINFO) + return EXIT_SUCCESS; + + return EXIT_FAILURE; +} + +static struct bootinfo_hdr spacemit_bootinfo_hdr; + +U_BOOT_IMAGE_TYPE( + spacemit_bootinfo, /* id */ + "SpacemiT BootInfo Header", /* name */ + sizeof(struct bootinfo_hdr), /* header_size */ + &spacemit_bootinfo_hdr, /* header */ + spacemit_bootinfo_check_params, /* check_params */ + spacemit_bootinfo_verify_header, /* verify header */ + spacemit_bootinfo_print_header, /* print header */ + spacemit_bootinfo_set_header, /* set header */ + NULL, /* extract_subimage */ + spacemit_bootinfo_check_image_type, /* check_image_type */ + NULL, /* fflag_handle */ + NULL /* vrec_header */ +); diff --git a/tools/spacemit-spl.c b/tools/spacemit-spl.c new file mode 100644 index 00000000000..8e11d2d401d --- /dev/null +++ b/tools/spacemit-spl.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2026 Hangfan Li + */ + + +#include "imagetool.h" +#include +#include + +#define SPACEMIT_SPL_HDR_MAGIC_LE32 0x44484941 + +struct spl_hdr { + struct { + /** @magic: MAGIC value, always 0x44484941 */ + uint32_t magic; + /** @version: ??? */ + uint8_t version; + /** @secure: ??? */ + uint8_t secure; + uint8_t _reserved_0[2]; + /** @payload_size: Size of payload only */ + uint64_t payload_size; + /** @loadaddr: Target load address */ + uint64_t loadaddr; + } header; + struct { + /** @header: crc32 of header data */ + uint32_t header; + /** @payload: crc32 of payload image */ + uint32_t payload; + } checksum; + // Useful for mmap-ed output file + uint8_t payload[0]; +}; + +static int spacemit_spl_check_params(struct image_tool_params *params) +{ + /* Only the RISC-V architecture is supported */ + if (params->Aflag && params->arch != IH_ARCH_RISCV) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static int spacemit_spl_verify_header(unsigned char *buf, int size, + struct image_tool_params *params) +{ + const struct spl_hdr *hdr = (void *)buf; + if (le32_to_cpu(hdr->header.magic) != SPACEMIT_SPL_HDR_MAGIC_LE32) { + printf("Unmatched header MAGIC value: %08x\n", le32_to_cpu(hdr->header.magic)); + return EXIT_FAILURE; + } + if (le32_to_cpu(hdr->checksum.header) != crc32(0, (void *)&hdr->header, sizeof(hdr->header))) { + printf("Unmatched header checksum\n"); + return EXIT_FAILURE; + } + if (le32_to_cpu(hdr->header.payload_size) + sizeof(struct spl_hdr) > params->file_size) { + printf("Payload size (%lu) exceeds file size (%u) - header size (%lu)\n", + le32_to_cpu(hdr->header.payload_size), params->file_size, sizeof(struct spl_hdr)); + return EXIT_FAILURE; + } + if (le32_to_cpu(hdr->checksum.payload) != crc32(0, (void *)&hdr->payload, le32_to_cpu(hdr->header.payload_size))) { + printf("Unmatched payload checksum\n"); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +static void spacemit_spl_print_header(const void *buf, + struct image_tool_params *params) +{ + const struct spl_hdr *hdr = buf; + printf("SpacemiT BootROM Loadable Image\n"); + printf("-> Header Version: 0x%02x\n", hdr->header.version); + printf("-> Secure Mode: "); + if (hdr->header.secure == 0) { + printf("Disabled\n"); + } else { + printf("Enabled (0x%02x)\n", hdr->header.secure); + } + printf("-> Payload Size: %lu\n", le64_to_cpu(hdr->header.payload_size)); + printf("-> Payload Load Addr: %lu\n", le64_to_cpu(hdr->header.loadaddr)); +} + +static void spacemit_spl_set_header(void *buf, struct stat *sbuf, int infd, + struct image_tool_params *params) +{ + // Filling header info + struct spl_hdr *hdr = buf; + memset((void *)hdr, 0, sizeof(struct spl_hdr)); + hdr->header.magic = cpu_to_le32(SPACEMIT_SPL_HDR_MAGIC_LE32); + hdr->header.version = 0x01; + hdr->header.secure = 0; + hdr->header.payload_size = cpu_to_le64(params->file_size - sizeof(struct spl_hdr)); + hdr->header.loadaddr = cpu_to_le64(0x0); + hdr->checksum.header = cpu_to_le32(crc32(0, (void *)&hdr->header, sizeof(hdr->header))); + hdr->checksum.payload = cpu_to_le32(crc32(0, (void *)hdr->payload, le64_to_cpu(hdr->header.payload_size))); + + // Payload is already copied by mkimage + + // Generate signature + // Here we directly call into OpenSSL to avoid U-Boot overheads +} + +static int spacemit_spl_check_image_type(uint8_t type) +{ + if (type == IH_TYPE_SPACEMIT_SPL) + return EXIT_SUCCESS; + + return EXIT_FAILURE; +} + +static struct spl_hdr spacemit_spl_hdr; + +U_BOOT_IMAGE_TYPE( + spacemit_spl, /* id */ + "SpacemiT BROM loadable Image", /* name */ + sizeof(struct spl_hdr), /* header_size */ + &spacemit_spl_hdr, /* header */ + spacemit_spl_check_params, /* check_params */ + spacemit_spl_verify_header, /* verify header */ + spacemit_spl_print_header, /* print header */ + spacemit_spl_set_header, /* set header */ + NULL, /* extract_subimage */ + spacemit_spl_check_image_type, /* check_image_type */ + NULL, /* fflag_handle */ + NULL /* vrec_header */ +);