From b023176c17e655f9371df65f6fddc0c1bcbb1fc7 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Fri, 21 Dec 2018 09:52:27 +0530 Subject: top: Rename "blob" to "firmware" everywhere This patch renames "blob" to "firmware" everywhere for better and intutive naming. Signed-off-by: Anup Patel --- Makefile | 34 ++--- README.md | 14 +- blob/fw_common.S | 326 -------------------------------------------- blob/fw_common.ldS | 89 ------------ blob/fw_jump.S | 48 ------- blob/fw_jump.elf.ldS | 16 --- blob/fw_payload.S | 63 --------- blob/fw_payload.elf.ldS | 26 ---- blob/objects.mk | 39 ------ docs/blob/fw_jump.md | 37 ----- docs/blob/fw_payload.md | 51 ------- docs/firmware/fw_jump.md | 37 +++++ docs/firmware/fw_payload.md | 51 +++++++ firmware/fw_common.S | 326 ++++++++++++++++++++++++++++++++++++++++++++ firmware/fw_common.ldS | 89 ++++++++++++ firmware/fw_jump.S | 48 +++++++ firmware/fw_jump.elf.ldS | 16 +++ firmware/fw_payload.S | 63 +++++++++ firmware/fw_payload.elf.ldS | 26 ++++ firmware/objects.mk | 39 ++++++ 20 files changed, 719 insertions(+), 719 deletions(-) delete mode 100644 blob/fw_common.S delete mode 100644 blob/fw_common.ldS delete mode 100644 blob/fw_jump.S delete mode 100644 blob/fw_jump.elf.ldS delete mode 100644 blob/fw_payload.S delete mode 100644 blob/fw_payload.elf.ldS delete mode 100644 blob/objects.mk delete mode 100644 docs/blob/fw_jump.md delete mode 100644 docs/blob/fw_payload.md create mode 100644 docs/firmware/fw_jump.md create mode 100644 docs/firmware/fw_payload.md create mode 100644 firmware/fw_common.S create mode 100644 firmware/fw_common.ldS create mode 100644 firmware/fw_jump.S create mode 100644 firmware/fw_jump.elf.ldS create mode 100644 firmware/fw_payload.S create mode 100644 firmware/fw_payload.elf.ldS create mode 100644 firmware/objects.mk diff --git a/Makefile b/Makefile index ff416744..112d3722 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ export plat_dir=$(CURDIR)/$(plat_subdir) export plat_common_dir=$(CURDIR)/plat/common export include_dir=$(CURDIR)/include export lib_dir=$(CURDIR)/lib -export blob_dir=$(CURDIR)/blob +export firmware_dir=$(CURDIR)/firmware # Setup list of objects.mk files ifdef PLAT @@ -70,7 +70,7 @@ plat-object-mks=$(shell if [ -d $(plat_dir) ]; then find $(plat_dir) -iname "obj plat-common-object-mks=$(shell if [ -d $(plat_common_dir) ]; then find $(plat_common_dir) -iname "objects.mk" | sort -r; fi) endif lib-object-mks=$(shell if [ -d $(lib_dir) ]; then find $(lib_dir) -iname "objects.mk" | sort -r; fi) -blob-object-mks=$(shell if [ -d $(blob_dir) ]; then find $(blob_dir) -iname "objects.mk" | sort -r; fi) +firmware-object-mks=$(shell if [ -d $(firmware_dir) ]; then find $(firmware_dir) -iname "objects.mk" | sort -r; fi) # Include platform specifig config.mk ifdef PLAT @@ -83,23 +83,23 @@ include $(plat-object-mks) include $(plat-common-object-mks) endif include $(lib-object-mks) -include $(blob-object-mks) +include $(firmware-object-mks) # Setup list of objects lib-objs-path-y=$(foreach obj,$(lib-objs-y),$(build_dir)/lib/$(obj)) ifdef PLAT plat-objs-path-y=$(foreach obj,$(plat-objs-y),$(build_dir)/$(plat_subdir)/$(obj)) plat-common-objs-path-y=$(foreach obj,$(plat-common-objs-y),$(build_dir)/plat/common/$(obj)) -blob-bins-path-y=$(foreach bin,$(blob-bins-y),$(build_dir)/$(plat_subdir)/blob/$(bin)) +firmware-bins-path-y=$(foreach bin,$(firmware-bins-y),$(build_dir)/$(plat_subdir)/firmware/$(bin)) endif -blob-elfs-path-y=$(blob-bins-path-y:.bin=.elf) -blob-objs-path-y=$(blob-bins-path-y:.bin=.o) +firmware-elfs-path-y=$(firmware-bins-path-y:.bin=.elf) +firmware-objs-path-y=$(firmware-bins-path-y:.bin=.o) # Setup list of deps files for objects deps-y=$(plat-objs-path-y:.o=.dep) deps-y+=$(plat-common-objs-path-y:.o=.dep) deps-y+=$(lib-objs-path-y:.o=.dep) -deps-y+=$(blob-objs-path-y:.o=.dep) +deps-y+=$(firmware-objs-path-y:.o=.dep) # Setup compilation environment cpp=$(CROSS_COMPILE)cpp @@ -109,14 +109,14 @@ cppflags+=-I$(plat_dir)/include cppflags+=-I$(plat_common_dir)/include cppflags+=-I$(include_dir) cppflags+=$(plat-cppflags-y) -cppflags+=$(blob-cppflags-y) +cppflags+=$(firmware-cppflags-y) cc=$(CROSS_COMPILE)gcc cflags=-g -Wall -Werror -nostdlib -fno-strict-aliasing -O2 cflags+=-fno-omit-frame-pointer -fno-optimize-sibling-calls cflags+=-mno-save-restore -mstrict-align cflags+=$(cppflags) cflags+=$(plat-cflags-y) -cflags+=$(blob-cflags-y) +cflags+=$(firmware-cflags-y) cflags+=$(EXTRA_CFLAGS) as=$(CROSS_COMPILE)gcc asflags=-g -Wall -nostdlib -D__ASSEMBLY__ @@ -124,14 +124,14 @@ asflags+=-fno-omit-frame-pointer -fno-optimize-sibling-calls asflags+=-mno-save-restore -mstrict-align asflags+=$(cppflags) asflags+=$(plat-asflags-y) -asflags+=$(blob-asflags-y) +asflags+=$(firmware-asflags-y) asflags+=$(EXTRA_ASFLAGS) ar=$(CROSS_COMPILE)ar arflags=rcs ld=$(CROSS_COMPILE)gcc ldflags=-g -Wall -nostdlib -Wl,--build-id=none ldflags+=$(plat-ldflags-y) -ldflags+=$(blob-ldflags-y) +ldflags+=$(firmware-ldflags-y) merge=$(CROSS_COMPILE)ld mergeflags=-r objcopy=$(CROSS_COMPILE)objcopy @@ -195,7 +195,7 @@ targets-y = $(build_dir)/lib/libsbi.a ifdef PLAT targets-y += $(build_dir)/$(plat_subdir)/lib/libplatsbi.a endif -targets-y += $(blob-bins-path-y) +targets-y += $(firmware-bins-path-y) # Default rule "make" should always be first rule .PHONY: all @@ -252,7 +252,7 @@ all-deps-2 = $(if $(findstring clean,$(MAKECMDGOALS)),,$(all-deps-1)) install_targets-y = install_libsbi ifdef PLAT install_targets-y += install_libplatsbi -install_targets-y += install_blobs +install_targets-y += install_firmwares endif # Rule for "make install" @@ -269,10 +269,10 @@ install_libplatsbi: $(build_dir)/$(plat_subdir)/lib/libplatsbi.a $(build_dir)/li $(call inst_header_dir,$(install_dir)/$(plat_subdir)/include,$(include_dir)/sbi) $(call inst_file,$(install_dir)/$(plat_subdir)/lib/libplatsbi.a,$(build_dir)/$(plat_subdir)/lib/libplatsbi.a) -.PHONY: install_blobs -install_blobs: $(build_dir)/$(plat_subdir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(blob-bins-path-y) - $(call inst_file_list,$(install_dir)/$(plat_subdir)/blob,$(plat_subdir)/blob,$(blob-elfs-path-y)) - $(call inst_file_list,$(install_dir)/$(plat_subdir)/blob,$(plat_subdir)/blob,$(blob-bins-path-y)) +.PHONY: install_firmwares +install_firmwares: $(build_dir)/$(plat_subdir)/lib/libplatsbi.a $(build_dir)/lib/libsbi.a $(firmware-bins-path-y) + $(call inst_file_list,$(install_dir)/$(plat_subdir)/firmware,$(plat_subdir)/firmware,$(firmware-elfs-path-y)) + $(call inst_file_list,$(install_dir)/$(plat_subdir)/firmware,$(plat_subdir)/firmware,$(firmware-bins-path-y)) # Rule for "make clean" .PHONY: clean diff --git a/README.md b/README.md index 82084c3d..ca70e0ef 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ We can create three things using the RISC-V OpenSBI project: 2. **libplatsbi.a** - Platform specific OpenSBI static library (It is libsbi.a plus platform specific hooks represented by "platform" symbol) -3. **blobs** - Platform specific firware blobs +3. **firmwares** - Platform specific firmware binaries How to Build? ------------- @@ -31,7 +31,7 @@ How to Build? For cross-compiling, please ensure that CROSS_COMPILE environment variable is set before starting build system. -The libplatsbi.a and blobs are optional and only built when +The libplatsbi.a and firmwares are optional and only built when `PLAT=` parameter is specified to top-level make. (**NOTE**: `` is sub-directory under plat/ directory) @@ -46,14 +46,14 @@ OR OR `make I= install` -To build and install platform specific OpenSBI library and blobs +To build and install platform specific OpenSBI library and firmwares do the following: -1. Build **libsbi, libplatsbi, and blobs**: +1. Build **libsbi, libplatsbi, and firmwares**: `make PLAT=` OR `make PLAT= O=` -2. Install **libsbi, headers, libplatsbi, and blobs**: +2. Install **libsbi, headers, libplatsbi, and firmwares**: `make PLAT= install` OR `make PLAT= I= install` @@ -61,7 +61,7 @@ OR In addition, we can also specify platform specific command-line options to top-level make (such as `PLAT_` or `FW_`) which are described under `docs/plat/.md` OR -`docs/blob/.md`. +`docs/firmware/.md`. Documentation ------------- @@ -72,7 +72,7 @@ manner: * `docs/platform_guide.md` - Guidelines for adding new platform support * `docs/library_usage.md` - Guidelines for using static library * `docs/plat/.md` - Documentation for `` platform -* `docs/blob/.md` - Documentation for firmware blob `` +* `docs/firmware/.md` - Documentation for firmware `` We also prefer source level documentation, so wherever possible we describe stuff directly in the source code. This helps us maintain source and its diff --git a/blob/fw_common.S b/blob/fw_common.S deleted file mode 100644 index a2685cf2..00000000 --- a/blob/fw_common.S +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2018 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include - - .align 3 - .section .entry, "ax", %progbits - .globl _start - .globl _start_warm -_start: - /* - * Jump to warm-boot if this is not the first core booting, - * that is, for mhartid != 0 - */ - csrr a6, mhartid - blt zero, a6, _wait_for_boot_hart - - /* Zero-out BSS */ - la a4, _bss_start - la a5, _bss_end -_bss_zero: - REG_S zero, (a4) - add a4, a4, __SIZEOF_POINTER__ - blt a4, a5, _bss_zero - - /* Override pervious arg1 */ - add s0, a0, zero - add s1, a1, zero - call fw_prev_arg1 - add t1, a0, zero - add a0, s0, zero - add a1, s1, zero - beqz t1, _prev_arg1_override_done - add a1, t1, zero -_prev_arg1_override_done: - - /* - * Relocate Flatened Device Tree (FDT) - * source FDT address = previous arg1 - * destination FDT address = next arg1 - * - * Note: We will preserve a0 and a1 passed by - * previous booting stage. - */ - beqz a1, _fdt_reloc_done - /* Mask values in a3 and a4 */ - li a3, ~0xf - li a4, 0xff - /* t1 = destination FDT start address */ - add s0, a0, zero - add s1, a1, zero - call fw_next_arg1 - add t1, a0, zero - add a0, s0, zero - add a1, s1, zero - beqz t1, _fdt_reloc_done - and t1, t1, a3 - /* t0 = source FDT start address */ - add t0, a1, zero - and t0, t0, a3 - /* t2 = source FDT size in big-endian */ - lwu t2, 4(t0) - /* t3 = bit[15:8] of FDT size */ - add t3, t2, zero - srli t3, t3, 16 - and t3, t3, a4 - slli t3, t3, 8 - /* t4 = bit[23:16] of FDT size */ - add t4, t2, zero - srli t4, t4, 8 - and t4, t4, a4 - slli t4, t4, 16 - /* t5 = bit[31:24] of FDT size */ - add t5, t2, zero - and t5, t5, a4 - slli t5, t5, 24 - /* t2 = bit[7:0] of FDT size */ - srli t2, t2, 24 - and t2, t2, a4 - /* t2 = FDT size in little-endian */ - or t2, t2, t3 - or t2, t2, t4 - or t2, t2, t5 - /* t2 = destination FDT end address */ - add t2, t1, t2 - /* FDT copy loop */ - ble t2, t1, _fdt_reloc_done -_fdt_reloc_again: - REG_L t3, 0(t0) - REG_S t3, 0(t1) - add t0, t0, __SIZEOF_POINTER__ - add t1, t1, __SIZEOF_POINTER__ - blt t1, t2, _fdt_reloc_again -_fdt_reloc_done: - - /* Update boot hart flag */ - la a4, _boot_hart_done - li a5, 1 - REG_S a5, (a4) - j _wait_for_boot_hart - - .align 3 -_boot_hart_done: - RISCV_PTR 0 - .align 3 - - /* Wait for boot hart */ -_wait_for_boot_hart: - la a4, _boot_hart_done - REG_L a5, (a4) - beqz a5, _wait_for_boot_hart - -_start_warm: - /* Disable and clear all interrupts */ - csrw mie, zero - csrw mip, zero - - /* set MSIE bit to receive IPI */ - li a2, MIP_MSIP - csrw mie, a2 - /* HART ID should be withing expected limit */ - csrr a6, mhartid - li a5, PLAT_HART_COUNT - bge a6, a5, _start_hang - - /* Setup scratch space */ - li a5, PLAT_HART_STACK_SIZE - la tp, _stack_end - mul a5, a5, a6 - sub tp, tp, a5 - li a5, RISCV_SCRATCH_SIZE - sub tp, tp, a5 - csrw mscratch, tp - - /* Initialize scratch space */ - REG_S zero, RISCV_SCRATCH_TMP0_OFFSET(tp) - la a4, _fw_start - la a5, _fw_end - sub a5, a5, a4 - REG_S a4, RISCV_SCRATCH_FW_START_OFFSET(tp) - REG_S a5, RISCV_SCRATCH_FW_SIZE_OFFSET(tp) - /* Note: fw_next_arg1() uses a0, a1, and ra */ - call fw_next_arg1 - REG_S a0, RISCV_SCRATCH_NEXT_ARG1_OFFSET(tp) - /* Note: fw_next_addr() uses a0, a1, and ra */ - call fw_next_addr - REG_S a0, RISCV_SCRATCH_NEXT_ADDR_OFFSET(tp) - li a4, PRV_S - REG_S a4, RISCV_SCRATCH_NEXT_MODE_OFFSET(tp) - la a4, _start_warm - REG_S a4, RISCV_SCRATCH_WARMBOOT_ADDR_OFFSET(tp) - la a4, platform - REG_S a4, RISCV_SCRATCH_PLATFORM_ADDR_OFFSET(tp) - la a4, _hartid_to_scratch - REG_S a4, RISCV_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp) - REG_S zero, RISCV_SCRATCH_IPI_TYPE_OFFSET(tp) - - /* Setup stack */ - add sp, tp, zero - - /* Setup trap handler */ - la a4, _trap_handler - csrw mtvec, a4 - - /* Initialize SBI runtime */ - csrr a0, mscratch - call sbi_init - - /* We don't expect to reach here hence just hang */ - j _start_hang - - .align 3 - .section .entry, "ax", %progbits - .globl _hartid_to_scratch -_hartid_to_scratch: - add sp, sp, -(2 * __SIZEOF_POINTER__) - REG_S a1, (sp) - REG_S a2, (__SIZEOF_POINTER__)(sp) - li a1, PLAT_HART_STACK_SIZE - la a2, _stack_end - mul a1, a1, a0 - sub a2, a2, a1 - li a1, RISCV_SCRATCH_SIZE - sub a0, a2, a1 - REG_L a1, (sp) - REG_L a2, (__SIZEOF_POINTER__)(sp) - add sp, sp, (2 * __SIZEOF_POINTER__) - ret - - .align 3 - .section .entry, "ax", %progbits - .globl _start_hang -_start_hang: - wfi - j _start_hang - - .align 3 - .section .entry, "ax", %progbits - .globl _trap_handler -_trap_handler: - /* Swap SP and MSCRATCH */ - csrrw sp, mscratch, sp - - /* Setup exception stack */ - add sp, sp, -(RISCV_TRAP_REGS_SIZE) - - /* Save RA, T0, T1, and T2 */ - REG_S ra, RISCV_TRAP_REGS_OFFSET(ra)(sp) - REG_S t0, RISCV_TRAP_REGS_OFFSET(t0)(sp) - REG_S t1, RISCV_TRAP_REGS_OFFSET(t1)(sp) - REG_S t2, RISCV_TRAP_REGS_OFFSET(t2)(sp) - - /* Save original SP and restore MSCRATCH */ - add t0, sp, RISCV_TRAP_REGS_SIZE - csrrw t0, mscratch, t0 - REG_S t0, RISCV_TRAP_REGS_OFFSET(sp)(sp) - - /* Save MEPC and MSTATUS CSRs */ - csrr t0, mepc - csrr t1, mstatus - - /* - * Note: Fast path trap handling can be done here - * using SP, RA, T0, T1, and T2 registers where - * T0 <- MEPC - * T1 <- MSTATUS - */ - - /* Save MEPC and MSTATUS CSRs */ - REG_S t0, RISCV_TRAP_REGS_OFFSET(mepc)(sp) - REG_S t1, RISCV_TRAP_REGS_OFFSET(mstatus)(sp) - - /* Save all general regisers except SP, RA, T0, T1, and T2 */ - REG_S zero, RISCV_TRAP_REGS_OFFSET(zero)(sp) - REG_S gp, RISCV_TRAP_REGS_OFFSET(gp)(sp) - REG_S tp, RISCV_TRAP_REGS_OFFSET(tp)(sp) - REG_S s0, RISCV_TRAP_REGS_OFFSET(s0)(sp) - REG_S s1, RISCV_TRAP_REGS_OFFSET(s1)(sp) - REG_S a0, RISCV_TRAP_REGS_OFFSET(a0)(sp) - REG_S a1, RISCV_TRAP_REGS_OFFSET(a1)(sp) - REG_S a2, RISCV_TRAP_REGS_OFFSET(a2)(sp) - REG_S a3, RISCV_TRAP_REGS_OFFSET(a3)(sp) - REG_S a4, RISCV_TRAP_REGS_OFFSET(a4)(sp) - REG_S a5, RISCV_TRAP_REGS_OFFSET(a5)(sp) - REG_S a6, RISCV_TRAP_REGS_OFFSET(a6)(sp) - REG_S a7, RISCV_TRAP_REGS_OFFSET(a7)(sp) - REG_S s2, RISCV_TRAP_REGS_OFFSET(s2)(sp) - REG_S s3, RISCV_TRAP_REGS_OFFSET(s3)(sp) - REG_S s4, RISCV_TRAP_REGS_OFFSET(s4)(sp) - REG_S s5, RISCV_TRAP_REGS_OFFSET(s5)(sp) - REG_S s6, RISCV_TRAP_REGS_OFFSET(s6)(sp) - REG_S s7, RISCV_TRAP_REGS_OFFSET(s7)(sp) - REG_S s8, RISCV_TRAP_REGS_OFFSET(s8)(sp) - REG_S s9, RISCV_TRAP_REGS_OFFSET(s9)(sp) - REG_S s10, RISCV_TRAP_REGS_OFFSET(s10)(sp) - REG_S s11, RISCV_TRAP_REGS_OFFSET(s11)(sp) - REG_S t3, RISCV_TRAP_REGS_OFFSET(t3)(sp) - REG_S t4, RISCV_TRAP_REGS_OFFSET(t4)(sp) - REG_S t5, RISCV_TRAP_REGS_OFFSET(t5)(sp) - REG_S t6, RISCV_TRAP_REGS_OFFSET(t6)(sp) - - /* Call C routine */ - add a0, sp, zero - csrr a1, mscratch - call sbi_trap_handler - - /* Restore all general regisers except SP, RA, T0, T1, T2, and T3 */ - REG_L gp, RISCV_TRAP_REGS_OFFSET(gp)(sp) - REG_L tp, RISCV_TRAP_REGS_OFFSET(tp)(sp) - REG_L s0, RISCV_TRAP_REGS_OFFSET(s0)(sp) - REG_L s1, RISCV_TRAP_REGS_OFFSET(s1)(sp) - REG_L a0, RISCV_TRAP_REGS_OFFSET(a0)(sp) - REG_L a1, RISCV_TRAP_REGS_OFFSET(a1)(sp) - REG_L a2, RISCV_TRAP_REGS_OFFSET(a2)(sp) - REG_L a3, RISCV_TRAP_REGS_OFFSET(a3)(sp) - REG_L a4, RISCV_TRAP_REGS_OFFSET(a4)(sp) - REG_L a5, RISCV_TRAP_REGS_OFFSET(a5)(sp) - REG_L a6, RISCV_TRAP_REGS_OFFSET(a6)(sp) - REG_L a7, RISCV_TRAP_REGS_OFFSET(a7)(sp) - REG_L s2, RISCV_TRAP_REGS_OFFSET(s2)(sp) - REG_L s3, RISCV_TRAP_REGS_OFFSET(s3)(sp) - REG_L s4, RISCV_TRAP_REGS_OFFSET(s4)(sp) - REG_L s5, RISCV_TRAP_REGS_OFFSET(s5)(sp) - REG_L s6, RISCV_TRAP_REGS_OFFSET(s6)(sp) - REG_L s7, RISCV_TRAP_REGS_OFFSET(s7)(sp) - REG_L s8, RISCV_TRAP_REGS_OFFSET(s8)(sp) - REG_L s9, RISCV_TRAP_REGS_OFFSET(s9)(sp) - REG_L s10, RISCV_TRAP_REGS_OFFSET(s10)(sp) - REG_L s11, RISCV_TRAP_REGS_OFFSET(s11)(sp) - REG_L t3, RISCV_TRAP_REGS_OFFSET(t3)(sp) - REG_L t4, RISCV_TRAP_REGS_OFFSET(t4)(sp) - REG_L t5, RISCV_TRAP_REGS_OFFSET(t5)(sp) - REG_L t6, RISCV_TRAP_REGS_OFFSET(t6)(sp) - - /* Load T0 and T1 with MEPC and MSTATUS */ - REG_L t0, RISCV_TRAP_REGS_OFFSET(mepc)(sp) - REG_L t1, RISCV_TRAP_REGS_OFFSET(mstatus)(sp) - - /* - * Note: Jump here after fast trap handling - * using SP, RA, T0, T1, and T2 - * T0 <- MEPC - * T1 <- MSTATUS - */ - - /* Restore MEPC and MSTATUS CSRs */ - csrw mepc, t0 - csrw mstatus, t1 - - /* Restore RA, T0, T1, and T2 */ - REG_L ra, RISCV_TRAP_REGS_OFFSET(ra)(sp) - REG_L t0, RISCV_TRAP_REGS_OFFSET(t0)(sp) - REG_L t1, RISCV_TRAP_REGS_OFFSET(t1)(sp) - REG_L t2, RISCV_TRAP_REGS_OFFSET(t2)(sp) - - /* Restore SP */ - REG_L sp, RISCV_TRAP_REGS_OFFSET(sp)(sp) - - mret diff --git a/blob/fw_common.ldS b/blob/fw_common.ldS deleted file mode 100644 index 3761d62f..00000000 --- a/blob/fw_common.ldS +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2018 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel - * - * SPDX-License-Identifier: BSD-2-Clause - */ - - . = FW_TEXT_START; - - PROVIDE(_fw_start = .); - - . = ALIGN(0x1000); /* Need this to create proper sections */ - - /* Beginning of the code section */ - - .text : - { - PROVIDE(_text_start = .); - *(.entry) - *(.text) - . = ALIGN(8); - PROVIDE(_text_end = .); - } - - . = ALIGN(0x1000); /* Ensure next section is page aligned */ - - /* End of the code sections */ - - /* Beginning of the read-only data sections */ - - . = ALIGN(0x1000); /* Ensure next section is page aligned */ - - .rodata : - { - PROVIDE(_rodata_start = .); - *(.rodata .rodata.*) - . = ALIGN(8); - PROVIDE(_rodata_end = .); - } - - /* End of the read-only data sections */ - - /* Beginning of the read-write data sections */ - - . = ALIGN(0x1000); /* Ensure next section is page aligned */ - - .data : - { - PROVIDE(_data_start = .); - - *(.data) - *(.data.*) - *(.readmostly.data) - *(*.data) - . = ALIGN(8); - - PROVIDE(_data_end = .); - } - - . = ALIGN(0x1000); /* Ensure next section is page aligned */ - - .stack : - { - PROVIDE(_stack_start = .); - *(.stack) - *(.stack.*) - . = . + (PLAT_HART_STACK_SIZE * PLAT_HART_COUNT); - . = ALIGN(8); - PROVIDE(_stack_end = .); - } - - . = ALIGN(0x1000); /* Ensure next section is page aligned */ - - .bss : - { - PROVIDE(_bss_start = .); - *(.bss) - *(.bss.*) - . = ALIGN(8); - PROVIDE(_bss_end = .); - } - - /* End of the read-write data sections */ - - . = ALIGN(0x1000); /* Need this to create proper sections */ - - PROVIDE(_fw_end = .); diff --git a/blob/fw_jump.S b/blob/fw_jump.S deleted file mode 100644 index d05d87fe..00000000 --- a/blob/fw_jump.S +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2018 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "fw_common.S" - - .align 3 - .section .entry, "ax", %progbits - .global fw_prev_arg1 -fw_prev_arg1: - /* We return previous arg1 in 'a0' */ - add a0, zero, zero - ret - - .align 3 - .section .entry, "ax", %progbits - .global fw_next_arg1 -fw_next_arg1: - /* We return next arg1 in 'a0' */ -#ifdef FW_JUMP_FDT_ADDR - li a0, FW_JUMP_FDT_ADDR -#else - add a0, zero, zero -#endif - ret - - .align 3 - .section .entry, "ax", %progbits - .global fw_next_addr -fw_next_addr: - /* We return next address in 'a0' */ - la a0, _jump_addr - REG_L a0, (a0) - ret - -#ifndef FW_JUMP_ADDR -#error "Must define FW_JUMP_ADDR" -#endif - - .align 3 - .section .entry, "ax", %progbits -_jump_addr: - RISCV_PTR FW_JUMP_ADDR diff --git a/blob/fw_jump.elf.ldS b/blob/fw_jump.elf.ldS deleted file mode 100644 index dfffbf60..00000000 --- a/blob/fw_jump.elf.ldS +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2018 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -OUTPUT_ARCH(riscv) -ENTRY(_start) - -SECTIONS -{ - #include "fw_common.ldS" -} diff --git a/blob/fw_payload.S b/blob/fw_payload.S deleted file mode 100644 index b6f3cb96..00000000 --- a/blob/fw_payload.S +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2018 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "fw_common.S" - - .align 3 - .section .entry, "ax", %progbits - .global fw_prev_arg1 -fw_prev_arg1: - /* We return previous arg1 in 'a0' */ -#ifdef FW_PAYLOAD_FDT_PATH - la a0, fdt_bin -#else - add a0, zero, zero -#endif - ret - - .align 3 - .section .entry, "ax", %progbits - .global fw_next_arg1 -fw_next_arg1: - /* We return next arg1 in 'a0' */ -#ifdef FW_PAYLOAD_FDT_ADDR - li a0, FW_PAYLOAD_FDT_ADDR -#else - add a0, zero, zero -#endif - ret - - .align 3 - .section .entry, "ax", %progbits - .global fw_next_addr -fw_next_addr: - /* We return next address in 'a0' */ - la a0, payload_bin - ret - -#define str(s) #s -#define stringify(s) str(s) - -#ifdef FW_PAYLOAD_FDT_PATH - .align 3 - .section .text, "ax", %progbits - .globl fdt_bin -fdt_bin: - .incbin stringify(FW_PAYLOAD_FDT_PATH) -#endif - - .section .payload, "ax", %progbits - .globl payload_bin -payload_bin: -#ifndef FW_PAYLOAD_PATH - wfi - j payload_bin -#else - .incbin stringify(FW_PAYLOAD_PATH) -#endif diff --git a/blob/fw_payload.elf.ldS b/blob/fw_payload.elf.ldS deleted file mode 100644 index 201338b5..00000000 --- a/blob/fw_payload.elf.ldS +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2018 Western Digital Corporation or its affiliates. - * - * Authors: - * Anup Patel - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -OUTPUT_ARCH(riscv) -ENTRY(_start) - -SECTIONS -{ - #include "fw_common.ldS" - - . = FW_TEXT_START + FW_PAYLOAD_OFFSET; - - .payload : - { - PROVIDE(_payload_start = .); - *(.payload) - . = ALIGN(8); - PROVIDE(_payload_end = .); - } -} diff --git a/blob/objects.mk b/blob/objects.mk deleted file mode 100644 index 717f4550..00000000 --- a/blob/objects.mk +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (c) 2018 Western Digital Corporation or its affiliates. -# -# Authors: -# Anup Patel -# -# SPDX-License-Identifier: BSD-2-Clause -# - -blob-cppflags-y = -blob-cflags-y = -blob-asflags-y = -blob-ldflags-y = - -ifdef FW_TEXT_START -blob-cppflags-y += -DFW_TEXT_START=$(FW_TEXT_START) -endif - -blob-bins-$(FW_JUMP) += fw_jump.bin -ifdef FW_JUMP_ADDR -blob-cppflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR) -endif -ifdef FW_JUMP_FDT_ADDR -blob-cppflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR) -endif - -blob-bins-$(FW_PAYLOAD) += fw_payload.bin -ifdef FW_PAYLOAD_PATH -blob-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_PATH=$(FW_PAYLOAD_PATH) -endif -ifdef FW_PAYLOAD_OFFSET -blob-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_OFFSET=$(FW_PAYLOAD_OFFSET) -endif -ifdef FW_PAYLOAD_FDT_PATH -blob-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_PATH=$(FW_PAYLOAD_FDT_PATH) -endif -ifdef FW_PAYLOAD_FDT_ADDR -blob-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR) -endif diff --git a/docs/blob/fw_jump.md b/docs/blob/fw_jump.md deleted file mode 100644 index ee6ad0d8..00000000 --- a/docs/blob/fw_jump.md +++ /dev/null @@ -1,37 +0,0 @@ -OpenSBI Firmware with Jump Address(FW_JUMP) -=========================================== - -The **OpenSBI firmware with Jump Address (FW_JUMP)** is a -firmware which only know the address of next booting stage -(i.e. bootloader/kernel). - -This **FW_JUMP** firmware is particularly useful when booting -stage prior to OpenSBI firmware is capable of loading OpenSBI -firmware and booting stage after OpenSBI firmware separately. - -How to Enable? --------------- - -The **FW_JUMP** firmware can be enabled by any of the following -methods: - -1. Passing `FW_JUMP=y` command-line parameter to -top-level `make` -2. Setting `FW_JUMP=y` in platform `config.mk` - -Config Options --------------- - -We need more config details for **FW_JUMP** firmware to work -correctly. These config details can be passed as paramter to -top-level `make` or can be set in platform `config.mk`. - -Following are the config options for **FW_JUMP** firmware: - -* **FW_JUMP_ADDR** - Address where next booting stage is -located. This is a mandatory config option and will result -in compile error if not provided. -* **FW_JUMP_FDT_ADDR** - Address where FDT passed by prior -booting stage will be placed before passing to next booting -stage. If this option is not provided then firmware will pass -zero as FDT address to next booting stage. \ No newline at end of file diff --git a/docs/blob/fw_payload.md b/docs/blob/fw_payload.md deleted file mode 100644 index 2fab092c..00000000 --- a/docs/blob/fw_payload.md +++ /dev/null @@ -1,51 +0,0 @@ -OpenSBI Firmware with Payload (FW_PAYLOAD) -========================================== - -The **OpenSBI firmware with Payload (FW_PAYLOAD)** is a -firmware which includes next booting stage binary (i.e. -bootloader/kernel) as payload in the OpenSBI firmware binary. - -This **FW_PAYLOAD** firmware is particularly useful when -booting stage prior to OpenSBI firmware is not capable of -loading OpenSBI firmware and booting stage after OpenSBI -firmware separately. - -It is also possible that booting stage prior to OpenSBI -firmware does not pass **flattened device tree (FDT)**. In -this case, we have provision to embed FDT in .text section -of **FW_PAYLOAD** firmware. - -How to Enable? --------------- - -The **FW_PAYLOAD** firmware can be enabled by any of the -following methods: - -1. Passing `FW_PAYLOAD=y` command-line parameter to -top-level `make` -2. Setting `FW_PAYLOAD=y` in platform `config.mk` - -Config Options --------------- - -We need more config details for **FW_PAYLOAD** firmware to -work correctly. These config details can be passed as paramter -to top-level `make` or can be set in platform `config.mk`. - -Following are the config options for **FW_PAYLOAD** firmware: - -* **FW_PAYLOAD_OFFSET** - Offset from FW_TEXT_BASE where next -booting stage binary will be linked to **FW_PAYLOAD** firmware. -This is a mandatory config option and will result in compile -error if not provided. -* **FW_PAYLOAD_PATH** - Path to the next booting stage binary. -If this option is not provided then **`while (1)`** is taken as -payload. -* **FW_PAYLOAD_FDT_PATH** - Path to the FDT binary to be embedded -in .text section of **FW_PAYLOAD** firmware. If this option is -not provided then firmware will expect FDT to be passed by prior -booting stage. -* **FW_PAYLOAD_FDT_ADDR** - Address where FDT passed by prior -booting stage (or embedded FDT) will be placed before passing -to next booting stage. If this option is not provided then -firmware will pass zero as FDT address to next booting stage. \ No newline at end of file diff --git a/docs/firmware/fw_jump.md b/docs/firmware/fw_jump.md new file mode 100644 index 00000000..ee6ad0d8 --- /dev/null +++ b/docs/firmware/fw_jump.md @@ -0,0 +1,37 @@ +OpenSBI Firmware with Jump Address(FW_JUMP) +=========================================== + +The **OpenSBI firmware with Jump Address (FW_JUMP)** is a +firmware which only know the address of next booting stage +(i.e. bootloader/kernel). + +This **FW_JUMP** firmware is particularly useful when booting +stage prior to OpenSBI firmware is capable of loading OpenSBI +firmware and booting stage after OpenSBI firmware separately. + +How to Enable? +-------------- + +The **FW_JUMP** firmware can be enabled by any of the following +methods: + +1. Passing `FW_JUMP=y` command-line parameter to +top-level `make` +2. Setting `FW_JUMP=y` in platform `config.mk` + +Config Options +-------------- + +We need more config details for **FW_JUMP** firmware to work +correctly. These config details can be passed as paramter to +top-level `make` or can be set in platform `config.mk`. + +Following are the config options for **FW_JUMP** firmware: + +* **FW_JUMP_ADDR** - Address where next booting stage is +located. This is a mandatory config option and will result +in compile error if not provided. +* **FW_JUMP_FDT_ADDR** - Address where FDT passed by prior +booting stage will be placed before passing to next booting +stage. If this option is not provided then firmware will pass +zero as FDT address to next booting stage. \ No newline at end of file diff --git a/docs/firmware/fw_payload.md b/docs/firmware/fw_payload.md new file mode 100644 index 00000000..2fab092c --- /dev/null +++ b/docs/firmware/fw_payload.md @@ -0,0 +1,51 @@ +OpenSBI Firmware with Payload (FW_PAYLOAD) +========================================== + +The **OpenSBI firmware with Payload (FW_PAYLOAD)** is a +firmware which includes next booting stage binary (i.e. +bootloader/kernel) as payload in the OpenSBI firmware binary. + +This **FW_PAYLOAD** firmware is particularly useful when +booting stage prior to OpenSBI firmware is not capable of +loading OpenSBI firmware and booting stage after OpenSBI +firmware separately. + +It is also possible that booting stage prior to OpenSBI +firmware does not pass **flattened device tree (FDT)**. In +this case, we have provision to embed FDT in .text section +of **FW_PAYLOAD** firmware. + +How to Enable? +-------------- + +The **FW_PAYLOAD** firmware can be enabled by any of the +following methods: + +1. Passing `FW_PAYLOAD=y` command-line parameter to +top-level `make` +2. Setting `FW_PAYLOAD=y` in platform `config.mk` + +Config Options +-------------- + +We need more config details for **FW_PAYLOAD** firmware to +work correctly. These config details can be passed as paramter +to top-level `make` or can be set in platform `config.mk`. + +Following are the config options for **FW_PAYLOAD** firmware: + +* **FW_PAYLOAD_OFFSET** - Offset from FW_TEXT_BASE where next +booting stage binary will be linked to **FW_PAYLOAD** firmware. +This is a mandatory config option and will result in compile +error if not provided. +* **FW_PAYLOAD_PATH** - Path to the next booting stage binary. +If this option is not provided then **`while (1)`** is taken as +payload. +* **FW_PAYLOAD_FDT_PATH** - Path to the FDT binary to be embedded +in .text section of **FW_PAYLOAD** firmware. If this option is +not provided then firmware will expect FDT to be passed by prior +booting stage. +* **FW_PAYLOAD_FDT_ADDR** - Address where FDT passed by prior +booting stage (or embedded FDT) will be placed before passing +to next booting stage. If this option is not provided then +firmware will pass zero as FDT address to next booting stage. \ No newline at end of file diff --git a/firmware/fw_common.S b/firmware/fw_common.S new file mode 100644 index 00000000..a2685cf2 --- /dev/null +++ b/firmware/fw_common.S @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + + .align 3 + .section .entry, "ax", %progbits + .globl _start + .globl _start_warm +_start: + /* + * Jump to warm-boot if this is not the first core booting, + * that is, for mhartid != 0 + */ + csrr a6, mhartid + blt zero, a6, _wait_for_boot_hart + + /* Zero-out BSS */ + la a4, _bss_start + la a5, _bss_end +_bss_zero: + REG_S zero, (a4) + add a4, a4, __SIZEOF_POINTER__ + blt a4, a5, _bss_zero + + /* Override pervious arg1 */ + add s0, a0, zero + add s1, a1, zero + call fw_prev_arg1 + add t1, a0, zero + add a0, s0, zero + add a1, s1, zero + beqz t1, _prev_arg1_override_done + add a1, t1, zero +_prev_arg1_override_done: + + /* + * Relocate Flatened Device Tree (FDT) + * source FDT address = previous arg1 + * destination FDT address = next arg1 + * + * Note: We will preserve a0 and a1 passed by + * previous booting stage. + */ + beqz a1, _fdt_reloc_done + /* Mask values in a3 and a4 */ + li a3, ~0xf + li a4, 0xff + /* t1 = destination FDT start address */ + add s0, a0, zero + add s1, a1, zero + call fw_next_arg1 + add t1, a0, zero + add a0, s0, zero + add a1, s1, zero + beqz t1, _fdt_reloc_done + and t1, t1, a3 + /* t0 = source FDT start address */ + add t0, a1, zero + and t0, t0, a3 + /* t2 = source FDT size in big-endian */ + lwu t2, 4(t0) + /* t3 = bit[15:8] of FDT size */ + add t3, t2, zero + srli t3, t3, 16 + and t3, t3, a4 + slli t3, t3, 8 + /* t4 = bit[23:16] of FDT size */ + add t4, t2, zero + srli t4, t4, 8 + and t4, t4, a4 + slli t4, t4, 16 + /* t5 = bit[31:24] of FDT size */ + add t5, t2, zero + and t5, t5, a4 + slli t5, t5, 24 + /* t2 = bit[7:0] of FDT size */ + srli t2, t2, 24 + and t2, t2, a4 + /* t2 = FDT size in little-endian */ + or t2, t2, t3 + or t2, t2, t4 + or t2, t2, t5 + /* t2 = destination FDT end address */ + add t2, t1, t2 + /* FDT copy loop */ + ble t2, t1, _fdt_reloc_done +_fdt_reloc_again: + REG_L t3, 0(t0) + REG_S t3, 0(t1) + add t0, t0, __SIZEOF_POINTER__ + add t1, t1, __SIZEOF_POINTER__ + blt t1, t2, _fdt_reloc_again +_fdt_reloc_done: + + /* Update boot hart flag */ + la a4, _boot_hart_done + li a5, 1 + REG_S a5, (a4) + j _wait_for_boot_hart + + .align 3 +_boot_hart_done: + RISCV_PTR 0 + .align 3 + + /* Wait for boot hart */ +_wait_for_boot_hart: + la a4, _boot_hart_done + REG_L a5, (a4) + beqz a5, _wait_for_boot_hart + +_start_warm: + /* Disable and clear all interrupts */ + csrw mie, zero + csrw mip, zero + + /* set MSIE bit to receive IPI */ + li a2, MIP_MSIP + csrw mie, a2 + /* HART ID should be withing expected limit */ + csrr a6, mhartid + li a5, PLAT_HART_COUNT + bge a6, a5, _start_hang + + /* Setup scratch space */ + li a5, PLAT_HART_STACK_SIZE + la tp, _stack_end + mul a5, a5, a6 + sub tp, tp, a5 + li a5, RISCV_SCRATCH_SIZE + sub tp, tp, a5 + csrw mscratch, tp + + /* Initialize scratch space */ + REG_S zero, RISCV_SCRATCH_TMP0_OFFSET(tp) + la a4, _fw_start + la a5, _fw_end + sub a5, a5, a4 + REG_S a4, RISCV_SCRATCH_FW_START_OFFSET(tp) + REG_S a5, RISCV_SCRATCH_FW_SIZE_OFFSET(tp) + /* Note: fw_next_arg1() uses a0, a1, and ra */ + call fw_next_arg1 + REG_S a0, RISCV_SCRATCH_NEXT_ARG1_OFFSET(tp) + /* Note: fw_next_addr() uses a0, a1, and ra */ + call fw_next_addr + REG_S a0, RISCV_SCRATCH_NEXT_ADDR_OFFSET(tp) + li a4, PRV_S + REG_S a4, RISCV_SCRATCH_NEXT_MODE_OFFSET(tp) + la a4, _start_warm + REG_S a4, RISCV_SCRATCH_WARMBOOT_ADDR_OFFSET(tp) + la a4, platform + REG_S a4, RISCV_SCRATCH_PLATFORM_ADDR_OFFSET(tp) + la a4, _hartid_to_scratch + REG_S a4, RISCV_SCRATCH_HARTID_TO_SCRATCH_OFFSET(tp) + REG_S zero, RISCV_SCRATCH_IPI_TYPE_OFFSET(tp) + + /* Setup stack */ + add sp, tp, zero + + /* Setup trap handler */ + la a4, _trap_handler + csrw mtvec, a4 + + /* Initialize SBI runtime */ + csrr a0, mscratch + call sbi_init + + /* We don't expect to reach here hence just hang */ + j _start_hang + + .align 3 + .section .entry, "ax", %progbits + .globl _hartid_to_scratch +_hartid_to_scratch: + add sp, sp, -(2 * __SIZEOF_POINTER__) + REG_S a1, (sp) + REG_S a2, (__SIZEOF_POINTER__)(sp) + li a1, PLAT_HART_STACK_SIZE + la a2, _stack_end + mul a1, a1, a0 + sub a2, a2, a1 + li a1, RISCV_SCRATCH_SIZE + sub a0, a2, a1 + REG_L a1, (sp) + REG_L a2, (__SIZEOF_POINTER__)(sp) + add sp, sp, (2 * __SIZEOF_POINTER__) + ret + + .align 3 + .section .entry, "ax", %progbits + .globl _start_hang +_start_hang: + wfi + j _start_hang + + .align 3 + .section .entry, "ax", %progbits + .globl _trap_handler +_trap_handler: + /* Swap SP and MSCRATCH */ + csrrw sp, mscratch, sp + + /* Setup exception stack */ + add sp, sp, -(RISCV_TRAP_REGS_SIZE) + + /* Save RA, T0, T1, and T2 */ + REG_S ra, RISCV_TRAP_REGS_OFFSET(ra)(sp) + REG_S t0, RISCV_TRAP_REGS_OFFSET(t0)(sp) + REG_S t1, RISCV_TRAP_REGS_OFFSET(t1)(sp) + REG_S t2, RISCV_TRAP_REGS_OFFSET(t2)(sp) + + /* Save original SP and restore MSCRATCH */ + add t0, sp, RISCV_TRAP_REGS_SIZE + csrrw t0, mscratch, t0 + REG_S t0, RISCV_TRAP_REGS_OFFSET(sp)(sp) + + /* Save MEPC and MSTATUS CSRs */ + csrr t0, mepc + csrr t1, mstatus + + /* + * Note: Fast path trap handling can be done here + * using SP, RA, T0, T1, and T2 registers where + * T0 <- MEPC + * T1 <- MSTATUS + */ + + /* Save MEPC and MSTATUS CSRs */ + REG_S t0, RISCV_TRAP_REGS_OFFSET(mepc)(sp) + REG_S t1, RISCV_TRAP_REGS_OFFSET(mstatus)(sp) + + /* Save all general regisers except SP, RA, T0, T1, and T2 */ + REG_S zero, RISCV_TRAP_REGS_OFFSET(zero)(sp) + REG_S gp, RISCV_TRAP_REGS_OFFSET(gp)(sp) + REG_S tp, RISCV_TRAP_REGS_OFFSET(tp)(sp) + REG_S s0, RISCV_TRAP_REGS_OFFSET(s0)(sp) + REG_S s1, RISCV_TRAP_REGS_OFFSET(s1)(sp) + REG_S a0, RISCV_TRAP_REGS_OFFSET(a0)(sp) + REG_S a1, RISCV_TRAP_REGS_OFFSET(a1)(sp) + REG_S a2, RISCV_TRAP_REGS_OFFSET(a2)(sp) + REG_S a3, RISCV_TRAP_REGS_OFFSET(a3)(sp) + REG_S a4, RISCV_TRAP_REGS_OFFSET(a4)(sp) + REG_S a5, RISCV_TRAP_REGS_OFFSET(a5)(sp) + REG_S a6, RISCV_TRAP_REGS_OFFSET(a6)(sp) + REG_S a7, RISCV_TRAP_REGS_OFFSET(a7)(sp) + REG_S s2, RISCV_TRAP_REGS_OFFSET(s2)(sp) + REG_S s3, RISCV_TRAP_REGS_OFFSET(s3)(sp) + REG_S s4, RISCV_TRAP_REGS_OFFSET(s4)(sp) + REG_S s5, RISCV_TRAP_REGS_OFFSET(s5)(sp) + REG_S s6, RISCV_TRAP_REGS_OFFSET(s6)(sp) + REG_S s7, RISCV_TRAP_REGS_OFFSET(s7)(sp) + REG_S s8, RISCV_TRAP_REGS_OFFSET(s8)(sp) + REG_S s9, RISCV_TRAP_REGS_OFFSET(s9)(sp) + REG_S s10, RISCV_TRAP_REGS_OFFSET(s10)(sp) + REG_S s11, RISCV_TRAP_REGS_OFFSET(s11)(sp) + REG_S t3, RISCV_TRAP_REGS_OFFSET(t3)(sp) + REG_S t4, RISCV_TRAP_REGS_OFFSET(t4)(sp) + REG_S t5, RISCV_TRAP_REGS_OFFSET(t5)(sp) + REG_S t6, RISCV_TRAP_REGS_OFFSET(t6)(sp) + + /* Call C routine */ + add a0, sp, zero + csrr a1, mscratch + call sbi_trap_handler + + /* Restore all general regisers except SP, RA, T0, T1, T2, and T3 */ + REG_L gp, RISCV_TRAP_REGS_OFFSET(gp)(sp) + REG_L tp, RISCV_TRAP_REGS_OFFSET(tp)(sp) + REG_L s0, RISCV_TRAP_REGS_OFFSET(s0)(sp) + REG_L s1, RISCV_TRAP_REGS_OFFSET(s1)(sp) + REG_L a0, RISCV_TRAP_REGS_OFFSET(a0)(sp) + REG_L a1, RISCV_TRAP_REGS_OFFSET(a1)(sp) + REG_L a2, RISCV_TRAP_REGS_OFFSET(a2)(sp) + REG_L a3, RISCV_TRAP_REGS_OFFSET(a3)(sp) + REG_L a4, RISCV_TRAP_REGS_OFFSET(a4)(sp) + REG_L a5, RISCV_TRAP_REGS_OFFSET(a5)(sp) + REG_L a6, RISCV_TRAP_REGS_OFFSET(a6)(sp) + REG_L a7, RISCV_TRAP_REGS_OFFSET(a7)(sp) + REG_L s2, RISCV_TRAP_REGS_OFFSET(s2)(sp) + REG_L s3, RISCV_TRAP_REGS_OFFSET(s3)(sp) + REG_L s4, RISCV_TRAP_REGS_OFFSET(s4)(sp) + REG_L s5, RISCV_TRAP_REGS_OFFSET(s5)(sp) + REG_L s6, RISCV_TRAP_REGS_OFFSET(s6)(sp) + REG_L s7, RISCV_TRAP_REGS_OFFSET(s7)(sp) + REG_L s8, RISCV_TRAP_REGS_OFFSET(s8)(sp) + REG_L s9, RISCV_TRAP_REGS_OFFSET(s9)(sp) + REG_L s10, RISCV_TRAP_REGS_OFFSET(s10)(sp) + REG_L s11, RISCV_TRAP_REGS_OFFSET(s11)(sp) + REG_L t3, RISCV_TRAP_REGS_OFFSET(t3)(sp) + REG_L t4, RISCV_TRAP_REGS_OFFSET(t4)(sp) + REG_L t5, RISCV_TRAP_REGS_OFFSET(t5)(sp) + REG_L t6, RISCV_TRAP_REGS_OFFSET(t6)(sp) + + /* Load T0 and T1 with MEPC and MSTATUS */ + REG_L t0, RISCV_TRAP_REGS_OFFSET(mepc)(sp) + REG_L t1, RISCV_TRAP_REGS_OFFSET(mstatus)(sp) + + /* + * Note: Jump here after fast trap handling + * using SP, RA, T0, T1, and T2 + * T0 <- MEPC + * T1 <- MSTATUS + */ + + /* Restore MEPC and MSTATUS CSRs */ + csrw mepc, t0 + csrw mstatus, t1 + + /* Restore RA, T0, T1, and T2 */ + REG_L ra, RISCV_TRAP_REGS_OFFSET(ra)(sp) + REG_L t0, RISCV_TRAP_REGS_OFFSET(t0)(sp) + REG_L t1, RISCV_TRAP_REGS_OFFSET(t1)(sp) + REG_L t2, RISCV_TRAP_REGS_OFFSET(t2)(sp) + + /* Restore SP */ + REG_L sp, RISCV_TRAP_REGS_OFFSET(sp)(sp) + + mret diff --git a/firmware/fw_common.ldS b/firmware/fw_common.ldS new file mode 100644 index 00000000..3761d62f --- /dev/null +++ b/firmware/fw_common.ldS @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * + * SPDX-License-Identifier: BSD-2-Clause + */ + + . = FW_TEXT_START; + + PROVIDE(_fw_start = .); + + . = ALIGN(0x1000); /* Need this to create proper sections */ + + /* Beginning of the code section */ + + .text : + { + PROVIDE(_text_start = .); + *(.entry) + *(.text) + . = ALIGN(8); + PROVIDE(_text_end = .); + } + + . = ALIGN(0x1000); /* Ensure next section is page aligned */ + + /* End of the code sections */ + + /* Beginning of the read-only data sections */ + + . = ALIGN(0x1000); /* Ensure next section is page aligned */ + + .rodata : + { + PROVIDE(_rodata_start = .); + *(.rodata .rodata.*) + . = ALIGN(8); + PROVIDE(_rodata_end = .); + } + + /* End of the read-only data sections */ + + /* Beginning of the read-write data sections */ + + . = ALIGN(0x1000); /* Ensure next section is page aligned */ + + .data : + { + PROVIDE(_data_start = .); + + *(.data) + *(.data.*) + *(.readmostly.data) + *(*.data) + . = ALIGN(8); + + PROVIDE(_data_end = .); + } + + . = ALIGN(0x1000); /* Ensure next section is page aligned */ + + .stack : + { + PROVIDE(_stack_start = .); + *(.stack) + *(.stack.*) + . = . + (PLAT_HART_STACK_SIZE * PLAT_HART_COUNT); + . = ALIGN(8); + PROVIDE(_stack_end = .); + } + + . = ALIGN(0x1000); /* Ensure next section is page aligned */ + + .bss : + { + PROVIDE(_bss_start = .); + *(.bss) + *(.bss.*) + . = ALIGN(8); + PROVIDE(_bss_end = .); + } + + /* End of the read-write data sections */ + + . = ALIGN(0x1000); /* Need this to create proper sections */ + + PROVIDE(_fw_end = .); diff --git a/firmware/fw_jump.S b/firmware/fw_jump.S new file mode 100644 index 00000000..d05d87fe --- /dev/null +++ b/firmware/fw_jump.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "fw_common.S" + + .align 3 + .section .entry, "ax", %progbits + .global fw_prev_arg1 +fw_prev_arg1: + /* We return previous arg1 in 'a0' */ + add a0, zero, zero + ret + + .align 3 + .section .entry, "ax", %progbits + .global fw_next_arg1 +fw_next_arg1: + /* We return next arg1 in 'a0' */ +#ifdef FW_JUMP_FDT_ADDR + li a0, FW_JUMP_FDT_ADDR +#else + add a0, zero, zero +#endif + ret + + .align 3 + .section .entry, "ax", %progbits + .global fw_next_addr +fw_next_addr: + /* We return next address in 'a0' */ + la a0, _jump_addr + REG_L a0, (a0) + ret + +#ifndef FW_JUMP_ADDR +#error "Must define FW_JUMP_ADDR" +#endif + + .align 3 + .section .entry, "ax", %progbits +_jump_addr: + RISCV_PTR FW_JUMP_ADDR diff --git a/firmware/fw_jump.elf.ldS b/firmware/fw_jump.elf.ldS new file mode 100644 index 00000000..dfffbf60 --- /dev/null +++ b/firmware/fw_jump.elf.ldS @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +OUTPUT_ARCH(riscv) +ENTRY(_start) + +SECTIONS +{ + #include "fw_common.ldS" +} diff --git a/firmware/fw_payload.S b/firmware/fw_payload.S new file mode 100644 index 00000000..b6f3cb96 --- /dev/null +++ b/firmware/fw_payload.S @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "fw_common.S" + + .align 3 + .section .entry, "ax", %progbits + .global fw_prev_arg1 +fw_prev_arg1: + /* We return previous arg1 in 'a0' */ +#ifdef FW_PAYLOAD_FDT_PATH + la a0, fdt_bin +#else + add a0, zero, zero +#endif + ret + + .align 3 + .section .entry, "ax", %progbits + .global fw_next_arg1 +fw_next_arg1: + /* We return next arg1 in 'a0' */ +#ifdef FW_PAYLOAD_FDT_ADDR + li a0, FW_PAYLOAD_FDT_ADDR +#else + add a0, zero, zero +#endif + ret + + .align 3 + .section .entry, "ax", %progbits + .global fw_next_addr +fw_next_addr: + /* We return next address in 'a0' */ + la a0, payload_bin + ret + +#define str(s) #s +#define stringify(s) str(s) + +#ifdef FW_PAYLOAD_FDT_PATH + .align 3 + .section .text, "ax", %progbits + .globl fdt_bin +fdt_bin: + .incbin stringify(FW_PAYLOAD_FDT_PATH) +#endif + + .section .payload, "ax", %progbits + .globl payload_bin +payload_bin: +#ifndef FW_PAYLOAD_PATH + wfi + j payload_bin +#else + .incbin stringify(FW_PAYLOAD_PATH) +#endif diff --git a/firmware/fw_payload.elf.ldS b/firmware/fw_payload.elf.ldS new file mode 100644 index 00000000..201338b5 --- /dev/null +++ b/firmware/fw_payload.elf.ldS @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +OUTPUT_ARCH(riscv) +ENTRY(_start) + +SECTIONS +{ + #include "fw_common.ldS" + + . = FW_TEXT_START + FW_PAYLOAD_OFFSET; + + .payload : + { + PROVIDE(_payload_start = .); + *(.payload) + . = ALIGN(8); + PROVIDE(_payload_end = .); + } +} diff --git a/firmware/objects.mk b/firmware/objects.mk new file mode 100644 index 00000000..9bed733d --- /dev/null +++ b/firmware/objects.mk @@ -0,0 +1,39 @@ +# +# Copyright (c) 2018 Western Digital Corporation or its affiliates. +# +# Authors: +# Anup Patel +# +# SPDX-License-Identifier: BSD-2-Clause +# + +firmware-cppflags-y = +firmware-cflags-y = +firmware-asflags-y = +firmware-ldflags-y = + +ifdef FW_TEXT_START +firmware-cppflags-y += -DFW_TEXT_START=$(FW_TEXT_START) +endif + +firmware-bins-$(FW_JUMP) += fw_jump.bin +ifdef FW_JUMP_ADDR +firmware-cppflags-$(FW_JUMP) += -DFW_JUMP_ADDR=$(FW_JUMP_ADDR) +endif +ifdef FW_JUMP_FDT_ADDR +firmware-cppflags-$(FW_JUMP) += -DFW_JUMP_FDT_ADDR=$(FW_JUMP_FDT_ADDR) +endif + +firmware-bins-$(FW_PAYLOAD) += fw_payload.bin +ifdef FW_PAYLOAD_PATH +firmware-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_PATH=$(FW_PAYLOAD_PATH) +endif +ifdef FW_PAYLOAD_OFFSET +firmware-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_OFFSET=$(FW_PAYLOAD_OFFSET) +endif +ifdef FW_PAYLOAD_FDT_PATH +firmware-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_PATH=$(FW_PAYLOAD_FDT_PATH) +endif +ifdef FW_PAYLOAD_FDT_ADDR +firmware-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR) +endif -- cgit v1.3.1