From 73fce596315df530d7ce04f34319f62058882886 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 7 Feb 2012 15:02:44 +0100 Subject: [PATCH] software: shell from original BIOS --- software/bios/Makefile | 3 +- software/bios/main.c | 457 +++++++++++++++++++++++++++++++- software/include/base/console.h | 1 - software/include/base/stdio.h | 3 + software/libbase/console.c | 25 +- software/libextra/Makefile | 18 ++ software/libextra/crc16.c | 2 +- software/libextra/crc32.c | 2 +- 8 files changed, 476 insertions(+), 35 deletions(-) create mode 100644 software/libextra/Makefile diff --git a/software/bios/Makefile b/software/bios/Makefile index 5a5ac66d3..f916aaab0 100644 --- a/software/bios/Makefile +++ b/software/bios/Makefile @@ -18,11 +18,12 @@ bios.elf: linker.ld $(OBJECTS) libs bios-rescue.elf: linker-rescue.ld $(OBJECTS) libs %.elf: - $(LD) $(LDFLAGS) -T $< -N -o $@ $(OBJECTS) -L$(M2DIR)/software/libbase -lbase + $(LD) $(LDFLAGS) -T $< -N -o $@ $(OBJECTS) -L$(M2DIR)/software/libbase -L$(M2DIR)/software/libextra -lbase -lextra chmod -x $@ libs: make -C $(M2DIR)/software/libbase + make -C $(M2DIR)/software/libextra .PHONY: clean libs diff --git a/software/bios/main.c b/software/bios/main.c index d90867b42..c408b8e3f 100644 --- a/software/bios/main.c +++ b/software/bios/main.c @@ -1,19 +1,454 @@ -#include -#include -#include +/* + * Milkymist SoC (Software) + * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Sebastien Bourdeauducq + * + * 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, version 3 of the License. + * + * 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, see . + */ -int main(void) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +enum { + CSR_IE = 1, CSR_IM, CSR_IP, CSR_ICC, CSR_DCC, CSR_CC, CSR_CFG, CSR_EBA, + CSR_DC, CSR_DEBA, CSR_JTX, CSR_JRX, CSR_BP0, CSR_BP1, CSR_BP2, CSR_BP3, + CSR_WP0, CSR_WP1, CSR_WP2, CSR_WP3, +}; + +/* General address space functions */ + +#define NUMBER_OF_BYTES_ON_A_LINE 16 +static void dump_bytes(unsigned int *ptr, int count, unsigned addr) { - char c; - + char *data = (char *)ptr; + int line_bytes = 0, i = 0; + + putsnonl("Memory dump:"); + while(count > 0){ + line_bytes = + (count > NUMBER_OF_BYTES_ON_A_LINE)? + NUMBER_OF_BYTES_ON_A_LINE : count; + + printf("\n0x%08x ", addr); + for(i=0;i 0x7e)) + printf("."); + else + printf("%c", *(data+i)); + } + + for(;i [length]\n"); + return; + } + addr = (unsigned *)strtoul(startaddr, &c, 0); + if(*c != 0) { + printf("incorrect address\n"); + return; + } + if(*len == 0) { + length = 1; + } else { + length = strtoul(len, &c, 0); + if(*c != 0) { + printf("incorrect length\n"); + return; + } + } + + dump_bytes(addr, length, (unsigned)addr); +} + +static void mw(char *addr, char *value, char *count) +{ + char *c; + unsigned int *addr2; + unsigned int value2; + unsigned int count2; + unsigned int i; + + if((*addr == 0) || (*value == 0)) { + printf("mw
[count]\n"); + return; + } + addr2 = (unsigned int *)strtoul(addr, &c, 0); + if(*c != 0) { + printf("incorrect address\n"); + return; + } + value2 = strtoul(value, &c, 0); + if(*c != 0) { + printf("incorrect value\n"); + return; + } + if(*count == 0) { + count2 = 1; + } else { + count2 = strtoul(count, &c, 0); + if(*c != 0) { + printf("incorrect count\n"); + return; + } + } + for (i=0;i [count]\n"); + return; + } + dstaddr2 = (unsigned int *)strtoul(dstaddr, &c, 0); + if(*c != 0) { + printf("incorrect destination address\n"); + return; + } + srcaddr2 = (unsigned int *)strtoul(srcaddr, &c, 0); + if(*c != 0) { + printf("incorrect source address\n"); + return; + } + if(*count == 0) { + count2 = 1; + } else { + count2 = strtoul(count, &c, 0); + if(*c != 0) { + printf("incorrect count\n"); + return; + } + } + for (i=0;i \n"); + return; + } + addr = (char *)strtoul(startaddr, &c, 0); + if(*c != 0) { + printf("incorrect address\n"); + return; + } + length = strtoul(len, &c, 0); + if(*c != 0) { + printf("incorrect length\n"); + return; + } + + printf("CRC32: %08x\n", crc32((unsigned char *)addr, length)); +} + +/* processor registers */ +static int parse_csr(const char *csr) +{ + if(!strcmp(csr, "ie")) return CSR_IE; + if(!strcmp(csr, "im")) return CSR_IM; + if(!strcmp(csr, "ip")) return CSR_IP; + if(!strcmp(csr, "icc")) return CSR_ICC; + if(!strcmp(csr, "dcc")) return CSR_DCC; + if(!strcmp(csr, "cc")) return CSR_CC; + if(!strcmp(csr, "cfg")) return CSR_CFG; + if(!strcmp(csr, "eba")) return CSR_EBA; + if(!strcmp(csr, "dc")) return CSR_DC; + if(!strcmp(csr, "deba")) return CSR_DEBA; + if(!strcmp(csr, "jtx")) return CSR_JTX; + if(!strcmp(csr, "jrx")) return CSR_JRX; + if(!strcmp(csr, "bp0")) return CSR_BP0; + if(!strcmp(csr, "bp1")) return CSR_BP1; + if(!strcmp(csr, "bp2")) return CSR_BP2; + if(!strcmp(csr, "bp3")) return CSR_BP3; + if(!strcmp(csr, "wp0")) return CSR_WP0; + if(!strcmp(csr, "wp1")) return CSR_WP1; + if(!strcmp(csr, "wp2")) return CSR_WP2; + if(!strcmp(csr, "wp3")) return CSR_WP3; + + return 0; +} + +static void rcsr(char *csr) +{ + unsigned int csr2; + register unsigned int value; + + if(*csr == 0) { + printf("rcsr \n"); + return; + } + + csr2 = parse_csr(csr); + if(csr2 == 0) { + printf("incorrect csr\n"); + return; + } + + switch(csr2) { + case CSR_IE: asm volatile ("rcsr %0,ie":"=r"(value)); break; + case CSR_IM: asm volatile ("rcsr %0,im":"=r"(value)); break; + case CSR_IP: asm volatile ("rcsr %0,ip":"=r"(value)); break; + case CSR_CC: asm volatile ("rcsr %0,cc":"=r"(value)); break; + case CSR_CFG: asm volatile ("rcsr %0,cfg":"=r"(value)); break; + case CSR_EBA: asm volatile ("rcsr %0,eba":"=r"(value)); break; + case CSR_DEBA: asm volatile ("rcsr %0,deba":"=r"(value)); break; + case CSR_JTX: asm volatile ("rcsr %0,jtx":"=r"(value)); break; + case CSR_JRX: asm volatile ("rcsr %0,jrx":"=r"(value)); break; + default: printf("csr write only\n"); return; + } + + printf("%08x\n", value); +} + +static void wcsr(char *csr, char *value) +{ + char *c; + unsigned int csr2; + register unsigned int value2; + + if((*csr == 0) || (*value == 0)) { + printf("wcsr
\n"); + return; + } + + csr2 = parse_csr(csr); + if(csr2 == 0) { + printf("incorrect csr\n"); + return; + } + value2 = strtoul(value, &c, 0); + if(*c != 0) { + printf("incorrect value\n"); + return; + } + + switch(csr2) { + case CSR_IE: asm volatile ("wcsr ie,%0"::"r"(value2)); break; + case CSR_IM: asm volatile ("wcsr im,%0"::"r"(value2)); break; + case CSR_ICC: asm volatile ("wcsr icc,%0"::"r"(value2)); break; + case CSR_DCC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break; + case CSR_EBA: asm volatile ("wcsr eba,%0"::"r"(value2)); break; + case CSR_DC: asm volatile ("wcsr dcc,%0"::"r"(value2)); break; + case CSR_DEBA: asm volatile ("wcsr deba,%0"::"r"(value2)); break; + case CSR_JTX: asm volatile ("wcsr jtx,%0"::"r"(value2)); break; + case CSR_JRX: asm volatile ("wcsr jrx,%0"::"r"(value2)); break; + case CSR_BP0: asm volatile ("wcsr bp0,%0"::"r"(value2)); break; + case CSR_BP1: asm volatile ("wcsr bp1,%0"::"r"(value2)); break; + case CSR_BP2: asm volatile ("wcsr bp2,%0"::"r"(value2)); break; + case CSR_BP3: asm volatile ("wcsr bp3,%0"::"r"(value2)); break; + case CSR_WP0: asm volatile ("wcsr wp0,%0"::"r"(value2)); break; + case CSR_WP1: asm volatile ("wcsr wp1,%0"::"r"(value2)); break; + case CSR_WP2: asm volatile ("wcsr wp2,%0"::"r"(value2)); break; + case CSR_WP3: asm volatile ("wcsr wp3,%0"::"r"(value2)); break; + default: printf("csr read only\n"); return; + } +} + +/* Init + command line */ + +static void help() +{ + puts("Milkymist(tm) BIOS"); + puts("Don't know what to do? Try 'flashboot'.\n"); + puts("Available commands:"); + puts("mr - read address space"); + puts("mw - write address space"); + puts("mc - copy address space"); + puts("crc - compute CRC32 of a part of the address space"); + puts("rcsr - read processor CSR"); + puts("wcsr - write processor CSR"); + puts("version - display version"); + puts("reboot - system reset"); + puts("reconf - reload FPGA configuration"); +} + +static char *get_token(char **str) +{ + char *c, *d; + + c = (char *)strchr(*str, ' '); + if(c == NULL) { + d = *str; + *str = *str+strlen(*str); + return d; + } + *c = 0; + d = *str; + *str = c+1; + return d; +} + +static void do_command(char *c) +{ + char *token; + + token = get_token(&c); + + if(strcmp(token, "mr") == 0) mr(get_token(&c), get_token(&c)); + else if(strcmp(token, "mw") == 0) mw(get_token(&c), get_token(&c), get_token(&c)); + else if(strcmp(token, "mc") == 0) mc(get_token(&c), get_token(&c), get_token(&c)); + else if(strcmp(token, "crc") == 0) crc(get_token(&c), get_token(&c)); + + else if(strcmp(token, "version") == 0) puts(VERSION); + else if(strcmp(token, "reboot") == 0) reboot(); + else if(strcmp(token, "reconf") == 0) reconf(); + + else if(strcmp(token, "help") == 0) help(); + + else if(strcmp(token, "rcsr") == 0) rcsr(get_token(&c)); + else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c)); + + else if(strcmp(token, "") != 0) + printf("Command not found\n"); +} + +int rescue; +extern unsigned int _edata; + +static void crcbios() +{ + unsigned int offset_bios; + unsigned int length; + unsigned int expected_crc; + unsigned int actual_crc; + + /* + * _edata is located right after the end of the flat + * binary image. The CRC tool writes the 32-bit CRC here. + * We also use the address of _edata to know the length + * of our code. + */ + offset_bios = rescue ? FLASH_OFFSET_RESCUE_BIOS : FLASH_OFFSET_REGULAR_BIOS; + expected_crc = _edata; + length = (unsigned int)&_edata - offset_bios; + actual_crc = crc32((unsigned char *)offset_bios, length); + if(expected_crc == actual_crc) + printf("I: BIOS CRC passed (%08x)\n", actual_crc); + else { + printf("W: BIOS CRC failed (expected %08x, got %08x)\n", expected_crc, actual_crc); + printf("W: The system will continue, but expect problems.\n"); + } +} + +static void print_mac() +{ + unsigned char *macadr = (unsigned char *)FLASH_OFFSET_MAC_ADDRESS; + + printf("I: MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", macadr[0], macadr[1], macadr[2], macadr[3], macadr[4], macadr[5]); +} + +static const char banner[] = + "\nMILKYMIST(tm) v"VERSION" BIOS http://www.milkymist.org\n" + "(c) Copyright 2007-2012 Sebastien Bourdeauducq\n\n" + "This program is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, version 3 of the License.\n"; + +static void readstr(char *s, int size) +{ + char c[2]; + int ptr; + + c[1] = 0; + ptr = 0; + while(1) { + c[0] = readchar(); + switch(c[0]) { + case 0x7f: + case 0x08: + if(ptr > 0) { + ptr--; + putsnonl("\x08 \x08"); + } + break; + case 0x07: + break; + case '\r': + case '\n': + s[ptr] = 0x00; + putsnonl("\n"); + return; + default: + putsnonl(c); + s[ptr] = c[0]; + ptr++; + break; + } + } +} + +int main(int i, char **c) +{ + char buffer[64]; + + rescue = !((unsigned int)main > FLASH_OFFSET_REGULAR_BIOS); + irq_setmask(0); irq_setie(1); uart_init(); - - printf("Hello World with IRQs\n"); - + printf(banner); + crcbios(); + + if(rescue) + printf("I: Booting in rescue mode\n"); + + print_mac(); while(1) { - c = uart_read(); - printf("You typed: %c\n", c); + putsnonl("\e[1mBIOS>\e[0m "); + readstr(buffer, 64); + do_command(buffer); } + return 0; } diff --git a/software/include/base/console.h b/software/include/base/console.h index d89f0a153..795176372 100644 --- a/software/include/base/console.h +++ b/software/include/base/console.h @@ -28,7 +28,6 @@ void console_set_read_hook(console_read_hook r, console_read_nonblock_hook rn); char readchar(void); int readchar_nonblock(void); -int puts(const char *s); void putsnonl(const char *s); #endif /* __CONSOLE_H */ diff --git a/software/include/base/stdio.h b/software/include/base/stdio.h index 5fb35a59c..f80e3a6f1 100644 --- a/software/include/base/stdio.h +++ b/software/include/base/stdio.h @@ -20,6 +20,9 @@ #include +int putchar(int c); +int puts(const char *s); + int snprintf(char *buf, size_t size, const char *fmt, ...); int scnprintf(char *buf, size_t size, const char *fmt, ...); int sprintf(char *buf, const char *fmt, ...); diff --git a/software/libbase/console.c b/software/libbase/console.c index d27bff3d2..19d0a97b5 100644 --- a/software/libbase/console.c +++ b/software/libbase/console.c @@ -19,8 +19,6 @@ #include #include #include -#include -#include static console_write_hook write_hook; static console_read_hook read_hook; @@ -37,11 +35,12 @@ void console_set_read_hook(console_read_hook r, console_read_nonblock_hook rn) read_nonblock_hook = rn; } -static void writechar(char c) +int putchar(int c) { uart_write(c); if(write_hook != NULL) write_hook(c); + return c; } char readchar(void) @@ -62,34 +61,20 @@ int readchar_nonblock(void) int puts(const char *s) { - unsigned int oldmask; - - oldmask = irq_getmask(); - irq_setmask(IRQ_UART); // HACK: prevent UART data loss - while(*s) { - writechar(*s); + putchar(*s); s++; } - writechar('\n'); - - irq_setmask(oldmask); + putchar('\n'); return 1; } void putsnonl(const char *s) { - unsigned int oldmask; - - oldmask = irq_getmask(); - irq_setmask(IRQ_UART); // HACK: prevent UART data loss - while(*s) { - writechar(*s); + putchar(*s); s++; } - - irq_setmask(oldmask); } int printf(const char *fmt, ...) diff --git a/software/libextra/Makefile b/software/libextra/Makefile new file mode 100644 index 000000000..34747a65c --- /dev/null +++ b/software/libextra/Makefile @@ -0,0 +1,18 @@ +M2DIR=../.. +include $(M2DIR)/software/include.mak + +OBJECTS=crc16.o crc32.o + +all: libextra.a + +# pull in dependency info for *existing* .o files +-include $(OBJECTS:.o=.d) + +libextra.a: $(OBJECTS) + $(AR) clr libextra.a $(OBJECTS) + $(RANLIB) libextra.a + +.PHONY: clean + +clean: + rm -f $(OBJECTS) $(OBJECTS:.o=.d) libextra.a .*~ *~ diff --git a/software/libextra/crc16.c b/software/libextra/crc16.c index a1222e861..afd848c60 100644 --- a/software/libextra/crc16.c +++ b/software/libextra/crc16.c @@ -1,4 +1,4 @@ -#include +#include static const unsigned int crc16_table[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, diff --git a/software/libextra/crc32.c b/software/libextra/crc32.c index 29b9b9944..f9438227d 100644 --- a/software/libextra/crc32.c +++ b/software/libextra/crc32.c @@ -3,7 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include +#include static const unsigned int crc_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,