|
|
1.1 root 1: /* diskio.c -- C routines for disk i/o in tertiary boot programs.
2: *
3: * La Monte H. Yarroll <[email protected]>, September 1991
4: */
5:
6: #include <sys/types.h>
7: #include <canon.h>
8: #include <sys/filsys.h>
9: #include <sys/ino.h>
10: #include <sys/inode.h>
11: #include <sys/dir.h>
12: #include <sys/buf.h>
13: #include <sys/stat.h>
14:
15: #include "tboot.h"
16:
17: /* Aligning bread.
18: * Reads 1 block into an arbitrary buffer. The assembly language
19: * routine bread() needs a buffer aligned on a 4K boundary.
20: */
21:
22: char bufspace[FOURK+BLOCK];
23: char *lbuf = NULL; /* Buffer for bread. */
24:
25: BUF *
26: bread(blockno)
27: daddr_t blockno; /* Block number. */
28: {
29: BUF *retval = NULL;
30:
31: /* If not already aligned, align buffer on a 4K boundary. */
32: if (NULL == lbuf) {
33: lbuf = bufspace + FOURK;
34: (short) lbuf &= FOURKBOUNDRY;
35: }
36:
37: sanity_check("bread() entry");
38: /*
39: * Get a buffer to cache this in.
40: */
41:
42: retval = bclaim(blockno);
43:
44: sanity_check("bread() returning from bclaim()");
45:
46: /*
47: * If the buffer has the right block number,
48: * we need not go further.
49: */
50: if ((THE_DEV == retval->b_dev) && (blockno == retval->b_bno)) {
51: return(retval);
52: }
53:
54: /* Read the block, ignoring
55: * the return value.
56: */
57: sanity_check("bread() to _bread()");
58: _bread(blockno, lbuf);
59: sanity_check("bread() from _bread()");
60:
61: /* Copy to the unaligned buffer. */
62: sanity_check("bread() to memcpy()");
63: memcpy((uint16) (retval->b_paddr), lbuf, BLOCK);
64: sanity_check("bread() from memcpy()");
65:
66: retval->b_dev = THE_DEV; /* Associate it with a device, */
67: retval->b_bno = blockno; /* and block number. */
68:
69: sanity_check("bread() about to return");
70: /* Return the buffer we just filled in. */
71: return(retval);
72: } /* bread() */
73:
74:
75: /*
76: * Inode OPEN: Load the inode for a file into memory.
77: * iopen(struct inode *ip,
78: * ino_t inode_number)
79: *
80: */
81:
82: int
83: iopen(meminode, inode_number)
84: struct inode *meminode;
85: ino_t inode_number;
86: {
87: BUF *bp;
88: char *my_block;
89:
90: daddr_t blockno; /* Physical block the inode lives on. */
91: uint16 offset; /* Offset within that block for inode. */
92: struct dinode *diskinode; /* Pointer into buffer for disk
93: * inode structure.
94: */
95:
96: /* Read the super block to check the inode_number.
97: * bp = bread(1L);
98: * WRITE ME
99: */
100:
101: /* Convert from inode number to block number. */
102:
103: /* This code fragment should (but doesn't) examine the
104: * bad block list, to skip over bad blocks in the free list.
105: *
106: * I'm no longer certain of the preceeding comment... :-(
107: */
108: blockno = ((inode_number - 1) / INODES_PER_BLOCK) + 2;
109:
110: offset = ((inode_number - 1) % INODES_PER_BLOCK) *
111: sizeof(struct dinode);
112:
113: /* Get the inode off disk. */
114: bp = bread(blockno);
115:
116: /* Point at the actual disk block. */
117: my_block = (char *) bp->b_paddr;
118:
119: /* Pick out the particular inode we want. */
120: diskinode = (struct dinode *) (my_block + offset);
121:
122: meminode->i_dev = THE_DEV; /* We're making something up. */
123: meminode->i_ino = inode_number; /* Inode index */
124: meminode->i_refc = diskinode->di_nlink;
125: meminode->i_gate[0] = 0; /* Gate (unused) */
126: meminode->i_gate[1] = 0; /* Gate (unused) */
127: meminode->i_flag = 0; /* Flags (unused) */
128: meminode->i_mode = diskinode->di_mode;
129: meminode->i_nlink = diskinode->di_nlink;
130: meminode->i_uid = diskinode->di_uid;
131: meminode->i_gid = diskinode->di_gid;
132: meminode->i_size = diskinode->di_size;
133: meminode->i_atime = diskinode->di_atime;
134: meminode->i_mtime = diskinode->di_mtime;
135: meminode->i_ctime = diskinode->di_ctime;
136: meminode->i_lrt = GREATEST( /* Last reference time */
137: meminode->i_atime,
138: meminode->i_mtime,
139: meminode->i_ctime);
140: /* Disk addresses */
141: /* Copy all block numbers (10 direct, 3 indirects). */
142: l3tol(meminode->i_a.i_addr, diskinode->di_a.di_addb, NADDR);
143:
144: /* Translate cannonical form to internal form. */
145: canshort(meminode->i_nlink); /* Reference count */
146: canshort(meminode->i_mode); /* Mode and type */
147: canshort(meminode->i_nlink); /* Number of links */
148: canshort(meminode->i_uid); /* Owner's user id */
149: canshort(meminode->i_gid); /* Owner's group id */
150: cansize(meminode->i_size); /* Size of file in bytes */
151: cantime(meminode->i_atime); /* Last access time */
152: cantime(meminode->i_mtime); /* Last modify time */
153: cantime(meminode->i_ctime); /* Creation time */
154:
155:
156: sanity_check("iopen() calling brelease()");
157: brelease(bp);
158:
159: return(1);
160: } /* iopen() */
161:
162:
163:
164: /* Convert a filename to an inode number. Returns inode number 0 on
165: * failure.
166: */
167: ino_t
168: namei(filename)
169: char *filename;
170: {
171: fsize_t i;
172: struct direct dirent;
173: struct inode dir;
174:
175: iopen(&dir, (ino_t) 2); /* Open the root directory. */
176:
177: /* Read each directory entry one at a time. */
178: for (i = 0; i < dir.i_size; i += sizeof(struct direct)) {
179:
180: iread(&dir, (char *) &dirent, (fsize_t) i,
181: (uint16) sizeof(struct direct));
182:
183: /* Canonicalize it. */
184: canino(dirent.d_ino);
185: if (0 == strncmp(filename, dirent.d_name, DIRSIZ)){
186: return(dirent.d_ino);
187: }
188: }
189: return((ino_t) 0);
190: } /* namei() */
191:
192: /*
193: * Inode READ: Load a local buffer from a file.
194: * iread(struct inode *ip,
195: * char *buffer,
196: * fsize_t offset,
197: * uint16 lenarg);
198: */
199: void
200: iread(ip, buffer, offset, lenarg)
201: struct inode *ip; /* Read from this file, */
202: char *buffer; /* into this buffer, */
203: fsize_t offset; /* from here in the file, */
204: uint16 lenarg; /* for this many bytes. */
205: {
206: extern uint16 myds; /* Contents of ds register. */
207:
208: ifread(ip, myds, buffer, offset, (fsize_t) lenarg);
209: } /* iread() */
210:
211: /*
212: * Inode to Far READ: Load an arbitrary length from a file into a far address.
213: * ifread(struct inode *ip,
214: * uint16 toseg,
215: * uint16 tooffset,
216: * fsize_t offset,
217: * fsize_t length);
218: */
219: void
220: ifread(ip, toseg, tooffset, offset, lenarg)
221: struct inode *ip; /* Read from this file, */
222: uint16 toseg; /* into this far buffer, */
223: uint16 tooffset;
224: fsize_t offset; /* from here in the file, */
225: fsize_t lenarg; /* for this many bytes. */
226: {
227: BUF *bp;
228: char *my_block;
229:
230: daddr_t fblockno; /* Block number relative to file. */
231: daddr_t pblockno; /* Block number relative to disk. */
232: uint16 blockoffset; /* How far into buffer to start or end. */
233: uint16 blocklen; /* Size of first fractional block. */
234: long length;
235:
236: extern uint16 myds; /* Contents of register ds. */
237:
238: length = (int32) lenarg; /* We need something that can go negative. */
239:
240: /* Calculate the first block of the requested file segment. */
241: fblockno = (daddr_t) (offset / (fsize_t) BLOCK);
242: /* Look up the physical block number. */
243: pblockno = vmap(ip, fblockno);
244: /* Calculate starting offset within that block. */
245: blockoffset = (uint16) (offset % (fsize_t) BLOCK);
246: blocklen =
247: (uint16) LESSER((int32) (BLOCK - blockoffset), length);
248:
249: /* Read the first fraction of a block. */
250: bp = bread(pblockno);
251:
252: /* Point at the actual data. */
253: my_block = (char *) bp->b_paddr;
254:
255: /* Copy it in place. */
256: ffcopy(tooffset, toseg, &(my_block[blockoffset]), myds, blocklen);
257:
258: sanity_check("ifread() calling the first brelease()");
259: brelease(bp);
260:
261: /* Don't bother with the rest if there is nothing more to read. */
262: if (blocklen == (uint16) length) {
263: return;
264: }
265:
266: ++fblockno;
267: pblockno = vmap(ip, fblockno);
268:
269: length -= (int32) blocklen;
270: seginc(&tooffset, &toseg, blocklen);
271:
272: /* Read the middle blocks. */
273: while (length - (int32) BLOCK > 0L) {
274: sanity_check("ifread() to middle bread()");
275: bp = bread(pblockno);
276: sanity_check("ifread() from middle bread()");
277:
278: /* Point at the actual data. */
279: my_block = (char *) bp->b_paddr;
280:
281: sanity_check("ifread() to middle ffcopy()");
282: ffcopy(tooffset, toseg, my_block, myds, BLOCK);
283: sanity_check("ifread() from middle ffcopy()");
284:
285: sanity_check("ifread() to middle brelease()");
286: brelease(bp);
287: sanity_check("ifread() from middle brelease()");
288:
289: /* pacifier */ puts(".");
290: ++fblockno;
291: sanity_check("ifread() to middle vmap()");
292: pblockno = vmap(ip, fblockno);
293: sanity_check("ifread() to middle vmap()");
294:
295: length -= (int32) BLOCK;
296: sanity_check("ifread() to middle seginc()");
297: seginc(&tooffset, &toseg, BLOCK);
298: sanity_check("ifread() from middle seginc()");
299: }
300:
301: /* Read the last fraction of a block. */
302: if (length > 0L) {
303: /* ASSERTION: length < BLOCK */
304: bp = bread(pblockno);
305:
306: /* Point at the actual data. */
307: my_block = (char *) bp->b_paddr;
308:
309: ffcopy(tooffset, toseg, my_block, myds, (uint16)length);
310: sanity_check("ifread() calling the last brelease()");
311: brelease(bp);
312: }
313: } /* ifread() */
314:
315:
316: /* Aligning xbread.
317: * Disk addresses are relative to the start of the disk, rather than
318: * the start of the partition.
319: * Reads 1 block into an arbitrary buffer. The assembly language
320: * routine xbread() needs a buffer aligned on a 4K boundary.
321: */
322: BUF *
323: xbread(blockno)
324: daddr_t blockno; /* Block number. */
325: {
326: BUF *retval = NULL;
327:
328: /* If not already aligned, align buffer on a 4K boundary. */
329: if (NULL == lbuf) {
330: lbuf = bufspace + FOURK;
331: (short) lbuf &= FOURKBOUNDRY;
332: }
333:
334: sanity_check("xbread() entry");
335: /*
336: * Get a buffer to cache this in.
337: */
338:
339: retval = bclaim(blockno);
340:
341: sanity_check("xbread() returning from bclaim()");
342:
343: /*
344: * If the buffer has the right block number,
345: * we need not go further.
346: */
347: if ((THE_XDEV == retval->b_dev) && (blockno == retval->b_bno)) {
348: return(retval);
349: }
350:
351: /* Read the block, ignoring
352: * the return value.
353: */
354: sanity_check("xbread() to _xbread()");
355: _xbread(blockno, lbuf);
356: sanity_check("xbread() from _xbread()");
357:
358: /* Copy to the unaligned buffer. */
359: sanity_check("xbread() to memcpy()");
360: memcpy((uint16) (retval->b_paddr), lbuf, BLOCK);
361: sanity_check("xbread() from memcpy()");
362:
363: retval->b_dev = THE_XDEV; /* Associate it with a device, */
364: retval->b_bno = blockno; /* and block number. */
365:
366: sanity_check("xbread() about to return");
367: /* Return the buffer we just filled in. */
368: return(retval);
369: } /* xbread() */
370:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.