|
|
1.1 ! root 1: /* $Header: /y/coh.386/RCS/null.c,v 1.7 93/04/14 10:06:37 root Exp $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or persuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 2.3.37 ! 11: * Copyright (c) 1982, 1983, 1984. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * Null and memory driver. ! 17: * Minor device 0 is /dev/null ! 18: * Minor device 1 is /dev/mem, physical memory ! 19: * Minor device 2 is /dev/kmem, kernel data ! 20: * Minor device 3 is /dev/cmos ! 21: * Minor device 4 is /dev/boot_gift ! 22: * Minor device 5 is /dev/clock ! 23: * Minor device 6 is /dev/ps ! 24: * Minor device 7 is /dev/kmemhi, virtual memory 0x8000_0000-0xFFFF_FFFF ! 25: * ! 26: * $Log: null.c,v $ ! 27: * Revision 1.7 93/04/14 10:06:37 root ! 28: * r75 ! 29: * ! 30: * Revision 1.10 93/03/02 08:16:25 bin ! 31: * kernel 73 update ! 32: * ! 33: * Revision 1.6 92/11/09 17:10:54 root ! 34: * Just before adding vio segs. ! 35: * ! 36: * Revision 1.2 92/01/06 11:59:49 hal ! 37: * Compile with cc.mwc. ! 38: * ! 39: * Revision 1.1 88/03/24 16:14:04 src ! 40: * Initial revision ! 41: * ! 42: */ ! 43: ! 44: /* ! 45: * The symbol "DANGEROUS" should be undefined for a production system. ! 46: */ ! 47: #ifdef TRACER ! 48: #define NULL_IOCTL /* Allow ioctl()s for /dev/kmem. */ ! 49: #define DANGEROUS /* Allow dangerous ioctl()s for /dev/null. */ ! 50: #endif ! 51: ! 52: #include <sys/coherent.h> ! 53: #include <sys/con.h> ! 54: #include <errno.h> ! 55: #include <sys/stat.h> ! 56: #include <sys/typed.h> ! 57: #include <sys/inode.h> ! 58: #include <sys/seg.h> ! 59: #include <sys/coh_ps.h> ! 60: #ifdef NULL_IOCTL ! 61: #include <sys/null.h> ! 62: #endif /* NULL_IOCTL */ ! 63: ! 64: /* These are minor numbers. */ ! 65: #define DEV_NULL 0 /* /dev/null */ ! 66: #define DEV_MEM 1 /* /dev/mem */ ! 67: #define DEV_KMEM 2 /* /dev/kmem */ ! 68: #define DEV_CMOS 3 /* /dev/cmos */ ! 69: #define DEV_BOOTGIFT 4 /* /dev/bootgift */ ! 70: #define DEV_CLOCK 5 /* /dev/clock */ ! 71: #define DEV_PS 6 /* /dev/ps */ ! 72: #define DEV_KMEMHI 7 /* /dev/kmemhi */ ! 73: ! 74: #define KMEMHI_BASE 0x80000000 ! 75: #define PXCOPY_LIM 4096 ! 76: ! 77: /* ! 78: * CMOS devices are limited by an 8 bit address. ! 79: */ ! 80: #define MAX_CMOS 255 ! 81: #define CMOS_LEN 256 ! 82: ! 83: /* ! 84: * The first 14 bytes of the CMOS are the clock. ! 85: */ ! 86: #define MAX_CLOCK 13 ! 87: #define CLOCK_LEN 14 ! 88: ! 89: /* ! 90: * These are definitions for mucking with the CMOS clock. ! 91: */ ! 92: #define SRA 10 /* Status Register A */ ! 93: #define SRB 11 /* Status Register B */ ! 94: #define SRC 12 /* Status Register C */ ! 95: #define SRD 13 /* Status Register D */ ! 96: ! 97: #define UIP 0x80 /* Update In Progress bit of SRA. */ ! 98: #define NO_UPD 0x80 /* No Update bit of SRB. */ ! 99: ! 100: /* ! 101: * Functions for configuration. ! 102: */ ! 103: void nlopen(); ! 104: void nlclose(); ! 105: void nlread(); ! 106: void nlwrite(); ! 107: int nlioctl(); ! 108: int nulldev(); ! 109: int nonedev(); ! 110: ! 111: /* ! 112: * Configuration table. ! 113: */ ! 114: CON nlcon ={ ! 115: DFCHR, /* Flags */ ! 116: 0, /* Major index */ ! 117: nlopen, /* Open */ ! 118: nlclose, /* Close */ ! 119: nulldev, /* Block */ ! 120: nlread, /* Read */ ! 121: nlwrite, /* Write */ ! 122: #ifdef NULL_IOCTL ! 123: nlioctl, /* Ioctl */ ! 124: #else /* NULL_IOCTL */ ! 125: nonedev, /* Ioctl */ ! 126: #endif /* NULL_IOCTL */ ! 127: nulldev, /* Powerfail */ ! 128: nulldev, /* Timeout */ ! 129: nulldev, /* Load */ ! 130: nulldev /* Unload */ ! 131: }; ! 132: ! 133: int lock_clock(); ! 134: void unlock_clock(); ! 135: ! 136: /* ! 137: * Null/memory open routine. ! 138: */ ! 139: void ! 140: nlopen(dev, mode) ! 141: dev_t dev; ! 142: int mode; ! 143: { ! 144: switch (minor(dev)) { ! 145: case DEV_PS: ! 146: /* /dev/ps is read only */ ! 147: if (IPR != (IPR & mode)) ! 148: SET_U_ERROR( EACCES, "/dev/ps is read only" ); ! 149: break; ! 150: default: ! 151: /* ! 152: * For minor devices on NULL there is ! 153: * usually no action for open(). ! 154: */ ! 155: break; ! 156: } ! 157: return; ! 158: } /* nlopen() */ ! 159: ! 160: /* ! 161: * Null/memory close routine. ! 162: */ ! 163: void ! 164: nlclose(dev, mode) ! 165: dev_t dev; ! 166: int mode; ! 167: { ! 168: /* ! 169: * For minor devices on NULL there is ! 170: * Usually no action for close(). ! 171: */ ! 172: return; ! 173: } /* nlclose() */ ! 174: ! 175: /* ! 176: * Null/memory read routine. ! 177: */ ! 178: void ! 179: nlread(dev, iop) ! 180: dev_t dev; ! 181: register IO *iop; ! 182: { ! 183: register unsigned bytesRead; ! 184: register SEG *sp; /* u area segment */ ! 185: register PROC *pp1; /* */ ! 186: char psBuf[ARGSZ]; /* buffer for command line ! 187: * arguments for ps. */ ! 188: stMonitor psData; /* All process data for */ ! 189: UPROC *uprc; /* pointer to u area */ ! 190: int ndpUseg; /* System global address ! 191: * of U segment */ ! 192: unsigned int seek; ! 193: unsigned char read_cmos(); ! 194: extern typed_space boot_gift; ! 195: ! 196: switch (minor(dev)) { ! 197: case DEV_NULL: ! 198: /* ! 199: * Read nothing. ! 200: * Do NOT update iop->io_ioc. ! 201: * This way, caller knows 0 bytes were read. ! 202: */ ! 203: break; ! 204: ! 205: case DEV_MEM: ! 206: while (iop->io_ioc) { ! 207: int src = iop->io_seek; ! 208: int dest = iop->io.pbase; ! 209: int numBytes = PXCOPY_LIM; ! 210: if (numBytes > iop->io_ioc) ! 211: numBytes = iop->io_ioc; ! 212: ! 213: bytesRead = pxcopy(src, dest, numBytes, SEG_386_UD); ! 214: src += bytesRead; ! 215: dest += bytesRead; ! 216: iop->io_ioc -= bytesRead; ! 217: if (u.u_error == EFAULT) { ! 218: u.u_error = 0; ! 219: break; ! 220: } ! 221: } ! 222: break; ! 223: ! 224: case DEV_KMEM: ! 225: iowrite(iop, iop->io_seek, iop->io_ioc); ! 226: if (u.u_error == EFAULT) ! 227: u.u_error = 0; ! 228: break; ! 229: ! 230: case DEV_CLOCK: ! 231: /* ! 232: * Don't go past the end of the CLOCK. ! 233: */ ! 234: if (iop->io_seek >= CLOCK_LEN) ! 235: break; ! 236: ! 237: /* ! 238: * Lock the clock before any reading. ! 239: */ ! 240: if (lock_clock() == 0) { ! 241: SET_U_ERROR(EIO, "RT clock will not settle."); ! 242: break; ! 243: } ! 244: ! 245: /* ! 246: * Read the requested data out of the CMOS. ! 247: */ ! 248: for (seek = iop->io_seek; seek < CLOCK_LEN; seek++) { ! 249: if(ioputc(read_cmos(seek), iop) == -1) ! 250: break; ! 251: } ! 252: ! 253: /* ! 254: * Now that we are done reading the CMOS, let ! 255: * the clock loose. ! 256: */ ! 257: unlock_clock(); ! 258: break; ! 259: ! 260: case DEV_CMOS: ! 261: /* ! 262: * Don't go past the end of the CMOS. ! 263: */ ! 264: if (iop->io_seek >= CMOS_LEN) ! 265: break; ! 266: ! 267: /* ! 268: * Read the requested data out of the CMOS. ! 269: */ ! 270: for (seek = iop->io_seek; seek < CMOS_LEN; seek++) { ! 271: if(ioputc(read_cmos(seek), iop) == -1) ! 272: break; ! 273: } ! 274: break; ! 275: ! 276: case DEV_BOOTGIFT: ! 277: /* ! 278: * Reads all from the data structure boot_gift. ! 279: */ ! 280: if (iop->io_seek < BG_LEN) { ! 281: bytesRead = iop->io_ioc; ! 282: /* ! 283: * Copy no more than to the end of boot_gift. ! 284: */ ! 285: if (iop->io_seek + bytesRead > BG_LEN) { ! 286: bytesRead = BG_LEN - (iop->io_seek); ! 287: } ! 288: ! 289: iowrite(iop, ! 290: (char *)(&boot_gift) + iop->io_seek, ! 291: bytesRead); ! 292: } ! 293: break; ! 294: ! 295: case DEV_PS: ! 296: /* Lock the process table. It allows to have an atomic ps. */ ! 297: lock(pnxgate); ! 298: /* Main driver loop. Go through all processes. Fill struct PS ! 299: * and send put to user buffer. ! 300: */ ! 301: for (pp1 = &procq; (pp1=pp1->p_nforw) != &procq; ) { ! 302: register int i; /* loop index */ ! 303: register unsigned uLen, /* Process size */ ! 304: uLenR; /* Real process size */ ! 305: int work; /* virtual click number */ ! 306: ! 307: /* Check if driver can send next proc data */ ! 308: if ( iop->io_ioc < sizeof(stMonitor)) ! 309: break; ! 310: ! 311: /* Calculate the size of process. */ ! 312: uLen = uLenR = 0; ! 313: for (i = 0; i < NUSEG + 1; i++) { ! 314: if ((sp=pp1->p_segp[i]) == NULL) ! 315: continue; ! 316: uLenR += sp->s_size; ! 317: if (i == SIUSERP || i == SIAUXIL) ! 318: continue; ! 319: uLen += sp->s_size; ! 320: ! 321: } ! 322: ! 323: /* Find u area for process pp1 */ ! 324: sp = pp1->p_segp[SIUSERP]; ! 325: ndpUseg = MAPIO(sp->s_vmem, U_OFFSET); ! 326: work = workAlloc(); ! 327: ptable1_v[work] = ! 328: sysmem.u.pbase[btocrd(ndpUseg)] | SEG_RW; ! 329: mmuupd(); ! 330: uprc = (UPROC *) (ctob(work) + U_OFFSET); ! 331: kkcopy(uprc->u_comm, psData.u_comm, ARGSZ); ! 332: kkcopy(uprc->u_sleep, psData.u_sleep, U_SLEEP_LEN); ! 333: workFree(work); ! 334: ! 335: /* fill up stMonitor */ ! 336: psData.p_pid = pp1->p_pid; ! 337: psData.p_ppid = pp1->p_ppid; ! 338: psData.p_uid = pp1->p_uid; ! 339: psData.p_ruid = pp1->p_ruid; ! 340: psData.p_rgid = pp1->p_rgid; ! 341: psData.p_state = pp1->p_state; ! 342: psData.p_flags = pp1->p_flags; ! 343: psData.rrun = (char *) pp1 != pp1->p_event; ! 344: psData.p_event = pp1->p_event; ! 345: psData.p_ttdev = pp1->p_ttdev; ! 346: psData.p_nice = pp1->p_nice; ! 347: psData.size = (short) (uLen>>10); ! 348: psData.rsize = (short) (uLenR>>10); ! 349: psData.p_schedPri = pp1->p_schedPri; ! 350: psData.p_utime = pp1->p_utime; ! 351: psData.p_stime = pp1->p_stime; ! 352: kkcopy(psBuf, psData.pr_argv, ARGSZ); ! 353: /* send data to user */ ! 354: iowrite(iop, (char *) &psData, sizeof(stMonitor)); ! 355: } ! 356: unlock(pnxgate); ! 357: break; ! 358: case DEV_KMEMHI: ! 359: iowrite(iop, iop->io_seek - KMEMHI_BASE, iop->io_ioc); ! 360: if (u.u_error == EFAULT) ! 361: u.u_error = 0; ! 362: break; ! 363: default: ! 364: SET_U_ERROR(ENXIO, "nlread(): illegal minor device for null"); ! 365: } ! 366: return; ! 367: } ! 368: ! 369: /* ! 370: * Null/memory write routine. ! 371: */ ! 372: void ! 373: nlwrite(dev, iop) ! 374: dev_t dev; ! 375: register IO *iop; ! 376: { ! 377: register unsigned bytesWrit; ! 378: unsigned write_cmos(); ! 379: unsigned seek; ! 380: int ch; ! 381: ! 382: switch (minor(dev)) { ! 383: case DEV_NULL: ! 384: /* ! 385: * Tell caller all bytes were written. ! 386: */ ! 387: iop->io_ioc = 0; ! 388: break; ! 389: ! 390: case DEV_MEM: ! 391: while(iop->io_ioc) { ! 392: int src = iop->io.pbase; ! 393: int dest = iop->io_seek; ! 394: int numBytes = PXCOPY_LIM; ! 395: if (numBytes > iop->io_ioc) ! 396: numBytes = iop->io_ioc; ! 397: ! 398: bytesWrit = xpcopy(src, dest, numBytes, SEG_386_UD); ! 399: src += bytesWrit; ! 400: dest += bytesWrit; ! 401: iop->io_ioc -= bytesWrit; ! 402: if (u.u_error == EFAULT) { ! 403: u.u_error = 0; ! 404: break; ! 405: } ! 406: } ! 407: break; ! 408: ! 409: case DEV_KMEM: ! 410: ioread(iop, iop->io_seek, iop->io_ioc); ! 411: break; ! 412: ! 413: case DEV_CLOCK: ! 414: /* ! 415: * Don't go past the end of the CLOCK. ! 416: */ ! 417: if (iop->io_seek >= CLOCK_LEN) ! 418: break; ! 419: ! 420: /* ! 421: * Lock the clock before any writing. ! 422: */ ! 423: if (lock_clock() == 0) { ! 424: SET_U_ERROR(EIO, "RT clock will not settle."); ! 425: break; ! 426: } ! 427: ! 428: /* ! 429: * Write the requested data into the CMOS. ! 430: */ ! 431: for (seek = iop->io_seek; seek < CLOCK_LEN; seek++) { ! 432: if((ch = iogetc(iop)) == -1) ! 433: break; ! 434: write_cmos(seek, ch); ! 435: } ! 436: ! 437: /* ! 438: * Now that we are done writing the CMOS, let ! 439: * the clock loose. ! 440: */ ! 441: unlock_clock(); ! 442: break; ! 443: ! 444: case DEV_CMOS: ! 445: /* ! 446: * Don't go past the end of the CMOS. ! 447: */ ! 448: if (iop->io_seek >= CMOS_LEN) ! 449: break; ! 450: ! 451: /* ! 452: * Write the requested data into the CMOS. ! 453: */ ! 454: for (seek = iop->io_seek; seek < CMOS_LEN; seek++) { ! 455: if((ch = iogetc(iop)) == -1) ! 456: break; ! 457: write_cmos(seek, ch); ! 458: } ! 459: break; ! 460: ! 461: case DEV_BOOTGIFT: ! 462: /* ! 463: * /dev/bootgift is not writable. ! 464: */ ! 465: break; ! 466: ! 467: case DEV_PS: ! 468: /* We should not be able to open /dev/ps to write. ! 469: * Just paranoya. ! 470: */ ! 471: break; ! 472: ! 473: case DEV_KMEMHI: ! 474: ioread(iop, iop->io_seek - KMEMHI_BASE, iop->io_ioc); ! 475: break; ! 476: ! 477: default: ! 478: SET_U_ERROR(ENXIO, ! 479: "nlwrite(): illegal minor device for null"); ! 480: } ! 481: return; ! 482: } ! 483: ! 484: #ifdef NULL_IOCTL /* Includes all of nlioctl(). */ ! 485: ! 486: /* ! 487: * Do an ioctl call for /dev/null. ! 488: */ ! 489: int ! 490: nlioctl(dev, cmd, vec) ! 491: dev_t dev; ! 492: int cmd; ! 493: char * vec; ! 494: { ! 495: /* Only /dev/kmem has an ioctl. */ ! 496: switch (minor(dev)) { ! 497: case DEV_KMEM: ! 498: switch (cmd) { ! 499: #ifdef DANGEROUS ! 500: case NLCALL: /* Call a function. */ ! 501: return docall(vec); ! 502: #endif /* DANGEROUS */ ! 503: default: ! 504: SET_U_ERROR(EINVAL, ! 505: "nioctl(): illegal command for kmem"); ! 506: return(-1); ! 507: } ! 508: default: ! 509: SET_U_ERROR(EINVAL, "illegal minor device for null ioctl"); ! 510: return (-1); ! 511: } /* switch on minor device */ ! 512: ! 513: } /* nlioctl() */ ! 514: ! 515: #endif /* NULL_IOCTL */ ! 516: ! 517: #ifdef DANGEROUS /* Includes all of docall(). */ ! 518: /* ! 519: * MASSIVE SECURITY HOLE! This should NOT be included in a distribution ! 520: * system. Among other problems, it becomes possible to do "setuid(0)". ! 521: * ! 522: * Call a function with arguments. ! 523: * ! 524: * Takes an array of unsigned ints. The first element is the length of ! 525: * the whole array, the second element is a pointer to the function to ! 526: * call, all other elements are arguments. At most 5 arguments may be ! 527: * passed. ! 528: * ! 529: * Returns the return value of the called fuction in uvec[0]. ! 530: */ ! 531: int ! 532: docall(uvec) ! 533: unsigned uvec[]; ! 534: { ! 535: int (* func)(); ! 536: unsigned kvec[7]; ! 537: int retval; ! 538: ! 539: printf("NLCALL security hole.\n"); ! 540: ! 541: /* Fetch the first element of vec. */ ! 542: ukcopy(uvec, kvec, sizeof(unsigned)); ! 543: ! 544: if ((kvec[0] < 2) || (kvec[0] > 7)) { ! 545: /* Invalid number of elements in uvec. */ ! 546: SET_U_ERROR(EINVAL, "Invalid number of elements in uvec"); ! 547: return(-1); ! 548: } ! 549: ! 550: /* Fetch the whole vector. */ ! 551: ukcopy(uvec, kvec, kvec[0] * sizeof(unsigned)); ! 552: ! 553: /* Extract the function. */ ! 554: func = (int (*)()) kvec[1]; ! 555: ! 556: /* Call the function with all arguments. */ ! 557: retval = (*func)(kvec[2], kvec[3], kvec[4], kvec[5], kvec[6]); ! 558: ! 559: kucopy(&retval, uvec, sizeof(unsigned)); ! 560: ! 561: } /* docall() */ ! 562: ! 563: #endif /* DANGEROUS */ ! 564: ! 565: /* ! 566: * int lock_clock() -- Stop the update cycle on the CMOS RT clock and ! 567: * wait for it to settle. Returns 0 if the clock would not settle ! 568: * in time. ! 569: */ ! 570: int ! 571: lock_clock() ! 572: { ! 573: register int i; ! 574: ! 575: /* ! 576: * Wait for the clock to settle. If it does not settle in ! 577: * a reasonable amount of time, give up. ! 578: */ ! 579: i = 65536; /* Loop for a longish time. */ ! 580: while (--i > 0) { ! 581: if (0 == (UIP & read_cmos(SRA))) { ! 582: break; /* Break if there is no update in progress. */ ! 583: } ! 584: } ! 585: ! 586: if (0 == i) { ! 587: /* The clock would not settle. */ ! 588: return 0; ! 589: } ! 590: ! 591: /* ! 592: * There is a tiny race here--an interrupt could conceivably ! 593: * come here, thus allowing enough delay for another update to ! 594: * begin. But if we take interrupts that take a full second ! 595: * to process, other things are going to break horribly. ! 596: */ ! 597: ! 598: /* ! 599: * Lock out updates. ! 600: * We set the No Updates bit in Clock Status Register B. ! 601: */ ! 602: write_cmos(SRB, (NO_UPD | read_cmos(SRB))); ! 603: ! 604: return 1; ! 605: } /* lock_clock() */ ! 606: ! 607: /* ! 608: * void unlock_clock() -- Restart the update cycle on the CMOS RT clock. ! 609: */ ! 610: void ! 611: unlock_clock() ! 612: { ! 613: /* ! 614: * We clear the No Updates bit in Clock Status Register B. ! 615: */ ! 616: write_cmos(SRB, ((~ NO_UPD) & read_cmos(SRB))); ! 617: } /* unlock_clock() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.