| /* |
| * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| * 02110-1301, USA. |
| * |
| * You can also choose to distribute this program under the terms of |
| * the Unmodified Binary Distribution Licence (as given in the file |
| * COPYING.UBDL), provided that you have satisfied its requirements. |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ) |
| |
| /** @file |
| * |
| * SBI position-independent executable prefix |
| * |
| */ |
| |
| .section ".note.GNU-stack", "", @progbits |
| .text |
| |
| /* SBI debug console extension */ |
| #define SBI_DBCN ( ( 'D' << 24 ) | ( 'B' << 16 ) | ( 'C' << 8 ) | 'N' ) |
| #define SBI_DBCN_WRITE 0x00 |
| |
| /* SBI system reset extension */ |
| #define SBI_SRST ( ( 'S' << 24 ) | ( 'R' << 16 ) | ( 'S' << 8 ) | 'T' ) |
| #define SBI_SRST_SYSTEM_RESET 0x00 |
| #define SBI_RESET_COLD 0x00000001 |
| |
| /* Relative relocation type */ |
| #define R_RISCV_RELATIVE 3 |
| |
| /* Layout of a relocation record */ |
| .struct 0 |
| rela_offset: .space ( __riscv_xlen / 8 ) |
| rela_type: .space ( __riscv_xlen / 8 ) |
| rela_addend: .space ( __riscv_xlen / 8 ) |
| rela_len: |
| .previous |
| |
| /* |
| * Display progress message via debug console |
| */ |
| .macro progress message |
| #ifndef NDEBUG |
| .section ".prefix.data", "aw", @progbits |
| progress_\@: |
| .ascii "\message" |
| .equ progress_\@_len, . - progress_\@ |
| .size progress_\@, . - progress_\@ |
| .previous |
| li a7, SBI_DBCN |
| li a6, SBI_DBCN_WRITE |
| li a0, progress_\@_len |
| la a1, progress_\@ |
| mv a2, zero |
| ecall |
| #endif |
| .endm |
| |
| /* |
| * SBI entry point |
| */ |
| .section ".prefix", "ax", @progbits |
| .org 0 |
| .globl _sbi_start |
| _sbi_start: |
| /* Preserve arguments */ |
| mv s0, a0 |
| mv s1, a1 |
| progress "\nSBI->iPXE" |
| |
| /* Apply dynamic relocations */ |
| la t0, _reloc |
| la t1, _ereloc |
| la t2, _sbi_start |
| 1: /* Read relocation record */ |
| LOADN t3, rela_offset(t0) |
| LOADN t4, rela_type(t0) |
| LOADN t5, rela_addend(t0) |
| /* Check relocation type */ |
| addi t4, t4, -R_RISCV_RELATIVE |
| bnez t4, 2f |
| /* Apply relocation */ |
| add t3, t3, t2 |
| add t5, t5, t2 |
| STOREN t5, (t3) |
| 2: /* Loop */ |
| addi t0, t0, rela_len |
| blt t0, t1, 1b |
| progress " .reloc" |
| |
| /* Zero the bss */ |
| la t0, _bss |
| la t1, _ebss |
| 1: STOREN zero, (t0) |
| addi t0, t0, ( __riscv_xlen / 8 ) |
| blt t0, t1, 1b |
| progress " .bss" |
| |
| /* Set up stack */ |
| la sp, _estack |
| progress " .stack" |
| |
| /* Store boot hart */ |
| la t0, boot_hart |
| STOREN s0, (t0) |
| |
| /* Register device tree */ |
| mv a0, s1 |
| call register_fdt |
| |
| /* Call main program */ |
| progress "\n\n" |
| call main |
| |
| /* We have no return path, since the M-mode SBI implementation |
| * will have jumped to us by setting our start address in MEPC |
| * and issuing an MRET instruction. |
| * |
| * Attempt a system reset, since there is nothing else we can |
| * viably do at this point. |
| */ |
| progress "\niPXE->SBI reset\n" |
| li a7, SBI_SRST |
| li a6, SBI_SRST_SYSTEM_RESET |
| li a0, SBI_RESET_COLD |
| mv a1, zero |
| ecall |
| |
| /* If reset failed, lock the system */ |
| progress "(reset failed)\n" |
| 1: wfi |
| j 1b |
| .size _sbi_start, . - _sbi_start |
| |
| /* File split information for the compressor */ |
| .section ".zinfo", "a", @progbits |
| .ascii "COPY" |
| .word 0 |
| .word _sbi_filesz |
| .word 1 |