1implement Configflash; 2 3# 4# this isn't a proper config program: it's currently just 5# enough to set important parameters such as ethernet address. 6# an extension is in the works. 7# --chf 8 9include "sys.m"; 10 sys: Sys; 11 12include "draw.m"; 13 14include "string.m"; 15 str: String; 16 17Configflash: module 18{ 19 init: fn(nil: ref Draw->Context, args: list of string); 20}; 21 22Region: adt { 23 base: int; 24 limit: int; 25}; 26 27# 28# structure of allocation descriptor 29# 30Fcheck: con 0; 31Fbase: con 4; 32Flen: con 8; 33Ftag: con 11; 34Fsig: con 12; 35Fasize: con 3*4+3+1; 36 37Tdead: con byte 0; 38Tboot: con byte 16r01; 39Tconf: con byte 16r02; 40Tnone: con byte 16rFF; 41 42flashsig := array[] of {byte 16rF1, byte 16rA5, byte 16r5A, byte 16r1F}; 43noval := array[] of {0 to 3 =>byte 16rFF}; # 44 45Ctag, Cscreen, Cconsole, Cbaud, Cether, Cea, Cend: con iota; 46config := array[] of { 47 Ctag => "#plan9.ini\n", # current flag for qboot, don't change 48 Cscreen => "vgasize=640x480x8\n", 49 Cconsole => "console=0 lcd\n", 50 Cbaud => "baud=9600\n", 51 Cether => "ether0=type=SCC port=2 ", # note missing \n 52 Cea => "ea=08003e400080\n", 53 Cend => "\0" # qboot currently requires it but shouldn't 54}; 55 56Param: adt { 57 name: string; 58 index: int; 59}; 60 61params := array[] of { 62 Param("vgasize", Cscreen), 63 Param("console", Cconsole), 64 Param("ea", Cea), 65 Param("baud", Cbaud) 66}; 67 68# could come from file or #F/flash/flashctl 69FLASHSEG: con 256*1024; 70bootregion := Region(0, FLASHSEG); 71 72stderr: ref Sys->FD; 73prog := "qconfig"; 74damaged := 0; 75debug := 0; 76 77usage() 78{ 79 sys->fprint(stderr, "Usage: %s [-D] [-f flash] [-param value ...]\n", prog); 80 exit; 81} 82 83err(s: string) 84{ 85 sys->fprint(stderr, "%s: %s", prog, s); 86 if(!damaged) 87 sys->fprint(stderr, "; flash not modified\n"); 88 else 89 sys->fprint(stderr, "; flash might now be invalid\n"); 90 exit; 91} 92 93init(nil: ref Draw->Context, args: list of string) 94{ 95 sys = load Sys Sys->PATH; 96 sys->pctl(Sys->FORKFD|Sys->NEWPGRP, nil); 97 stderr = sys->fildes(2); 98 if(args != nil){ 99 prog = hd args; 100 args = tl args; 101 } 102 str = load String String->PATH; 103 if(str == nil) 104 err(sys->sprint("can't load %s: %r", String->PATH)); 105 flash := "#F/flash/flash"; 106 offset := 0; 107 region := bootregion; 108 109 for(; args != nil && (hd args)[0] == '-'; args = tl args) 110 case a := hd args { 111 "-f" => 112 (flash, args) = argf(tl args); 113 "-D" => 114 debug = 1; 115 * => 116 p := lookparam(params, a[1:]); 117 if(p.index < 0) 118 err(sys->sprint("unknown config parameter: %s", a)); 119 v: string; 120 (v, args) = argf(tl args); 121 config[p.index] = a[1:]+"="+v+"\n"; # would be nice to check it 122 } 123 if(len args > 0) 124 usage(); 125 out := sys->open(flash, Sys->ORDWR); 126 if(out == nil) 127 err(sys->sprint("can't open %s for read/write: %r", flash)); 128 # TO DO: hunt for free space and add new entry 129 plonk(out, FLASHSEG-Fasize, mkdesc(0, 128*1024, Tboot)); 130 c := flatten(config); 131 if(debug) 132 sys->print("%s", c); 133 bconf := array of byte c; 134 plonk(out, FLASHSEG-Fasize*2, mkdesc(128*1024, len bconf, Tconf)); 135 plonk(out, 128*1024, bconf); 136} 137 138argf(args: list of string): (string, list of string) 139{ 140 if(args == nil) 141 usage(); 142 return (hd args, args); 143} 144 145lookparam(options: array of Param, s: string): Param 146{ 147 for(i := 0; i < len options; i++) 148 if(options[i].name == s) 149 return options[i]; 150 return Param(nil, -1); 151} 152 153flatten(a: array of string): string 154{ 155 s := ""; 156 for(i := 0; i < len a; i++) 157 s += a[i]; 158 return s; 159} 160 161plonk(out: ref Sys->FD, where: int, val: array of byte) 162{ 163 if(debug){ 164 sys->print("write #%ux [%d]:", where, len val); 165 for(i:=0; i<len val; i++) 166 sys->print(" %.2ux", int val[i]); 167 sys->print("\n"); 168 } 169 sys->seek(out, big where, 0); 170 if(sys->write(out, val, len val) != len val) 171 err(sys->sprint("bad flash write: %r")); 172} 173 174cvt(v: int): array of byte 175{ 176 a := array[4] of byte; 177 a[0] = byte (v>>24); 178 a[1] = byte (v>>16); 179 a[2] = byte (v>>8); 180 a[3] = byte (v & 16rff); 181 return a; 182} 183 184mkdesc(base: int, length: int, tag: byte): array of byte 185{ 186 a := array[Fasize] of byte; 187 a[Fcheck:] = noval; 188 a[Fbase:] = cvt(base); 189 a[Flen:] = cvt(length)[1:]; # it's three bytes 190 a[Ftag] = tag; 191 a[Fsig:] = flashsig; 192 return a; 193} 194