This patch introduces a new "fel uboot" command. Its purpose is to handle not only the SPL part of a combined u-boot-sunxi-with-spl.bin boot file, but additionally transfer the main u-boot binary (image) contained within the second part of such files.
With recent (dtb-based) U-Boot versions, the idea of this modification is to prevent users mixing up u-boot.bin and u-boot-dtb.bin (possibly unconscious, e.g. by relying on outdated FEL scripts). see e.g. http://lists.denx.de/pipermail/u-boot/2015-June/217476.html Signed-off-by: Bernhard Nortmann <[email protected]> --- fel.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/fel.c b/fel.c index adf8f35..843be14 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 %u, 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,7 @@ 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" + " uboot file-with-spl Load and execute SPL, and write U-Boot\n" , argv[0] ); } @@ -874,6 +932,14 @@ int main(int argc, char **argv) uint8_t *buf = load_file(argv[2], &size); aw_fel_write_and_execute_spl(handle, buf, size); skip=2; + } else if (strcmp(argv[1], "uboot") == 0 && argc > 2) { + /* Write (and execute) SPL, then write (main) U-Boot */ + size_t size; + uint8_t *buf = load_file(argv[2], &size); + aw_fel_write_and_execute_spl(handle, buf, size); + usleep(500000); // give SPL execution some time (0.5s) to complete + aw_fel_write_uboot_image(handle, buf + SPL_LEN_LIMIT, size - SPL_LEN_LIMIT); + skip=2; } else { fprintf(stderr,"Invalid command %s\n", argv[1]); exit(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.
