Devtab created with linker tables
[akaros.git] / kern / drivers / dev / root.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 /* courtesy of the inferno mkroot script. */
17 int rootmaxq = 12;
18 struct dirtab roottab[12] = {
19         {"",    {0, 0, QTDIR},   0,     0555},
20         {"chan",        {1, 0, QTDIR},   0,     0555},
21         {"dev", {2, 0, QTDIR},   0,     0555},
22         {"fd",  {3, 0, QTDIR},   0,     0555},
23         {"prog",        {4, 0, QTDIR},   0,     0555},
24         {"prof",        {5, 0, QTDIR},   0,     0555},
25         {"net", {6, 0, QTDIR},   0,     0555},
26         {"net.alt",     {7, 0, QTDIR},   0,     0555},
27         {"nvfs",        {8, 0, QTDIR},   0,     0555},
28         {"env", {9, 0, QTDIR},   0,     0555},
29         {"root",        {10, 0, QTDIR},  0,     0555},
30         {"srv", {11, 0, QTDIR},  0,     0555},
31 };
32 struct rootdata rootdata[12] = {
33         {0,      &roottab[1],    11,    NULL},
34         {0,      NULL,   0,      NULL},
35         {0,      NULL,   0,      NULL},
36         {0,      NULL,   0,      NULL},
37         {0,      NULL,   0,      NULL},
38         {0,      NULL,   0,      NULL},
39         {0,      NULL,   0,      NULL},
40         {0,      NULL,   0,      NULL},
41         {0,      NULL,   0,      NULL},
42         {0,      NULL,   0,      NULL},
43         {0,      NULL,   0,      NULL},
44         {0,      NULL,   0,      NULL},
45 };
46
47 static struct chan*
48 rootattach(char *spec)
49 {
50         int i;
51         uint32_t len;
52         struct rootdata *r;
53
54         if(*spec)
55                 error(Ebadspec);
56         for (i = 0; i < rootmaxq; i++){
57                 r = &rootdata[i];
58                 if (r->sizep){
59                         len = *r->sizep;
60                         r->size = len;
61                         roottab[i].length = len;
62                 }
63         }
64         return devattach('r', spec);
65 }
66
67 static int
68 rootgen(struct chan *c, char *name,
69         struct dirtab *tab, int nd, int s, struct dir *dp)
70 {
71         int p, i;
72         struct rootdata *r;
73
74         if(s == DEVDOTDOT){
75                 p = rootdata[c->qid.path].dotdot;
76                 c->qid.path = p;
77                 c->qid.type = QTDIR;
78                 name = "#r";
79                 if(p != 0){
80                         for(i = 0; i < rootmaxq; i++)
81                                 if(roottab[i].qid.path == c->qid.path){
82                                         name = roottab[i].name;
83                                         break;
84                                 }
85                 }
86                 devdir(c, c->qid, name, 0, eve, 0555, dp);
87                 return 1;
88         }
89         if(name != NULL){
90                 isdir(c);
91                 r = &rootdata[(int)c->qid.path];
92                 tab = r->ptr;
93                 for(i=0; i<r->size; i++, tab++)
94                         if(strcmp(tab->name, name) == 0){
95                                 devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
96                                 return 1;
97                         }
98                 return -1;
99         }
100         if(s >= nd)
101                 return -1;
102         tab += s;
103         devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
104         return 1;
105 }
106
107 static struct walkqid*
108 rootwalk(struct chan *c, struct chan *nc, char **name, int nname)
109 {
110         uint32_t p;
111
112         p = c->qid.path;
113         if(nname == 0)
114                 p = rootdata[p].dotdot;
115         return devwalk(c, nc, name, nname, rootdata[p].ptr, rootdata[p].size, rootgen);
116 }
117
118 static int
119 rootstat(struct chan *c, uint8_t *dp, int n)
120 {
121         int p;
122
123         p = rootdata[c->qid.path].dotdot;
124         return devstat(c, dp, n, rootdata[p].ptr, rootdata[p].size, rootgen);
125 }
126
127 static struct chan*
128 rootopen(struct chan *c, int omode)
129 {
130         int p;
131
132         p = rootdata[c->qid.path].dotdot;
133         return devopen(c, omode, rootdata[p].ptr, rootdata[p].size, rootgen);
134 }
135
136 /*
137  * sysremove() knows this is a nop
138  */
139 static void      
140 rootclose(struct chan *c)
141 {
142 }
143
144 static long      
145 rootread(struct chan *c, void *buf, long n, int64_t offset)
146 {
147         uint32_t p, len;
148         uint8_t *data;
149
150         p = c->qid.path;
151         if(c->qid.type & QTDIR)
152                 return devdirread(c, buf, n, rootdata[p].ptr, rootdata[p].size, rootgen);
153         len = rootdata[p].size;
154         if(offset < 0 || offset >= len)
155                 return 0;
156         if(offset+n > len)
157                 n = len - offset;
158         data = rootdata[p].ptr;
159         memmove(buf, data+offset, n);
160         return n;
161 }
162
163 static long      
164 rootwrite(struct chan *c, void *a, long n, int64_t off)
165 {
166         error(Eperm);
167         return 0;
168 }
169
170 struct dev rootdevtab __devtab = {
171         'r',
172         "root",
173         devreset,
174         devinit,
175         devshutdown,
176         rootattach,
177         rootwalk,
178         rootstat,
179         rootopen,
180         devcreate,
181         rootclose,
182         rootread,
183         devbread,
184         rootwrite,
185         devbwrite,
186         devremove,
187         devwstat,
188 };