spl: Add support for passing handoff info to U-Boot proper
authorSimon Glass <sjg@chromium.org>
Fri, 16 Nov 2018 01:44:09 +0000 (18:44 -0700)
committerTom Rini <trini@konsulko.com>
Mon, 26 Nov 2018 13:25:37 +0000 (08:25 -0500)
There is some basic informaton that SPL normally wants to pass through to
U-Boot, such as the SDRAM size and bank information.

Mkae use of the new bloblist structure for this. Add a new 'handoff' blob
which is set up in SPL and passed to U-Boot proper. Also adda  test for
sandbox_spl that checks that this works correctly and a new 'sb' command
to show the information passed from SPL.

Reviewed-by: Tom Rini <trini@konsulko.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
14 files changed:
arch/powerpc/include/asm/spl.h
arch/sandbox/include/asm/handoff.h [new file with mode: 0644]
cmd/sb.c
common/board_f.c
common/init/Makefile
common/init/handoff.c [new file with mode: 0644]
common/spl/Kconfig
common/spl/spl.c
configs/sandbox_spl_defconfig
include/asm-generic/global_data.h
include/handoff.h [new file with mode: 0644]
include/spl.h
test/py/tests/test_handoff.py [new file with mode: 0644]
test/run

index cd6d31c..60a7d37 100644 (file)
@@ -8,7 +8,4 @@
 
 #define BOOT_DEVICE_NOR                1
 
-/* Linker symbols */
-extern char __bss_start[], __bss_end[];
-
 #endif
diff --git a/arch/sandbox/include/asm/handoff.h b/arch/sandbox/include/asm/handoff.h
new file mode 100644 (file)
index 0000000..be4e7b0
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Architecture-specific SPL handoff information for sandbox
+ *
+ * Copyright 2018 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __handoff_h
+#define __handoff_h
+
+#define TEST_HANDOFF_MAGIC     0x14f93c7b
+
+struct arch_spl_handoff {
+       ulong   magic;          /* Used for testing */
+};
+
+#endif
index 6ca3361..5701e03 100644 (file)
--- a/cmd/sb.c
+++ b/cmd/sb.c
@@ -9,6 +9,23 @@
 #include <spl.h>
 #include <asm/state.h>
 
+static int do_sb_handoff(cmd_tbl_t *cmdtp, int flag, int argc,
+                        char *const argv[])
+{
+#if CONFIG_IS_ENABLED(HANDOFF)
+       if (gd->spl_handoff)
+               printf("SPL handoff magic %lx\n", gd->spl_handoff->arch.magic);
+       else
+               printf("SPL handoff info not received\n");
+
+       return 0;
+#else
+       printf("Command not supported\n");
+
+       return CMD_RET_USAGE;
+#endif
+}
+
 static int do_sb_state(cmd_tbl_t *cmdtp, int flag, int argc,
                       char * const argv[])
 {
@@ -21,6 +38,7 @@ static int do_sb_state(cmd_tbl_t *cmdtp, int flag, int argc,
 }
 
 static cmd_tbl_t cmd_sb_sub[] = {
+       U_BOOT_CMD_MKENT(handoff, 1, 0, do_sb_handoff, "", ""),
        U_BOOT_CMD_MKENT(state, 1, 0, do_sb_state, "", ""),
 };
 
@@ -42,5 +60,6 @@ static int do_sb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 U_BOOT_CMD(
        sb,     8,      1,      do_sb,
        "Sandbox status commands",
-       "state       - Show sandbox state"
+       "handoff     - Show handoff data received from SPL\n"
+       "sb state       - Show sandbox state"
 );
index 290e2b0..835b724 100644 (file)
@@ -25,6 +25,9 @@
 #include <post.h>
 #include <relocate.h>
 #include <spi.h>
+#ifdef CONFIG_SPL
+#include <spl.h>
+#endif
 #include <status_led.h>
 #include <sysreset.h>
 #include <timer.h>
@@ -286,6 +289,17 @@ static int setup_mon_len(void)
        return 0;
 }
 
+static int setup_spl_handoff(void)
+{
+#if CONFIG_IS_ENABLED(HANDOFF)
+       gd->spl_handoff = bloblist_find(BLOBLISTT_SPL_HANDOFF,
+                                       sizeof(struct spl_handoff));
+       debug("Found SPL hand-off info %p\n", gd->spl_handoff);
+#endif
+
+       return 0;
+}
+
 __weak int arch_cpu_init(void)
 {
        return 0;
@@ -845,6 +859,7 @@ static const init_fnc_t init_sequence_f[] = {
 #ifdef CONFIG_BLOBLIST
        bloblist_init,
 #endif
+       setup_spl_handoff,
        initf_console_record,
 #if defined(CONFIG_HAVE_FSP)
        arch_fsp_init,
index 4902635..853b56d 100644 (file)
@@ -5,3 +5,4 @@
 #
 
 obj-y += board_init.o
+obj-$(CONFIG_$(SPL_TPL_)HANDOFF) += handoff.o
diff --git a/common/init/handoff.c b/common/init/handoff.c
new file mode 100644 (file)
index 0000000..e00b43e
--- /dev/null
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Passing basic information from SPL to U-Boot proper
+ *
+ * Copyright 2018 Google, Inc
+ */
+
+#include <common.h>
+#include <handoff.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void handoff_save_dram(struct spl_handoff *ho)
+{
+       ho->ram_size = gd->ram_size;
+#ifdef CONFIG_NR_DRAM_BANKS
+       {
+               struct bd_info *bd = gd->bd;
+               int i;
+
+               for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+                       ho->ram_bank[i].start = bd->bi_dram[i].start;
+                       ho->ram_bank[i].size = bd->bi_dram[i].size;
+               }
+       }
+#endif
+}
+
+void handoff_load_dram_size(struct spl_handoff *ho)
+{
+       gd->ram_size = ho->ram_size;
+}
+
+void handoff_load_dram_banks(struct spl_handoff *ho)
+{
+#ifdef CONFIG_NR_DRAM_BANKS
+       {
+               struct bd_info *bd = gd->bd;
+               int i;
+
+               for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+                       bd->bi_dram[i].start = ho->ram_bank[i].start;
+                       bd->bi_dram[i].size = ho->ram_bank[i].size;
+               }
+       }
+#endif
+}
index 32fa575..0ddbffc 100644 (file)
@@ -25,8 +25,28 @@ config SPL_FRAMEWORK
          supports MMC, NAND and YMODEM and other methods loading of U-Boot
          and the Linux Kernel.  If unsure, say Y.
 
+config HANDOFF
+       bool "Pass hand-off information from SPL to U-Boot proper"
+       depends on BLOBLIST
+       help
+         It is useful to be able to pass information from SPL to U-Boot
+         proper to preserve state that is known in SPL and is needed in U-Boot.
+         Enable this to locate the handoff information in U-Boot proper, early
+         in boot. It is available in gd->handoff. The state state is set up
+         in SPL (or TPL if that is being used).
+
 if SPL
 
+config SPL_HANDOFF
+       bool "Pass hand-off information from SPL to U-Boot proper"
+       depends on HANDOFF
+       default y
+       help
+         This option enables SPL to write handoff information. This can be
+         used to pass information like the size of SDRAM from SPL to U-Boot
+         proper. Also SPL can receive information from TPL in the same place
+         if that is enabled.
+
 config SPL_LDSCRIPT
        string "Linker script for the SPL stage"
        default "arch/$(ARCH)/cpu/u-boot-spl.lds"
@@ -867,6 +887,16 @@ config TPL
 
 if TPL
 
+config TPL_HANDOFF
+       bool "Pass hand-off information from TPL to SPL and U-Boot proper"
+       depends on HANDOFF
+       default y
+       help
+         This option enables TPL to write handoff information. This can be
+         used to pass information like the size of SDRAM from TPL to U-Boot
+         proper. The information is also available to SPL if it is useful
+         there.
+
 config TPL_BOARD_INIT
        bool "Call board-specific initialization in TPL"
        help
index 4313710..35120b6 100644 (file)
@@ -10,6 +10,7 @@
 #include <bloblist.h>
 #include <binman_sym.h>
 #include <dm.h>
+#include <handoff.h>
 #include <spl.h>
 #include <asm/u-boot.h>
 #include <nand.h>
@@ -45,6 +46,14 @@ static bd_t bdata __attribute__ ((section(".data")));
  */
 __weak void show_boot_progress(int val) {}
 
+#if defined(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF)
+/* weak, default platform-specific function to initialize dram banks */
+__weak int dram_init_banksize(void)
+{
+       return 0;
+}
+#endif
+
 /*
  * Default function to determine if u-boot or the OS should
  * be started. This implementation always returns 1.
@@ -64,14 +73,6 @@ __weak int spl_start_uboot(void)
        return 1;
 }
 
-/* weak default platform specific function to initialize
- * dram banks
- */
-__weak int dram_init_banksize(void)
-{
-       return 0;
-}
-
 /*
  * Weak default function for arch specific zImage check. Return zero
  * and fill start and end address if image is recognized.
@@ -320,6 +321,44 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
        image_entry();
 }
 
+#if CONFIG_IS_ENABLED(HANDOFF)
+/**
+ * Set up the SPL hand-off information
+ *
+ * This is initially empty (zero) but can be written by
+ */
+static int setup_spl_handoff(void)
+{
+       struct spl_handoff *ho;
+
+       ho = bloblist_ensure(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff));
+       if (!ho)
+               return -ENOENT;
+
+       return 0;
+}
+
+static int write_spl_handoff(void)
+{
+       struct spl_handoff *ho;
+
+       ho = bloblist_find(BLOBLISTT_SPL_HANDOFF, sizeof(struct spl_handoff));
+       if (!ho)
+               return -ENOENT;
+       handoff_save_dram(ho);
+#ifdef CONFIG_SANDBOX
+       ho->arch.magic = TEST_HANDOFF_MAGIC;
+#endif
+       debug(SPL_TPL_PROMPT "Wrote SPL handoff\n");
+
+       return 0;
+}
+#else
+static inline int setup_spl_handoff(void) { return 0; }
+static inline int write_spl_handoff(void) { return 0; }
+
+#endif /* HANDOFF */
+
 static int spl_common_init(bool setup_malloc)
 {
        int ret;
@@ -355,6 +394,15 @@ static int spl_common_init(bool setup_malloc)
                        return ret;
                }
        }
+       if (CONFIG_IS_ENABLED(HANDOFF)) {
+               int ret;
+
+               ret = setup_spl_handoff();
+               if (ret) {
+                       puts(SPL_TPL_PROMPT "Cannot set up SPL handoff\n");
+                       hang();
+               }
+       }
        if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
                ret = fdtdec_setup();
                if (ret) {
@@ -503,10 +551,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
 
        spl_set_bd();
 
-#ifdef CONFIG_SPL_OS_BOOT
-       dram_init_banksize();
-#endif
-
 #if defined(CONFIG_SYS_SPL_MALLOC_START)
        mem_malloc_init(CONFIG_SYS_SPL_MALLOC_START,
                        CONFIG_SYS_SPL_MALLOC_SIZE);
@@ -528,6 +572,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
        spl_board_init();
 #endif
 
+       if (IS_ENABLED(CONFIG_SPL_OS_BOOT) || CONFIG_IS_ENABLED(HANDOFF))
+               dram_init_banksize();
+
        bootcount_inc();
 
        memset(&spl_image, '\0', sizeof(spl_image));
@@ -544,6 +591,12 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
        }
 
        spl_perform_fixups(&spl_image);
+       if (CONFIG_IS_ENABLED(HANDOFF)) {
+               ret = write_spl_handoff();
+               if (ret)
+                       printf(SPL_TPL_PROMPT
+                              "SPL hand-off write failed (err=%d)\n", ret);
+       }
        if (CONFIG_IS_ENABLED(BLOBLIST)) {
                ret = bloblist_finish();
                if (ret)
index f44e80e..452a2ef 100644 (file)
@@ -22,6 +22,7 @@ CONFIG_CONSOLE_RECORD=y
 CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
 CONFIG_SILENT_CONSOLE=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_HANDOFF=y
 CONFIG_SPL_BOARD_INIT=y
 CONFIG_SPL_ENV_SUPPORT=y
 CONFIG_CMD_CPU=y
index ccf361e..dffd6b2 100644 (file)
@@ -125,6 +125,9 @@ typedef struct global_data {
 #if CONFIG_IS_ENABLED(BLOBLIST)
        struct bloblist_hdr *bloblist;  /* Bloblist information */
        struct bloblist_hdr *new_bloblist;      /* Relocated blolist info */
+# ifdef CONFIG_SPL
+       struct spl_handoff *spl_handoff;
+# endif
 #endif
 } gd_t;
 #endif
diff --git a/include/handoff.h b/include/handoff.h
new file mode 100644 (file)
index 0000000..aacb0f5
--- /dev/null
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Passing basic information from SPL to U-Boot proper
+ *
+ * Copyright 2018 Google, Inc
+ */
+
+#ifndef __HANDOFF_H
+#define __HANDOFF_H
+
+#if CONFIG_IS_ENABLED(HANDOFF)
+
+#include <asm/handoff.h>
+
+/**
+ * struct spl_handoff - information passed from SPL to U-Boot proper
+ *
+ * @ram_size: Value to use for gd->ram_size
+ */
+struct spl_handoff {
+       struct arch_spl_handoff arch;
+       u64 ram_size;
+#ifdef CONFIG_NR_DRAM_BANKS
+       struct {
+               u64 start;
+               u64 size;
+       } ram_bank[CONFIG_NR_DRAM_BANKS];
+#endif
+};
+
+void handoff_save_dram(struct spl_handoff *ho);
+void handoff_load_dram_size(struct spl_handoff *ho);
+void handoff_load_dram_banks(struct spl_handoff *ho);
+#endif
+
+#endif
index 205aaff..ee92832 100644 (file)
@@ -11,6 +11,7 @@
 /* Platform-specific defines */
 #include <linux/compiler.h>
 #include <asm/spl.h>
+#include <handoff.h>
 
 /* Value in r0 indicates we booted from U-Boot */
 #define UBOOT_NOT_LOADED_FROM_SPL      0x13578642
diff --git a/test/py/tests/test_handoff.py b/test/py/tests/test_handoff.py
new file mode 100644 (file)
index 0000000..0ee9722
--- /dev/null
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2016 Google, Inc
+
+import pytest
+
+# Magic number to check that SPL handoff is working
+TEST_HANDOFF_MAGIC = 0x14f93c7b
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('spl')
+def test_handoff(u_boot_console):
+    """Test that of-platdata can be generated and used in sandbox"""
+    cons = u_boot_console
+    response = cons.run_command('sb handoff')
+    assert ('SPL handoff magic %x' % TEST_HANDOFF_MAGIC) in response
index fb8ff5d..cd323b0 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -19,7 +19,7 @@ run_test "sandbox" ./test/py/test.py --bd sandbox --build
 
 # Run tests which require sandbox_spl
 run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl --build \
-       -k test_ofplatdata.py
+       -k 'test_ofplatdata or test_handoff'
 
 # Run tests for the flat-device-tree version of sandbox. This is a special
 # build which does not enable CONFIG_OF_LIVE for the live device tree, so we can