1*37da2899SCharles.Forsythimplement Writeflash; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsyth sys: Sys; 5*37da2899SCharles.Forsyth 6*37da2899SCharles.Forsythinclude "draw.m"; 7*37da2899SCharles.Forsyth 8*37da2899SCharles.Forsythinclude "string.m"; 9*37da2899SCharles.Forsyth str: String; 10*37da2899SCharles.Forsyth 11*37da2899SCharles.ForsythWriteflash: module 12*37da2899SCharles.Forsyth{ 13*37da2899SCharles.Forsyth init: fn(nil: ref Draw->Context, args: list of string); 14*37da2899SCharles.Forsyth}; 15*37da2899SCharles.Forsyth 16*37da2899SCharles.ForsythRegion: adt { 17*37da2899SCharles.Forsyth base: int; 18*37da2899SCharles.Forsyth limit: int; 19*37da2899SCharles.Forsyth}; 20*37da2899SCharles.Forsyth 21*37da2899SCharles.Forsyth# could come from file or #F/flash/flashctl 22*37da2899SCharles.ForsythFLASHSEG: con 256*1024; 23*37da2899SCharles.Forsythkernelregion := Region(FLASHSEG, FLASHSEG+2*FLASHSEG); 24*37da2899SCharles.Forsythbootregion := Region(0, FLASHSEG); 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsythstderr: ref Sys->FD; 27*37da2899SCharles.Forsythprog := "qflash"; 28*37da2899SCharles.Forsythdamaged := 0; 29*37da2899SCharles.Forsyth 30*37da2899SCharles.Forsythusage() 31*37da2899SCharles.Forsyth{ 32*37da2899SCharles.Forsyth sys->fprint(stderr, "Usage: %s [-b] [-o offset] [-f flashdev] file\n", prog); 33*37da2899SCharles.Forsyth exit; 34*37da2899SCharles.Forsyth} 35*37da2899SCharles.Forsyth 36*37da2899SCharles.Forsytherr(s: string) 37*37da2899SCharles.Forsyth{ 38*37da2899SCharles.Forsyth sys->fprint(stderr, "%s: %s", prog, s); 39*37da2899SCharles.Forsyth if(!damaged) 40*37da2899SCharles.Forsyth sys->fprint(stderr, "; flash not modified\n"); 41*37da2899SCharles.Forsyth else 42*37da2899SCharles.Forsyth sys->fprint(stderr, "; flash might now be invalid\n"); 43*37da2899SCharles.Forsyth exit; 44*37da2899SCharles.Forsyth} 45*37da2899SCharles.Forsyth 46*37da2899SCharles.Forsythinit(nil: ref Draw->Context, args: list of string) 47*37da2899SCharles.Forsyth{ 48*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 49*37da2899SCharles.Forsyth sys->pctl(Sys->FORKFD|Sys->NEWPGRP, nil); 50*37da2899SCharles.Forsyth stderr = sys->fildes(2); 51*37da2899SCharles.Forsyth if(args != nil){ 52*37da2899SCharles.Forsyth prog = hd args; 53*37da2899SCharles.Forsyth args = tl args; 54*37da2899SCharles.Forsyth } 55*37da2899SCharles.Forsyth str = load String String->PATH; 56*37da2899SCharles.Forsyth if(str == nil) 57*37da2899SCharles.Forsyth err(sys->sprint("can't load %s: %r", String->PATH)); 58*37da2899SCharles.Forsyth region := kernelregion; 59*37da2899SCharles.Forsyth flash := "#F/flash/flash"; 60*37da2899SCharles.Forsyth offset := 0; 61*37da2899SCharles.Forsyth save := 0; 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth for(; args != nil && (hd args)[0] == '-'; args = tl args) 64*37da2899SCharles.Forsyth case hd args { 65*37da2899SCharles.Forsyth "-b" => 66*37da2899SCharles.Forsyth region = bootregion; 67*37da2899SCharles.Forsyth offset = 16r100 - 8*4; # size of exec header 68*37da2899SCharles.Forsyth save = 1; 69*37da2899SCharles.Forsyth "-h" => 70*37da2899SCharles.Forsyth region.limit += FLASHSEG; 71*37da2899SCharles.Forsyth "-f" => 72*37da2899SCharles.Forsyth if(tl args == nil) 73*37da2899SCharles.Forsyth usage(); 74*37da2899SCharles.Forsyth flash = hd args; 75*37da2899SCharles.Forsyth args = tl args; 76*37da2899SCharles.Forsyth "-o" => 77*37da2899SCharles.Forsyth if(tl args == nil) 78*37da2899SCharles.Forsyth usage(); 79*37da2899SCharles.Forsyth args = tl args; 80*37da2899SCharles.Forsyth s := hd args; 81*37da2899SCharles.Forsyth v: int; 82*37da2899SCharles.Forsyth rs: string; 83*37da2899SCharles.Forsyth if(str->prefix("16r", s)) 84*37da2899SCharles.Forsyth (v, rs) = str->toint(s[3:], 16); 85*37da2899SCharles.Forsyth else if(str->prefix("0x", s)) 86*37da2899SCharles.Forsyth (v, rs) = str->toint(s[2:], 16); 87*37da2899SCharles.Forsyth else if(str->prefix("0", s)) 88*37da2899SCharles.Forsyth (v, rs) = str->toint(s[1:], 8); 89*37da2899SCharles.Forsyth else 90*37da2899SCharles.Forsyth (v, rs) = str->toint(s, 10); 91*37da2899SCharles.Forsyth if(v < 0 || len rs != 0) 92*37da2899SCharles.Forsyth err(sys->sprint("bad offset: %s", s)); 93*37da2899SCharles.Forsyth offset = v; 94*37da2899SCharles.Forsyth "-s" => 95*37da2899SCharles.Forsyth save = 1; 96*37da2899SCharles.Forsyth * => 97*37da2899SCharles.Forsyth usage(); 98*37da2899SCharles.Forsyth } 99*37da2899SCharles.Forsyth if(args == nil) 100*37da2899SCharles.Forsyth usage(); 101*37da2899SCharles.Forsyth fname := hd args; 102*37da2899SCharles.Forsyth fd := sys->open(fname, Sys->OREAD); 103*37da2899SCharles.Forsyth if(fd == nil) 104*37da2899SCharles.Forsyth err(sys->sprint("can't open %s: %r", fname)); 105*37da2899SCharles.Forsyth (r, dir) := sys->fstat(fd); 106*37da2899SCharles.Forsyth if(r < 0) 107*37da2899SCharles.Forsyth err(sys->sprint("can't stat %s: %r", fname)); 108*37da2899SCharles.Forsyth length := int dir.length; 109*37da2899SCharles.Forsyth avail := region.limit - (region.base+offset); 110*37da2899SCharles.Forsyth if(length > avail) 111*37da2899SCharles.Forsyth err(sys->sprint("%s contents %ud bytes, exceeds flash region %ud bytes", fname, length, avail)); 112*37da2899SCharles.Forsyth # check fname's contents... 113*37da2899SCharles.Forsyth where := region.base+offset; 114*37da2899SCharles.Forsyth saved: list of (int, array of byte); 115*37da2899SCharles.Forsyth if(save){ 116*37da2899SCharles.Forsyth saved = saveflash(flash, region.base, where) :: saved; 117*37da2899SCharles.Forsyth saved = saveflash(flash, where+length, region.limit) :: saved; 118*37da2899SCharles.Forsyth } 119*37da2899SCharles.Forsyth for(i := (region.base+offset)/FLASHSEG; i < region.limit/FLASHSEG; i++) 120*37da2899SCharles.Forsyth erase(flash, i); 121*37da2899SCharles.Forsyth out := sys->open(flash, Sys->OWRITE); 122*37da2899SCharles.Forsyth if(out == nil) 123*37da2899SCharles.Forsyth err(sys->sprint("can't open %s for writing: %r", flash)); 124*37da2899SCharles.Forsyth if(sys->seek(out, big where, 0) != big where) 125*37da2899SCharles.Forsyth err(sys->sprint("can't seek to #%6.6ux on flash: %r", where)); 126*37da2899SCharles.Forsyth if(length) 127*37da2899SCharles.Forsyth sys->print("writing %ud bytes to %s at #%6.6ux\n", length, flash, where); 128*37da2899SCharles.Forsyth buf := array[Sys->ATOMICIO] of byte; 129*37da2899SCharles.Forsyth total := 0; 130*37da2899SCharles.Forsyth while((n := sys->read(fd, buf, len buf)) > 0) { 131*37da2899SCharles.Forsyth if(total+n > avail) 132*37da2899SCharles.Forsyth err(sys->sprint("file %s too big for region of %ud bytes", fname, avail)); 133*37da2899SCharles.Forsyth r = sys->write(out, buf, n); 134*37da2899SCharles.Forsyth damaged = 1; 135*37da2899SCharles.Forsyth if(r != n){ 136*37da2899SCharles.Forsyth if(r < 0) 137*37da2899SCharles.Forsyth err(sys->sprint("error writing %s at byte %ud: %r", flash, total)); 138*37da2899SCharles.Forsyth else 139*37da2899SCharles.Forsyth err(sys->sprint("short write on %s at byte %ud", flash, total)); 140*37da2899SCharles.Forsyth } 141*37da2899SCharles.Forsyth total += n; 142*37da2899SCharles.Forsyth } 143*37da2899SCharles.Forsyth if(n < 0) 144*37da2899SCharles.Forsyth err(sys->sprint("error reading %s: %r", fname)); 145*37da2899SCharles.Forsyth sys->print("wrote %ud bytes from %s to flash %s (#%6.6ux-#%6.6ux)\n", total, fname, flash, region.base, region.base+total); 146*37da2899SCharles.Forsyth for(l := saved; l != nil; l = tl l){ 147*37da2899SCharles.Forsyth (addr, data) := hd l; 148*37da2899SCharles.Forsyth n = len data; 149*37da2899SCharles.Forsyth if(n == 0) 150*37da2899SCharles.Forsyth continue; 151*37da2899SCharles.Forsyth sys->print("restoring %ud bytes at #%6.6ux\n", n, addr); 152*37da2899SCharles.Forsyth if(sys->seek(out, big addr, 0) != big addr) 153*37da2899SCharles.Forsyth err(sys->sprint("can't seek to #%6.6ux on %s: %r", addr, flash)); 154*37da2899SCharles.Forsyth r = sys->write(out, data, n); 155*37da2899SCharles.Forsyth if(r < 0) 156*37da2899SCharles.Forsyth err(sys->sprint("error writing %s: %r", flash)); 157*37da2899SCharles.Forsyth else if(r != n) 158*37da2899SCharles.Forsyth err(sys->sprint("short write on %s at byte %ud/%ud", flash, r, n)); 159*37da2899SCharles.Forsyth else 160*37da2899SCharles.Forsyth sys->print("restored %ud bytes at #%6.6ux\n", n, addr); 161*37da2899SCharles.Forsyth } 162*37da2899SCharles.Forsyth} 163*37da2899SCharles.Forsyth 164*37da2899SCharles.Forsytherase(flash: string, seg: int) 165*37da2899SCharles.Forsyth{ 166*37da2899SCharles.Forsyth ctl := sys->open(flash+"ctl", Sys->OWRITE); 167*37da2899SCharles.Forsyth if(ctl == nil) 168*37da2899SCharles.Forsyth err(sys->sprint("can't open %sctl: %r\n", flash)); 169*37da2899SCharles.Forsyth if(sys->fprint(ctl, "erase %ud", seg*FLASHSEG) < 0) 170*37da2899SCharles.Forsyth err(sys->sprint("can't erase flash %s segment %d: %r\n", flash, seg)); 171*37da2899SCharles.Forsyth} 172*37da2899SCharles.Forsyth 173*37da2899SCharles.Forsythsaveflash(flash: string, base: int, limit: int): (int, array of byte) 174*37da2899SCharles.Forsyth{ 175*37da2899SCharles.Forsyth fd := sys->open(flash, Sys->OREAD); 176*37da2899SCharles.Forsyth if(fd == nil) 177*37da2899SCharles.Forsyth err(sys->sprint("can't open %s for reading: %r", flash)); 178*37da2899SCharles.Forsyth nb := limit - base; 179*37da2899SCharles.Forsyth if(nb <= 0) 180*37da2899SCharles.Forsyth return (base, nil); 181*37da2899SCharles.Forsyth if(sys->seek(fd, big base, 0) != big base) 182*37da2899SCharles.Forsyth err(sys->sprint("can't seek to #%6.6ux to save flash contents: %r", base)); 183*37da2899SCharles.Forsyth saved := array[nb] of byte; 184*37da2899SCharles.Forsyth if(sys->read(fd, saved, len saved) != len saved) 185*37da2899SCharles.Forsyth err(sys->sprint("can't read flash #%6.6ux to #%6.6ux: %r", base, limit)); 186*37da2899SCharles.Forsyth sys->print("saved %ud bytes at #%6.6ux\n", len saved, base); 187*37da2899SCharles.Forsyth return (base, saved); 188*37da2899SCharles.Forsyth} 189