bootstrap.h revision 40140
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 *	$Id: bootstrap.h,v 1.12 1998/10/09 07:09:22 msmith Exp $
27 */
28
29#include <sys/types.h>
30
31/* XXX debugging */
32extern struct console vidconsole;
33#define MARK(s, c) {vidconsole.c_out(s); vidconsole.c_out(c); while (!vidconsole.c_ready()) ; vidconsole.c_in();}
34
35/*
36 * Generic device specifier; architecture-dependant
37 * versions may be larger, but should be allowed to
38 * overlap.
39 */
40struct devdesc
41{
42    struct devsw	*d_dev;
43    int			d_type;
44#define DEVT_NONE	0
45#define DEVT_DISK	1
46#define DEVT_NET	2
47};
48
49/* Commands and return values; nonzero return sets command_errmsg != NULL */
50typedef int	(bootblk_cmd_t)(int argc, char *argv[]);
51extern char	*command_errmsg;
52extern char	command_errbuf[];	/* XXX blah, length */
53#define CMD_OK		0
54#define CMD_ERROR	1
55
56/* interp.c */
57extern void	interact(void);
58extern void	source(char *filename);
59
60/* interp_parse.c */
61extern int	parse(int *argc, char ***argv, char *str);
62
63/* boot.c */
64extern int	autoboot(int delay, char *prompt);
65extern void	autoboot_maybe(void);
66
67/* misc.c */
68extern char	*unargv(int argc, char *argv[]);
69extern void	hexdump(caddr_t region, size_t len);
70extern size_t	strlenout(vm_offset_t str);
71extern char	*strdupout(vm_offset_t str);
72
73/*
74 * Modular console support.
75 */
76struct console
77{
78    char	*c_name;
79    char	*c_desc;
80    int		c_flags;
81#define C_PRESENTIN	(1<<0)
82#define C_PRESENTOUT	(1<<1)
83#define C_ACTIVEIN	(1<<2)
84#define C_ACTIVEOUT	(1<<3)
85    void	(* c_probe)(struct console *cp);	/* set c_flags to match hardware */
86    int		(* c_init)(int arg);			/* reinit XXX may need more args */
87    void	(* c_out)(int c);			/* emit c */
88    int		(* c_in)(void);				/* wait for and return input */
89    int		(* c_ready)(void);			/* return nonzer if input waiting */
90};
91extern struct console	*consoles[];
92extern void		cons_probe(void);
93
94/*
95 * Plug-and-play enumerator/configurator interface.
96 */
97struct pnpident
98{
99    char		*id_ident;	/* ASCII identifier, actual format varies with bus/handler */
100    struct pnpident	*id_next;	/* the next identifier */
101};
102
103struct pnphandler;
104struct pnpinfo
105{
106    struct pnpident	*pi_ident;	/* list of identifiers */
107    int			pi_revision;	/* optional revision (or -1) if not supported */
108    char		*pi_module;	/* module/args nominated to handle device */
109    int			pi_argc;	/* module arguments */
110    char		**pi_argv;
111    struct pnphandler	*pi_handler;	/* handler which detected this device */
112    struct pnpinfo	*pi_next;
113};
114
115struct pnphandler
116{
117    char	*pp_name;				/* handler/bus name */
118    void	(* pp_enumerate)(struct pnpinfo **);    /* add detected devices to chain */
119};
120
121extern struct pnphandler	*pnphandlers[];		/* provided by MD code */
122
123extern void			pnp_addident(struct pnpinfo *pi, char *ident);
124
125/*
126 * Module metadata header.
127 *
128 * Metadata are allocated on our heap, and copied into kernel space
129 * before executing the kernel.
130 */
131struct module_metadata
132{
133    size_t			md_size;
134    u_int16_t			md_type;
135    struct module_metadata	*md_next;
136    char			md_data[0];	/* data are immediately appended */
137};
138
139/*
140 * Loaded module information.
141 *
142 * At least one module (the kernel) must be loaded in order to boot.
143 * The kernel is always loaded first.
144 *
145 * String fields (m_name, m_type) should be dynamically allocated.
146 */
147struct loaded_module
148{
149    char			*m_name;	/* module name */
150    char			*m_type;	/* verbose module type, eg 'ELF kernel', 'pnptable', etc. */
151    char			*m_args;	/* arguments for the module */
152    struct module_metadata	*m_metadata;	/* metadata that will be placed in the module directory */
153    int				m_loader;	/* index of the loader that read the file */
154    vm_offset_t			m_addr;		/* load address */
155    size_t			m_size;		/* module size */
156    struct loaded_module	*m_next;	/* next module */
157};
158
159struct module_format
160{
161    /* Load function must return EFTYPE if it can't handle the module supplied */
162    int		(* l_load)(char *filename, vm_offset_t dest, struct loaded_module **result);
163    /* Only a loader that will load a kernel (first module) should have an exec handler */
164    int		(* l_exec)(struct loaded_module *mp);
165};
166extern struct module_format	*module_formats[];	/* supplied by consumer */
167extern struct loaded_module	*loaded_modules;
168extern int			mod_load(char *name, int argc, char *argv[]);
169extern int			mod_loadobj(char *type, char *name);
170extern struct loaded_module	*mod_findmodule(char *name, char *type);
171extern void			mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p);
172extern struct module_metadata	*mod_findmetadata(struct loaded_module *mp, int type);
173extern void			mod_discard(struct loaded_module *mp);
174extern struct loaded_module	*mod_allocmodule(void);
175
176
177/* MI module loaders */
178extern int		aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result);
179extern vm_offset_t	aout_findsym(char *name, struct loaded_module *mp);
180
181extern int	elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result);
182
183#if defined(__ELF__)
184
185/*
186 * Alpha GAS needs an align before the section change.  It seems to assume
187 * that after the .previous, it is aligned, so the following .align 3 is
188 * ignored.  Since the previous instructions often contain strings, this is
189 * a problem.
190 */
191
192#ifdef __alpha__
193#define MAKE_SET(set, sym)			\
194	static void const * const __set_##set##_sym_##sym = &sym; \
195	__asm(".align 3");			\
196	__asm(".section .set." #set ",\"aw\"");	\
197	__asm(".quad " #sym);			\
198	__asm(".previous")
199#else
200#define MAKE_SET(set, sym)			\
201	static void const * const __set_##set##_sym_##sym = &sym; \
202	__asm(".section .set." #set ",\"aw\"");	\
203	__asm(".long " #sym);			\
204	__asm(".previous")
205#endif
206#define TEXT_SET(set, sym) MAKE_SET(set, sym)
207#define DATA_SET(set, sym) MAKE_SET(set, sym)
208#define BSS_SET(set, sym)  MAKE_SET(set, sym)
209#define ABS_SET(set, sym)  MAKE_SET(set, sym)
210
211#else
212
213/*
214 * Linker set support, directly from <sys/kernel.h>
215 *
216 * NB: the constants defined below must match those defined in
217 * ld/ld.h.  Since their calculation requires arithmetic, we
218 * can't name them symbolically (e.g., 23 is N_SETT | N_EXT).
219 */
220#define MAKE_SET(set, sym, type) \
221	static void const * const __set_##set##_sym_##sym = &sym; \
222	__asm(".stabs \"_" #set "\", " #type ", 0, 0, _" #sym)
223#define TEXT_SET(set, sym) MAKE_SET(set, sym, 23)
224#define DATA_SET(set, sym) MAKE_SET(set, sym, 25)
225#define BSS_SET(set, sym)  MAKE_SET(set, sym, 27)
226#define ABS_SET(set, sym)  MAKE_SET(set, sym, 21)
227
228#endif
229
230struct linker_set {
231    int             ls_length;
232    const void      *ls_items[1];	/* really ls_length of them, trailing NULL */
233};
234
235/*
236 * Support for commands
237 */
238struct bootblk_command
239{
240    const char		*c_name;
241    const char		*c_desc;
242    bootblk_cmd_t	*c_fn;
243};
244
245#define COMMAND_SET(tag, key, desc, func)				\
246    static bootblk_cmd_t func;						\
247    static struct bootblk_command _cmd_ ## tag = { key, desc, func };	\
248    DATA_SET(Xcommand_set, _cmd_ ## tag);
249
250extern struct linker_set Xcommand_set;
251
252/*
253 * The intention of the architecture switch is to provide a convenient
254 * encapsulation of the interface between the bootstrap MI and MD code.
255 * MD code may selectively populate the switch at runtime based on the
256 * actual configuration of the target system.
257 */
258struct arch_switch
259{
260    /* Automatically load modules as required by detected hardware */
261    int			(* arch_autoload)();
262    /* Locate the device for (name), return pointer to tail in (*path) */
263    int			(*arch_getdev)(void **dev, const char *name, const char **path);
264    /* Copy from local address space to module address space, similar to bcopy() */
265    int			(*arch_copyin)(void *src, vm_offset_t dest, size_t len);
266    /* Copy to local address space from module address space, similar to bcopy() */
267    int			(*arch_copyout)(vm_offset_t src, void *dest, size_t len);
268    /* Read from file to module address space, same semantics as read() */
269    int			(*arch_readin)(int fd, vm_offset_t dest, size_t len);
270    /* Perform ISA byte port I/O (only for systems with ISA) */
271    int			(*arch_isainb)(int port);
272    void		(*arch_isaoutb)(int port, int value);
273};
274extern struct arch_switch archsw;
275
276/* This must be provided by the MD code, but should it be in the archsw? */
277extern void		delay(int delay);
278