|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1993 NeXT Computer, Inc. All rights reserved.
27: *
28: * miniMon.c -- Machine-independent mini-monitor.
29: *
30: * HISTORY
31: * 04-Oct-1993 Curtis Galloway at NeXT
32: * Created.
33: *
34: */
35:
36: #import <kern/miniMon.h>
37: #import <kern/miniMonPrivate.h>
38: #import <sys/param.h>
39: #import <sys/systm.h>
40: #import <sys/reboot.h>
41: #include <stdarg.h>
42: #import <mach/machine/simple_lock.h>
43:
44: extern int boothowto;
45:
46: static boolean_t miniMonContinue(char *);
47: static boolean_t miniMonHelp(char *);
48: static boolean_t miniMonResetKdp(char *);
49: static boolean_t miniMonTryGdb(char *);
50: static boolean_t miniMonForceGdb(char *);
51: void *miniMonState;
52:
53: miniMonCommand_t miniMonCommands[] = {
54: {"continue", miniMonContinue, "Continue execution"},
55: {"reboot", miniMonReboot, "Reboot the computer, no sync"},
56: {"halt", miniMonHalt, "Sync and halt the computer"},
57: {"gdb", miniMonTryGdb, "Break to remote debugger"},
58: {"forcegdb", miniMonForceGdb, "Break to remote debugger"},
59: {"reset", miniMonResetKdp, "Reset debugger state"},
60: {"help", miniMonHelp, 0},
61: {"?", miniMonHelp, 0},
62: {0,0}
63: };
64:
65:
66: static match_t
67: commandcmp(char *command, char *line)
68: {
69: while (*command) {
70: if (*line == ' ' || *line == '\t' ||
71: *line == '\n' || *line == '\0')
72: return FOUND;
73: if (*command++ != *line++)
74: return NOT_FOUND;
75: }
76: return FOUND;
77: }
78:
79:
80:
81: static boolean_t
82: miniMonParseLine(char *line)
83: {
84: struct miniMonCommand *command, *found_command = NULL;
85:
86: for (command = miniMonCommands; command->name; command++) {
87: if (commandcmp(command->name, line) == FOUND) {
88: if (found_command != NULL) {
89: safe_prf("Ambiguous command - type '?' for help\n");
90: return TRUE;
91: } else {
92: found_command = command;
93: }
94: }
95: }
96: for (command = miniMonMDCommands; command->name; command++) {
97: if (commandcmp(command->name, line) == FOUND) {
98: if (found_command != NULL) {
99: safe_prf("Ambiguous command - type '?' for help\n");
100: return TRUE;
101: } else {
102: found_command = command;
103: }
104: }
105: }
106: if (found_command != NULL) {
107: return (*found_command->function)(line);
108: } else {
109: safe_prf("Invalid command - type '?' for help\n");
110: return TRUE;
111: }
112: }
113:
114: static void
115: miniMonGetLine(char *line, int len)
116: {
117: register int c;
118: char *anchor = line;
119:
120: len--; /* for '\0' */
121: for (;;) {
122: c = miniMonGetchar();
123: switch (c) {
124: case '\r':
125: miniMonPutchar('\n');
126: /* fall into ... */
127: case '\n':
128: *line++ = '\0';
129: return;
130: case '\b': /* bs */
131: miniMonPutchar(' ');
132: if (line != anchor) {
133: miniMonPutchar('\b');
134: line--;
135: len++;
136: }
137: continue;
138: case '\025': /* ^u */
139: line = anchor;
140: miniMonPutchar('\n');
141: continue;
142: default:
143: if (len) {
144: *line++ = c;
145: len--;
146: } else {
147: miniMonPutchar('\b');
148: miniMonPutchar(' ');
149: miniMonPutchar('\b');
150: }
151: }
152: }
153: }
154:
155: simple_lock_t _kernDebuggerLock;
156:
157: void
158: miniMonInit(void)
159: {
160: /*
161: * Initialize kernel debugger lock.
162: */
163: _kernDebuggerLock = simple_lock_alloc();
164: simple_lock_init(_kernDebuggerLock);
165: }
166:
167:
168: static char miniMonLine[128];
169:
170: void
171: miniMonLoop(char *prompt, int panic, void *state)
172: {
173: int c;
174:
175: miniMonState = state;
176: if (panic) {
177: safe_prf("System Panic:\n");
178: safe_prf("%s\n",panicstr);
179: #if defined(ppc)
180: {
181: unsigned int *fp;
182: unsigned int register sp;
183: unsigned int depth=15;
184: __asm__ volatile("mr %0,r1" : "=r" (sp));
185:
186: safe_prf("stack backtrace - ");
187: fp = *((unsigned int *)sp);
188: while (fp && (--depth)) {
189: safe_prf("0x%08x ", fp[2]);
190: fp = (unsigned int *)*fp;
191: }
192: safe_prf("\n");
193: }
194: #endif /* ppc */
195:
196: if ((boothowto & RB_DEBUG) == 0) {
197: /* Reboot automatically */
198: safe_prf("(Type 'm' for monitor,\n");
199: safe_prf("or wait for automatic reboot)");
200: /* Wait for 30 seconds */
201: for (c=30000; c>0; c--) {
202: if (miniMonTryGetchar() == 'm') {
203: safe_prf("\n");
204: break;
205: }
206: us_spin(1000);
207: }
208: if (c == 0) {
209: safe_prf("\nRebooting...");
210: miniMonReboot("");
211: }
212: } else {
213: safe_prf("(Type 'r' to reboot or 'm' for monitor)");
214: for (;;) {
215: c = miniMonTryGetchar();
216: if (c == 'r') {
217: safe_prf("\nRebooting...");
218: miniMonReboot("");
219: } else if (c == 'm') {
220: safe_prf("\n");
221: break;
222: }
223: }
224: }
225: }
226: safe_prf("Mini-monitor\n");
227: for(;;) {
228: safe_prf("%s> ",prompt);
229: miniMonGetLine(miniMonLine, sizeof(miniMonLine));
230: if (miniMonParseLine(miniMonLine) == FALSE)
231: break;
232: }
233: }
234:
235: static boolean_t
236: miniMonContinue(char *line)
237: {
238: return FALSE;
239: }
240:
241: static boolean_t
242: miniMonHelp(char *line)
243: {
244: struct miniMonCommand *command;
245: safe_prf("Mini-monitor commands:\n");
246: safe_prf("?,help - Print this message\n");
247: for (command = miniMonCommands; command->name; command++) {
248: if (command->help)
249: safe_prf("%s - %s\n",command->name,command->help);
250: }
251: for (command = miniMonMDCommands; command->name; command++) {
252: if (command->help)
253: safe_prf("%s - %s\n",command->name,command->help);
254: }
255: return TRUE;
256: }
257:
258: /* keep messages from getting written to message log */
259: void safe_prf(const char *format, ...)
260: {
261: va_list ap;
262: static char buf[512];
263: char *p = buf;
264:
265: va_start(ap, format);
266: #define TOSTR 0x8
267: prf(format, ap, TOSTR, (struct tty *)&p);
268: va_end(ap);
269: *p++ = '\0';
270:
271: p = buf;
272: while (*p)
273: miniMonPutchar(*p++);
274: }
275:
276: static boolean_t
277: miniMonResetKdp(char *line)
278: {
279: extern void kdp_reset(void);
280:
281: kdp_reset();
282: return TRUE;
283: }
284:
285: static boolean_t
286: miniMonTryGdb(char *line)
287: {
288: extern simple_lock_t _kernDebuggerLock;
289: boolean_t ret;
290:
291: if (simple_lock_try(_kernDebuggerLock)) {
292: ret = miniMonGdb(line);
293: simple_unlock(_kernDebuggerLock);
294: } else {
295: safe_prf("Couldn't acquire debugger lock:\n");
296: safe_prf("exit from monitor and try again.\n");
297: ret = TRUE;
298: }
299: return ret;
300: }
301:
302: static boolean_t
303: miniMonForceGdb(char *line)
304: {
305: extern simple_lock_t _kernDebuggerLock;
306: boolean_t ret;
307:
308: simple_lock_try(_kernDebuggerLock);
309: ret = miniMonGdb(line);
310: simple_unlock(_kernDebuggerLock);
311:
312: return ret;
313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.