|
|
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: lbuf = (char *) (((unsigned 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: pac_init(); /* Turn on the pacifier. */
273: /* Read the middle blocks. */
274: while (length - (int32) BLOCK > 0L) {
275: sanity_check("ifread() to middle bread()");
276: bp = bread(pblockno);
277: sanity_check("ifread() from middle bread()");
278:
279: /* Point at the actual data. */
280: my_block = (char *) bp->b_paddr;
281:
282: sanity_check("ifread() to middle ffcopy()");
283: ffcopy(tooffset, toseg, my_block, myds, BLOCK);
284: sanity_check("ifread() from middle ffcopy()");
285:
286: sanity_check("ifread() to middle brelease()");
287: brelease(bp);
288: sanity_check("ifread() from middle brelease()");
289:
290: pacifier(); /* Put something reassuring on the screen. */
291: ++fblockno;
292: sanity_check("ifread() to middle vmap()");
293: pblockno = vmap(ip, fblockno);
294: sanity_check("ifread() to middle vmap()");
295:
296: length -= (int32) BLOCK;
297: sanity_check("ifread() to middle seginc()");
298: seginc(&tooffset, &toseg, BLOCK);
299: sanity_check("ifread() from middle seginc()");
300: }
301: pac_cleanup(); /* Turn off the pacifier. */
302:
303: /* Read the last fraction of a block. */
304: if (length > 0L) {
305: /* ASSERTION: length < BLOCK */
306: bp = bread(pblockno);
307:
308: /* Point at the actual data. */
309: my_block = (char *) bp->b_paddr;
310:
311: ffcopy(tooffset, toseg, my_block, myds, (uint16)length);
312: sanity_check("ifread() calling the last brelease()");
313: brelease(bp);
314: }
315: } /* ifread() */
316:
317:
318: /* Aligning xbread.
319: * Disk addresses are relative to the start of the disk, rather than
320: * the start of the partition.
321: * Reads 1 block into an arbitrary buffer. The assembly language
322: * routine xbread() needs a buffer aligned on a 4K boundary.
323: */
324: BUF *
325: xbread(blockno)
326: daddr_t blockno; /* Block number. */
327: {
328: BUF *retval = NULL;
329:
330: /* If not already aligned, align buffer on a 4K boundary. */
331: if (NULL == lbuf) {
332: lbuf = bufspace + FOURK;
333: lbuf = (char *) (((unsigned short) lbuf) & FOURKBOUNDRY);
334: }
335:
336: sanity_check("xbread() entry");
337: /*
338: * Get a buffer to cache this in.
339: */
340:
341: retval = bclaim(blockno);
342:
343: sanity_check("xbread() returning from bclaim()");
344:
345: /*
346: * If the buffer has the right block number,
347: * we need not go further.
348: */
349: if ((THE_XDEV == retval->b_dev) && (blockno == retval->b_bno)) {
350: return(retval);
351: }
352:
353: /* Read the block, ignoring
354: * the return value.
355: */
356: sanity_check("xbread() to _xbread()");
357: _xbread(blockno, lbuf);
358: sanity_check("xbread() from _xbread()");
359:
360: /* Copy to the unaligned buffer. */
361: sanity_check("xbread() to memcpy()");
362: memcpy((uint16) (retval->b_paddr), lbuf, BLOCK);
363: sanity_check("xbread() from memcpy()");
364:
365: retval->b_dev = THE_XDEV; /* Associate it with a device, */
366: retval->b_bno = blockno; /* and block number. */
367:
368: sanity_check("xbread() about to return");
369: /* Return the buffer we just filled in. */
370: return(retval);
371: } /* xbread() */
372:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.