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