From aaaaaa2d4863e69063dee36d7bbe70108f84806c Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 15 Sep 2017 12:33:10 +0200 Subject: rockchip: back-to-bootrom: replace assembly-implementation with C-code The back-to-bootrom implementation for Rockchip has always relied on the stack-pointer being valid on entry, so there was little reason to have this as an assembly implementation. This provides a new C-only implementation of save_boot_params and back_to_bootrom (relying on setjmp/longjmp) and removes the older assembly-only implementation. Signed-off-by: Philipp Tomsich Tested-by: Andy Yan Series-cc: Andy Yan Series-cc: Klaus Goger Series-version: 3 Cover-letter: rockchip: back-to-bootrom: replace assembly-implementation with C-code Recent discussions confirmed (what the code always assumed): the Rockchip BROM always enters U-Boot with the stack-pointer valid (i.e. the U-Boot startup code is running off the BROM stack). We can thus replace the back-to-bootrom code (i.e. both the save_boot_params and back_to_bootrom implementations) using C-code based on setjmp/longjmp. The new implementation is already structured to allow an easy drop-in of Andy's changes to enter download-mode when returning to the BROM. This turned out to require a some tweaking to system.h (making sure that the prototype for save_boot_params_ret is visible for A64)and start.S (so binutils knows that this is a possible function entry and it can correctly insert A32-to-Thumb transitions) and taking the axe to setjmp.h (which created quite a few issues with it not expecting A32/T32/Thumb call-sites and some fragility from GCC being smart about the clobber-list of the inline assembly... which led to r9 not being saved or restored). END --- arch/arm/mach-rockchip/bootrom.c | 52 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-rockchip/bootrom.c') diff --git a/arch/arm/mach-rockchip/bootrom.c b/arch/arm/mach-rockchip/bootrom.c index 8380e4e006..7b9b307a89 100644 --- a/arch/arm/mach-rockchip/bootrom.c +++ b/arch/arm/mach-rockchip/bootrom.c @@ -6,11 +6,61 @@ #include #include +#include +#include + +/* + * Force the jmp_buf to the data-section, as .bss will not be valid + * when save_boot_params is invoked. + */ +static jmp_buf brom_ctx __section(".data"); void back_to_bootrom(void) { #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) puts("Returning to boot ROM...\n"); #endif - _back_to_bootrom_s(); + longjmp(brom_ctx, BROM_BOOT_NEXTSTAGE); +} + +/* + * All Rockchip BROM implementations enter with a valid stack-pointer, + * so this can safely be implemented in C (providing a single + * implementation both for ARMv7 and AArch64). + */ +int save_boot_params(void) +{ + int ret = setjmp(brom_ctx); + + switch (ret) { + case 0: + /* + * This is the initial pass through this function + * (i.e. saving the context), setjmp just setup up the + * brom_ctx: transfer back into the startup-code at + * 'save_boot_params_ret' and let the compiler know + * that this will not return. + */ + save_boot_params_ret(); + while (true) + /* does not return */; + break; + + case BROM_BOOT_NEXTSTAGE: + /* + * To instruct the BROM to boot the next stage, we + * need to return 0 to it: i.e. we need to rewrite + * the return code once more. + */ + ret = 0; + break; + + default: +#if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) + puts("FATAL: unexpected command to back_to_bootrom()\n"); +#endif + hang(); + }; + + return ret; } -- cgit v1.2.3