bootstrap.h revision 40597
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.14 1998/10/21 20:07:04 msmith Exp $ 27 */ 28 29#include <sys/types.h> 30#include <sys/queue.h> 31 32/* XXX debugging */ 33extern struct console vidconsole; 34#define MARK(s, c) {vidconsole.c_out(s); vidconsole.c_out(c); while (!vidconsole.c_ready()) ; vidconsole.c_in();} 35 36/* 37 * Generic device specifier; architecture-dependant 38 * versions may be larger, but should be allowed to 39 * overlap. 40 */ 41struct devdesc 42{ 43 struct devsw *d_dev; 44 int d_type; 45#define DEVT_NONE 0 46#define DEVT_DISK 1 47#define DEVT_NET 2 48}; 49 50/* Commands and return values; nonzero return sets command_errmsg != NULL */ 51typedef int (bootblk_cmd_t)(int argc, char *argv[]); 52extern char *command_errmsg; 53extern char command_errbuf[]; /* XXX blah, length */ 54#define CMD_OK 0 55#define CMD_ERROR 1 56 57/* interp.c */ 58extern void interact(void); 59extern void source(char *filename); 60 61/* interp_parse.c */ 62extern int parse(int *argc, char ***argv, char *str); 63 64/* boot.c */ 65extern int autoboot(int delay, char *prompt); 66extern void autoboot_maybe(void); 67 68/* misc.c */ 69extern char *unargv(int argc, char *argv[]); 70extern void hexdump(caddr_t region, size_t len); 71extern size_t strlenout(vm_offset_t str); 72extern char *strdupout(vm_offset_t str); 73 74/* 75 * Modular console support. 76 */ 77struct console 78{ 79 char *c_name; 80 char *c_desc; 81 int c_flags; 82#define C_PRESENTIN (1<<0) 83#define C_PRESENTOUT (1<<1) 84#define C_ACTIVEIN (1<<2) 85#define C_ACTIVEOUT (1<<3) 86 void (* c_probe)(struct console *cp); /* set c_flags to match hardware */ 87 int (* c_init)(int arg); /* reinit XXX may need more args */ 88 void (* c_out)(int c); /* emit c */ 89 int (* c_in)(void); /* wait for and return input */ 90 int (* c_ready)(void); /* return nonzer if input waiting */ 91}; 92extern struct console *consoles[]; 93extern void cons_probe(void); 94 95/* 96 * Plug-and-play enumerator/configurator interface. 97 */ 98struct pnphandler 99{ 100 char *pp_name; /* handler/bus name */ 101 void (* pp_enumerate)(void); /* enumerate PnP devices, add to chain */ 102}; 103 104struct pnpident 105{ 106 char *id_ident; /* ASCII identifier, actual format varies with bus/handler */ 107 STAILQ_ENTRY(pnpident) id_link; 108}; 109 110struct pnpinfo 111{ 112 char *pi_desc; /* ASCII description, optional */ 113 int pi_revision; /* optional revision (or -1) if not supported */ 114 char *pi_module; /* module/args nominated to handle device */ 115 int pi_argc; /* module arguments */ 116 char **pi_argv; 117 struct pnphandler *pi_handler; /* handler which detected this device */ 118 STAILQ_HEAD(,pnpident) pi_ident; /* list of identifiers */ 119 STAILQ_ENTRY(pnpinfo) pi_link; 120}; 121 122extern struct pnphandler *pnphandlers[]; /* provided by MD code */ 123 124extern void pnp_addident(struct pnpinfo *pi, char *ident); 125extern struct pnpinfo *pnp_allocinfo(void); 126extern void pnp_freeinfo(struct pnpinfo *pi); 127extern void pnp_addinfo(struct pnpinfo *pi); 128extern char *pnp_eisaformat(u_int8_t *data); 129 130/* 131 * < 0 - No ISA in system 132 * == 0 - Maybe ISA, search for read data port 133 * > 0 - ISA in system, value is read data port address 134 */ 135extern int isapnp_readport; 136 137/* 138 * Module metadata header. 139 * 140 * Metadata are allocated on our heap, and copied into kernel space 141 * before executing the kernel. 142 */ 143struct module_metadata 144{ 145 size_t md_size; 146 u_int16_t md_type; 147 struct module_metadata *md_next; 148 char md_data[0]; /* data are immediately appended */ 149}; 150 151/* 152 * Loaded module information. 153 * 154 * At least one module (the kernel) must be loaded in order to boot. 155 * The kernel is always loaded first. 156 * 157 * String fields (m_name, m_type) should be dynamically allocated. 158 */ 159struct loaded_module 160{ 161 char *m_name; /* module name */ 162 char *m_type; /* verbose module type, eg 'ELF kernel', 'pnptable', etc. */ 163 char *m_args; /* arguments for the module */ 164 struct module_metadata *m_metadata; /* metadata that will be placed in the module directory */ 165 int m_loader; /* index of the loader that read the file */ 166 vm_offset_t m_addr; /* load address */ 167 size_t m_size; /* module size */ 168 struct loaded_module *m_next; /* next module */ 169}; 170 171struct module_format 172{ 173 /* Load function must return EFTYPE if it can't handle the module supplied */ 174 int (* l_load)(char *filename, vm_offset_t dest, struct loaded_module **result); 175 /* Only a loader that will load a kernel (first module) should have an exec handler */ 176 int (* l_exec)(struct loaded_module *mp); 177}; 178extern struct module_format *module_formats[]; /* supplied by consumer */ 179extern struct loaded_module *loaded_modules; 180extern int mod_load(char *name, int argc, char *argv[]); 181extern int mod_loadobj(char *type, char *name); 182extern struct loaded_module *mod_findmodule(char *name, char *type); 183extern void mod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p); 184extern struct module_metadata *mod_findmetadata(struct loaded_module *mp, int type); 185extern void mod_discard(struct loaded_module *mp); 186extern struct loaded_module *mod_allocmodule(void); 187 188 189/* MI module loaders */ 190extern int aout_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result); 191extern vm_offset_t aout_findsym(char *name, struct loaded_module *mp); 192 193extern int elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module **result); 194 195#ifndef NEW_LINKER_SET 196#if defined(__ELF__) 197 198/* 199 * Alpha GAS needs an align before the section change. It seems to assume 200 * that after the .previous, it is aligned, so the following .align 3 is 201 * ignored. Since the previous instructions often contain strings, this is 202 * a problem. 203 */ 204 205#ifdef __alpha__ 206#define MAKE_SET(set, sym) \ 207 static void const * const __set_##set##_sym_##sym = &sym; \ 208 __asm(".align 3"); \ 209 __asm(".section .set." #set ",\"aw\""); \ 210 __asm(".quad " #sym); \ 211 __asm(".previous") 212#else 213#define MAKE_SET(set, sym) \ 214 static void const * const __set_##set##_sym_##sym = &sym; \ 215 __asm(".section .set." #set ",\"aw\""); \ 216 __asm(".long " #sym); \ 217 __asm(".previous") 218#endif 219#define TEXT_SET(set, sym) MAKE_SET(set, sym) 220#define DATA_SET(set, sym) MAKE_SET(set, sym) 221#define BSS_SET(set, sym) MAKE_SET(set, sym) 222#define ABS_SET(set, sym) MAKE_SET(set, sym) 223 224#else 225 226/* 227 * Linker set support, directly from <sys/kernel.h> 228 * 229 * NB: the constants defined below must match those defined in 230 * ld/ld.h. Since their calculation requires arithmetic, we 231 * can't name them symbolically (e.g., 23 is N_SETT | N_EXT). 232 */ 233#define MAKE_SET(set, sym, type) \ 234 static void const * const __set_##set##_sym_##sym = &sym; \ 235 __asm(".stabs \"_" #set "\", " #type ", 0, 0, _" #sym) 236#define TEXT_SET(set, sym) MAKE_SET(set, sym, 23) 237#define DATA_SET(set, sym) MAKE_SET(set, sym, 25) 238#define BSS_SET(set, sym) MAKE_SET(set, sym, 27) 239#define ABS_SET(set, sym) MAKE_SET(set, sym, 21) 240 241#endif 242 243struct linker_set { 244 int ls_length; 245 const void *ls_items[1]; /* really ls_length of them, trailing NULL */ 246}; 247 248/* XXX just for conversion's sake, until we move to the new linker set code */ 249 250#define SET_FOREACH(pvar, set) \ 251 for (pvar = set.ls_items; \ 252 pvar < set.ls_items + set.ls_length; \ 253 pvar++) 254 255#else /* NEW_LINKER_SET */ 256 257/* 258 * Private macros, not to be used outside this header file. 259 */ 260#define __MAKE_SET(set, sym) \ 261 static void *__CONCAT(__setentry,__LINE__) \ 262 __attribute__((__section__("set_" #set),__unused__)) = &sym 263#define __SET_BEGIN(set) \ 264 ({ extern void *__CONCAT(__start_set_,set); \ 265 &__CONCAT(__start_set_,set); }) 266#define __SET_END(set) \ 267 ({ extern void *__CONCAT(__stop_set_,set); \ 268 &__CONCAT(__stop_set_,set); }) 269 270/* 271 * Public macros. 272 */ 273 274/* Add an entry to a set. */ 275#define TEXT_SET(set, sym) __MAKE_SET(set, sym) 276#define DATA_SET(set, sym) __MAKE_SET(set, sym) 277#define BSS_SET(set, sym) __MAKE_SET(set, sym) 278#define ABS_SET(set, sym) __MAKE_SET(set, sym) 279 280/* 281 * Iterate over all the elements of a set. 282 * 283 * Sets always contain addresses of things, and "pvar" points to words 284 * containing those addresses. Thus is must be declared as "type **pvar", 285 * and the address of each set item is obtained inside the loop by "*pvar". 286 */ 287#define SET_FOREACH(pvar, set) \ 288 for (pvar = (__typeof__(pvar))__SET_BEGIN(set); \ 289 pvar < (__typeof__(pvar))__SET_END(set); pvar++) 290#endif 291 292/* 293 * Support for commands 294 */ 295struct bootblk_command 296{ 297 const char *c_name; 298 const char *c_desc; 299 bootblk_cmd_t *c_fn; 300}; 301 302#define COMMAND_SET(tag, key, desc, func) \ 303 static bootblk_cmd_t func; \ 304 static struct bootblk_command _cmd_ ## tag = { key, desc, func }; \ 305 DATA_SET(Xcommand_set, _cmd_ ## tag); 306 307extern struct linker_set Xcommand_set; 308 309/* 310 * The intention of the architecture switch is to provide a convenient 311 * encapsulation of the interface between the bootstrap MI and MD code. 312 * MD code may selectively populate the switch at runtime based on the 313 * actual configuration of the target system. 314 */ 315struct arch_switch 316{ 317 /* Automatically load modules as required by detected hardware */ 318 int (* arch_autoload)(); 319 /* Locate the device for (name), return pointer to tail in (*path) */ 320 int (*arch_getdev)(void **dev, const char *name, const char **path); 321 /* Copy from local address space to module address space, similar to bcopy() */ 322 int (*arch_copyin)(void *src, vm_offset_t dest, size_t len); 323 /* Copy to local address space from module address space, similar to bcopy() */ 324 int (*arch_copyout)(vm_offset_t src, void *dest, size_t len); 325 /* Read from file to module address space, same semantics as read() */ 326 int (*arch_readin)(int fd, vm_offset_t dest, size_t len); 327 /* Perform ISA byte port I/O (only for systems with ISA) */ 328 int (*arch_isainb)(int port); 329 void (*arch_isaoutb)(int port, int value); 330}; 331extern struct arch_switch archsw; 332 333/* This must be provided by the MD code, but should it be in the archsw? */ 334extern void delay(int delay); 335