/*-1* Copyright (c) 1998 Michael Smith <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#ifndef _BOOTSTRAP_H_27#define _BOOTSTRAP_H_2829#include <stand.h>30#include <sys/types.h>31#include <sys/queue.h>32#include <sys/linker_set.h>33#include <stdbool.h>3435#include "readin.h"3637/* Commands and return values; nonzero return sets command_errmsg != NULL */38typedef int (bootblk_cmd_t)(int argc, char *argv[]);39#define COMMAND_ERRBUFSZ (256)40extern const char *command_errmsg;41extern char command_errbuf[COMMAND_ERRBUFSZ];42#define CMD_OK 043#define CMD_WARN 144#define CMD_ERROR 245#define CMD_CRIT 346#define CMD_FATAL 44748/* interp.c */49void interact(void);50void interp_emit_prompt(void);51int interp_builtin_cmd(int argc, char *argv[]);52bool interp_has_builtin_cmd(const char *cmd);5354/* Called by interp.c for interp_*.c embedded interpreters */55int interp_include(const char *); /* Execute commands from filename */56void interp_preinit(void); /* Initialize interpreater execution engine */57void interp_init(void); /* Initialize interpreater and run main script */58int interp_run(const char *); /* Run a single command */5960/* interp_backslash.c */61char *backslash(const char *str);6263/* interp_parse.c */64int parse(int *argc, char ***argv, const char *str);6566/* boot.c */67void autoboot_maybe(void);68int getrootmount(char *rootdev);6970/* misc.c */71char *unargv(int argc, char *argv[]);72size_t strlenout(vm_offset_t str);73char *strdupout(vm_offset_t str);74void kern_bzero(vm_offset_t dest, size_t len);75int kern_pread(readin_handle_t fd, vm_offset_t dest, size_t len, off_t off);76void *alloc_pread(readin_handle_t fd, off_t off, size_t len);7778/* bcache.c */79void bcache_init(size_t nblks, size_t bsize);80void bcache_add_dev(int);81void *bcache_allocate(void);82void bcache_free(void *);83int bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size,84char *buf, size_t *rsize);8586/*87* Disk block cache88*/89struct bcache_devdata90{91int (*dv_strategy)(void *, int, daddr_t, size_t, char *, size_t *);92void *dv_devdata;93void *dv_cache;94};9596/*97* Modular console support.98*/99struct console100{101const char *c_name;102const char *c_desc;103int c_flags;104#define C_PRESENTIN (1<<0) /* console can provide input */105#define C_PRESENTOUT (1<<1) /* console can provide output */106#define C_ACTIVEIN (1<<2) /* user wants input from console */107#define C_ACTIVEOUT (1<<3) /* user wants output to console */108#define C_WIDEOUT (1<<4) /* c_out routine groks wide chars */109110/* set c_flags to match hardware */111void (* c_probe)(struct console *cp);112/* reinit XXX may need more args */113int (* c_init)(int arg);114/* emit c */115void (* c_out)(int c);116/* wait for and return input */117int (* c_in)(void);118/* return nonzero if input waiting */119int (* c_ready)(void);120};121extern struct console *consoles[];122void cons_probe(void);123bool cons_update_mode(bool);124void autoload_font(bool);125126extern int module_verbose;127enum {128MODULE_VERBOSE_SILENT, /* say nothing */129MODULE_VERBOSE_SIZE, /* print name and size */130MODULE_VERBOSE_TWIDDLE, /* show progress */131MODULE_VERBOSE_FULL, /* all we have */132};133134/*135* Plug-and-play enumerator/configurator interface.136*/137struct pnphandler138{139const char *pp_name; /* handler/bus name */140void (*pp_enumerate)(void); /* enumerate PnP devices, add to chain */141};142143struct pnpident144{145/* ASCII identifier, actual format varies with bus/handler */146char *id_ident;147STAILQ_ENTRY(pnpident) id_link;148};149150struct pnpinfo151{152char *pi_desc; /* ASCII description, optional */153int pi_revision; /* optional revision (or -1) if not supported */154char *pi_module; /* module/args nominated to handle device */155int pi_argc; /* module arguments */156char **pi_argv;157struct pnphandler *pi_handler; /* handler which detected this device */158STAILQ_HEAD(, pnpident) pi_ident; /* list of identifiers */159STAILQ_ENTRY(pnpinfo) pi_link;160};161162STAILQ_HEAD(pnpinfo_stql, pnpinfo);163164extern struct pnphandler *pnphandlers[]; /* provided by MD code */165166void pnp_addident(struct pnpinfo *pi, char *ident);167struct pnpinfo *pnp_allocinfo(void);168void pnp_freeinfo(struct pnpinfo *pi);169void pnp_addinfo(struct pnpinfo *pi);170char *pnp_eisaformat(uint8_t *data);171172/*173* < 0 - No ISA in system174* == 0 - Maybe ISA, search for read data port175* > 0 - ISA in system, value is read data port address176*/177extern int isapnp_readport;178179/*180* Version information181*/182extern char bootprog_info[];183extern unsigned bootprog_rev;184185/*186* Interpreter information187*/188extern const char bootprog_interp[];189#define INTERP_DEFINE(interpstr) \190const char bootprog_interp[] = "$Interpreter:" interpstr191192193/*194* Preloaded file metadata header.195*196* Metadata are allocated on our heap, and copied into kernel space197* before executing the kernel.198*/199struct file_metadata200{201size_t md_size;202uint16_t md_type;203vm_offset_t md_addr; /* Valid after copied to kernel space */204struct file_metadata *md_next;205char md_data[1]; /* data are immediately appended */206};207208struct preloaded_file;209struct mod_depend;210211struct kernel_module212{213char *m_name; /* module name */214int m_version; /* module version */215/* char *m_args; */ /* arguments for the module */216struct preloaded_file *m_fp;217struct kernel_module *m_next;218};219220/*221* Preloaded file information. Depending on type, file can contain222* additional units called 'modules'.223*224* At least one file (the kernel) must be loaded in order to boot.225* The kernel is always loaded first.226*227* String fields (m_name, m_type) should be dynamically allocated.228*/229struct preloaded_file230{231char *f_name; /* file name */232char *f_type; /* verbose file type, eg 'elf kernel', 'pnptable', etc. */233char *f_args; /* arguments for the file */234/* metadata that will be placed in the module directory */235struct file_metadata *f_metadata;236int f_loader; /* index of the loader that read the file */237vm_offset_t f_addr; /* load address */238size_t f_size; /* file size */239struct kernel_module *f_modules; /* list of modules if any */240struct preloaded_file *f_next; /* next file */241#if defined(__amd64__) || (defined(__i386__) && defined(EFI))242bool f_kernphys_relocatable;243#endif244#if defined(__i386__) && !defined(EFI)245bool f_tg_kernel_support;246#endif247};248249struct file_format250{251/*252* Load function must return EFTYPE if it can't handle253* the module supplied254*/255int (*l_load)(char *, uint64_t, struct preloaded_file **);256/*257* Only a loader that will load a kernel (first module)258* should have an exec handler259*/260int (*l_exec)(struct preloaded_file *);261};262263extern struct file_format *file_formats[]; /* supplied by consumer */264extern struct preloaded_file *preloaded_files;265266int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]);267int mod_loadkld(const char *name, int argc, char *argv[]);268void unload(void);269270struct preloaded_file *file_alloc(void);271struct preloaded_file *file_findfile(const char *name, const char *type);272struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type);273struct preloaded_file *file_loadraw(const char *name, const char *type, int insert);274void file_discard(struct preloaded_file *fp);275void file_addmetadata(struct preloaded_file *, int, size_t, void *);276int file_addmodule(struct preloaded_file *, char *, int,277struct kernel_module **);278void file_removemetadata(struct preloaded_file *fp);279int file_addbuf(const char *name, const char *type, size_t len, void *buf);280int tslog_init(void);281int tslog_publish(void);282283vm_offset_t build_font_module(vm_offset_t);284vm_offset_t build_splash_module(vm_offset_t);285286/* MI module loaders */287#ifdef __elfN288/* Relocation types. */289#define ELF_RELOC_REL 1290#define ELF_RELOC_RELA 2291292/* Relocation offset for some architectures */293extern uint64_t __elfN(relocation_offset);294295struct elf_file;296typedef Elf_Addr (symaddr_fn)(struct elf_file *ef, Elf_Size symidx);297298int __elfN(loadfile)(char *, uint64_t, struct preloaded_file **);299int __elfN(obj_loadfile)(char *, uint64_t, struct preloaded_file **);300int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr,301const void *reldata, int reltype, Elf_Addr relbase,302Elf_Addr dataaddr, void *data, size_t len);303int __elfN(loadfile_raw)(char *, uint64_t, struct preloaded_file **, int);304int __elfN(load_modmetadata)(struct preloaded_file *, uint64_t);305#endif306307/*308* Support for commands309*/310struct bootblk_command311{312const char *c_name;313const char *c_desc;314bootblk_cmd_t *c_fn;315};316317#define COMMAND_SET(tag, key, desc, func) \318static bootblk_cmd_t func; \319static struct bootblk_command _cmd_ ## tag = { key, desc, func }; \320DATA_SET(Xcommand_set, _cmd_ ## tag)321322SET_DECLARE(Xcommand_set, struct bootblk_command);323324/*325* The intention of the architecture switch is to provide a convenient326* encapsulation of the interface between the bootstrap MI and MD code.327* MD code may selectively populate the switch at runtime based on the328* actual configuration of the target system, though some routines are329* mandatory.330*/331struct arch_switch332{333/* Automatically load modules as required by detected hardware */334int (*arch_autoload)(void);335/* Locate the device for (name), return pointer to tail in (*path) */336int (*arch_getdev)(void **dev, const char *name, const char **path);337/*338* Copy from local address space to module address space,339* similar to bcopy()340*/341ssize_t (*arch_copyin)(const void *, vm_offset_t, const size_t);342/*343* Copy to local address space from module address space,344* similar to bcopy()345*/346ssize_t (*arch_copyout)(const vm_offset_t, void *, const size_t);347/* Read from file to module address space, same semantics as read() */348ssize_t (*arch_readin)(readin_handle_t, vm_offset_t, const size_t);349/* Perform ISA byte port I/O (only for systems with ISA) */350int (*arch_isainb)(int port);351void (*arch_isaoutb)(int port, int value);352353/*354* Interface to inform MD code about a loaded (ELF) segment. This355* can be used to flush caches and/or set up translations.356*/357#ifdef __elfN358void (*arch_loadseg)(Elf_Ehdr *eh, Elf_Phdr *ph, uint64_t delta);359#else360void (*arch_loadseg)(void *eh, void *ph, uint64_t delta);361#endif362363/* Probe ZFS pool(s), if needed. */364void (*arch_zfs_probe)(void);365366/* Return the hypervisor name/type or NULL if not virtualized. */367const char *(*arch_hypervisor)(void);368};369extern struct arch_switch archsw;370371/* This must be provided by the MD code, but should it be in the archsw? */372void delay(int delay);373374int setprint_delay(struct env_var *ev, int flags, const void *value);375376/* common code to set currdev variable. */377int gen_setcurrdev(struct env_var *ev, int flags, const void *value);378int mount_currdev(struct env_var *, int, const void *);379void set_currdev(const char *devname);380381#endif /* !_BOOTSTRAP_H_ */382383384