summaryrefslogtreecommitdiff
path: root/os/mpc/devboot.c
blob: 126fe6e6b6277e07b376fea04e96c5815b624c27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"

enum{
	Qdir,
	Qboot,
	Qmem,
};

Dirtab bootdir[]={
	".",			{Qdir,0,QTDIR},	0,	0555,
	"boot",		{Qboot},	0,	0666,
	"mem",		{Qmem},		0,	0666,
};

#define	NBOOT	(sizeof bootdir/sizeof(Dirtab))

static void
bootreset(void)
{
}

static Chan*
bootattach(char *spec)
{
	return devattach('B', spec);
}

static Walkqid*
bootwalk(Chan *c, Chan *nc, char **name, int nname)
{
	return devwalk(c, nc, name, nname, bootdir, NBOOT, devgen);
}

static int
bootstat(Chan *c, uchar *dp, int n)
{
	return devstat(c, dp, n, bootdir, NBOOT, devgen);
}

static Chan*
bootopen(Chan *c, int omode)
{
	return devopen(c, omode, bootdir, NBOOT, devgen);
}

static void	 
bootclose(Chan*)
{
}

static long	 
bootread(Chan *c, void *buf, long n, vlong off)
{
	ulong offset = off;

	switch((ulong)c->qid.path){

	case Qdir:
		return devdirread(c, buf, n, bootdir, NBOOT, devgen);

	case Qmem:
		/* kernel memory */
		if(offset>=KZERO && offset<KZERO+conf.npage*BY2PG){
			if(offset+n > KZERO+conf.npage*BY2PG)
				n = KZERO+conf.npage*BY2PG - offset;
			memmove(buf, (char*)offset, n);
			return n;
		}
		error(Ebadarg);
	}

	error(Egreg);
	return 0;	/* not reached */
}

static long	 
bootwrite(Chan *c, void *buf, long n, vlong off)
{
	ulong offset = off;
	ulong pc;
	uchar *p;

	switch((ulong)c->qid.path){
	case Qmem:
		/* kernel memory */
		if(offset>=KZERO && offset<KZERO+conf.npage*BY2PG){
			if(offset+n > KZERO+conf.npage*BY2PG)
				n = KZERO+conf.npage*BY2PG - offset;
			memmove((char*)offset, buf, n);
			segflush((void*)offset, n);
			return n;
		}
		error(Ebadarg);

	case Qboot:
		p = (uchar*)buf;
		pc = (((((p[0]<<8)|p[1])<<8)|p[2])<<8)|p[3];
		if(pc < KZERO || pc >= KZERO+conf.npage*BY2PG)
			error(Ebadarg);
		splhi();
		segflush((void*)pc, 64*1024);
		gotopc(pc);
	}
	error(Ebadarg);
	return 0;	/* not reached */
}

Dev bootdevtab = {
	'B',
	"boot",

	bootreset,
	devinit,
	devshutdown,
	bootattach,
	bootwalk,
	bootstat,
	bootopen,
	devcreate,
	bootclose,
	bootread,
	devbread,
	bootwrite,
	devbwrite,
	devremove,
	devwstat,
};