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