riscv: add SPL support
U-Boot SPL on the generic RISC-V CPU supports two boot flows, directly jumping to the image and via OpenSBI firmware. In the first case, both U-Boot SPL and proper must be compiled to run in the same privilege mode. Using OpenSBI firmware, U-Boot SPL must be compiled for machine mode and U-Boot proper for supervisor mode. To be able to use SPL, boards have to provide a supported SPL boot device. Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Tested-by: Bin Meng <bmeng.cn@gmail.com> Reviewed-by: Anup Patel <anup.patel@wdc.com>
This commit is contained in:
		
							parent
							
								
									5e30e45c83
								
							
						
					
					
						commit
						8c59f2023c
					
				|  | @ -76,6 +76,12 @@ config RISCV | ||||||
| 	imply MTD | 	imply MTD | ||||||
| 	imply TIMER | 	imply TIMER | ||||||
| 	imply CMD_DM | 	imply CMD_DM | ||||||
|  | 	imply SPL_DM | ||||||
|  | 	imply SPL_OF_CONTROL | ||||||
|  | 	imply SPL_LIBCOMMON_SUPPORT | ||||||
|  | 	imply SPL_LIBGENERIC_SUPPORT | ||||||
|  | 	imply SPL_SERIAL_SUPPORT | ||||||
|  | 	imply SPL_TIMER | ||||||
| 
 | 
 | ||||||
| config SANDBOX | config SANDBOX | ||||||
| 	bool "Sandbox" | 	bool "Sandbox" | ||||||
|  |  | ||||||
|  | @ -226,4 +226,7 @@ config STACK_SIZE_SHIFT | ||||||
| 	int | 	int | ||||||
| 	default 13 | 	default 13 | ||||||
| 
 | 
 | ||||||
|  | config SPL_LDSCRIPT | ||||||
|  | 	default "arch/riscv/cpu/u-boot-spl.lds" | ||||||
|  | 
 | ||||||
| endmenu | endmenu | ||||||
|  |  | ||||||
|  | @ -10,3 +10,6 @@ config GENERIC_RISCV | ||||||
| 	imply RISCV_TIMER | 	imply RISCV_TIMER | ||||||
| 	imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE) | 	imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE) | ||||||
| 	imply CMD_CPU | 	imply CMD_CPU | ||||||
|  | 	imply SPL_CPU_SUPPORT | ||||||
|  | 	imply SPL_OPENSBI | ||||||
|  | 	imply SPL_LOAD_FIT | ||||||
|  |  | ||||||
|  | @ -75,7 +75,11 @@ _start: | ||||||
|  */ |  */ | ||||||
| call_board_init_f: | call_board_init_f: | ||||||
| 	li	t0, -16 | 	li	t0, -16 | ||||||
|  | #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) | ||||||
|  | 	li	t1, CONFIG_SPL_STACK | ||||||
|  | #else | ||||||
| 	li	t1, CONFIG_SYS_INIT_SP_ADDR | 	li	t1, CONFIG_SYS_INIT_SP_ADDR | ||||||
|  | #endif | ||||||
| 	and	sp, t1, t0		/* force 16 byte alignment */ | 	and	sp, t1, t0		/* force 16 byte alignment */ | ||||||
| 
 | 
 | ||||||
| call_board_init_f_0: | call_board_init_f_0: | ||||||
|  | @ -159,7 +163,24 @@ wait_for_gd_init: | ||||||
| 
 | 
 | ||||||
| 	mv	a0, zero		/* a0 <-- boot_flags = 0 */ | 	mv	a0, zero		/* a0 <-- boot_flags = 0 */ | ||||||
| 	la	t5, board_init_f | 	la	t5, board_init_f | ||||||
| 	jr	t5			/* jump to board_init_f() */ | 	jalr	t5			/* jump to board_init_f() */ | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_SPL_BUILD | ||||||
|  | spl_clear_bss: | ||||||
|  | 	la	t0, __bss_start | ||||||
|  | 	la	t1, __bss_end | ||||||
|  | 	beq	t0, t1, spl_call_board_init_r | ||||||
|  | 
 | ||||||
|  | spl_clear_bss_loop: | ||||||
|  | 	SREG	zero, 0(t0) | ||||||
|  | 	addi	t0, t0, REGBYTES | ||||||
|  | 	bne	t0, t1, spl_clear_bss_loop | ||||||
|  | 
 | ||||||
|  | spl_call_board_init_r: | ||||||
|  | 	mv	a0, zero | ||||||
|  | 	mv	a1, zero | ||||||
|  | 	jal	board_init_r | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| /* | /* | ||||||
|  * void relocate_code (addr_sp, gd, addr_moni) |  * void relocate_code (addr_sp, gd, addr_moni) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,82 @@ | ||||||
|  | /* SPDX-License-Identifier: GPL-2.0+ */ | ||||||
|  | /* | ||||||
|  |  * Based on arch/riscv/cpu/u-boot.lds, which is | ||||||
|  |  * Copyright (C) 2017 Andes Technology Corporation | ||||||
|  |  * Rick Chen, Andes Technology Corporation <rick@andestech.com> | ||||||
|  |  * | ||||||
|  |  * and arch/mips/cpu/u-boot-spl.lds. | ||||||
|  |  */ | ||||||
|  | MEMORY { .spl_mem : ORIGIN = IMAGE_TEXT_BASE, LENGTH = IMAGE_MAX_SIZE } | ||||||
|  | MEMORY { .bss_mem : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \ | ||||||
|  | 		    LENGTH = CONFIG_SPL_BSS_MAX_SIZE } | ||||||
|  | 
 | ||||||
|  | OUTPUT_ARCH("riscv") | ||||||
|  | ENTRY(_start) | ||||||
|  | 
 | ||||||
|  | SECTIONS | ||||||
|  | { | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 	.text : { | ||||||
|  | 		arch/riscv/cpu/start.o	(.text) | ||||||
|  | 		*(.text*) | ||||||
|  | 	} > .spl_mem | ||||||
|  | 
 | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 	.rodata : { | ||||||
|  | 		*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) | ||||||
|  | 	} > .spl_mem | ||||||
|  | 
 | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 	.data : { | ||||||
|  | 		*(.data*) | ||||||
|  | 	} > .spl_mem | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 
 | ||||||
|  | 	.got : { | ||||||
|  | 		__got_start = .; | ||||||
|  | 		*(.got.plt) *(.got) | ||||||
|  | 		__got_end = .; | ||||||
|  | 	} > .spl_mem | ||||||
|  | 
 | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 
 | ||||||
|  | 	.u_boot_list : { | ||||||
|  | 		KEEP(*(SORT(.u_boot_list*))); | ||||||
|  | 	} > .spl_mem | ||||||
|  | 
 | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 
 | ||||||
|  | 	.binman_sym_table : { | ||||||
|  | 		__binman_sym_start = .; | ||||||
|  | 		KEEP(*(SORT(.binman_sym*))); | ||||||
|  | 		__binman_sym_end = .; | ||||||
|  | 	} > .spl_mem | ||||||
|  | 
 | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 
 | ||||||
|  | 	/DISCARD/ : { *(.rela.plt*) } | ||||||
|  | 	.rela.dyn : { | ||||||
|  | 		__rel_dyn_start = .; | ||||||
|  | 		*(.rela*) | ||||||
|  | 		__rel_dyn_end = .; | ||||||
|  | 	} > .spl_mem | ||||||
|  | 
 | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 
 | ||||||
|  | 	.dynsym : { | ||||||
|  | 		__dyn_sym_start = .; | ||||||
|  | 		*(.dynsym) | ||||||
|  | 		__dyn_sym_end = .; | ||||||
|  | 	} > .spl_mem | ||||||
|  | 
 | ||||||
|  | 	. = ALIGN(4); | ||||||
|  | 
 | ||||||
|  | 	_end = .; | ||||||
|  | 
 | ||||||
|  | 	.bss : { | ||||||
|  | 		__bss_start = .; | ||||||
|  | 		*(.bss*) | ||||||
|  | 		. = ALIGN(4); | ||||||
|  | 		__bss_end = .; | ||||||
|  | 	} > .bss_mem | ||||||
|  | } | ||||||
|  | @ -0,0 +1,31 @@ | ||||||
|  | /* SPDX-License-Identifier: GPL-2.0+ */ | ||||||
|  | /*
 | ||||||
|  |  * Based on arch/mips/include/asm/spl.h. | ||||||
|  |  * | ||||||
|  |  * (C) Copyright 2012 | ||||||
|  |  * Texas Instruments, <www.ti.com> | ||||||
|  |  */ | ||||||
|  | #ifndef _ASM_RISCV_SPL_H_ | ||||||
|  | #define _ASM_RISCV_SPL_H_ | ||||||
|  | 
 | ||||||
|  | enum { | ||||||
|  | 	BOOT_DEVICE_RAM, | ||||||
|  | 	BOOT_DEVICE_MMC1, | ||||||
|  | 	BOOT_DEVICE_MMC2, | ||||||
|  | 	BOOT_DEVICE_MMC2_2, | ||||||
|  | 	BOOT_DEVICE_NAND, | ||||||
|  | 	BOOT_DEVICE_ONENAND, | ||||||
|  | 	BOOT_DEVICE_NOR, | ||||||
|  | 	BOOT_DEVICE_UART, | ||||||
|  | 	BOOT_DEVICE_SPI, | ||||||
|  | 	BOOT_DEVICE_USB, | ||||||
|  | 	BOOT_DEVICE_SATA, | ||||||
|  | 	BOOT_DEVICE_I2C, | ||||||
|  | 	BOOT_DEVICE_BOARD, | ||||||
|  | 	BOOT_DEVICE_DFU, | ||||||
|  | 	BOOT_DEVICE_XIP, | ||||||
|  | 	BOOT_DEVICE_BOOTROM, | ||||||
|  | 	BOOT_DEVICE_NONE | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -22,6 +22,7 @@ obj-y	+= interrupts.o | ||||||
| obj-y	+= reset.o | obj-y	+= reset.o | ||||||
| obj-y   += setjmp.o | obj-y   += setjmp.o | ||||||
| obj-$(CONFIG_SMP) += smp.o | obj-$(CONFIG_SMP) += smp.o | ||||||
|  | obj-$(CONFIG_SPL_BUILD)	+= spl.o | ||||||
| 
 | 
 | ||||||
| # For building EFI apps
 | # For building EFI apps
 | ||||||
| CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI) | CFLAGS_$(EFI_CRT0) := $(CFLAGS_EFI) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,48 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0+
 | ||||||
|  | /*
 | ||||||
|  |  * Copyright (C) 2019 Fraunhofer AISEC, | ||||||
|  |  * Lukas Auer <lukas.auer@aisec.fraunhofer.de> | ||||||
|  |  */ | ||||||
|  | #include <common.h> | ||||||
|  | #include <spl.h> | ||||||
|  | #include <asm/smp.h> | ||||||
|  | 
 | ||||||
|  | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  | 
 | ||||||
|  | __weak void board_init_f(ulong dummy) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = spl_early_init(); | ||||||
|  | 	if (ret) | ||||||
|  | 		panic("spl_early_init() failed: %d\n", ret); | ||||||
|  | 
 | ||||||
|  | 	arch_cpu_init_dm(); | ||||||
|  | 
 | ||||||
|  | 	preloader_console_init(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) | ||||||
|  | { | ||||||
|  | 	typedef void __noreturn (*image_entry_riscv_t)(ulong hart, void *dtb); | ||||||
|  | 	void *fdt_blob; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | #if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL) | ||||||
|  | 	fdt_blob = spl_image->fdt_addr; | ||||||
|  | #else | ||||||
|  | 	fdt_blob = (void *)gd->fdt_blob; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	image_entry_riscv_t image_entry = | ||||||
|  | 		(image_entry_riscv_t)spl_image->entry_point; | ||||||
|  | 	invalidate_icache_all(); | ||||||
|  | 
 | ||||||
|  | 	debug("image entry point: 0x%lX\n", spl_image->entry_point); | ||||||
|  | #ifdef CONFIG_SMP | ||||||
|  | 	ret = smp_call_function(spl_image->entry_point, (ulong)fdt_blob, 0); | ||||||
|  | 	if (ret) | ||||||
|  | 		hang(); | ||||||
|  | #endif | ||||||
|  | 	image_entry(gd->arch.boot_hart, fdt_blob); | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue