boot.c (2984B)
1 // Copyright 2022, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0 3 4 #include <hw/riscv.h> 5 #include <hw/context.h> 6 #include <hw/intrinsics.h> 7 #include <hw/debug.h> 8 9 #include <hw/platform.h> 10 #include <hw/litex.h> 11 12 #include <string.h> 13 14 #include "boot.h" 15 16 eframe_t *EF; 17 volatile int STOP = 0; 18 19 // we expect the supervisor program to be in memory after the end of the bootloader 20 #define SVC_ENTRY (DRAM_BASE + BOOTLOADER_SIZE) 21 22 23 #define uart_rd(a) io_rd32(UART0_BASE + LX_UART_ ## a) 24 #define uart_wr(a,v) io_wr32(UART0_BASE + LX_UART_ ## a, v) 25 26 static char cmdbuf[128]; 27 static unsigned cmdlen = 0; 28 29 void console_char(uint32_t ch) { 30 if ((ch == '\r') || (ch == '\n')) { 31 xputs("\r\n"); 32 cmdbuf[cmdlen] = 0; 33 // rd32safe, rd8safe modify MTVEC/MSTATUS 34 // ensure they're saved and restored here 35 uint32_t status = csr_read(CSR_MSTATUS); 36 console_line(cmdbuf); 37 csr_write(CSR_MSTATUS, status); 38 csr_write(CSR_MTVEC, ((uintptr_t) mach_exception_entry) ); 39 cmdlen = 0; 40 return; 41 } 42 if ((ch == 8) || (ch == 127)) { 43 if (cmdlen > 0) { 44 xputs("\x08 \x08"); 45 cmdlen--; 46 } else { 47 xputc(7); 48 } 49 return; 50 } 51 if ((ch < ' ') || (ch > 127)) { 52 return; 53 } 54 if (cmdlen == (sizeof(cmdbuf) - 1)) { 55 xputc(7); 56 return; 57 } 58 cmdbuf[cmdlen++] = ch; 59 xputc(ch); 60 } 61 62 void mach_exception_handler(eframe_t *ef) { 63 uint32_t cause = csr_read(CSR_MCAUSE); 64 65 if (cause == 0x8000000b) { 66 EF = ef; 67 do { 68 while (uart_rd(RXEMPTY) == 0) { 69 unsigned ch = uart_rd(RX); 70 uart_wr(EV_PENDING, LX_UART_EVb_RX); 71 console_char(ch); 72 } 73 } while (STOP); 74 return; 75 } 76 77 xprintf("\n** MACHINE EXCEPTION **\n"); 78 xprint_m_exception(ef); 79 xprintf("\nHALT\n"); 80 for (;;) ; 81 } 82 83 // interrupts and exceptions to delegate to supervisor mode 84 #define INT_LIST (INTb_SVC_SW|INTb_SVC_TIMER|INTb_SVC_EXTERN) 85 //#define EXC_LIST (EXCb_ECALL_UMODE) 86 #define EXC_LIST (0xFFFF) 87 88 void start(uint32_t hartid, uint32_t fdt) { 89 xprintf("\n** Frobozz Magic Bootloader v0.2 **\n\n"); 90 91 int qemu = (csr_read(CSR_MVENDORID) == 0); 92 93 // set mach exception vector and stack pointer 94 csr_write(CSR_MTVEC, ((uintptr_t) mach_exception_entry) ); 95 96 // use the free ram below the supervisor entry as our exception stack 97 csr_write(CSR_MSCRATCH, SVC_ENTRY); 98 99 // QEMU currently emulates memory protection, which we must appease 100 if (qemu) { 101 // U/S allow access to all memory 102 csr_write(CSR_PMPCFG(0), PMP_CFG_A_TOR | PMP_CFG_X | PMP_CFG_W | PMP_CFG_R); 103 csr_write(CSR_PMPADDR(0), 0xFFFFFFFF); 104 } 105 106 // delegate interrupts and exceptions 107 csr_set(CSR_MIDELEG, INT_LIST); 108 csr_set(CSR_MEDELEG, EXC_LIST); 109 110 // set previous status to S_MODE, previous interrupt status ENABLED 111 csr_write(CSR_MSTATUS, (PRIV_S << MSTATUS_MPP_SHIFT) | MSTATUS_MPIE); 112 113 xprintf("SVC ENTRY @0x%08x\n\n", SVC_ENTRY); 114 115 uart_wr(EV_ENABLE, LX_UART_EVb_RX); 116 uart_wr(EV_PENDING, LX_UART_EVb_RX); 117 csr_write(CSR_M_INTC_ENABLE, UART0_IRQb); 118 csr_set(CSR_MIE, INTb_MACH_EXTERN); 119 120 exit_mode_m(hartid, fdt, SVC_ENTRY, 0); 121 122 } 123