xref: /inferno-os/os/boot/pc/kfsboot.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth #include	"u.h"
2*74a4d8c2SCharles.Forsyth #include	"lib.h"
3*74a4d8c2SCharles.Forsyth #include	"mem.h"
4*74a4d8c2SCharles.Forsyth #include	"dat.h"
5*74a4d8c2SCharles.Forsyth #include	"fns.h"
6*74a4d8c2SCharles.Forsyth #include	"fs.h"
7*74a4d8c2SCharles.Forsyth 
8*74a4d8c2SCharles.Forsyth typedef struct Tag Tag;
9*74a4d8c2SCharles.Forsyth 
10*74a4d8c2SCharles.Forsyth /*
11*74a4d8c2SCharles.Forsyth  * tags on block
12*74a4d8c2SCharles.Forsyth  */
13*74a4d8c2SCharles.Forsyth enum
14*74a4d8c2SCharles.Forsyth {
15*74a4d8c2SCharles.Forsyth 	Tnone		= 0,
16*74a4d8c2SCharles.Forsyth 	Tsuper,			/* the super block */
17*74a4d8c2SCharles.Forsyth 	Tdir,			/* directory contents */
18*74a4d8c2SCharles.Forsyth 	Tind1,			/* points to blocks */
19*74a4d8c2SCharles.Forsyth 	Tind2,			/* points to Tind1 */
20*74a4d8c2SCharles.Forsyth 	Tfile,			/* file contents */
21*74a4d8c2SCharles.Forsyth 	Tfree,			/* in free list */
22*74a4d8c2SCharles.Forsyth 	Tbuck,			/* cache fs bucket */
23*74a4d8c2SCharles.Forsyth 	Tvirgo,			/* fake worm virgin bits */
24*74a4d8c2SCharles.Forsyth 	Tcache,			/* cw cache things */
25*74a4d8c2SCharles.Forsyth 	MAXTAG
26*74a4d8c2SCharles.Forsyth };
27*74a4d8c2SCharles.Forsyth 
28*74a4d8c2SCharles.Forsyth #define	QPDIR	0x80000000L
29*74a4d8c2SCharles.Forsyth #define	QPNONE	0
30*74a4d8c2SCharles.Forsyth #define	QPROOT	1
31*74a4d8c2SCharles.Forsyth #define	QPSUPER	2
32*74a4d8c2SCharles.Forsyth 
33*74a4d8c2SCharles.Forsyth /* DONT TOUCH, this is the disk structure */
34*74a4d8c2SCharles.Forsyth struct	Tag
35*74a4d8c2SCharles.Forsyth {
36*74a4d8c2SCharles.Forsyth 	short	pad;
37*74a4d8c2SCharles.Forsyth 	short	tag;
38*74a4d8c2SCharles.Forsyth 	long	path;
39*74a4d8c2SCharles.Forsyth };
40*74a4d8c2SCharles.Forsyth 
41*74a4d8c2SCharles.Forsyth static int thisblock = -1;
42*74a4d8c2SCharles.Forsyth static Fs *thisfs;
43*74a4d8c2SCharles.Forsyth static uchar *block;
44*74a4d8c2SCharles.Forsyth 
45*74a4d8c2SCharles.Forsyth /*
46*74a4d8c2SCharles.Forsyth  * we end up reading 2x or 3x the number of blocks we need to read.
47*74a4d8c2SCharles.Forsyth  * this is okay because we need to read so few.  if it wasn't okay, we could
48*74a4d8c2SCharles.Forsyth  * have getblock return a pointer to a block, and keep a cache of the last
49*74a4d8c2SCharles.Forsyth  * three read blocks.  that would get us down to the minimum.
50*74a4d8c2SCharles.Forsyth  * but this is fine.
51*74a4d8c2SCharles.Forsyth  */
52*74a4d8c2SCharles.Forsyth static int
getblock(Fs * fs,ulong n)53*74a4d8c2SCharles.Forsyth getblock(Fs *fs, ulong n)
54*74a4d8c2SCharles.Forsyth {
55*74a4d8c2SCharles.Forsyth 	if(!block)
56*74a4d8c2SCharles.Forsyth 		block = malloc(16384);
57*74a4d8c2SCharles.Forsyth 
58*74a4d8c2SCharles.Forsyth 	if(thisblock == n && thisfs == fs)
59*74a4d8c2SCharles.Forsyth 		return 0;
60*74a4d8c2SCharles.Forsyth 	thisblock = -1;
61*74a4d8c2SCharles.Forsyth 	if(fs->diskseek(fs, (vlong)n*fs->kfs.RBUFSIZE) < 0)
62*74a4d8c2SCharles.Forsyth 		return -1;
63*74a4d8c2SCharles.Forsyth 	if(fs->diskread(fs, block, fs->kfs.RBUFSIZE) != fs->kfs.RBUFSIZE)
64*74a4d8c2SCharles.Forsyth 		return -1;
65*74a4d8c2SCharles.Forsyth 	thisblock = n;
66*74a4d8c2SCharles.Forsyth 	thisfs = fs;
67*74a4d8c2SCharles.Forsyth 
68*74a4d8c2SCharles.Forsyth 	return 1;
69*74a4d8c2SCharles.Forsyth }
70*74a4d8c2SCharles.Forsyth 
71*74a4d8c2SCharles.Forsyth static int
checktag(Fs * fs,uchar * block,int tag,long qpath)72*74a4d8c2SCharles.Forsyth checktag(Fs *fs, uchar *block, int tag, long qpath)
73*74a4d8c2SCharles.Forsyth {
74*74a4d8c2SCharles.Forsyth 	Tag *t;
75*74a4d8c2SCharles.Forsyth 
76*74a4d8c2SCharles.Forsyth 	t = (Tag*)(block+fs->kfs.BUFSIZE);
77*74a4d8c2SCharles.Forsyth 	if(t->tag != tag)
78*74a4d8c2SCharles.Forsyth 		return -1;
79*74a4d8c2SCharles.Forsyth 	if(qpath != QPNONE && (qpath&~QPDIR) != t->path)
80*74a4d8c2SCharles.Forsyth 		return -1;
81*74a4d8c2SCharles.Forsyth 	return 1;
82*74a4d8c2SCharles.Forsyth }
83*74a4d8c2SCharles.Forsyth 
84*74a4d8c2SCharles.Forsyth static int
getblocktag(Fs * fs,ulong n,int tag,long qpath)85*74a4d8c2SCharles.Forsyth getblocktag(Fs *fs, ulong n, int tag, long qpath)
86*74a4d8c2SCharles.Forsyth {
87*74a4d8c2SCharles.Forsyth 	if(getblock(fs, n) < 0 || checktag(fs, block, tag, qpath) < 0)
88*74a4d8c2SCharles.Forsyth 		return -1;
89*74a4d8c2SCharles.Forsyth 	return 1;
90*74a4d8c2SCharles.Forsyth }
91*74a4d8c2SCharles.Forsyth 
92*74a4d8c2SCharles.Forsyth static int
readinfo(Fs * fs)93*74a4d8c2SCharles.Forsyth readinfo(Fs *fs)
94*74a4d8c2SCharles.Forsyth {
95*74a4d8c2SCharles.Forsyth 	fs->kfs.RBUFSIZE = 512;
96*74a4d8c2SCharles.Forsyth 	if(getblock(fs, 0) < 0)
97*74a4d8c2SCharles.Forsyth 		return -1;
98*74a4d8c2SCharles.Forsyth 
99*74a4d8c2SCharles.Forsyth 	if(memcmp(block+256, "kfs wren device\n", 16) != 0)
100*74a4d8c2SCharles.Forsyth 		return -1;
101*74a4d8c2SCharles.Forsyth 
102*74a4d8c2SCharles.Forsyth 	fs->kfs.RBUFSIZE = atoi((char*)block+256+16);
103*74a4d8c2SCharles.Forsyth 	if(!fs->kfs.RBUFSIZE || (fs->kfs.RBUFSIZE&(fs->kfs.RBUFSIZE-1)))
104*74a4d8c2SCharles.Forsyth 		return -1;
105*74a4d8c2SCharles.Forsyth 
106*74a4d8c2SCharles.Forsyth 	fs->kfs.BUFSIZE = fs->kfs.RBUFSIZE - sizeof(Tag);
107*74a4d8c2SCharles.Forsyth 	fs->kfs.DIRPERBUF = fs->kfs.BUFSIZE / sizeof(Dentry);
108*74a4d8c2SCharles.Forsyth 	fs->kfs.INDPERBUF = fs->kfs.BUFSIZE / sizeof(long);
109*74a4d8c2SCharles.Forsyth 	fs->kfs.INDPERBUF2 = fs->kfs.INDPERBUF * fs->kfs.INDPERBUF;
110*74a4d8c2SCharles.Forsyth 
111*74a4d8c2SCharles.Forsyth 	return 1;
112*74a4d8c2SCharles.Forsyth }
113*74a4d8c2SCharles.Forsyth 
114*74a4d8c2SCharles.Forsyth static int
readroot(Fs * fs,Dentry * d)115*74a4d8c2SCharles.Forsyth readroot(Fs *fs, Dentry *d)
116*74a4d8c2SCharles.Forsyth {
117*74a4d8c2SCharles.Forsyth 	Dentry *d2;
118*74a4d8c2SCharles.Forsyth 
119*74a4d8c2SCharles.Forsyth 	if(getblocktag(fs, 2, Tdir, QPROOT) < 0)
120*74a4d8c2SCharles.Forsyth 		return -1;
121*74a4d8c2SCharles.Forsyth 	d2 = (Dentry*)block;
122*74a4d8c2SCharles.Forsyth 	if(strcmp(d2->name, "/") != 0)
123*74a4d8c2SCharles.Forsyth 		return -1;
124*74a4d8c2SCharles.Forsyth 	*d = *(Dentry*)block;
125*74a4d8c2SCharles.Forsyth 	return 1;
126*74a4d8c2SCharles.Forsyth }
127*74a4d8c2SCharles.Forsyth 
128*74a4d8c2SCharles.Forsyth static long
indfetch(Fs * fs,long addr,long off,int tag,long path)129*74a4d8c2SCharles.Forsyth indfetch(Fs *fs, long addr, long off, int tag, long path)
130*74a4d8c2SCharles.Forsyth {
131*74a4d8c2SCharles.Forsyth 	if(getblocktag(fs, addr, tag, path) < 0)
132*74a4d8c2SCharles.Forsyth 		return -1;
133*74a4d8c2SCharles.Forsyth 	return ((long*)block)[off];
134*74a4d8c2SCharles.Forsyth }
135*74a4d8c2SCharles.Forsyth 
136*74a4d8c2SCharles.Forsyth static long
rel2abs(Fs * fs,Dentry * d,long a)137*74a4d8c2SCharles.Forsyth rel2abs(Fs *fs, Dentry *d, long a)
138*74a4d8c2SCharles.Forsyth {
139*74a4d8c2SCharles.Forsyth 	long addr;
140*74a4d8c2SCharles.Forsyth 
141*74a4d8c2SCharles.Forsyth 	if(a < NDBLOCK)
142*74a4d8c2SCharles.Forsyth 		return d->dblock[a];
143*74a4d8c2SCharles.Forsyth 	a -= NDBLOCK;
144*74a4d8c2SCharles.Forsyth 	if(a < fs->kfs.INDPERBUF){
145*74a4d8c2SCharles.Forsyth 		if(d->iblock == 0)
146*74a4d8c2SCharles.Forsyth 			return 0;
147*74a4d8c2SCharles.Forsyth 		addr = indfetch(fs, d->iblock, a, Tind1, d->qid.path);
148*74a4d8c2SCharles.Forsyth 		if(addr == 0)
149*74a4d8c2SCharles.Forsyth 			print("rel2abs indfetch 0 %s %ld\n", d->name, a);
150*74a4d8c2SCharles.Forsyth 		return addr;
151*74a4d8c2SCharles.Forsyth 	}
152*74a4d8c2SCharles.Forsyth 	a -= fs->kfs.INDPERBUF;
153*74a4d8c2SCharles.Forsyth 	if(a < fs->kfs.INDPERBUF2){
154*74a4d8c2SCharles.Forsyth 		if(d->diblock == 0)
155*74a4d8c2SCharles.Forsyth 			return 0;
156*74a4d8c2SCharles.Forsyth 		addr = indfetch(fs, d->diblock, a/fs->kfs.INDPERBUF, Tind2, d->qid.path);
157*74a4d8c2SCharles.Forsyth 		if(addr == 0){
158*74a4d8c2SCharles.Forsyth 			print("rel2abs indfetch 0 %s %ld\n", d->name, a/fs->kfs.INDPERBUF);
159*74a4d8c2SCharles.Forsyth 			return 0;
160*74a4d8c2SCharles.Forsyth 		}
161*74a4d8c2SCharles.Forsyth 		addr = indfetch(fs, addr, a%fs->kfs.INDPERBUF, Tind1, d->qid.path);
162*74a4d8c2SCharles.Forsyth 		return addr;
163*74a4d8c2SCharles.Forsyth 	}
164*74a4d8c2SCharles.Forsyth 	print("rel2abs trip ind %s %ld\n", d->name, a);
165*74a4d8c2SCharles.Forsyth 	return -1;
166*74a4d8c2SCharles.Forsyth }
167*74a4d8c2SCharles.Forsyth 
168*74a4d8c2SCharles.Forsyth static int
readdentry(Fs * fs,Dentry * d,int n,Dentry * e)169*74a4d8c2SCharles.Forsyth readdentry(Fs *fs, Dentry *d, int n, Dentry *e)
170*74a4d8c2SCharles.Forsyth {
171*74a4d8c2SCharles.Forsyth 	long addr, m;
172*74a4d8c2SCharles.Forsyth 
173*74a4d8c2SCharles.Forsyth 	m = n/fs->kfs.DIRPERBUF;
174*74a4d8c2SCharles.Forsyth 	if((addr = rel2abs(fs, d, m)) <= 0)
175*74a4d8c2SCharles.Forsyth 		return addr;
176*74a4d8c2SCharles.Forsyth 	if(getblocktag(fs, addr, Tdir, d->qid.path) < 0)
177*74a4d8c2SCharles.Forsyth 		return -1;
178*74a4d8c2SCharles.Forsyth 	*e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry));
179*74a4d8c2SCharles.Forsyth 	return 1;
180*74a4d8c2SCharles.Forsyth }
181*74a4d8c2SCharles.Forsyth 
182*74a4d8c2SCharles.Forsyth static int
getdatablock(Fs * fs,Dentry * d,long a)183*74a4d8c2SCharles.Forsyth getdatablock(Fs *fs, Dentry *d, long a)
184*74a4d8c2SCharles.Forsyth {
185*74a4d8c2SCharles.Forsyth 	long addr;
186*74a4d8c2SCharles.Forsyth 
187*74a4d8c2SCharles.Forsyth 	if((addr = rel2abs(fs, d, a)) == 0)
188*74a4d8c2SCharles.Forsyth 		return -1;
189*74a4d8c2SCharles.Forsyth 	return getblocktag(fs, addr, Tfile, QPNONE);
190*74a4d8c2SCharles.Forsyth }
191*74a4d8c2SCharles.Forsyth 
192*74a4d8c2SCharles.Forsyth static int
walk(Fs * fs,Dentry * d,char * name,Dentry * e)193*74a4d8c2SCharles.Forsyth walk(Fs *fs, Dentry *d, char *name, Dentry *e)
194*74a4d8c2SCharles.Forsyth {
195*74a4d8c2SCharles.Forsyth 	int i, n;
196*74a4d8c2SCharles.Forsyth 	Dentry x;
197*74a4d8c2SCharles.Forsyth 
198*74a4d8c2SCharles.Forsyth 	for(i=0;; i++){
199*74a4d8c2SCharles.Forsyth 		if((n=readdentry(fs, d, i, &x)) <= 0)
200*74a4d8c2SCharles.Forsyth 			return n;
201*74a4d8c2SCharles.Forsyth 		if(strcmp(x.name, name) == 0){
202*74a4d8c2SCharles.Forsyth 			*e = x;
203*74a4d8c2SCharles.Forsyth 			return 1;
204*74a4d8c2SCharles.Forsyth 		}
205*74a4d8c2SCharles.Forsyth 	}
206*74a4d8c2SCharles.Forsyth }
207*74a4d8c2SCharles.Forsyth 
208*74a4d8c2SCharles.Forsyth static long
kfsread(File * f,void * va,long len)209*74a4d8c2SCharles.Forsyth kfsread(File *f, void *va, long len)
210*74a4d8c2SCharles.Forsyth {
211*74a4d8c2SCharles.Forsyth 	uchar *a;
212*74a4d8c2SCharles.Forsyth 	long tot, off, o, n;
213*74a4d8c2SCharles.Forsyth 	Fs *fs;
214*74a4d8c2SCharles.Forsyth 
215*74a4d8c2SCharles.Forsyth 	a = va;
216*74a4d8c2SCharles.Forsyth 	fs = f->fs;
217*74a4d8c2SCharles.Forsyth 	off = f->kfs.off;
218*74a4d8c2SCharles.Forsyth 	tot = 0;
219*74a4d8c2SCharles.Forsyth 	while(tot < len){
220*74a4d8c2SCharles.Forsyth 		if(getdatablock(fs, &f->kfs, off/fs->kfs.BUFSIZE) < 0)
221*74a4d8c2SCharles.Forsyth 			return -1;
222*74a4d8c2SCharles.Forsyth 		o = off%fs->kfs.BUFSIZE;
223*74a4d8c2SCharles.Forsyth 		n = fs->kfs.BUFSIZE - o;
224*74a4d8c2SCharles.Forsyth 		if(n > len-tot)
225*74a4d8c2SCharles.Forsyth 			n = len-tot;
226*74a4d8c2SCharles.Forsyth 		memmove(a+tot, block+o, n);
227*74a4d8c2SCharles.Forsyth 		off += n;
228*74a4d8c2SCharles.Forsyth 		tot += n;
229*74a4d8c2SCharles.Forsyth 	}
230*74a4d8c2SCharles.Forsyth 	f->kfs.off = off;
231*74a4d8c2SCharles.Forsyth 	return tot;
232*74a4d8c2SCharles.Forsyth }
233*74a4d8c2SCharles.Forsyth 
234*74a4d8c2SCharles.Forsyth static int
kfswalk(File * f,char * name)235*74a4d8c2SCharles.Forsyth kfswalk(File *f, char *name)
236*74a4d8c2SCharles.Forsyth {
237*74a4d8c2SCharles.Forsyth 	int n;
238*74a4d8c2SCharles.Forsyth 
239*74a4d8c2SCharles.Forsyth 	n = walk(f->fs, &f->kfs, name, &f->kfs);
240*74a4d8c2SCharles.Forsyth 	if(n < 0)
241*74a4d8c2SCharles.Forsyth 		return -1;
242*74a4d8c2SCharles.Forsyth 	f->kfs.off = 0;
243*74a4d8c2SCharles.Forsyth 	return 1;
244*74a4d8c2SCharles.Forsyth }
245*74a4d8c2SCharles.Forsyth 
246*74a4d8c2SCharles.Forsyth int
kfsinit(Fs * fs)247*74a4d8c2SCharles.Forsyth kfsinit(Fs *fs)
248*74a4d8c2SCharles.Forsyth {
249*74a4d8c2SCharles.Forsyth 	if(readinfo(fs) < 0 || readroot(fs, &fs->root.kfs) < 0)
250*74a4d8c2SCharles.Forsyth 		return -1;
251*74a4d8c2SCharles.Forsyth 
252*74a4d8c2SCharles.Forsyth 	fs->root.fs = fs;
253*74a4d8c2SCharles.Forsyth 	fs->read = kfsread;
254*74a4d8c2SCharles.Forsyth 	fs->walk = kfswalk;
255*74a4d8c2SCharles.Forsyth 	return 0;
256*74a4d8c2SCharles.Forsyth }
257