Home | History | Annotate | Line # | Download | only in common
fileload.c revision 1.2.22.2
      1  1.2.22.2     tls /*	$NetBSD: fileload.c,v 1.2.22.2 2014/08/20 00:03:08 tls 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.2.22.1     tls #include <lib/libsa/loadfile.h>
     37  1.2.22.1     tls #include <lib/libkern/libkern.h>
     38       1.1  cherry #include <sys/param.h>
     39       1.1  cherry #include <sys/queue.h>
     40       1.1  cherry 
     41       1.1  cherry #include "bootstrap.h"
     42       1.1  cherry 
     43       1.1  cherry static int			file_load(char *filename, vaddr_t dest, struct preloaded_file **result);
     44       1.1  cherry static int			file_havepath(const char *name);
     45       1.1  cherry static void			file_insert_tail(struct preloaded_file *mp);
     46       1.1  cherry 
     47       1.1  cherry /* load address should be tweaked by first module loaded (kernel) */
     48       1.1  cherry static vaddr_t	loadaddr = 0;
     49       1.1  cherry 
     50       1.1  cherry struct preloaded_file *preloaded_files = NULL;
     51       1.1  cherry 
     52       1.1  cherry /*
     53       1.1  cherry  * load a kernel from disk.
     54       1.1  cherry  *
     55       1.1  cherry  * kernels are loaded as:
     56       1.1  cherry  *
     57       1.1  cherry  * load <path> <options>
     58       1.1  cherry  */
     59       1.1  cherry 
     60       1.1  cherry int
     61       1.1  cherry command_load(int argc, char *argv[])
     62       1.1  cherry {
     63       1.1  cherry     char	*typestr;
     64  1.2.22.2     tls     int		dofile, dokld, ch;
     65       1.1  cherry 
     66       1.1  cherry     dokld = dofile = 0;
     67       1.1  cherry     optind = 1;
     68       1.1  cherry     optreset = 1;
     69       1.1  cherry     typestr = NULL;
     70       1.1  cherry     if (argc == 1) {
     71  1.2.22.2     tls 	command_seterr("no filename specified");
     72       1.1  cherry 	return(CMD_ERROR);
     73       1.1  cherry     }
     74       1.1  cherry     while ((ch = getopt(argc, argv, "k:")) != -1) {
     75       1.1  cherry 	switch(ch) {
     76       1.1  cherry 	case 'k':
     77       1.1  cherry 	    dokld = 1;
     78       1.1  cherry 	    break;
     79       1.1  cherry 	case '?':
     80       1.1  cherry 	default:
     81       1.1  cherry 	    /* getopt has already reported an error */
     82       1.1  cherry 	    return(CMD_OK);
     83       1.1  cherry 	}
     84       1.1  cherry     }
     85       1.1  cherry     argv += (optind - 1);
     86       1.1  cherry     argc -= (optind - 1);
     87       1.1  cherry 
     88       1.1  cherry     /*
     89       1.1  cherry      * Do we have explicit KLD load ?
     90       1.1  cherry      */
     91       1.1  cherry     if (dokld || file_havepath(argv[1])) {
     92  1.2.22.2     tls 	int error = file_loadkernel(argv[1], argc - 2, argv + 2);
     93       1.1  cherry 	if (error == EEXIST)
     94  1.2.22.2     tls 	    command_seterr("warning: KLD '%s' already loaded", argv[1]);
     95  1.2.22.2     tls 	return error == 0 ? CMD_OK : CMD_ERROR;
     96       1.1  cherry     }
     97  1.2.22.2     tls     return CMD_OK;
     98       1.1  cherry }
     99       1.1  cherry 
    100       1.1  cherry 
    101       1.1  cherry int
    102       1.1  cherry command_unload(int argc, char *argv[])
    103       1.1  cherry {
    104       1.1  cherry     struct preloaded_file	*fp;
    105       1.1  cherry 
    106       1.1  cherry     while (preloaded_files != NULL) {
    107       1.1  cherry 	fp = preloaded_files;
    108       1.1  cherry 	preloaded_files = preloaded_files->f_next;
    109       1.1  cherry 	file_discard(fp);
    110       1.1  cherry     }
    111       1.1  cherry     loadaddr = 0;
    112       1.1  cherry     unsetenv("kernelname");
    113       1.1  cherry     return(CMD_OK);
    114       1.1  cherry }
    115       1.1  cherry 
    116       1.1  cherry 
    117       1.1  cherry int
    118       1.1  cherry command_lskern(int argc, char *argv[])
    119       1.1  cherry {
    120       1.1  cherry     struct preloaded_file	*fp;
    121       1.1  cherry     char			lbuf[80];
    122       1.1  cherry     int				ch, verbose;
    123       1.1  cherry 
    124       1.1  cherry     verbose = 0;
    125       1.1  cherry     optind = 1;
    126       1.1  cherry     optreset = 1;
    127       1.1  cherry 
    128       1.1  cherry     pager_open();
    129       1.1  cherry     for (fp = preloaded_files; fp; fp = fp->f_next) {
    130  1.2.22.2     tls 	snprintf(lbuf, sizeof(lbuf), " %p: %s (%s, 0x%lx)\n",
    131       1.1  cherry 		(void *) fp->f_addr, fp->f_name, fp->f_type, (long) fp->f_size);
    132       1.1  cherry 	pager_output(lbuf);
    133       1.1  cherry 	if (fp->f_args != NULL) {
    134       1.1  cherry 	    pager_output("    args: ");
    135       1.1  cherry 	    pager_output(fp->f_args);
    136       1.1  cherry 	    pager_output("\n");
    137       1.1  cherry 	}
    138       1.1  cherry     }
    139       1.1  cherry     pager_close();
    140       1.1  cherry     return(CMD_OK);
    141       1.1  cherry }
    142       1.1  cherry 
    143       1.1  cherry /*
    144       1.1  cherry  * File level interface, functions file_*
    145       1.1  cherry  */
    146       1.1  cherry int
    147       1.1  cherry file_load(char *filename, vaddr_t dest, struct preloaded_file **result)
    148       1.1  cherry {
    149       1.1  cherry     struct preloaded_file *fp;
    150       1.1  cherry     int error;
    151       1.1  cherry     int i;
    152       1.1  cherry 
    153       1.1  cherry     error = EFTYPE;
    154       1.1  cherry     for (i = 0, fp = NULL; file_formats[i] && fp == NULL; i++) {
    155       1.1  cherry 	error = (file_formats[i]->l_load)(filename, dest, &fp);
    156       1.1  cherry 	if (error == 0) {
    157       1.1  cherry 	    fp->f_loader = i;		/* remember the loader */
    158       1.1  cherry 	    *result = fp;
    159       1.1  cherry 	    break;
    160       1.1  cherry 	}
    161       1.1  cherry 	if (error == EFTYPE)
    162       1.1  cherry 	    continue;		/* Unknown to this handler? */
    163       1.1  cherry 	if (error) {
    164  1.2.22.2     tls 	    command_seterr("can't load file '%s': %s",
    165       1.1  cherry 		filename, strerror(error));
    166       1.1  cherry 	    break;
    167       1.1  cherry 	}
    168       1.1  cherry     }
    169       1.1  cherry     return (error);
    170       1.1  cherry }
    171       1.1  cherry 
    172       1.1  cherry /*
    173       1.1  cherry  * Load specified KLD. If path is omitted, then try to locate it via
    174       1.1  cherry  * search path.
    175       1.1  cherry  */
    176       1.1  cherry int
    177       1.1  cherry file_loadkernel(char *filename, int argc, char *argv[])
    178       1.1  cherry {
    179       1.1  cherry     struct preloaded_file	*fp, *last_file;
    180       1.1  cherry     int				err;
    181       1.1  cherry 
    182       1.1  cherry     /*
    183       1.1  cherry      * Check if KLD already loaded
    184       1.1  cherry      */
    185       1.1  cherry     fp = file_findfile(filename, NULL);
    186       1.1  cherry     if (fp) {
    187  1.2.22.2     tls 	command_seterr("warning: KLD '%s' already loaded", filename);
    188       1.1  cherry 	free(filename);
    189       1.1  cherry 	return (0);
    190       1.1  cherry     }
    191       1.1  cherry     for (last_file = preloaded_files;
    192       1.1  cherry 	 last_file != NULL && last_file->f_next != NULL;
    193       1.1  cherry 	 last_file = last_file->f_next)
    194       1.1  cherry 	;
    195       1.1  cherry 
    196       1.1  cherry     do {
    197       1.1  cherry 	err = file_load(filename, loadaddr, &fp);
    198       1.1  cherry 	if (err)
    199       1.1  cherry 	    break;
    200       1.1  cherry 	fp->f_args = unargv(argc, argv);
    201       1.1  cherry 	loadaddr = fp->f_addr + fp->f_size;
    202       1.1  cherry 	file_insert_tail(fp);		/* Add to the list of loaded files */
    203       1.1  cherry     } while(0);
    204       1.1  cherry     if (err == EFTYPE)
    205  1.2.22.2     tls 	command_seterr("don't know how to load module '%s'", filename);
    206       1.1  cherry     if (err && fp)
    207       1.1  cherry 	file_discard(fp);
    208       1.1  cherry     free(filename);
    209       1.1  cherry     return (err);
    210       1.1  cherry }
    211       1.1  cherry 
    212       1.1  cherry /*
    213       1.1  cherry  * Find a file matching (name) and (type).
    214       1.1  cherry  * NULL may be passed as a wildcard to either.
    215       1.1  cherry  */
    216       1.1  cherry struct preloaded_file *
    217       1.1  cherry file_findfile(char *name, char *type)
    218       1.1  cherry {
    219       1.1  cherry     struct preloaded_file *fp;
    220       1.1  cherry 
    221       1.1  cherry     for (fp = preloaded_files; fp != NULL; fp = fp->f_next) {
    222       1.1  cherry 	if (((name == NULL) || !strcmp(name, fp->f_name)) &&
    223       1.1  cherry 	    ((type == NULL) || !strcmp(type, fp->f_type)))
    224       1.1  cherry 	    break;
    225       1.1  cherry     }
    226       1.1  cherry     return (fp);
    227       1.1  cherry }
    228       1.1  cherry 
    229       1.1  cherry /*
    230       1.1  cherry  * Check if file name have any qualifiers
    231       1.1  cherry  */
    232       1.1  cherry static int
    233       1.1  cherry file_havepath(const char *name)
    234       1.1  cherry {
    235       1.1  cherry     const char		*cp;
    236       1.1  cherry 
    237       1.1  cherry     archsw.arch_getdev(NULL, name, &cp);
    238       1.1  cherry     return (cp != name || strchr(name, '/') != NULL);
    239       1.1  cherry }
    240       1.1  cherry 
    241       1.1  cherry /*
    242       1.1  cherry  * Throw a file away
    243       1.1  cherry  */
    244       1.1  cherry void
    245       1.1  cherry file_discard(struct preloaded_file *fp)
    246       1.1  cherry {
    247       1.1  cherry     if (fp == NULL)
    248       1.1  cherry 	return;
    249       1.1  cherry     if (fp->f_name != NULL)
    250       1.1  cherry 	free(fp->f_name);
    251       1.1  cherry     if (fp->f_type != NULL)
    252       1.1  cherry         free(fp->f_type);
    253       1.1  cherry     if (fp->f_args != NULL)
    254       1.1  cherry         free(fp->f_args);
    255       1.1  cherry     if (fp->marks != NULL)
    256       1.1  cherry 	free(fp->marks);
    257       1.1  cherry     free(fp);
    258       1.1  cherry }
    259       1.1  cherry 
    260       1.1  cherry /*
    261       1.1  cherry  * Allocate a new file; must be used instead of malloc()
    262       1.1  cherry  * to ensure safe initialisation.
    263       1.1  cherry  */
    264       1.1  cherry struct preloaded_file *
    265       1.1  cherry file_alloc(void)
    266       1.1  cherry {
    267       1.1  cherry     struct preloaded_file	*fp;
    268       1.1  cherry 
    269       1.1  cherry     if ((fp = alloc(sizeof(struct preloaded_file))) != NULL) {
    270       1.2  cegger 	memset(fp, 0, sizeof(struct preloaded_file));
    271  1.2.22.1     tls /*
    272       1.1  cherry 	if (fp->marks = alloc(sizeof(u_long))) {
    273       1.2  cegger 		memset(fp->marks, 0, sizeof(u_long));
    274       1.1  cherry 	}
    275  1.2.22.1     tls */
    276       1.1  cherry     }
    277       1.1  cherry     return (fp);
    278       1.1  cherry }
    279       1.1  cherry 
    280       1.1  cherry /*
    281       1.1  cherry  * Add a module to the chain
    282       1.1  cherry  */
    283       1.1  cherry static void
    284       1.1  cherry file_insert_tail(struct preloaded_file *fp)
    285       1.1  cherry {
    286       1.1  cherry     struct preloaded_file	*cm;
    287       1.1  cherry 
    288       1.1  cherry     /* Append to list of loaded file */
    289       1.1  cherry     fp->f_next = NULL;
    290       1.1  cherry     if (preloaded_files == NULL) {
    291       1.1  cherry 	preloaded_files = fp;
    292       1.1  cherry     } else {
    293       1.1  cherry 	for (cm = preloaded_files; cm->f_next != NULL; cm = cm->f_next)
    294       1.1  cherry 	    ;
    295       1.1  cherry 	cm->f_next = fp;
    296       1.1  cherry     }
    297       1.1  cherry }
    298       1.1  cherry 
    299