Added C7200 support (thanks to V�g� Tibor).
parent
b5ecd94191
commit
1e53ccbe5c
@ -0,0 +1,3 @@
|
|||||||
|
*.o
|
||||||
|
*.elf
|
||||||
|
*.bin
|
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef _INCLUDE_MACH_C7200_PLATFORM_H
|
||||||
|
#define _INCLUDE_MACH_C7200_PLATFORM_H
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#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 */
|
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef _INCLUDE_MACH_C7200_PLATIO
|
||||||
|
#define _INCLUDE_MACH_C7200_PLATIO
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <ciloio.h>
|
||||||
|
|
||||||
|
/* 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 */
|
@ -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
|
@ -0,0 +1,44 @@
|
|||||||
|
#include <types.h>
|
||||||
|
#include <mach/c7200/platform.h>
|
||||||
|
#include <mach/c7200/platio.h>
|
||||||
|
#include <printf.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/* Platform specific operations for I/O for the cisco 7200 Series
|
||||||
|
* (C) 2008 Philippe Vachon <philippe@cowpig.ca>
|
||||||
|
*
|
||||||
|
* Licensed under the GNU General Public License v2.
|
||||||
|
*/
|
||||||
|
#include <types.h>
|
||||||
|
#include <mach/c7200/platio.h>
|
||||||
|
#include <ciloio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <mach/c7200/platform.h>
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,206 @@
|
|||||||
|
/**
|
||||||
|
* PROM Library for Cisco Systems 7200 Series Routers
|
||||||
|
* (C) 2008 Philippe Vachon <philippe@cowpig.ca>
|
||||||
|
* -----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calling convention:
|
||||||
|
* a0 - syscall number
|
||||||
|
* a1 - arg1 ... etc
|
||||||
|
* v0 - returned value from syscall
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <promlib.h>
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/* Initial entry point for ciscoboot. Sets up some stack at 0x80008000
|
||||||
|
* and jumps to main
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm/regdef.h>
|
||||||
|
#include <asm/asm.h>
|
||||||
|
|
||||||
|
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)
|
Loading…
Reference in New Issue