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