xref: /inferno-os/appl/cmd/mpc/qconfig.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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