aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Lohoff <flo@rfc822.org>2008-11-29 12:16:56 +0000
committerGuido G√ľnther <agx@sigxcpu.org>2009-04-26 15:26:27 +0200
commit7b4ca7013c58a67f1ec41478b1bfc250b3485d28 (patch)
treef759f75d5ac13dda6c581c3f6357d976b6cb593a
parent4ce5705be57a10598775d14cc1b8a6296df9c653 (diff)
Add basic SNIRM support
Add basic SNIRM support - Currently has a hardcoded boot location but you get the idea.
-rw-r--r--Makefile11
-rw-r--r--common/prom.h7
-rw-r--r--common/subarch.h1
-rw-r--r--ext2load/Makefile16
-rw-r--r--snilib/Makefile20
-rw-r--r--snilib/sniprom.c181
-rw-r--r--snilib/sniprom.h59
-rw-r--r--tip22/Makefile19
-rw-r--r--tip22/tftpload.c4
9 files changed, 302 insertions, 16 deletions
diff --git a/Makefile b/Makefile
index 7bac668..bae197b 100644
--- a/Makefile
+++ b/Makefile
@@ -12,12 +12,21 @@ KERNELADDR=0x88002000
MAXLOADSIZE=0x1700000
LOADADDR=0x88802000
OUTPUTFORMAT=ecoff-bigmips
+ARCHLIB=arclib
endif
ifeq ($(SUBARCH),IP32)
KERNELADDR=0x80004000
MAXLOADSIZE=0x1400000
LOADADDR=0x81404000
OUTPUTFORMAT=elf32-tradbigmips
+ARCHLIB=arclib
+endif
+ifeq ($(SUBARCH),SNIRM)
+KERNELADDR=0x80030000
+MAXLOADSIZE=0x400000
+LOADADDR=0x80e00000
+OUTPUTFORMAT=elf32-tradbigmips
+ARCHLIB=snilib
endif
# these contain subarch independent files
@@ -26,7 +35,7 @@ SUBARCH_INDEP_DIRS= \
# these contain subarch dependent files
SUBARCH_DIRS= \
common \
- arclib \
+ $(ARCHLIB) \
ext2load \
tip22
diff --git a/common/prom.h b/common/prom.h
index 1a3acf5..9f81e76 100644
--- a/common/prom.h
+++ b/common/prom.h
@@ -1,4 +1,11 @@
+
+/*
+ * Gets called before anything else - even the first printf
+ *
+ */
+void prom_init(void );
+
void prom_restart(void );
void prom_return_interactive(void );
void prom_flush_cache_all(void );
diff --git a/common/subarch.h b/common/subarch.h
index 28e2d1d..284d6ed 100644
--- a/common/subarch.h
+++ b/common/subarch.h
@@ -10,5 +10,6 @@
#define PAGE_SIZE 4096
#define STACK_PAGES 16
#define KSEG0ADDR(addr) (((addr) & 0x1fffffff) | 0x80000000)
+#define KSEG1ADDR(addr) (((addr) & 0x1fffffff) | 0xa0000000)
#endif
diff --git a/ext2load/Makefile b/ext2load/Makefile
index f10d678..3d441a8 100644
--- a/ext2load/Makefile
+++ b/ext2load/Makefile
@@ -11,17 +11,23 @@ E2FSINCLUDEDIR ?= /usr/include/ext2fs
E2FSLIBDIR ?= /usr/lib
EXT2LIB ?= $(E2FSLIBDIR)/libext2fs-nopic.a
-ARCINCLUDEDIR = ../arclib
-ARCLIBDIR = ../arclib
-ARCLIB = $(ARCLIBDIR)/libarc.a
+ifeq ($(SUBARCH),SNIRM)
+PROMINCLUDEDIR = ../snilib
+PROMLIBDIR = ../snilib
+PROMLIB = $(PROMLIBDIR)/libsni.a
+else
+PROMINCLUDEDIR = ../arclib
+PROMLIBDIR = ../arclib
+PROMLIB = $(PROMLIBDIR)/libarc.a
+endif
LIBC = ../common/libc.a
OBJECTS = loader.o ext2io.o conffile.o
-LIBS = $(EXT2LIB) $(LIBC) $(ARCLIB)
+LIBS = $(EXT2LIB) $(LIBC) $(PROMLIB)
TARGETS = ext2load
-CFLAGS = -O2 -I$(COMMONDIR) -I$(ARCINCLUDEDIR) -I$(E2FSINCLUDEDIR) \
+CFLAGS = -O2 -I$(COMMONDIR) -I$(PROMINCLUDEDIR) -I$(E2FSINCLUDEDIR) \
-W -Wall -mno-abicalls -G 0 -fno-pic \
-DSUBARCH=${SUBARCH} -fno-strict-aliasing
diff --git a/snilib/Makefile b/snilib/Makefile
new file mode 100644
index 0000000..4e6ec18
--- /dev/null
+++ b/snilib/Makefile
@@ -0,0 +1,20 @@
+#
+# Copyright 1999 Silicon Graphics, Inc.
+#
+CFLAGS += -O2 -I../common -mno-abicalls -G 0 -fno-pic -ffreestanding -DDEBUG
+
+TARGETS = libsni.a
+OBJECTS = sniprom.o
+
+all: $(TARGETS)
+
+$(TARGETS): $(OBJECTS)
+ rm -f $@
+ $(AR) -crs $@ $(OBJECTS)
+
+install: $(TARGETS)
+ install -d ${PREFIX}/${LIBDIR}
+ install -m 644 $< ${PREFIX}/${LIBDIR}
+
+clean:
+ rm -f libsni.a $(OBJECTS) *~ tags
diff --git a/snilib/sniprom.c b/snilib/sniprom.c
new file mode 100644
index 0000000..fa5acc1
--- /dev/null
+++ b/snilib/sniprom.c
@@ -0,0 +1,181 @@
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <subarch.h>
+#include "sniprom.h"
+
+#define MAX_ARG 64
+
+static char *iargv[MAX_ARG];
+static int iargc=0;
+static char *label=NULL;
+
+extern unsigned long _end;
+
+void prom_wait(const char *prompt) {
+ printf("%s: called\n\r", __FUNCTION__);
+}
+
+void prom_fatal(const char *message, ...) {
+ va_list ap;
+
+ if (message != NULL) {
+ printf("FATAL ERROR: ");
+ va_start(ap, message);
+ vprintf(message, ap);
+ va_end(ap);
+ }
+
+ prom_wait("\n\r--- Press <spacebar> to enter ARC interactive mode ---");
+ __prom_reset();
+}
+
+int (*__prom_lseek)(FILE, int, int) = NULL;
+
+
+/*
+ * The SNI Prom does not contain an official entry point for "prom_seek" which is
+ * a pain and basically is a showstopper for bootloaders. There is a seek function
+ * though which seems to be inbetween prom_open and prom_read. We try to find
+ * it by looking for the function prolog e.g. the $sp setup. We then know the
+ * address of the seek. flo@rfc822.org 2007-08-13
+ */
+
+void prom_init(void ) {
+ unsigned int jump;
+ unsigned int *readaddr,
+ *openaddr,
+ *saddr;
+
+ jump = *((unsigned int *)PROM_ENTRY(PROM_READ));
+ readaddr=(unsigned int *) (((jump & 0x03ffffff)<<2)|0xb0000000);
+ jump = *((unsigned int *)PROM_ENTRY(PROM_OPEN));
+ openaddr= (unsigned int *) (((jump & 0x03ffffff)<<2)|0xb0000000);
+
+ for(saddr=readaddr-1;saddr>openaddr;saddr--) {
+ /* Search for addiu $sp, negative */
+ if ((*saddr & 0xffff8000) == 0x27bd8000) {
+ __prom_lseek=(void *) saddr;
+ break;
+ }
+ }
+
+ if (__prom_lseek == NULL)
+ prom_fatal("Didnt find prom_seek prolog between open and read\n\r");
+}
+
+
+/* Give 1MByte of memory behind the arcboot to the allocator */
+void prom_init_malloc(unsigned long loadaddr, unsigned long size) {
+ malloc_area_add((unsigned long) &_end, 0x100000);
+}
+
+int prom_seek(FILE stream, long long position, int whence) {
+ int pos32=position, res;
+
+ res=__prom_lseek(stream, pos32, whence);
+
+ if (res != position)
+ prom_fatal("Seek failed\n\r");
+
+ return 0;
+}
+
+void prom_restart(void ) {
+ printf("%s: called\n\r", __FUNCTION__);
+}
+
+void prom_flush_cache_all(void ) {
+ __prom_flushcache();
+}
+
+void prom_return_interactive(void ) {
+ printf("%s: called\n\r", __FUNCTION__);
+}
+
+int prom_write(FILE stream, char *buf, unsigned long len, unsigned long *rlen) {
+ int res;
+ /* SNI returns no status but standard conform length */
+ res=__prom_write(stream, buf, len);
+ *rlen=res;
+ return res<0;
+}
+
+/*
+ * We have seen larger reads to fail on RM200C Prom Version 5
+ * and RM400 Prom Version 4. It seems this is secondary cache related. As we
+ * would like to use the read-ahead and cache we simply split the reads into
+ * smaller chunks here.
+ *
+ */
+int prom_read(FILE stream, char *buf, unsigned long len, unsigned long *rlen) {
+ int res=0,i;
+ int read=0, thisread;
+
+ while(read < len) {
+ int left=len-read;
+ if (left > 4096)
+ thisread=4096;
+ else
+ thisread=left;
+
+ res=__prom_read(stream, buf+read, thisread);
+
+ read+=thisread;
+
+ if (res < thisread)
+ break;
+ }
+ *rlen=read;
+
+ return (len > read);
+}
+
+int prom_open(char *name, int mode, FILE *stream) {
+ int res;
+ res=__prom_open(name, mode);
+ *stream=res;
+ return 0;
+}
+
+int prom_close(FILE stream) {
+ return 0;
+}
+
+void prom_add_arg(char *arg) {
+ iargv[iargc++]=strdup(arg);
+}
+
+/*
+ * dkncr(0,0,10) label cmd line arg
+ * Kernel drops argv[0] so we need to add dkncr... and drop the label
+ *
+ */
+int prom_parse_args(int argc, char **argv) {
+ int i;
+ prom_add_arg(argv[0]);
+ if (argc > 1)
+ label=strdup(argv[1]);
+ for(i=2;i<argc;i++ )
+ prom_add_arg(argv[i]);
+ return iargc;
+}
+
+char *prom_get_label(void ) {
+ return (label) ? label : "linux";
+}
+
+char *prom_get_partition(void ) {
+ return "dkncr(0,0,1)";
+}
+
+char *prom_get_options(void ) {
+ return NULL;
+}
+
+void prom_get_karg(int *argc, char ***argv) {
+ *argc=iargc;
+ *argv=iargv;
+}
diff --git a/snilib/sniprom.h b/snilib/sniprom.h
new file mode 100644
index 0000000..db079ad
--- /dev/null
+++ b/snilib/sniprom.h
@@ -0,0 +1,59 @@
+
+#include <subarch.h>
+
+#define PROM_VEC KSEG1ADDR(0x1fc00000)
+#define PROM_ENTRY(x) (PROM_VEC + (x*8))
+
+#define PROM_RESET 0
+#define PROM_OPEN 6
+#define PROM_READ 7
+#define PROM_WRITE 8
+//#define PROM_SEEK 8
+#define PROM_PUTCHAR 12
+#define PROM_FLUSHCACHE 28
+#define PROM_CLEARCACHE 29
+#define PROM_GETENV 33
+#define PROM_GET_MEMCONF 58
+
+
+typedef struct {
+ unsigned int size;
+ unsigned int base;
+ unsigned int size2;
+ unsigned int pad1;
+ unsigned int pad2;
+} MEMBANK;
+
+typedef struct {
+ MEMBANK bank[8];
+} MEMCONF;
+
+static inline int __prom_get_memconf(MEMCONF *mc) {
+ return ((int (*)(MEMCONF *))PROM_ENTRY(PROM_GET_MEMCONF))(mc);
+}
+
+static inline int __prom_putchar(char a) {
+ return ((int (*)(int))PROM_ENTRY(PROM_PUTCHAR))(a);
+}
+
+static inline int __prom_open(char *filename, int mode) {
+ return ((int (*)(char *, int))PROM_ENTRY(PROM_OPEN))(filename, mode);
+}
+
+static inline int __prom_write(FILE stream, char *buf, unsigned long len) {
+ return ((int (*)(FILE, char *, unsigned long))PROM_ENTRY(PROM_WRITE))
+ (stream, buf, len);
+}
+
+static inline int __prom_read(FILE stream, char *buf, unsigned long len) {
+ return ((int (*)(FILE, char *, unsigned long))PROM_ENTRY(PROM_READ))
+ (stream, buf, len);
+}
+
+static inline void __prom_reset(void ) {
+ ((void (*)(void ))PROM_ENTRY(PROM_RESET))();
+}
+
+static inline void __prom_flushcache(void) {
+ ((void (*)(void ))PROM_ENTRY(PROM_FLUSHCACHE))();
+}
diff --git a/tip22/Makefile b/tip22/Makefile
index 48829b4..27ba0ce 100644
--- a/tip22/Makefile
+++ b/tip22/Makefile
@@ -2,12 +2,19 @@
# Copyright 2002-2004 Guido Guenther <agx@sigxcpu.org>
#
-ARCLIBDIR = ../arclib
-ARCLIB = $(ARCLIBDIR)/libarc.a
+ifeq ($(SUBARCH),SNIRM)
+PROMINCLUDEDIR = ../snilib
+PROMLIBDIR = ../snilib
+PROMLIB = $(PROMLIBDIR)/libsni.a
+else
+PROMINCLUDEDIR = ../arclib
+PROMLIBDIR = ../arclib
+PROMLIB = $(PROMLIBDIR)/libarc.a
+endif
COMMONDIR = ../common
-CFLAGS += -O2 -I$(COMMONDIR) -I$(ARCLIBDIR) -Wall -mno-abicalls -G 0 \
+CFLAGS += -O2 -I$(COMMONDIR) -I$(PROMLIBDIR) -Wall -mno-abicalls -G 0 \
-fno-pic -DSUBARCH=${SUBARCH}
ASFLAGS = -O2 -mno-abicalls -G 0 -fno-pic
@@ -15,7 +22,7 @@ ASFLAGS = -O2 -mno-abicalls -G 0 -fno-pic
LIBDIR ?= /usr/lib/tip22
BINDIR ?= /usr/sbin
-LIBS=${ARCLIB}
+LIBS=${PROMLIB}
BINS=tip22 tip32
LD_SCRIPTS = ld.kernel.script ld.ramdisk.script ld.script
OBJECTS = tftpload.o
@@ -29,7 +36,7 @@ all: ${LIBS} $(TARGETS)
$(ARCLIB):
- @$(MAKE) -C $(ARCLIBDIR)
+ @$(MAKE) -C $(PROMLIBDIR)
$(PRINT_LOADADDR):
@$(MAKE) -C $(COMMONDIR) SUBARCH=$(SUBARCH)
@@ -45,7 +52,7 @@ $(PRINT_LOADADDR):
-e "s/@@OUTPUTFORMAT@@/$$OUTPUTFORMAT/" <$< >$@
clean:
- @$(MAKE) -C $(ARCLIBDIR) clean
+ @$(MAKE) -C $(PROMLIBDIR) clean
@$(MAKE) -C $(COMMONDIR) clean
rm -f $(TARGETS)
diff --git a/tip22/tftpload.c b/tip22/tftpload.c
index ed31e15..e048399 100644
--- a/tip22/tftpload.c
+++ b/tip22/tftpload.c
@@ -9,9 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <types.h>
-#include <arc.h>
#include <prom.h>
#include <elf.h>
@@ -20,8 +18,6 @@
#include <version.h>
#include <subarch.h>
-#define KSEG0ADDR(addr) (((addr) & 0x1fffffff) | 0x80000000)
-
#define ANSI_CLEAR "\033[2J"
extern void* __kernel_start;