Index: head/sys/boot/common/interp.c =================================================================== --- head/sys/boot/common/interp.c (revision 41999) +++ head/sys/boot/common/interp.c (revision 42000) @@ -1,272 +1,281 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: interp.c,v 1.7 1998/10/21 20:07:04 msmith Exp $ + * $Id: interp.c,v 1.8 1998/11/04 00:29:01 msmith Exp $ */ /* * Simple commandline interpreter, toplevel and misc. * * XXX may be obsoleted by BootFORTH or some other, better, interpreter. */ #include #include #include "bootstrap.h" +#ifdef BOOT_FORTH +#include "ficl.h" +#define RETURN(x) stackPushINT32(bf_vm->pStack,!x); return(x) + +extern FICL_VM *bf_vm; +#else +#define RETURN(x) return(x) +#endif + #define MAXARGS 20 /* maximum number of arguments allowed */ static void prompt(void); /* * Perform the command */ int perform(int argc, char *argv[]) { int i, result; struct bootblk_command **cmdp; bootblk_cmd_t *cmd; if (argc < 1) return(CMD_OK); /* set return defaults; a successful command will override these */ command_errmsg = command_errbuf; strcpy(command_errbuf, "no error message"); cmd = NULL; result = CMD_ERROR; /* search the command set for the command */ SET_FOREACH(cmdp, Xcommand_set) { if (((*cmdp)->c_name != NULL) && !strcmp(argv[0], (*cmdp)->c_name)) cmd = (*cmdp)->c_fn; } if (cmd != NULL) { result = (cmd)(argc, argv); } else { command_errmsg = "unknown command"; } - return(result); + RETURN(result); } /* * Interactive mode */ void interact(void) { char input[256]; /* big enough? */ int argc; char **argv; #ifdef BOOT_FORTH bf_init(); #endif /* * Read our default configuration */ source("/boot/boot.conf"); printf("\n"); /* * Before interacting, we might want to autoboot. */ autoboot_maybe(); /* * Not autobooting, go manual */ printf("\nType '?' for a list of commands, 'help' for more detailed help.\n"); setenv("prompt", "${currdev}>", 1); for (;;) { input[0] = '\0'; prompt(); ngets(input, sizeof(input)); #ifdef BOOT_FORTH bf_run(input); #else if (!parse(&argc, &argv, input)) { if (perform(argc, argv)) printf("%s: %s\n", argv[0], command_errmsg); free(argv); } else { printf("parse error\n"); } #endif } } /* * Read commands from a file, then execute them. * * We store the commands in memory and close the source file so that the media * holding it can safely go away while we are executing. * * Commands may be prefixed with '@' (so they aren't displayed) or '-' (so * that the script won't stop if they fail). */ COMMAND_SET(source, "source", "read commands from a file", command_source); static int command_source(int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) source(argv[i]); - return(CMD_OK); + RETURN(CMD_OK); } struct sourceline { char *text; int flags; int line; #define SL_QUIET (1<<0) #define SL_IGNOREERR (1<<1) struct sourceline *next; }; void source(char *filename) { struct sourceline *script, *se, *sp; char input[256]; /* big enough? */ int argc; char **argv, *cp; int fd, flags, line; if (((fd = open(filename, O_RDONLY)) == -1)) { printf("can't open '%s': %s\n", filename, strerror(errno)); return; } /* * Read the script into memory. */ script = se = NULL; line = 0; while (fgetstr(input, sizeof(input), fd) > 0) { line++; flags = 0; /* Discard comments */ if (input[0] == '#') continue; cp = input; /* Echo? */ if (input[0] == '@') { cp++; flags |= SL_QUIET; } /* Error OK? */ if (input[0] == '-') { cp++; flags |= SL_IGNOREERR; } /* Allocate script line structure and copy line, flags */ sp = malloc(sizeof(struct sourceline) + strlen(cp) + 1); sp->text = (char *)sp + sizeof(struct sourceline); strcpy(sp->text, cp); sp->flags = flags; sp->line = line; sp->next = NULL; if (script == NULL) { script = sp; } else { se->next = sp; } se = sp; } close(fd); /* * Execute the script */ argv = NULL; for (sp = script; sp != NULL; sp = sp->next) { /* print if not being quiet */ if (!(sp->flags & SL_QUIET)) { prompt(); printf("%s\n", sp->text); } /* Parse the command */ if (!parse(&argc, &argv, sp->text)) { if ((argc > 0) && (perform(argc, argv) != 0)) { /* normal command */ printf("%s: %s\n", argv[0], command_errmsg); if (!(sp->flags & SL_IGNOREERR)) break; } free(argv); argv = NULL; } else { printf("%s line %d: parse error\n", filename, sp->line); break; } } if (argv != NULL) free(argv); while(script != NULL) { se = script; script = script->next; free(se); } } /* * Emit the current prompt; use the same syntax as the parser * for embedding environment variables. */ static void prompt(void) { char *p, *cp, *ev; if ((cp = getenv("prompt")) == NULL) cp = ">"; p = strdup(cp); while (*p != 0) { if ((*p == '$') && (*(p+1) == '{')) { for (cp = p + 2; (*cp != 0) && (*cp != '}'); cp++) ; *cp = 0; ev = getenv(p + 2); if (ev != NULL) printf(ev); p = cp + 1; continue; } putchar(*p++); } putchar(' '); } Index: head/sys/boot/common/interp_forth.c =================================================================== --- head/sys/boot/common/interp_forth.c (revision 41999) +++ head/sys/boot/common/interp_forth.c (revision 42000) @@ -1,138 +1,141 @@ /* * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: interp_forth.c,v 1.6 1998/11/07 03:44:10 jkh Exp $ + * $Id: interp_forth.c,v 1.7 1998/11/07 06:18:00 jkh Exp $ */ #include #include "bootstrap.h" #include "ficl.h" /* #define BFORTH_DEBUG */ #ifdef BFORTH_DEBUG # define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __FUNCTION__ , ## args) #else # define DEBUG(fmt, args...) #endif /* * BootForth Interface to Ficl Forth interpreter. */ -static FICL_VM *bf_vm; +FICL_VM *bf_vm; /* * Shim for taking commands from BF and passing them out to 'standard' * argv/argc command functions. */ static void bf_command(FICL_VM *vm) { char *name, *line, *tail, *cp; int len; struct bootblk_command **cmdp; bootblk_cmd_t *cmd; int argc, result; char **argv; /* Get the name of the current word */ name = vm->runningWord->name; /* Find our command structure */ cmd == NULL; SET_FOREACH(cmdp, Xcommand_set) { if (((*cmdp)->c_name != NULL) && !strcmp(name, (*cmdp)->c_name)) cmd = (*cmdp)->c_fn; } if (cmd == NULL) panic("callout for unknown command '%s'", name); /* Get remainder of invocation */ tail = vmGetInBuf(vm); for (cp = tail, len = 0; *cp != 0 && *cp != '\n'; cp++, len++) ; line = malloc(strlen(name) + len + 2); strcpy(line, name); if (len > 0) { strcat(line, " "); strncat(line, tail, len); vmUpdateTib(vm, tail + len); } DEBUG("cmd '%s'", line); command_errmsg = command_errbuf; command_errbuf[0] = 0; if (!parse(&argc, &argv, line)) { result = (cmd)(argc, argv); free(argv); - if (result != 0) { - strcpy(command_errmsg, vm->pad); - vmTextOut(vm, vm->pad, 1); + if(result != 0) { + vmTextOut(vm,argv[0],0); + vmTextOut(vm,": ",0); + vmTextOut(vm,command_errmsg,1); } } else { vmTextOut(vm, "parse error\n", 1); + result=1; } free(line); + stackPushINT32(vm->pStack,!result); } /* * Initialise the Forth interpreter, create all our commands as words. */ void bf_init(void) { struct bootblk_command **cmdp; int fd; ficlInitSystem(4000); /* Default dictionary ~4000 cells */ bf_vm = ficlNewVM(); /* make all commands appear as Forth words */ SET_FOREACH(cmdp, Xcommand_set) ficlBuild((*cmdp)->c_name, bf_command, FW_DEFAULT); /* try to load and run init file if present */ if ((fd = open("/boot/boot.4th", O_RDONLY)) != -1) { (void)ficlExecFD(bf_vm, fd); close(fd); } } /* * Feed a line of user input to the Forth interpreter */ void bf_run(char *line) { int result; result = ficlExec(bf_vm, line); DEBUG("ficlExec '%s' = %d", line, result); if (result == VM_USEREXIT) panic("interpreter exit"); } Index: head/sys/boot/common/load_aout.c =================================================================== --- head/sys/boot/common/load_aout.c (revision 41999) +++ head/sys/boot/common/load_aout.c (revision 42000) @@ -1,355 +1,359 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: load_aout.c,v 1.9 1998/10/09 23:15:39 peter Exp $ + * $Id: load_aout.c,v 1.10 1998/10/12 09:05:12 peter Exp $ */ #include #include #include #include #include #include #include #include #include #define FREEBSD_AOUT #include #include "bootstrap.h" static int aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel); #if 0 static vm_offset_t aout_findkldident(struct loaded_module *mp, struct exec *ehdr); static int aout_fixupkldmod(struct loaded_module *mp, struct exec *ehdr); #endif char *aout_kerneltype = "a.out kernel"; char *aout_moduletype = "a.out module"; /* * Attempt to load the file (file) as an a.out module. It will be stored at * (dest), and a pointer to a module structure describing the loaded object * will be saved in (result). */ int aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) { struct loaded_module *mp, *kmp; struct exec ehdr; int fd; vm_offset_t addr; int err, kernel; u_int pad; char *s; mp = NULL; /* * Open the image, read and validate the a.out header */ if (filename == NULL) /* can't handle nameless */ return(EFTYPE); if ((fd = open(filename, O_RDONLY)) == -1) return(errno); if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) { err = EFTYPE; /* could be EIO, but may be small file */ goto oerr; } if (N_BADMAG(ehdr)) { err = EFTYPE; goto oerr; } /* * Check to see what sort of module we are. * * XXX should check N_GETMID() */ kmp = mod_findmodule(NULL, NULL); if ((N_GETFLAG(ehdr)) & EX_DYNAMIC) { /* Looks like a kld module */ if (kmp == NULL) { printf("aout_loadmodule: can't load module before kernel\n"); err = EPERM; goto oerr; } if (strcmp(aout_kerneltype, kmp->m_type)) { printf("aout_loadmodule: can't load module with kernel type '%s'\n", kmp->m_type); err = EPERM; goto oerr; } /* Looks OK, got ahead */ kernel = 0; } else if (N_GETFLAG(ehdr) == 0) { /* Looks like a kernel */ if (kmp != NULL) { printf("aout_loadmodule: kernel already loaded\n"); err = EPERM; goto oerr; } /* * Calculate destination address based on kernel entrypoint * XXX this is i386-freebsd-aout specific */ dest = ehdr.a_entry & 0x100000; if (dest == 0) { printf("aout_loadmodule: not a kernel (maybe static binary?)\n"); err = EPERM; goto oerr; } kernel = 1; } else { err = EFTYPE; goto oerr; } /* * Ok, we think we should handle this. */ mp = mod_allocmodule(); if (kernel) setenv("kernelname", filename, 1); s = strrchr(filename, '/'); if (s) mp->m_name = strdup(s + 1); else mp->m_name = strdup(filename); mp->m_type = strdup(kernel ? aout_kerneltype : aout_moduletype); /* Page-align the load address */ addr = dest; pad = (u_int)addr & PAGE_MASK; if (pad != 0) { pad = PAGE_SIZE - pad; addr += pad; } mp->m_addr = addr; /* save the aligned load address */ if (kernel) printf("%s at %p\n", filename, (void *) addr); mp->m_size = aout_loadimage(mp, fd, addr, &ehdr, kernel); if (mp->m_size == 0) goto ioerr; #if 0 /* Handle KLD module data */ if (!kernel && ((err = aout_fixupkldmod(mp, &ehdr)) != 0)) goto oerr; #endif /* save exec header as metadata */ mod_addmetadata(mp, MODINFOMD_AOUTEXEC, sizeof(struct exec), &ehdr); /* Load OK, return module pointer */ *result = (struct loaded_module *)mp; err = 0; goto out; ioerr: err = EIO; oerr: mod_discard(mp); free(mp); out: close(fd); return(err); } /* * With the file (fd) open on the image, and (ehdr) containing * the exec header, load the image at (addr) * * Fixup the a_bss field in (ehdr) to reflect the padding added to * align the symbol table. */ static int aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel) { u_int pad; vm_offset_t addr; int ss; vm_offset_t ssym, esym; addr = loadaddr; lseek(fd, N_TXTOFF(*ehdr), SEEK_SET); /* text segment */ printf(" text=0x%lx ", ehdr->a_text); if (archsw.arch_readin(fd, addr, ehdr->a_text) != ehdr->a_text) return(0); addr += ehdr->a_text; /* data segment */ printf("data=0x%lx ", ehdr->a_data); if (archsw.arch_readin(fd, addr, ehdr->a_data) != ehdr->a_data) return(0); addr += ehdr->a_data; /* For kernels, we pad the BSS to a page boundary */ if (kernel) { pad = (u_int)ehdr->a_bss & PAGE_MASK; if (pad != 0) { pad = PAGE_SIZE - pad; ehdr->a_bss += pad; } } printf("bss=0x%lx ", ehdr->a_bss); addr += ehdr->a_bss; /* symbol table size */ ssym = addr; - archsw.arch_copyin(&ehdr->a_syms, addr, sizeof(ehdr->a_syms)); - addr += sizeof(ehdr->a_syms); + if(ehdr->a_syms!=NULL) { + archsw.arch_copyin(&ehdr->a_syms, addr, sizeof(ehdr->a_syms)); + addr += sizeof(ehdr->a_syms); - /* symbol table */ - printf("symbols=[0x%x+0x%lx", sizeof(ehdr->a_syms), ehdr->a_syms); - if (archsw.arch_readin(fd, addr, ehdr->a_syms) != ehdr->a_syms) - return(0); - addr += ehdr->a_syms; + /* symbol table */ + printf("symbols=[0x%x+0x%lx", sizeof(ehdr->a_syms), ehdr->a_syms); + if (archsw.arch_readin(fd, addr, ehdr->a_syms) != ehdr->a_syms) + return(0); + addr += ehdr->a_syms; - /* string table */ - read(fd, &ss, sizeof(ss)); - archsw.arch_copyin(&ss, addr, sizeof(ss)); - addr += sizeof(ss); - ss -= sizeof(ss); - printf("+0x%x+0x%x]", sizeof(ss), ss); - if (archsw.arch_readin(fd, addr, ss) != ss) - return(0); - printf(" \n"); - addr += ss; - esym = addr; + /* string table */ + read(fd, &ss, sizeof(ss)); + archsw.arch_copyin(&ss, addr, sizeof(ss)); + addr += sizeof(ss); + ss -= sizeof(ss); + printf("+0x%x+0x%x]", sizeof(ss), ss); + if (archsw.arch_readin(fd, addr, ss) != ss) + return(0); + addr += ss; - mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym); - mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym); + mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym); + mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym); + } else { + printf("symbols=[none]"); + } + printf("\n"); + esym = addr; return(addr - loadaddr); } #if 0 #define AOUT_RELOC(mp, off) ((mp)->m_addr + (vm_offset_t)(off)) /* * The goal here is to find the one symbol in the loaded object * which fits the format "kld_identifier_. If there's * more than one, we fail. */ static vm_offset_t aout_findkldident(struct loaded_module *mp, struct exec *ehdr) { /* XXX much of this can go when we can address the load area directly */ vm_offset_t sp, ep, cand, stringbase, result; struct _dynamic dynamic; struct section_dispatch_table sdt; struct nzlist nzl; char *np; int match; /* Get the _DYNAMIC object, which we assume is first in the data segment */ archsw.arch_copyout(AOUT_RELOC(mp, ehdr->a_text), &dynamic, sizeof(dynamic)); archsw.arch_copyout(AOUT_RELOC(mp, dynamic.d_un.d_sdt), &sdt, sizeof(struct section_dispatch_table)); dynamic.d_un.d_sdt = &sdt; /* fix up SDT pointer */ if (dynamic.d_version != LD_VERSION_BSD) return(0); stringbase = AOUT_RELOC(mp, LD_STRINGS(&dynamic)); /* start pointer */ sp = AOUT_RELOC(mp, LD_SYMBOL(&dynamic)); /* end pointer */ ep = sp + LD_STABSZ(&dynamic); /* * Walk the entire table comparing names. */ match = 0; result = 0; for (cand = sp; cand < ep; cand += sizeof(struct nzlist)) { /* get the entry, check for a name */ archsw.arch_copyout(cand, &nzl, sizeof(struct nzlist)); /* is this symbol worth looking at? */ if ((nzl.nz_strx == 0) || /* no name */ (nzl.nz_value == 0) || /* not a definition */ ((nzl.nz_type == N_UNDF+N_EXT) && (nzl.nz_value != 0) && (nzl.nz_other == AUX_FUNC))) /* weak function */ continue; np = strdupout(stringbase + nzl.nz_strx); match = (np[0] == '_') && !strncmp(KLD_IDENT_SYMNAME, np + 1, strlen(KLD_IDENT_SYMNAME)); free(np); if (match) { /* duplicates? */ if (result) return(0); result = AOUT_RELOC(mp, nzl.nz_value); } } return(result); } /* * Perform extra housekeeping associated with loading a KLD module. * * XXX if this returns an error, it seems the heap becomes corrupted. */ static int aout_fixupkldmod(struct loaded_module *mp, struct exec *ehdr) { struct kld_module_identifier kident; struct kld_module_dependancy *kdeps; vm_offset_t vp; size_t dsize; /* Find the KLD identifier */ if ((vp = aout_findkldident(mp, ehdr)) == 0) { printf("bad a.out module format\n"); return(EFTYPE); } archsw.arch_copyout(vp, &kident, sizeof(struct kld_module_identifier)); /* Name the module using the name from the KLD data */ if (mod_findmodule(kident.ki_name, NULL) != NULL) { printf("module '%s' already loaded\n", kident.ki_name); return(EPERM); } mp->m_name = strdup(kident.ki_name); /* Save the module identifier */ mod_addmetadata(mp, MODINFOMD_KLDIDENT, sizeof(struct kld_module_identifier), &kident); /* Look for dependancy data, add to metadata list */ if (kident.ki_ndeps > 0) { dsize = kident.ki_ndeps * kident.ki_depsize; kdeps = malloc(dsize); archsw.arch_copyout(AOUT_RELOC(mp, kident.ki_deps), kdeps, dsize); mod_addmetadata(mp, MODINFOMD_KLDDEP, dsize, kdeps); free(kdeps); } return(0); } #endif