Bootstrap updates.

- Move some startup code from MD to MI sections
 - Add a 'copyout' and some copyout-related functions.  These will be
   obsoleted when BTX is available for the 386 and the kernel load
   area becomes directly addressable.
 - Add the ability load an arbitrary file as a module, associating
   and arbitrary type string with it.  This can be used eg. for loading
   splash-screen images etc.
 - Add KLD module dependancy infrastructure.  We know how to look for
   dependancies inside KLD modules, how to resolve these dependancies
   and what to do if things go wrong.  Only works for a.out at the
   moment, due to lack of an MI ELF loader.  Attach KLD module information
   to loaded modules as metadata, but don't pass it to the kernel (it
   can find it itself).
 - Load a.out KLD modules on a page boundary.  Only pad the a.out BSS
   for the kernel, as it may want to throw symbols away.  (We might want
   to do this for KLD modules too.)
 - Allow commands to be hidden from the '?' display, to avoid cluttering
   it with things like 'echo'.  Add 'echo'.
 - Bring the 'prompt' command into line with the parser syntax.
 - Fix the verbose 'ls'; it was using an uninitialised stack variable.
 - Add a '-v' flag to 'lsmod' to have it display module metadata as well
   (not terribly useful for the average user)
 - Support a 'module searchpath' for required modules.
 - The bootstrap file on i386 is now called 'loader' to permit the
   /boot directory to use that name.
 - Discard the old i386 pread() function, as it's replaced by
   arch_readin()
This commit is contained in:
Mike Smith 1998-09-03 02:10:09 +00:00
parent 9de9848b61
commit 06b57b0e09
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=38764
17 changed files with 871 additions and 142 deletions

View File

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: main.c,v 1.2 1998/08/22 10:31:00 dfr Exp $
* $Id: main.c,v 1.3 1998/08/31 21:10:40 msmith Exp $
*/
@ -118,6 +118,7 @@ main(void)
archsw.arch_autoload = alpha_autoload;
archsw.arch_getdev = alpha_getdev;
archsw.arch_copyin = alpha_copyin;
archsw.arch_copyout = alpha_copyout;
archsw.arch_readin = alpha_readin;
/*
@ -128,15 +129,6 @@ main(void)
*/
open("/", O_RDONLY);
/*
* XXX should these be in the MI source?
*/
source("/boot/boot.config");
printf("\n");
autoboot(10, NULL); /* try to boot automatically */
printf("\nType '?' for a list of commands, 'help' for more detailed help.\n");
/* setenv("prompt", "$currdev>", 1); */
interact(); /* doesn't return */
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: alpha_copy.c,v 1.1 1998/08/31 21:10:40 msmith Exp $
*/
/*
* MD primitives supporting placement of module data
@ -41,6 +41,13 @@ alpha_copyin(void *src, vm_offset_t dest, size_t len)
return(len);
}
int
alpha_copyout(void *src, vm_offset_t dest, size_t len)
{
bcopy(src, dest, len);
return(len);
}
int
alpha_readin(int fd, vm_offset_t dest, size_t len)
{

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: bootstrap.h,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
* $Id: bootstrap.h,v 1.2 1998/08/31 21:10:42 msmith Exp $
*/
#include <sys/types.h>
@ -62,6 +62,8 @@ extern int autoboot(int delay, char *prompt);
/* misc.c */
extern char *unargv(int argc, char *argv[]);
extern size_t strlenout(vm_offset_t str);
extern char *strdupout(vm_offset_t str);
/*
* Modular console support.
@ -123,14 +125,16 @@ struct module_format
/* Load function must return EFTYPE if it can't handle the module supplied */
int (* l_load)(char *filename, vm_offset_t dest, struct loaded_module **result);
/* Only a loader that will load a kernel (first module) should have an exec handler */
int (* l_exec)(struct loaded_module *amp);
int (* l_exec)(struct loaded_module *mp);
};
extern struct module_format *module_formats[]; /* supplied by consumer */
extern struct loaded_module *loaded_modules;
extern int mod_load(char *name, int argc, char *argv[]);
extern int mod_loadobj(char *type, char *name);
extern struct loaded_module *mod_findmodule(char *name, char *type);
extern void mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p);
extern struct module_metadata *mod_findmetadata(struct loaded_module *mp, int type);
extern void mod_discard(struct loaded_module *mp);
/*
* Module information subtypes
@ -144,12 +148,18 @@ extern struct module_metadata *mod_findmetadata(struct loaded_module *mp, int ty
#define MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */
#define MODINFOMD_ELFHDR 0x0002 /* ELF header */
#define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */
/* MI module loaders */
extern int aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result);
extern int aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result);
extern vm_offset_t aout_findsym(char *name, struct loaded_module *mp);
/* extern int elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result); */
#define KLD_IDENT_SYMNAME "kld_identifier_"
#define MODINFOMD_KLDIDENT (MODINFOMD_NOCOPY | 0x4000)
#define MODINFOMD_KLDDEP (MODINFOMD_NOCOPY | 0x4001)
#if defined(__ELF__)
/*
@ -231,8 +241,36 @@ struct arch_switch
int (*arch_getdev)(void **dev, char *name, char **path);
/* Copy from local address space to module address space, similar to bcopy() */
int (*arch_copyin)(void *src, vm_offset_t dest, size_t len);
/* Copy to local address space from module address space, similar to bcopy() */
int (*arch_copyout)(vm_offset_t src, void *dest, size_t len);
/* Read from file to module address space, same semantics as read() */
int (*arch_readin)(int fd, vm_offset_t dest, size_t len);
};
extern struct arch_switch archsw;
/*
* XXX these belong in a system header
*/
#define KLD_NAMELEN 32
struct kld_module_dependancy
{
char kd_name[KLD_NAMELEN];
u_int32_t kd_version;
};
struct kld_module_identifier
{
u_int32_t ki_kldversion;
char ki_name[KLD_NAMELEN];
u_int32_t ki_version;
struct kld_module_dependancy *ki_deps;
int ki_ndeps;
size_t ki_depsize;
};
/*
* Use the depsize field in the identifier to correctly index a
* dependancy.
*/
#define KLD_GETDEP(ki, kd, n) (struct kld_module_dependancy *)((char *)(kd) + ((ki)->ki_depsize * (n)))

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: commands.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
*/
#include <stand.h>
@ -61,7 +61,7 @@ command_commandlist(int argc, char *argv[])
printf("Available commands:\n");
cmdp = (struct bootblk_command **)Xcommand_set.ls_items;
for (i = 0; i < Xcommand_set.ls_length; i++)
if (cmdp[i]->c_name != NULL)
if ((cmdp[i]->c_name != NULL) && (cmdp[i]->c_desc != NULL))
printf(" %-15s %s\n", cmdp[i]->c_name, cmdp[i]->c_desc);
return(CMD_OK);
}
@ -153,3 +153,38 @@ command_panic(int argc, char *argv[])
cp = unargv(argc - 1, argv + 1);
panic(cp);
}
COMMAND_SET(echo, "echo", NULL, command_echo);
static int
command_echo(int argc, char *argv[])
{
char *s;
int nl, ch;
nl = 0;
optind = 1;
while ((ch = getopt(argc, argv, "n")) != -1) {
switch(ch) {
case 'n':
nl = 1;
break;
case '?':
default:
/* getopt has already reported an error */
return(CMD_OK);
}
}
argv += (optind);
argc -= (optind);
s = unargv(argc, argv);
if (s != NULL) {
printf(s);
free(s);
}
if (!nl)
printf("\n");
return(CMD_OK);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: interp.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
* $Id: interp.c,v 1.2 1998/09/01 00:41:24 msmith Exp $
*/
/*
* Simple commandline interpreter, toplevel and misc.
@ -83,6 +83,24 @@ interact(void)
int argc;
char **argv;
/*
* Read our default configuration
*/
source("/boot/boot.conf");
printf("\n");
/*
* Before interacting, we might want to autoboot
*/
if (getenv("no_autoboot") == NULL)
autoboot(10, NULL); /* try to boot automatically */
/*
* 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();
@ -149,32 +167,29 @@ source(char *filename)
}
/*
* Emit the current prompt; support primitive embedding of
* environment variables.
* We're a little rude here, modifying the return from getenv().
* Emit the current prompt; use the same syntax as the parser
* for embedding environment variables.
*/
static void
prompt(void)
{
char *p, *cp, *ev, c;
char *p, *cp, *ev;
if ((p = getenv("prompt")) == NULL)
p = ">";
if ((cp = getenv("prompt")) == NULL)
cp = ">";
p = strdup(cp);
while (*p != 0) {
if (*p == '$') {
for (cp = p + 1; (*cp != 0) && isalpha(*cp); cp++)
if ((*p == '$') && (*(p+1) == '{')) {
for (cp = p + 2; (*cp != 0) && (*cp != '}'); cp++)
;
c = *cp;
*cp = 0;
ev = getenv(p + 1);
*cp = c;
ev = getenv(p + 2);
if (ev != NULL) {
if (ev != NULL)
printf(ev);
p = cp;
continue;
}
p = cp + 1;
continue;
}
putchar(*p++);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: aout_freebsd.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
* $Id: load_aout.c,v 1.1 1998/08/31 21:10:42 msmith Exp $
*/
#include <sys/param.h>
@ -33,10 +33,15 @@
#include <string.h>
#include <machine/bootinfo.h>
#include <stand.h>
#define _AOUT_INCLUDE_
#include <nlist.h>
#include <link.h>
#include "bootstrap.h"
static int aout_loadimage(int fd, vm_offset_t loadaddr, struct exec *ehdr);
static int aout_loadimage(int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel);
static vm_offset_t aout_findkldident(struct loaded_module *mp, struct exec *ehdr);
static int aout_fixupkldmod(struct loaded_module *mp, struct exec *ehdr);
char *aout_kerneltype = "a.out kernel";
char *aout_moduletype = "a.out module";
@ -49,12 +54,15 @@ char *aout_moduletype = "a.out module";
int
aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
{
struct loaded_module *mp;
struct loaded_module *mp, *kmp;
struct exec ehdr;
int fd;
vm_offset_t addr;
int err, kernel;
u_int pad;
mp = NULL;
/*
* Open the image, read and validate the a.out header
*/
@ -62,35 +70,42 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
return(EFTYPE);
if ((fd = open(filename, O_RDONLY)) == -1)
return(errno);
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
return(EFTYPE); /* could be EIO, but may be small file */
if (N_BADMAG(ehdr))
return(EFTYPE);
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()
*/
mp = mod_findmodule(NULL, NULL);
kmp = mod_findmodule(NULL, NULL);
if (N_GETFLAG(ehdr) == (EX_DYNAMIC | EX_PIC)) {
/* Looks like a kld module */
if (mp == NULL) {
if (kmp == NULL) {
printf("aout_loadmodule: can't load module before kernel\n");
return(EPERM);
err = EPERM;
goto oerr;
}
if (strcmp(aout_kerneltype, mp->m_type)) {
printf("out_loadmodule: can't load module with kernel type '%s'\n", mp->m_type);
return(EPERM);
if (strcmp(aout_kerneltype, kmp->m_type)) {
printf("out_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 (mp != NULL) {
if (kmp != NULL) {
printf("aout_loadmodule: kernel already loaded\n");
return(EPERM);
err = EPERM;
goto oerr;
}
/*
* Calculate destination address based on kernel entrypoint
@ -99,39 +114,56 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
dest = ehdr.a_entry & 0x100000;
if (dest == 0) {
printf("aout_loadmodule: not a kernel (maybe static binary?)\n");
return(EPERM);
err = EPERM;
goto oerr;
}
kernel = 1;
} else {
return(EFTYPE);
err = EFTYPE;
goto oerr;
}
/*
* Ok, we think we should handle this.
*/
mp = malloc(sizeof(struct loaded_module));
mp->m_name = strdup(filename); /* XXX should we prune the name? */
mp->m_name = kernel ? strdup(filename) : NULL; /* XXX should we prune the name? */
mp->m_type = strdup(kernel ? aout_kerneltype : aout_moduletype);
mp->m_args = NULL; /* XXX should we put the bootstrap args here and parse later? */
mp->m_args = NULL; /* filled in by parent */
mp->m_metadata = NULL;
mp->m_addr = addr = dest;
/* 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 */
printf("%s at 0x%x\n", filename, addr);
mp->m_size = aout_loadimage(fd, addr, &ehdr);
mp->m_size = aout_loadimage(fd, addr, &ehdr, kernel);
if (mp->m_size == 0)
goto ioerr;
/* Handle KLD module data */
if (!kernel && ((err = aout_fixupkldmod(mp, &ehdr)) != 0))
goto oerr;
/* save exec header as metadata */
mod_addmetadata(mp, MODINFOMD_AOUTEXEC, sizeof(struct exec), &ehdr);
/* Load OK, return module pointer */
*result = (struct loaded_module *)mp;
return(0);
err = 0;
goto out;
ioerr:
err = EIO;
close(fd);
oerr:
mod_discard(mp);
free(mp);
out:
close(fd);
return(err);
}
@ -143,17 +175,17 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result)
* align the symbol table.
*/
static int
aout_loadimage(int fd, vm_offset_t loadaddr, struct exec *ehdr)
aout_loadimage(int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel)
{
u_int pad;
vm_offset_t addr;
int ss;
addr = loadaddr;
lseek(fd, N_TXTOFF(*ehdr), SEEK_SET);
/* text segment */
printf("text=0x%lx ", ehdr->a_text);
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;
@ -164,24 +196,23 @@ aout_loadimage(int fd, vm_offset_t loadaddr, struct exec *ehdr)
return(0);
addr += ehdr->a_data;
/* skip the BSS */
/* 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;
/* pad to a page boundary */
pad = (u_int)addr & PAGE_MASK;
if (pad != 0) {
pad = PAGE_SIZE - pad;
addr += pad;
ehdr->a_bss += pad;
}
/* symbol table size */
archsw.arch_copyin(&ehdr->a_syms, addr, sizeof(ehdr->a_syms));
addr += sizeof(ehdr->a_syms);
/* symbol table */
printf("symbols=[0x%x+0x%x+0x%lx", pad, sizeof(ehdr->a_syms), ehdr->a_syms);
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;
@ -200,3 +231,230 @@ aout_loadimage(int fd, vm_offset_t loadaddr, struct exec *ehdr)
return(addr - loadaddr);
}
#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_<something>. 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);
}
#if 0
/************************************************************/
/* XXX Arbitrary symbol lookup - unused at this point XXX */
/* */
/* Code heavily borrowed from kern/link_aout.c (c) DFR */
/************************************************************/
static long
symbol_hash_value(struct _dynamic *dynamic, const char* name)
{
long hashval;
const char* p;
hashval = '_'; /* fake a starting '_' for C symbols */
for (p = name; *p; p++)
hashval = (hashval << 1) + *p;
return (hashval & 0x7fffffff) % LD_BUCKETS(dynamic);
}
/*
* Locate the symbol (name) in the a.out object associated with (mp),
* return a vm_offset_t containing the value of the symbol.
*/
static vm_offset_t
aout_findsym(char *name, struct loaded_module *mp)
{
struct module_metadata *md;
struct exec *ehdr;
struct _dynamic dynamic;
struct section_dispatch_table sdt;
vm_offset_t hashbase, symbolbase, stringbase, hp, np, cp;
struct rrs_hash hash;
struct nzlist nzl;
char *symbol, *asymbol; /* XXX symbol name limit? */
long hashval;
vm_offset_t result;
symbol = NULL;
asymbol = NULL;
result = 0;
/* Find the exec header */
if ((md = mod_findmetadata(mp, MODINFOMD_AOUTEXEC)) == NULL)
goto out;
ehdr = (struct exec *)md->md_data;
/* 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) ||
(LD_BUCKETS(&dynamic) == 0))
goto out;
hashbase = AOUT_RELOC(mp, LD_HASH(&dynamic));
symbolbase = AOUT_RELOC(mp, LD_SYMBOL(&dynamic));
stringbase = AOUT_RELOC(mp, LD_STRINGS(&dynamic));
restart:
hashval = symbol_hash_value(&dynamic, name);
hp = hashbase + (hashval * sizeof(struct rrs_hash));
archsw.arch_copyout(hp, &hash, sizeof(struct rrs_hash));
if (hash.rh_symbolnum == -1)
goto out;
while (hp) {
np = symbolbase + (hash.rh_symbolnum * sizeof(struct nzlist));
archsw.arch_copyout(np, &nzl, sizeof(struct nzlist));
cp = stringbase + nzl.nz_strx;
if (symbol != NULL)
free(symbol);
symbol = strdupout(cp);
/*
* Note: we fake the leading '_' for C symbols.
*/
if (symbol[0] == '_' && !strcmp(symbol + 1, name))
break;
if (hash.rh_next == 0) {
hp = 0;
} else {
hp = hashbase + (hash.rh_next * sizeof(struct rrs_hash));
archsw.arch_copyout(hp, &hash, sizeof(struct rrs_hash));
}
}
/* Not found. */
if (hp == 0)
goto out;
/*
* Check for an aliased symbol, whatever that is.
*/
if (nzl.nz_type == N_INDR+N_EXT) {
np += sizeof(struct nzlist);
archsw.arch_copyout(np, &nzl, sizeof(struct nzlist));
asymbol = strdupout(stringbase + nzl.nz_strx + 1); /* +1 for '_' */
goto restart;
}
/*
* Check this is an actual definition of the symbol.
*/
if (nzl.nz_value == 0)
goto out;
if (nzl.nz_type == N_UNDF+N_EXT && nzl.nz_value != 0)
if (nzl.nz_other == AUX_FUNC)
/* weak function */
goto out;
/* Return a vm_offset_t pointing to the object itself */
result = AOUT_RELOC(mp, nzl.nz_value);
out:
if (symbol)
free(symbol);
if (asymbol)
free(asymbol);
return(result);
}
#endif

View File

@ -1,5 +1,5 @@
/*
* $Id$
* $Id: ls.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
* From: $NetBSD: ls.c,v 1.3 1997/06/13 13:48:47 drochner Exp $
*/
@ -57,9 +57,8 @@ command_ls(int argc, char *argv[])
int fd;
struct stat sb;
size_t size;
char dirbuf[DIRBLKSIZ];
char pathbuf[128]; /* XXX path length constant? */
char buf[128]; /* must be long enough for dir entry! */
static char dirbuf[DIRBLKSIZ];
static char buf[128]; /* must be long enough for full pathname */
char *path;
int result, ch;
#ifdef VERBOSE_LS
@ -138,10 +137,12 @@ command_ls(int argc, char *argv[])
if (verbose) {
/* stat the file, if possible */
sb.st_size = 0;
sprintf(buf, "%s/%s", pathbuf, dp->d_name);
sprintf(buf, "%s/%s", path, dp->d_name);
/* ignore return */
if (stat(buf, &sb))
if (stat(buf, &sb)) {
printf("stat(%s) failed: %s\n", buf, strerror(errno));
sb.st_size = -1;
}
sprintf(buf, " %c %8d %s\n", typestr[dp->d_type], (int)sb.st_size, dp->d_name);
#endif
} else

View File

@ -23,11 +23,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: misc.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
*/
#include <string.h>
#include <stand.h>
#include <bootstrap.h>
/*
* Concatenate the (argc) elements of (argv) into a single string, and return
@ -53,3 +54,36 @@ unargv(int argc, char *argv[])
return(cp);
}
/*
* Get the length of a string in kernel space
*/
size_t
strlenout(vm_offset_t src)
{
char c;
size_t len;
for (len = 0; ; len++) {
archsw.arch_copyout(src++, &c, 1);
if (c == 0)
break;
}
return(len);
}
/*
* Make a duplicate copy of a string in kernel space
*/
char *
strdupout(vm_offset_t str)
{
char *result, *cp;
result = malloc(strlenout(str) + 1);
for (cp = result; ;cp++) {
archsw.arch_copyout(str++, cp, 1);
if (*cp == 0)
break;
}
return(result);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: module.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
* $Id: module.c,v 1.2 1998/08/31 21:10:42 msmith Exp $
*/
/*
@ -38,16 +38,68 @@
#include "bootstrap.h"
static struct loaded_module *mod_loadmodule(char *name, int argc, char *argv[]);
static char *mod_searchdep(struct loaded_module *mp);
static char *mod_searchmodule(char *name);
static void mod_append(struct loaded_module *mp);
/* XXX load address should be tweaked by first module loaded (kernel) */
static vm_offset_t loadaddr = 0;
struct loaded_module *loaded_modules = NULL;
/*
* load an object, either a disk file or code module.
*
* To load a file, the syntax is:
*
* load -t <type> <path>
*
* code modules are loaded as:
*
* load <path> <options>
*/
COMMAND_SET(load, "load", "load a kernel or module", command_load);
static int
command_load(int argc, char *argv[])
{
char *typestr;
int dofile, ch;
dofile = 0;
optind = 1;
typestr = NULL;
while ((ch = getopt(argc, argv, "t:")) != -1) {
switch(ch) {
case 't':
typestr = optarg;
dofile = 1;
break;
case '?':
default:
/* getopt has already reported an error */
return(CMD_OK);
}
}
argv += (optind - 1);
argc -= (optind - 1);
/*
* Request to load a raw file?
*/
if (dofile) {
if ((typestr == NULL) || (*typestr == 0)) {
command_errmsg = "invalid load type";
return(CMD_ERROR);
}
return(mod_loadobj(typestr, argv[1]));
}
/*
* Looks like a request for a module.
*/
return(mod_load(argv[1], argc - 2, argv + 2));
}
@ -57,21 +109,11 @@ static int
command_unload(int argc, char *argv[])
{
struct loaded_module *mp;
struct module_metadata *md;
while (loaded_modules != NULL) {
mp = loaded_modules;
loaded_modules = loaded_modules->m_next;
while (mp->m_metadata != NULL) {
md = mp->m_metadata;
mp->m_metadata = mp->m_metadata->md_next;
free(md);
}
free(mp->m_name);
free(mp->m_type);
if (mp->m_args != NULL)
free(mp->m_args);
free(mp);
mod_discard(mp);
}
loadaddr = 0;
return(CMD_OK);
@ -83,8 +125,24 @@ static int
command_lsmod(int argc, char *argv[])
{
struct loaded_module *am;
struct module_metadata *md;
char lbuf[80];
int ch, verbose;
verbose = 0;
optind = 1;
while ((ch = getopt(argc, argv, "v")) != -1) {
switch(ch) {
case 'v':
verbose = 1;
break;
case '?':
default:
/* getopt has already reported an error */
return(CMD_OK);
}
}
pager_open();
for (am = loaded_modules; (am != NULL); am = am->m_next) {
sprintf(lbuf, " %x: %s (%s, 0x%x)\n",
@ -95,20 +153,141 @@ command_lsmod(int argc, char *argv[])
pager_output(am->m_args);
pager_output("\n");
}
if (verbose)
/* XXX could add some formatting smarts here to display some better */
for (md = am->m_metadata; md != NULL; md = md->md_next) {
sprintf(lbuf, " 0x%04x, 0x%x\n", md->md_type, md->md_size);
pager_output(lbuf);
}
}
pager_close();
return(CMD_OK);
}
/*
* We've been asked to load (name) and give it (argc),(argv).
* Start by trying to load it, and then attempt to load all of its
* dependancies. If we fail at any point, throw them all away and
* fail the entire load.
*
* XXX if a depended-on module requires arguments, it must be loaded
* explicitly first.
*/
int
mod_load(char *name, int argc, char *argv[])
{
struct loaded_module *am, *cm;
int i, err;
struct loaded_module *last_mod, *base_mod, *mp;
char *dep_name;
/* remember previous last module on chain */
for (last_mod = loaded_modules;
(last_mod != NULL) && (last_mod->m_next != NULL);
last_mod = last_mod->m_next)
;
for (i = 0, am = NULL; (module_formats[i] != NULL) && (am == NULL); i++) {
/* XXX call searchmodule() to search for module (name) */
if ((err = (module_formats[i]->l_load)(name, loadaddr, &am)) != 0) {
/*
* Load the first module; note that it's the only one that gets
* arguments explicitly.
*/
if ((base_mod = mod_loadmodule(name, argc, argv)) == NULL)
return(CMD_ERROR);
/*
* Look for dependancies.
*/
while ((dep_name = mod_searchdep(base_mod)) != NULL) {
printf("loading required module '%s'\n", dep_name);
if ((mp = mod_loadmodule(dep_name, 0, NULL)) == NULL) {
/* Load failed; discard everything */
while (base_mod != NULL) {
mp = base_mod;
base_mod = base_mod->m_next;
mod_discard(mp);
}
last_mod->m_next = NULL;
loadaddr = last_mod->m_addr + last_mod->m_size;
/* error message already set by mod_loadmodule */
return(CMD_ERROR);
}
}
return(CMD_OK);
}
/*
* We've been asked to load (name) as (type), so just suck it in,
* no arguments or anything.
*/
int
mod_loadobj(char *type, char *name)
{
struct loaded_module *mp;
char *cp;
int fd, got;
vm_offset_t laddr;
/* We can't load first */
if ((mod_findmodule(NULL, NULL)) == NULL) {
command_errmsg = "can't load file before kernel";
return(CMD_ERROR);
}
/* Try to come up with a fully-qualified name if we don't have one */
if ((cp = mod_searchmodule(name)) != NULL)
name = cp;
if ((fd = open(name, O_RDONLY)) < 0) {
sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
return(CMD_ERROR);
}
laddr = loadaddr;
for (;;) {
/* read in 4k chunks; size is not really important */
got = archsw.arch_readin(fd, laddr, 4096);
if (got == 0) /* end of file */
break;
if (got < 0) { /* error */
sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno));
return(CMD_ERROR);
}
laddr += got;
}
/* Looks OK so far; create & populate control structure */
mp = malloc(sizeof(struct loaded_module));
mp->m_name = strdup(name);
mp->m_type = strdup(type);
mp->m_args = NULL;
mp->m_metadata = NULL;
mp->m_loader = -1;
mp->m_addr = loadaddr;
mp->m_size = laddr - loadaddr;
/* recognise space consumption */
loadaddr = laddr;
/* Add to the list of loaded modules */
mod_append(mp);
return(CMD_OK);
}
/*
* Load the module (name), pass it (argc),(argv).
* Don't do any dependancy checking.
*/
static struct loaded_module *
mod_loadmodule(char *name, int argc, char *argv[])
{
struct loaded_module *mp;
int i, err;
char *cp;
/* Try to come up with a fully-qualified name if we don't have one */
if ((cp = mod_searchmodule(name)) != NULL)
name = cp;
err = 0;
for (i = 0, mp = NULL; (module_formats[i] != NULL) && (mp == NULL); i++) {
if ((err = (module_formats[i]->l_load)(name, loadaddr, &mp)) != 0) {
/* Unknown to this handler? */
if (err == EFTYPE)
@ -116,34 +295,87 @@ mod_load(char *name, int argc, char *argv[])
/* Fatal error */
sprintf(command_errbuf, "can't load module '%s': %s", name, strerror(err));
return(CMD_ERROR);
return(NULL);
} else {
/* Load was OK, set args */
mp->m_args = unargv(argc, argv);
/* where can we put the next one? */
loadaddr = mp->m_addr + mp->m_size;
/* remember the loader */
am->m_loader = i;
mp->m_loader = i;
/* Add to the list of loaded modules */
mod_append(mp);
break;
}
}
if (am == NULL) {
sprintf(command_errbuf, "can't work out what to do with '%s'", name);
return(CMD_ERROR);
}
/* where can we put the next one? */
loadaddr = am->m_addr + am->m_size;
/* Load was OK, set args */
am->m_args = unargv(argc, argv);
/* Append to list of loaded modules */
am->m_next = NULL;
if (loaded_modules == NULL) {
loaded_modules = am;
} else {
for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next)
;
cm->m_next = am;
}
return(CMD_OK);
if (err == EFTYPE)
sprintf(command_errbuf, "don't know how to load module '%s'", name);
return(mp);
}
/*
* Search the modules from (mp) onwards, and return the name of the
* first unresolved dependancy, or NULL if none were found.
*/
static char *
mod_searchdep(struct loaded_module *mp)
{
struct kld_module_identifier *ident, *dident;
struct kld_module_dependancy *deps, *dp;
struct module_metadata *md;
struct loaded_module *dmp;
int dindex;
for (; mp != NULL; mp = mp->m_next) {
/*
* Get KLD module data
*/
ident = NULL;
deps = NULL;
if ((md = mod_findmetadata(mp, MODINFOMD_KLDIDENT)) != NULL)
ident = (struct kld_module_identifier *)md->md_data;
if ((md = mod_findmetadata(mp, MODINFOMD_KLDDEP)) != NULL)
deps = (struct kld_module_dependancy *)md->md_data;
/*
* Both must exist for this module to depend on anything
*/
if ((ident != NULL) && (deps != NULL)) {
/* Iterate over dependancies */
for (dindex = 0; dindex < ident->ki_ndeps; dindex++) {
dp = KLD_GETDEP(ident, deps, dindex);
/*
* Look for a module matching the dependancy; if we don't have it,
* we need it.
*/
if ((dmp = mod_findmodule(dp->kd_name, NULL)) == NULL)
return(dp->kd_name);
/* Version check */
if ((md = mod_findmetadata(dmp, MODINFOMD_KLDIDENT)) != NULL) {
dident = (struct kld_module_identifier *)md->md_data;
if (dp->kd_version != dident->ki_version)
printf("module '%s' requires '%s' version %d, but version %d is loaded\n",
mp->m_name, dp->kd_name, dp->kd_version, dident->ki_version);
}
}
}
}
return(NULL);
}
/*
* Find a module matching (name) and (type).
* NULL may be passed as a wildcard to either.
*/
struct loaded_module *
mod_findmodule(char *name, char *type)
{
@ -157,6 +389,10 @@ mod_findmodule(char *name, char *type)
return(mp);
}
/*
* Make a copy of (size) bytes of data from (p), and associate them as
* metadata of (type) to the module (mp).
*/
void
mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p)
{
@ -170,6 +406,10 @@ mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p)
mp->m_metadata = md;
}
/*
* Find a metadata object of (type) associated with the module
* (mp)
*/
struct module_metadata *
mod_findmetadata(struct loaded_module *mp, int type)
{
@ -180,3 +420,101 @@ mod_findmetadata(struct loaded_module *mp, int type)
break;
return(md);
}
/*
* Attempt to locate a kernel module file for the module (name).
* If (name) is qualified in any way, we simply check it and
* return it or NULL. If it is not qualified, then we attempt
* to construct a path using entries in the environment variable
* module_path.
*
* The path we return a pointer to need never be freed, as we manage
* it internally.
*/
static char *
mod_searchmodule(char *name)
{
static char *result = NULL;
static char *defpath = "/boot", *path;
char *cp, *sp;
struct stat sb;
/* Don't look for nothing */
if ((name == NULL) || (*name == 0))
return(name);
/*
* See if there's a device on the front, or a directory name.
*/
archsw.arch_getdev(NULL, name, &cp);
if ((cp != name) || (strchr(name, '/') != NULL)) {
/* Qualified, so just see if it exists */
if (stat(name, &sb) == 0)
return(name);
return(NULL);
}
/*
* Get the module path
*/
if ((cp = getenv("module_path")) == NULL)
cp = defpath;
sp = path = strdup(cp);
/*
* Traverse the path, splitting off ';'-delimited components.
*/
if (result != NULL)
free(result);
while((cp = strsep(&path, ";")) != NULL) {
result = malloc(strlen(cp) + strlen(name) + 2);
sprintf(result, "%s/%s", cp, name);
if (stat(result, &sb) == 0)
break;
free(result);
result = NULL;
}
free(sp);
return(result);
}
/*
* Throw a module away
*/
void
mod_discard(struct loaded_module *mp)
{
struct module_metadata *md;
while (mp->m_metadata != NULL) {
md = mp->m_metadata;
mp->m_metadata = mp->m_metadata->md_next;
free(md);
}
if (mp->m_name != NULL)
free(mp->m_name);
if (mp->m_type != NULL)
free(mp->m_type);
if (mp->m_args != NULL)
free(mp->m_args);
free(mp);
}
/*
* Add a module to the chain
*/
static void
mod_append(struct loaded_module *mp)
{
struct loaded_module *cm;
/* Append to list of loaded modules */
mp->m_next = NULL;
if (loaded_modules == NULL) {
loaded_modules = mp;
} else {
for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next)
;
cm->m_next = mp;
}
}

View File

@ -59,7 +59,7 @@
#include "bbinfo.h"
#define DEFBBLKNAME "boot"
#define DEFBBLKNAME "loader"
struct fraglist *fraglist;

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: bootinfo.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
*/
#include <sys/reboot.h>
@ -191,7 +191,8 @@ bi_copymodules(vm_offset_t addr)
MOD_ADDR(addr, mp->m_addr);
MOD_SIZE(addr, mp->m_size);
for (md = mp->m_metadata; md != NULL; md = md->md_next)
MOD_METADATA(addr, md);
if (!(md->md_type & MODINFOMD_NOCOPY))
MOD_METADATA(addr, md);
}
return(addr);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: bootinfo.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
*/
#include <sys/reboot.h>
@ -191,7 +191,8 @@ bi_copymodules(vm_offset_t addr)
MOD_ADDR(addr, mp->m_addr);
MOD_SIZE(addr, mp->m_size);
for (md = mp->m_metadata; md != NULL; md = md->md_next)
MOD_METADATA(addr, md);
if (!(md->md_type & MODINFOMD_NOCOPY))
MOD_METADATA(addr, md);
}
return(addr);
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: bootinfo.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
*/
#include <sys/reboot.h>
@ -191,7 +191,8 @@ bi_copymodules(vm_offset_t addr)
MOD_ADDR(addr, mp->m_addr);
MOD_SIZE(addr, mp->m_size);
for (md = mp->m_metadata; md != NULL; md = md->md_next)
MOD_METADATA(addr, md);
if (!(md->md_type & MODINFOMD_NOCOPY))
MOD_METADATA(addr, md);
}
return(addr);
}

View File

@ -19,6 +19,14 @@ i386_copyin(void *src, vm_offset_t dest, size_t len)
return(len);
}
int
i386_copyout(vm_offset_t src, void *dest, size_t len)
{
pvbcopy(src, dest, len);
return(len);
}
int
i386_readin(int fd, vm_offset_t dest, size_t len)
{

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: libi386.h,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
* $Id: libi386.h,v 1.2 1998/08/31 21:10:43 msmith Exp $
*/
@ -64,20 +64,18 @@ extern struct devdesc currdev; /* our current device */
extern struct devsw biosdisk;
/* from crt module */
extern void vpbcopy(void*, vm_offset_t, int);
extern void pvbcopy(vm_offset_t, void*, int);
extern void pbzero(vm_offset_t, int);
extern vm_offset_t vtophys(void*);
extern void vpbcopy(void *src, vm_offset_t dest, size_t size);
extern void pvbcopy(vm_offset_t src, void *dest, size_t size);
extern void pbzero(vm_offset_t dest, size_t size);
extern vm_offset_t vtophys(void *addr);
extern int i386_copyin(void *src, vm_offset_t dest, size_t len);
extern int i386_copyout(vm_offset_t src, void *dest, size_t len);
extern int i386_readin(int fd, vm_offset_t dest, size_t len);
/* XXX pread deprecated */
extern int pread(int, vm_offset_t, int);
extern void startprog(vm_offset_t entry, int argc, u_int32_t *argv, vm_offset_t stack);
extern void startprog(vm_offset_t, int, u_int32_t *, vm_offset_t);
extern void delay(int);
extern void delay(int delay);
extern int getbasemem(void);
extern int getextmem(void);

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: main.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $
* $Id: main.c,v 1.2 1998/08/31 21:10:43 msmith Exp $
*/
/*
@ -102,19 +102,14 @@ main(void)
archsw.arch_autoload = i386_autoload;
archsw.arch_getdev = i386_getdev;
archsw.arch_copyin = i386_copyin;
archsw.arch_copyout = i386_copyout;
archsw.arch_readin = i386_readin;
/*
* XXX should these be in the MI source?
*/
source("/boot/boot.conf");
#if 0
legacy_config(); /* read old /boot.config file */
#endif
printf("\n");
autoboot(10, NULL); /* try to boot automatically */
printf("\nType '?' for a list of commands, 'help' for more detailed help.\n");
setenv("prompt", "$currdev>", 1);
interact(); /* doesn't return */
}

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id$
* $Id: alpha_copy.c,v 1.1 1998/08/31 21:10:40 msmith Exp $
*/
/*
* MD primitives supporting placement of module data
@ -41,6 +41,13 @@ alpha_copyin(void *src, vm_offset_t dest, size_t len)
return(len);
}
int
alpha_copyout(void *src, vm_offset_t dest, size_t len)
{
bcopy(src, dest, len);
return(len);
}
int
alpha_readin(int fd, vm_offset_t dest, size_t len)
{