|
|
1.1 ! root 1: /* ! 2: * conf/patch.c ! 3: * ! 4: * patch device ! 5: * Used for inspecting and altering the value of kernel ! 6: * variables, and enabling device drivers, after the kernel ! 7: * has started running. ! 8: * ! 9: * NOTICE: This driver is a massive kluge (just ask Nigel). It is ! 10: * intended for use ONLY with the bootstrap kernel shipped on ! 11: * the first diskette of the installation set. Otherwise, ! 12: * kernel variables can be patched using mtune/stune, and ! 13: * drivers enabled using mdevice/sdevice. ! 14: * ! 15: * Revised: Thu Jul 22 16:25:23 1993 CDT ! 16: */ ! 17: ! 18: /* ! 19: * ----------------------------------------------------------------- ! 20: * Includes. ! 21: */ ! 22: #define __KERNEL__ 1 ! 23: ! 24: #include <string.h> ! 25: #include <sys/coherent.h> ! 26: #include <sys/con.h> ! 27: #include <sys/errno.h> ! 28: #include <sys/patch.h> ! 29: #include <kernel/v_types.h> ! 30: ! 31: /* ! 32: * ----------------------------------------------------------------- ! 33: * Definitions. ! 34: * Constants. ! 35: * Macros with argument lists. ! 36: * Typedefs. ! 37: * Enums. ! 38: */ ! 39: ! 40: /* ! 41: * ----------------------------------------------------------------- ! 42: * Functions. ! 43: * Import Functions. ! 44: * Export Functions. ! 45: * Local Functions. ! 46: */ ! 47: int nulldev(); ! 48: ! 49: /* ! 50: * Configuration functions (local functions). ! 51: */ ! 52: struct patch; ! 53: static int patchioctl __PROTO((dev_t dev, int com, struct patch * vec)); ! 54: ! 55: /* ! 56: * Support functions (local functions). ! 57: */ ! 58: static int copyinEfault __PROTO((_VOID * userBuf, _VOID * driverBuf, ! 59: size_t byteCount)); ! 60: static int copyoutEfault __PROTO((_VOID * driverBuf, _VOID * userBuf, ! 61: size_t byteCount)); ! 62: ! 63: static struct patchVarInternal * patchVarLookup(); ! 64: static struct patchConInternal * patchConLookup(); ! 65: ! 66: static int matchMajor(); ! 67: static int validMajor(); ! 68: ! 69: /* ! 70: * ----------------------------------------------------------------- ! 71: * Global Data. ! 72: * Import Variables. ! 73: * Export Variables. ! 74: * Local Variables. ! 75: */ ! 76: ! 77: /* ! 78: * Configuration table (export data). ! 79: */ ! 80: CON patchcon ={ ! 81: DFCHR, /* Flags */ ! 82: 0, /* Major index */ ! 83: nulldev, /* Open */ ! 84: nulldev, /* Close */ ! 85: nulldev, /* Block */ ! 86: nulldev, /* Read */ ! 87: nulldev, /* Write */ ! 88: patchioctl, /* Ioctl */ ! 89: nulldev, /* Powerfail */ ! 90: nulldev, /* Timeout */ ! 91: nulldev, /* Load */ ! 92: nulldev, /* Unload */ ! 93: nulldev /* Poll */ ! 94: }; ! 95: ! 96: /* ! 97: * ----------------------------------------------------------------- ! 98: * Code. ! 99: */ ! 100: ! 101: /******************************************************************* ! 102: * matchMajor() ! 103: * ! 104: * See if drvl entry at the given major number matches the given ! 105: * address. ! 106: * Return 0 if there is a match. ! 107: * Return -1 and set EINVAL if no match. ! 108: ******************************************************************/ ! 109: static int ! 110: matchMajor(major, addr) ! 111: int major; ! 112: CON * addr; ! 113: { ! 114: if (drvl[major].d_conp == addr) ! 115: return 0; ! 116: else { ! 117: u.u_error = EINVAL; ! 118: return -1; ! 119: } ! 120: } ! 121: ! 122: /******************************************************************* ! 123: * validMajor() ! 124: * ! 125: * See if the given major number is within the allowable range. ! 126: * Return 0 if valid. ! 127: * Return -1 and set EINVAL if not valid. ! 128: ******************************************************************/ ! 129: static int ! 130: validMajor(major) ! 131: unsigned int major; ! 132: { ! 133: if (major < NDRV) ! 134: return 0; ! 135: else { ! 136: u.u_error = EINVAL; ! 137: return -1; ! 138: } ! 139: } ! 140: ! 141: /******************************************************************* ! 142: * patchVarLookup() ! 143: * ! 144: * Given a variable name, look for a matching record in the table ! 145: * of kernel patchable variables. ! 146: * ! 147: * Return a pointer to the matching record if there is a match. ! 148: * Return 0 and set EINVAL if no match. ! 149: ******************************************************************/ ! 150: static struct patchVarInternal * ! 151: patchVarLookup(vname) ! 152: char * vname; ! 153: { ! 154: int i; ! 155: struct patchVarInternal * match = NULL; ! 156: ! 157: for (i = 0; i < patchVarCount && ! match; i++) ! 158: if (strncmp(vname, patchVarTable[i].patch_vname, ! 159: PATCH_VAR_NAME_LENGTH) == 0) ! 160: match = patchVarTable + i; ! 161: ! 162: if (!match) ! 163: u.u_error = EINVAL; ! 164: return match; ! 165: } ! 166: ! 167: /******************************************************************* ! 168: * patchConLookup() ! 169: * ! 170: * Given a CON structure name, look for a matching record in the ! 171: * table of deferred-load devices. ! 172: * ! 173: * Return a pointer to the matching record if there is a match. ! 174: * Return 0 and set EINVAL if no match. ! 175: ******************************************************************/ ! 176: static struct patchConInternal * ! 177: patchConLookup(vname) ! 178: char * vname; ! 179: { ! 180: int i; ! 181: struct patchConInternal * match = NULL; ! 182: ! 183: for (i = 0; i < patchConCount && ! match; i++) ! 184: if (strncmp(vname, patchConTable[i].patch_vname, ! 185: PATCH_VAR_NAME_LENGTH) == 0) ! 186: match = patchConTable + i; ! 187: ! 188: if (!match) ! 189: u.u_error = EINVAL; ! 190: return match; ! 191: } ! 192: ! 193: /******************************************************************* ! 194: * copyinEfault() ! 195: * ! 196: * Do a copy from user data to kernel data. ! 197: * Set EFAULT if there is a problem. ! 198: * Return 0 on success, -1 on failure. ! 199: ******************************************************************/ ! 200: #if __USE_PROTO___ ! 201: static int copyinEfault (_VOID * userBuf, _VOID * driverBuf, ! 202: size_t byteCount) ! 203: #else ! 204: static int ! 205: copyinEfault(userBuf, driverBuf, byteCount) ! 206: _VOID * userBuf; ! 207: _VOID * driverBuf; ! 208: size_t byteCount; ! 209: #endif ! 210: { ! 211: size_t result; ! 212: ! 213: result = copyin(userBuf, driverBuf, byteCount); ! 214: if (result) ! 215: u.u_error = EFAULT; ! 216: return result; ! 217: } ! 218: ! 219: /******************************************************************* ! 220: * copyoutEfault() ! 221: * ! 222: * Do a copy from user data to kernel data. ! 223: * Set EFAULT if there is a problem. ! 224: * Return 0 on success, -1 on failure. ! 225: ******************************************************************/ ! 226: #if __USE_PROTO__ ! 227: static int copyoutEfault (_VOID * driverBuf, _VOID * userBuf, ! 228: size_t byteCount) ! 229: #else ! 230: static int ! 231: copyoutEfault(driverBuf, userBuf, byteCount) ! 232: _VOID * driverBuf; ! 233: _VOID * userBuf; ! 234: size_t byteCount; ! 235: #endif ! 236: { ! 237: size_t result; ! 238: ! 239: result = copyout(driverBuf, userBuf, byteCount); ! 240: if (result) ! 241: u.u_error = EFAULT; ! 242: return result; ! 243: } ! 244: ! 245: /******************************************************************* ! 246: * patchioctl() ! 247: * ! 248: * Although the type returned is int according to con.h, the ! 249: * return value is discarded by bio.c !!! ! 250: ******************************************************************/ ! 251: #if __USE_PROTO__ ! 252: static int patchioctl(dev_t __NOTUSED(dev), int com, struct patch * vec) ! 253: #else ! 254: static int ! 255: patchioctl(dev, com, vec) ! 256: dev_t dev; ! 257: int com; ! 258: struct patch *vec; ! 259: #endif ! 260: { ! 261: int result; /* ignored */ ! 262: ! 263: struct patchVar pvar; ! 264: struct patchCon pcon; ! 265: ! 266: struct patchVarInternal * pvarintp; ! 267: struct patchConInternal * pconintp; ! 268: ! 269: switch (com) { ! 270: case PATCH_WR: ! 271: /* ! 272: * Write a new value to a patchable variable. ! 273: * Fetch patch record from user data. ! 274: * Look for variable in patch table. ! 275: * Copy value from user data to kernel data. ! 276: */ ! 277: if (copyinEfault(vec, &pvar, sizeof(pvar)) || ! 278: !(pvarintp = patchVarLookup(pvar.patch_vname)) || ! 279: copyinEfault(pvar.patch_data, pvarintp->patch_addr, ! 280: pvarintp->patch_size)) ! 281: result = -1; ! 282: else ! 283: result = pvarintp->patch_size; ! 284: break; ! 285: case PATCH_RD: ! 286: /* ! 287: * Read value of a patchable variable. ! 288: * Fetch patch record from user data. ! 289: * Look for variable in patch table. ! 290: * Copy value from kernel data to user data. ! 291: */ ! 292: if (copyinEfault(vec, &pvar, sizeof(pvar)) || ! 293: !(pvarintp = patchVarLookup(pvar.patch_vname)) || ! 294: copyoutEfault(pvarintp->patch_addr, pvar.patch_data, ! 295: pvarintp->patch_size)) ! 296: result = -1; ! 297: else ! 298: result = pvarintp->patch_size; ! 299: break; ! 300: case PATCH_CON_IN: ! 301: /* ! 302: * Delayed activation of a device driver. ! 303: * Fetch patch record from user data. ! 304: * Look for variable in patch table. ! 305: * Make sure major number is valid. ! 306: * Make sure user-specified major number is free. ! 307: * Enter the device into the drvl table. ! 308: * Call the device load routine. ! 309: */ ! 310: if (copyinEfault(vec, &pcon, sizeof(pcon)) || ! 311: !(pconintp = patchConLookup(pcon.patch_vname)) || ! 312: validMajor(pcon.patch_maj) || ! 313: matchMajor(pcon.patch_maj, NULL)) ! 314: result = -1; ! 315: else { ! 316: drvl[pcon.patch_maj].d_conp = ! 317: (CON *)(pconintp->patch_addr); ! 318: (*drvl[pcon.patch_maj].d_conp->c_load)(); ! 319: result = 0; ! 320: } ! 321: break; ! 322: case PATCH_CON_OUT: ! 323: /* ! 324: * Deactivation of a device driver. ! 325: * Fetch patch record from user data. ! 326: * Look for variable in patch table. ! 327: * Make sure major number is valid. ! 328: * Make sure specified device is at specified major number. ! 329: * Call the device unload routine. ! 330: * Delete the device from the drvl table. ! 331: */ ! 332: if (copyinEfault(vec, &pcon, sizeof(pcon)) || ! 333: !(pconintp = patchConLookup(pcon.patch_vname)) || ! 334: validMajor(pcon.patch_maj) || ! 335: matchMajor(pcon.patch_maj, pconintp->patch_addr)) ! 336: result = -1; ! 337: else { ! 338: (*drvl[pcon.patch_maj].d_conp->c_uload)(); ! 339: drvl[pcon.patch_maj].d_conp = NULL; ! 340: result = 0; ! 341: } ! 342: break; ! 343: default: ! 344: u.u_error = EINVAL; ! 345: result = -1; ! 346: } ! 347: ! 348: return result; /* ignored */ ! 349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.