diff options
author | bp <bp@FreeBSD.org> | 2000-05-01 17:41:25 +0000 |
---|---|---|
committer | bp <bp@FreeBSD.org> | 2000-05-01 17:41:25 +0000 |
commit | 816e92565a65b81ec26724758fea6f694964d18f (patch) | |
tree | 1dc1dbf863d6b27d97804bdaca0c1d05f196c481 /sys/boot/common | |
parent | 222439bc50eba6251adfdfbf06fc7474d33911ad (diff) | |
download | FreeBSD-src-816e92565a65b81ec26724758fea6f694964d18f.zip FreeBSD-src-816e92565a65b81ec26724758fea6f694964d18f.tar.gz |
Update loader logic to distinguish modules vs. files.
Add support for module metadata. The old way of dependancy
handling will be supported for a while.
Reviewed by: peter
Diffstat (limited to 'sys/boot/common')
-rw-r--r-- | sys/boot/common/boot.c | 16 | ||||
-rw-r--r-- | sys/boot/common/bootstrap.h | 71 | ||||
-rw-r--r-- | sys/boot/common/load_aout.c | 60 | ||||
-rw-r--r-- | sys/boot/common/load_elf.c | 338 | ||||
-rw-r--r-- | sys/boot/common/module.c | 463 | ||||
-rw-r--r-- | sys/boot/common/pnp.c | 4 |
6 files changed, 601 insertions, 351 deletions
diff --git a/sys/boot/common/boot.c b/sys/boot/common/boot.c index 4fded2c..e4d0583 100644 --- a/sys/boot/common/boot.c +++ b/sys/boot/common/boot.c @@ -50,7 +50,7 @@ COMMAND_SET(boot, "boot", "boot a file or loaded kernel", command_boot); static int command_boot(int argc, char *argv[]) { - struct loaded_module *km; + struct preloaded_file *fp; char *cp; int try; int i; @@ -61,7 +61,7 @@ command_boot(int argc, char *argv[]) if ((argc > 1) && (argv[1][0] != '-')) { /* XXX maybe we should discard everything and start again? */ - if (mod_findmodule(NULL, NULL) != NULL) { + if (file_findfile(NULL, NULL) != NULL) { sprintf(command_errbuf, "can't boot '%s', kernel module already loaded", argv[1]); return(CMD_ERROR); } @@ -76,7 +76,7 @@ command_boot(int argc, char *argv[]) /* * See if there is a kernel module already loaded */ - if (mod_findmodule(NULL, NULL) == NULL) { + if (file_findfile(NULL, NULL) == NULL) { for (try = 0; (cp = getbootfile(try)) != NULL; try++) { if (mod_load(cp, argc - 1, argv + 1) != 0) { printf("can't load '%s'\n", cp); @@ -91,7 +91,7 @@ command_boot(int argc, char *argv[]) /* * Loaded anything yet? */ - if ((km = mod_findmodule(NULL, NULL)) == NULL) { + if ((fp = file_findfile(NULL, NULL)) == NULL) { command_errmsg = "no bootable kernel"; return(CMD_ERROR); } @@ -101,9 +101,9 @@ command_boot(int argc, char *argv[]) * XXX should we merge arguments? Hard to DWIM. */ if (argc > 1) { - if (km->m_args != NULL) - free(km->m_args); - km->m_args = unargv(argc - 1, argv + 1); + if (fp->f_args != NULL) + free(fp->f_args); + fp->f_args = unargv(argc - 1, argv + 1); } /* Hook for platform-specific autoloading of modules */ @@ -116,7 +116,7 @@ command_boot(int argc, char *argv[]) (devsw[i]->dv_cleanup)(); /* Call the exec handler from the loader matching the kernel */ - module_formats[km->m_loader]->l_exec(km); + file_formats[fp->f_loader]->l_exec(fp); return(CMD_ERROR); } diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index c614335..4c38154 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -153,62 +153,79 @@ extern char *pnp_eisaformat(u_int8_t *data); extern int isapnp_readport; /* - * Module metadata header. + * Preloaded file metadata header. * * Metadata are allocated on our heap, and copied into kernel space * before executing the kernel. */ -struct module_metadata +struct file_metadata { size_t md_size; u_int16_t md_type; - struct module_metadata *md_next; + struct file_metadata *md_next; char md_data[0]; /* data are immediately appended */ }; +struct preloaded_file; + +struct kernel_module +{ + char *m_name; /* module name */ +/* char *m_args;*/ /* arguments for the module */ + struct preloaded_file *m_fp; + struct kernel_module *m_next; +}; + /* - * Loaded module information. + * Preloaded file information. Depending on type, file can contain + * additional units called 'modules'. * - * At least one module (the kernel) must be loaded in order to boot. + * At least one file (the kernel) must be loaded in order to boot. * The kernel is always loaded first. * * String fields (m_name, m_type) should be dynamically allocated. */ -struct loaded_module +struct preloaded_file { - char *m_name; /* module name */ - char *m_type; /* verbose module type, eg 'ELF kernel', 'pnptable', etc. */ - char *m_args; /* arguments for the module */ - struct module_metadata *m_metadata; /* metadata that will be placed in the module directory */ - int m_loader; /* index of the loader that read the file */ - vm_offset_t m_addr; /* load address */ - size_t m_size; /* module size */ - struct loaded_module *m_next; /* next module */ + char *f_name; /* file name */ + char *f_type; /* verbose file type, eg 'ELF kernel', 'pnptable', etc. */ + char *f_args; /* arguments for the file */ + struct file_metadata *f_metadata; /* metadata that will be placed in the module directory */ + int f_loader; /* index of the loader that read the file */ + vm_offset_t f_addr; /* load address */ + size_t f_size; /* file size */ + struct kernel_module *f_modules; /* list of modules if any */ + struct preloaded_file *f_next; /* next file */ }; -struct module_format +struct file_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); + int (* l_load)(char *filename, vm_offset_t dest, struct preloaded_file **result); /* Only a loader that will load a kernel (first module) should have an exec handler */ - int (* l_exec)(struct loaded_module *mp); + int (* l_exec)(struct preloaded_file *mp); }; -extern struct module_format *module_formats[]; /* supplied by consumer */ -extern struct loaded_module *loaded_modules; + +extern struct file_format *file_formats[]; /* supplied by consumer */ +extern struct preloaded_file *preloaded_files; + 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); -extern struct loaded_module *mod_allocmodule(void); + +struct preloaded_file *file_alloc(void); +struct preloaded_file *file_findfile(char *name, char *type); +struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type); +void file_discard(struct preloaded_file *fp); +void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); +int file_addmodule(struct preloaded_file *fp, char *modname, + struct kernel_module **newmp); /* MI module loaders */ -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 aout_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result); +extern vm_offset_t aout_findsym(char *name, struct preloaded_file *fp); -extern int elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result); +extern int elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result); #ifndef NEW_LINKER_SET #include <sys/linker_set.h> diff --git a/sys/boot/common/load_aout.c b/sys/boot/common/load_aout.c index 4384ac9..52315f5 100644 --- a/sys/boot/common/load_aout.c +++ b/sys/boot/common/load_aout.c @@ -40,11 +40,11 @@ #include "bootstrap.h" -static int aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel); +static int aout_loadimage(struct preloaded_file *fp, 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); +static vm_offset_t aout_findkldident(struct preloaded_file *fp, struct exec *ehdr); +static int aout_fixupkldmod(struct preloaded_file *fp, struct exec *ehdr); #endif char *aout_kerneltype = "a.out kernel"; @@ -56,9 +56,9 @@ char *aout_moduletype = "a.out module"; * will be saved in (result). */ int -aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) +aout_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result) { - struct loaded_module *mp, *kmp; + struct preloaded_file *fp, *kfp; struct exec ehdr; int fd; vm_offset_t addr; @@ -66,7 +66,7 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) u_int pad; char *s; - mp = NULL; + fp = NULL; /* * Open the image, read and validate the a.out header @@ -89,16 +89,16 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) * * XXX should check N_GETMID() */ - kmp = mod_findmodule(NULL, NULL); + kfp = file_findfile(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"); + if (kfp == NULL) { + printf("aout_loadfile: 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); + if (strcmp(aout_kerneltype, kfp->f_type)) { + printf("aout_loadfile: can't load module with kernel type '%s'\n", kfp->f_type); err = EPERM; goto oerr; } @@ -107,8 +107,8 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) } else if (N_GETFLAG(ehdr) == 0) { /* Looks like a kernel */ - if (kmp != NULL) { - printf("aout_loadmodule: kernel already loaded\n"); + if (kfp != NULL) { + printf("aout_loadfile: kernel already loaded\n"); err = EPERM; goto oerr; } @@ -118,7 +118,7 @@ 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"); + printf("aout_loadfile: not a kernel (maybe static binary?)\n"); err = EPERM; goto oerr; } @@ -131,15 +131,15 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) /* * Ok, we think we should handle this. */ - mp = mod_allocmodule(); + fp = file_alloc(); if (kernel) setenv("kernelname", filename, 1); s = strrchr(filename, '/'); if (s) - mp->m_name = strdup(s + 1); + fp->f_name = strdup(s + 1); else - mp->m_name = strdup(filename); - mp->m_type = strdup(kernel ? aout_kerneltype : aout_moduletype); + fp->f_name = strdup(filename); + fp->f_type = strdup(kernel ? aout_kerneltype : aout_moduletype); /* Page-align the load address */ addr = dest; @@ -148,32 +148,32 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) pad = PAGE_SIZE - pad; addr += pad; } - mp->m_addr = addr; /* save the aligned load address */ + fp->f_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) + fp->f_size = aout_loadimage(fp, fd, addr, &ehdr, kernel); + if (fp->f_size == 0) goto ioerr; #if 0 /* Handle KLD module data */ - if (!kernel && ((err = aout_fixupkldmod(mp, &ehdr)) != 0)) + if (!kernel && ((err = aout_fixupkldmod(fp, &ehdr)) != 0)) goto oerr; #endif /* save exec header as metadata */ - mod_addmetadata(mp, MODINFOMD_AOUTEXEC, sizeof(struct exec), &ehdr); + file_addmetadata(fp, MODINFOMD_AOUTEXEC, sizeof(struct exec), &ehdr); /* Load OK, return module pointer */ - *result = (struct loaded_module *)mp; + *result = fp; err = 0; goto out; ioerr: err = EIO; oerr: - mod_discard(mp); + file_discard(fp); out: close(fd); return(err); @@ -187,7 +187,7 @@ aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) * align the symbol table. */ static int -aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel) +aout_loadimage(struct preloaded_file *fp, int fd, vm_offset_t loadaddr, struct exec *ehdr, int kernel) { u_int pad; vm_offset_t addr; @@ -227,7 +227,7 @@ aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct ex addr += sizeof(ehdr->a_syms); /* symbol table */ - printf("symbols=[0x%lx+0x%lx", 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; @@ -237,14 +237,14 @@ aout_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, struct ex archsw.arch_copyin(&ss, addr, sizeof(ss)); addr += sizeof(ss); ss -= sizeof(ss); - printf("+0x%lx+0x%x]", sizeof(ss), ss); + printf("+0x%x+0x%x]", sizeof(ss), ss); if (archsw.arch_readin(fd, addr, ss) != ss) return(0); addr += ss; esym = addr; - mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym); - mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym); + file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym); + file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym); } else { printf("symbols=[none]"); } diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c index 8fbcf19..239d431 100644 --- a/sys/boot/common/load_elf.c +++ b/sys/boot/common/load_elf.c @@ -31,6 +31,7 @@ #include <sys/exec.h> #include <sys/reboot.h> #include <sys/linker.h> +#include <sys/module.h> #include <string.h> #include <machine/bootinfo.h> #include <machine/elf.h> @@ -40,7 +41,30 @@ #include "bootstrap.h" -static int elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t loadaddr, Elf_Ehdr *ehdr, int kernel, caddr_t firstpage, int firstlen); +#define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l) + + +typedef struct elf_file { + Elf_Phdr *ph; + Elf_Ehdr *ehdr; + Elf_Sym *symtab; + Elf_Off *hashtab; + Elf_Off nbuckets; + Elf_Off nchains; + Elf_Off* buckets; + Elf_Off* chains; + char *strtab; + size_t strsz; + int fd; + caddr_t firstpage; + int firstlen; + int kernel; + vm_offset_t off; +} *elf_file_t; + +static int elf_loadimage(struct preloaded_file *mp, elf_file_t ef, vm_offset_t loadaddr); +static int elf_lookup_symbol(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym); +static int elf_parse_modmetadata(struct preloaded_file *mp, elf_file_t ef); char *elf_kerneltype = "elf kernel"; char *elf_moduletype = "elf module"; @@ -51,35 +75,36 @@ char *elf_moduletype = "elf module"; * will be saved in (result). */ int -elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) +elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result) { - struct loaded_module *mp, *kmp; - Elf_Ehdr *ehdr; - int fd; - int err, kernel; + struct preloaded_file *fp, *kfp; + struct elf_file ef; + Elf_Ehdr *ehdr; + int err; u_int pad; char *s; - caddr_t firstpage; - int firstlen; - mp = NULL; + fp = NULL; + bzero(&ef, sizeof(struct elf_file)); /* * Open the image, read and validate the ELF header */ if (filename == NULL) /* can't handle nameless */ return(EFTYPE); - if ((fd = open(filename, O_RDONLY)) == -1) + if ((ef.fd = open(filename, O_RDONLY)) == -1) return(errno); - firstpage = malloc(PAGE_SIZE); - if (firstpage == NULL) + ef.firstpage = malloc(PAGE_SIZE); + if (ef.firstpage == NULL) { + close(ef.fd); return(ENOMEM); - firstlen = read(fd, firstpage, PAGE_SIZE); - if (firstlen <= sizeof(ehdr)) { + } + ef.firstlen = read(ef.fd, ef.firstpage, PAGE_SIZE); + if (ef.firstlen <= sizeof(Elf_Ehdr)) { err = EFTYPE; /* could be EIO, but may be small file */ goto oerr; } - ehdr = (Elf_Ehdr *)firstpage; + ehdr = ef.ehdr = (Elf_Ehdr *)ef.firstpage; /* Is it ELF? */ if (!IS_ELF(*ehdr)) { @@ -99,21 +124,21 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) /* * Check to see what sort of module we are. */ - kmp = mod_findmodule(NULL, NULL); + kfp = file_findfile(NULL, NULL); if (ehdr->e_type == ET_DYN) { /* Looks like a kld module */ - if (kmp == NULL) { - printf("elf_loadmodule: can't load module before kernel\n"); + if (kfp == NULL) { + printf("elf_loadfile: can't load module before kernel\n"); err = EPERM; goto oerr; } - if (strcmp(elf_kerneltype, kmp->m_type)) { - printf("elf_loadmodule: can't load module with kernel type '%s'\n", kmp->m_type); + if (strcmp(elf_kerneltype, kfp->f_type)) { + printf("elf_loadfile: can't load module with kernel type '%s'\n", kfp->f_type); err = EPERM; goto oerr; } /* Looks OK, got ahead */ - kernel = 0; + ef.kernel = 0; /* Page-align the load address */ pad = (u_int)dest & PAGE_MASK; @@ -123,8 +148,8 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) } } else if (ehdr->e_type == ET_EXEC) { /* Looks like a kernel */ - if (kmp != NULL) { - printf("elf_loadmodule: kernel already loaded\n"); + if (kfp != NULL) { + printf("elf_loadfile: kernel already loaded\n"); err = EPERM; goto oerr; } @@ -133,11 +158,11 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) */ dest = (vm_offset_t) ehdr->e_entry; if (dest == 0) { - printf("elf_loadmodule: not a kernel (maybe static binary?)\n"); + printf("elf_loadfile: not a kernel (maybe static binary?)\n"); err = EPERM; goto oerr; } - kernel = 1; + ef.kernel = 1; } else { err = EFTYPE; @@ -147,48 +172,48 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) /* * Ok, we think we should handle this. */ - mp = mod_allocmodule(); - if (mp == NULL) { - printf("elf_loadmodule: cannot allocate module info\n"); + fp = file_alloc(); + if (fp == NULL) { + printf("elf_loadfile: cannot allocate module info\n"); err = EPERM; goto out; } - if (kernel) + if (ef.kernel) setenv("kernelname", filename, 1); s = strrchr(filename, '/'); if (s) - mp->m_name = strdup(s + 1); + fp->f_name = strdup(s + 1); else - mp->m_name = strdup(filename); - mp->m_type = strdup(kernel ? elf_kerneltype : elf_moduletype); + fp->f_name = strdup(filename); + fp->f_type = strdup(ef.kernel ? elf_kerneltype : elf_moduletype); #ifdef ELF_VERBOSE - if (kernel) + if (ef.kernel) printf("%s entry at %p\n", filename, (void *) dest); #else printf("%s ", filename); #endif - mp->m_size = elf_loadimage(mp, fd, dest, ehdr, kernel, firstpage, firstlen); - if (mp->m_size == 0 || mp->m_addr == 0) + fp->f_size = elf_loadimage(fp, &ef, dest); + if (fp->f_size == 0 || fp->f_addr == 0) goto ioerr; /* save exec header as metadata */ - mod_addmetadata(mp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr); + file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr); /* Load OK, return module pointer */ - *result = (struct loaded_module *)mp; + *result = (struct preloaded_file *)fp; err = 0; goto out; ioerr: err = EIO; oerr: - mod_discard(mp); + file_discard(fp); out: - if (firstpage) - free(firstpage); - close(fd); + if (ef.firstpage) + free(ef.firstpage); + close(ef.fd); return(err); } @@ -197,11 +222,11 @@ elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result) * the Elf header, load the image at (off) */ static int -elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, - Elf_Ehdr *ehdr, int kernel, caddr_t firstpage, int firstlen) +elf_loadimage(struct preloaded_file *fp, elf_file_t ef, vm_offset_t off) { int i, j; - Elf_Phdr *phdr; + Elf_Ehdr *ehdr; + Elf_Phdr *phdr, *php; Elf_Shdr *shdr; int ret; vm_offset_t firstaddr; @@ -213,8 +238,6 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, Elf_Dyn *dp; int ndp; char *s; - char *strtab; - size_t strsz; int symstrindex; int symtabindex; long size; @@ -224,19 +247,21 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, shdr = NULL; ret = 0; firstaddr = lastaddr = 0; - if (kernel) { + ehdr = ef->ehdr; + if (ef->kernel) { #ifdef __i386__ off = - (off & 0xff000000u); /* i386 relocates after locore */ #else off = 0; /* alpha is direct mapped for kernels */ #endif } + ef->off = off; - if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > firstlen) { + if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) { printf("elf_loadimage: program header not within first page\n"); goto out; } - phdr = (Elf_Phdr *)(firstpage + ehdr->e_phoff); + phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; i++) { /* We want to load PT_LOAD segments only.. */ @@ -259,17 +284,17 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, } #endif fpcopy = 0; - if (firstlen > phdr[i].p_offset) { - fpcopy = firstlen - phdr[i].p_offset; - archsw.arch_copyin(firstpage + phdr[i].p_offset, + if (ef->firstlen > phdr[i].p_offset) { + fpcopy = ef->firstlen - phdr[i].p_offset; + archsw.arch_copyin(ef->firstpage + phdr[i].p_offset, phdr[i].p_vaddr + off, fpcopy); } if (phdr[i].p_filesz > fpcopy) { - if (lseek(fd, phdr[i].p_offset + fpcopy, SEEK_SET) == -1) { + if (lseek(ef->fd, phdr[i].p_offset + fpcopy, SEEK_SET) == -1) { printf("\nelf_loadexec: cannot seek\n"); goto out; } - if (archsw.arch_readin(fd, phdr[i].p_vaddr + off + fpcopy, + if (archsw.arch_readin(ef->fd, phdr[i].p_vaddr + off + fpcopy, phdr[i].p_filesz - fpcopy) != phdr[i].p_filesz - fpcopy) { printf("\nelf_loadexec: archsw.readin failed\n"); goto out; @@ -285,6 +310,10 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, /* no archsw.arch_bzero */ buf = malloc(PAGE_SIZE); + if (buf == NULL) { + printf("\nelf_loadimage: malloc() failed\n"); + goto out; + } bzero(buf, PAGE_SIZE); resid = phdr[i].p_memsz - phdr[i].p_filesz; dest = phdr[i].p_vaddr + off + phdr[i].p_filesz; @@ -319,11 +348,11 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, shdr = malloc(chunk); if (shdr == NULL) goto nosyms; - if (lseek(fd, ehdr->e_shoff, SEEK_SET) == -1) { + if (lseek(ef->fd, ehdr->e_shoff, SEEK_SET) == -1) { printf("\nelf_loadimage: cannot lseek() to section headers"); goto nosyms; } - if (read(fd, shdr, chunk) != chunk) { + if (read(ef->fd, shdr, chunk) != chunk) { printf("\nelf_loadimage: read section headers failed"); goto nosyms; } @@ -388,13 +417,13 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, printf("0x%lx+0x%lx", (long)sizeof(size), size); #endif - if (lseek(fd, shdr[i].sh_offset, SEEK_SET) == -1) { + if (lseek(ef->fd, shdr[i].sh_offset, SEEK_SET) == -1) { printf("\nelf_loadimage: could not seek for symbols - skipped!"); lastaddr = ssym; ssym = 0; goto nosyms; } - if (archsw.arch_readin(fd, lastaddr, shdr[i].sh_size) != + if (archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size) != shdr[i].sh_size) { printf("\nelf_loadimage: could not read symbols - skipped!"); lastaddr = ssym; @@ -414,66 +443,81 @@ elf_loadimage(struct loaded_module *mp, int fd, vm_offset_t off, printf("]"); #endif - mod_addmetadata(mp, MODINFOMD_SSYM, sizeof(ssym), &ssym); - mod_addmetadata(mp, MODINFOMD_ESYM, sizeof(esym), &esym); + file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym); + file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym); nosyms: printf("\n"); ret = lastaddr - firstaddr; - mp->m_addr = firstaddr; + fp->f_addr = firstaddr; + php = NULL; for (i = 0; i < ehdr->e_phnum; i++) { if (phdr[i].p_type == PT_DYNAMIC) { - dp = (Elf_Dyn *)(phdr[i].p_vaddr); - mod_addmetadata(mp, MODINFOMD_DYNAMIC, sizeof(dp), &dp); + php = phdr + i; + dp = (Elf_Dyn *)(php->p_vaddr); + file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(dp), &dp); dp = NULL; break; } } - if (kernel) /* kernel must not depend on anything */ + if (php == NULL) /* this is bad, we cannot get to symbols or _DYNAMIC */ goto out; - ndp = 0; - for (i = 0; i < ehdr->e_phnum; i++) { - if (phdr[i].p_type == PT_DYNAMIC) { - ndp = phdr[i].p_filesz / sizeof(Elf_Dyn); - dp = malloc(phdr[i].p_filesz); - archsw.arch_copyout(phdr[i].p_vaddr + off, dp, phdr[i].p_filesz); - } - } - if (dp == NULL || ndp == 0) + ndp = php->p_filesz / sizeof(Elf_Dyn); + if (ndp == 0) + goto out; + dp = malloc(php->p_filesz); + if (dp == NULL) goto out; - strtab = NULL; - strsz = 0; + archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz); + + ef->strsz = 0; for (i = 0; i < ndp; i++) { if (dp[i].d_tag == NULL) break; switch (dp[i].d_tag) { + case DT_HASH: + ef->hashtab = (Elf_Off*)(dp[i].d_un.d_ptr + off); + break; case DT_STRTAB: - strtab = (char *)(dp[i].d_un.d_ptr + off); + ef->strtab = (char *)(dp[i].d_un.d_ptr + off); break; case DT_STRSZ: - strsz = dp[i].d_un.d_val; + ef->strsz = dp[i].d_un.d_val; + break; + case DT_SYMTAB: + ef->symtab = (Elf_Sym*)(dp[i].d_un.d_ptr + off); break; default: break; } } - if (strtab == NULL || strsz == 0) + if (ef->hashtab == NULL || ef->symtab == NULL || + ef->strtab == NULL || ef->strsz == 0) + goto out; + COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets)); + COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains)); + ef->buckets = ef->hashtab + 2; + ef->chains = ef->buckets + ef->nbuckets; + if (elf_parse_modmetadata(fp, ef) == 0) + goto out; + + if (ef->kernel) /* kernel must not depend on anything */ goto out; for (i = 0; i < ndp; i++) { - if (dp[i].d_tag == NULL) + if (dp[i].d_tag == NULL) break; if (dp[i].d_tag != DT_NEEDED) continue; j = dp[i].d_un.d_ptr; - if (j < 1 || j > (strsz - 2)) - continue; /* bad symbol name index */ - s = strdupout((vm_offset_t)&strtab[j]); - mod_addmetadata(mp, MODINFOMD_DEPLIST, strlen(s) + 1, s); + if (j < 1 || j > ef->strsz - 2) + continue; + s = strdupout((vm_offset_t)&ef->strtab[j]); + file_addmetadata(fp, MODINFOMD_DEPLIST, strlen(s) + 1, s); free(s); } @@ -484,3 +528,131 @@ out: free(shdr); return ret; } + +static char invalid_name[] = "bad"; +char * +fake_modname(char *name) { + char *sp, *ep; + int len; + + sp = strrchr(name, '/'); + if (sp) + sp++; + else + sp = name; + ep = strrchr(name, '.'); + if (ep) { + if (ep == name) { + sp = invalid_name; + ep = invalid_name + sizeof(invalid_name) - 1; + } + } else + ep = name + strlen(name); + len = ep - sp; + ep = malloc(len + 1); + if (ep == NULL) + return NULL; + memcpy(ep, sp, len); + ep[len] = '\0'; + return ep; +} + +int +elf_parse_modmetadata(struct preloaded_file *fp, elf_file_t ef) { + struct mod_metadata md; + Elf_Sym sym; + void **p, *v; + char *s; + int entries, modcnt; + + if (elf_lookup_symbol(fp, ef, "modmetadata_set", &sym) != 0) + return ENOENT; + COPYOUT(sym.st_value + ef->off, &entries, sizeof(entries)); + + modcnt = 0; + p = (void*)(sym.st_value + ef->off + sizeof(entries)); + while (entries--) { + COPYOUT(p++, &v, sizeof(v)); + COPYOUT(v + ef->off, &md, sizeof(md)); + switch(md.md_type) { + case MDT_DEPEND: + if (ef->kernel) /* kernel must not depend on anything */ + break; + s = strdupout((vm_offset_t)(md.md_cval + ef->off)); + file_addmetadata(fp, MODINFOMD_DEPLIST, strlen(s) + 1, s); + free(s); + break; + case MDT_VERSION: + s = strdupout((vm_offset_t)(md.md_cval + ef->off)); + file_addmodule(fp, s, NULL); + printf(" module: %s\n", s); + free(s); + modcnt++; + break; + } + } + if (modcnt == 0) { + s = fake_modname(fp->f_name); + file_addmodule(fp, s, NULL); + free(s); + } + return 0; +} + +static unsigned long +elf_hash(const char *name) +{ + const unsigned char *p = (const unsigned char *) name; + unsigned long h = 0; + unsigned long g; + + while (*p != '\0') { + h = (h << 4) + *p++; + if ((g = h & 0xf0000000) != 0) + h ^= g >> 24; + h &= ~g; + } + return h; +} + +static const char elf_bad_symtable[] = "elf_lookup_symbol: corrupt symbol table\n"; +int +elf_lookup_symbol(struct preloaded_file *fp, elf_file_t ef, const char* name, + Elf_Sym *symp) +{ + unsigned long symnum; + Elf_Sym sym; + char *strp; + unsigned long hash; + + hash = elf_hash(name); + COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum)); + + while (symnum != STN_UNDEF) { + if (symnum >= ef->nchains) { + printf(elf_bad_symtable); + return ENOENT; + } + + COPYOUT(ef->symtab + symnum, &sym, sizeof(sym)); + if (sym.st_name == 0) { + printf(elf_bad_symtable); + return ENOENT; + } + + strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name)); + if (strcmp(name, strp) == 0) { + free(strp); + if (sym.st_shndx != SHN_UNDEF || + (sym.st_value != 0 && + ELF_ST_TYPE(sym.st_info) == STT_FUNC)) { + *symp = sym; + return 0; + } + return ENOENT; + } + free(strp); + COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum)); + } + return ENOENT; +} diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c index 7022427..8ad0dc0 100644 --- a/sys/boot/common/module.c +++ b/sys/boot/common/module.c @@ -27,7 +27,7 @@ */ /* - * module function dispatcher, support, etc. + * file/module function dispatcher, support, etc. */ #include <stand.h> @@ -37,19 +37,21 @@ #include "bootstrap.h" -static int mod_loadmodule(char *name, int argc, char *argv[], struct loaded_module **mpp); -static int file_load_dependancies(struct loaded_module *base_file); -static char *mod_searchfile(char *name); +static int file_load(char *filename, vm_offset_t dest, struct preloaded_file **result); +static int file_loadraw(char *type, char *name); +static int file_load_dependancies(struct preloaded_file *base_mod); +static char * file_search(char *name); +struct kernel_module * file_findmodule(struct preloaded_file *fp, char *modname); static char *mod_searchmodule(char *name); -static void mod_append(struct loaded_module *mp); -static struct module_metadata *metadata_next(struct module_metadata *md, int type); +static void file_insert_tail(struct preloaded_file *mp); +struct file_metadata* metadata_next(struct file_metadata *base_mp, int type); /* load address should be tweaked by first module loaded (kernel) */ static vm_offset_t loadaddr = 0; static char *default_searchpath ="/;/boot;/modules"; -struct loaded_module *loaded_modules = NULL; +struct preloaded_file *preloaded_files = NULL; /* * load an object, either a disk file or code module. @@ -102,7 +104,7 @@ command_load(int argc, char *argv[]) command_errmsg = "invalid load type"; return(CMD_ERROR); } - return(mod_loadobj(typestr, argv[1])); + return(file_loadraw(typestr, argv[1])); } /* @@ -119,12 +121,12 @@ COMMAND_SET(unload, "unload", "unload all modules", command_unload); static int command_unload(int argc, char *argv[]) { - struct loaded_module *mp; + struct preloaded_file *fp; - while (loaded_modules != NULL) { - mp = loaded_modules; - loaded_modules = loaded_modules->m_next; - mod_discard(mp); + while (preloaded_files != NULL) { + fp = preloaded_files; + preloaded_files = preloaded_files->f_next; + file_discard(fp); } loadaddr = 0; return(CMD_OK); @@ -135,8 +137,9 @@ COMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod); static int command_lsmod(int argc, char *argv[]) { - struct loaded_module *am; - struct module_metadata *md; + struct preloaded_file *fp; + struct kernel_module *mp; + struct file_metadata *md; char lbuf[80]; int ch, verbose; @@ -156,90 +159,115 @@ command_lsmod(int argc, char *argv[]) } pager_open(); - for (am = loaded_modules; (am != NULL); am = am->m_next) { + for (fp = preloaded_files; fp; fp = fp->f_next) { sprintf(lbuf, " %p: %s (%s, 0x%lx)\n", - (void *) am->m_addr, am->m_name, am->m_type, (long) am->m_size); + (void *) fp->f_addr, fp->f_name, fp->f_type, (long) fp->f_size); pager_output(lbuf); - if (am->m_args != NULL) { + if (fp->f_args != NULL) { pager_output(" args: "); - pager_output(am->m_args); + pager_output(fp->f_args); pager_output("\n"); } - if (verbose) + if (fp->f_modules) { + pager_output(" modules: "); + for (mp = fp->f_modules; mp; mp = mp->m_next) { + sprintf(lbuf, "%s ", mp->m_name); + pager_output(lbuf); + } + 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) { + for (md = fp->f_metadata; md != NULL; md = md->md_next) { sprintf(lbuf, " 0x%04x, 0x%lx\n", md->md_type, (long) 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. + * File level interface, functions file_* */ int -mod_load(char *name, int argc, char *argv[]) +file_load(char *filename, vm_offset_t dest, struct preloaded_file **result) { - struct loaded_module *last_mod, *base_mod, *mp; - int error; + struct preloaded_file *fp; + int error; + int i; + + error = EFTYPE; + for (i = 0, fp = NULL; file_formats[i] && fp == NULL; i++) { + error = (file_formats[i]->l_load)(filename, loadaddr, &fp); + if (error == 0) { + fp->f_loader = i; /* remember the loader */ + *result = fp; + break; + } + if (error == EFTYPE) + continue; /* Unknown to this handler? */ + if (error) { + sprintf(command_errbuf, "can't load file '%s': %s", + filename, strerror(error)); + break; + } + } + return (error); +} - /* 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) - ; - - /* - * Load the first module; note that it's the only one that gets - * arguments explicitly. - */ - error = mod_loadmodule(name, argc, argv, &base_mod); - if (error) - return (error); +static int +file_load_dependancies(struct preloaded_file *base_file) { + struct file_metadata *md; + struct preloaded_file *fp; + char *dmodname; + int error; - error = file_load_dependancies(base_mod); + md = file_findmetadata(base_file, MODINFOMD_DEPLIST); + if (md == NULL) + return (0); + error = 0; + do { + dmodname = (char *)md->md_data; + if (file_findmodule(NULL, dmodname) == NULL) { + printf("loading required module '%s'\n", dmodname); + error = mod_load(dmodname, 0, NULL); + if (error) + break; + } + md = metadata_next(md, MODINFOMD_DEPLIST); + } while (md); if (!error) return (0); - /* Load failed; discard everything */ - last_mod->m_next = NULL; - loadaddr = last_mod->m_addr + last_mod->m_size; - while (base_mod != NULL) { - mp = base_mod; - base_mod = base_mod->m_next; - mod_discard(mp); + while (base_file != NULL) { + fp = base_file; + base_file = base_file->f_next; + file_discard(fp); } return (error); } - /* * 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) +file_loadraw(char *type, char *name) { - struct loaded_module *mp; + struct preloaded_file *fp; char *cp; int fd, got; vm_offset_t laddr; /* We can't load first */ - if ((mod_findmodule(NULL, NULL)) == NULL) { + if ((file_findfile(NULL, NULL)) == NULL) { command_errmsg = "can't load file before kernel"; return(CMD_ERROR); } /* locate the file on the load path */ - cp = mod_searchfile(name); + cp = file_search(name); if (cp == NULL) { sprintf(command_errbuf, "can't find '%s'", name); return(CMD_ERROR); @@ -268,166 +296,168 @@ mod_loadobj(char *type, char *name) } /* Looks OK so far; create & populate control structure */ - mp = malloc(sizeof(struct loaded_module)); - mp->m_name = 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; + fp = file_alloc(); + fp->f_name = name; + fp->f_type = strdup(type); + fp->f_args = NULL; + fp->f_metadata = NULL; + fp->f_loader = -1; + fp->f_addr = loadaddr; + fp->f_size = laddr - loadaddr; /* recognise space consumption */ loadaddr = laddr; - /* Add to the list of loaded modules */ - mod_append(mp); + /* Add to the list of loaded files */ + file_insert_tail(fp); close(fd); return(CMD_OK); } /* - * Load the module (name), pass it (argc),(argv). - * Don't do any dependancy checking. + * Load the module (name), pass it (argc),(argv), add container file + * to the list of loaded files. + * If module is already loaded just assign new argc/argv. */ -static int -mod_loadmodule(char *name, int argc, char *argv[], struct loaded_module **mpp) +int +mod_load(char *modname, int argc, char *argv[]) { - struct loaded_module *mp; - int i, err; - char *cp; + struct preloaded_file *fp, *last_file; + struct kernel_module *mp; + int err; + char *filename; - /* locate the module on the search path */ - cp = mod_searchmodule(name); - if (cp == NULL) { - sprintf(command_errbuf, "can't find '%s'", name); - return (ENOENT); - } - name = cp; - - cp = strrchr(name, '/'); - if (cp) - cp++; - else - cp = name; /* see if module is already loaded */ - mp = mod_findmodule(cp, NULL); + mp = file_findmodule(NULL, modname); if (mp) { - *mpp = mp; - return (EEXIST); +#ifdef moduleargs + if (mp->m_args) + free(mp->m_args); + mp->m_args = unargv(argc, argv); +#endif + sprintf(command_errbuf, "warning: module '%s' already loaded", mp->m_name); + return (0); } + /* locate file with the module on the search path */ + filename = mod_searchmodule(modname); + if (filename == NULL) { + sprintf(command_errbuf, "can't find '%s'", modname); + return (ENOENT); + } + for (last_file = preloaded_files; + last_file != NULL && last_file->f_next != NULL; + last_file = last_file->f_next) + ; - 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) - continue; - - /* Fatal error */ - sprintf(command_errbuf, "can't load module '%s': %s", name, strerror(err)); - free(name); - return (err); - } 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 */ - mp->m_loader = i; - - /* Add to the list of loaded modules */ - mod_append(mp); - *mpp = mp; - + fp = NULL; + do { + err = file_load(filename, loadaddr, &fp); + if (err) + break; +#ifdef moduleargs + mp = file_findmodule(fp, modname); + if (mp == NULL) { + sprintf(command_errbuf, "module '%s' not found in the file '%s': %s", + modname, filename, strerror(err)); + err = ENOENT; break; } - } + mp->m_args = unargv(argc, argv); +#else + fp->f_args = unargv(argc, argv); +#endif + loadaddr = fp->f_addr + fp->f_size; + file_insert_tail(fp); /* Add to the list of loaded files */ + if (file_load_dependancies(fp) != 0) { + err = ENOENT; + last_file->f_next = NULL; + loadaddr = last_file->f_addr + last_file->f_size; + fp = NULL; + break; + } + } while(0); if (err == EFTYPE) - sprintf(command_errbuf, "don't know how to load module '%s'", name); - free(name); + sprintf(command_errbuf, "don't know how to load module '%s'", filename); + if (err && fp) + file_discard(fp); + free(filename); return (err); } -static int -file_load_dependancies(struct loaded_module *base_file) +/* + * Find a file matching (name) and (type). + * NULL may be passed as a wildcard to either. + */ +struct preloaded_file * +file_findfile(char *name, char *type) { - struct module_metadata *md; - char *dmodname; - int error; + struct preloaded_file *fp; - md = mod_findmetadata(base_file, MODINFOMD_DEPLIST); - if (md == NULL) - return (0); - error = 0; - do { - dmodname = (char *)md->md_data; - if (mod_findmodule(NULL, dmodname) == NULL) { - printf("loading required module '%s'\n", dmodname); - error = mod_load(dmodname, 0, NULL); - if (error && error != EEXIST) - break; - } - md = metadata_next(md, MODINFOMD_DEPLIST); - } while (md); - return (error); + for (fp = preloaded_files; fp != NULL; fp = fp->f_next) { + if (((name == NULL) || !strcmp(name, fp->f_name)) && + ((type == NULL) || !strcmp(type, fp->f_type))) + break; + } + return (fp); } /* - * Find a module matching (name) and (type). - * NULL may be passed as a wildcard to either. + * Find a module matching (name) inside of given file. + * NULL may be passed as a wildcard. */ -struct loaded_module * -mod_findmodule(char *name, char *type) +struct kernel_module * +file_findmodule(struct preloaded_file *fp, char *modname) { - struct loaded_module *mp; - - for (mp = loaded_modules; mp != NULL; mp = mp->m_next) { - if (((name == NULL) || !strcmp(name, mp->m_name)) && - ((type == NULL) || !strcmp(type, mp->m_type))) - break; + struct kernel_module *mp; + + if (fp == NULL) { + for (fp = preloaded_files; fp; fp = fp->f_next) { + for (mp = fp->f_modules; mp; mp = mp->m_next) { + if (strcmp(modname, mp->m_name) == 0) + return (mp); + } + } + return (NULL); + } + for (mp = fp->f_modules; mp; mp = mp->m_next) { + if (strcmp(modname, mp->m_name) == 0) + return (mp); } - return(mp); + return (NULL); } - /* * 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) +file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p) { - struct module_metadata *md; + struct file_metadata *md; - md = malloc(sizeof(struct module_metadata) + size); + md = malloc(sizeof(struct file_metadata) + size); md->md_size = size; md->md_type = type; bcopy(p, md->md_data, size); - md->md_next = mp->m_metadata; - mp->m_metadata = md; + md->md_next = fp->f_metadata; + fp->f_metadata = md; } /* - * Find a metadata object of (type) associated with the module - * (mp) + * Find a metadata object of (type) associated with the file (fp) */ -struct module_metadata * -mod_findmetadata(struct loaded_module *mp, int type) +struct file_metadata * +file_findmetadata(struct preloaded_file *fp, int type) { - struct module_metadata *md; + struct file_metadata *md; - for (md = mp->m_metadata; md != NULL; md = md->md_next) + for (md = fp->f_metadata; md != NULL; md = md->md_next) if (md->md_type == type) break; return(md); } -struct module_metadata * -metadata_next(struct module_metadata *md, int type) +struct file_metadata * +metadata_next(struct file_metadata *md, int type) { if (md == NULL) return (NULL); @@ -448,7 +478,7 @@ metadata_next(struct module_metadata *md, int type) * it internally. */ static char * -mod_searchfile(char *name) +file_search(char *name) { char *result; char *path, *sp; @@ -490,7 +520,6 @@ mod_searchfile(char *name) if (cp[strlen(cp) - 1] != '/') strcat(result, "/"); strcat(result, name); -/* printf("search '%s'\n", result); */ if ((stat(result, &sb) == 0) && S_ISREG(sb.st_mode)) break; @@ -513,71 +542,101 @@ mod_searchmodule(char *name) tn = malloc(strlen(name) + 3 + 1); strcpy(tn, name); strcat(tn, ".ko"); - result = mod_searchfile(tn); + result = file_search(tn); free(tn); /* Look for just (name) (useful for finding kernels) */ if (result == NULL) - result = mod_searchfile(name); + result = file_search(name); return(result); } +int +file_addmodule(struct preloaded_file *fp, char *modname, + struct kernel_module **newmp) +{ + struct kernel_module *mp; + + mp = file_findmodule(fp, modname); + if (mp) + return (EEXIST); + mp = malloc(sizeof(struct kernel_module)); + if (mp == NULL) + return (ENOMEM); + bzero(mp, sizeof(struct kernel_module)); + mp->m_name = strdup(modname); + mp->m_fp = fp; + mp->m_next = fp->f_modules; + fp->f_modules = mp; + if (newmp) + *newmp = mp; + return (0); +} /* - * Throw a module away + * Throw a file away */ void -mod_discard(struct loaded_module *mp) +file_discard(struct preloaded_file *fp) { - struct module_metadata *md; - - if (mp != NULL) { - 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); + struct file_metadata *md, *md1; + struct kernel_module *mp, *mp1; + if (fp == NULL) + return; + md = fp->f_metadata; + while (md) { + md1 = md; + md = md->md_next; + free(md1); } + mp = fp->f_modules; + while (mp) { + if (mp->m_name) + free(mp->m_name); + mp1 = mp; + mp = mp->m_next; + free(mp1); + } + if (fp->f_name != NULL) + free(fp->f_name); + if (fp->f_type != NULL) + free(fp->f_type); + if (fp->f_args != NULL) + free(fp->f_args); + free(fp); } /* - * Allocate a new module; must be used instead of malloc() + * Allocate a new file; must be used instead of malloc() * to ensure safe initialisation. */ -struct loaded_module * -mod_allocmodule(void) +struct preloaded_file * +file_alloc(void) { - struct loaded_module *mp; + struct preloaded_file *fp; - if ((mp = malloc(sizeof(struct loaded_module))) != NULL) { - bzero(mp, sizeof(struct loaded_module)); + if ((fp = malloc(sizeof(struct preloaded_file))) != NULL) { + bzero(fp, sizeof(struct preloaded_file)); } - return(mp); + return (fp); } - /* * Add a module to the chain */ static void -mod_append(struct loaded_module *mp) +file_insert_tail(struct preloaded_file *fp) { - struct loaded_module *cm; + struct preloaded_file *cm; - /* Append to list of loaded modules */ - mp->m_next = NULL; - if (loaded_modules == NULL) { - loaded_modules = mp; + /* Append to list of loaded file */ + fp->f_next = NULL; + if (preloaded_files == NULL) { + preloaded_files = fp; } else { - for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next) + for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next) ; - cm->m_next = mp; + cm->f_next = fp; } } + diff --git a/sys/boot/common/pnp.c b/sys/boot/common/pnp.c index 21c07a2..bb3695b 100644 --- a/sys/boot/common/pnp.c +++ b/sys/boot/common/pnp.c @@ -1,5 +1,7 @@ /* * mjs copyright + * + * $FreeBSD$ */ /* * "Plug and Play" functionality. @@ -113,7 +115,7 @@ pnp_load(int argc, char *argv[]) /* try to load any modules that have been nominated */ for (pi = pnp_devices.stqh_first; pi != NULL; pi = pi->pi_link.stqe_next) { /* Already loaded? */ - if ((pi->pi_module != NULL) && (mod_findmodule(pi->pi_module, NULL) == NULL)) { + if ((pi->pi_module != NULL) && (file_findfile(pi->pi_module, NULL) == NULL)) { modfname = malloc(strlen(pi->pi_module) + 4); sprintf(modfname, "%s.ko", pi->pi_module); /* XXX implicit knowledge of KLD module filenames */ if (mod_load(pi->pi_module, pi->pi_argc, pi->pi_argv)) |