This patch extends the "fel spl" command to properly handle not only the SPL part of a combined u-boot-sunxi-with-spl.bin boot file, but additionally also transfer the main u-boot binary (image) contained within the second part of such files.
This can simplify the boot process / steps required to get a proper FEL setup - e.g. it avoids having to select u-boot.bin vs. u-boot-dtb.bin, see e.g. http://lists.denx.de/pipermail/u-boot/2015-June/217476.html Original patch/RFC was here: https://groups.google.com/forum/#!topic/linux-sunxi/wBEGUoLNRro Signed-off-by: Bernhard Nortmann <[email protected]> --- fel.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/fel.c b/fel.c index adf8f35..de8afad 100644 --- a/fel.c +++ b/fel.c @@ -599,6 +599,11 @@ void aw_restore_and_enable_mmu(libusb_device_handle *usb, uint32_t *tt) free(tt); } +/* + * Maximum size of SPL, at the same time this is the start offset + * of the main U-Boot image within u-boot-sunxi-with-spl.bin + */ +static const int SPL_LEN_LIMIT = 0x8000; void aw_fel_write_and_execute_spl(libusb_device_handle *usb, uint8_t *buf, size_t len) @@ -608,7 +613,7 @@ void aw_fel_write_and_execute_spl(libusb_device_handle *usb, char header_signature[9] = { 0 }; size_t i, thunk_size; uint32_t *thunk_buf; - uint32_t spl_checksum, spl_len, spl_len_limit = 0x8000; + uint32_t spl_checksum, spl_len, spl_len_limit = SPL_LEN_LIMIT; uint32_t *buf32 = (uint32_t *)buf; uint32_t written = 0; uint32_t *tt = NULL; @@ -722,6 +727,58 @@ void aw_fel_write_and_execute_spl(libusb_device_handle *usb, aw_restore_and_enable_mmu(usb, tt); } +/* Constants taken from ${U-BOOT}/include/image.h */ +#define IH_MAGIC 0x27051956 /* Image Magic Number */ +#define IH_ARCH_ARM 2 /* ARM */ +#define IH_TYPE_FIRMWARE 5 /* Firmware Image */ +#define IH_NMLEN 32 /* Image Name Length */ + +#define HEADER_NAME_OFFSET 32 /* offset of name field */ +#define HEADER_SIZE (HEADER_NAME_OFFSET + IH_NMLEN) + +void aw_fel_write_uboot_image(libusb_device_handle *usb, + uint8_t *buf, size_t len) +{ + uint32_t *buf32 = (uint32_t *)buf; + uint32_t load_addr, data_size; + + /* Check for a valid mkimage header */ + if (be32toh(buf32[0]) != IH_MAGIC) { + fprintf(stderr, "U-Boot image verification failure: " + "expected IH_MAGIC, got 0x%X\n", be32toh(buf32[0])); + exit(1); + } + if (buf[29] != IH_ARCH_ARM|| buf[30] != IH_TYPE_FIRMWARE) { + fprintf(stderr, "U-Boot image verification failure: " + "expected ARM firmware, got %02X %02X\n", buf[29], buf[30]); + exit(1); + } + data_size = be32toh(buf32[3]); /* Image Data Size */ + load_addr = be32toh(buf32[4]); /* Data Load Address */ + if (data_size != len - HEADER_SIZE) { + fprintf(stderr, "U-Boot image data size mismatch: " + "expected %d, got %u\n", len - HEADER_SIZE, data_size); + exit(1); + } + /* TODO: Verify image data integrity using the checksum field ih_dcrc, + * available from be32toh(buf32[6]) + * + * However, this requires CRC routines that mimic their U-Boot + * counterparts, namely image_check_dcrc() in ${U-BOOT}/common/image.cabs + * and crc_wd() in ${U-BOOT}/lib/crc32.c + * + * It should be investigated if existing CRC routines in sunxi-tools + * could be factored out and reused for this purpose - e.g. calc_crc32() + * from nand-part-main.c + */ + + /* If we get here, we're "good to go" (i.e. actually write the data) */ + pr_info("Writing image \"%.*s\", %u bytes @ 0x%X\n", + IH_NMLEN, buf + HEADER_NAME_OFFSET, data_size, load_addr); + + aw_fel_write(usb, buf + HEADER_SIZE, load_addr, data_size); +} + static int aw_fel_get_endpoint(libusb_device_handle *usb) { struct libusb_device *dev = libusb_get_device(usb); @@ -790,6 +847,9 @@ int main(int argc, char **argv) " clear address length Clear memory\n" " fill address length value Fill memory\n" " spl file Load and execute U-Boot SPL\n" + " If file additionally contains a main U-Boot binary\n" + " (u-boot-sunxi-with-spl.bin), this command will also\n" + " write it to memory (default address from image)\n" , argv[0] ); } @@ -873,6 +933,10 @@ int main(int argc, char **argv) size_t size; uint8_t *buf = load_file(argv[2], &size); aw_fel_write_and_execute_spl(handle, buf, size); + // calculate size of (optional) main U-Boot binary, write it if > 0 + int size_main = size - SPL_LEN_LIMIT; + if (size_main > 0) + aw_fel_write_uboot_image(handle, buf + SPL_LEN_LIMIT, size_main); skip=2; } else { fprintf(stderr,"Invalid command %s\n", argv[1]); -- 2.0.5 -- You received this message because you are subscribed to the Google Groups "linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
