Home | History | Annotate | Line # | Download | only in common
fileload.c revision 1.1.92.1
      1  1.1.92.1     jym /*	$NetBSD: fileload.c,v 1.1.92.1 2009/05/13 17:17:57 jym Exp $	*/
      2       1.1  cherry 
      3       1.1  cherry /*-
      4       1.1  cherry  * Copyright (c) 1998 Michael Smith <msmith (at) freebsd.org>
      5       1.1  cherry  * All rights reserved.
      6       1.1  cherry  *
      7       1.1  cherry  * Redistribution and use in source and binary forms, with or without
      8       1.1  cherry  * modification, are permitted provided that the following conditions
      9       1.1  cherry  * are met:
     10       1.1  cherry  * 1. Redistributions of source code must retain the above copyright
     11       1.1  cherry  *    notice, this list of conditions and the following disclaimer.
     12       1.1  cherry  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1  cherry  *    notice, this list of conditions and the following disclaimer in the
     14       1.1  cherry  *    documentation and/or other materials provided with the distribution.
     15       1.1  cherry  *
     16       1.1  cherry  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17       1.1  cherry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18       1.1  cherry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19       1.1  cherry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20       1.1  cherry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21       1.1  cherry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22       1.1  cherry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23       1.1  cherry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24       1.1  cherry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25       1.1  cherry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26       1.1  cherry  * SUCH DAMAGE.
     27       1.1  cherry  */
     28       1.1  cherry 
     29       1.1  cherry #include <sys/cdefs.h>
     30       1.1  cherry 
     31       1.1  cherry /*
     32       1.1  cherry  * file/module function dispatcher, support, etc.
     33       1.1  cherry  */
     34       1.1  cherry 
     35       1.1  cherry #include <lib/libsa/stand.h>
     36       1.1  cherry #include <sys/param.h>
     37       1.1  cherry #include <sys/lkm.h>
     38       1.1  cherry #include <sys/queue.h>
     39       1.1  cherry 
     40       1.1  cherry #include "bootstrap.h"
     41       1.1  cherry 
     42       1.1  cherry static int			file_load(char *filename, vaddr_t dest, struct preloaded_file **result);
     43       1.1  cherry static int			file_havepath(const char *name);
     44       1.1  cherry static void			file_insert_tail(struct preloaded_file *mp);
     45       1.1  cherry 
     46       1.1  cherry /* load address should be tweaked by first module loaded (kernel) */
     47       1.1  cherry static vaddr_t	loadaddr = 0;
     48       1.1  cherry 
     49       1.1  cherry struct preloaded_file *preloaded_files = NULL;
     50       1.1  cherry 
     51       1.1  cherry /*
     52       1.1  cherry  * load a kernel from disk.
     53       1.1  cherry  *
     54       1.1  cherry  * kernels are loaded as:
     55       1.1  cherry  *
     56       1.1  cherry  * load <path> <options>
     57       1.1  cherry  */
     58       1.1  cherry 
     59       1.1  cherry int
     60       1.1  cherry command_load(int argc, char *argv[])
     61       1.1  cherry {
     62       1.1  cherry     char	*typestr;
     63       1.1  cherry     int		dofile, dokld, ch, error;
     64       1.1  cherry 
     65       1.1  cherry     dokld = dofile = 0;
     66       1.1  cherry     optind = 1;
     67       1.1  cherry     optreset = 1;
     68       1.1  cherry     typestr = NULL;
     69       1.1  cherry     if (argc == 1) {
     70       1.1  cherry 	command_errmsg = "no filename specified";
     71       1.1  cherry 	return(CMD_ERROR);
     72       1.1  cherry     }
     73       1.1  cherry     while ((ch = getopt(argc, argv, "k:")) != -1) {
     74       1.1  cherry 	switch(ch) {
     75       1.1  cherry 	case 'k':
     76       1.1  cherry 	    dokld = 1;
     77       1.1  cherry 	    break;
     78       1.1  cherry 	case '?':
     79       1.1  cherry 	default:
     80       1.1  cherry 	    /* getopt has already reported an error */
     81       1.1  cherry 	    return(CMD_OK);
     82       1.1  cherry 	}
     83       1.1  cherry     }
     84       1.1  cherry     argv += (optind - 1);
     85       1.1  cherry     argc -= (optind - 1);
     86       1.1  cherry 
     87       1.1  cherry     /*
     88       1.1  cherry      * Do we have explicit KLD load ?
     89       1.1  cherry      */
     90       1.1  cherry     if (dokld || file_havepath(argv[1])) {
     91       1.1  cherry 	error = file_loadkernel(argv[1], argc - 2, argv + 2);
     92       1.1  cherry 	if (error == EEXIST)
     93       1.1  cherry 	    sprintf(command_errbuf, "warning: KLD '%s' already loaded", argv[1]);
     94       1.1  cherry     }
     95       1.1  cherry     return (error == 0 ? CMD_OK : CMD_ERROR);
     96       1.1  cherry }
     97       1.1  cherry 
     98       1.1  cherry 
     99       1.1  cherry int
    100       1.1  cherry command_unload(int argc, char *argv[])
    101       1.1  cherry {
    102       1.1  cherry     struct preloaded_file	*fp;
    103       1.1  cherry 
    104       1.1  cherry     while (preloaded_files != NULL) {
    105       1.1  cherry 	fp = preloaded_files;
    106       1.1  cherry 	preloaded_files = preloaded_files->f_next;
    107       1.1  cherry 	file_discard(fp);
    108       1.1  cherry     }
    109       1.1  cherry     loadaddr = 0;
    110       1.1  cherry     unsetenv("kernelname");
    111       1.1  cherry     return(CMD_OK);
    112       1.1  cherry }
    113       1.1  cherry 
    114       1.1  cherry 
    115       1.1  cherry int
    116       1.1  cherry command_lskern(int argc, char *argv[])
    117       1.1  cherry {
    118       1.1  cherry     struct preloaded_file	*fp;
    119       1.1  cherry     char			lbuf[80];
    120       1.1  cherry     int				ch, verbose;
    121       1.1  cherry 
    122       1.1  cherry     verbose = 0;
    123       1.1  cherry     optind = 1;
    124       1.1  cherry     optreset = 1;
    125       1.1  cherry 
    126       1.1  cherry     pager_open();
    127       1.1  cherry     for (fp = preloaded_files; fp; fp = fp->f_next) {
    128       1.1  cherry 	sprintf(lbuf, " %p: %s (%s, 0x%lx)\n",
    129       1.1  cherry 		(void *) fp->f_addr, fp->f_name, fp->f_type, (long) fp->f_size);
    130       1.1  cherry 	pager_output(lbuf);
    131       1.1  cherry 	if (fp->f_args != NULL) {
    132       1.1  cherry 	    pager_output("    args: ");
    133       1.1  cherry 	    pager_output(fp->f_args);
    134       1.1  cherry 	    pager_output("\n");
    135       1.1  cherry 	}
    136       1.1  cherry     }
    137       1.1  cherry     pager_close();
    138       1.1  cherry     return(CMD_OK);
    139       1.1  cherry }
    140       1.1  cherry 
    141       1.1  cherry /*
    142       1.1  cherry  * File level interface, functions file_*
    143       1.1  cherry  */
    144       1.1  cherry int
    145       1.1  cherry file_load(char *filename, vaddr_t dest, struct preloaded_file **result)
    146       1.1  cherry {
    147       1.1  cherry     struct preloaded_file *fp;
    148       1.1  cherry     int error;
    149       1.1  cherry     int i;
    150       1.1  cherry 
    151       1.1  cherry     error = EFTYPE;
    152       1.1  cherry     for (i = 0, fp = NULL; file_formats[i] && fp == NULL; i++) {
    153       1.1  cherry 	error = (file_formats[i]->l_load)(filename, dest, &fp);
    154       1.1  cherry 	if (error == 0) {
    155       1.1  cherry 	    fp->f_loader = i;		/* remember the loader */
    156       1.1  cherry 	    *result = fp;
    157       1.1  cherry 	    break;
    158       1.1  cherry 	}
    159       1.1  cherry 	if (error == EFTYPE)
    160       1.1  cherry 	    continue;		/* Unknown to this handler? */
    161       1.1  cherry 	if (error) {
    162       1.1  cherry 	    sprintf(command_errbuf, "can't load file '%s': %s",
    163       1.1  cherry 		filename, strerror(error));
    164       1.1  cherry 	    break;
    165       1.1  cherry 	}
    166       1.1  cherry     }
    167       1.1  cherry     return (error);
    168       1.1  cherry }
    169       1.1  cherry 
    170       1.1  cherry /*
    171       1.1  cherry  * Load specified KLD. If path is omitted, then try to locate it via
    172       1.1  cherry  * search path.
    173       1.1  cherry  */
    174       1.1  cherry int
    175       1.1  cherry file_loadkernel(char *filename, int argc, char *argv[])
    176       1.1  cherry {
    177       1.1  cherry     struct preloaded_file	*fp, *last_file;
    178       1.1  cherry     int				err;
    179       1.1  cherry 
    180       1.1  cherry     /*
    181       1.1  cherry      * Check if KLD already loaded
    182       1.1  cherry      */
    183       1.1  cherry     fp = file_findfile(filename, NULL);
    184       1.1  cherry     if (fp) {
    185       1.1  cherry 	sprintf(command_errbuf, "warning: KLD '%s' already loaded", filename);
    186       1.1  cherry 	free(filename);
    187       1.1  cherry 	return (0);
    188       1.1  cherry     }
    189       1.1  cherry     for (last_file = preloaded_files;
    190       1.1  cherry 	 last_file != NULL && last_file->f_next != NULL;
    191       1.1  cherry 	 last_file = last_file->f_next)
    192       1.1  cherry 	;
    193       1.1  cherry 
    194       1.1  cherry     do {
    195       1.1  cherry 	err = file_load(filename, loadaddr, &fp);
    196       1.1  cherry 	if (err)
    197       1.1  cherry 	    break;
    198       1.1  cherry 	fp->f_args = unargv(argc, argv);
    199       1.1  cherry 	loadaddr = fp->f_addr + fp->f_size;
    200       1.1  cherry 	file_insert_tail(fp);		/* Add to the list of loaded files */
    201       1.1  cherry     } while(0);
    202       1.1  cherry     if (err == EFTYPE)
    203       1.1  cherry 	sprintf(command_errbuf, "don't know how to load module '%s'", filename);
    204       1.1  cherry     if (err && fp)
    205       1.1  cherry 	file_discard(fp);
    206       1.1  cherry     free(filename);
    207       1.1  cherry     return (err);
    208       1.1  cherry }
    209       1.1  cherry 
    210       1.1  cherry /*
    211       1.1  cherry  * Find a file matching (name) and (type).
    212       1.1  cherry  * NULL may be passed as a wildcard to either.
    213       1.1  cherry  */
    214       1.1  cherry struct preloaded_file *
    215       1.1  cherry file_findfile(char *name, char *type)
    216       1.1  cherry {
    217       1.1  cherry     struct preloaded_file *fp;
    218       1.1  cherry 
    219       1.1  cherry     for (fp = preloaded_files; fp != NULL; fp = fp->f_next) {
    220       1.1  cherry 	if (((name == NULL) || !strcmp(name, fp->f_name)) &&
    221       1.1  cherry 	    ((type == NULL) || !strcmp(type, fp->f_type)))
    222       1.1  cherry 	    break;
    223       1.1  cherry     }
    224       1.1  cherry     return (fp);
    225       1.1  cherry }
    226       1.1  cherry 
    227       1.1  cherry /*
    228       1.1  cherry  * Check if file name have any qualifiers
    229       1.1  cherry  */
    230       1.1  cherry static int
    231       1.1  cherry file_havepath(const char *name)
    232       1.1  cherry {
    233       1.1  cherry     const char		*cp;
    234       1.1  cherry 
    235       1.1  cherry     archsw.arch_getdev(NULL, name, &cp);
    236       1.1  cherry     return (cp != name || strchr(name, '/') != NULL);
    237       1.1  cherry }
    238       1.1  cherry 
    239       1.1  cherry /*
    240       1.1  cherry  * Throw a file away
    241       1.1  cherry  */
    242       1.1  cherry void
    243       1.1  cherry file_discard(struct preloaded_file *fp)
    244       1.1  cherry {
    245       1.1  cherry     if (fp == NULL)
    246       1.1  cherry 	return;
    247       1.1  cherry     if (fp->f_name != NULL)
    248       1.1  cherry 	free(fp->f_name);
    249       1.1  cherry     if (fp->f_type != NULL)
    250       1.1  cherry         free(fp->f_type);
    251       1.1  cherry     if (fp->f_args != NULL)
    252       1.1  cherry         free(fp->f_args);
    253       1.1  cherry     if (fp->marks != NULL)
    254       1.1  cherry 	free(fp->marks);
    255       1.1  cherry     free(fp);
    256       1.1  cherry }
    257       1.1  cherry 
    258       1.1  cherry /*
    259       1.1  cherry  * Allocate a new file; must be used instead of malloc()
    260       1.1  cherry  * to ensure safe initialisation.
    261       1.1  cherry  */
    262       1.1  cherry struct preloaded_file *
    263       1.1  cherry file_alloc(void)
    264       1.1  cherry {
    265       1.1  cherry     struct preloaded_file	*fp;
    266       1.1  cherry 
    267       1.1  cherry     if ((fp = alloc(sizeof(struct preloaded_file))) != NULL) {
    268  1.1.92.1     jym 	memset(fp, 0, sizeof(struct preloaded_file));
    269       1.1  cherry 
    270       1.1  cherry 	if (fp->marks = alloc(sizeof(u_long))) {
    271  1.1.92.1     jym 		memset(fp->marks, 0, sizeof(u_long));
    272       1.1  cherry 	}
    273       1.1  cherry     }
    274       1.1  cherry     return (fp);
    275       1.1  cherry }
    276       1.1  cherry 
    277       1.1  cherry /*
    278       1.1  cherry  * Add a module to the chain
    279       1.1  cherry  */
    280       1.1  cherry static void
    281       1.1  cherry file_insert_tail(struct preloaded_file *fp)
    282       1.1  cherry {
    283       1.1  cherry     struct preloaded_file	*cm;
    284       1.1  cherry 
    285       1.1  cherry     /* Append to list of loaded file */
    286       1.1  cherry     fp->f_next = NULL;
    287       1.1  cherry     if (preloaded_files == NULL) {
    288       1.1  cherry 	preloaded_files = fp;
    289       1.1  cherry     } else {
    290       1.1  cherry 	for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next)
    291       1.1  cherry 	    ;
    292       1.1  cherry 	cm->f_next = fp;
    293       1.1  cherry     }
    294       1.1  cherry }
    295       1.1  cherry 
    296