xref: /plan9/sys/src/9/port/devroot.c (revision a84536681645e23c630ce4ef2e5c3b284d4c590b)
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
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
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
89 addrootdir(char *name)
90 {
91 	addlist(&rootlist, name, nil, 0, DMDIR|0555);
92 }
93 
94 static 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*
110 rootattach(char *spec)
111 {
112 	return devattach('/', spec);
113 }
114 
115 static int
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 	return -1;
163 }
164 
165 static Walkqid*
166 rootwalk(Chan *c, Chan *nc, char **name, int nname)
167 {
168 	return devwalk(c,  nc, name, nname, nil, 0, rootgen);
169 }
170 
171 static int
172 rootstat(Chan *c, uchar *dp, int n)
173 {
174 	return devstat(c, dp, n, nil, 0, rootgen);
175 }
176 
177 static Chan*
178 rootopen(Chan *c, int omode)
179 {
180 	return devopen(c, omode, nil, 0, devgen);
181 }
182 
183 /*
184  * sysremove() knows this is a nop
185  */
186 static void
187 rootclose(Chan*)
188 {
189 }
190 
191 static long
192 rootread(Chan *c, void *buf, long n, vlong off)
193 {
194 	ulong t;
195 	Dirtab *d;
196 	Dirlist *l;
197 	uchar *data;
198 	ulong offset = off;
199 
200 	t = c->qid.path;
201 	switch(t){
202 	case Qdir:
203 	case Qboot:
204 		return devdirread(c, buf, n, nil, 0, rootgen);
205 	}
206 
207 	if(t<Qboot)
208 		l = &rootlist;
209 	else{
210 		t -= Qboot;
211 		l = &bootlist;
212 	}
213 
214 	t--;
215 	if(t >= l->ndir)
216 		error(Egreg);
217 
218 	d = &l->dir[t];
219 	data = l->data[t];
220 	if(offset >= d->length)
221 		return 0;
222 	if(offset+n > d->length)
223 		n = d->length - offset;
224 #ifdef asdf
225 print("[%d] kaddr %.8ulx base %.8ulx offset %ld (%.8ulx), n %d %.8ulx %.8ulx %.8ulx\n",
226 		t, buf, data, offset, offset, n,
227 		((ulong*)(data+offset))[0],
228 		((ulong*)(data+offset))[1],
229 		((ulong*)(data+offset))[2]);
230 #endif asdf
231 	memmove(buf, data+offset, n);
232 	return n;
233 }
234 
235 static long
236 rootwrite(Chan*, void*, long, vlong)
237 {
238 	error(Egreg);
239 	return 0;
240 }
241 
242 Dev rootdevtab = {
243 	'/',
244 	"root",
245 
246 	rootreset,
247 	devinit,
248 	devshutdown,
249 	rootattach,
250 	rootwalk,
251 	rootstat,
252 	rootopen,
253 	devcreate,
254 	rootclose,
255 	rootread,
256 	devbread,
257 	rootwrite,
258 	devbwrite,
259 	devremove,
260 	devwstat,
261 };
262 
263