1 #include "boot.h" 2 3 typedef struct Flashdev Flashdev; 4 struct Flashdev { 5 uchar* base; 6 int size; 7 uchar* exec; 8 char* config; 9 int conflen; 10 }; 11 12 enum { 13 FLASHSEG = 256*1024, 14 CONFIGLIM = FLASHSEG, 15 BOOTOFF = FLASHSEG, 16 BOOTLEN = 3*FLASHSEG, /* third segment might be filsys */ 17 /* rest of flash is free */ 18 }; 19 20 static Flashdev flash; 21 22 /* 23 * configuration data is written between the bootstrap and 24 * the end of region 0. the region ends with allocation descriptors 25 * of the following form: 26 * 27 * byte order is big endian 28 * 29 * the last valid region found that starts with the string "#plan9.ini\n" is plan9.ini 30 */ 31 typedef struct Flalloc Flalloc; 32 struct Flalloc { 33 ulong check; /* checksum of data, or ~0 */ 34 ulong base; /* base of region; ~0 if unallocated, 0 if deleted */ 35 uchar len[3]; 36 uchar tag; /* see below */ 37 uchar sig[4]; 38 }; 39 40 enum { 41 /* tags */ 42 Tdead= 0, 43 Tboot= 0x01, /* space reserved for boot */ 44 Tconf= 0x02, /* configuration data */ 45 Tnone= 0xFF, 46 47 Noval= ~0, 48 }; 49 50 static char flashsig[] = {0xF1, 0xA5, 0x5A, 0x1F}; 51 static char conftag[] = "#plan9.ini\n"; 52 53 static ulong 54 checksum(uchar* p, int n) 55 { 56 ulong s; 57 58 for(s=0; --n >= 0;) 59 s += *p++; 60 return s; 61 } 62 63 static int 64 validptr(Flalloc *ap, uchar *p) 65 { 66 return p > (uchar*)&end && p < (uchar*)ap; 67 } 68 69 static int 70 flashcheck(Flalloc *ap, char **val, int *len) 71 { 72 uchar *base; 73 int n; 74 75 if(ap->base == Noval || ap->base >= FLASHSEG || ap->tag == Tnone) 76 return 0; 77 base = flash.base+ap->base; 78 if(!validptr(ap, base)) 79 return 0; 80 n = (((ap->len[0]<<8)|ap->len[1])<<8)|ap->len[2]; 81 if(n == 0xFFFFFF) 82 n = 0; 83 if(n < 0) 84 return 0; 85 if(n > 0 && !validptr(ap, base+n-1)) 86 return 0; 87 if(ap->check != Noval && checksum(base, n) != ap->check){ 88 print("flash: bad checksum\n"); 89 return 0; 90 } 91 *val = (char*)base; 92 *len = n; 93 return 1; 94 } 95 96 int 97 flashinit(void) 98 { 99 int len; 100 char *val; 101 Flalloc *ap; 102 void *addr; 103 long mbytes; 104 char type[20]; 105 106 flash.base = 0; 107 flash.exec = 0; 108 flash.size = 0; 109 if(archflashreset(type, &addr, &mbytes) < 0){ 110 print("flash: flash not present or not enabled\n"); /* shouldn't happen */ 111 return 0; 112 } 113 flash.size = mbytes; 114 flash.base = addr; 115 flash.exec = flash.base + BOOTOFF; 116 flash.config = nil; 117 flash.conflen = 0; 118 119 for(ap = (Flalloc*)(flash.base+CONFIGLIM)-1; memcmp(ap->sig, flashsig, 4) == 0; ap--){ 120 if(0) 121 print("conf #%8.8lux: #%x #%6.6lux\n", ap, ap->tag, ap->base); 122 if(ap->tag == Tconf && 123 flashcheck(ap, &val, &len) && 124 len >= sizeof(conftag)-1 && 125 memcmp(val, conftag, sizeof(conftag)-1) == 0){ 126 flash.config = val; 127 flash.conflen = len; 128 if(0) 129 print("flash: found config %8.8lux(%d):\n%s\n", val, len, val); 130 } 131 } 132 if(flash.config == nil) 133 print("flash: no config\n"); 134 else 135 print("flash config %8.8lux(%d):\n%s\n", flash.config, flash.conflen, flash.config); 136 if(issqueezed(flash.exec) == Q_MAGIC){ 137 print("flash: squeezed powerpc kernel installed\n"); 138 return 1<<0; 139 } 140 if(GLLONG(flash.exec) == Q_MAGIC){ 141 print("flash: unsqueezed powerpc kernel installed\n"); 142 return 1<<0; 143 } 144 flash.exec = 0; 145 print("flash: no powerpc kernel in Flash\n"); 146 return 0; 147 } 148 149 char* 150 flashconfig(int) 151 { 152 return flash.config; 153 } 154 155 int 156 flashbootable(int) 157 { 158 return flash.exec != nil && (issqueezed(flash.exec) || GLLONG(flash.exec) == Q_MAGIC); 159 } 160 161 int 162 flashboot(int) 163 { 164 ulong entry, addr; 165 void (*b)(void); 166 Exec *ep; 167 Block in; 168 long n; 169 uchar *p; 170 171 if(flash.exec == 0) 172 return -1; 173 p = flash.exec; 174 if(GLLONG(p) == Q_MAGIC){ 175 /* unsqueezed: copy data and perhaps text, then jump to it */ 176 ep = (Exec*)p; 177 entry = PADDR(GLLONG(ep->entry)); 178 p += sizeof(Exec); 179 addr = entry; 180 n = GLLONG(ep->text); 181 if(addr != (ulong)p){ 182 memmove((void*)addr, p, n); 183 print("text: %8.8lux <- %8.8lux [%ld]\n", addr, p, n); 184 } 185 p += n; 186 if(entry >= FLASHMEM) 187 addr = 3*BY2PG; /* kernel text is in Flash, data in RAM */ 188 else 189 addr = PGROUND(addr+n); 190 n = GLLONG(ep->data); 191 memmove((void*)addr, p, n); 192 print("data: %8.8lux <- %8.8lux [%ld]\n", addr, p, n); 193 }else{ 194 in.data = p; 195 in.rp = in.data; 196 in.lim = p+BOOTLEN; 197 in.wp = in.lim; 198 n = unsqueezef(&in, &entry); 199 if(n < 0) 200 return -1; 201 } 202 print("entry=0x%lux\n", entry); 203 uartwait(); 204 scc2stop(); 205 /* 206 * Go to new code. It's up to the program to get its PC relocated to 207 * the right place. 208 */ 209 b = (void (*)(void))KADDR(PADDR(entry)); 210 (*b)(); 211 return -1; 212 } 213