diff options
author | Andre Przywara | 2018-12-20 01:15:18 +0000 |
---|---|---|
committer | Andre Przywara | 2021-01-11 23:19:33 +0000 |
commit | 6d295099cc96ed39cd2229dad376ab00baba9a5d (patch) | |
tree | 1f080b61c5cd25edfc132b2ca1938163d131c9cc /tools | |
parent | 23c0ee83aa09c484df3d2c19a8550d31782fd42d (diff) |
tools: mkimage: Add Allwinner eGON support
So far we used the separate mksunxiboot tool for generating a bootable
image for Allwinner SPLs, probably just for historical reasons.
Use the mkimage framework to generate a so called eGON image the
Allwinner BROM expects.
The new image type is called "sunxi_egon", to differentiate it
from the (still to be implemented) secure boot TOC0 image.
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Samuel Holland <samuel@sholland.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 1 | ||||
-rw-r--r-- | tools/sunxi_egon.c | 136 |
2 files changed, 137 insertions, 0 deletions
diff --git a/tools/Makefile b/tools/Makefile index 14fb0ed98f6..9b1aa51b10a 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -104,6 +104,7 @@ dumpimage-mkimage-objs := aisimage.o \ stm32image.o \ $(ROCKCHIP_OBS) \ socfpgaimage.o \ + sunxi_egon.o \ lib/crc16.o \ lib/sha1.o \ lib/sha256.o \ diff --git a/tools/sunxi_egon.c b/tools/sunxi_egon.c new file mode 100644 index 00000000000..a5299eb6a11 --- /dev/null +++ b/tools/sunxi_egon.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 Arm Ltd. + */ + +#include "imagetool.h" +#include <image.h> + +#include <sunxi_image.h> + +/* + * NAND requires 8K padding. SD/eMMC gets away with 512 bytes, + * but let's use the larger padding to cover both. + */ +#define PAD_SIZE 8192 + +static int egon_check_params(struct image_tool_params *params) +{ + /* We just need a binary image file. */ + return !params->dflag; +} + +static int egon_verify_header(unsigned char *ptr, int image_size, + struct image_tool_params *params) +{ + const struct boot_file_head *header = (void *)ptr; + uint32_t length; + + /* First 4 bytes must be an ARM branch instruction. */ + if ((le32_to_cpu(header->b_instruction) & 0xff000000) != 0xea000000) + return EXIT_FAILURE; + + if (memcmp(header->magic, BOOT0_MAGIC, sizeof(header->magic))) + return EXIT_FAILURE; + + length = le32_to_cpu(header->length); + /* Must be at least 512 byte aligned. */ + if (length & 511) + return EXIT_FAILURE; + + /* + * Image could also contain U-Boot proper, so could be bigger. + * But it must not be shorter. + */ + if (image_size < length) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void egon_print_header(const void *buf) +{ + const struct boot_file_head *header = buf; + + printf("Allwinner eGON image, size: %d bytes\n", + le32_to_cpu(header->length)); + + if (memcmp(header->spl_signature, SPL_SIGNATURE, 3)) + return; + + printf("\tSPL header version %d.%d\n", + header->spl_signature[3] >> SPL_MINOR_BITS, + header->spl_signature[3] & ((1U << SPL_MINOR_BITS) - 1)); + if (header->spl_signature[3] >= SPL_DT_HEADER_VERSION) { + uint32_t dt_name_offs = le32_to_cpu(header->dt_name_offset); + + if (dt_name_offs > 0) + printf("\tDT name: %s\n", (char *)buf + dt_name_offs); + } +} + +static void egon_set_header(void *buf, struct stat *sbuf, int infd, + struct image_tool_params *params) +{ + struct boot_file_head *header = buf; + uint32_t *buf32 = buf; + uint32_t checksum = 0, value; + int i; + + /* Generate an ARM branch instruction to jump over the header. */ + value = 0xea000000 | (sizeof(struct boot_file_head) / 4 - 2); + header->b_instruction = cpu_to_le32(value); + + memcpy(header->magic, BOOT0_MAGIC, sizeof(header->magic)); + header->check_sum = cpu_to_le32(BROM_STAMP_VALUE); + header->length = cpu_to_le32(params->file_size); + + memcpy(header->spl_signature, SPL_SIGNATURE, 3); + header->spl_signature[3] = SPL_ENV_HEADER_VERSION; + + /* If an image name has been provided, use it as the DT name. */ + if (params->imagename && params->imagename[0]) { + if (strlen(params->imagename) > sizeof(header->string_pool) - 1) + printf("WARNING: DT name too long for SPL header!\n"); + else { + strcpy((char *)header->string_pool, params->imagename); + value = offsetof(struct boot_file_head, string_pool); + header->dt_name_offset = cpu_to_le32(value); + header->spl_signature[3] = SPL_DT_HEADER_VERSION; + } + } + + /* Calculate the checksum. Yes, it's that simple. */ + for (i = 0; i < sbuf->st_size / 4; i++) + checksum += le32_to_cpu(buf32[i]); + header->check_sum = cpu_to_le32(checksum); +} + +static int egon_check_image_type(uint8_t type) +{ + return type == IH_TYPE_SUNXI_EGON ? 0 : 1; +} + +static int egon_vrec_header(struct image_tool_params *params, + struct image_type_params *tparams) +{ + tparams->hdr = calloc(sizeof(struct boot_file_head), 1); + + /* Return padding to 8K blocks. */ + return ALIGN(params->file_size, PAD_SIZE) - params->file_size; +} + +U_BOOT_IMAGE_TYPE( + sunxi_egon, + "Allwinner eGON Boot Image support", + sizeof(struct boot_file_head), + NULL, + egon_check_params, + egon_verify_header, + egon_print_header, + egon_set_header, + NULL, + egon_check_image_type, + NULL, + egon_vrec_header +); |