xref: /plan9-contrib/sys/src/cmd/jtagfs/jtagfs.c (revision dedb130315e7b691e306ee069395ee1f0b18e4d4)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include <regexp.h>
6 #include <bio.h>
7 #include "debug.h"
8 #include "tap.h"
9 #include "chain.h"
10 #include "jtag.h"
11 #include "icert.h"
12 #include "mmu.h"
13 #include "mpsse.h"
14 #include "/sys/src/9/kw/arm.h"
15 #include "/arm/include/ureg.h"
16 #include "lebo.h"
17 
18 /*
19  * Like rdbfs + jtag icert control for arm cores.
20  * Memory just goes through in arm order, registers get translated
21  * to host order and back after.
22  */
23 
24 typedef struct Fid Fid;
25 typedef struct Fs Fs;
26 enum
27 {
28 	OPERM	= 0x3,		/* mask of all permission types in open mode */
29 	Nfidhash	= 32,
30 
31 	/*
32 	 * qids
33 	 */
34 	Qroot	= 1,
35 	Qctl,
36 	Qnote,
37 	Qmem,
38 			/* copied from rdbfs */
39 	Qkregs,
40 	Qfpregs,
41 	Qproc,
42 	Qregs,
43 	Qtext,
44 	Qstatus,
45 };
46 
47 static int		textfd;
48 static char*	textfile = "/arm/s9plug";
49 
50 
51 struct Fid
52 {
53 	Lock;
54 	Fid	*next;
55 	Fid	**last;
56 	uint	fid;
57 	int	ref;			/* number of fcalls using the fid */
58 	int	attached;		/* fid has beed attached or cloned and not clunked */
59 
60 	int	open;
61 	Qid	qid;
62 };
63 
64 static int			dostat(int, uchar*, int);
65 static void*		emalloc(uint);
66 static void			fatal(char*, ...);
67 static void			usage(void);
68 
69 struct Fs
70 {
71 	Lock;				/* for fids */
72 
73 	Fid		*hash[Nfidhash];
74 	uchar	statbuf[1024];	/* plenty big enough */
75 	JMedium *jmed;
76 };
77 
78 static	void		fsrun(Fs*, int);
79 static	Fid*		getfid(Fs*, uint);
80 static	Fid*		mkfid(Fs*, uint);
81 static	void		putfid(Fs*, Fid*);
82 static	char*	fsversion(Fs*, Fcall*);
83 static	char*	fsauth(Fs*, Fcall*);
84 static	char*	fsattach(Fs*, Fcall*);
85 static	char*	fswalk(Fs*, Fcall*);
86 static	char*	fsopen(Fs*, Fcall*);
87 static	char*	fscreate(Fs*, Fcall*);
88 static	char*	fsread(Fs*, Fcall*);
89 static	char*	fswrite(Fs*, Fcall*);
90 static	char*	fsclunk(Fs*, Fcall*);
91 static	char*	fsremove(Fs*, Fcall*);
92 static	char*	fsstat(Fs*, Fcall*);
93 static	char*	fswstat(Fs*, Fcall*);
94 
95 static char	*(*fcalls[])(Fs*, Fcall*) =
96 {
97 	[Tversion]		fsversion,
98 	[Tattach]		fsattach,
99 	[Tauth]		fsauth,
100 	[Twalk]		fswalk,
101 	[Topen]		fsopen,
102 	[Tcreate]		fscreate,
103 	[Tread]		fsread,
104 	[Twrite]		fswrite,
105 	[Tclunk]		fsclunk,
106 	[Tremove]	fsremove,
107 	[Tstat]		fsstat,
108 	[Twstat]		fswstat
109 };
110 
111 static char	Eperm[]		=	"permission denied";
112 static char	Enotdir[]		=	"not a directory";
113 static char	Enotexist[]	=	"file does not exist";
114 static char	Eisopen[]		= 	"file already open for I/O";
115 static char	Einuse[]		=	"fid is already in use";
116 static char	Enofid[]		= 	"no such fid";
117 static char	Enotopen[]	=	"file is not open";
118 static char	Ebadcmd[]	=	"error in jtag operation";
119 
120 static ArmCtxt ctxt;
121 static Fs		fs;
122 static int		messagesize = 8192+IOHDRSZ;
123 
124 static int
cmdsetdebug(uchar * deb)125 cmdsetdebug(uchar *deb)
126 {
127 	int i;
128 
129 	memset(debug, 0, 255);
130 	for(i = 0; i < strlen((char *)deb); i++){
131 		debug[deb[i]]++;
132 	}
133 	return 0;
134 }
135 
136 
137 
138 void
main(int argc,char ** argv)139 main(int argc, char **argv)
140 {
141 	char buf[12], *mnt, *srv, *mbname;
142 	int fd, p[2], mb;
143 	uchar *deb;
144 
145 	deb = nil;
146 	mb = Sheeva;
147 	mbname = nil;
148 	mnt = "/n/jtagfs";
149 	srv = nil;
150 	ARGBEGIN{
151 		case 'b':
152 			mbname = EARGF(usage());
153 			break;
154 		case 's':
155 			srv = ARGF();
156 			mnt = nil;
157 			break;
158 		case 'm':
159 			mnt = ARGF();
160 			break;
161 		case 'd':
162 			deb = (uchar *)EARGF(usage());
163 			break;
164 		case 't':
165 			textfile = EARGF(usage());
166 			break;
167 	}ARGEND
168 
169 	fmtinstall('F', fcallfmt);
170 	if(deb  != nil)
171 		cmdsetdebug(deb);
172 	if(argc != 1)
173 		usage();
174 	print("jtagfs: %s\n", argv[0]);
175 	fd = open(argv[0], ORDWR);
176 	if(fd < 0)
177 		fatal("can't open jtag file %s: %r", argv[0]);
178 
179 	if(mbname == nil)
180 		mb = Sheeva;
181 	else if(strncmp(mbname, "sheeva", 6) == 0)
182 		mb = Sheeva;
183 	else if(strncmp(mbname, "gurudisp", 6) == 0)
184 		mb = GuruDisp;
185 	fs.jmed = initmpsse(fd, mb);
186 	if(fs.jmed == nil)
187 		fatal("jtag initialization %r");
188 
189 	if(pipe(p) < 0)
190 		fatal("pipe failed");
191 
192 	switch(rfork(RFPROC|RFMEM|RFNOTEG|RFNAMEG)){
193 	case 0:
194 		fsrun(&fs, p[0]);
195 		exits(nil);
196 	case -1:
197 		fatal("fork failed");
198 	}
199 
200 	if(mnt == nil){
201 		if(srv == nil)
202 			usage();
203 		fd = create(srv, OWRITE, 0666);
204 		if(fd < 0){
205 			remove(srv);
206 			fd = create(srv, OWRITE, 0666);
207 			if(fd < 0){
208 				close(p[1]);
209 				fatal("create of %s failed", srv);
210 			}
211 		}
212 		sprint(buf, "%d", p[1]);
213 		if(write(fd, buf, strlen(buf)) < 0){
214 			close(p[1]);
215 			fatal("writing %s", srv);
216 		}
217 		close(p[1]);
218 		exits(nil);
219 	}
220 
221 	if(mount(p[1], -1, mnt, MREPL, "") < 0){
222 		close(p[1]);
223 		fatal("mount failed");
224 	}
225 	close(p[1]);
226 	exits(nil);
227 }
228 
229 static void
fsrun(Fs * fs,int fd)230 fsrun(Fs *fs, int fd)
231 {
232 	Fcall rpc;
233 	char *err;
234 	uchar *buf;
235 	int n;
236 
237 	buf = emalloc(messagesize);
238 	for(;;){
239 		/*
240 		 * reading from a pipe or a network device
241 		 * will give an error after a few eof reads
242 		 * however, we cannot tell the difference
243 		 * between a zero-length read and an interrupt
244 		 * on the processes writing to us,
245 		 * so we wait for the error
246 		 */
247 		n = read9pmsg(fd, buf, messagesize);
248 		if(n == 0)
249 			continue;
250 		if(n < 0)
251 			fatal("mount read");
252 
253 		rpc.data = (char*)buf + IOHDRSZ;
254 		if(convM2S(buf, n, &rpc) == 0)
255 			continue;
256 		// fprint(2, "recv: %F\n", &rpc);
257 
258 
259 		/*
260 		 * TODO: flushes are broken
261 		 */
262 		if(rpc.type == Tflush)
263 			continue;
264 		else if(rpc.type >= Tmax || !fcalls[rpc.type])
265 			err = "bad fcall type";
266 		else
267 			err = (*fcalls[rpc.type])(fs, &rpc);
268 		if(err){
269 			rpc.type = Rerror;
270 			rpc.ename = err;
271 		}
272 		else
273 			rpc.type++;
274 		n = convS2M(&rpc, buf, messagesize);
275 		// fprint(2, "send: %F\n", &rpc);
276 		if(write(fd, buf, n) != n)
277 			fatal("mount write");
278 	}
279 }
280 
281 static Fid*
mkfid(Fs * fs,uint fid)282 mkfid(Fs *fs, uint fid)
283 {
284 	Fid *f;
285 	int h;
286 
287 	h = fid % Nfidhash;
288 	for(f = fs->hash[h]; f; f = f->next){
289 		if(f->fid == fid)
290 			return nil;
291 	}
292 
293 	f = emalloc(sizeof *f);
294 	f->next = fs->hash[h];
295 	if(f->next != nil)
296 		f->next->last = &f->next;
297 	f->last = &fs->hash[h];
298 	fs->hash[h] = f;
299 
300 	f->fid = fid;
301 	f->ref = 1;
302 	f->attached = 1;
303 	f->open = 0;
304 	return f;
305 }
306 
307 static Fid*
getfid(Fs * fs,uint fid)308 getfid(Fs *fs, uint fid)
309 {
310 	Fid *f;
311 	int h;
312 
313 	h = fid % Nfidhash;
314 	for(f = fs->hash[h]; f; f = f->next){
315 		if(f->fid == fid){
316 			if(f->attached == 0)
317 				break;
318 			f->ref++;
319 			return f;
320 		}
321 	}
322 	return nil;
323 }
324 
325 static void
putfid(Fs *,Fid * f)326 putfid(Fs *, Fid *f)
327 {
328 	f->ref--;
329 	if(f->ref == 0 && f->attached == 0){
330 		*f->last = f->next;
331 		if(f->next != nil)
332 			f->next->last = f->last;
333 		free(f);
334 	}
335 }
336 
337 static char*
fsversion(Fs *,Fcall * rpc)338 fsversion(Fs *, Fcall *rpc)
339 {
340 	if(rpc->msize < 256)
341 		return "version: message size too small";
342 	if(rpc->msize > messagesize)
343 		rpc->msize = messagesize;
344 	messagesize = rpc->msize;
345 	if(strncmp(rpc->version, "9P2000", 6) != 0)
346 		return "unrecognized 9P version";
347 	rpc->version = "9P2000";
348 	return nil;
349 }
350 
351 static char*
fsauth(Fs *,Fcall *)352 fsauth(Fs *, Fcall *)
353 {
354 	return "searchfs: authentication not required";
355 }
356 
357 static char*
fsattach(Fs * fs,Fcall * rpc)358 fsattach(Fs *fs, Fcall *rpc)
359 {
360 	Fid *f;
361 
362 	f = mkfid(fs, rpc->fid);
363 	if(f == nil)
364 		return Einuse;
365 	f->open = 0;
366 	f->qid.type = QTDIR;
367 	f->qid.path = Qroot;
368 	f->qid.vers = 0;
369 	rpc->qid = f->qid;
370 	putfid(fs, f);
371 	return nil;
372 }
373 
374 typedef struct DEntry DEntry;
375 struct DEntry {
376 	uvlong path;
377 	char *name;
378 };
379 
380 DEntry entries[] = {
381 	{Qctl,	"ctl"},
382 	{Qmem,	"mem"},
383 	{Qkregs,	"kregs"},
384 	{Qfpregs,	"fpregs"},
385 	{Qproc,	"proc"},
386 	{Qregs,	"regs"},
387 	{Qtext,	"text"},
388 	{Qstatus,	"status"},
389 	{Qnote,	"note"},
390 	{~0,	nil},
391 };
392 
393 static uvlong
nm2qpath(char * name)394 nm2qpath(char *name)
395 {
396 	int i;
397 
398 	for(i = 0; entries[i].name != nil; i++)
399 		if(strcmp(name, entries[i].name) == 0)
400 			return entries[i].path;
401 
402 	return ~0;
403 }
404 
405 static char*
fswalk(Fs * fs,Fcall * rpc)406 fswalk(Fs *fs, Fcall *rpc)
407 {
408 	Fid *f, *nf;
409 	int nqid, nwname, type;
410 	char *err, *name;
411 	ulong path, fpath;
412 
413 	f = getfid(fs, rpc->fid);
414 	if(f == nil)
415 		return Enofid;
416 	nf = nil;
417 	if(rpc->fid != rpc->newfid){
418 		nf = mkfid(fs, rpc->newfid);
419 		if(nf == nil){
420 			putfid(fs, f);
421 			return Einuse;
422 		}
423 		nf->qid = f->qid;
424 		putfid(fs, f);
425 		f = nf;	/* walk f */
426 	}
427 
428 	err = nil;
429 	path = f->qid.path;
430 	nwname = rpc->nwname;
431 	for(nqid=0; nqid<nwname; nqid++){
432 		if(path != Qroot){
433 			err = Enotdir;
434 			break;
435 		}
436 		name = rpc->wname[nqid];
437 		/* BUG this is a kludge, rewrite */
438 		fpath = nm2qpath(name);
439 		if(fpath != ~0){
440 			type = QTFILE;
441 			path = fpath;
442 		}
443 		else	if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
444 			type = QTDIR;
445 		else {
446 			err = Enotexist;
447 			break;
448 		}
449 
450 		rpc->wqid[nqid] = (Qid){path, 0, type};
451 	}
452 
453 	if(nwname > 0){
454 		if(nf != nil && nqid < nwname)
455 			nf->attached = 0;
456 		if(nqid == nwname)
457 			f->qid = rpc->wqid[nqid-1];
458 	}
459 
460 	putfid(fs, f);
461 	rpc->nwqid = nqid;
462 	f->open = 0;
463 	return err;
464 }
465 
466 static char *
fsopen(Fs * fs,Fcall * rpc)467 fsopen(Fs *fs, Fcall *rpc)
468 {
469 	Fid *f;
470 	int mode;
471 	char buf[512];
472 
473 	f = getfid(fs, rpc->fid);
474 	if(f == nil)
475 		return Enofid;
476 	if(f->open){
477 		putfid(fs, f);
478 		return Eisopen;
479 	}
480 	mode = rpc->mode & OPERM;
481 	if(mode == OEXEC
482 	|| f->qid.path == Qroot && (mode == OWRITE || mode == ORDWR)){
483 		putfid(fs, f);
484 		return Eperm;
485 	}
486 	if(f->qid.path == Qtext){
487 		close(textfd);
488 		textfd = open(textfile, OREAD);
489 		if(textfd < 0) {
490 			snprint(buf, sizeof buf, "text: %r");
491 			putfid(fs, f);
492 			return "opening text file";
493 		}
494 	}
495 	f->open = 1;
496 	rpc->qid = f->qid;
497 	rpc->iounit = messagesize-IOHDRSZ;
498 	putfid(fs, f);
499 	return nil;
500 }
501 
502 static char *
fscreate(Fs *,Fcall *)503 fscreate(Fs *, Fcall *)
504 {
505 	return Eperm;
506 }
507 
508 static int
readbuf(Fcall * rpc,void * s,long n)509 readbuf(Fcall *rpc, void *s, long n)
510 {
511 	int count;
512 	count = rpc->count;
513 	if(rpc->offset >= n){
514 		count = 0;
515 	}
516 	if(rpc->offset+count > n)
517 		count = n - rpc->offset;
518 	memmove(rpc->data, (char*)s+rpc->offset, count);
519 	rpc->count = count;
520 	return count;
521 }
522 
523 enum{
524 	Maxctl = 4*1024,
525 };
526 
527 static char ctlread[Maxctl];
528 
529 static int
readctl(Fs * fs,Fcall * rpc)530 readctl(Fs *fs, Fcall *rpc)
531 {
532 	char *e;
533 	int ssz;
534 
535 	ssz = Maxctl;
536 	ctxt.debug = icedebugstate(fs->jmed);
537 
538 	if(ctxt.debug == 0){
539 		e = seprint(ctlread, ctlread+Maxctl, "Arm is in debug: %d", ctxt.debug);
540 		ssz = readbuf(rpc, ctlread, e - ctlread);
541 		return ssz;
542 	}
543 	e = armsprctxt(&ctxt, ctlread, ssz);
544 	if(e >= ctlread + Maxctl)
545 		return e - ctlread;
546 	ssz = Maxctl - (ctlread - e);
547 	e = printmmuregs(&ctxt, e, ssz);
548 
549 	ssz = readbuf(rpc, ctlread, e - ctlread);
550 	return ssz;
551 
552 }
553 
554 static int
readbytes(JMedium * jmed,u32int startaddr,u32int nbytes,u32int dataoff,Fcall * rpc)555 readbytes(JMedium *jmed, u32int startaddr, u32int nbytes, u32int dataoff, Fcall *rpc)
556 {
557 	u32int i, data;
558 	int nb, res;
559 
560 	nb = 0;
561 	for(i = startaddr; i < startaddr+nbytes; i++){
562 		res = armrdmemwd(jmed, i, &data, 1);
563 		if(res < 0){
564 			fprint(2, "Error reading [%#8.8ux]\n",
565 				i);
566 			werrstr("read error");
567 			return -1;
568 			break;
569 		}
570 		nb += res;
571 		rpc->data[dataoff] = (char)data;
572 		dprint(Dfs, "[B%#8.8ux] = %#2.2ux \n",
573 				i, data);
574 	}
575 	return nb;
576 
577 }
578 
579 /*
580  *	BUG: This is horrifyingly slow, could be made much (10x)
581  *	faster using load multiple/store multiple
582  * 	both on memory and while reading back the registers.
583  *	but it doesn't matter for acid (normally it reads words
584  *	or byte long chunks). There may also be another way
585  *	where you can inject instructions without waiting for
586  *	debug mode on the way back. I haven't been able to
587  *	make it work.
588  */
589 static int
readmem(Fs * fs,Fcall * rpc)590 readmem(Fs *fs, Fcall *rpc)
591 {
592 	u32int count, i, data, addr, prenb, nb, postnb, st;
593 	int res;
594 
595 	count = (u32int)rpc->count;
596 
597 	addr = (u32int)rpc->offset;
598 	dprint(Dfs, "[%#8.8ux, %ud] =?\n",
599 				addr, count);
600 
601 	prenb = 0;
602 	nb = 0;
603 	/* The start is not aligned */
604 	if(addr & 0x3U){
605 		prenb = sizeof(u32int) - (addr & 0x3U);
606 		res = readbytes(fs->jmed, addr, prenb, 0, rpc);
607 		if(res < 0){
608 			werrstr("read error");
609 			return -1;
610 		}
611 		nb += res;
612 		dprint(Dfs, "readmem: aligned now\n");
613 	}
614 	for(i = prenb; i/4 < (count-prenb)/sizeof(u32int); i += sizeof(u32int)){
615 		res = armrdmemwd(fs->jmed, addr+i, &data, 4);
616 		if(res < 0){
617 			fprint(2, "Error reading %#8.8ux [%#8.8ux]\n",
618 				addr+i, i);
619 			werrstr("read error");
620 			return -1;
621 			break;
622 		}
623 		nb += res;
624 
625 		*(u32int *)(rpc->data+i) = data;
626 		dprint(Dfs, "%d[%#8.8ux] = %#8.8ux \n",
627 				i, addr+i, data);
628 	}
629 
630 	dprint(Dfs, "readmem: end of aligned\n");
631 	/* The end is not aligned */
632 	if((count-prenb) & 0x3U){
633 		postnb = (count-prenb)%sizeof(u32int);
634 		st = addr + 1 + ((count-prenb)& 0x3U);
635 		res = readbytes(fs->jmed, st, postnb, nb, rpc);
636 		if(res < 0){
637 			werrstr("read error");
638 			return -1;
639 		}
640 		nb += res;
641 		dprint(Dfs, "readmem: end of non aligned\n");
642 	}
643 	return nb;
644 }
645 
646 static int
writebytes(JMedium * jmed,u32int startaddr,u32int nbytes,u32int dataoff,Fcall * rpc)647 writebytes(JMedium *jmed, u32int startaddr, u32int nbytes, u32int dataoff, Fcall *rpc)
648 {
649 	u32int i, data;
650 	int nb, res;
651 
652 	nb = 0;
653 	for(i = startaddr; i < startaddr+nbytes; i++){
654 		data = (char)rpc->data[dataoff];
655 		res = armwrmemwd(jmed, i, data, 1);
656 		if(res < 0){
657 			fprint(2, "Error writing [%#8.8ux]\n",
658 				i);
659 			werrstr("read error");
660 			return -1;
661 			break;
662 		}
663 		nb += res;
664 		dprint(Dfs, "[B%#8.8ux] = %#2.2ux \n",
665 				i, data);
666 	}
667 	return nb;
668 
669 }
670 
671 static int
writemem(Fs * fs,Fcall * rpc)672 writemem(Fs *fs, Fcall *rpc)
673 {
674 	u32int count, i, addr, *p, prenb, nb, postnb, st;
675 	int res;
676 
677 	count = rpc->count;
678 	addr = rpc->offset;
679 
680 	prenb = 0;
681 	nb = 0;
682 	/* not aligned offset */
683 	if(addr & 0x3U){
684 		prenb = sizeof(u32int) - (addr & 0x3U);
685 		res = writebytes(fs->jmed, addr, prenb, 0, rpc);
686 		if(res < 0){
687 			werrstr("write error");
688 			return -1;
689 		}
690 		nb += res;
691 		dprint(Dfs, "writemem: aligned now\n");
692 	}
693 	for(i = prenb; i/4 < (count-prenb)/sizeof(u32int); i += sizeof(u32int)){
694 		p = (u32int *)(rpc->data + i);
695 		dprint(Dfs, "%d[%#8.8ux] = %#8.8ux \n",
696 				i, addr+i, *p);
697 		res = armwrmemwd(fs->jmed, addr + i, *p, 4);
698 		if(res < 0){
699 			fprint(2, "Error writing %#8.8ux [%#8.8ux]\n",
700 				addr+i, i);
701 			werrstr("write error");
702 			return -1;
703 			break;
704 		}
705 		nb += res;
706 	}
707 	dprint(Dfs, "writemem: end of aligned\n");
708 	/* not aligned end */
709 	if((count-prenb)  & 0x3U){
710 		postnb = (count-prenb)%sizeof(u32int);
711 		st = addr + 1 + ((count-prenb)& 0x3U);
712 		res = writebytes(fs->jmed, st, postnb, nb, rpc);
713 		if(res < 0){
714 			werrstr("write error");
715 			return -1;
716 		}
717 		nb += res;
718 		dprint(Dfs, "writemem: end of non aligned\n");
719 	}
720 	return nb;
721 }
722 
723 /* host to Arm (le) */
724 static void
setkernur(Ureg * kur,ArmCtxt * context)725 setkernur(Ureg *kur, ArmCtxt *context)
726 {
727 	int i;
728 	u32int *p;
729 
730 	kur->type = context->cpsr&PsrMask;
731 	hleputl(&kur->type, kur->type);
732 
733 	kur->psr = context->spsr;
734 	hleputl(&kur->psr, kur->psr);
735 
736 	p = (u32int *)kur;
737 	for(i = 0; i < 14; i++)
738 		hleputl(p + i, context->r[i]);
739 	kur->pc = context->r[15];
740 	hleputl(&kur->pc, kur->pc);
741 }
742 
743 typedef struct Regs Regs;
744 struct Regs {
745 	Ureg kur;
746 	MMURegs mmust;
747 };
748 
749 static Regs procregs;	/* kludge: just for reading */
750 
751 /* host to Arm (le) */
752 static void
setmmust(MMURegs * mmust,ArmCtxt * context)753 setmmust(MMURegs *mmust, ArmCtxt *context)
754 {
755 	int i;
756 	u32int *o, *d;
757 	d = (u32int *)mmust;
758 	o = (u32int *) &context->MMURegs;
759 	for(i = 0; i < sizeof(MMURegs)/sizeof(u32int); i++)
760 		hleputl(d + i, o[i]);
761 }
762 
763 static char*
fsread(Fs * fs,Fcall * rpc)764 fsread(Fs *fs, Fcall *rpc)
765 {
766 	Fid *f;
767 	int off, count, len, i;
768 	uchar *rptr;
769 	char buf[512];
770 
771 	f = getfid(fs, rpc->fid);
772 	if(f == nil)
773 		return Enofid;
774 	if(!f->open){
775 		putfid(fs, f);
776 		return Enotopen;
777 	}
778 	count = rpc->count;
779 	off = rpc->offset;
780 	if(f->qid.path == Qroot){
781 		if(off > 0)
782 			rpc->count = 0;
783 		else {
784 			rpc->count = 0;
785 			for(i = 0; entries[i].name != nil; i++)
786 				rpc->count += dostat(entries[i].path,
787 					rpc->count+(uchar*)rpc->data, count-rpc->count);
788 		}
789 
790 		putfid(fs, f);
791 		if(off == 0 && rpc->count <= BIT16SZ)
792 			return "directory read count too small";
793 		return nil;
794 	}
795 	len = 0;
796 	if(f->qid.path == Qctl){
797 		dprint(Dfs, "ctlread\n");
798 		len = readctl(fs, rpc);
799 		dprint(Dfs, "ctlread read %d %s\n", len, ctlread);
800 		if(len < 0){
801 			putfid(fs, f);
802 			return "ctl read";
803 		}
804 	}
805 	else if(f->qid.path == Qmem){
806 		dprint(Dfs, "readmem\n");
807 		len = readmem(fs, rpc);
808 		dprint(Dfs, "readmem read %d %s\n", len, ctlread);
809 		if(len < 0){
810 			putfid(fs, f);
811 			return "readmem read";
812 		}
813 	}
814 	else if(f->qid.path == Qkregs){
815 		dprint(Dfs, "kregs read n %d off %d\n", rpc->count, rpc->offset);
816 		memset(&procregs, 0, sizeof(Regs));
817 		setkernur(&procregs.kur, &ctxt);
818 		setmmust(&procregs.mmust, &ctxt);
819 		rptr = (uchar*)&procregs;
820 		len = readbuf(rpc, rptr, sizeof(Regs));
821 	}
822 	else if(f->qid.path == Qtext){
823 		dprint(Dfs, "text\n");
824 		len = pread(textfd, rpc->data, rpc->count, rpc->offset);
825 		if(len < 0) {
826 			rerrstr(buf, sizeof buf);
827 			fprint(2, "error reading text: %r");
828 			putfid(fs, f);
829 			return "text read";
830 		}
831 	}
832 	else if(f->qid.path == Qstatus){
833 		dprint(Dfs, "status\n");
834 		len = snprint(buf, sizeof buf, "%-28s%-28s%-28s", "remote", "system", "New");
835 		for(i = 0; i < 9; i++)
836 			len += snprint(buf + len, sizeof buf - len, "%-12d", 0);
837 		len = readbuf(rpc, buf, len);
838 
839 	}
840 	putfid(fs, f);
841 	rpc->count = len;
842 	return nil;
843 }
844 
845 typedef struct Cmdbuf Cmdbuf;
846 typedef struct Cmdtab Cmdtab;
847 struct Cmdbuf
848 {
849 	char	*buf;
850 	char	**f;
851 	int	nf;
852 };
853 
854 struct Cmdtab
855 {
856 	int	index;	/* used by client to switch on result */
857 	char	*cmd;	/* command name */
858 	int	narg;	/* expected #args; 0 ==> variadic */
859 };
860 /*
861  * Generous estimate of number of fields, including terminal nil pointer
862  */
863 static int
ncmdfield(char * p,int n)864 ncmdfield(char *p, int n)
865 {
866 	int white, nwhite;
867 	char *ep;
868 	int nf;
869 
870 	if(p == nil)
871 		return 1;
872 
873 	nf = 0;
874 	ep = p+n;
875 	white = 1;	/* first text will start field */
876 	while(p < ep){
877 		nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0);	/* UTF is irrelevant */
878 		if(white && !nwhite)						/* beginning of field */
879 			nf++;
880 		white = nwhite;
881 	}
882 	return nf+1;								/* +1 for nil */
883 }
884 
885 /*
886  *  parse a command written to a device
887  */
888 static Cmdbuf*
parsecmd(char * p,int n)889 parsecmd(char *p, int n)
890 {
891 	Cmdbuf *cb;
892 	int nf;
893 	char *sp;
894 
895 	nf = ncmdfield(p, n);
896 
897 	/* allocate Cmdbuf plus string pointers plus copy of string including \0 */
898 	sp = malloc(sizeof(*cb) + nf * sizeof(char*) + n + 1);
899 	if(sp == nil)
900 		sysfatal("memory");
901 	cb = (Cmdbuf*)sp;
902 	cb->f = (char**)(&cb[1]);
903 	cb->buf = (char*)(&cb->f[nf]);
904 
905 	memmove(cb->buf, p, n);
906 
907 	/* dump new line and null terminate */
908 	if(n > 0 && cb->buf[n-1] == '\n')
909 		n--;
910 	cb->buf[n] = '\0';
911 
912 	cb->nf = tokenize(cb->buf, cb->f, nf-1);
913 	cb->f[cb->nf] = nil;
914 
915 	return cb;
916 }
917 
918 /*
919  * Look up entry in table
920  */
921 
922 static Cmdtab*
lookupcmd(Cmdbuf * cb,Cmdtab * ctab,int nctab)923 lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab)
924 {
925 	int i;
926 	Cmdtab *ct;
927 
928 	if(cb->nf == 0){
929 		werrstr("empty control message");
930 		return nil;
931 	}
932 
933 	for(ct = ctab, i=0; i<nctab; i++, ct++){
934 		if(strcmp(ct->cmd, "*") !=0)	/* wildcard always matches */
935 		if(strcmp(ct->cmd, cb->f[0]) != 0)
936 			continue;
937 		if(ct->narg != 0 && ct->narg != cb->nf){
938 			werrstr("bad # args to command");
939 			return nil;
940 		}
941 		return ct;
942 	}
943 
944 	werrstr("unknown control message");
945 	return nil;
946 }
947 
948 enum {
949 	CMcpuid,
950 	CMdebug,
951 	CMreset,
952 	CMstop,
953 	CMstartstop,
954 	CMwaitstop,
955 	CMstart,
956 	CMdump,
957 	CMveccatch,
958 	CMbreakpoint,
959 };
960 
961 static Cmdtab ctab[] = {
962 	CMdebug,	"debug",	2,
963 	CMreset,	"reset",	1,
964 	CMcpuid,	"cpuid",	1,
965 	CMstop,	"stop",	1,
966 	CMstart,	"start",	1,
967 	CMdump,	"dump",	3,
968 	CMveccatch,	"veccatch",	2,
969 	CMwaitstop,	"waitstop",	1,
970 	CMstartstop,	"startstop",	1,
971 	CMbreakpoint,	"breakpoint",	0,	/* 2 or 3 args, optional mask */
972 };
973 
974 static int
cmdcpuid(JMedium * jmed)975 cmdcpuid(JMedium *jmed)
976 {
977 	u32int cpuid;
978 
979 	cpuid = armidentify(jmed);
980 	dprint(Dfs, "---- Cpuid --- %8.8ux\n", cpuid);
981 	if(cpuid == ~0){
982 		werrstr("not feroceon or nstrs bug...");
983 		return -1;
984 	}
985 
986 	dprint(Dfs, "---- Bypass probe --- \n");
987 	if(armbpasstest(jmed) < 0){
988 		fprint(2, "error in bypass\n");
989 		werrstr("bypass test");
990 		return -1;
991 	}
992 	ctxt.cpuid = cpuid;
993 	return 0;
994 }
995 
996 static int
checkcpuid(JMedium * jmed)997 checkcpuid(JMedium *jmed)
998 {
999 	if(ctxt.cpuid != 0)
1000 		return 0;
1001 
1002 	return cmdcpuid(jmed);
1003 }
1004 
1005 
1006 typedef struct VecMode VecMode;
1007 struct VecMode{
1008 	char c;
1009 	u32int mode;
1010 };
1011 
1012 static VecMode vmode[] = {
1013 	{'R',	ResetCat},
1014 	{'S',	SWICat},
1015 	{'P',	PAbortCat},
1016 	{'D',	DAbortCat},
1017 	{'I',	IrqCat},
1018 	{'F',	FiqCat},
1019 };
1020 
1021 static u32int
vecval(char * conds)1022 vecval(char *conds)
1023 {
1024 	int i, j;
1025 	u32int vcregval;
1026 
1027 	vcregval = 0;
1028 	for(i = 0; i < strlen(conds); i++){
1029 		for(j = 0; j < nelem(vmode); j++){
1030 			if(vmode[j].c == conds[i])
1031 				vcregval |= vmode[j].mode;
1032 		}
1033 	}
1034 
1035 	return vcregval;
1036 }
1037 /* if running, stop, set catch, start, else, set catch, not start*/
1038 static int
cmdveccatch(JMedium * jmed,char * conds)1039 cmdveccatch(JMedium *jmed, char *conds)
1040 {
1041 	u32int vcregval;
1042 	int res, wasdebug;
1043 
1044 	wasdebug = ctxt.debug;
1045 	if(!wasdebug){
1046 		res = iceenterdebug(jmed, &ctxt);
1047 		if(res< 0){
1048 			werrstr("entering debug to set veccat");
1049 			return -1;
1050 		}
1051 	}
1052 
1053 	vcregval = vecval(conds);
1054 	res = setchain(jmed, ChCommit, 2);
1055 	if(res < 0)
1056 		return -1;
1057 	fprint(Dice, "veccatch: %#8.8ux\n", vcregval);
1058 	res = icesetreg(jmed, VecCatReg, vcregval);
1059 	if(res < 0)
1060 		return -1;
1061 
1062 	ctxt.exitreas = VeccatReqReas;
1063 	if(!wasdebug){
1064 		res = iceexitdebug(jmed, &ctxt);
1065 		if(res < 0){
1066 			werrstr("exiting debug to set veccat");
1067 			return -1;
1068 		}
1069 	}
1070 
1071 	return 0;
1072 }
1073 
1074 /* if running, stop, set breakpoint, start, else, set breakpoint, not start*/
1075 static int
cmdbreakpoint(JMedium * jmed,u32int addr,u32int mask)1076 cmdbreakpoint(JMedium *jmed, u32int addr, u32int mask)
1077 {
1078 	int res, wasdebug;
1079 
1080 	wasdebug = ctxt.debug;
1081 	if(!wasdebug){
1082 		if(ctxt.debugreas != BreakReas && ctxt.debugreas != NoReas){
1083 			werrstr("already waiting debug");
1084 			return -1;
1085 		}
1086 		res = iceenterdebug(jmed, &ctxt);
1087 		if(res< 0){
1088 			werrstr("entering debug to set breakpoint");
1089 			return -1;
1090 		}
1091 	}
1092 
1093 	res = setchain(jmed, ChCommit, 2);
1094 	if(res < 0)
1095 		return -1;
1096 	res = icesetreg(jmed, Wp0|AddrValReg, addr);
1097 	if(res < 0)
1098 		return -1;
1099 
1100 	res = icesetreg(jmed, Wp0|AddrMskReg, mask);
1101 	if(res < 0)
1102 		return -1;
1103 
1104 	res = icesetreg(jmed, Wp0|DataMskReg, 0xffffffff);
1105 	if(res < 0)
1106 		return -1;
1107 
1108 	res = icesetreg(jmed, Wp0|CtlMskReg, 0xff&~DataWPCtl);
1109 	if(res < 0)
1110 		return -1;
1111 	res = icesetreg(jmed, Wp0|CtlValReg, EnableWPCtl);
1112 	if(res < 0)
1113 		return -1;
1114 	fprint(Dice, "breakpoint: addr %#8.8ux msk %#8.8ux \n", addr, mask);
1115 
1116 	ctxt.exitreas = BreakReqReas;
1117 	if(!wasdebug){
1118 		res = iceexitdebug(jmed, &ctxt);
1119 		if(res < 0){
1120 			werrstr("exiting debug to set breakpoint");
1121 			return -1;
1122 		}
1123 	}
1124 	return 0;
1125 }
1126 
1127 static char dbgstr[4*1024];
1128 
1129 static int
cmdstop(JMedium * jmed)1130 cmdstop(JMedium *jmed)
1131 {
1132 	int res;
1133 
1134 	res = iceenterdebug(jmed, &ctxt);
1135 	if(res < 0){
1136 		return -1;
1137 	}
1138 
1139 	ctxt.debug = icedebugstate(fs.jmed);
1140 	return 0;
1141 }
1142 
1143 static int
cmdwaitstop(JMedium * jmed)1144 cmdwaitstop(JMedium *jmed)
1145 {
1146 	int res;
1147 
1148 	res = icewaitentry(jmed, &ctxt);
1149 	if(res < 0){
1150 		werrstr("timeout waiting for entry to debug state");
1151 		return -1;
1152 	}
1153 	return 0;
1154 }
1155 
1156 static int
cmdstart(JMedium * jmed)1157 cmdstart(JMedium *jmed)
1158 {
1159 	int res;
1160 	res = iceexitdebug(jmed, &ctxt);
1161 	if(res < 0){
1162 		werrstr("could not exit debug");
1163 		return -1;
1164 	}
1165 	ctxt.debug = icedebugstate(fs.jmed);
1166 	return 0;
1167 }
1168 
1169 static int
cmddump(JMedium * jmed,u32int start,u32int end)1170 cmddump(JMedium *jmed, u32int start, u32int end)
1171 {
1172 	int res, i;
1173 	u32int data;
1174 	debug[Dctxt] = 1;
1175 
1176 
1177 	for(i = 0; i < end-start; i+=4){
1178 		res = armrdmemwd(jmed, start+i, &data, 4);
1179 		if(res < 0){
1180 			fprint(2, "Error reading %#8.8ux [%#8.8ux]\n", start+i, i);
1181 			werrstr("read error");
1182 			return -1;
1183 			break;
1184 		}
1185 		dprint(Dfs, "%d[%#8.8ux] = %#8.8ux \n",
1186 				i, start+i, data);
1187 	}
1188 	return 0;
1189 }
1190 
1191 static int
cmdhwreset(Fs * fs)1192 cmdhwreset(Fs *fs)
1193 {
1194 	JMedium *jmed;
1195 
1196 	jmed = fs->jmed;
1197 	if(jmed->flush(jmed->mdata)){
1198 		werrstr("flush");
1199 		return -1;
1200 	}
1201 
1202 	fs->jmed = resetmpsse(fs->jmed);
1203 	if(fs->jmed == nil)
1204 		return -1;
1205 	ctxt.debug = 0;
1206 
1207 	jmed = fs->jmed;
1208 	/* BUG make this medium independant..., add a send 5 TMS to interface */
1209 	if(pushcmd(jmed->mdata, "TmsCsOut EdgeDown LSB B0x7 0x7f") < 0) {
1210 		werrstr("going to reset");
1211 		return -1;
1212 	}
1213 	if(jmed->flush(jmed->mdata)){
1214 		werrstr("flush");
1215 		return -1;
1216 	}
1217 	sleep(1000);
1218 	jmed->resets(jmed->mdata, 1, 0);
1219 	sleep(200);
1220 	jmed->resets(jmed->mdata, 1, 1);
1221 	sleep(200);
1222 	jmed->resets(jmed->mdata, 0, 1);
1223 	sleep(200);
1224 	jmed->resets(jmed->mdata, 0, 0);
1225 	sleep(200);
1226 	if(jmed->flush(jmed->mdata)){
1227 		werrstr("flush");
1228 		return -1;
1229 	}
1230 	memset(&ctxt, 0, sizeof(ArmCtxt));
1231 	return 0;
1232 }
1233 
1234 static int
cmdstartstop(JMedium * jmed)1235 cmdstartstop(JMedium *jmed)
1236 {
1237 	if(cmdstart(jmed) < 0){
1238 		werrstr("starting");
1239 		return -1;
1240 	}
1241 	if(cmdstop(jmed) < 0){
1242 		werrstr("stopping");
1243 		return -1;
1244 	}
1245 	return 0;
1246 }
1247 
1248 
1249 static int
runcmd(Fs * fs,char * data,int count)1250 runcmd(Fs *fs, char *data, int count)
1251 {
1252 	Cmdtab *t;
1253 	Cmdbuf *cb;
1254 	int res;
1255 	u32int st, end, addr, msk;
1256 
1257 	cb = parsecmd(data, count);
1258 	if(cb->nf < 1){
1259 		werrstr("empty control message");
1260 		free(cb);
1261 		return -1;
1262 	}
1263 
1264 	t = lookupcmd(cb, ctab, nelem(ctab));
1265 	if(t == nil){
1266 		free(cb);
1267 		return -1;
1268 	}
1269 
1270 	if(t->index != CMreset && t->index != CMcpuid &&
1271 		t->index != CMdebug &&
1272 		checkcpuid(fs->jmed) < 0)
1273 		return -1;
1274 
1275 	switch(t->index){
1276 	case CMdebug:
1277 		res = cmdsetdebug((uchar *)cb->f[1]);
1278 		break;
1279 	case CMreset:
1280 		dprint(Dfs, "reset\n");
1281 		res = cmdhwreset(fs);
1282 		break;
1283 	case CMcpuid:
1284 		dprint(Dfs, "cpuid\n");
1285 		res = checkcpuid(fs->jmed);
1286 		break;
1287 	case CMstop:
1288 		dprint(Dfs, "stop\n");
1289 		res = cmdstop(fs->jmed);
1290 		break;
1291 	case CMwaitstop:
1292 		dprint(Dfs, "waitstop\n");
1293 		res = cmdwaitstop(fs->jmed);
1294 		break;
1295 	case CMstart:
1296 		dprint(Dfs, "start\n");
1297 		res = cmdstart(fs->jmed);
1298 		break;
1299 	case CMdump:
1300 		st = atol(cb->f[1]);
1301 		end = atol(cb->f[2]);
1302 		dprint(Dfs, "dump %#8.8ux %#8.8ux\n", st, end);
1303 		res = cmddump(fs->jmed, st, end);
1304 		break;
1305 	case CMveccatch:
1306 		dprint(Dfs, "veccatch %s\n", cb->f[1]);
1307 		res = cmdveccatch(fs->jmed, cb->f[1]);
1308 		break;
1309 	case CMbreakpoint:
1310 		addr = atol(cb->f[1]);
1311 		if(cb->nf > 0 && cb->nf == 3)
1312 			msk = atol(cb->f[2]);
1313 		else	if(cb->nf > 0 && cb->nf == 2)
1314 				msk = 0;
1315 		else {
1316 			res = -1;
1317 			goto Exit;
1318 		}
1319 
1320 		dprint(Dfs, "breakpoint addr %#8.8ux mask %#8.8ux\n", addr, msk);
1321 		res = cmdbreakpoint(fs->jmed, addr, msk);
1322 		break;
1323 	default:
1324 		res = -1;
1325 	}
1326 Exit:
1327 	free(cb);
1328 	return res;
1329 }
1330 
1331 /* Arm (le) order to host */
1332 static void
getkernur(ArmCtxt * ct,Ureg * kur)1333 getkernur(ArmCtxt *ct, Ureg *kur)
1334 {
1335 	int i;
1336 
1337 	ct->cpsr = (ct->cpsr&~PsrMask) | kur->type;
1338 	ct->cpsr = lehgetl(&ct->cpsr);
1339 
1340 	ct->spsr = kur->psr;
1341 	ct->spsr = lehgetl(&ct->spsr);
1342 
1343 	memmove(ct->r, kur, 14*sizeof(u32int));
1344 	ct->r[15] = kur->pc;
1345 	for(i = 0; i < 15; i++)
1346 		ct->r[i] = lehgetl(ct->r + i);
1347 }
1348 
1349 static int
setkregs(Fs * fs,Fcall * rpc)1350 setkregs(Fs *fs, Fcall *rpc)
1351 {
1352 	Ureg kur;
1353 	ArmCtxt lc;
1354 	u32int mask, *lp, *gp;
1355 	int res, nb, i;
1356 	char *p;
1357 	JMedium *jmed;
1358 
1359 	jmed = fs->jmed;
1360 
1361 	nb = 0;
1362 	lc = ctxt;
1363 	setkernur(&kur, &ctxt);
1364 	p = (char *)&kur;
1365 	if(rpc->count + rpc->offset > sizeof(Ureg))	/* cannot write mmuregs*/
1366 		return -1;
1367 	else
1368 		memmove(p + rpc->offset, rpc->data, rpc->count);
1369 
1370 	getkernur(&ctxt, &kur);
1371 
1372 	/* BUG? hmm, order matters here, if I get both I am not sure of what to do */
1373 	if(ctxt.cpsr != lc.cpsr){
1374 		res = armsetexec(jmed, 1, &ctxt.cpsr, ARMLDMIA|0x0001);
1375 		if(res < 0)
1376 			return -1;
1377 		res = armgofetch(jmed, ARMMSRr0CPSR, 0);
1378 		if(res < 0)
1379 			return -1;
1380 		nb += sizeof(u32int);
1381 	}
1382 
1383 	if(ctxt.spsr != lc.spsr){
1384 		res = armsetexec(jmed, 1, &ctxt.spsr, ARMLDMIA|0x0001);
1385 		if(res < 0)
1386 			return -1;
1387 		res = armgofetch(jmed, ARMMSRr0SPSR, 0);
1388 		if(res < 0)
1389 			return -1;
1390 		nb += sizeof(u32int);
1391 	}
1392 
1393 
1394 
1395 	/* last I update the registers */
1396 	lp = (u32int *)&lc;
1397 	gp = (u32int *)&ctxt;
1398 	mask = 0;
1399 	for(i = 0; i < 16; i++){
1400 		if(lp[i] != gp[i]){	/* see which ones changed */
1401 			mask |= (1 << i);
1402 			nb += sizeof(u32int);
1403 		}
1404 	}
1405 	mask |= 0x0001;	/* this one I contaminated myself */
1406 	res = armsetregs(jmed, mask, ctxt.r);
1407 	if(res < 0)
1408 		return -1;
1409 	return nb;
1410 }
1411 
1412 static char*
fswrite(Fs * fs,Fcall * rpc)1413 fswrite(Fs *fs, Fcall *rpc)
1414 {
1415 	Fid *f;
1416 	int res, len;
1417 
1418 	f = getfid(fs, rpc->fid);
1419 	if(f == nil)
1420 		return Enofid;
1421 	if(!f->open){
1422 		putfid(fs, f);
1423 		return Enotopen;
1424 	}
1425 
1426 	if(f->qid.path == Qctl){
1427 		res = runcmd(fs, rpc->data, rpc->count);
1428 		if(res < 0){
1429 			fprint(2, "error %r\n");
1430 			putfid(fs, f);
1431 			return Ebadcmd;
1432 		}
1433 	}
1434 	else if(f->qid.path == Qmem){
1435 		len = writemem(fs, rpc);
1436 		if(len < 0){
1437 			putfid(fs, f);
1438 			return "reading memory";
1439 		}
1440 	}
1441 	else if(f->qid.path == Qkregs){
1442 		dprint(Dfs, "kregs write n %d off %d\n", rpc->count, rpc->offset);
1443 		len = setkregs(fs, rpc);
1444 		if(len < 0){
1445 			putfid(fs, f);
1446 			return "writing kregs";
1447 		}
1448 	}
1449 	else {
1450 		putfid(fs, f);
1451 		return Eperm;
1452 	}
1453 	putfid(fs, f);
1454 	return nil;
1455 }
1456 
1457 static char *
fsclunk(Fs * fs,Fcall * rpc)1458 fsclunk(Fs *fs, Fcall *rpc)
1459 {
1460 	Fid *f;
1461 
1462 	f = getfid(fs, rpc->fid);
1463 	if(f != nil){
1464 		f->attached = 0;
1465 		putfid(fs, f);
1466 	}
1467 	return nil;
1468 }
1469 
1470 static char *
fsremove(Fs *,Fcall *)1471 fsremove(Fs *, Fcall *)
1472 {
1473 	return Eperm;
1474 }
1475 
1476 static char *
fsstat(Fs * fs,Fcall * rpc)1477 fsstat(Fs *fs, Fcall *rpc)
1478 {
1479 	Fid *f;
1480 
1481 	f = getfid(fs, rpc->fid);
1482 	if(f == nil)
1483 		return Enofid;
1484 	rpc->stat = fs->statbuf;
1485 	rpc->nstat = dostat(f->qid.path, rpc->stat, sizeof fs->statbuf);
1486 	putfid(fs, f);
1487 	if(rpc->nstat <= BIT16SZ)
1488 		return "stat count too small";
1489 	return nil;
1490 }
1491 
1492 static char *
fswstat(Fs *,Fcall *)1493 fswstat(Fs *, Fcall *)
1494 {
1495 	return Eperm;
1496 }
1497 
1498 static int
dostat(int path,uchar * buf,int nbuf)1499 dostat(int path, uchar *buf, int nbuf)
1500 {
1501 	Dir d;
1502 
1503 	switch(path){
1504 	case Qroot:
1505 		d.name = ".";
1506 		d.mode = DMDIR|0555;
1507 		d.qid.type = QTDIR;
1508 		break;
1509 	case Qctl:
1510 		d.name = "ctl";
1511 		d.mode = 0666;
1512 		d.qid.type = QTFILE;
1513 		break;
1514 	case Qmem:
1515 		d.name = "mem";
1516 		d.mode = 0666;
1517 		d.qid.type = QTFILE;
1518 		break;
1519 	case Qkregs:
1520 		d.name = "kregs";
1521 		d.mode = 0666;
1522 		d.qid.type = QTFILE;
1523 		break;
1524 	case Qfpregs:
1525 		d.name = "fpregs";
1526 		d.mode = 0666;
1527 		d.qid.type = QTFILE;
1528 		break;
1529 	case Qproc:
1530 		d.name = "proc";
1531 		d.mode = 0444;
1532 		d.qid.type = QTFILE;
1533 		break;
1534 	case Qregs:
1535 		d.name = "regs";
1536 		d.mode = 0666;
1537 		d.qid.type = QTFILE;
1538 		break;
1539 	case Qtext:
1540 		d.name = "text";
1541 		d.mode = 0444;
1542 		d.qid.type = QTFILE;
1543 		break;
1544 	case Qstatus:
1545 		d.name = "status";
1546 		d.mode = 0444;
1547 		d.qid.type = QTFILE;
1548 		break;
1549 	}
1550 	d.qid.path = path;
1551 	d.qid.vers = 0;
1552 	d.length = 0;
1553 	d.uid = d.gid = d.muid = "none";
1554 	d.atime = d.mtime = time(nil);
1555 	return convD2M(&d, buf, nbuf);
1556 }
1557 
1558 static void
fatal(char * fmt,...)1559 fatal(char *fmt, ...)
1560 {
1561 	va_list arg;
1562 	char buf[1024];
1563 
1564 	write(2, "jtagfs: ", 8);
1565 	va_start(arg, fmt);
1566 	vseprint(buf, buf+1024, fmt, arg);
1567 	va_end(arg);
1568 	write(2, buf, strlen(buf));
1569 	write(2, "\n", 1);
1570 	exits(fmt);
1571 }
1572 
1573 static void *
emalloc(uint n)1574 emalloc(uint n)
1575 {
1576 	void *p;
1577 
1578 	p = malloc(n);
1579 	if(p == nil)
1580 		fatal("out of memory");
1581 	memset(p, 0, n);
1582 	return p;
1583 }
1584 
1585 static void
usage(void)1586 usage(void)
1587 {
1588 	fprint(2, "usage: jtagfs  [-t text] [-d debug] [-m mountpoint] [-s srvfile] jtag\n");
1589 	exits("usage");
1590 }
1591