From b0edea3c27af3bf7b959fa190a7fe9d7881153c5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 15 Nov 2018 18:44:09 -0700 Subject: [PATCH] spl: Add support for passing handoff info to U-Boot proper 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 Signed-off-by: Simon Glass --- arch/powerpc/include/asm/spl.h | 3 -- arch/sandbox/include/asm/handoff.h | 18 +++++++ cmd/sb.c | 21 +++++++- common/board_f.c | 15 ++++++ common/init/Makefile | 1 + common/init/handoff.c | 47 ++++++++++++++++++ common/spl/Kconfig | 30 ++++++++++++ common/spl/spl.c | 77 +++++++++++++++++++++++++----- configs/sandbox_spl_defconfig | 1 + include/asm-generic/global_data.h | 3 ++ include/handoff.h | 36 ++++++++++++++ include/spl.h | 1 + test/py/tests/test_handoff.py | 15 ++++++ test/run | 2 +- 14 files changed, 253 insertions(+), 17 deletions(-) create mode 100644 arch/sandbox/include/asm/handoff.h create mode 100644 common/init/handoff.c create mode 100644 include/handoff.h create mode 100644 test/py/tests/test_handoff.py diff --git a/arch/powerpc/include/asm/spl.h b/arch/powerpc/include/asm/spl.h index cd6d31c71a..60a7d37d30 100644 --- a/arch/powerpc/include/asm/spl.h +++ b/arch/powerpc/include/asm/spl.h @@ -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 index 0000000000..be4e7b0fae --- /dev/null +++ b/arch/sandbox/include/asm/handoff.h @@ -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 + */ + +#ifndef __handoff_h +#define __handoff_h + +#define TEST_HANDOFF_MAGIC 0x14f93c7b + +struct arch_spl_handoff { + ulong magic; /* Used for testing */ +}; + +#endif diff --git a/cmd/sb.c b/cmd/sb.c index 6ca3361d7e..5701e03797 100644 --- a/cmd/sb.c +++ b/cmd/sb.c @@ -9,6 +9,23 @@ #include #include +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" ); diff --git a/common/board_f.c b/common/board_f.c index 290e2b09b9..835b7247c5 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -25,6 +25,9 @@ #include #include #include +#ifdef CONFIG_SPL +#include +#endif #include #include #include @@ -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, diff --git a/common/init/Makefile b/common/init/Makefile index 4902635f53..853b56d1e5 100644 --- a/common/init/Makefile +++ b/common/init/Makefile @@ -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 index 0000000000..e00b43e6a7 --- /dev/null +++ b/common/init/handoff.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Passing basic information from SPL to U-Boot proper + * + * Copyright 2018 Google, Inc + */ + +#include +#include + +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 +} diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 32fa5758bf..0ddbffc7d1 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -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 diff --git a/common/spl/spl.c b/common/spl/spl.c index 43137105ba..35120b6efd 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -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) diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index f44e80e8c3..452a2ef4a5 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -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 diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index ccf361ed88..dffd6b2602 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -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 index 0000000000..aacb0f5ebf --- /dev/null +++ b/include/handoff.h @@ -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 + +/** + * 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 diff --git a/include/spl.h b/include/spl.h index 205aaff4b9..ee92832f0a 100644 --- a/include/spl.h +++ b/include/spl.h @@ -11,6 +11,7 @@ /* Platform-specific defines */ #include #include +#include /* 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 index 0000000000..0ee972298c --- /dev/null +++ b/test/py/tests/test_handoff.py @@ -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 diff --git a/test/run b/test/run index fb8ff5da0c..cd323b0a85 100755 --- 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 -- 2.39.5