xref: /plan9/sys/src/9/port/devroot.c (revision 9acf08355bbda9b28aaf3d1ea7fa4e1adfa4d13f)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"../port/error.h"
7 
8 enum
9 {
10 	Qdir = 0,
11 	Qboot = 0x1000,
12 
13 	Nrootfiles = 32,
14 	Nbootfiles = 32,
15 };
16 
17 typedef struct Dirlist Dirlist;
18 struct Dirlist
19 {
20 	uint base;
21 	Dirtab *dir;
22 	uchar **data;
23 	int ndir;
24 	int mdir;
25 };
26 
27 static Dirtab rootdir[Nrootfiles] = {
28 	"#/",		{Qdir, 0, QTDIR},	0,		DMDIR|0555,
29 	"boot",	{Qboot, 0, QTDIR},	0,		DMDIR|0555,
30 };
31 static uchar *rootdata[Nrootfiles];
32 static Dirlist rootlist =
33 {
34 	0,
35 	rootdir,
36 	rootdata,
37 	2,
38 	Nrootfiles
39 };
40 
41 static Dirtab bootdir[Nbootfiles] = {
42 	"boot",	{Qboot, 0, QTDIR},	0,		DMDIR|0555,
43 };
44 static uchar *bootdata[Nbootfiles];
45 static Dirlist bootlist =
46 {
47 	Qboot,
48 	bootdir,
49 	bootdata,
50 	1,
51 	Nbootfiles
52 };
53 
54 /*
55  *  add a file to the list
56  */
57 static void
addlist(Dirlist * l,char * name,uchar * contents,ulong len,int perm)58 addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm)
59 {
60 	Dirtab *d;
61 
62 	if(l->ndir >= l->mdir)
63 		panic("too many root files");
64 	l->data[l->ndir] = contents;
65 	d = &l->dir[l->ndir];
66 	strcpy(d->name, name);
67 	d->length = len;
68 	d->perm = perm;
69 	d->qid.type = 0;
70 	d->qid.vers = 0;
71 	d->qid.path = ++l->ndir + l->base;
72 	if(perm & DMDIR)
73 		d->qid.type |= QTDIR;
74 }
75 
76 /*
77  *  add a root file
78  */
79 void
addbootfile(char * name,uchar * contents,ulong len)80 addbootfile(char *name, uchar *contents, ulong len)
81 {
82 	addlist(&bootlist, name, contents, len, 0555);
83 }
84 
85 /*
86  *  add a root directory
87  */
88 static void
addrootdir(char * name)89 addrootdir(char *name)
90 {
91 	addlist(&rootlist, name, nil, 0, DMDIR|0555);
92 }
93 
94 static void
rootreset(void)95 rootreset(void)
96 {
97 	addrootdir("bin");
98 	addrootdir("dev");
99 	addrootdir("env");
100 	addrootdir("fd");
101 	addrootdir("mnt");
102 	addrootdir("net");
103 	addrootdir("net.alt");
104 	addrootdir("proc");
105 	addrootdir("root");
106 	addrootdir("srv");
107 }
108 
109 static Chan*
rootattach(char * spec)110 rootattach(char *spec)
111 {
112 	return devattach('/', spec);
113 }
114 
115 static int
rootgen(Chan * c,char * name,Dirtab *,int,int s,Dir * dp)116 rootgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
117 {
118 	int t;
119 	Dirtab *d;
120 	Dirlist *l;
121 
122 	switch((int)c->qid.path){
123 	case Qdir:
124 		if(s == DEVDOTDOT){
125 			devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
126 			return 1;
127 		}
128 		return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
129 	case Qboot:
130 		if(s == DEVDOTDOT){
131 			devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
132 			return 1;
133 		}
134 		return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
135 	default:
136 		if(s == DEVDOTDOT){
137 			if((int)c->qid.path < Qboot)
138 				devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
139 			else
140 				devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
141 			return 1;
142 		}
143 		if(s != 0)
144 			return -1;
145 		if((int)c->qid.path < Qboot){
146 			t = c->qid.path-1;
147 			l = &rootlist;
148 		}else{
149 			t = c->qid.path - Qboot - 1;
150 			l = &bootlist;
151 		}
152 		if(t >= l->ndir)
153 			return -1;
154 if(t < 0){
155 print("rootgen %llud %d %d\n", c->qid.path, s, t);
156 panic("whoops");
157 }
158 		d = &l->dir[t];
159 		devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
160 		return 1;
161 	}
162 }
163 
164 static Walkqid*
rootwalk(Chan * c,Chan * nc,char ** name,int nname)165 rootwalk(Chan *c, Chan *nc, char **name, int nname)
166 {
167 	return devwalk(c,  nc, name, nname, nil, 0, rootgen);
168 }
169 
170 static int
rootstat(Chan * c,uchar * dp,int n)171 rootstat(Chan *c, uchar *dp, int n)
172 {
173 	return devstat(c, dp, n, nil, 0, rootgen);
174 }
175 
176 static Chan*
rootopen(Chan * c,int omode)177 rootopen(Chan *c, int omode)
178 {
179 	return devopen(c, omode, nil, 0, devgen);
180 }
181 
182 /*
183  * sysremove() knows this is a nop
184  */
185 static void
rootclose(Chan *)186 rootclose(Chan*)
187 {
188 }
189 
190 static long
rootread(Chan * c,void * buf,long n,vlong off)191 rootread(Chan *c, void *buf, long n, vlong off)
192 {
193 	ulong t;
194 	Dirtab *d;
195 	Dirlist *l;
196 	uchar *data;
197 	ulong offset = off;
198 
199 	t = c->qid.path;
200 	switch(t){
201 	case Qdir:
202 	case Qboot:
203 		return devdirread(c, buf, n, nil, 0, rootgen);
204 	}
205 
206 	if(t<Qboot)
207 		l = &rootlist;
208 	else{
209 		t -= Qboot;
210 		l = &bootlist;
211 	}
212 
213 	t--;
214 	if(t >= l->ndir)
215 		error(Egreg);
216 
217 	d = &l->dir[t];
218 	data = l->data[t];
219 	if(offset >= d->length)
220 		return 0;
221 	if(offset+n > d->length)
222 		n = d->length - offset;
223 #ifdef asdf
224 print("[%d] kaddr %.8ulx base %.8ulx offset %ld (%.8ulx), n %d %.8ulx %.8ulx %.8ulx\n",
225 		t, buf, data, offset, offset, n,
226 		((ulong*)(data+offset))[0],
227 		((ulong*)(data+offset))[1],
228 		((ulong*)(data+offset))[2]);
229 #endif asdf
230 	memmove(buf, data+offset, n);
231 	return n;
232 }
233 
234 static long
rootwrite(Chan *,void *,long,vlong)235 rootwrite(Chan*, void*, long, vlong)
236 {
237 	error(Egreg);
238 	return 0;
239 }
240 
241 Dev rootdevtab = {
242 	'/',
243 	"root",
244 
245 	rootreset,
246 	devinit,
247 	devshutdown,
248 	rootattach,
249 	rootwalk,
250 	rootstat,
251 	rootopen,
252 	devcreate,
253 	rootclose,
254 	rootread,
255 	devbread,
256 	rootwrite,
257 	devbwrite,
258 	devremove,
259 	devwstat,
260 };
261 
262