From 1e53ccbe5c7672702722ab3781ea939662283e3b Mon Sep 17 00:00:00 2001 From: Philippe Vachon Date: Thu, 29 Jan 2009 15:36:38 -0500 Subject: [PATCH] =?UTF-8?q?Added=20C7200=20support=20(thanks=20to=20V?= =?UTF-8?q?=EF=BF=BDg=EF=BF=BD=20Tibor).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + Makefile | 11 ++ include/mach/c7200/platform.h | 15 +++ include/mach/c7200/platio.h | 37 ++++++ mach/c7200/Makefile | 18 +++ mach/c7200/platform.c | 44 ++++++++ mach/c7200/platio.c | 97 ++++++++++++++++ mach/c7200/promlib.c | 206 ++++++++++++++++++++++++++++++++++ mach/c7200/start.S | 52 +++++++++ 9 files changed, 483 insertions(+) create mode 100644 .gitignore create mode 100644 include/mach/c7200/platform.h create mode 100644 include/mach/c7200/platio.h create mode 100644 mach/c7200/Makefile create mode 100644 mach/c7200/platform.c create mode 100644 mach/c7200/platio.c create mode 100644 mach/c7200/promlib.c create mode 100644 mach/c7200/start.S diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7cf238f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +*.elf +*.bin diff --git a/Makefile b/Makefile index 8f61b78..aa18520 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,17 @@ LDFLAGS=-Ttext ${TEXTADDR} # endif # LDFLAGS=-Ttext=${TEXTADDR} +# Configuration for the Cisco 7200 Series Routers +# TARGET=c7200 +# MACHCODE=0x19 +# TEXTADDR=0x80008000 +# LOADADDR=0x80028000 +# ifndef CROSS_COMPILE +# CROSS_COMPILE=mips-elf- +# endif +# CFLAGS=-DDEBUG -mno-abicalls +# LDFLAGS=-Ttext ${TEXTADDR} + # additional CFLAGS CFLAGS+= diff --git a/include/mach/c7200/platform.h b/include/mach/c7200/platform.h new file mode 100644 index 0000000..1d0b20d --- /dev/null +++ b/include/mach/c7200/platform.h @@ -0,0 +1,15 @@ +#ifndef _INCLUDE_MACH_C7200_PLATFORM_H +#define _INCLUDE_MACH_C7200_PLATFORM_H + +#include + +#define FLASH_BASE 0xBA000000 +#define FLASHFS_BASE 0xBA040000 +#define KERNEL_ENTRY_POINT 0x80008000 +#define MEMORY_BASE 0x80000000 + +void platform_init(); +uint32_t check_flash(); +void flash_directory(); + +#endif /* _INCLUDE_MACH_C7200_PLATFORM_H */ diff --git a/include/mach/c7200/platio.h b/include/mach/c7200/platio.h new file mode 100644 index 0000000..8a6e590 --- /dev/null +++ b/include/mach/c7200/platio.h @@ -0,0 +1,37 @@ +#ifndef _INCLUDE_MACH_C7200_PLATIO +#define _INCLUDE_MACH_C7200_PLATIO + +#include +#include + +/* a flash filesystem entry for the C7200 */ +struct fs_ent { + uint32_t magic; /* C7200 bootflash filesystem magi number */ + uint32_t fileno; /* number of the file */ + char filename[64]; /* 64bytes filename string*/ + uint32_t length; /* size of the file in bytes */ + uint32_t seek; /* address of the next fs_ent from FLASH_BASE (0xBA000000) and not FLASHFS_BASE (0xBA040000) */ + uint32_t crc32; /* CRC32 value of the file */ + uint32_t type; /* file type (ascii or binary etc.) */ + uint32_t date; /* the file last modification time in UNIX time */ + /* todo: figure out exactly what these two fields contain */ + uint32_t sg01; /* 0xffffffffh */ + uint32_t sg02; /* 0xfffffff8h */ + uint32_t sg03; /* 0xffffffffh */ + uint32_t sg04; /* 0xffffffffh */ + uint32_t sg05; /* 0xffffffffh */ + uint32_t sg06; /* 0xffffffffh */ + uint32_t sg07; /* 0xffffffffh */ + uint32_t sg08; /* 0xffffffffh */ + uint32_t sg09; /* 0xffffffffh */ +}; + +void platio_file_open(struct file *fp, const char *filename); + +uint32_t platio_read(void *pbuf, uint32_t size, uint32_t nmemb, struct file *fp); + +uint8_t platio_find_file(const char *filename); + +#define FS_FILE_MAGIC 0x07158805 + +#endif /* _INCLUDE_MACH_C7200_PLATIO */ diff --git a/mach/c7200/Makefile b/mach/c7200/Makefile new file mode 100644 index 0000000..aa73d3d --- /dev/null +++ b/mach/c7200/Makefile @@ -0,0 +1,18 @@ +ifndef CROSS_COMPILE +CROSS_COMPILE=mips-elf- +endif + +OBJECTS=start.o promlib.o platform.o platio.o + +INCLUDE=-I../../include + +all: ${OBJECTS} + +.c.o: + $(CC) ${CFLAGS} ${INCLUDE} -c $< + +.S.o: + $(CC) ${CFLAGS} ${INCLUDE} ${ASFLAGS} -c $< + +clean: + -rm -f *.o diff --git a/mach/c7200/platform.c b/mach/c7200/platform.c new file mode 100644 index 0000000..ebb229a --- /dev/null +++ b/mach/c7200/platform.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +/** + * perform hardware-specifc initialization for this platform + */ +void platform_init() +{ +} + +/** + * Perform a sanity check on flash + * @returns 0 if no flash found, number of flash devices found otherwise + */ +uint32_t check_flash() +{ + uint32_t *ptr = (uint32_t *)FLASHFS_BASE; + + if (*ptr != FS_FILE_MAGIC) { + return 0; + } + + return 1; + /* TODO: add support for PCMCIA flash */ +} + +/** + * print a directory listing of the 'main' flash device in the system + */ + +void flash_directory() +{ + struct fs_ent *f = (struct fs_ent *)FLASHFS_BASE; + uint32_t offset = 0; + + /* Iterate over the files; f->magic is 0 if an invalid file is found. */ + while (f->magic == FS_FILE_MAGIC) { + printf("%s\n", f->filename); + offset += sizeof(struct fs_ent) + f->length; + f = (struct fs_ent *)(FLASHFS_BASE + offset); + } +} diff --git a/mach/c7200/platio.c b/mach/c7200/platio.c new file mode 100644 index 0000000..daac927 --- /dev/null +++ b/mach/c7200/platio.c @@ -0,0 +1,97 @@ +/* Platform specific operations for I/O for the cisco 7200 Series + * (C) 2008 Philippe Vachon + * + * Licensed under the GNU General Public License v2. + */ +#include +#include +#include +#include + +#include + +/* find file in filesystem starting at base */ +struct fs_ent *find_file(const char *filename, uint32_t base) +{ + /* Actual file offset */ + uint32_t offset = 0; + + struct fs_ent *f = (struct fs_ent *)(base + offset); + + /* iterate over files in flash */ + while (f->magic == FS_FILE_MAGIC) { + if (!strncmp(f->filename, filename, 64)) { + return f; + } + + offset += sizeof(struct fs_ent) + f->length; + f = (struct fs_ent *)(base + offset); + } + + return NULL; +} + +/** + * Find a file within the platform-supported I/O devices + * @param filename the file + * @returns 0 on failure, device ID number on success + */ +uint8_t platio_find_file(const char *filename) +{ + if (find_file(filename, FLASHFS_BASE)) { + return 1; + } + /* todo: add support for PCMCIA devices */ + + return 0; +} + +/** + * Open a file. + * @param fp File structure to hold file information + * @param filename name of the file + */ +void platio_file_open(struct file *fp, const char *filename) +{ + struct fs_ent *ent = find_file(filename, FLASHFS_BASE); + + if (ent == NULL) { + fp->code = 0; + fp->private = NULL; + return; + } + + fp->dev = 1; /* TODO: add support for PCMCIA flash */ + + fp->private = (void *)ent; + + fp->file_len = ent->length; + fp->file_pos = 0; + + /* copy the filename */ + strncpy(fp->filename, ent->filename, 64); + + fp->code = 1; + +} + +/** + * Read data from a given file + * @param pbuf Buffer to read data into + * @param size size of entity to be read + * @param nmemb number of members to read + * @param fp file information structure to read from. + * @returns number of bytes read (should = size * nmemb for C7200) + */ +uint32_t platio_read(void *pbuf, uint32_t size, uint32_t nmemb, struct file *fp) +{ + /* calculate the effective offset of the data we want to read: */ + char *from = (char *)((uint32_t)(fp->private) + sizeof(struct fs_ent) + fp->file_pos); + + memcpy(pbuf, from, size * nmemb); + + fp->file_pos += size * nmemb; + + return nmemb * size; + +} diff --git a/mach/c7200/promlib.c b/mach/c7200/promlib.c new file mode 100644 index 0000000..b6e02ea --- /dev/null +++ b/mach/c7200/promlib.c @@ -0,0 +1,206 @@ +/** + * PROM Library for Cisco Systems 7200 Series Routers + * (C) 2008 Philippe Vachon + * ----------------------------------------------------------- + */ + +/** + * Calling convention: + * a0 - syscall number + * a1 - arg1 ... etc + * v0 - returned value from syscall + */ + +#include + +/* putc - Syscall 1 + * output character c to console + * @param c ASCII number for character + */ +void c_putc(const char c) +{ + asm ( ".set noreorder\n " + "li $a0, %[syscall]\n" + "lb $a1, (%[character])\n" + "syscall\n" + "nop\n" + ".set reorder\n" + : /* no output */ + : [character] "r"(&c), [syscall] "g"(PUTC) + : "a0", "a1" + ); +} + +/* puts - wrapper for putc + * output the string pointed to by s + * @param s String to be written to the console + */ +void c_puts(const char *s) +{ + while(*s != '\0') { + c_putc(*(s++)); + } +} + +/* putsn - put a string of length n on the console + * @param s string to be written + * @param n length + */ +void c_putsn(const char *s, int n) +{ + int i = 0; + while (*s != '\0' && i != n) { + c_putc(*(s++)); + i++; + } +} + + +/* getc - Syscall n + * get one character of input from the console + * @return ASCII code for character read from console + */ +char c_getc(void) +{ + char c; + + asm ( ".set noreorder\n " + "li $a0, %[syscall]\n" + "syscall\n" + "nop\n" + "move %[charout], $v0 \n" + ".set reorder\n" + : [charout] "=r" (c) + : [syscall] "g" (GETC) + : "a0","v0" + ); + + return c; +} + +/* gets - wrapper for getc + * reads up to n characters into buffer b + * @param b Buffer to read characters into + * @param n size of buffer + * @return the number of characters read into b + */ +int c_gets(char *b, int n) +{ + int i = 0; + do { + b[i] = c_getc(); + c_putc(b[i]); + i++; + if (b[i - 1] == '\n' || b[i-1] == '\r') { + break; + } + else if (b[i - 1] == 0x8) { + i--; + } + } while (i < n); + + b[i - 1] = '\0'; + + return i; + +} + +/* c_version - get version string + * @return pointer to version string + */ +char *c_verstr(void) +{ + char *c; + + asm ( ".set noreorder\n" + "li $a0, %[syscall]\n" + "syscall\n" + "nop\n" + "move %[result], $v0\n" + ".set reorder\n" + : [result] "=r" (c) + : [syscall] "g" (VERSION) + : "a0", "v0" + ); + + return c; +} + +/* memsz - get total memory size (in bytes) + * @return the size of the memory installed in the router, in bytes + */ +int c_memsz(void) +{ + int r = 0; + + asm ( " .set noreorder \n" + "li $a0, %[syscall]\n" + "syscall\n" + "nop\n" + "move %[result], $v0\n" + ".set reorder\n" + : [result] "=r" (r) + : [syscall] "g" (MEMSIZE) + : "a0","v0" + ); + + return r; +} + +/* timer - get number of ticks from timer + * @return the value in the timer + */ +long c_timer(void) +{ + long t = 0; + + asm (" .set noreorder\n" + "li $a0, %[syscall]\n" + "syscall\n" + "nop\n" + "move %[result], $a0\n" + ".set reorder\n" + : [result]"=r"(t) + : [syscall]"g"(TIMER) + : "a0","v0" + ); + + return t; +} + +/* String length with a maximum length allowed + * @param s pointer to string + * @param maxlen maximum length + */ +int c_strnlen(const char *s, int maxlen) +{ + int i = 0; + if (!s) return 0; + + while (*(s++) != '\0' && i != maxlen) { + i++; + } + + return i; +} + +/* baud - get console baud rate + * @return boot console baud rate + */ +int c_baud(void) +{ + int b = 0; + + asm volatile (".set noreorder\n" + "li $a0, %[syscall]\n" + "syscall\n" + "nop\n" + "move %[result], $a0\n" + ".set reorder\n" + : [result]"=r"(b) + : [syscall]"g"(GETBAUD) + : "a0", "v0" + ); + + return b; +} diff --git a/mach/c7200/start.S b/mach/c7200/start.S new file mode 100644 index 0000000..1409c3c --- /dev/null +++ b/mach/c7200/start.S @@ -0,0 +1,52 @@ +/* Initial entry point for ciscoboot. Sets up some stack at 0x80008000 + * and jumps to main + */ + +#include +#include + +EXPORT(_start) + +.extern start_bootloader + +LEAF(_start) + .set noreorder + li sp, 0x80008000 + + /* Save return address */ + sw ra, -4(sp) + + /* print out a letter C */ + li a0, 1 + li a1, 67 + syscall + nop + + /* get the total amount of RAM */ + li a0, 4 + syscall + nop + + /* set the stack at the top of RAM */ + li sp, 0x80000000 + add sp, sp, v0 + + /* save return address*/ + /*sw ra, -4(sp) + + addi sp, sp, -4 */ + + /* start bootloader */ + jal start_bootloader + nop + + /* bootloader failed for some reason: */ + li sp, 0x80008000 + + /* re-load return address to ROM: */ + ld ra, -4(sp) + + jr ra + + .set reorder + END(_start)