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