summaryrefslogtreecommitdiff
path: root/sys/src/boot/bitsy
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/boot/bitsy
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/boot/bitsy')
-rwxr-xr-xsys/src/boot/bitsy/dat.h0
-rwxr-xr-xsys/src/boot/bitsy/donprint.c332
-rwxr-xr-xsys/src/boot/bitsy/fns.h7
-rwxr-xr-xsys/src/boot/bitsy/il.s99
-rwxr-xr-xsys/src/boot/bitsy/imain.c48
-rwxr-xr-xsys/src/boot/bitsy/inflate.c208
-rwxr-xr-xsys/src/boot/bitsy/io.h261
-rwxr-xr-xsys/src/boot/bitsy/l.s454
-rwxr-xr-xsys/src/boot/bitsy/lib.h143
-rwxr-xr-xsys/src/boot/bitsy/map10
-rwxr-xr-xsys/src/boot/bitsy/mem.h213
-rwxr-xr-xsys/src/boot/bitsy/mkfile45
-rwxr-xr-xsys/src/boot/bitsy/print.c56
-rwxr-xr-xsys/src/boot/bitsy/sinflatebin0 -> 20696 bytes
-rwxr-xr-xsys/src/boot/bitsy/uart.c69
15 files changed, 1945 insertions, 0 deletions
diff --git a/sys/src/boot/bitsy/dat.h b/sys/src/boot/bitsy/dat.h
new file mode 100755
index 000000000..e69de29bb
--- /dev/null
+++ b/sys/src/boot/bitsy/dat.h
diff --git a/sys/src/boot/bitsy/donprint.c b/sys/src/boot/bitsy/donprint.c
new file mode 100755
index 000000000..4125e6904
--- /dev/null
+++ b/sys/src/boot/bitsy/donprint.c
@@ -0,0 +1,332 @@
+#include "u.h"
+#include "lib.h"
+
+#define PTR sizeof(char*)
+#define SHORT sizeof(int)
+#define INT sizeof(int)
+#define LONG sizeof(long)
+#define IDIGIT 30
+#define MAXCON 30
+
+#define FLONG (1<<0)
+#define FSHORT (1<<1)
+#define FUNSIGN (1<<2)
+
+typedef struct Op Op;
+struct Op
+{
+ char *p;
+ char *ep;
+ void *argp;
+ int f1;
+ int f2;
+ int f3;
+};
+
+static int noconv(Op*);
+static int cconv(Op*);
+static int dconv(Op*);
+static int hconv(Op*);
+static int lconv(Op*);
+static int oconv(Op*);
+static int sconv(Op*);
+static int uconv(Op*);
+static int xconv(Op*);
+static int Xconv(Op*);
+static int percent(Op*);
+
+static
+int (*fmtconv[MAXCON])(Op*) =
+{
+ noconv,
+ cconv, dconv, hconv, lconv,
+ oconv, sconv, uconv, xconv,
+ Xconv, percent,
+};
+static
+char fmtindex[128] =
+{
+ ['c'] 1,
+ ['d'] 2,
+ ['h'] 3,
+ ['l'] 4,
+ ['o'] 5,
+ ['s'] 6,
+ ['u'] 7,
+ ['x'] 8,
+ ['X'] 9,
+ ['%'] 10,
+};
+
+static int convcount = { 11 };
+static int ucase;
+
+static void
+PUT(Op *o, int c)
+{
+ static int pos;
+ int opos;
+
+ if(c == '\t'){
+ opos = pos;
+ pos = (opos+8) & ~7;
+ while(opos++ < pos && o->p < o->ep)
+ *o->p++ = ' ';
+ return;
+ }
+ if(o->p < o->ep){
+ *o->p++ = c;
+ pos++;
+ }
+ if(c == '\n')
+ pos = 0;
+}
+
+int
+fmtinstall(char c, int (*f)(Op*))
+{
+
+ c &= 0177;
+ if(fmtindex[c] == 0) {
+ if(convcount >= MAXCON)
+ return 1;
+ fmtindex[c] = convcount++;
+ }
+ fmtconv[fmtindex[c]] = f;
+ return 0;
+}
+
+char*
+donprint(char *p, char *ep, char *fmt, void *argp)
+{
+ int sf1, c;
+ Op o;
+
+ o.p = p;
+ o.ep = ep;
+ o.argp = argp;
+
+loop:
+ c = *fmt++;
+ if(c != '%') {
+ if(c == 0) {
+ if(o.p < o.ep)
+ *o.p = 0;
+ return o.p;
+ }
+ PUT(&o, c);
+ goto loop;
+ }
+ o.f1 = 0;
+ o.f2 = -1;
+ o.f3 = 0;
+ c = *fmt++;
+ sf1 = 0;
+ if(c == '-') {
+ sf1 = 1;
+ c = *fmt++;
+ }
+ while(c >= '0' && c <= '9') {
+ o.f1 = o.f1*10 + c-'0';
+ c = *fmt++;
+ }
+ if(sf1)
+ o.f1 = -o.f1;
+ if(c != '.')
+ goto l1;
+ c = *fmt++;
+ while(c >= '0' && c <= '9') {
+ if(o.f2 < 0)
+ o.f2 = 0;
+ o.f2 = o.f2*10 + c-'0';
+ c = *fmt++;
+ }
+l1:
+ if(c == 0)
+ fmt--;
+ c = (*fmtconv[fmtindex[c&0177]])(&o);
+ if(c < 0) {
+ o.f3 |= -c;
+ c = *fmt++;
+ goto l1;
+ }
+ o.argp = (char*)o.argp + c;
+ goto loop;
+}
+
+void
+strconv(char *o, Op *op, int f1, int f2)
+{
+ int n, c;
+ char *p;
+
+ n = strlen(o);
+ if(f1 >= 0)
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ for(p=o; c = *p++;)
+ if(f2 != 0) {
+ PUT(op, c);
+ f2--;
+ }
+ if(f1 < 0) {
+ f1 = -f1;
+ while(n < f1) {
+ PUT(op, ' ');
+ n++;
+ }
+ }
+}
+
+int
+numbconv(Op *op, int base)
+{
+ char b[IDIGIT];
+ int i, f, n, r;
+ long v;
+ short h;
+
+ f = 0;
+ switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) {
+ case FLONG:
+ v = *(long*)op->argp;
+ r = LONG;
+ break;
+
+ case FUNSIGN|FLONG:
+ v = *(ulong*)op->argp;
+ r = LONG;
+ break;
+
+ case FSHORT:
+ h = *(int*)op->argp;
+ v = h;
+ r = SHORT;
+ break;
+
+ case FUNSIGN|FSHORT:
+ h = *(int*)op->argp;
+ v = (ushort)h;
+ r = SHORT;
+ break;
+
+ default:
+ v = *(int*)op->argp;
+ r = INT;
+ break;
+
+ case FUNSIGN:
+ v = *(unsigned*)op->argp;
+ r = INT;
+ break;
+ }
+ if(!(op->f3 & FUNSIGN) && v < 0) {
+ v = -v;
+ f = 1;
+ }
+ b[IDIGIT-1] = 0;
+ for(i = IDIGIT-2;; i--) {
+ n = (ulong)v % base;
+ n += '0';
+ if(n > '9'){
+ n += 'a' - ('9'+1);
+ if(ucase)
+ n += 'A'-'a';
+ }
+ b[i] = n;
+ if(i < 2)
+ break;
+ v = (ulong)v / base;
+ if(op->f2 >= 0 && i >= IDIGIT-op->f2)
+ continue;
+ if(v <= 0)
+ break;
+ }
+ if(f)
+ b[--i] = '-';
+ strconv(b+i, op, op->f1, -1);
+ return r;
+}
+
+static int
+noconv(Op *op)
+{
+
+ strconv("***", op, 0, -1);
+ return 0;
+}
+
+static int
+cconv(Op *op)
+{
+ char b[2];
+
+ b[0] = *(int*)op->argp;
+ b[1] = 0;
+ strconv(b, op, op->f1, -1);
+ return INT;
+}
+
+static int
+dconv(Op *op)
+{
+ return numbconv(op, 10);
+}
+
+static int
+hconv(Op*)
+{
+ return -FSHORT;
+}
+
+static int
+lconv(Op*)
+{
+ return -FLONG;
+}
+
+static int
+oconv(Op *op)
+{
+ return numbconv(op, 8);
+}
+
+static int
+sconv(Op *op)
+{
+ strconv(*(char**)op->argp, op, op->f1, op->f2);
+ return PTR;
+}
+
+static int
+uconv(Op*)
+{
+ return -FUNSIGN;
+}
+
+static int
+xconv(Op *op)
+{
+ return numbconv(op, 16);
+}
+
+static int
+Xconv(Op *op)
+{
+ int r;
+
+ ucase = 1;
+ r = numbconv(op, 16);
+ ucase = 0;
+ return r;
+}
+
+static int
+percent(Op *op)
+{
+
+ PUT(op, '%');
+ return 0;
+}
diff --git a/sys/src/boot/bitsy/fns.h b/sys/src/boot/bitsy/fns.h
new file mode 100755
index 000000000..53af19bf0
--- /dev/null
+++ b/sys/src/boot/bitsy/fns.h
@@ -0,0 +1,7 @@
+/*
+ * functions defined locally
+ */
+extern int gunzip(uchar *out, int outn, uchar *in, int inn);
+extern void delay(int ms);
+extern void serialputs(char *str, int n);
+extern void draincache(void);
diff --git a/sys/src/boot/bitsy/il.s b/sys/src/boot/bitsy/il.s
new file mode 100755
index 000000000..c75ad987d
--- /dev/null
+++ b/sys/src/boot/bitsy/il.s
@@ -0,0 +1,99 @@
+#include "mem.h"
+/*
+ * Entered here from Compaq's bootldr. First relocate to
+ * the location we're linked for and then copy back the
+ * decompressed kernel.
+ *
+ * All
+ */
+TEXT _start(SB), $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+ MOVW $1, R0 /* dance to make 5l think that the magic */
+ MOVW $1, R1 /* numbers in WORDs below are being used */
+ CMP.S R0, R1 /* and to align them to where bootldr wants */
+ BEQ _start2
+ WORD $0x016f2818 /* magic number to say we are a kernel */
+ WORD $0xc0008000 /* entry point address */
+ WORD $0 /* size?, or end of data? */
+
+_start2:
+
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+
+ /* disable the MMU */
+ MOVW $0x130, R1
+ MCR CpMMU, 0, R1, C(CpControl), C(0x0)
+
+ /* enable caches */
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ ORR $(CpCdcache|CpCicache|CpCwb), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+
+ /* flush caches */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+
+ /* relocate to where we expect to be */
+ MOVW $(512*1024),R3
+ MOVW $0xC0008000,R1
+ MOVW $0xC0200000,R2
+ ADD R1,R3
+_relloop:
+ MOVW (R1),R0
+ MOVW R0,(R2)
+ ADD $4,R1
+ ADD $4,R2
+ CMP.S R1,R3
+ BNE _relloop
+
+ MOVW $(MACHADDR+BY2PG), R13 /* stack */
+ SUB $4, R13 /* link */
+
+ /* jump to where we've been relocated */
+ MOVW $_relocated(SB),R15
+
+TEXT _relocated(SB),$-4
+ BL main(SB)
+ BL exit(SB)
+ /* we shouldn't get here */
+_mainloop:
+ B _mainloop
+ BL _div(SB) /* hack to get _div etc loaded */
+
+TEXT mypc(SB),$-4
+ MOVW R14,R0
+ RET
+
+TEXT draincache(SB),$-4
+ /* write back any dirty data */
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cfloop:
+ MOVW.P 32(R0),R2
+ CMP.S R0,R1
+ BNE _cfloop
+
+ /* drain write buffer and invalidate i&d cache contents */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+
+ /* disable caches */
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ BIC $(CpCdcache|CpCicache|CpCwb), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
diff --git a/sys/src/boot/bitsy/imain.c b/sys/src/boot/bitsy/imain.c
new file mode 100755
index 000000000..4b8ef2ef2
--- /dev/null
+++ b/sys/src/boot/bitsy/imain.c
@@ -0,0 +1,48 @@
+#include "u.h"
+#include "lib.h"
+#include "fns.h"
+#include "dat.h"
+#include "mem.h"
+
+void
+main(void)
+{
+ void (*f)(void);
+ ulong *kernel;
+
+ print("inflating kernel\n");
+
+ kernel = (ulong*)(0xc0200000+20*1024);
+ if(gunzip((uchar*)0xc0008000, 2*1024*1024, (uchar*)kernel, 512*1024) > 0){
+ f = (void (*)(void))0xc0008010;
+ draincache();
+ } else {
+ print("inflation failed\n");
+ f = nil;
+ }
+ (*f)();
+}
+
+void
+exit(void)
+{
+
+ void (*f)(void);
+
+ delay(1000);
+
+ print("it's a wonderful day to die\n");
+ f = nil;
+ (*f)();
+}
+
+void
+delay(int ms)
+{
+ int i;
+
+ while(ms-- > 0){
+ for(i = 0; i < 1000; i++)
+ ;
+ }
+}
diff --git a/sys/src/boot/bitsy/inflate.c b/sys/src/boot/bitsy/inflate.c
new file mode 100755
index 000000000..abfed034e
--- /dev/null
+++ b/sys/src/boot/bitsy/inflate.c
@@ -0,0 +1,208 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include <flate.h>
+
+typedef struct Biobuf Biobuf;
+
+struct Biobuf
+{
+ uchar *bp;
+ uchar *p;
+ uchar *ep;
+};
+
+static int header(Biobuf*);
+static int trailer(Biobuf*, Biobuf*);
+static int getc(void*);
+static ulong offset(Biobuf*);
+static int crcwrite(void *out, void *buf, int n);
+static ulong get4(Biobuf *b);
+static ulong Boffset(Biobuf *bp);
+
+/* GZIP flags */
+enum {
+ Ftext= (1<<0),
+ Fhcrc= (1<<1),
+ Fextra= (1<<2),
+ Fname= (1<<3),
+ Fcomment= (1<<4),
+
+ GZCRCPOLY = 0xedb88320UL,
+};
+
+static ulong *crctab;
+static ulong crc;
+
+int
+gunzip(uchar *out, int outn, uchar *in, int inn)
+{
+ Biobuf bin, bout;
+ int err;
+
+ crc = 0;
+ crctab = mkcrctab(GZCRCPOLY);
+ err = inflateinit();
+ if(err != FlateOk)
+ print("inflateinit failed: %s\n", flateerr(err));
+
+ bin.bp = bin.p = in;
+ bin.ep = in+inn;
+ bout.bp = bout.p = out;
+ bout.ep = out+outn;
+
+ err = header(&bin);
+ if(err != FlateOk)
+ return err;
+
+ err = inflate(&bout, crcwrite, &bin, getc);
+ if(err != FlateOk)
+ print("inflate failed: %s\n", flateerr(err));
+
+ err = trailer(&bout, &bin);
+ if(err != FlateOk)
+ return err;
+
+ return Boffset(&bout);
+}
+
+static int
+header(Biobuf *bin)
+{
+ int i, flag;
+
+ if(getc(bin) != 0x1f || getc(bin) != 0x8b){
+ print("bad magic\n");
+ return FlateCorrupted;
+ }
+ if(getc(bin) != 8){
+ print("unknown compression type\n");
+ return FlateCorrupted;
+ }
+
+ flag = getc(bin);
+
+ /* mod time */
+ get4(bin);
+
+ /* extra flags */
+ getc(bin);
+
+ /* OS type */
+ getc(bin);
+
+ if(flag & Fextra)
+ for(i=getc(bin); i>0; i--)
+ getc(bin);
+
+ /* name */
+ if(flag&Fname)
+ while(getc(bin) != 0)
+ ;
+
+ /* comment */
+ if(flag&Fcomment)
+ while(getc(bin) != 0)
+ ;
+
+ /* crc16 */
+ if(flag&Fhcrc) {
+ getc(bin);
+ getc(bin);
+ }
+
+ return FlateOk;
+}
+
+static int
+trailer(Biobuf *bout, Biobuf *bin)
+{
+ /* crc32 */
+ ulong x;
+
+ x = get4(bin);
+ if(crc != x){
+ print("crc mismatch %lux %lux\n", crc, x);
+ return FlateCorrupted;
+ }
+
+ /* length */
+ if(get4(bin) != Boffset(bout)){
+ print("bad output len\n");
+ return FlateCorrupted;
+ }
+ return FlateOk;
+}
+
+static ulong
+get4(Biobuf *b)
+{
+ ulong v;
+ int i, c;
+
+ v = 0;
+ for(i = 0; i < 4; i++){
+ c = getc(b);
+ v |= c << (i * 8);
+ }
+ return v;
+}
+
+static int
+getc(void *in)
+{
+ Biobuf *bp = in;
+
+ if((bp->p - bp->bp) % 10000 == 0)
+ print(".");
+ if(bp->p >= bp->ep)
+ return -1;
+ return *bp->p++;
+}
+
+static ulong
+Boffset(Biobuf *bp)
+{
+ return bp->p - bp->bp;
+}
+
+static int
+crcwrite(void *out, void *buf, int n)
+{
+ Biobuf *bp;
+
+ crc = blockcrc(crctab, crc, buf, n);
+ bp = out;
+ if(n > bp->ep-bp->p)
+ n = bp->ep-bp->p;
+ memmove(bp->p, buf, n);
+ bp->p += n;
+ return n;
+}
+
+#undef malloc
+#undef free
+
+static ulong ibrkp = ~0;
+
+void *
+malloc(ulong n)
+{
+ ulong rv;
+
+ if(ibrkp == ~0)
+ ibrkp = ((ulong)end)+1024*1024;
+ n = (n+3)>>2;
+ n <<= 2;
+ rv = ibrkp;
+ ibrkp += n;
+ return (void*)rv;
+}
+
+void
+free(void *)
+{
+}
diff --git a/sys/src/boot/bitsy/io.h b/sys/src/boot/bitsy/io.h
new file mode 100755
index 000000000..6791a6625
--- /dev/null
+++ b/sys/src/boot/bitsy/io.h
@@ -0,0 +1,261 @@
+/*
+ * Definitions for IO devices. Used only in C.
+ */
+
+enum
+{
+ /* hardware counter frequency */
+ ClockFreq= 3686400,
+};
+
+/*
+ * IRQ's defined by SA1100
+ */
+enum
+{
+ IRQgpio0= 0,
+ IRQgpio1= 1,
+ IRQgpio2= 2,
+ IRQgpio3= 3,
+ IRQgpio4= 4,
+ IRQgpio5= 5,
+ IRQgpio6= 6,
+ IRQgpio7= 7,
+ IRQgpio8= 8,
+ IRQgpio9= 9,
+ IRQgpio10= 10,
+ IRQgpiohi= 11,
+ IRQlcd= 12,
+ IRQudc= 13,
+ IRQuart1b= 15,
+ IRQuart2= 16,
+ IRQuart3= 17,
+ IRQmcp= 18,
+ IRQssp= 19,
+ IRQdma0= 20,
+ IRQdma1= 21,
+ IRQdma2= 22,
+ IRQdma3= 23,
+ IRQdma4= 24,
+ IRQdma5= 25,
+ IRQtimer0= 26,
+ IRQtimer1= 27,
+ IRQtimer2= 28,
+ IRQtimer3= 29,
+ IRQsecond= 30,
+ IRQrtc= 31,
+};
+
+/*
+ * GPIO lines (signal names from compaq document). _i indicates input
+ * and _o output.
+ */
+enum
+{
+ GPIO_PWR_ON_i= 1<<0, /* power button */
+ GPIO_UP_IRQ_i= 1<<1, /* microcontroller interrupts */
+ GPIO_LDD8_o= 1<<2, /* LCD data 8-15 */
+ GPIO_LDD9_o= 1<<3,
+ GPIO_LDD10_o= 1<<4,
+ GPIO_LDD11_o= 1<<5,
+ GPIO_LDD12_o= 1<<6,
+ GPIO_LDD13_o= 1<<7,
+ GPIO_LDD14_o= 1<<8,
+ GPIO_LDD15_o= 1<<9,
+ GPIO_CARD_IND1_i= 1<<10, /* card inserted in PCMCIA socket 1 */
+ GPIO_CARD_IRQ1_i= 1<<11, /* PCMCIA socket 1 interrupt */
+ GPIO_CLK_SET0_o= 1<<12, /* clock selects for audio codec */
+ GPIO_CLK_SET1_o= 1<<13,
+ GPIO_L3_SDA_io= 1<<14, /* UDA1341 interface */
+ GPIO_L3_MODE_o= 1<<15,
+ GPIO_L3_SCLK_o= 1<<16,
+ GPIO_CARD_IND0_i= 1<<17, /* card inserted in PCMCIA socket 0 */
+ GPIO_KEY_ACT_i= 1<<18, /* hot key from cradle */
+ GPIO_SYS_CLK_i= 1<<19, /* clock from codec */
+ GPIO_BAT_FAULT_i= 1<<20, /* battery fault */
+ GPIO_CARD_IRQ0_i= 1<<21, /* PCMCIA socket 0 interrupt */
+ GPIO_LOCK_i= 1<<22, /* expansion pack lock/unlock */
+ GPIO_COM_DCD_i= 1<<23, /* DCD from UART3 */
+ GPIO_OPT_IRQ_i= 1<<24, /* expansion pack IRQ */
+ GPIO_COM_CTS_i= 1<<25, /* CTS from UART3 */
+ GPIO_COM_RTS_o= 1<<26, /* RTS to UART3 */
+ GPIO_OPT_IND_i= 1<<27, /* expansion pack inserted */
+
+/* Peripheral Unit GPIO pin assignments: alternate functions */
+ GPIO_SSP_TXD_o= 1<<10, /* SSP Transmit Data */
+ GPIO_SSP_RXD_i= 1<<11, /* SSP Receive Data */
+ GPIO_SSP_SCLK_o= 1<<12, /* SSP Sample CLocK */
+ GPIO_SSP_SFRM_o= 1<<13, /* SSP Sample FRaMe */
+ /* ser. port 1: */
+ GPIO_UART_TXD_o= 1<<14, /* UART Transmit Data */
+ GPIO_UART_RXD_i= 1<<15, /* UART Receive Data */
+ GPIO_SDLC_SCLK_io= 1<<16, /* SDLC Sample CLocK (I/O) */
+ GPIO_SDLC_AAF_o= 1<<17, /* SDLC Abort After Frame */
+ GPIO_UART_SCLK1_i= 1<<18, /* UART Sample CLocK 1 */
+ /* ser. port 4: */
+ GPIO_SSP_CLK_i= 1<<19, /* SSP external CLocK */
+ /* ser. port 3: */
+ GPIO_UART_SCLK3_i= 1<<20, /* UART Sample CLocK 3 */
+ /* ser. port 4: */
+ GPIO_MCP_CLK_i= 1<<21, /* MCP CLocK */
+ /* test controller: */
+ GPIO_TIC_ACK_o= 1<<21, /* TIC ACKnowledge */
+ GPIO_MBGNT_o= 1<<21, /* Memory Bus GraNT */
+ GPIO_TREQA_i= 1<<22, /* TIC REQuest A */
+ GPIO_MBREQ_i= 1<<22, /* Memory Bus REQuest */
+ GPIO_TREQB_i= 1<<23, /* TIC REQuest B */
+ GPIO_1Hz_o= 1<<25, /* 1 Hz clock */
+ GPIO_RCLK_o= 1<<26, /* internal (R) CLocK (O, fcpu/2) */
+ GPIO_32_768kHz_o= 1<<27, /* 32.768 kHz clock (O, RTC) */
+};
+
+/*
+ * types of interrupts
+ */
+enum
+{
+ GPIOrising,
+ GPIOfalling,
+ GPIOboth,
+ IRQ,
+};
+
+/* hardware registers */
+typedef struct Uartregs Uartregs;
+struct Uartregs
+{
+ ulong ctl[4];
+ ulong dummya;
+ ulong data;
+ ulong dummyb;
+ ulong status[2];
+};
+Uartregs *uart3regs;
+
+/* general purpose I/O lines control registers */
+typedef struct GPIOregs GPIOregs;
+struct GPIOregs
+{
+ ulong level; /* 1 == high */
+ ulong direction; /* 1 == output */
+ ulong set; /* a 1 sets the bit, 0 leaves it alone */
+ ulong clear; /* a 1 clears the bit, 0 leaves it alone */
+ ulong rising; /* rising edge detect enable */
+ ulong falling; /* falling edge detect enable */
+ ulong edgestatus; /* writing a 1 bit clears */
+ ulong altfunc; /* turn on alternate function for any set bits */
+};
+
+extern GPIOregs *gpioregs;
+
+/* extra general purpose I/O bits, output only */
+enum
+{
+ EGPIO_prog_flash= 1<<0,
+ EGPIO_pcmcia_reset= 1<<1,
+ EGPIO_exppack_reset= 1<<2,
+ EGPIO_codec_reset= 1<<3,
+ EGPIO_exp_nvram_power= 1<<4,
+ EGPIO_exp_full_power= 1<<5,
+ EGPIO_lcd_3v= 1<<6,
+ EGPIO_rs232_power= 1<<7,
+ EGPIO_lcd_ic_power= 1<<8,
+ EGPIO_ir_power= 1<<9,
+ EGPIO_audio_power= 1<<10,
+ EGPIO_audio_ic_power= 1<<11,
+ EGPIO_audio_mute= 1<<12,
+ EGPIO_fir= 1<<13, /* not set is sir */
+ EGPIO_lcd_5v= 1<<14,
+ EGPIO_lcd_9v= 1<<15,
+};
+extern ulong *egpioreg;
+
+/* Peripheral pin controller registers */
+typedef struct PPCregs PPCregs;
+struct PPCregs {
+ ulong direction;
+ ulong state;
+ ulong assignment;
+ ulong sleepdir;
+ ulong flags;
+};
+extern PPCregs *ppcregs;
+
+/* Synchronous Serial Port controller registers */
+typedef struct SSPregs SSPregs;
+struct SSPregs {
+ ulong control0;
+ ulong control1;
+ ulong dummy0;
+ ulong data;
+ ulong dummy1;
+ ulong status;
+};
+extern SSPregs *sspregs;
+
+/* Multimedia Communications Port controller registers */
+typedef struct MCPregs MCPregs;
+struct MCPregs {
+ ulong control0;
+ ulong reserved0;
+ ulong data0;
+ ulong data1;
+ ulong data2;
+ ulong reserved1;
+ ulong status;
+ ulong reserved[11];
+ ulong control1;
+};
+extern MCPregs *mcpregs;
+
+/*
+ * memory configuration
+ */
+enum
+{
+ /* bit shifts for pcmcia access time counters */
+ MECR_io0= 0,
+ MECR_attr0= 5,
+ MECR_mem0= 10,
+ MECR_fast0= 11,
+ MECR_io1= MECR_io0+16,
+ MECR_attr1= MECR_attr0+16,
+ MECR_mem1= MECR_mem0+16,
+ MECR_fast1= MECR_fast0+16,
+};
+
+typedef struct MemConfRegs MemConfRegs;
+struct MemConfRegs
+{
+ ulong mdcnfg; /* dram */
+ ulong mdcas00; /* dram banks 0/1 */
+ ulong mdcas01;
+ ulong mdcas02;
+ ulong msc0; /* static */
+ ulong msc1;
+ ulong mecr; /* pcmcia */
+ ulong mdrefr; /* dram refresh */
+ ulong mdcas20; /* dram banks 2/3 */
+ ulong mdcas21;
+ ulong mdcas22;
+ ulong msc2; /* static */
+ ulong smcnfg; /* SMROM config */
+};
+extern MemConfRegs *memconfregs;
+
+/*
+ * power management
+ */
+typedef struct PowerRegs PowerRegs;
+struct PowerRegs
+{
+ ulong pmcr; /* Power manager control register */
+ ulong pssr; /* Power manager sleep status register */
+ ulong pspr; /* Power manager scratch pad register */
+ ulong pwer; /* Power manager wakeup enable register */
+ ulong pcfr; /* Power manager general configuration register */
+ ulong ppcr; /* Power manager PPL configuration register */
+ ulong pgsr; /* Power manager GPIO sleep state register */
+ ulong posr; /* Power manager oscillator status register */
+};
+extern PowerRegs *powerregs;
diff --git a/sys/src/boot/bitsy/l.s b/sys/src/boot/bitsy/l.s
new file mode 100755
index 000000000..0afdb8baf
--- /dev/null
+++ b/sys/src/boot/bitsy/l.s
@@ -0,0 +1,454 @@
+#include "mem.h"
+
+/*
+ * Entered here from Compaq's bootldr with MMU disabled.
+ */
+TEXT _start(SB), $-4
+ MOVW $setR12(SB), R12 /* load the SB */
+_main:
+ /* SVC mode, interrupts disabled */
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1
+ MOVW R1, CPSR
+
+ /* disable the MMU */
+ MOVW $0x130, R1
+ MCR CpMMU, 0, R1, C(CpControl), C(0x0)
+
+ /* flush caches */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+
+ MOVW $(MACHADDR+BY2PG), R13 /* stack */
+ SUB $4, R13 /* link */
+ BL main(SB)
+ BL exit(SB)
+ /* we shouldn't get here */
+_mainloop:
+ B _mainloop
+ BL _div(SB) /* hack to get _div etc loaded */
+
+/* flush tlb's */
+TEXT mmuinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
+ RET
+
+/* flush tlb's */
+TEXT mmuinvalidateaddr(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
+ RET
+
+/* write back and invalidate i and d caches */
+TEXT cacheflush(SB), $-4
+ /* write back any dirty data */
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cfloop:
+ MOVW.P 32(R0),R2
+ CMP.S R0,R1
+ BNE _cfloop
+
+ /* drain write buffer and invalidate i&d cache contents */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
+
+ /* drain prefetch */
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ RET
+
+/* write back d cache */
+TEXT cachewb(SB), $-4
+ /* write back any dirty data */
+_cachewb:
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cwbloop:
+ MOVW.P 32(R0),R2
+ CMP.S R0,R1
+ BNE _cwbloop
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ RET
+
+/* write back a single cache line */
+TEXT cachewbaddr(SB), $-4
+ BIC $31,R0
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+ B _wbflush
+
+/* write back a region of cache lines */
+TEXT cachewbregion(SB), $-4
+ MOVW 4(FP),R1
+ CMP.S $(4*1024),R1
+ BGT _cachewb
+ ADD R0,R1
+ BIC $31,R0
+_cwbrloop:
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+ ADD $32,R0
+ CMP.S R0,R1
+ BGT _cwbrloop
+ B _wbflush
+
+/* invalidate the dcache */
+TEXT dcacheinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
+ RET
+
+/* invalidate the icache */
+TEXT icacheinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
+ RET
+
+/* drain write buffer */
+TEXT wbflush(SB), $-4
+_wbflush:
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ RET
+
+/* return cpu id */
+TEXT getcpuid(SB), $-4
+ MRC CpMMU, 0, R0, C(CpCPUID), C(0x0)
+ RET
+
+/* return fault status */
+TEXT getfsr(SB), $-4
+ MRC CpMMU, 0, R0, C(CpFSR), C(0x0)
+ RET
+
+/* return fault address */
+TEXT getfar(SB), $-4
+ MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
+ RET
+
+/* return fault address */
+TEXT putfar(SB), $-4
+ MRC CpMMU, 0, R0, C(CpFAR), C(0x0)
+ RET
+
+/* set the translation table base */
+TEXT putttb(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTTB), C(0x0)
+ RET
+
+/*
+ * enable mmu, i and d caches
+ */
+TEXT mmuenable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ ORR $(CpCmmuena|CpCdcache|CpCicache|CpCwb), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+TEXT mmudisable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ BIC $(CpCmmuena|CpCdcache|CpCicache|CpCwb|CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+/*
+ * use exception vectors at 0xffff0000
+ */
+TEXT mappedIvecEnable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ ORR $(CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+TEXT mappedIvecDisable(SB), $-4
+ MRC CpMMU, 0, R0, C(CpControl), C(0x0)
+ BIC $(CpCvivec), R0
+ MCR CpMMU, 0, R0, C(CpControl), C(0x0)
+ RET
+
+/* set the translation table base */
+TEXT putdac(SB), $-4
+ MCR CpMMU, 0, R0, C(CpDAC), C(0x0)
+ RET
+
+/* set address translation pid */
+TEXT putpid(SB), $-4
+ MCR CpMMU, 0, R0, C(CpPID), C(0x0)
+ RET
+
+/*
+ * set the stack value for the mode passed in R0
+ */
+TEXT setr13(SB), $-4
+ MOVW 4(FP), R1
+
+ MOVW CPSR, R2
+ BIC $PsrMask, R2, R3
+ ORR R0, R3
+ MOVW R3, CPSR
+
+ MOVW R13, R0
+ MOVW R1, R13
+
+ MOVW R2, CPSR
+ RET
+
+/*
+ * exception vectors, copied by trapinit() to somewhere useful
+ */
+
+TEXT vectors(SB), $-4
+ MOVW 0x18(R15), R15 /* reset */
+ MOVW 0x18(R15), R15 /* undefined */
+ MOVW 0x18(R15), R15 /* SWI */
+ MOVW 0x18(R15), R15 /* prefetch abort */
+ MOVW 0x18(R15), R15 /* data abort */
+ MOVW 0x18(R15), R15 /* reserved */
+ MOVW 0x18(R15), R15 /* IRQ */
+ MOVW 0x18(R15), R15 /* FIQ */
+
+TEXT vtable(SB), $-4
+ WORD $_vsvc(SB) /* reset, in svc mode already */
+ WORD $_vund(SB) /* undefined, switch to svc mode */
+ WORD $_vsvc(SB) /* swi, in svc mode already */
+ WORD $_vpabt(SB) /* prefetch abort, switch to svc mode */
+ WORD $_vdabt(SB) /* data abort, switch to svc mode */
+ WORD $_vsvc(SB) /* reserved */
+ WORD $_virq(SB) /* IRQ, switch to svc mode */
+ WORD $_vfiq(SB) /* FIQ, switch to svc mode */
+
+TEXT _vrst(SB), $-4
+ BL resettrap(SB)
+
+TEXT _vsvc(SB), $-4 /* SWI */
+ MOVW.W R14, -4(R13) /* ureg->pc = interupted PC */
+ MOVW SPSR, R14 /* ureg->psr = SPSR */
+ MOVW.W R14, -4(R13) /* ... */
+ MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */
+ MOVW.W R14, -4(R13) /* ... */
+ MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link */
+
+ BL syscall(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vund(SB), $-4 /* undefined */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMund, R0
+ B _vswitch
+
+TEXT _vpabt(SB), $-4 /* prefetch abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMabt, R0 /* r0 = type */
+ B _vswitch
+
+TEXT _vdabt(SB), $-4 /* prefetch abort */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $(PsrMabt+1), R0 /* r0 = type */
+ B _vswitch
+
+TEXT _virq(SB), $-4 /* IRQ */
+ MOVM.IA [R0-R4], (R13) /* free some working space */
+ MOVW $PsrMirq, R0 /* r0 = type */
+ B _vswitch
+
+ /*
+ * come here with type in R0 and R13 pointing above saved [r0-r4]
+ * and type in r0. we'll switch to SVC mode and then call trap.
+ */
+_vswitch:
+ MOVW SPSR, R1 /* save SPSR for ureg */
+ MOVW R14, R2 /* save interrupted pc for ureg */
+ MOVW R13, R3 /* save pointer to where the original [R0-R3] are */
+
+ /* switch to svc mode */
+ MOVW CPSR, R14
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR
+
+ /* interupted code kernel or user? */
+ AND.S $0xf, R1, R4
+ BEQ _userexcep
+
+ /* here for trap from SVC mode */
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+ MOVM.DB.W [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link (for debugger) */
+ MOVW $0xdeaddead,R11 /* marker */
+
+ BL trap(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+ /* here for trap from USER mode */
+_userexcep:
+ MOVM.DB.W [R0-R2], (R13) /* set ureg->{type, psr, pc}; r13 points to ureg->type */
+ MOVM.IA (R3), [R0-R4] /* restore [R0-R4] from previous mode's stack */
+ MOVM.DB.W.S [R0-R14], (R13) /* save kernel level registers, at end r13 points to ureg */
+ MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */
+ MOVW R13, R0 /* first arg is pointer to ureg */
+ SUB $8, R13 /* space for argument+link (for debugger) */
+
+ BL trap(SB)
+
+ ADD $(8+4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT _vfiq(SB), $-4 /* FIQ */
+ RFE /* FIQ is special, ignore it for now */
+
+/*
+ * This is the first jump from kernel to user mode.
+ * Fake a return from interrupt.
+ *
+ * Enter with R0 containing the user stack pointer.
+ * UTZERO + 0x20 is always the entry point.
+ *
+ */
+TEXT touser(SB),$-4
+ /* store the user stack pointer into the USR_r13 */
+ MOVM.DB.W [R0], (R13)
+ MOVM.S.IA.W (R13),[R13]
+
+ /* set up a PSR for user level */
+ MOVW $(PsrMusr), R0
+ MOVW R0,SPSR
+
+ /* save the PC on the stack */
+ MOVW $(UTZERO+0x20), R0
+ MOVM.DB.W [R0],(R13)
+
+ /* return from interrupt */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+/*
+ * here to jump to a newly forked process
+ */
+TEXT forkret(SB),$-4
+ ADD $(4*15), R13 /* make r13 point to ureg->type */
+ MOVW 8(R13), R14 /* restore link */
+ MOVW 4(R13), R0 /* restore SPSR */
+ MOVW R0, SPSR /* ... */
+ MOVM.DB.S (R13), [R0-R14] /* restore registers */
+ ADD $8, R13 /* pop past ureg->{type+psr} */
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT splhi(SB), $-4
+ /* save caller pc in Mach */
+ MOVW $(MACHADDR+0x04),R2
+ MOVW R14,0(R2)
+ /* turn off interrupts */
+ MOVW CPSR, R0
+ ORR $(PsrDfiq|PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT spllo(SB), $-4
+ MOVW CPSR, R0
+ BIC $(PsrDfiq|PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT splx(SB), $-4
+ /* save caller pc in Mach */
+ MOVW $(MACHADDR+0x04),R2
+ MOVW R14,0(R2)
+ /* reset interrupt level */
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT splxpc(SB), $-4 /* for iunlock */
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT spldone(SB), $0
+ RET
+
+TEXT islo(SB), $-4
+ MOVW CPSR, R0
+ AND $(PsrDfiq|PsrDirq), R0
+ EOR $(PsrDfiq|PsrDirq), R0
+ RET
+
+TEXT cpsrr(SB), $-4
+ MOVW CPSR, R0
+ RET
+
+TEXT spsrr(SB), $-4
+ MOVW SPSR, R0
+ RET
+
+TEXT getcallerpc(SB), $-4
+ MOVW 0(R13), R0
+ RET
+
+TEXT tas(SB), $-4
+ MOVW R0, R1
+ MOVW $0xDEADDEAD, R2
+ SWPW R2, (R1), R0
+ RET
+
+TEXT setlabel(SB), $-4
+ MOVW R13, 0(R0) /* sp */
+ MOVW R14, 4(R0) /* pc */
+ MOVW $0, R0
+ RET
+
+TEXT gotolabel(SB), $-4
+ MOVW 0(R0), R13 /* sp */
+ MOVW 4(R0), R14 /* pc */
+ MOVW $1, R0
+ RET
+
+
+/* The first MCR instruction of this function needs to be on a cache-line
+ * boundary; to make this happen, it will be copied (in trap.c).
+ *
+ * Doze puts the machine into idle mode. Any interrupt will get it out
+ * at the next instruction (the RET, to be precise).
+ */
+TEXT _doze(SB), $-4
+ MOVW $UCDRAMZERO, R1
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MCR CpPWR, 0, R0, C(CpTest), C(0x2), 2
+ MOVW (R1), R0
+ MCR CpPWR, 0, R0, C(CpTest), C(0x8), 2
+ RET
diff --git a/sys/src/boot/bitsy/lib.h b/sys/src/boot/bitsy/lib.h
new file mode 100755
index 000000000..5c99d1fe9
--- /dev/null
+++ b/sys/src/boot/bitsy/lib.h
@@ -0,0 +1,143 @@
+/*
+ * functions (possibly) linked in, complete, from libc.
+ */
+
+/*
+ * mem routines
+ */
+extern void *memccpy(void*, void*, int, long);
+extern void *memset(void*, int, long);
+extern int memcmp(void*, void*, long);
+extern void *memmove(void*, void*, long);
+extern void *memchr(void*, int, long);
+
+/*
+ * string routines
+ */
+extern char *strcat(char*, char*);
+extern char *strchr(char*, char);
+extern char *strrchr(char*, char);
+extern int strcmp(char*, char*);
+extern char *strcpy(char*, char*);
+extern char *strncat(char*, char*, long);
+extern char *strncpy(char*, char*, long);
+extern int strncmp(char*, char*, long);
+extern long strlen(char*);
+extern char* strstr(char*, char*);
+extern int atoi(char*);
+
+enum
+{
+ UTFmax = 3, /* maximum bytes per rune */
+ Runesync = 0x80, /* cannot represent part of a UTF sequence */
+ Runeself = 0x80, /* rune and UTF sequences are the same (<) */
+ Runeerror = 0x80, /* decoding error in UTF */
+};
+
+/*
+ * rune routines
+ */
+extern int runetochar(char*, Rune*);
+extern int chartorune(Rune*, char*);
+extern char* utfrune(char*, long);
+extern int utflen(char*);
+extern int runelen(long);
+
+extern int abs(int);
+
+/*
+ * print routines
+ */
+typedef struct Cconv Fconv;
+extern char* donprint(char*, char*, char*, void*);
+extern int sprint(char*, char*, ...);
+extern char* seprint(char*, char*, char*, ...);
+extern int snprint(char*, int, char*, ...);
+extern int print(char*, ...);
+
+/*
+ * one-of-a-kind
+ */
+extern char* cleanname(char*);
+extern uintptr getcallerpc(void*);
+extern long strtol(char*, char**, int);
+extern ulong strtoul(char*, char**, int);
+extern vlong strtoll(char*, char**, int);
+extern uvlong strtoull(char*, char**, int);
+extern char etext[];
+extern char edata[];
+extern char end[];
+extern int getfields(char*, char**, int, int, char*);
+
+/*
+ * Syscall data structures
+ */
+#define MORDER 0x0003 /* mask for bits defining order of mounting */
+#define MREPL 0x0000 /* mount replaces object */
+#define MBEFORE 0x0001 /* mount goes before others in union directory */
+#define MAFTER 0x0002 /* mount goes after others in union directory */
+#define MCREATE 0x0004 /* permit creation in mounted directory */
+#define MCACHE 0x0010 /* cache some data */
+#define MMASK 0x001F /* all bits on */
+
+#define OREAD 0 /* open for read */
+#define OWRITE 1 /* write */
+#define ORDWR 2 /* read and write */
+#define OEXEC 3 /* execute, == read but check execute permission */
+#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
+#define OCEXEC 32 /* or'ed in, close on exec */
+#define ORCLOSE 64 /* or'ed in, remove on close */
+
+#define NCONT 0 /* continue after note */
+#define NDFLT 1 /* terminate after note */
+#define NSAVE 2 /* clear note but hold state */
+#define NRSTR 3 /* restore saved state */
+
+typedef struct Qid Qid;
+typedef struct Dir Dir;
+typedef struct Waitmsg Waitmsg;
+
+#define ERRLEN 64
+#define DIRLEN 116
+#define NAMELEN 28
+
+struct Qid
+{
+ ulong path;
+ ulong vers;
+};
+
+struct Dir
+{
+ char name[NAMELEN];
+ char uid[NAMELEN];
+ char gid[NAMELEN];
+ Qid qid;
+ ulong mode;
+ long atime;
+ long mtime;
+ vlong length;
+ short type;
+ short dev;
+};
+
+struct Waitmsg
+{
+ char pid[12]; /* of loved one */
+ char time[3*12]; /* of loved one and descendants */
+ char msg[ERRLEN];
+};
+
+/*
+ * locks
+ */
+typedef
+struct Lock {
+ int val;
+} Lock;
+
+extern int _tas(int*);
+
+extern void lock(Lock*);
+extern void unlock(Lock*);
+extern int canlock(Lock*);
diff --git a/sys/src/boot/bitsy/map b/sys/src/boot/bitsy/map
new file mode 100755
index 000000000..87f67bece
--- /dev/null
+++ b/sys/src/boot/bitsy/map
@@ -0,0 +1,10 @@
+defn acidmap()
+{
+ local dfoffset;
+
+ dfoffset = map()[1][3];
+ map({"text", _start, etext, 0x20});
+ map({"data", etext+1, edata, dfoffset});
+ print("Set map for plan 9 kernel image\n");
+ print("btext ", _start, " etext ", etext, "\n");
+}
diff --git a/sys/src/boot/bitsy/mem.h b/sys/src/boot/bitsy/mem.h
new file mode 100755
index 000000000..2be6e705c
--- /dev/null
+++ b/sys/src/boot/bitsy/mem.h
@@ -0,0 +1,213 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2V 8 /* bytes per double word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+#define BLOCKALIGN 8
+
+#define MAXMACH 1 /* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define HZ (20) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
+#define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */
+
+/*
+ * Virtual addresses:
+ *
+ * We direct map all discovered DRAM and the area twixt 0xe0000000 and
+ * 0xe8000000 used to provide zeros for cache flushing.
+ *
+ * Flash is mapped to 0xb0000000 and special registers are mapped
+ * on demand to areas starting at 0xa0000000.
+ *
+ * The direct mapping is convenient but not necessary. It means
+ * that we don't have to turn on the MMU till well into the
+ * kernel. This can be changed by providing a mapping in l.s
+ * before calling main.
+ */
+#define UZERO 0 /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define KZERO 0xC0000000 /* base of kernel address space */
+#define KTZERO 0xC0008000 /* first address in kernel text */
+#define EMEMZERO 0x90000000 /* 256 meg for add on memory */
+#define EMEMTOP 0xA0000000 /* ... */
+#define REGZERO 0xA0000000 /* 128 meg for mapspecial regs */
+#define REGTOP 0xA8000000 /* ... */
+#define FLASHZERO 0xB0000000 /* 128 meg for flash */
+#define FLASHTOP 0xB8000000 /* ... */
+#define DRAMZERO 0xC0000000 /* 128 meg for dram */
+#define DRAMTOP 0xC8000000 /* ... */
+#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */
+#define UCDRAMTOP 0xD0000000 /* ... */
+#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
+#define NULLTOP 0xE8000000 /* ... */
+#define USTKTOP 0x2000000 /* byte just beyond user stack */
+#define USTKSIZE (8*1024*1024) /* size of user stack */
+#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */
+#define TSTKSIZ 100
+#define MACHADDR (KZERO+0x00001000)
+#define EVECTORS 0xFFFF0000 /* virt base of exception vectors */
+
+#define KSTACK (16*1024) /* Size of kernel stack */
+
+/*
+ * Offsets into flash
+ */
+#define Flash_bootldr (FLASHZERO+0x0) /* boot loader */
+#define Flash_kernel (FLASHZERO+0x10000) /* boot kernel */
+#define Flash_tar (FLASHZERO+0x100000) /* tar file containing fs.sac */
+
+/*
+ * virtual MMU
+ */
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * SA1110 definitions
+ */
+
+/*
+ * memory physical addresses
+ */
+#define PHYSFLASH0 0x00000000
+#define PHYSDRAM0 0xC0000000
+#define PHYSNULL0 0xE0000000
+
+/*
+ * peripheral control module physical addresses
+ */
+#define USBREGS 0x80000000 /* serial port 0 - USB */
+#define UART1REGS 0x80010000 /* serial port 1 - UART */
+#define GPCLKREGS 0x80020060 /* serial port 1 - general purpose clock */
+#define UART2REGS 0x80030000 /* serial port 2 - low speed IR */
+#define HSSPREGS 0x80040060 /* serial port 2 - high speed IR */
+#define UART3REGS 0x80050000 /* serial port 3 - RS232 UART */
+#define MCPREGS 0x80060000 /* serial port 4 - multimedia comm port */
+#define SSPREGS 0x80070060 /* serial port 4 - synchronous serial port */
+#define OSTIMERREGS 0x90000000 /* operating system timer registers */
+#define POWERREGS 0x90020000 /* power management */
+#define GPIOREGS 0x90040000 /* 28 general purpose IO pins */
+#define INTRREGS 0x90050000 /* interrupt registers */
+#define PPCREGS 0x90060000 /* peripheral pin controller */
+#define MEMCONFREGS 0xA0000000 /* memory configuration */
+#define LCDREGS 0xB0100000 /* display */
+
+/*
+ * PCMCIA addresses
+ */
+#define PHYSPCM0REGS 0x20000000
+#define PYHSPCM0ATTR 0x28000000
+#define PYHSPCM0MEM 0x2C000000
+#define PHYSPCM1REGS 0x30000000
+#define PYHSPCM1ATTR 0x38000000
+#define PYHSPCM1MEM 0x3C000000
+
+/*
+ * Program Status Registers
+ */
+#define PsrMusr 0x00000010 /* mode */
+#define PsrMfiq 0x00000011
+#define PsrMirq 0x00000012
+#define PsrMsvc 0x00000013
+#define PsrMabt 0x00000017
+#define PsrMund 0x0000001B
+#define PsrMask 0x0000001F
+
+#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
+#define PsrDirq 0x00000080 /* disable IRQ interrupts */
+
+#define PsrV 0x10000000 /* overflow */
+#define PsrC 0x20000000 /* carry/borrow/extend */
+#define PsrZ 0x40000000 /* zero */
+#define PsrN 0x80000000 /* negative/less than */
+
+/*
+ * Coprocessors
+ */
+#define CpMMU 15
+#define CpPWR 15
+
+/*
+ * Internal MMU coprocessor registers
+ */
+#define CpCPUID 0 /* R: */
+#define CpControl 1 /* R: */
+#define CpTTB 2 /* RW: translation table base */
+#define CpDAC 3 /* RW: domain access control */
+#define CpFSR 5 /* RW: fault status */
+#define CpFAR 6 /* RW: fault address */
+#define CpCacheFlush 7 /* W: cache flushing, wb draining*/
+#define CpTLBFlush 8 /* W: TLB flushing */
+#define CpRBFlush 9 /* W: Read Buffer ops */
+#define CpPID 13 /* RW: PID for virtual mapping */
+#define CpBpt 14 /* W: Breakpoint register */
+#define CpTest 15 /* W: Test, Clock and Idle Control */
+
+/*
+ * CpControl
+ */
+#define CpCmmuena 0x00000001 /* M: MMU enable */
+#define CpCalign 0x00000002 /* A: alignment fault enable */
+#define CpCdcache 0x00000004 /* C: data cache on */
+#define CpCwb 0x00000008 /* W: write buffer turned on */
+#define CpCi32 0x00000010 /* P: 32-bit program space */
+#define CpCd32 0x00000020 /* D: 32-bit data space */
+#define CpCbe 0x00000080 /* B: big-endian operation */
+#define CpCsystem 0x00000100 /* S: system permission */
+#define CpCrom 0x00000200 /* R: ROM permission */
+#define CpCicache 0x00001000 /* I: instruction cache on */
+#define CpCvivec 0x00002000 /* X: virtual interrupt vector adjust */
+
+/*
+ * fault codes
+ */
+#define FCterm 0x2 /* terminal */
+#define FCvec 0x0 /* vector */
+#define FCalignf 0x1 /* unaligned full word data access */
+#define FCalignh 0x3 /* unaligned half word data access */
+#define FCl1abort 0xc /* level 1 external abort on translation */
+#define FCl2abort 0xe /* level 2 external abort on translation */
+#define FCtransSec 0x5 /* section translation */
+#define FCtransPage 0x7 /* page translation */
+#define FCdomainSec 0x9 /* section domain */
+#define FCdomainPage 0x11 /* page domain */
+#define FCpermSec 0x9 /* section permissions */
+#define FCpermPage 0x11 /* page permissions */
+#define FCabortLFSec 0x4 /* external abort on linefetch for section */
+#define FCabortLFPage 0x6 /* external abort on linefetch for page */
+#define FCabortNLFSec 0x8 /* external abort on non-linefetch for section */
+#define FCabortNLFPage 0xa /* external abort on non-linefetch for page */
+
+/*
+ * PTE bits used by fault.h. mmu.c translates them to real values.
+ */
+#define PTEVALID (1<<0)
+#define PTERONLY 0 /* this is implied by the absence of PTEWRITE */
+#define PTEWRITE (1<<1)
+#define PTEUNCACHED (1<<2)
+#define PTEKERNEL (1<<3) /* no user access */
+
+/*
+ * H3650 specific definitions
+ */
+#define EGPIOREGS 0x49000000 /* Additional GPIO register */
diff --git a/sys/src/boot/bitsy/mkfile b/sys/src/boot/bitsy/mkfile
new file mode 100755
index 000000000..fe32e6880
--- /dev/null
+++ b/sys/src/boot/bitsy/mkfile
@@ -0,0 +1,45 @@
+objtype=arm
+</$objtype/mkfile
+BIN=/arm
+
+TARG=\
+ inflate\
+
+INFLATE=\
+ il.$O\
+ imain.$O\
+
+CORE=\
+ uart.$O\
+ inflate.$O\
+ donprint.$O\
+ print.$O\
+
+HFILES=\
+ mem.h\
+
+CFLAGS=-w -I.
+
+all:V: $TARG
+
+install:V: $BIN/$TARG
+
+$BIN/%: %
+ cp $stem $BIN/$stem
+
+inflate: $INFLATE $CORE
+ $LD -o s$target -R4 -T0xC0200010 $prereq -lflate -lc
+ $LD -o _^$target -H5 -R4 -T0xC0200010 $prereq -lflate -lc
+ dd -conv sync -ibs 20k -if _^$target -of $target
+
+%.$O: %.s
+ $AS $stem.s
+
+%.$O: %.c
+ $CC $CFLAGS $stem.c
+
+%.$O: $HFILES
+
+clean:
+ rm -f *.[$OS] [$OS].out y.tab.? y.debug y.output $TARG _$TARG
+
diff --git a/sys/src/boot/bitsy/print.c b/sys/src/boot/bitsy/print.c
new file mode 100755
index 000000000..f2b852878
--- /dev/null
+++ b/sys/src/boot/bitsy/print.c
@@ -0,0 +1,56 @@
+#include "u.h"
+#include "lib.h"
+#include "fns.h"
+#include "dat.h"
+
+
+#define SIZE 1024
+
+int
+print(char *fmt, ...)
+{
+ char buf[SIZE], *out;
+ va_list arg;
+
+ va_start(arg, fmt);
+ out = donprint(buf, buf+SIZE, fmt, arg);
+ va_end(arg);
+ serialputs(buf, out-buf);
+ return out-buf;
+}
+
+int
+sprint(char *buf, char *fmt, ...)
+{
+ char *out;
+ va_list arg;
+
+ va_start(arg, fmt);
+ out = donprint(buf, buf+SIZE, fmt, arg);
+ va_end(arg);
+ return out-buf;
+}
+
+int
+snprint(char *buf, int len, char *fmt, ...)
+{
+ char *out;
+ va_list arg;
+
+ va_start(arg, fmt);
+ out = donprint(buf, buf+len, fmt, arg);
+ va_end(arg);
+ return out-buf;
+}
+
+char*
+seprint(char *buf, char *e, char *fmt, ...)
+{
+ char *out;
+ va_list arg;
+
+ va_start(arg, fmt);
+ out = donprint(buf, e, fmt, arg);
+ va_end(arg);
+ return out;
+}
diff --git a/sys/src/boot/bitsy/sinflate b/sys/src/boot/bitsy/sinflate
new file mode 100755
index 000000000..8f5a83924
--- /dev/null
+++ b/sys/src/boot/bitsy/sinflate
Binary files differ
diff --git a/sys/src/boot/bitsy/uart.c b/sys/src/boot/bitsy/uart.c
new file mode 100755
index 000000000..e060aa9d2
--- /dev/null
+++ b/sys/src/boot/bitsy/uart.c
@@ -0,0 +1,69 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum
+{
+ /* ctl[0] bits */
+ Parity= 1<<0,
+ Even= 1<<1,
+ Stop2= 1<<2,
+ Bits8= 1<<3,
+ SCE= 1<<4, /* synchronous clock enable */
+ RCE= 1<<5, /* rx on falling edge of clock */
+ TCE= 1<<6, /* tx on falling edge of clock */
+
+ /* ctl[3] bits */
+ Rena= 1<<0, /* receiver enable */
+ Tena= 1<<1, /* transmitter enable */
+ Break= 1<<2, /* force TXD3 low */
+ Rintena= 1<<3, /* enable receive interrupt */
+ Tintena= 1<<4, /* enable transmitter interrupt */
+ Loopback= 1<<5, /* loop back data */
+
+ /* data bits */
+ DEparity= 1<<8, /* parity error */
+ DEframe= 1<<9, /* framing error */
+ DEoverrun= 1<<10, /* overrun error */
+
+ /* status[0] bits */
+ Tint= 1<<0, /* transmit fifo half full interrupt */
+ Rint0= 1<<1, /* receiver fifo 1/3-2/3 full */
+ Rint1= 1<<2, /* receiver fifo not empty and receiver idle */
+ Breakstart= 1<<3,
+ Breakend= 1<<4,
+ Fifoerror= 1<<5, /* fifo error */
+
+ /* status[1] bits */
+ Tbusy= 1<<0, /* transmitting */
+ Rnotempty= 1<<1, /* receive fifo not empty */
+ Tnotfull= 1<<2, /* transmit fifo not full */
+ ParityError= 1<<3,
+ FrameError= 1<<4,
+ Overrun= 1<<5,
+};
+
+Uartregs *uart3regs = (Uartregs*)UART3REGS;
+
+
+/*
+ * for iprint, just write it
+ */
+void
+serialputs(char *str, int n)
+{
+ Uartregs *ur;
+
+ ur = uart3regs;
+ while(n-- > 0){
+ /* wait for output ready */
+ while((ur->status[1] & Tnotfull) == 0)
+ ;
+ ur->data = *str++;
+ }
+ while((ur->status[1] & Tbusy))
+ ;
+}