Init
This commit is contained in:
586
sys/debug/main.c
Normal file
586
sys/debug/main.c
Normal file
@@ -0,0 +1,586 @@
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)main.c 1.1 94/10/31 SMI";
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <machine/reg.h>
|
||||
#include <debug/debugger.h>
|
||||
#include <a.out.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifdef OPENPROMS
|
||||
#include <sun/openprom.h>
|
||||
#include <sun/autoconf.h>
|
||||
#include <machine/pte.h>
|
||||
|
||||
extern char *prom_bootpath(), *prom_bootargs();
|
||||
#endif
|
||||
|
||||
char vmunix[50] = "vmunix"; /* and room to patch to whatever */
|
||||
char myname[50]; /* name of the debugger */
|
||||
char aline[LINEBUFSZ]; /* generic buffer used for console input */
|
||||
extern int debugcmd();
|
||||
extern char *malloc();
|
||||
extern char estack[];
|
||||
char *malreturn;
|
||||
|
||||
#ifdef MULTIPROCESSOR
|
||||
unsigned nodeid;
|
||||
unsigned who;
|
||||
extern int cpus_enabled[];
|
||||
#ifdef PROM_IDLECPUS_WORKS
|
||||
extern unsigned cpus_nodeid[];
|
||||
#endif /* PROM_IDLECPUS_WORKS */
|
||||
#endif MULTIPROCESSOR
|
||||
|
||||
#define MALLOC_PAD 0x1000 /* malloc pad */
|
||||
|
||||
static interactive = 0; /* true if -d flag passed in */
|
||||
|
||||
#ifndef sun2
|
||||
u_int memory_avail;
|
||||
#endif
|
||||
|
||||
main()
|
||||
{
|
||||
func_t go2, load_it();
|
||||
char *arg;
|
||||
#ifdef mc68000
|
||||
struct regs fakeregs;
|
||||
struct stkfmt fakestkfmt;
|
||||
int fakedfc, fakesfc;
|
||||
#endif
|
||||
#ifdef OPENPROMS
|
||||
register struct memlist *pmem;
|
||||
extern struct memlist *getmemlist();
|
||||
#endif
|
||||
|
||||
ttysync();
|
||||
#ifdef OPENPROMS
|
||||
if (romp->op_romvec_version > 0) {
|
||||
pmem = getmemlist("memory", "available");
|
||||
if (pmem == (struct memlist *)0)
|
||||
return;
|
||||
} else
|
||||
pmem = *romp->v_availmemory;
|
||||
for (memory_avail = 0; pmem->next != (struct memlist *)NULL;
|
||||
pmem = pmem->next) {
|
||||
memory_avail += pmem->size;
|
||||
}
|
||||
memory_avail += pmem->size;
|
||||
#elif !defined(sun2)
|
||||
/*
|
||||
* Initialize so that the standalone code doesn't
|
||||
* use the same pages the debugger is in.
|
||||
*/
|
||||
memory_avail = *romp->v_memoryavail;
|
||||
#endif OPENPROMS || !sun2
|
||||
spawn((int *)estack, debugcmd);
|
||||
while ((go2 = load_it(&arg)) == (func_t)-1)
|
||||
continue;
|
||||
if (go2 == (func_t)-2)
|
||||
return;
|
||||
free(malloc(MALLOC_PAD));
|
||||
|
||||
printf("%s loaded - 0x%x bytes used\n",
|
||||
arg, mmu_ptob(pagesused));
|
||||
|
||||
#ifdef MULTIPROCESSOR
|
||||
nodeid = prom_nextnode(0); /* root node */
|
||||
for (nodeid = prom_childnode(nodeid);
|
||||
(nodeid != 0) && (nodeid != -1);
|
||||
nodeid = prom_nextnode(nodeid)) {
|
||||
if ((prom_getproplen(nodeid, "mid") == sizeof who) &&
|
||||
(prom_getprop(nodeid, "mid", &who) != -1)) {
|
||||
if (who == 15)
|
||||
who = 0; /* level-1 mbus module */
|
||||
else
|
||||
who &= 3;
|
||||
#ifdef PROM_IDLECPUS_WORKS
|
||||
cpus_nodeid[who] = nodeid;
|
||||
#endif /* PROM_IDLECPUS_WORKS */
|
||||
cpus_enabled[who] = 1;
|
||||
}
|
||||
}
|
||||
#endif MULTIPROCESSOR
|
||||
if (interactive) {
|
||||
#ifdef mc68000
|
||||
bzero((caddr_t)&fakeregs, sizeof (fakeregs));
|
||||
bzero((caddr_t)&fakestkfmt, sizeof (fakestkfmt));
|
||||
(void) cmd(fakedfc, fakesfc, fakeregs, fakestkfmt);
|
||||
#else
|
||||
(void) cmd();
|
||||
#endif
|
||||
if (dotrace) {
|
||||
scbstop = 1;
|
||||
dotrace = 0;
|
||||
}
|
||||
}
|
||||
nobrk = 1; /* no more sbrk's allowed */
|
||||
exitto(go2);
|
||||
}
|
||||
|
||||
#define LOAD 0x4000
|
||||
|
||||
/*
|
||||
* Read in a Unix executable file and return its entry point.
|
||||
* Handle the various a.out formats correctly.
|
||||
* "Io" is the standalone file descriptor to read from.
|
||||
* Print informative little messages if "print" is on.
|
||||
* Returns -1 for errors.
|
||||
*/
|
||||
func_t
|
||||
readfile(io, print, name)
|
||||
register int io;
|
||||
int print;
|
||||
char *name;
|
||||
{
|
||||
struct exec x;
|
||||
register int i;
|
||||
register char *addr;
|
||||
register int shared = 0;
|
||||
register int loadaddr;
|
||||
register int segsiz;
|
||||
register int datasize;
|
||||
|
||||
i = read(io, (char *)&x, sizeof x);
|
||||
if (i != sizeof (x)) {
|
||||
printf("Bad read: expected 0x%x got 0x%x\n", sizeof(x), i);
|
||||
return ((func_t)-1);
|
||||
}
|
||||
if (N_BADMAG(x)) {
|
||||
printf("Not executable\n");
|
||||
return ((func_t)-1);
|
||||
}
|
||||
shared = (x.a_magic == OMAGIC? 0: 1);
|
||||
if (print)
|
||||
printf("Size: %d", x.a_text);
|
||||
datasize = x.a_data;
|
||||
if (!shared) {
|
||||
x.a_text = x.a_text + x.a_data;
|
||||
x.a_data = 0;
|
||||
}
|
||||
if (lseek(io, N_TXTOFF(x), 0) == -1)
|
||||
goto shread;
|
||||
if (read(io, (char *)LOAD, (int)x.a_text) < x.a_text)
|
||||
goto shread;
|
||||
addr = (char *)(x.a_text + LOAD);
|
||||
if (x.a_machtype == M_OLDSUN2)
|
||||
segsiz = OLD_SEGSIZ;
|
||||
else
|
||||
segsiz = SEGSIZ;
|
||||
if (shared)
|
||||
while ((int)addr & (segsiz-1))
|
||||
*addr++ = 0;
|
||||
if (print)
|
||||
printf("+%d", datasize);
|
||||
if (read(io, addr, (int)x.a_data) < x.a_data)
|
||||
goto shread;
|
||||
if (print)
|
||||
printf("+%d", x.a_bss);
|
||||
addr += x.a_data;
|
||||
for (i = 0; i < x.a_bss; i++)
|
||||
*addr++ = 0;
|
||||
if (print)
|
||||
printf(" bytes\n");
|
||||
if (x.a_machtype != M_OLDSUN2 && x.a_magic == ZMAGIC)
|
||||
loadaddr = LOAD + sizeof (struct exec);
|
||||
else
|
||||
loadaddr = LOAD;
|
||||
debuginit(io, &x, name);
|
||||
return ((func_t)loadaddr);
|
||||
|
||||
shread:
|
||||
printf("Truncated file\n");
|
||||
return ((func_t)-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prompt for name of file to be read into memory for debugging.
|
||||
*/
|
||||
#ifdef OPENPROMS
|
||||
func_t
|
||||
obp_load_it(arg)
|
||||
register char **arg;
|
||||
{
|
||||
register int howto;
|
||||
register int io;
|
||||
func_t go2;
|
||||
extern char myname_default[];
|
||||
static char filename[LINEBUFSZ];
|
||||
register char *bargs;
|
||||
register char *bpath;
|
||||
char *args[8];
|
||||
register char abuf[128];
|
||||
|
||||
bpath = prom_bootpath();
|
||||
bargs = prom_bootargs();
|
||||
(void)strcpy(abuf, bargs);
|
||||
setparam(abuf, args);
|
||||
|
||||
if (myname[0] == '\0') {
|
||||
register char *s, *p;
|
||||
|
||||
for (s = bargs; isspace(*s); s++)
|
||||
;
|
||||
if (*s == '-')
|
||||
s = myname_default;
|
||||
for (p = myname; *s && !isspace(*s); )
|
||||
*p++ = *s++;
|
||||
} else if (interactive == 0) {
|
||||
/*
|
||||
* 2nd time thru and we are not interactive,
|
||||
* return fatal error code back to caller.
|
||||
*/
|
||||
return ((func_t)-2);
|
||||
}
|
||||
|
||||
if (*args[0] == '-')
|
||||
howto = bootflags(args[0]);
|
||||
else
|
||||
howto = bootflags(args[1]);
|
||||
if (howto & RB_DEBUG)
|
||||
interactive = 1;
|
||||
|
||||
/*
|
||||
* Now we have to ask for the name of the program to load
|
||||
* if we are interactive.
|
||||
*/
|
||||
*filename = '\0';
|
||||
if (interactive) {
|
||||
printf("%s: ", myname);
|
||||
gets(filename);
|
||||
}
|
||||
|
||||
/*
|
||||
* If no file name given (or we are non-interactive),
|
||||
* default to patchable string in vmunix[]
|
||||
*/
|
||||
if (*filename == '\0') {
|
||||
(void)strcpy(filename, vmunix);
|
||||
printf("%s: %s\n", myname, filename);
|
||||
}
|
||||
parseargs(filename, howto, args, bargs);
|
||||
|
||||
(void) reopen(0); /* Restart the I/O. */
|
||||
io = open(filename, 0);
|
||||
if (io >= 0) {
|
||||
go2 = readfile(io, 1, filename);
|
||||
} else {
|
||||
printf("boot failed\n");
|
||||
interactive = 1;
|
||||
go2 = (func_t)-1;
|
||||
}
|
||||
close(io); /* Done with it. */
|
||||
*arg = filename;
|
||||
return (go2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the boot line to set bootparam structure
|
||||
*/
|
||||
setparam(cp, bp)
|
||||
register char *cp;
|
||||
register char *bp[];
|
||||
{
|
||||
register int i = 0;
|
||||
|
||||
while (*cp && isspace(*cp))
|
||||
cp++;
|
||||
while ((i < 8) && *cp) {
|
||||
bp[i++] = cp;
|
||||
while (*cp && (!isspace(*cp)))
|
||||
cp++;
|
||||
if (isspace(*cp))
|
||||
*cp++ = '\0';
|
||||
while (*cp && isspace(*cp))
|
||||
cp++;
|
||||
}
|
||||
/*
|
||||
* Null out remaining args.
|
||||
*/
|
||||
for (; i < 8; ++i)
|
||||
bp[i] = '\0';
|
||||
}
|
||||
#endif OPENPROMS
|
||||
|
||||
func_t
|
||||
load_it(arg)
|
||||
register char **arg;
|
||||
{
|
||||
register struct bootparam *bp;
|
||||
register int howto;
|
||||
register int io;
|
||||
func_t go2;
|
||||
extern char myname_default[];
|
||||
register char *ap;
|
||||
static char filename[LINEBUFSZ];
|
||||
|
||||
#ifdef OPENPROMS
|
||||
if (romp->op_romvec_version > 0)
|
||||
return (obp_load_it(arg));
|
||||
#endif
|
||||
|
||||
#if defined(sun2) || defined(sun3)
|
||||
if (romp->v_bootparam == 0)
|
||||
bp = (struct bootparam *)0x2000; /* Old Sun-1 address */
|
||||
else
|
||||
#endif sun2 || sun3
|
||||
bp = *romp->v_bootparam; /* S-2: via romvec */
|
||||
|
||||
*arg = bp->bp_argv[0];
|
||||
if (*arg == NULL)
|
||||
*arg = "";
|
||||
if (myname[0] == '\0') {
|
||||
register char *s, *p;
|
||||
|
||||
for (s = *arg, ap = aline; *s && *s != ')';)
|
||||
*ap++ = *s++;
|
||||
*ap++ = *s++;
|
||||
if (*s == '\0')
|
||||
s = myname_default;
|
||||
for (p = myname; *s;)
|
||||
*p++ = *s++;
|
||||
} else if (interactive == 0) {
|
||||
/*
|
||||
* 2nd time thru and we are not interactive,
|
||||
* return fatal error code back to caller.
|
||||
*/
|
||||
return ((func_t)-2);
|
||||
}
|
||||
|
||||
howto = bootflags(bp->bp_argv[1]);
|
||||
if (howto & RB_DEBUG)
|
||||
interactive = 1;
|
||||
|
||||
/*
|
||||
* Now we have to ask for the name of the program to load
|
||||
* if we are interactive.
|
||||
*/
|
||||
*filename = '\0';
|
||||
if (interactive) {
|
||||
printf("%s: ", myname);
|
||||
gets(filename);
|
||||
}
|
||||
|
||||
/*
|
||||
* If no file name given (or we are non-interactive),
|
||||
* default to patchable string in vmunix[]
|
||||
*/
|
||||
if (*filename == '\0') {
|
||||
register char *s, *p;
|
||||
|
||||
for (s = filename, p = vmunix; *p;)
|
||||
*s++ = *p++;
|
||||
*s = '\0';
|
||||
printf("%s: %s\n", myname, filename);
|
||||
for (s = filename; *s; )
|
||||
*ap++ = *s++;
|
||||
*ap = '\0';
|
||||
}
|
||||
parseparam(filename, howto, bp);
|
||||
|
||||
(void) reopen(aline); /* Restart the I/O. */
|
||||
io = open(filename, 0);
|
||||
if (io >= 0) {
|
||||
go2 = readfile(io, 1, filename);
|
||||
} else {
|
||||
printf("boot failed\n");
|
||||
go2 = (func_t)-1;
|
||||
}
|
||||
close(io); /* Done with it. */
|
||||
*arg = filename;
|
||||
return (go2);
|
||||
}
|
||||
|
||||
struct bootf {
|
||||
char let;
|
||||
short bit;
|
||||
} bootf[] = {
|
||||
'a', RB_ASKNAME,
|
||||
's', RB_SINGLE,
|
||||
'i', RB_INITNAME,
|
||||
'h', RB_HALT,
|
||||
'b', RB_NOBOOTRC,
|
||||
'd', RB_DEBUG,
|
||||
'w', RB_WRITABLE,
|
||||
0, 0,
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Parse the boot line to determine boot flags
|
||||
*/
|
||||
bootflags(cp)
|
||||
register char *cp;
|
||||
{
|
||||
register int i, boothowto = 0;
|
||||
|
||||
if ((cp) && (*cp++ == '-'))
|
||||
while (*cp) {
|
||||
for (i = 0; bootf[i].let; i++) {
|
||||
if (*cp == bootf[i].let) {
|
||||
boothowto |= bootf[i].bit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cp++;
|
||||
}
|
||||
return (boothowto);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the boot line and put it in bootparam. Preserve the flags
|
||||
* unless redefined. Always preserve the remaining arguments.
|
||||
*
|
||||
* The boot line comes in in one of two forms:
|
||||
* xx(c,u,p)file[whitespace]\0
|
||||
* xx(c,u,p)file[whitespace]-[flags]\0
|
||||
* If the former is present, we take the bootflags and arguments from the
|
||||
* bootparam structure. If the latter is present, the user has overridden
|
||||
* the original boot flags with his/her own specification.
|
||||
*/
|
||||
parseparam(line, defaults, bp)
|
||||
char *line;
|
||||
int defaults;
|
||||
register struct bootparam *bp;
|
||||
{
|
||||
register int i;
|
||||
register char *cp, *lp = line;
|
||||
|
||||
while (*lp && isgraph(*lp))
|
||||
lp++;
|
||||
if (*lp) {
|
||||
*lp = '\0';
|
||||
}
|
||||
cp = lp++;
|
||||
while (*lp && isspace(*lp))
|
||||
lp++;
|
||||
if (*lp) {
|
||||
/*
|
||||
* There's something here. Is it new flags?
|
||||
*/
|
||||
if (*lp == '-') {
|
||||
defaults = bootflags(lp);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now backtrack, write the flags, and fill in the arguments.
|
||||
*/
|
||||
lp = cp + 1;
|
||||
defaults |= RB_DEBUG; /* or in debug flag */
|
||||
*lp++ = '-';
|
||||
for (i = 0; bootf[i].let; i++) {
|
||||
if (defaults & bootf[i].bit)
|
||||
*lp++ = bootf[i].let;
|
||||
}
|
||||
*lp++ = 0;
|
||||
for (i = 1; i < 8; ++i) {
|
||||
cp = bp->bp_argv[i];
|
||||
if (cp && *cp && (*cp != '-')) {
|
||||
while (*lp++ = *cp++)
|
||||
;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copy the fully qualified boot line to the string table.
|
||||
*/
|
||||
bcopy(line, bp->bp_strings, 95);
|
||||
bp->bp_strings[95] = '\0';
|
||||
/*
|
||||
* Scan the string table, setting the argv pointers.
|
||||
*/
|
||||
for (i = 0, cp = bp->bp_strings; i < 8; ++i) {
|
||||
if (cp && *cp) {
|
||||
bp->bp_argv[i] = cp;
|
||||
while (*cp++)
|
||||
;
|
||||
} else {
|
||||
bp->bp_argv[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OPENPROMS
|
||||
/*
|
||||
* Parse the line argument and put it in the bootargs in OBP.
|
||||
* Preserve the flags unless redefined. Always preserve the remaining
|
||||
* arguments. Leave just a filename in line.
|
||||
*
|
||||
* The line looks like:
|
||||
* file[whitespace]-[flags]\0
|
||||
*
|
||||
* We take the bootflags and arguments from the bargs structure.
|
||||
*/
|
||||
parseargs(line, defaults, bp, dp)
|
||||
char *line;
|
||||
int defaults;
|
||||
register char *bp[];
|
||||
register char *dp;
|
||||
{
|
||||
register int i;
|
||||
register char *cp, *lp = line;
|
||||
char buf[128];
|
||||
|
||||
/*
|
||||
* Find the end of the file argument.
|
||||
*/
|
||||
while (*lp && isgraph(*lp))
|
||||
lp++;
|
||||
cp = lp++;
|
||||
|
||||
/*
|
||||
* Scan ahead, looking for flags.
|
||||
*/
|
||||
while (*lp && isspace(*lp))
|
||||
lp++;
|
||||
if (*lp) {
|
||||
/*
|
||||
* There's something here. Is it new flags?
|
||||
*/
|
||||
if (*lp == '-') {
|
||||
defaults = bootflags(lp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now backtrack, write the flags, and fill in the arguments.
|
||||
*/
|
||||
lp = cp;
|
||||
defaults |= RB_DEBUG;
|
||||
if (defaults) {
|
||||
*lp++ = ' ';
|
||||
*lp++ = '-';
|
||||
for (i = 0; bootf[i].let; i++) {
|
||||
if (defaults & bootf[i].bit)
|
||||
*lp++ = bootf[i].let;
|
||||
}
|
||||
*lp = '\0';
|
||||
}
|
||||
if (bp[1] && *(bp[1]) == '-')
|
||||
i = 2;
|
||||
else
|
||||
i = 1;
|
||||
for (; i < 8; ++i) {
|
||||
cp = bp[i];
|
||||
if (cp && *cp && (*cp != '-')) {
|
||||
*lp++ = ' ';
|
||||
while (*lp++ = *cp++)
|
||||
;
|
||||
*lp = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the fully qualified boot line to the bootargs.
|
||||
* Reset the bootparam arguments.
|
||||
*/
|
||||
bcopy(line, dp, 100);
|
||||
setparam(line, bp);
|
||||
}
|
||||
#endif OPENPROMS
|
||||
Reference in New Issue
Block a user