soc/software/bios/main: revision command becomes ident
[litex.git] / litex / soc / software / bios / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <console.h>
4 #include <string.h>
5 #include <uart.h>
6 #include <system.h>
7 #include <id.h>
8 #include <irq.h>
9 #include <crc.h>
10
11 #include <generated/csr.h>
12 #include <generated/mem.h>
13 #include <net/microudp.h>
14
15 #include "sdram.h"
16 #include "boot.h"
17
18 /* General address space functions */
19
20 #define NUMBER_OF_BYTES_ON_A_LINE 16
21 static void dump_bytes(unsigned int *ptr, int count, unsigned addr)
22 {
23 char *data = (char *)ptr;
24 int line_bytes = 0, i = 0;
25
26 putsnonl("Memory dump:");
27 while(count > 0){
28 line_bytes =
29 (count > NUMBER_OF_BYTES_ON_A_LINE)?
30 NUMBER_OF_BYTES_ON_A_LINE : count;
31
32 printf("\n0x%08x ", addr);
33 for(i=0;i<line_bytes;i++)
34 printf("%02x ", *(unsigned char *)(data+i));
35
36 for(;i<NUMBER_OF_BYTES_ON_A_LINE;i++)
37 printf(" ");
38
39 printf(" ");
40
41 for(i=0;i<line_bytes;i++) {
42 if((*(data+i) < 0x20) || (*(data+i) > 0x7e))
43 printf(".");
44 else
45 printf("%c", *(data+i));
46 }
47
48 for(;i<NUMBER_OF_BYTES_ON_A_LINE;i++)
49 printf(" ");
50
51 data += (char)line_bytes;
52 count -= line_bytes;
53 addr += line_bytes;
54 }
55 printf("\n");
56 }
57
58 static void mr(char *startaddr, char *len)
59 {
60 char *c;
61 unsigned int *addr;
62 unsigned int length;
63
64 if(*startaddr == 0) {
65 printf("mr <address> [length]\n");
66 return;
67 }
68 addr = (unsigned *)strtoul(startaddr, &c, 0);
69 if(*c != 0) {
70 printf("incorrect address\n");
71 return;
72 }
73 if(*len == 0) {
74 length = 4;
75 } else {
76 length = strtoul(len, &c, 0);
77 if(*c != 0) {
78 printf("incorrect length\n");
79 return;
80 }
81 }
82
83 dump_bytes(addr, length, (unsigned)addr);
84 }
85
86 static void mw(char *addr, char *value, char *count)
87 {
88 char *c;
89 unsigned int *addr2;
90 unsigned int value2;
91 unsigned int count2;
92 unsigned int i;
93
94 if((*addr == 0) || (*value == 0)) {
95 printf("mw <address> <value> [count]\n");
96 return;
97 }
98 addr2 = (unsigned int *)strtoul(addr, &c, 0);
99 if(*c != 0) {
100 printf("incorrect address\n");
101 return;
102 }
103 value2 = strtoul(value, &c, 0);
104 if(*c != 0) {
105 printf("incorrect value\n");
106 return;
107 }
108 if(*count == 0) {
109 count2 = 1;
110 } else {
111 count2 = strtoul(count, &c, 0);
112 if(*c != 0) {
113 printf("incorrect count\n");
114 return;
115 }
116 }
117 for (i=0;i<count2;i++) *addr2++ = value2;
118 }
119
120 static void mc(char *dstaddr, char *srcaddr, char *count)
121 {
122 char *c;
123 unsigned int *dstaddr2;
124 unsigned int *srcaddr2;
125 unsigned int count2;
126 unsigned int i;
127
128 if((*dstaddr == 0) || (*srcaddr == 0)) {
129 printf("mc <dst> <src> [count]\n");
130 return;
131 }
132 dstaddr2 = (unsigned int *)strtoul(dstaddr, &c, 0);
133 if(*c != 0) {
134 printf("incorrect destination address\n");
135 return;
136 }
137 srcaddr2 = (unsigned int *)strtoul(srcaddr, &c, 0);
138 if(*c != 0) {
139 printf("incorrect source address\n");
140 return;
141 }
142 if(*count == 0) {
143 count2 = 1;
144 } else {
145 count2 = strtoul(count, &c, 0);
146 if(*c != 0) {
147 printf("incorrect count\n");
148 return;
149 }
150 }
151 for (i=0;i<count2;i++) *dstaddr2++ = *srcaddr2++;
152 }
153
154 static void crc(char *startaddr, char *len)
155 {
156 char *c;
157 char *addr;
158 unsigned int length;
159
160 if((*startaddr == 0)||(*len == 0)) {
161 printf("crc <address> <length>\n");
162 return;
163 }
164 addr = (char *)strtoul(startaddr, &c, 0);
165 if(*c != 0) {
166 printf("incorrect address\n");
167 return;
168 }
169 length = strtoul(len, &c, 0);
170 if(*c != 0) {
171 printf("incorrect length\n");
172 return;
173 }
174
175 printf("CRC32: %08x\n", crc32((unsigned char *)addr, length));
176 }
177
178 static void ident(void)
179 {
180 char buffer[IDENT_SIZE];
181
182 get_ident(buffer);
183 printf("Ident: %s\n", buffer);
184 }
185
186 #ifdef __lm32__
187 enum {
188 CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA,
189 CSR_DC, CSR_DEBA, CSR_JTX, CSR_JRX, CSR_BP0, CSR_BP1, CSR_BP2, CSR_BP3,
190 CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3,
191 };
192
193 /* processor registers */
194 static int parse_csr(const char *csr)
195 {
196 if(!strcmp(csr, "ie")) return CSR_IE;
197 if(!strcmp(csr, "im")) return CSR_IM;
198 if(!strcmp(csr, "ip")) return CSR_IP;
199 if(!strcmp(csr, "icc")) return CSR_ICC;
200 if(!strcmp(csr, "dcc")) return CSR_DCC;
201 if(!strcmp(csr, "cc")) return CSR_CC;
202 if(!strcmp(csr, "cfg")) return CSR_CFG;
203 if(!strcmp(csr, "eba")) return CSR_EBA;
204 if(!strcmp(csr, "dc")) return CSR_DC;
205 if(!strcmp(csr, "deba")) return CSR_DEBA;
206 if(!strcmp(csr, "jtx")) return CSR_JTX;
207 if(!strcmp(csr, "jrx")) return CSR_JRX;
208 if(!strcmp(csr, "bp0")) return CSR_BP0;
209 if(!strcmp(csr, "bp1")) return CSR_BP1;
210 if(!strcmp(csr, "bp2")) return CSR_BP2;
211 if(!strcmp(csr, "bp3")) return CSR_BP3;
212 if(!strcmp(csr, "wp0")) return CSR_WP0;
213 if(!strcmp(csr, "wp1")) return CSR_WP1;
214 if(!strcmp(csr, "wp2")) return CSR_WP2;
215 if(!strcmp(csr, "wp3")) return CSR_WP3;
216
217 return 0;
218 }
219
220 static void rcsr(char *csr)
221 {
222 unsigned int csr2;
223 register unsigned int value;
224
225 if(*csr == 0) {
226 printf("rcsr <csr>\n");
227 return;
228 }
229
230 csr2 = parse_csr(csr);
231 if(csr2 == 0) {
232 printf("incorrect csr\n");
233 return;
234 }
235
236 switch(csr2) {
237 case CSR_IE: asm volatile ("rcsr %0,ie":"=r"(value)); break;
238 case CSR_IM: asm volatile ("rcsr %0,im":"=r"(value)); break;
239 case CSR_IP: asm volatile ("rcsr %0,ip":"=r"(value)); break;
240 case CSR_CC: asm volatile ("rcsr %0,cc":"=r"(value)); break;
241 case CSR_CFG: asm volatile ("rcsr %0,cfg":"=r"(value)); break;
242 case CSR_EBA: asm volatile ("rcsr %0,eba":"=r"(value)); break;
243 case CSR_DEBA: asm volatile ("rcsr %0,deba":"=r"(value)); break;
244 case CSR_JTX: asm volatile ("rcsr %0,jtx":"=r"(value)); break;
245 case CSR_JRX: asm volatile ("rcsr %0,jrx":"=r"(value)); break;
246 default: printf("csr write only\n"); return;
247 }
248
249 printf("%08x\n", value);
250 }
251
252 static void wcsr(char *csr, char *value)
253 {
254 char *c;
255 unsigned int csr2;
256 register unsigned int value2;
257
258 if((*csr == 0) || (*value == 0)) {
259 printf("wcsr <csr> <address>\n");
260 return;
261 }
262
263 csr2 = parse_csr(csr);
264 if(csr2 == 0) {
265 printf("incorrect csr\n");
266 return;
267 }
268 value2 = strtoul(value, &c, 0);
269 if(*c != 0) {
270 printf("incorrect value\n");
271 return;
272 }
273
274 switch(csr2) {
275 case CSR_IE: asm volatile ("wcsr ie,%0"::"r"(value2)); break;
276 case CSR_IM: asm volatile ("wcsr im,%0"::"r"(value2)); break;
277 case CSR_ICC: asm volatile ("wcsr icc,%0"::"r"(value2)); break;
278 case CSR_DCC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
279 case CSR_EBA: asm volatile ("wcsr eba,%0"::"r"(value2)); break;
280 case CSR_DC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break;
281 case CSR_DEBA: asm volatile ("wcsr deba,%0"::"r"(value2)); break;
282 case CSR_JTX: asm volatile ("wcsr jtx,%0"::"r"(value2)); break;
283 case CSR_JRX: asm volatile ("wcsr jrx,%0"::"r"(value2)); break;
284 case CSR_BP0: asm volatile ("wcsr bp0,%0"::"r"(value2)); break;
285 case CSR_BP1: asm volatile ("wcsr bp1,%0"::"r"(value2)); break;
286 case CSR_BP2: asm volatile ("wcsr bp2,%0"::"r"(value2)); break;
287 case CSR_BP3: asm volatile ("wcsr bp3,%0"::"r"(value2)); break;
288 case CSR_WP0: asm volatile ("wcsr wp0,%0"::"r"(value2)); break;
289 case CSR_WP1: asm volatile ("wcsr wp1,%0"::"r"(value2)); break;
290 case CSR_WP2: asm volatile ("wcsr wp2,%0"::"r"(value2)); break;
291 case CSR_WP3: asm volatile ("wcsr wp3,%0"::"r"(value2)); break;
292 default: printf("csr read only\n"); return;
293 }
294 }
295
296 #endif /* __lm32__ */
297
298 /* Init + command line */
299
300 static void help(void)
301 {
302 puts("LiteX SoC BIOS");
303 puts("Available commands:");
304 puts("mr - read address space");
305 puts("mw - write address space");
306 puts("mc - copy address space");
307 puts("crc - compute CRC32 of a part of the address space");
308 puts("ident - display identifier");
309 #ifdef __lm32__
310 puts("rcsr - read processor CSR");
311 puts("wcsr - write processor CSR");
312 #endif
313 #ifdef CSR_ETHMAC_BASE
314 puts("netboot - boot via TFTP");
315 #endif
316 puts("serialboot - boot via SFL");
317 #ifdef FLASH_BOOT_ADDRESS
318 puts("flashboot - boot from flash");
319 #endif
320 #ifdef ROM_BOOT_ADDRESS
321 puts("romboot - boot from embedded rom");
322 #endif
323 #ifdef CSR_SDRAM_BASE
324 puts("memtest - run a memory test");
325 #endif
326 }
327
328 static char *get_token(char **str)
329 {
330 char *c, *d;
331
332 c = (char *)strchr(*str, ' ');
333 if(c == NULL) {
334 d = *str;
335 *str = *str+strlen(*str);
336 return d;
337 }
338 *c = 0;
339 d = *str;
340 *str = c+1;
341 return d;
342 }
343
344 static void do_command(char *c)
345 {
346 char *token;
347
348 token = get_token(&c);
349
350 if(strcmp(token, "mr") == 0) mr(get_token(&c), get_token(&c));
351 else if(strcmp(token, "mw") == 0) mw(get_token(&c), get_token(&c), get_token(&c));
352 else if(strcmp(token, "mc") == 0) mc(get_token(&c), get_token(&c), get_token(&c));
353 else if(strcmp(token, "crc") == 0) crc(get_token(&c), get_token(&c));
354 else if(strcmp(token, "ident") == 0) ident();
355
356 #ifdef L2_SIZE
357 else if(strcmp(token, "flushl2") == 0) flush_l2_cache();
358 #endif
359
360 #ifdef FLASH_BOOT_ADDRESS
361 else if(strcmp(token, "flashboot") == 0) flashboot();
362 #endif
363 #ifdef ROM_BOOT_ADDRESS
364 else if(strcmp(token, "romboot") == 0) romboot();
365 #endif
366 else if(strcmp(token, "serialboot") == 0) serialboot();
367 #ifdef CSR_ETHMAC_BASE
368 else if(strcmp(token, "netboot") == 0) netboot();
369 #endif
370
371 else if(strcmp(token, "help") == 0) help();
372
373 #ifdef __lm32__
374 else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c));
375 else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c));
376 #endif
377
378 #ifdef CSR_SDRAM_BASE
379 else if(strcmp(token, "sdrrow") == 0) sdrrow(get_token(&c));
380 else if(strcmp(token, "sdrsw") == 0) sdrsw();
381 else if(strcmp(token, "sdrhw") == 0) sdrhw();
382 else if(strcmp(token, "sdrrdbuf") == 0) sdrrdbuf(-1);
383 else if(strcmp(token, "sdrrd") == 0) sdrrd(get_token(&c), get_token(&c));
384 else if(strcmp(token, "sdrrderr") == 0) sdrrderr(get_token(&c));
385 else if(strcmp(token, "sdrwr") == 0) sdrwr(get_token(&c));
386 #ifdef CSR_DDRPHY_BASE
387 #ifndef A7DDRPHY_BITSLIP
388 else if(strcmp(token, "sdrwlon") == 0) sdrwlon();
389 else if(strcmp(token, "sdrwloff") == 0) sdrwloff();
390 #endif
391 else if(strcmp(token, "sdrlevel") == 0) sdrlevel();
392 #endif
393 else if(strcmp(token, "memtest") == 0) memtest();
394 else if(strcmp(token, "sdrinit") == 0) sdrinit();
395 #endif
396
397 else if(strcmp(token, "") != 0)
398 printf("Command not found\n");
399 }
400
401 extern unsigned int _ftext, _erodata;
402
403 static void crcbios(void)
404 {
405 unsigned int offset_bios;
406 unsigned int length;
407 unsigned int expected_crc;
408 unsigned int actual_crc;
409
410 /*
411 * _erodata is located right after the end of the flat
412 * binary image. The CRC tool writes the 32-bit CRC here.
413 * We also use the address of _erodata to know the length
414 * of our code.
415 */
416 offset_bios = (unsigned int)&_ftext;
417 expected_crc = _erodata;
418 length = (unsigned int)&_erodata - offset_bios;
419 actual_crc = crc32((unsigned char *)offset_bios, length);
420 if(expected_crc == actual_crc)
421 printf("BIOS CRC passed (%08x)\n", actual_crc);
422 else {
423 printf("BIOS CRC failed (expected %08x, got %08x)\n", expected_crc, actual_crc);
424 printf("The system will continue, but expect problems.\n");
425 }
426 }
427
428 static void readstr(char *s, int size)
429 {
430 char c[2];
431 int ptr;
432
433 c[1] = 0;
434 ptr = 0;
435 while(1) {
436 c[0] = readchar();
437 switch(c[0]) {
438 case 0x7f:
439 case 0x08:
440 if(ptr > 0) {
441 ptr--;
442 putsnonl("\x08 \x08");
443 }
444 break;
445 case 0x07:
446 break;
447 case '\r':
448 case '\n':
449 s[ptr] = 0x00;
450 putsnonl("\n");
451 return;
452 default:
453 putsnonl(c);
454 s[ptr] = c[0];
455 ptr++;
456 break;
457 }
458 }
459 }
460
461 static int test_user_abort(void)
462 {
463 char c;
464
465 printf("Automatic boot in 2 seconds...\n");
466 printf("Q/ESC: abort boot\n");
467 #ifdef FLASH_BOOT_ADDRESS
468 printf("F: boot from flash\n");
469 #endif
470 printf("S: boot from serial\n");
471 #ifdef CSR_ETHMAC_BASE
472 printf("N: boot from network\n");
473 #endif
474 #ifdef ROM_BOOT_ADDRESS
475 printf("R: boot from embedded ROM\n");
476 #endif
477 timer0_en_write(0);
478 timer0_reload_write(0);
479 #ifndef TEST_USER_ABORT_DELAY
480 timer0_load_write(SYSTEM_CLOCK_FREQUENCY*2);
481 #else
482 timer0_load_write(TEST_USER_ABORT_DELAY);
483 #endif
484 timer0_en_write(1);
485 timer0_update_value_write(1);
486 while(timer0_value_read()) {
487 if(readchar_nonblock()) {
488 c = readchar();
489 if((c == 'Q')||(c == 'q')||(c == '\e')) {
490 puts("Aborted");
491 return 0;
492 }
493 #ifdef FLASH_BOOT_ADDRESS
494 if((c == 'F')||(c == 'f')) {
495 flashboot();
496 return 0;
497 }
498 #endif
499 if((c == 'S')||(c == 's')) {
500 serialboot();
501 return 0;
502 }
503 #ifdef CSR_ETHMAC_BASE
504 if((c == 'N')||(c == 'n')) {
505 netboot();
506 return 0;
507 }
508 #endif
509 #ifdef ROM_BOOT_ADDRESS
510 if((c == 'R')||(c == 'r')) {
511 romboot();
512 return 0;
513 }
514 #endif
515 }
516 timer0_update_value_write(1);
517 }
518 return 1;
519 }
520
521 static void boot_sequence(void)
522 {
523 if(test_user_abort()) {
524 #ifdef FLASH_BOOT_ADDRESS
525 flashboot();
526 #endif
527 #ifdef ROM_BOOT_ADDRESS
528 romboot();
529 #endif
530 serialboot();
531 #ifdef CSR_ETHMAC_BASE
532 #ifdef CSR_ETHPHY_MODE_DETECTION_MODE_ADDR
533 eth_mode();
534 #endif
535 netboot();
536 #endif
537 printf("No boot medium found\n");
538 }
539 }
540
541 int main(int i, char **c)
542 {
543 char buffer[64];
544 int sdr_ok;
545
546 irq_setmask(0);
547 irq_setie(1);
548 uart_init();
549 printf("\nLiteX SoC BIOS ");
550 #ifdef __lm32__
551 printf("(lm32)\n");
552 #elif __or1k__
553 printf("(or1k)\n");
554 #elif __riscv__
555 printf("(riscv)\n");
556 #else
557 printf("(unknown)\n");
558 #endif
559 puts(
560 "(c) Copyright 2012-2016 Enjoy-Digital\n"
561 "(c) Copyright 2007-2016 M-Labs Limited\n"
562 "Built "__DATE__" "__TIME__"\n");
563
564 crcbios();
565 #ifdef CSR_ETHMAC_BASE
566 eth_init();
567 #endif
568 #ifdef CSR_SDRAM_BASE
569 sdr_ok = sdrinit();
570 #else
571 sdr_ok = 1;
572 #endif
573 if(sdr_ok)
574 boot_sequence();
575 else
576 printf("Memory initialization failed\n");
577
578 while(1) {
579 putsnonl("\e[1mBIOS>\e[0m ");
580 readstr(buffer, 64);
581 do_command(buffer);
582 }
583 return 0;
584 }