This patch makes use of a new sunxi SPL header format, where
fields for passing data to U-Boot are reserved. This allows the
"fel" utility to provide specific pieces of information by
setting these fields (which will be evaluated by U-Boot then).
For now, we may specify a memory region by address and size.

Currently the typical use case is to provide the memory location
of the boot script file (boot.scr). A suitably modified U-Boot
can adjust the boot process accordingly and will auto-execute
the script.

Signed-off-by: Bernhard Nortmann <bernhard.nortm...@web.de>
---
 fel.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/fel.c b/fel.c
index e3566fb..cd10dd3 100644
--- a/fel.c
+++ b/fel.c
@@ -926,6 +926,48 @@ void aw_fel_process_spl_and_uboot(libusb_device_handle 
*usb,
                aw_fel_write_uboot_image(usb, buf + SPL_LEN_LIMIT, size - 
SPL_LEN_LIMIT);
 }
 
+/*
+ * Test the SPL header for our "sunxi" variant. We want to make sure that
+ * we can safely use specific header fields to pass information to U-Boot.
+ * In case of a missing signature (e.g. Allwinner boot0) or header version
+ * mismatch, this function will return "false". If all seems fine,
+ * the result is "true".
+ */
+#define SPL_SIGNATURE                  "SPL" /* marks "sunxi" header */
+#define SPL_EXPECTED_VERSION           1
+int have_sunxi_spl(libusb_device_handle *usb, soc_sram_info *sram_info)
+{
+       const uint8_t expected[] = SPL_SIGNATURE;
+       uint8_t spl_signature[4];
+
+       aw_fel_read(usb, sram_info->spl_addr + 0x14,
+               &spl_signature, sizeof(spl_signature));
+       return (memcmp(spl_signature, expected, 3) == 0
+               && spl_signature[3] == SPL_EXPECTED_VERSION);
+}
+
+/*
+ * Pass information to U-Boot via specialized fields in the SPL header
+ * (see "boot_file_head" in ${U-BOOT}/tools/mksunxiboot.c), providing
+ * information about some data address and size.
+ * Typically this will be the DRAM location of a boot script (boot.scr).
+ */
+void pass_fel_information(libusb_device_handle *usb, soc_sram_info *sram_info,
+                         uint32_t data_addr, size_t data_size)
+{
+       /* write something _only_ if we have a suitable SPL header */
+       if (have_sunxi_spl(usb, sram_info)) {
+               struct {
+                       uint32_t fel_data_address;
+                       uint32_t fel_data_size;
+               } transfer = {data_addr, data_size};
+               pr_info("Passing boot info via sunxi SPL: data addr 0x%08X, 
size 0x%X\n",
+                       transfer.fel_data_address, transfer.fel_data_size);
+               aw_fel_write(usb, &transfer,
+                       sram_info->spl_addr + 0x18, sizeof(transfer));
+       }
+}
+
 static int aw_fel_get_endpoint(libusb_device_handle *usb)
 {
        struct libusb_device *dev = libusb_get_device(usb);
@@ -1067,13 +1109,24 @@ int main(int argc, char **argv)
                        double t1, t2;
                        size_t size;
                        void *buf = load_file(argv[3], &size);
+                       uint32_t offset = strtoul(argv[2], NULL, 0);
                        t1 = gettime();
-                       aw_fel_write(handle, buf, strtoul(argv[2], NULL, 0), 
size);
+                       aw_fel_write(handle, buf, offset, size);
                        t2 = gettime();
                        if (t2 > t1)
                                pr_info("Written %.1f KB in %.1f sec (speed: 
%.1f KB/s)\n",
                                        (double)size / 1000., t2 - t1,
                                        (double)size / (t2 - t1) / 1000.);
+
+                       /*
+                        * If we have transferred a script, try to inform 
U-Boot about it.
+                        * An IH_TYPE_SCRIPT has a well-defined header 
(including length),
+                        * so we pass only the address and keep the size value 
at zero.
+                        * (Reserving size > 0 for different data / future 
extensions.)
+                        */
+                       if (get_image_type(buf, size) == IH_TYPE_SCRIPT)
+                               pass_fel_information(handle, sram_info, offset, 
0);
+
                        free(buf);
                        skip=3;
                } else if (strcmp(argv[1], "read") == 0 && argc > 4) {
-- 
2.4.6

-- 
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 linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to