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