xref: /plan9/sys/src/9/port/devroot.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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 	Qdir=	0,
10 
11 	Nfiles=32,	/* max root files */
12 };
13 
14 extern ulong	bootlen;
15 extern uchar	bootcode[];
16 
17 Dirtab rootdir[Nfiles] = {
18 	".",	{Qdir, 0, QTDIR},	0,		DMDIR|0555,
19 };
20 
21 static uchar	*rootdata[Nfiles];
22 static int	nroot = 1;
23 
24 /*
25  *  add a root file
26  */
27 static void
28 addroot(char *name, uchar *contents, ulong len, int perm)
29 {
30 	Dirtab *d;
31 
32 	if(nroot >= Nfiles)
33 		panic("too many root files");
34 	rootdata[nroot] = contents;
35 	d = &rootdir[nroot];
36 	strcpy(d->name, name);
37 	d->length = len;
38 	d->perm = perm;
39 	d->qid.type = 0;
40 	d->qid.vers = 0;
41 	d->qid.path = nroot+1;
42 	if(perm & DMDIR)
43 		d->qid.type |= QTDIR;
44 	nroot++;
45 }
46 
47 /*
48  *  add a root file
49  */
50 void
51 addrootfile(char *name, uchar *contents, ulong len)
52 {
53 	addroot(name, contents, len, 0555);
54 }
55 
56 /*
57  *  add a root file
58  */
59 static void
60 addrootdir(char *name)
61 {
62 	addroot(name, nil, 0, DMDIR|0555);
63 }
64 
65 static void
66 rootreset(void)
67 {
68 	addrootdir("bin");
69 	addrootdir("dev");
70 	addrootdir("env");
71 	addrootdir("fd");
72 	addrootdir("mnt");
73 	addrootdir("net");
74 	addrootdir("net.alt");
75 	addrootdir("proc");
76 	addrootdir("root");
77 	addrootdir("srv");
78 
79 	addrootfile("boot", bootcode, bootlen);	/* always have a boot file */
80 }
81 
82 static Chan*
83 rootattach(char *spec)
84 {
85 	return devattach('/', spec);
86 }
87 
88 static Walkqid*
89 rootwalk(Chan *c, Chan *nc, char **name, int nname)
90 {
91 	return devwalk(c,  nc, name, nname, rootdir, nroot, devgen);
92 }
93 
94 static int
95 rootstat(Chan *c, uchar *dp, int n)
96 {
97 	return devstat(c, dp, n, rootdir, nroot, devgen);
98 }
99 
100 static Chan*
101 rootopen(Chan *c, int omode)
102 {
103 	switch((ulong)c->qid.path) {
104 	default:
105 		break;
106 	}
107 
108 	return devopen(c, omode, rootdir, nroot, devgen);
109 }
110 
111 /*
112  * sysremove() knows this is a nop
113  */
114 static void
115 rootclose(Chan*)
116 {
117 }
118 
119 static long
120 rootread(Chan *c, void *buf, long n, vlong off)
121 {
122 	ulong t;
123 	Dirtab *d;
124 	uchar *data;
125 	ulong offset = off;
126 
127 	t = c->qid.path;
128 	switch(t){
129 	case Qdir:
130 		return devdirread(c, buf, n, rootdir, nroot, devgen);
131 	}
132 
133 	d = &rootdir[t-1];
134 	data = rootdata[t-1];
135 	if(offset >= d->length)
136 		return 0;
137 	if(offset+n > d->length)
138 		n = d->length - offset;
139 	memmove(buf, data+offset, n);
140 	return n;
141 }
142 
143 static long
144 rootwrite(Chan *c, void*, long, vlong)
145 {
146 	switch((ulong)c->qid.path){
147 	default:
148 		error(Egreg);
149 	}
150 	return 0;
151 }
152 
153 Dev rootdevtab = {
154 	'/',
155 	"root",
156 
157 	rootreset,
158 	devinit,
159 	devshutdown,
160 	rootattach,
161 	rootwalk,
162 	rootstat,
163 	rootopen,
164 	devcreate,
165 	rootclose,
166 	rootread,
167 	devbread,
168 	rootwrite,
169 	devbwrite,
170 	devremove,
171 	devwstat,
172 };
173