console.c (4772B)
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/intrinsics.h> 6 #include <hw/context.h> 7 #include <hw/debug.h> 8 #include "boot.h" 9 #include <string.h> 10 11 int atoi(const char *s) { 12 unsigned c; 13 int n = 0; 14 while ((c = *s++)) { 15 if ((c >= '0') && (c <= '9')) { 16 n = n * 10 + (c - '0'); 17 } else { 18 break; 19 } 20 } 21 return n; 22 } 23 24 uint32_t atox(const char *s) { 25 uint32_t n = 0; 26 uint32_t c; 27 while ((c = *s++)) { 28 switch (c) { 29 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 30 c = c - 'a' + 10; 31 break; 32 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': 33 c = c - 'A' + 10; 34 break; 35 case '0': case '1': case '2': case '3': case '4': 36 case '5': case '6': case '7': case '8': case '9': 37 c = c - '0'; 38 break; 39 default: 40 return n; 41 } 42 n = (n << 4) | c; 43 } 44 return n; 45 } 46 47 extern eframe_t* EF; 48 extern volatile int STOP; 49 50 51 // args: x hex number 52 // i integer number 53 // s string 54 typedef struct { 55 const char* name; 56 const char* args; 57 const char* help; 58 void *fn; 59 } console_cmd_t; 60 61 void do_regs(void) { 62 eframe_t* ef = EF; 63 xprintf("pc %08x ra %08x sp %08x gp %08x sstatus %08x\n", 64 ef->pc, ef->ra, ef->sp, ef->gp, csr_read(CSR_SSTATUS)); 65 xprintf("tp %08x t0 %08x t1 %08x t2 %08x scause %08x\n", 66 ef->tp, ef->t0, ef->t1, ef->t2, csr_read(CSR_SCAUSE)); 67 xprintf("fp %08x s1 %08x a0 %08x a1 %08x stval %08x\n", 68 ef->s0, ef->s1, ef->a0, ef->a1, csr_read(CSR_STVAL)); 69 xprintf("a2 %08x a3 %08x a4 %08x a5 %08x stvec %08x\n", 70 ef->a2, ef->a3, ef->a4, ef->a5, csr_read(CSR_STVEC)); 71 xprintf("a6 %08x a7 %08x s2 %08x s3 %08x sepc %08x\n", 72 ef->a6, ef->a7, ef->s2, ef->s3, csr_read(CSR_SEPC)); 73 xprintf("s4 %08x s5 %08x s6 %08x s7 %08x sscratch %08x\n", 74 ef->s4, ef->s5, ef->s6, ef->s7, csr_read(CSR_SSCRATCH)); 75 xprintf("s8 %08x s9 %08x 10 %08x 11 %08x satp %08x\n", 76 ef->s8, ef->s9, ef->s10, ef->s11, csr_read(CSR_SATP)); 77 xprintf("t3 %08x t4 %08x t5 %08x t6 %08x sip %08x\n", 78 ef->t3, ef->t4, ef->t5, ef->t6, csr_read(CSR_SIP)); 79 } 80 81 void do_help(void); 82 83 void do_dw(unsigned n, unsigned addr, unsigned count) { 84 if (n < 2) count = 1; 85 if (count > 1024) count = 1024; 86 87 n = 0; 88 while (n < count) { 89 if ((n & 3) == 0) { 90 xprintf("\n%08x:", addr); 91 } 92 xprintf(" %08x", rd32safe(addr)); 93 addr += 4; 94 n++; 95 } 96 if ((n & 3) == 0) { 97 xprintf("\n"); 98 } 99 } 100 101 void do_db(unsigned n, unsigned addr, int count) { 102 char txt[17]; 103 if (count < 0) { 104 return; 105 } 106 txt[16] = 0; 107 while (count > 0) { 108 xprintf("%08x:", addr); 109 for (int i = 0; i < 16; i++) { 110 uint32_t c; 111 if (i < count) { 112 c = rd8safe(addr + i) & 0xFF; 113 xprintf(" %02x", c); 114 if ((c < ' ') || (c > 126)) c = '.'; 115 } else { 116 xprintf(" "); 117 c = ' '; 118 } 119 txt[i] = c; 120 } 121 xprintf(" %s\n", txt); 122 addr += 16; 123 count -= 16; 124 } 125 } 126 127 void do_stop(void) { STOP = 1; } 128 void do_cont(void) { STOP = 0; }; 129 130 console_cmd_t CMDS[] = { 131 { "help", "", "help", do_help }, 132 { "regs", "", "dump registers", do_regs }, 133 { "dw", "xx", "dump words <addr> <count>", do_dw }, 134 { "db", "xx", "dump bytes <addr> <count>", do_db }, 135 { "stop", "", "stop execution", do_stop }, 136 { "cont", "", "continue execution", do_cont }, 137 }; 138 139 void do_help(void) { 140 for (unsigned n = 0; n < (sizeof(CMDS)/sizeof(CMDS[0])); n++) { 141 xprintf("%-16s %s\n", CMDS[n].name, CMDS[n].help); 142 } 143 } 144 145 void console_cmd(console_cmd_t *cmd, char *args[], unsigned argc) { 146 uintptr_t argx[4]; 147 unsigned max = strlen(cmd->args); 148 149 if ((argc > max) || (argc > 4)) { 150 xprintf("error: too many arguments\n"); 151 return; 152 } 153 154 memset(argx, 0, sizeof(argx)); 155 for (unsigned n = 0; n < max; n++) { 156 switch (cmd->args[n]) { 157 case 'x': 158 argx[n] = (n < argc) ? atox(args[n]) : 0; 159 break; 160 case 'i': 161 argx[n] = (n < argc) ? atoi(args[n]) : 0; 162 break; 163 case 's': 164 argx[n] = (n < argc) ? (uintptr_t) args[n] : (uintptr_t) ""; 165 break; 166 default: 167 xprintf("error: internal: bad args '%s'\n", cmd->args); 168 return; 169 } 170 } 171 172 console_call_cmd(cmd->fn, argx[0], argx[1], argx[2], argx[3], argc); 173 } 174 175 #define MAXTOK 16 176 177 void console_line(char* line) { 178 char *token[MAXTOK]; 179 unsigned toklen = 0; 180 181 while (toklen < MAXTOK) { 182 while(*line == ' ') { 183 if (*line == 0) { 184 goto done; 185 } 186 *line++ = 0; 187 } 188 token[toklen] = line; 189 while (*line != ' ') { 190 if (*line == 0) { 191 if (token[toklen] != line) { 192 *line = 0; 193 toklen++; 194 } 195 goto done; 196 } 197 line++; 198 } 199 toklen++; 200 } 201 done: 202 if (toklen) { 203 for (unsigned n = 0; n < (sizeof(CMDS)/sizeof(CMDS[0])); n++) { 204 if (!strcmp(CMDS[n].name, token[0])) { 205 console_cmd(CMDS + n, token + 1, toklen - 1); 206 goto prompt; 207 } 208 } 209 xprintf("unknown command '%s'\n", token[0]); 210 } 211 prompt: 212 xputs("monitor> "); 213 } 214 215 216