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 <[email protected]>
---
 fel.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/fel.c b/fel.c
index c27ebe3..7befd15 100644
--- a/fel.c
+++ b/fel.c
@@ -259,6 +259,10 @@ void aw_fel_read(libusb_device_handle *usb, uint32_t 
offset, void *buf, size_t l
        aw_read_fel_status(usb);
 }
 
+/* forward declaration to keep the compiler happy */
+void pass_fel_information(libusb_device_handle *usb,
+                         uint32_t data_addr, size_t data_size);
+
 void aw_fel_write(libusb_device_handle *usb, void *buf, uint32_t offset, 
size_t len)
 {
        /* safeguard against overwriting an already loaded U-Boot binary */
@@ -272,6 +276,15 @@ void aw_fel_write(libusb_device_handle *usb, void *buf, 
uint32_t offset, size_t
        aw_send_fel_request(usb, AW_FEL_1_WRITE, offset, len);
        aw_usb_write(usb, buf, len);
        aw_read_fel_status(usb);
+
+       /*
+        * 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 (len > HEADER_SIZE && get_image_type(buf, 0) == IH_TYPE_SCRIPT)
+               pass_fel_information(usb, offset, 0);
 }
 
 void aw_fel_execute(libusb_device_handle *usb, uint32_t offset)
@@ -280,6 +293,46 @@ void aw_fel_execute(libusb_device_handle *usb, uint32_t 
offset)
        aw_read_fel_status(usb);
 }
 
+/*
+ * 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)
+{
+       const uint8_t expected[] = SPL_SIGNATURE;
+       uint8_t spl_signature[4];
+
+       aw_fel_read(usb, 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,
+                         uint32_t data_addr, size_t data_size)
+{
+       /* write something _only_ if we have a suitable SPL header */
+       if (have_sunxi_spl(usb)) {
+               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, 0x18, sizeof(transfer));
+       }
+}
+
 void hexdump(void *data, uint32_t offset, size_t size)
 {
        size_t j;
-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to