|
|
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.