1464615aToomas Soome/*
2199767fToomas Soome * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3199767fToomas Soome * All rights reserved.
4199767fToomas Soome *
5199767fToomas Soome * Redistribution and use in source and binary forms, with or without
6199767fToomas Soome * modification, are permitted provided that the following conditions
7199767fToomas Soome * are met:
8199767fToomas Soome * 1. Redistributions of source code must retain the above copyright
9199767fToomas Soome *    notice, this list of conditions and the following disclaimer.
10199767fToomas Soome * 2. Redistributions in binary form must reproduce the above copyright
11199767fToomas Soome *    notice, this list of conditions and the following disclaimer in the
12199767fToomas Soome *    documentation and/or other materials provided with the distribution.
13199767fToomas Soome *
14199767fToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15199767fToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16199767fToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17199767fToomas Soome * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18199767fToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19199767fToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20199767fToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21199767fToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22199767fToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23199767fToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24199767fToomas Soome * SUCH DAMAGE.
25199767fToomas Soome */
26199767fToomas Soome
27199767fToomas Soome#ifndef _BOOTSTRAP_H_
28199767fToomas Soome#define	_BOOTSTRAP_H_
29199767fToomas Soome
30199767fToomas Soome#include <sys/types.h>
31a103f15Toomas Soome#include <stdbool.h>
32199767fToomas Soome#include <sys/queue.h>
33199767fToomas Soome#include <sys/linker_set.h>
34199767fToomas Soome
35199767fToomas Soome/* Commands and return values; nonzero return sets command_errmsg != NULL */
36199767fToomas Soometypedef int	(bootblk_cmd_t)(int argc, char *argv[]);
37199767fToomas Soome#define	COMMAND_ERRBUFSZ	(256)
38199767fToomas Soomeextern const char	*command_errmsg;
39199767fToomas Soomeextern char	command_errbuf[COMMAND_ERRBUFSZ];
40464615aToomas Soome#define	CMD_OK		0
41464615aToomas Soome#define	CMD_WARN	1
42464615aToomas Soome#define	CMD_ERROR	2
43464615aToomas Soome#define	CMD_CRIT	3
44464615aToomas Soome#define	CMD_FATAL	4
45199767fToomas Soome
46199767fToomas Soome/* interp.c */
47199767fToomas Soomevoid	interact(const char *rc);
48199767fToomas Soomeint	include(const char *filename);
49199767fToomas Soome
50199767fToomas Soome/* interp_backslash.c */
51199767fToomas Soomechar	*backslash(char *str);
52199767fToomas Soome
53199767fToomas Soome/* interp_parse.c */
54199767fToomas Soomeint	parse(int *argc, char ***argv, char *str);
55199767fToomas Soome
56199767fToomas Soome/* interp_forth.c */
57199767fToomas Soomevoid	bf_init(char *rc);
58199767fToomas Soomeint	bf_run(char *line);
59199767fToomas Soome
60199767fToomas Soome/* boot.c */
61199767fToomas Soomeint	autoboot(int timeout, char *prompt);
62199767fToomas Soomevoid	autoboot_maybe(void);
63199767fToomas Soomeint	getrootmount(char *rootdev);
64199767fToomas Soome
65199767fToomas Soome/* misc.c */
66199767fToomas Soomechar	*unargv(int argc, char *argv[]);
67199767fToomas Soomevoid	hexdump(caddr_t region, size_t len);
68199767fToomas Soomesize_t	strlenout(vm_offset_t str);
69199767fToomas Soomechar	*strdupout(vm_offset_t str);
70199767fToomas Soomevoid	kern_bzero(vm_offset_t dest, size_t len);
71199767fToomas Soomeint	kern_pread(int fd, vm_offset_t dest, size_t len, off_t off);
72199767fToomas Soomevoid	*alloc_pread(int fd, off_t off, size_t len);
73199767fToomas Soome
74199767fToomas Soome/* bcache.c */
750754251Toomas Soomevoid	bcache_init(size_t nblks, size_t bsize);
76199767fToomas Soomevoid	bcache_add_dev(int);
77199767fToomas Soomevoid	*bcache_allocate(void);
78199767fToomas Soomevoid	bcache_free(void *);
79199767fToomas Soomeint	bcache_strategy(void *devdata, int rw, daddr_t blk,
8038dea91Toomas Soome    size_t size, char *buf, size_t *rsize);
81199767fToomas Soome
82199767fToomas Soome/*
83199767fToomas Soome * Disk block cache
84199767fToomas Soome */
85199767fToomas Soomestruct bcache_devdata
86199767fToomas Soome{
87464615aToomas Soome	int	(*dv_strategy)(void *devdata, int rw, daddr_t blk,
88464615aToomas Soome		size_t size, char *buf, size_t *rsize);
89464615aToomas Soome	void	*dv_devdata;
90464615aToomas Soome	void	*dv_cache;
91199767fToomas Soome};
92199767fToomas Soome
93199767fToomas Soome/*
94199767fToomas Soome * Modular console support.
95199767fToomas Soome */
969e08026Toomas Soomestruct console
97199767fToomas Soome{
98464615aToomas Soome	const char	*c_name;
99464615aToomas Soome	const char	*c_desc;
100464615aToomas Soome	int		c_flags;
101464615aToomas Soome#define	C_PRESENTIN	(1<<0)		/* console can provide input */
102464615aToomas Soome#define	C_PRESENTOUT	(1<<1)		/* console can provide output */
103464615aToomas Soome#define	C_ACTIVEIN	(1<<2)		/* user wants input from console */
104464615aToomas Soome#define	C_ACTIVEOUT	(1<<3)		/* user wants output to console */
105464615aToomas Soome#define	C_WIDEOUT	(1<<4)		/* c_out routine groks wide chars */
106464615aToomas Soome#define	C_MODERAW	(1<<5)		/* raw mode */
107464615aToomas Soome
108464615aToomas Soome	/* set c_flags to match hardware */
109464615aToomas Soome	void	(*c_probe)(struct console *);
110464615aToomas Soome	/* reinit XXX may need more args */
111464615aToomas Soome	int		(*c_init)(struct console *, int);
112464615aToomas Soome	/* emit c */
113464615aToomas Soome	void		(*c_out)(struct console *, int);
114464615aToomas Soome	/* wait for and return input */
115464615aToomas Soome	int		(*c_in)(struct console *);
116464615aToomas Soome	/* return nonzero if input is waiting */
117464615aToomas Soome	int		(*c_ready)(struct console *);
118464615aToomas Soome	int		(*c_ioctl)(struct console *, int, void *);
11980e4791Toomas Soome	/* Print device info */
12080e4791Toomas Soome	void		(*c_devinfo)(struct console *);
121464615aToomas Soome	void		*c_private;	/* private data */
122199767fToomas Soome};
123199767fToomas Soomeextern struct console	*consoles[];
124464615aToomas Soomevoid	cons_probe(void);
125464615aToomas Soomevoid	cons_mode(int);
126464615aToomas Soomevoid	autoload_font(void);
127199767fToomas Soome
128199767fToomas Soome/*
129199767fToomas Soome * Plug-and-play enumerator/configurator interface.
130199767fToomas Soome */
1319e08026Toomas Soomestruct pnphandler
132199767fToomas Soome{
133464615aToomas Soome	const char	*pp_name;		/* handler/bus name */
134464615aToomas Soome	/* enumerate PnP devices, add to chain */
135464615aToomas Soome	void		(*pp_enumerate)(void);
136199767fToomas Soome};
137199767fToomas Soome
138199767fToomas Soomestruct pnpident
139199767fToomas Soome{
140464615aToomas Soome	/* ASCII identifier, actual format varies with bus/handler */
141464615aToomas Soome	char			*id_ident;
142464615aToomas Soome	STAILQ_ENTRY(pnpident)	id_link;
143199767fToomas Soome};
144199767fToomas Soome
145199767fToomas Soomestruct pnpinfo
146199767fToomas Soome{
147464615aToomas Soome	/* ASCII description, optional */
148464615aToomas Soome	char			*pi_desc;
149464615aToomas Soome	/* optional revision (or -1) if not supported */
150464615aToomas Soome	int			pi_revision;
151464615aToomas Soome	/* module/args nominated to handle device */
152464615aToomas Soome	char			*pi_module;
153464615aToomas Soome	/* module arguments */
154464615aToomas Soome	int			pi_argc;
155464615aToomas Soome	char			**pi_argv;
156464615aToomas Soome	/* handler which detected this device */
157464615aToomas Soome	struct pnphandler	*pi_handler;
158464615aToomas Soome	/* list of identifiers */
159464615aToomas Soome	STAILQ_HEAD(, pnpident)	pi_ident;
160464615aToomas Soome	STAILQ_ENTRY(pnpinfo)	pi_link;
161199767fToomas Soome};
162199767fToomas Soome
163199767fToomas SoomeSTAILQ_HEAD(pnpinfo_stql, pnpinfo);
164199767fToomas Soome
165464615aToomas Soomeextern struct pnphandler *pnphandlers[];	/* provided by MD code */
166199767fToomas Soome
167199767fToomas Soomevoid			pnp_addident(struct pnpinfo *pi, char *ident);
168199767fToomas Soomestruct pnpinfo		*pnp_allocinfo(void);
169199767fToomas Soomevoid			pnp_freeinfo(struct pnpinfo *pi);
170199767fToomas Soomevoid			pnp_addinfo(struct pnpinfo *pi);
171464615aToomas Soomechar			*pnp_eisaformat(uint8_t *data);
172199767fToomas Soome
173199767fToomas Soome/*
174199767fToomas Soome *  < 0	- No ISA in system
175199767fToomas Soome * == 0	- Maybe ISA, search for read data port
176199767fToomas Soome *  > 0	- ISA in system, value is read data port address
177199767fToomas Soome */
178199767fToomas Soomeextern int			isapnp_readport;
179199767fToomas Soome
180199767fToomas Soome/*
1819e08026Toomas Soome * Version information
1829e08026Toomas Soome */
1839e08026Toomas Soomeextern char bootprog_info[];
1849e08026Toomas Soome
1859e08026Toomas Soome/*
186199767fToomas Soome * Preloaded file metadata header.
187199767fToomas Soome *
188199767fToomas Soome * Metadata are allocated on our heap, and copied into kernel space
189199767fToomas Soome * before executing the kernel.
190199767fToomas Soome */
1919e08026Toomas Soomestruct file_metadata
192199767fToomas Soome{
193464615aToomas Soome	size_t			md_size;
194464615aToomas Soome	uint16_t		md_type;
195464615aToomas Soome	struct file_metadata	*md_next;
196464615aToomas Soome	/* data are immediately appended */
197464615aToomas Soome	char			md_data[1];
198199767fToomas Soome};
199199767fToomas Soome
200199767fToomas Soomestruct preloaded_file;
201199767fToomas Soomestruct mod_depend;
202199767fToomas Soome
203199767fToomas Soomestruct kernel_module
204199767fToomas Soome{
205464615aToomas Soome	char			*m_name;	/* module name */
206464615aToomas Soome	int			m_version;	/* module version */
207464615aToomas Soome	char			*m_args;	/* arguments for the module */
208464615aToomas Soome	struct preloaded_file	*m_fp;
209464615aToomas Soome	struct kernel_module	*m_next;
210199767fToomas Soome};
211199767fToomas Soome
212199767fToomas Soome/*
213199767fToomas Soome * Preloaded file information. Depending on type, file can contain
214199767fToomas Soome * additional units called 'modules'.
215199767fToomas Soome *
216199767fToomas Soome * At least one file (the kernel) must be loaded in order to boot.
217199767fToomas Soome * The kernel is always loaded first.
218199767fToomas Soome *
219199767fToomas Soome * String fields (m_name, m_type) should be dynamically allocated.
220199767fToomas Soome */
221199767fToomas Soomestruct preloaded_file
222199767fToomas Soome{
223464615aToomas Soome	char			*f_name;	/* file name */
224464615aToomas Soome	/* verbose file type, eg 'ELF kernel', 'pnptable', etc. */
225464615aToomas Soome	char			*f_type;
226464615aToomas Soome	char			*f_args;	/* arguments for the file */
227464615aToomas Soome	/* metadata that will be placed in the module directory */
228464615aToomas Soome	struct file_metadata	*f_metadata;
229464615aToomas Soome	/* index of the loader that read the file */
230464615aToomas Soome	int			f_loader;
231464615aToomas Soome	vm_offset_t		f_addr;		/* load address */
232464615aToomas Soome	size_t			f_size;		/* file size */
233464615aToomas Soome	struct kernel_module	*f_modules;	/* list of modules if any */
234464615aToomas Soome	struct preloaded_file	*f_next;	/* next file */
235199767fToomas Soome};
236199767fToomas Soome
237199767fToomas Soomestruct file_format
238199767fToomas Soome{
239464615aToomas Soome	/*
240464615aToomas Soome	 * Load function must return EFTYPE if it can't handle the module
241464615aToomas Soome	 * supplied.
242464615aToomas Soome	 */
243464615aToomas Soome	int (*l_load)(char *, uint64_t, struct preloaded_file **);
244464615aToomas Soome	/*
245464615aToomas Soome	 * Only a loader that will load a kernel (first module)
246464615aToomas Soome	 * should have an exec handler.
247464615aToomas Soome	 */
248464615aToomas Soome	int (*l_exec)(struct preloaded_file *);
249199767fToomas Soome};
250199767fToomas Soome
251464615aToomas Soomeextern struct file_format *file_formats[];	/* supplied by consumer */
252464615aToomas Soomeextern struct preloaded_file *preloaded_files;
253199767fToomas Soome
254464615aToomas Soomeint mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]);
255464615aToomas Soomeint mod_loadkld(const char *name, int argc, char *argv[]);
256464615aToomas Soomevoid unload(void);
257199767fToomas Soome
258199767fToomas Soomestruct preloaded_file *file_alloc(void);
259199767fToomas Soomestruct preloaded_file *file_findfile(const char *name, const char *type);
260199767fToomas Soomestruct file_metadata *file_findmetadata(struct preloaded_file *fp, int type);
261199767fToomas Soomestruct preloaded_file *file_loadraw(const char *name, char *type, int argc,
262199767fToomas Soome	char **argv, int insert);
263199767fToomas Soomevoid file_discard(struct preloaded_file *fp);
264464615aToomas Soomevoid file_addmetadata(struct preloaded_file *, int, size_t, void *);
265464615aToomas Soomeint  file_addmodule(struct preloaded_file *, char *, int,
266464615aToomas Soome	struct kernel_module **);
26776608ffToomas Soomevoid build_environment_module(void);
2689890ff8Toomas Soomevoid build_font_module(void);
26976608ffToomas Soomevm_offset_t bi_copyenv(vm_offset_t);
270199767fToomas Soome
271199767fToomas Soome/* MI module loaders */
272199767fToomas Soome#ifdef __elfN
273199767fToomas Soome/* Relocation types. */
274464615aToomas Soome#define	ELF_RELOC_REL	1
275464615aToomas Soome#define	ELF_RELOC_RELA	2
276199767fToomas Soome
277199767fToomas Soome/* Relocation offset for some architectures */
278464615aToomas Soomeextern uint64_t __elfN(relocation_offset);
279199767fToomas Soome
280199767fToomas Soomestruct elf_file;
28106469a5Toomas Soometypedef Elf_Addr(symaddr_fn)(struct elf_file *, Elf_Size);
282199767fToomas Soome
283f9feeccToomas Soomeint	elf64_loadfile(char *, uint64_t, struct preloaded_file **);
284f9feeccToomas Soomeint	elf32_loadfile(char *, uint64_t, struct preloaded_file **);
285f9feeccToomas Soomeint	elf64_obj_loadfile(char *, uint64_t, struct preloaded_file **);
286f9feeccToomas Soomeint	elf32_obj_loadfile(char *, uint64_t, struct preloaded_file **);
287199767fToomas Soomeint	__elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr,
288199767fToomas Soome	    const void *reldata, int reltype, Elf_Addr relbase,
289199767fToomas Soome	    Elf_Addr dataaddr, void *data, size_t len);
290f9feeccToomas Soomeint	elf64_loadfile_raw(char *, uint64_t, struct preloaded_file **, int);
291f9feeccToomas Soomeint	elf32_loadfile_raw(char *, uint64_t, struct preloaded_file **, int);
292f9feeccToomas Soomeint	elf64_load_modmetadata(struct preloaded_file *, uint64_t);
293f9feeccToomas Soomeint	elf32_load_modmetadata(struct preloaded_file *, uint64_t);
294199767fToomas Soome#endif
295199767fToomas Soome
296199767fToomas Soome/*
2979e08026Toomas Soome * Support for commands
298199767fToomas Soome */
2999e08026Toomas Soomestruct bootblk_command
300199767fToomas Soome{
301464615aToomas Soome	const char	*c_name;
302464615aToomas Soome	const char	*c_desc;
303464615aToomas Soome	bootblk_cmd_t	*c_fn;
304199767fToomas Soome};
305199767fToomas Soome
306464615aToomas Soome#define	COMMAND_SET(tag, key, desc, func)				\
307199767fToomas Soome    static bootblk_cmd_t func;						\
308199767fToomas Soome    static struct bootblk_command _cmd_ ## tag = { key, desc, func };	\
309199767fToomas Soome    DATA_SET(Xcommand_set, _cmd_ ## tag)
310199767fToomas Soome
311199767fToomas SoomeSET_DECLARE(Xcommand_set, struct bootblk_command);
312199767fToomas Soome
3139e08026Toomas Soome/*
314199767fToomas Soome * The intention of the architecture switch is to provide a convenient
315199767fToomas Soome * encapsulation of the interface between the bootstrap MI and MD code.
316199767fToomas Soome * MD code may selectively populate the switch at runtime based on the
317199767fToomas Soome * actual configuration of the target system.
318199767fToomas Soome */
319199767fToomas Soomestruct arch_switch
320199767fToomas Soome{
321464615aToomas Soome	/* Automatically load modules as required by detected hardware */
322464615aToomas Soome	int	(*arch_autoload)(void);
323464615aToomas Soome	/* Locate the device for (name), return pointer to tail in (*path) */
324464615aToomas Soome	int	(*arch_getdev)(void **dev, const char *name, const char **path);
325464615aToomas Soome	/*
326464615aToomas Soome	 * Copy from local address space to module address space,
327464615aToomas Soome	 * similar to bcopy()
328464615aToomas Soome	 */
329464615aToomas Soome	ssize_t	(*arch_copyin)(const void *src, vm_offset_t dest,
330464615aToomas Soome		const size_t len);
331464615aToomas Soome	/*
332464615aToomas Soome	 * Copy to local address space from module address space,
333464615aToomas Soome	 * similar to bcopy()
334464615aToomas Soome	 */
335464615aToomas Soome	ssize_t	(*arch_copyout)(const vm_offset_t src, void *dest,
336199767fToomas Soome				const size_t len);
337464615aToomas Soome	/* Read from file to module address space, same semantics as read() */
338464615aToomas Soome	ssize_t	(*arch_readin)(const int fd, vm_offset_t dest,
339464615aToomas Soome		const size_t len);
340464615aToomas Soome	/* Perform ISA byte port I/O (only for systems with ISA) */
341464615aToomas Soome	int	(*arch_isainb)(int port);
342464615aToomas Soome	void	(*arch_isaoutb)(int port, int value);
343464615aToomas Soome
344464615aToomas Soome	/*
345464615aToomas Soome	 * Interface to adjust the load address according to the "object"
346464615aToomas Soome	 * being loaded.
347464615aToomas Soome	 */
348464615aToomas Soome	vm_offset_t (*arch_loadaddr)(uint_t type, void *data, vm_offset_t addr);
349199767fToomas Soome#define	LOAD_ELF	1	/* data points to the ELF header. */
35014ee0d2Toomas Soome#define	LOAD_RAW	2	/* data points to the module file name. */
35114ee0d2Toomas Soome#define	LOAD_KERN	3	/* data points to the kernel file name. */
35214ee0d2Toomas Soome#define	LOAD_MEM	4	/* data points to int for buffer size. */
353464615aToomas Soome	/*
354464615aToomas Soome	 * Interface to release the load address.
355464615aToomas Soome	 */
356464615aToomas Soome	void	(*arch_free_loadaddr)(vm_offset_t addr, size_t pages);
357464615aToomas Soome
358464615aToomas Soome	/*
359464615aToomas Soome	 * Interface to inform MD code about a loaded (ELF) segment. This
360464615aToomas Soome	 * can be used to flush caches and/or set up translations.
361464615aToomas Soome	 */
362199767fToomas Soome#ifdef __elfN
363464615aToomas Soome	void	(*arch_loadseg)(Elf_Ehdr *eh, Elf_Phdr *ph, uint64_t delta);
364199767fToomas Soome#else
365464615aToomas Soome	void	(*arch_loadseg)(void *eh, void *ph, uint64_t delta);
366199767fToomas Soome#endif
367199767fToomas Soome
368464615aToomas Soome	/* Probe ZFS pool(s), if needed. */
369464615aToomas Soome	void	(*arch_zfs_probe)(void);
370199767fToomas Soome};
371199767fToomas Soomeextern struct arch_switch archsw;
372199767fToomas Soome
373199767fToomas Soome/* This must be provided by the MD code, but should it be in the archsw? */
374199767fToomas Soomevoid	delay(int delay);
375199767fToomas Soome
376199767fToomas Soomevoid	dev_cleanup(void);
377199767fToomas Soome
378464615aToomas Soome#ifndef CTASSERT		/* Allow lint to override */
379464615aToomas Soome#define	CTASSERT(x)		_CTASSERT(x, __LINE__)
380464615aToomas Soome#define	_CTASSERT(x, y)		__CTASSERT(x, y)
381464615aToomas Soome#define	__CTASSERT(x, y)	typedef char __assert ## y[(x) ? 1 : -1]
382199767fToomas Soome#endif
383199767fToomas Soome
384199767fToomas Soome#endif /* !_BOOTSTRAP_H_ */
385