[U-Boot] [RFC PATCH 1/2] sunxi: retrieve FEL-provided values to environment variables

Bernhard Nortmann
2015-09-03T14:11:59Z

This patch extends the misc_init_r() function on sunxi boards
to test for the presence of a suitable "sunxi" SPL header. If
found, and the loader ("fel" utility) provided non-zero values
for either data address or size, then corresponding environment
variables get set.

misc_init_r() also sets (or clears) the "fel_booted" variable depending
on the active boot device, using the same logic as spl_boot_device().

The goal is to provide sufficient information (within the U-Boot
environment) to make intelligent decisions on how to continue the boot
process, allowing specific customizations for the "FEL boot" case.

Signed-off-by: Bernhard Nortmann <bernhard.nortmann@web.de>
---

board/sunxi/board.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)

diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 9c855f6..ceab1e0 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -516,6 +516,54 @@ void get_board_serial(struct tag_serialnr *serialnr)
}
#endif

+#if !defined(CONFIG_SPL_BUILD)
+static int check_signature(unsigned long io_addr, const char *signature,
+ int length)
+{
+ do {
+ if (readb(io_addr) != *signature)
+ return 0;
+ io_addr++;
+ signature++;
+ } while (--length > 0);
+ return 1;
+}
+
+#define SPL_SIGNATURE "SPL" /* marks "sunxi" header */
+#define SPL_EXPECTED_VERSION 1
+
+/*
+ * Check the SPL header for the "sunxi" variant. If found: parse values
+ * that might have been passed by the loader ("fel" utility), and update
+ * the environment accordingly.
+ */
+static void parse_spl_header(void)
+{
+ uint8_t spl_header_version;
+ uint32_t fel_data_address;
+ uint32_t fel_data_size;
+
+ if (check_signature(0x14, SPL_SIGNATURE, 3)) {
+ spl_header_version = readb(0x17);
+ if (spl_header_version == SPL_EXPECTED_VERSION) {
+ fel_data_address = readl(0x18);
+ fel_data_size = readl(0x1C);
+ if (fel_data_address)
+ setenv_hex("fel_data_addr", fel_data_address);
+ else
+ setenv("fel_data_addr", NULL);
+ if (fel_data_size)
+ setenv_hex("fel_data_size", fel_data_size);
+ else
+ setenv("fel_data_size", NULL);
+ } else {
+ printf("sunxi SPL header version mismatch: expected %u, got %u\n",
+ SPL_EXPECTED_VERSION, spl_header_version);
+ }
+ }
+}
+#endif /* !defined(CONFIG_SPL_BUILD) */
+
#ifdef CONFIG_MISC_INIT_R
int misc_init_r(void)
{
@@ -524,6 +572,17 @@ int misc_init_r(void)
uint8_t mac_addr[6];
int ret;

+#if !defined(CONFIG_SPL_BUILD)
+ /* determine if we are running in FEL mode */
+ if (readl(4) != 0x4E4F4765 || readl(8) != 0x3054422E) { /* eGON.BT0 */
+ setenv("fel_booted", "1");
+ parse_spl_header();
+ } else {
+ /* not in FEL mode, delete/clear env var (if present) */
+ setenv("fel_booted", NULL);
+ }
+#endif
+
ret = sunxi_get_sid(sid);
if (ret == 0 && sid[0] != 0 && sid[3] != 0) {
if (!getenv("ethaddr")) {
--
2.4.6