bootstrap.h revision 60938
1104476Ssam/*- 2139825Simp * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3104476Ssam * All rights reserved. 4104476Ssam * 5104476Ssam * Redistribution and use in source and binary forms, with or without 6104476Ssam * modification, are permitted provided that the following conditions 7104476Ssam * are met: 8104476Ssam * 1. Redistributions of source code must retain the above copyright 9104476Ssam * notice, this list of conditions and the following disclaimer. 10104476Ssam * 2. Redistributions in binary form must reproduce the above copyright 11104476Ssam * notice, this list of conditions and the following disclaimer in the 12104476Ssam * documentation and/or other materials provided with the distribution. 13104476Ssam * 14104476Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15104476Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16104476Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17104476Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18104476Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19104476Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20104476Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21104476Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22104476Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23104476Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24104476Ssam * SUCH DAMAGE. 25104476Ssam * 26104476Ssam * $FreeBSD: head/sys/boot/common/bootstrap.h 60938 2000-05-26 02:09:24Z jake $ 27104476Ssam */ 28104476Ssam 29104476Ssam#include <sys/types.h> 30104476Ssam#include <sys/queue.h> 31104476Ssam 32104476Ssam/* XXX debugging */ 33104476Ssamextern struct console vidconsole; 34104476Ssam#define MARK(s, c) {vidconsole.c_out(s); vidconsole.c_out(c); while (!vidconsole.c_ready()) ; vidconsole.c_in();} 35104476Ssam 36104476Ssam/* 37104476Ssam * Generic device specifier; architecture-dependant 38104476Ssam * versions may be larger, but should be allowed to 39116191Sobrien * overlap. 40116191Sobrien */ 41116191Sobrienstruct devdesc 42104476Ssam{ 43104476Ssam struct devsw *d_dev; 44104476Ssam int d_type; 45104476Ssam#define DEVT_NONE 0 46104476Ssam#define DEVT_DISK 1 47104476Ssam#define DEVT_NET 2 48104476Ssam}; 49104476Ssam 50104476Ssam/* Commands and return values; nonzero return sets command_errmsg != NULL */ 51104476Ssamtypedef int (bootblk_cmd_t)(int argc, char *argv[]); 52104476Ssamextern char *command_errmsg; 53104476Ssamextern char command_errbuf[]; /* XXX blah, length */ 54104476Ssam#define CMD_OK 0 55104476Ssam#define CMD_ERROR 1 56104476Ssam 57104476Ssam/* interp.c */ 58104476Ssamextern void interact(void); 59104476Ssamextern int include(char *filename); 60104476Ssam 61104476Ssam/* interp_parse.c */ 62104476Ssamextern int parse(int *argc, char ***argv, char *str); 63104476Ssam 64104476Ssam/* interp_forth.c */ 65104476Ssamextern void bf_init(void); 66104476Ssamextern int bf_run(char *line); 67104476Ssam 68104476Ssam/* boot.c */ 69104476Ssamextern int autoboot(int delay, char *prompt); 70104476Ssamextern void autoboot_maybe(void); 71104476Ssamextern int getrootmount(char *rootdev); 72104476Ssam 73104476Ssam/* misc.c */ 74104476Ssamextern char *unargv(int argc, char *argv[]); 75104476Ssamextern void hexdump(caddr_t region, size_t len); 76104476Ssamextern size_t strlenout(vm_offset_t str); 77104476Ssamextern char *strdupout(vm_offset_t str); 78104476Ssam 79104476Ssam/* bcache.c */ 80104476Ssamextern int bcache_init(int nblks, size_t bsize); 81104476Ssamextern void bcache_flush(); 82104476Ssam 83104476Ssam/* 84104476Ssam * Disk block cache 85104476Ssam */ 86104476Ssamstruct bcache_devdata 87104476Ssam{ 88104476Ssam int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size, void *buf, size_t *rsize); 89104476Ssam void *dv_devdata; 90104476Ssam}; 91104476Ssam 92104476Ssam/* 93104476Ssam * Modular console support. 94104476Ssam */ 95104476Ssamstruct console 96104476Ssam{ 97104476Ssam char *c_name; 98104476Ssam char *c_desc; 99104476Ssam int c_flags; 100104476Ssam#define C_PRESENTIN (1<<0) 101104476Ssam#define C_PRESENTOUT (1<<1) 102104476Ssam#define C_ACTIVEIN (1<<2) 103104476Ssam#define C_ACTIVEOUT (1<<3) 104104476Ssam void (* c_probe)(struct console *cp); /* set c_flags to match hardware */ 105104476Ssam int (* c_init)(int arg); /* reinit XXX may need more args */ 106104476Ssam void (* c_out)(int c); /* emit c */ 107104476Ssam int (* c_in)(void); /* wait for and return input */ 108104476Ssam int (* c_ready)(void); /* return nonzer if input waiting */ 109104476Ssam}; 110104476Ssamextern struct console *consoles[]; 111104476Ssamextern void cons_probe(void); 112104476Ssam 113104476Ssam/* 114104476Ssam * Plug-and-play enumerator/configurator interface. 115104476Ssam */ 116104476Ssamstruct pnphandler 117104476Ssam{ 118104476Ssam char *pp_name; /* handler/bus name */ 119104476Ssam void (* pp_enumerate)(void); /* enumerate PnP devices, add to chain */ 120104476Ssam}; 121104476Ssam 122104476Ssamstruct pnpident 123104476Ssam{ 124104476Ssam char *id_ident; /* ASCII identifier, actual format varies with bus/handler */ 125104476Ssam STAILQ_ENTRY(pnpident) id_link; 126104476Ssam}; 127104476Ssam 128104476Ssamstruct pnpinfo 129104476Ssam{ 130104476Ssam char *pi_desc; /* ASCII description, optional */ 131104476Ssam int pi_revision; /* optional revision (or -1) if not supported */ 132104476Ssam char *pi_module; /* module/args nominated to handle device */ 133104476Ssam int pi_argc; /* module arguments */ 134104476Ssam char **pi_argv; 135104476Ssam struct pnphandler *pi_handler; /* handler which detected this device */ 136104476Ssam STAILQ_HEAD(,pnpident) pi_ident; /* list of identifiers */ 137104476Ssam STAILQ_ENTRY(pnpinfo) pi_link; 138104476Ssam}; 139104476Ssam 140104476Ssamextern struct pnphandler *pnphandlers[]; /* provided by MD code */ 141104476Ssam 142104476Ssamextern void pnp_addident(struct pnpinfo *pi, char *ident); 143104476Ssamextern struct pnpinfo *pnp_allocinfo(void); 144104476Ssamextern void pnp_freeinfo(struct pnpinfo *pi); 145104476Ssamextern void pnp_addinfo(struct pnpinfo *pi); 146104476Ssamextern char *pnp_eisaformat(u_int8_t *data); 147104476Ssam 148104476Ssam/* 149104476Ssam * < 0 - No ISA in system 150104476Ssam * == 0 - Maybe ISA, search for read data port 151104476Ssam * > 0 - ISA in system, value is read data port address 152104476Ssam */ 153104476Ssamextern int isapnp_readport; 154104476Ssam 155104476Ssam/* 156104476Ssam * Preloaded file metadata header. 157104476Ssam * 158104476Ssam * Metadata are allocated on our heap, and copied into kernel space 159104476Ssam * before executing the kernel. 160104476Ssam */ 161104476Ssamstruct file_metadata 162104476Ssam{ 163104476Ssam size_t md_size; 164104476Ssam u_int16_t md_type; 165104476Ssam struct file_metadata *md_next; 166104476Ssam char md_data[0]; /* data are immediately appended */ 167104476Ssam}; 168104476Ssam 169104476Ssamstruct preloaded_file; 170104476Ssam 171104476Ssamstruct kernel_module 172104476Ssam{ 173104476Ssam char *m_name; /* module name */ 174104476Ssam/* char *m_args;*/ /* arguments for the module */ 175104476Ssam struct preloaded_file *m_fp; 176104476Ssam struct kernel_module *m_next; 177104476Ssam}; 178104476Ssam 179104476Ssam/* 180104476Ssam * Preloaded file information. Depending on type, file can contain 181104476Ssam * additional units called 'modules'. 182104476Ssam * 183104476Ssam * At least one file (the kernel) must be loaded in order to boot. 184104476Ssam * The kernel is always loaded first. 185104476Ssam * 186104476Ssam * String fields (m_name, m_type) should be dynamically allocated. 187104476Ssam */ 188104476Ssamstruct preloaded_file 189104476Ssam{ 190104476Ssam char *f_name; /* file name */ 191104476Ssam char *f_type; /* verbose file type, eg 'ELF kernel', 'pnptable', etc. */ 192104476Ssam char *f_args; /* arguments for the file */ 193104476Ssam struct file_metadata *f_metadata; /* metadata that will be placed in the module directory */ 194104476Ssam int f_loader; /* index of the loader that read the file */ 195104476Ssam vm_offset_t f_addr; /* load address */ 196104476Ssam size_t f_size; /* file size */ 197104476Ssam struct kernel_module *f_modules; /* list of modules if any */ 198104476Ssam struct preloaded_file *f_next; /* next file */ 199104476Ssam}; 200104476Ssam 201104476Ssamstruct file_format 202104476Ssam{ 203104476Ssam /* Load function must return EFTYPE if it can't handle the module supplied */ 204104476Ssam int (* l_load)(char *filename, vm_offset_t dest, struct preloaded_file **result); 205104476Ssam /* Only a loader that will load a kernel (first module) should have an exec handler */ 206104476Ssam int (* l_exec)(struct preloaded_file *mp); 207104476Ssam}; 208104476Ssam 209104476Ssamextern struct file_format *file_formats[]; /* supplied by consumer */ 210104476Ssamextern struct preloaded_file *preloaded_files; 211104476Ssam 212104476Ssamextern int mod_load(char *name, int argc, char *argv[]); 213104476Ssamextern int mod_loadobj(char *type, char *name); 214104476Ssam 215104476Ssamstruct preloaded_file *file_alloc(void); 216104476Ssamstruct preloaded_file *file_findfile(char *name, char *type); 217104476Ssamstruct file_metadata *file_findmetadata(struct preloaded_file *fp, int type); 218104476Ssamvoid file_discard(struct preloaded_file *fp); 219104476Ssamvoid file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); 220104476Ssamint file_addmodule(struct preloaded_file *fp, char *modname, 221104476Ssam struct kernel_module **newmp); 222104476Ssam 223104476Ssam 224104476Ssam/* MI module loaders */ 225104476Ssamextern int aout_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result); 226104476Ssamextern vm_offset_t aout_findsym(char *name, struct preloaded_file *fp); 227104476Ssam 228104476Ssamextern int elf_loadfile(char *filename, vm_offset_t dest, struct preloaded_file **result); 229104476Ssam 230104476Ssam#ifndef NEW_LINKER_SET 231104476Ssam#include <sys/linker_set.h> 232104476Ssam 233104476Ssam/* XXX just for conversion's sake, until we move to the new linker set code */ 234104476Ssam 235104476Ssam#define SET_FOREACH(pvar, set) \ 236104476Ssam for ((char*) pvar = set.ls_items; \ 237104476Ssam (char*) pvar < (char*) &set.ls_items[set.ls_length]; \ 238104476Ssam pvar++) 239104476Ssam 240104476Ssam#else /* NEW_LINKER_SET */ 241104476Ssam 242104476Ssam/* 243104476Ssam * Private macros, not to be used outside this header file. 244104476Ssam */ 245104476Ssam#define __MAKE_SET(set, sym) \ 246104476Ssam static void *__CONCAT(__setentry,__LINE__) \ 247104476Ssam __attribute__((__section__("set_" #set),__unused__)) = &sym 248104476Ssam#define __SET_BEGIN(set) \ 249104476Ssam ({ extern void *__CONCAT(__start_set_,set); \ 250104476Ssam &__CONCAT(__start_set_,set); }) 251104476Ssam#define __SET_END(set) \ 252104476Ssam ({ extern void *__CONCAT(__stop_set_,set); \ 253104476Ssam &__CONCAT(__stop_set_,set); }) 254104476Ssam 255104476Ssam/* 256104476Ssam * Public macros. 257104476Ssam */ 258104476Ssam 259104476Ssam/* Add an entry to a set. */ 260104476Ssam#define DATA_SET(set, sym) __MAKE_SET(set, sym) 261104476Ssam 262104476Ssam/* 263104476Ssam * Iterate over all the elements of a set. 264104476Ssam * 265104476Ssam * Sets always contain addresses of things, and "pvar" points to words 266104476Ssam * containing those addresses. Thus is must be declared as "type **pvar", 267104476Ssam * and the address of each set item is obtained inside the loop by "*pvar". 268104476Ssam */ 269104476Ssam#define SET_FOREACH(pvar, set) \ 270104476Ssam for (pvar = (__typeof__(pvar))__SET_BEGIN(set); \ 271104476Ssam pvar < (__typeof__(pvar))__SET_END(set); pvar++) 272104476Ssam#endif 273104476Ssam 274104476Ssam/* 275104476Ssam * Support for commands 276104476Ssam */ 277104476Ssamstruct bootblk_command 278104476Ssam{ 279104476Ssam const char *c_name; 280104476Ssam const char *c_desc; 281104476Ssam bootblk_cmd_t *c_fn; 282104476Ssam}; 283104476Ssam 284104476Ssam#define COMMAND_SET(tag, key, desc, func) \ 285104476Ssam static bootblk_cmd_t func; \ 286104476Ssam static struct bootblk_command _cmd_ ## tag = { key, desc, func }; \ 287104476Ssam DATA_SET(Xcommand_set, _cmd_ ## tag); 288104476Ssam 289104476Ssamextern struct linker_set Xcommand_set; 290104476Ssam 291104476Ssam/* 292104476Ssam * The intention of the architecture switch is to provide a convenient 293104476Ssam * encapsulation of the interface between the bootstrap MI and MD code. 294104476Ssam * MD code may selectively populate the switch at runtime based on the 295104476Ssam * actual configuration of the target system. 296104476Ssam */ 297104476Ssamstruct arch_switch 298104476Ssam{ 299104476Ssam /* Automatically load modules as required by detected hardware */ 300104476Ssam int (* arch_autoload)(); 301104476Ssam /* Locate the device for (name), return pointer to tail in (*path) */ 302104476Ssam int (*arch_getdev)(void **dev, const char *name, const char **path); 303104476Ssam /* Copy from local address space to module address space, similar to bcopy() */ 304104476Ssam int (*arch_copyin)(void *src, vm_offset_t dest, size_t len); 305104476Ssam /* Copy to local address space from module address space, similar to bcopy() */ 306104476Ssam int (*arch_copyout)(vm_offset_t src, void *dest, size_t len); 307104476Ssam /* Read from file to module address space, same semantics as read() */ 308104476Ssam int (*arch_readin)(int fd, vm_offset_t dest, size_t len); 309104476Ssam /* Perform ISA byte port I/O (only for systems with ISA) */ 310104476Ssam int (*arch_isainb)(int port); 311104476Ssam void (*arch_isaoutb)(int port, int value); 312104476Ssam}; 313104476Ssamextern struct arch_switch archsw; 314104476Ssam 315104476Ssam/* This must be provided by the MD code, but should it be in the archsw? */ 316104476Ssamextern void delay(int delay); 317104476Ssam