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