mirror of
https://github.com/Fishwaldo/opensbi.git
synced 2025-03-15 19:31:32 +00:00
firmware: Allow firmwares to provide next mode and options
This patch extends existing firmwares (i.e. fw_jump and fw_payload) to explicitly provide next mode and options to fw_base. We also introduce fw_save_info() which is called by fw_base very early on boot HART. This function can be used by existing firmwares (i.e. fw_jump and fw_payload) to save information passed by previous booting stage. Overall, this is a preparatory patch for implementing fw_dynamic. Signed-off-by: Anup Patel <anup.patel@wdc.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Atish Patra <atish.patra@wdc.com>
This commit is contained in:
parent
243a5e0532
commit
25472de89e
3 changed files with 148 additions and 25 deletions
|
@ -13,6 +13,20 @@
|
|||
#include <sbi/sbi_scratch.h>
|
||||
#include <sbi/sbi_trap.h>
|
||||
|
||||
.macro MOV_3R __d0, __s0, __d1, __s1, __d2, __s2
|
||||
add \__d0, \__s0, zero
|
||||
add \__d1, \__s1, zero
|
||||
add \__d2, \__s2, zero
|
||||
.endm
|
||||
|
||||
.macro MOV_5R __d0, __s0, __d1, __s1, __d2, __s2, __d3, __s3, __d4, __s4
|
||||
add \__d0, \__s0, zero
|
||||
add \__d1, \__s1, zero
|
||||
add \__d2, \__s2, zero
|
||||
add \__d3, \__s3, zero
|
||||
add \__d4, \__s4, zero
|
||||
.endm
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.globl _start
|
||||
|
@ -25,9 +39,15 @@ _start:
|
|||
csrr a6, CSR_MHARTID
|
||||
blt zero, a6, _wait_for_boot_hart
|
||||
|
||||
/* Reset all registers for boot HART */
|
||||
li ra, 0
|
||||
call _reset_regs
|
||||
|
||||
/* Allow main firmware to save info */
|
||||
MOV_5R s0, a0, s1, a1, s2, a2, s3, a3, s4, a4
|
||||
call fw_save_info
|
||||
MOV_5R a0, s0, a1, s1, a2, s2, a3, s3, a4, s4
|
||||
|
||||
/* Preload HART details
|
||||
* s7 -> HART Count
|
||||
* s8 -> HART Stack Size
|
||||
|
@ -59,6 +79,7 @@ _scratch_init:
|
|||
sub tp, tp, a5
|
||||
|
||||
/* Initialize scratch space */
|
||||
/* Store fw_start and fw_size in scratch space */
|
||||
la a4, _fw_start
|
||||
la a5, _fw_end
|
||||
mul t0, s7, s8
|
||||
|
@ -66,27 +87,44 @@ _scratch_init:
|
|||
sub a5, a5, a4
|
||||
REG_S a4, SBI_SCRATCH_FW_START_OFFSET(tp)
|
||||
REG_S a5, SBI_SCRATCH_FW_SIZE_OFFSET(tp)
|
||||
/* Note: fw_next_arg1() uses a0, a1, and ra */
|
||||
/* Store next arg1 in scratch space */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_next_arg1
|
||||
REG_S a0, SBI_SCRATCH_NEXT_ARG1_OFFSET(tp)
|
||||
/* Note: fw_next_addr() uses a0, a1, and ra */
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
/* Store next address in scratch space */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_next_addr
|
||||
REG_S a0, SBI_SCRATCH_NEXT_ADDR_OFFSET(tp)
|
||||
li a4, PRV_S
|
||||
REG_S a4, SBI_SCRATCH_NEXT_MODE_OFFSET(tp)
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
/* Store next mode in scratch space */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_next_mode
|
||||
REG_S a0, SBI_SCRATCH_NEXT_MODE_OFFSET(tp)
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
/* Store warm_boot address in scratch space */
|
||||
la a4, _start_warm
|
||||
REG_S a4, SBI_SCRATCH_WARMBOOT_ADDR_OFFSET(tp)
|
||||
/* Store platform address in scratch space */
|
||||
la a4, platform
|
||||
REG_S a4, SBI_SCRATCH_PLATFORM_ADDR_OFFSET(tp)
|
||||
/* Store hartid-to-scratch function address in scratch space */
|
||||
la a4, _hartid_to_scratch
|
||||
REG_S a4, SBI_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp)
|
||||
/* Clear tmp0 in scratch space */
|
||||
REG_S zero, SBI_SCRATCH_TMP0_OFFSET(tp)
|
||||
/* Store firmware options in scratch space */
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
#ifdef FW_OPTIONS
|
||||
li a4, FW_OPTIONS
|
||||
REG_S a4, SBI_SCRATCH_OPTIONS_OFFSET(tp)
|
||||
#else
|
||||
REG_S zero, SBI_SCRATCH_OPTIONS_OFFSET(tp)
|
||||
add a4, zero, zero
|
||||
#endif
|
||||
call fw_options
|
||||
or a4, a4, a0
|
||||
REG_S a4, SBI_SCRATCH_OPTIONS_OFFSET(tp)
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
/* Move to next scratch space */
|
||||
add t1, t1, t2
|
||||
blt t1, s7, _scratch_init
|
||||
|
||||
|
@ -99,12 +137,10 @@ _bss_zero:
|
|||
blt a4, a5, _bss_zero
|
||||
|
||||
/* Override pervious arg1 */
|
||||
add s0, a0, zero
|
||||
add s1, a1, zero
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_prev_arg1
|
||||
add t1, a0, zero
|
||||
add a0, s0, zero
|
||||
add a1, s1, zero
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
beqz t1, _prev_arg1_override_done
|
||||
add a1, t1, zero
|
||||
_prev_arg1_override_done:
|
||||
|
@ -122,13 +158,12 @@ _prev_arg1_override_done:
|
|||
li a3, ~(__SIZEOF_POINTER__ - 1)
|
||||
li a4, 0xff
|
||||
/* t1 = destination FDT start address */
|
||||
add s0, a0, zero
|
||||
add s1, a1, zero
|
||||
MOV_3R s0, a0, s1, a1, s2, a2
|
||||
call fw_next_arg1
|
||||
add t1, a0, zero
|
||||
add a0, s0, zero
|
||||
add a1, s1, zero
|
||||
MOV_3R a0, s0, a1, s1, a2, s2
|
||||
beqz t1, _fdt_reloc_done
|
||||
beq t1, a1, _fdt_reloc_done
|
||||
and t1, t1, a3
|
||||
/* t0 = source FDT start address */
|
||||
add t0, a1, zero
|
||||
|
@ -188,6 +223,7 @@ _wait_for_boot_hart:
|
|||
beqz a5, _wait_for_boot_hart
|
||||
|
||||
_start_warm:
|
||||
/* Reset all registers for non-boot HARTs */
|
||||
li ra, 0
|
||||
call _reset_regs
|
||||
|
||||
|
@ -430,7 +466,7 @@ _reset_regs:
|
|||
|
||||
/* flush the instruction cache */
|
||||
fence.i
|
||||
/* Reset all registers except ra, a0,a1 */
|
||||
/* Reset all registers except ra, a0, a1 and a2 */
|
||||
li sp, 0
|
||||
li gp, 0
|
||||
li tp, 0
|
||||
|
@ -439,7 +475,6 @@ _reset_regs:
|
|||
li t2, 0
|
||||
li s0, 0
|
||||
li s1, 0
|
||||
li a2, 0
|
||||
li a3, 0
|
||||
li a4, 0
|
||||
li a5, 0
|
||||
|
|
|
@ -9,19 +9,37 @@
|
|||
|
||||
#include "fw_base.S"
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_save_info
|
||||
/*
|
||||
* We can only use a0, a1, a2, a3, and a4 registers here.
|
||||
* The a0, a1, and a2 registers will be same as passed by
|
||||
* previous booting stage.
|
||||
* Nothing to be returned here.
|
||||
*/
|
||||
fw_save_info:
|
||||
ret
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_prev_arg1
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The previous arg1 should be returned in 'a0'.
|
||||
*/
|
||||
fw_prev_arg1:
|
||||
/* We return previous arg1 in 'a0' */
|
||||
add a0, zero, zero
|
||||
ret
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_arg1
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next arg1 should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_arg1:
|
||||
/* We return next arg1 in 'a0' */
|
||||
#ifdef FW_JUMP_FDT_ADDR
|
||||
li a0, FW_JUMP_FDT_ADDR
|
||||
#else
|
||||
|
@ -32,12 +50,38 @@ fw_next_arg1:
|
|||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_addr
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_addr:
|
||||
/* We return next address in 'a0' */
|
||||
la a0, _jump_addr
|
||||
REG_L a0, (a0)
|
||||
ret
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_mode
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'
|
||||
*/
|
||||
fw_next_mode:
|
||||
li a0, PRV_S
|
||||
ret
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_options
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The 'a4' register will have default options.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_options:
|
||||
add a0, zero, zero
|
||||
ret
|
||||
|
||||
#ifndef FW_JUMP_ADDR
|
||||
#error "Must define FW_JUMP_ADDR"
|
||||
#endif
|
||||
|
|
|
@ -9,11 +9,26 @@
|
|||
|
||||
#include "fw_base.S"
|
||||
|
||||
.align 4
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_save_info
|
||||
/*
|
||||
* We can only use a0, a1, a2, a3, and a4 registers here.
|
||||
* The a0, a1, and a2 registers will be same as passed by
|
||||
* previous booting stage.
|
||||
* Nothing to be returned here.
|
||||
*/
|
||||
fw_save_info:
|
||||
ret
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_prev_arg1
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The previous arg1 should be returned in 'a0'.
|
||||
*/
|
||||
fw_prev_arg1:
|
||||
/* We return previous arg1 in 'a0' */
|
||||
#ifdef FW_PAYLOAD_FDT_PATH
|
||||
la a0, fdt_bin
|
||||
#else
|
||||
|
@ -21,11 +36,14 @@ fw_prev_arg1:
|
|||
#endif
|
||||
ret
|
||||
|
||||
.align 4
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_arg1
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next arg1 should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_arg1:
|
||||
/* We return next arg1 in 'a0' */
|
||||
#ifdef FW_PAYLOAD_FDT_ADDR
|
||||
li a0, FW_PAYLOAD_FDT_ADDR
|
||||
#else
|
||||
|
@ -33,14 +51,40 @@ fw_next_arg1:
|
|||
#endif
|
||||
ret
|
||||
|
||||
.align 4
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_addr
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_addr:
|
||||
/* We return next address in 'a0' */
|
||||
la a0, payload_bin
|
||||
ret
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_next_mode
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_next_mode:
|
||||
li a0, PRV_S
|
||||
ret
|
||||
|
||||
.align 3
|
||||
.section .entry, "ax", %progbits
|
||||
.global fw_options
|
||||
/*
|
||||
* We can only use a0, a1, and a2 registers here.
|
||||
* The 'a4' register will have default options.
|
||||
* The next address should be returned in 'a0'.
|
||||
*/
|
||||
fw_options:
|
||||
add a0, zero, zero
|
||||
ret
|
||||
|
||||
#ifdef FW_PAYLOAD_FDT_PATH
|
||||
.align 4
|
||||
.section .text, "ax", %progbits
|
||||
|
|
Loading…
Add table
Reference in a new issue