|
|
1.1 root 1: /*
2: * File: kpatch.c
3: *
4: * Purpose:
5: * This program is not expected to work other than on PC Coherent.
6: * Certain hot patches may not be effective, since some values are only
7: * referenced once at system initialization.
8: *
9: */
10:
11: /*
12: * ----------------------------------------------------------------------
13: * Includes.
14: */
15: #include <stdio.h>
16: #include <errno.h>
17: #include <sys/patch.h>
18: #include "patchl.h"
19:
20: /*
21: * ----------------------------------------------------------------------
22: * Definitions.
23: * Constants.
24: * Macros with argument lists.
25: * Typedefs.
26: * Enums.
27: */
28: #define PATCH_DEVICE_NAME "/dev/patch"
29:
30: /*
31: * ----------------------------------------------------------------------
32: * Functions.
33: * Import Functions.
34: * Export Functions.
35: * Local Functions.
36: */
37:
38: void main();
39: int arg_getc();
40:
41: static int kpatch();
42: static void usage();
43: static int peek_patch();
44:
45: /*
46: * ----------------------------------------------------------------------
47: * Global Data.
48: * Import Variables.
49: * Export Variables.
50: * Local Variables.
51: */
52: extern struct PatchInfo argInfo; /* yyparse puts info here. */
53:
54: static char * lex_input;
55: static int lex_index;
56:
57: static int verbose = 0; /* Are we printing feedback? */
58: static int kfd; /* File descriptor for patch device. */
59:
60: static char version[] = "kpatch version 1.0 for COHERENT v.4.2";
61:
62: static char short_helpmessage[] = "\
63: kpatch -- alter installation kernel\n\
64: Usage: kpatch [-v] \n\
65: { symbol? | symbol=value | symbol:maj:in | symbol:maj:out } ...\n\
66: ";
67:
68: static char helpmessage[] = "\
69: -v Verbose mode--print what's being done.\n\
70: symbol? Display present value of symbol.\n\
71: symbol=value Store value into symbol.\n\
72: symbol:maj:in If major number maj is not already in use,\n\
73: attach CON struct symbol to driver table at major\n\
74: number maj and call the load routine for the driver.\n\
75: symbol:maj:out If named CON symbol is installed at major number maj,\n\
76: call unload routine for the driver and remove the\n\
77: driver from the driver table.\n\
78: 'Value' is a numeric constant (decimal by default, hexadecimal if preceded\n\
79: by '0x', octal if preceded by '0' or '0o'.\n\
80: 'Value' may also be makedev(major-number, minor-number).\n\
81: ";
82:
83: /*
84: * ----------------------------------------------------------------------
85: * Code.
86: */
87:
88: /*************************************************************************
89: * main
90: ************************************************************************/
91: void
92: main(argc, argv)
93: int argc;
94: char *argv[];
95: {
96: int c; /* For reading options from getopt(). */
97: int i;
98: int patch_err;
99: char errmsg[80];
100:
101: extern int optind;
102: extern char *optarg;
103:
104: if ((kfd = open(PATCH_DEVICE_NAME, 0)) == -1) {
105: sprintf(errmsg, "%s: device %s", argv[0], PATCH_DEVICE_NAME);
106: perror(errmsg);
107: exit(1);
108: }
109:
110: while ((c = getopt(argc, argv, "v?")) != EOF) {
111: switch (c) {
112: case 'v':
113: verbose++;
114: break;
115: case '?':
116: fprintf(stderr, "%s\n", version);
117: usage(1); /* Does not return. */
118: default:
119: usage(0); /* Does not return. */
120: }
121: }
122:
123: /*
124: * There must be at least 2 arguments left.
125: */
126: if (argc - optind < 1) {
127: fprintf(stderr, "Missing arguments.\n");
128: usage(0); /* Does not return */
129: }
130:
131: /*
132: * Handle patch symbols one at a time.
133: * If an error occurs, display failure and save error status
134: * for exit value.
135: */
136: patch_err = 0;
137: for (i = optind; i < argc; i++) {
138: if (kpatch(argv[i])) {
139: sprintf(errmsg, "%s: %s", argv[0], argv[i]);
140: if (errno)
141: perror(errmsg);
142: patch_err = 1;
143: }
144: }
145: close(kfd);
146: exit(patch_err);
147: }
148:
149: /*************************************************************************
150: * kpatch
151: *
152: * Given a patch argument, attempt to do the patch.
153: * Return 0 if successful, -1 if failure.
154: ************************************************************************/
155: static int
156: kpatch(patch_arg)
157: char * patch_arg;
158: {
159: int result;
160:
161: /*
162: * Parse patch argument.
163: * If its type can be identified, pass the parsed info to
164: * the required action routine.
165: */
166: lex_input = patch_arg;
167: lex_index = 0;
168: argInfo.piType = bad_arg;
169: if(yyparse())
170: result = -1;
171: else { /* parse succeeded */
172: pDump();
173: switch(argInfo.piType) {
174: case peek_arg:
175: result = peek_patch(&argInfo);
176: break;
177: case assign_arg:
178: result = assign_patch(&argInfo);
179: break;
180: case con_in_arg:
181: result = con_in_patch(&argInfo);
182: break;
183: case con_out_arg:
184: result = con_out_patch(&argInfo);
185: break;
186: default:
187: result = -1;
188: }
189: }
190:
191: return result;
192: }
193:
194: /*************************************************************************
195: * usage
196: *
197: * Display usage message and terminate abnormally.
198: ************************************************************************/
199: /*
200: */
201: void
202: usage(verbose)
203: int verbose;
204: {
205: fprintf(stderr, short_helpmessage);
206: if (verbose) {
207: fprintf(stderr, helpmessage);
208: }
209: exit(1);
210: }
211:
212: /*************************************************************************
213: * arg_getc
214: *
215: * This replaces the default lex input function, taking input from global
216: * character pointer lex_input at position lex_index.
217: ************************************************************************/
218: int
219: arg_getc()
220: {
221: int result;
222:
223: /*
224: * Fetch the next available character.
225: * If at end of string
226: * Return EOF.
227: * Else
228: * Advance character pointer.
229: */
230: result = lex_input[lex_index];
231: if (result == 0)
232: result = -1;
233: else
234: lex_index++;
235: return result;
236: }
237:
238: /*************************************************************************
239: * assign_patch
240: *
241: * Try to modify a kernel variable.
242: * Return 0 if success, -1 if failure.
243: ************************************************************************/
244: static int
245: assign_patch(pip)
246: struct PatchInfo * pip;
247: {
248: struct patchVar pvar;
249: int result;
250:
251: strncpy(pvar.patch_vname, pip->piData.assignData.vname,
252: PATCH_VAR_NAME_LENGTH);
253: pvar.patch_data = & pip->piData.assignData.newValue;
254: result = ioctl(kfd, PATCH_WR, &pvar);
255:
256: if (result >= 0 && verbose)
257: printf("Value assigned: %s=0x%08x\n",
258: pvar.patch_vname, pip->piData.assignData.newValue);
259:
260: return result;
261: }
262:
263: /*************************************************************************
264: * con_in_patch
265: *
266: * Try to install a device driver.
267: * Return 0 if success, -1 if failure.
268: ************************************************************************/
269: static int
270: con_in_patch(pip)
271: struct PatchInfo * pip;
272: {
273: struct patchCon pcon;
274: int result;
275:
276: strncpy(pcon.patch_vname, pip->piData.conData.vname,
277: PATCH_VAR_NAME_LENGTH);
278: pcon.patch_maj = pip->piData.conData.maj;
279: result = ioctl(kfd, PATCH_CON_IN, &pcon);
280:
281: if (result >= 0 && verbose)
282: printf("Device %s attached at major number %d\n",
283: pcon.patch_vname, pcon.patch_maj);
284:
285: return result;
286: }
287:
288: /*************************************************************************
289: * con_out_patch
290: *
291: * Try to uninstall a device driver.
292: * Return 0 if success, -1 if failure.
293: ************************************************************************/
294: static int
295: con_out_patch(pip)
296: struct PatchInfo * pip;
297: {
298: struct patchCon pcon;
299: int result;
300:
301: strncpy(pcon.patch_vname, pip->piData.conData.vname,
302: PATCH_VAR_NAME_LENGTH);
303: pcon.patch_maj = pip->piData.conData.maj;
304: result = ioctl(kfd, PATCH_CON_OUT, &pcon);
305:
306: if (result >= 0 && verbose)
307: printf("Device %s detached from major number %d\n",
308: pcon.patch_vname, pcon.patch_maj);
309:
310: return result;
311: }
312:
313: /*************************************************************************
314: * peek_patch
315: *
316: * Try to examine a kernel variable.
317: * Return 0 if success, -1 if failure.
318: ************************************************************************/
319: static int
320: peek_patch(pip)
321: struct PatchInfo * pip;
322: {
323: int vdata = 0;
324: struct patchVar pvar;
325: int result;
326:
327: strncpy(pvar.patch_vname, pip->piData.peekData.vname,
328: PATCH_VAR_NAME_LENGTH);
329: pvar.patch_data = &vdata;
330: result = ioctl(kfd, PATCH_RD, &pvar);
331:
332: if (result >= 0)
333: printf("Value inspected: %s=0x%08x\n", pvar.patch_vname, vdata);
334:
335: return result;
336: }
337:
338: pDump()
339: {
340: #if 0
341: switch(argInfo.piType) {
342: case peek_arg:
343: printf("What is the value of %s?\n",
344: argInfo.piData.peekData.vname);
345: break;
346: case assign_arg:
347: printf("Set %s equal to %d\n",
348: argInfo.piData.assignData.vname,
349: argInfo.piData.assignData.newValue);
350: break;
351: case con_in_arg:
352: printf("Attach device %s to major number %d\n",
353: argInfo.piData.conData.vname,
354: argInfo.piData.conData.maj);
355: break;
356: case con_out_arg:
357: printf("Detach device %s from major number %d\n",
358: argInfo.piData.conData.vname,
359: argInfo.piData.conData.maj);
360: break;
361: default:
362: printf("Bad argument! %s\n", lex_input);
363: }
364: #endif
365: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.