Index: head/stand/common/bootstrap.h =================================================================== --- head/stand/common/bootstrap.h (revision 330863) +++ head/stand/common/bootstrap.h (revision 330864) @@ -1,339 +1,339 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _BOOTSTRAP_H_ #define _BOOTSTRAP_H_ #include #include #include /* Commands and return values; nonzero return sets command_errmsg != NULL */ typedef int (bootblk_cmd_t)(int argc, char *argv[]); #define COMMAND_ERRBUFSZ (256) extern char *command_errmsg; extern char command_errbuf[COMMAND_ERRBUFSZ]; #define CMD_OK 0 #define CMD_WARN 1 #define CMD_ERROR 2 #define CMD_CRIT 3 #define CMD_FATAL 4 /* interp.c */ void interact(void); void interp_emit_prompt(void); int interp_builtin_cmd(int argc, char *argv[]); /* Called by interp.c for interp_*.c embedded interpreters */ int interp_include(const char *filename); /* Execute commands from filename */ void interp_init(void); /* Initialize interpreater */ int interp_run(const char *line); /* Run a single command */ /* interp_backslash.c */ char *backslash(const char *str); /* interp_parse.c */ int parse(int *argc, char ***argv, const char *str); /* boot.c */ int autoboot(int timeout, char *prompt); void autoboot_maybe(void); int getrootmount(char *rootdev); /* misc.c */ char *unargv(int argc, char *argv[]); void hexdump(caddr_t region, size_t len); size_t strlenout(vm_offset_t str); char *strdupout(vm_offset_t str); void kern_bzero(vm_offset_t dest, size_t len); int kern_pread(int fd, vm_offset_t dest, size_t len, off_t off); void *alloc_pread(int fd, off_t off, size_t len); /* bcache.c */ void bcache_init(size_t nblks, size_t bsize); void bcache_add_dev(int); void *bcache_allocate(void); void bcache_free(void *); int bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize); /* * Disk block cache */ struct bcache_devdata { int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize); void *dv_devdata; void *dv_cache; }; /* * Modular console support. */ struct console { const char *c_name; const char *c_desc; int c_flags; #define C_PRESENTIN (1<<0) /* console can provide input */ #define C_PRESENTOUT (1<<1) /* console can provide output */ #define C_ACTIVEIN (1<<2) /* user wants input from console */ #define C_ACTIVEOUT (1<<3) /* user wants output to console */ #define C_WIDEOUT (1<<4) /* c_out routine groks wide chars */ void (* c_probe)(struct console *cp); /* set c_flags to match hardware */ int (* c_init)(int arg); /* reinit XXX may need more args */ void (* c_out)(int c); /* emit c */ int (* c_in)(void); /* wait for and return input */ int (* c_ready)(void); /* return nonzer if input waiting */ }; extern struct console *consoles[]; void cons_probe(void); /* * Plug-and-play enumerator/configurator interface. */ struct pnphandler { const char *pp_name; /* handler/bus name */ void (* pp_enumerate)(void); /* enumerate PnP devices, add to chain */ }; struct pnpident { char *id_ident; /* ASCII identifier, actual format varies with bus/handler */ STAILQ_ENTRY(pnpident) id_link; }; struct pnpinfo { char *pi_desc; /* ASCII description, optional */ int pi_revision; /* optional revision (or -1) if not supported */ char *pi_module; /* module/args nominated to handle device */ int pi_argc; /* module arguments */ char **pi_argv; struct pnphandler *pi_handler; /* handler which detected this device */ STAILQ_HEAD(,pnpident) pi_ident; /* list of identifiers */ STAILQ_ENTRY(pnpinfo) pi_link; }; STAILQ_HEAD(pnpinfo_stql, pnpinfo); extern struct pnphandler *pnphandlers[]; /* provided by MD code */ void pnp_addident(struct pnpinfo *pi, char *ident); struct pnpinfo *pnp_allocinfo(void); void pnp_freeinfo(struct pnpinfo *pi); void pnp_addinfo(struct pnpinfo *pi); -char *pnp_eisaformat(u_int8_t *data); +char *pnp_eisaformat(uint8_t *data); /* * < 0 - No ISA in system * == 0 - Maybe ISA, search for read data port * > 0 - ISA in system, value is read data port address */ extern int isapnp_readport; /* * Preloaded file metadata header. * * Metadata are allocated on our heap, and copied into kernel space * before executing the kernel. */ struct file_metadata { size_t md_size; - u_int16_t md_type; + uint16_t md_type; struct file_metadata *md_next; char md_data[1]; /* data are immediately appended */ }; struct preloaded_file; struct mod_depend; struct kernel_module { char *m_name; /* module name */ int m_version; /* module version */ /* char *m_args;*/ /* arguments for the module */ struct preloaded_file *m_fp; struct kernel_module *m_next; }; /* * Preloaded file information. Depending on type, file can contain * additional units called 'modules'. * * At least one file (the kernel) must be loaded in order to boot. * The kernel is always loaded first. * * String fields (m_name, m_type) should be dynamically allocated. */ struct preloaded_file { char *f_name; /* file name */ char *f_type; /* verbose file type, eg 'ELF kernel', 'pnptable', etc. */ char *f_args; /* arguments for the file */ struct file_metadata *f_metadata; /* metadata that will be placed in the module directory */ int f_loader; /* index of the loader that read the file */ vm_offset_t f_addr; /* load address */ size_t f_size; /* file size */ struct kernel_module *f_modules; /* list of modules if any */ struct preloaded_file *f_next; /* next file */ }; struct file_format { /* Load function must return EFTYPE if it can't handle the module supplied */ - int (* l_load)(char *filename, u_int64_t dest, struct preloaded_file **result); + int (* l_load)(char *filename, uint64_t dest, struct preloaded_file **result); /* Only a loader that will load a kernel (first module) should have an exec handler */ int (* l_exec)(struct preloaded_file *mp); }; extern struct file_format *file_formats[]; /* supplied by consumer */ extern struct preloaded_file *preloaded_files; int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]); int mod_loadkld(const char *name, int argc, char *argv[]); void unload(void); struct preloaded_file *file_alloc(void); struct preloaded_file *file_findfile(const char *name, const char *type); struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type); struct preloaded_file *file_loadraw(const char *name, char *type, int insert); void file_discard(struct preloaded_file *fp); void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p); int file_addmodule(struct preloaded_file *fp, char *modname, int version, struct kernel_module **newmp); void file_removemetadata(struct preloaded_file *fp); /* MI module loaders */ #ifdef __elfN /* Relocation types. */ #define ELF_RELOC_REL 1 #define ELF_RELOC_RELA 2 /* Relocation offset for some architectures */ -extern u_int64_t __elfN(relocation_offset); +extern uint64_t __elfN(relocation_offset); struct elf_file; typedef Elf_Addr (symaddr_fn)(struct elf_file *ef, Elf_Size symidx); -int __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result); -int __elfN(obj_loadfile)(char *filename, u_int64_t dest, +int __elfN(loadfile)(char *filename, uint64_t dest, struct preloaded_file **result); +int __elfN(obj_loadfile)(char *filename, uint64_t dest, struct preloaded_file **result); int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr, const void *reldata, int reltype, Elf_Addr relbase, Elf_Addr dataaddr, void *data, size_t len); -int __elfN(loadfile_raw)(char *filename, u_int64_t dest, +int __elfN(loadfile_raw)(char *filename, uint64_t dest, struct preloaded_file **result, int multiboot); -int __elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest); +int __elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest); #endif /* * Support for commands */ struct bootblk_command { const char *c_name; const char *c_desc; bootblk_cmd_t *c_fn; }; #define COMMAND_SET(tag, key, desc, func) \ static bootblk_cmd_t func; \ static struct bootblk_command _cmd_ ## tag = { key, desc, func }; \ DATA_SET(Xcommand_set, _cmd_ ## tag) SET_DECLARE(Xcommand_set, struct bootblk_command); /* * The intention of the architecture switch is to provide a convenient * encapsulation of the interface between the bootstrap MI and MD code. * MD code may selectively populate the switch at runtime based on the * actual configuration of the target system. */ struct arch_switch { /* Automatically load modules as required by detected hardware */ int (*arch_autoload)(void); /* Locate the device for (name), return pointer to tail in (*path) */ int (*arch_getdev)(void **dev, const char *name, const char **path); /* Copy from local address space to module address space, similar to bcopy() */ ssize_t (*arch_copyin)(const void *src, vm_offset_t dest, const size_t len); /* Copy to local address space from module address space, similar to bcopy() */ ssize_t (*arch_copyout)(const vm_offset_t src, void *dest, const size_t len); /* Read from file to module address space, same semantics as read() */ ssize_t (*arch_readin)(const int fd, vm_offset_t dest, const size_t len); /* Perform ISA byte port I/O (only for systems with ISA) */ int (*arch_isainb)(int port); void (*arch_isaoutb)(int port, int value); /* * Interface to adjust the load address according to the "object" * being loaded. */ uint64_t (*arch_loadaddr)(u_int type, void *data, uint64_t addr); #define LOAD_ELF 1 /* data points to the ELF header. */ #define LOAD_RAW 2 /* data points to the file name. */ /* * Interface to inform MD code about a loaded (ELF) segment. This * can be used to flush caches and/or set up translations. */ #ifdef __elfN void (*arch_loadseg)(Elf_Ehdr *eh, Elf_Phdr *ph, uint64_t delta); #else void (*arch_loadseg)(void *eh, void *ph, uint64_t delta); #endif /* Probe ZFS pool(s), if needed. */ void (*arch_zfs_probe)(void); /* For kexec-type loaders, get ksegment structure */ void (*arch_kexec_kseg_get)(int *nseg, void **kseg); }; extern struct arch_switch archsw; /* This must be provided by the MD code, but should it be in the archsw? */ void delay(int delay); void dev_cleanup(void); time_t time(time_t *tloc); #ifndef CTASSERT /* Allow lint to override */ #define CTASSERT(x) _CTASSERT(x, __LINE__) #define _CTASSERT(x, y) __CTASSERT(x, y) #define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] #endif #endif /* !_BOOTSTRAP_H_ */ Index: head/stand/common/isapnp.c =================================================================== --- head/stand/common/isapnp.c (revision 330863) +++ head/stand/common/isapnp.c (revision 330864) @@ -1,313 +1,313 @@ /*- * Copyright (c) 1998, Michael Smith * Copyright (c) 1996, Sujal M. Patel * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Machine-independant ISA PnP enumerator implementing a subset of the * ISA PnP specification. */ #include #include #include #include #define inb(x) (archsw.arch_isainb((x))) #define outb(x,y) (archsw.arch_isaoutb((x),(y))) static void isapnp_write(int d, int r); static void isapnp_send_Initiation_LFSR(void); -static int isapnp_get_serial(u_int8_t *p); +static int isapnp_get_serial(uint8_t *p); static int isapnp_isolation_protocol(void); static void isapnp_enumerate(void); /* PnP read data port */ int isapnp_readport = 0; #define _PNP_ID_LEN 9 struct pnphandler isapnphandler = { "ISA bus", isapnp_enumerate }; static void isapnp_write(int d, int r) { outb (_PNP_ADDRESS, d); outb (_PNP_WRITE_DATA, r); } /* * Send Initiation LFSR as described in "Plug and Play ISA Specification", * Intel May 94. */ static void isapnp_send_Initiation_LFSR(void) { int cur, i; /* Reset the LSFR */ outb(_PNP_ADDRESS, 0); outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */ cur = 0x6a; outb(_PNP_ADDRESS, cur); for (i = 1; i < 32; i++) { cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff); outb(_PNP_ADDRESS, cur); } } /* * Get the device's serial number. Returns 1 if the serial is valid. */ static int -isapnp_get_serial(u_int8_t *data) +isapnp_get_serial(uint8_t *data) { int i, bit, valid = 0, sum = 0x6a; bzero(data, _PNP_ID_LEN); outb(_PNP_ADDRESS, SERIAL_ISOLATION); for (i = 0; i < 72; i++) { bit = inb(isapnp_readport) == 0x55; delay(250); /* Delay 250 usec */ /* Can't Short Circuit the next evaluation, so 'and' is last */ bit = (inb(isapnp_readport) == 0xaa) && bit; delay(250); /* Delay 250 usec */ valid = valid || bit; if (i < 64) sum = (sum >> 1) | (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff); data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0); } valid = valid && (data[8] == sum); return valid; } /* * Fills the buffer with resource info from the device. * Returns nonzero if the device fails to report */ static int -isapnp_get_resource_info(u_int8_t *buffer, int len) +isapnp_get_resource_info(uint8_t *buffer, int len) { int i, j; u_char temp; for (i = 0; i < len; i++) { outb(_PNP_ADDRESS, STATUS); for (j = 0; j < 100; j++) { if ((inb(isapnp_readport)) & 0x1) break; delay(1); } if (j == 100) { printf("PnP device failed to report resource data\n"); return(1); } outb(_PNP_ADDRESS, RESOURCE_DATA); temp = inb(isapnp_readport); if (buffer != NULL) buffer[i] = temp; } return(0); } /* * Scan Resource Data for useful information. * * We scan the resource data for compatible device IDs and * identifier strings; we only take the first identifier string * and assume it's for the card as a whole. * * Returns 0 if the scan completed OK, nonzero on error. */ static int isapnp_scan_resdata(struct pnpinfo *pi) { u_char tag, resinfo[8]; u_int limit; size_t large_len; u_char *str; limit = 1000; while ((limit-- > 0) && !isapnp_get_resource_info(&tag, 1)) { if (PNP_RES_TYPE(tag) == 0) { /* Small resource */ switch (PNP_SRES_NUM(tag)) { case COMP_DEVICE_ID: /* Got a compatible device id resource */ if (isapnp_get_resource_info(resinfo, PNP_SRES_LEN(tag))) return(1); pnp_addident(pi, pnp_eisaformat(resinfo)); case END_TAG: return(0); break; default: /* Skip this resource */ if (isapnp_get_resource_info(NULL, PNP_SRES_LEN(tag))) return(1); break; } } else { /* Large resource */ if (isapnp_get_resource_info(resinfo, 2)) return(1); large_len = resinfo[1]; large_len = (large_len << 8) + resinfo[0]; switch(PNP_LRES_NUM(tag)) { case ID_STRING_ANSI: str = malloc(large_len + 1); if (isapnp_get_resource_info(str, (ssize_t)large_len)) { free(str); return(1); } str[large_len] = 0; if (pi->pi_desc == NULL) { pi->pi_desc = (char *)str; } else { free(str); } break; default: /* Large resource, skip it */ if (isapnp_get_resource_info(NULL, (ssize_t)large_len)) return(1); } } } return(1); } /* * Run the isolation protocol. Upon exiting, all cards are aware that * they should use isapnp_readport as the READ_DATA port. */ static int isapnp_isolation_protocol(void) { int csn; struct pnpinfo *pi; - u_int8_t cardid[_PNP_ID_LEN]; + uint8_t cardid[_PNP_ID_LEN]; int ndevs; isapnp_send_Initiation_LFSR(); ndevs = 0; isapnp_write(CONFIG_CONTROL, 0x04); /* Reset CSN for All Cards */ for (csn = 1; ; csn++) { /* Wake up cards without a CSN (ie. all of them) */ isapnp_write(WAKE, 0); isapnp_write(SET_RD_DATA, (isapnp_readport >> 2)); outb(_PNP_ADDRESS, SERIAL_ISOLATION); delay(1000); /* Delay 1 msec */ if (isapnp_get_serial(cardid)) { isapnp_write(SET_CSN, csn); pi = pnp_allocinfo(); ndevs++; pnp_addident(pi, pnp_eisaformat(cardid)); /* scan the card obtaining all the identifiers it holds */ if (isapnp_scan_resdata(pi)) { pnp_freeinfo(pi); /* error getting data, ignore */ } else { pnp_addinfo(pi); } } else { break; } } /* Move all cards to wait-for-key state */ while (--csn > 0) { isapnp_send_Initiation_LFSR(); isapnp_write(WAKE, csn); isapnp_write(CONFIG_CONTROL, 0x02); delay(1000); /* XXX is it really necessary ? */ csn--; } return(ndevs); } /* * Locate ISA-PnP devices and populate the supplied list. */ static void isapnp_enumerate(void) { int pnp_rd_port; /* Check for I/O port access */ if ((archsw.arch_isainb == NULL) || (archsw.arch_isaoutb == NULL)) return; /* * Validate a possibly-suggested read port value. If the autoscan failed * last time, this will return us to autoscan mode again. */ if ((isapnp_readport > 0) && (((isapnp_readport < 0x203) || (isapnp_readport > 0x3ff) || (isapnp_readport & 0x3) != 0x3))) /* invalid, go look for ourselves */ isapnp_readport = 0; if (isapnp_readport < 0) { /* someone is telling us there is no ISA in the system */ return; } else if (isapnp_readport > 0) { /* Someone has told us where the port is/should be, or we found one last time */ isapnp_isolation_protocol(); } else { /* No clues, look for it ourselves */ for (pnp_rd_port = 0x80; pnp_rd_port < 0xff; pnp_rd_port += 0x10) { /* Look for something, quit when we find it */ isapnp_readport = (pnp_rd_port << 2) | 0x3; if (isapnp_isolation_protocol() > 0) break; } } } Index: head/stand/common/load_elf.c =================================================================== --- head/stand/common/load_elf.c (revision 330863) +++ head/stand/common/load_elf.c (revision 330864) @@ -1,1216 +1,1216 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 1998 Peter Wemm * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #define FREEBSD_ELF #include #include "bootstrap.h" #define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l) #if defined(__i386__) && __ELF_WORD_SIZE == 64 #undef ELF_TARG_CLASS #undef ELF_TARG_MACH #define ELF_TARG_CLASS ELFCLASS64 #define ELF_TARG_MACH EM_X86_64 #endif typedef struct elf_file { Elf_Phdr *ph; Elf_Ehdr *ehdr; Elf_Sym *symtab; Elf_Hashelt *hashtab; Elf_Hashelt nbuckets; Elf_Hashelt nchains; Elf_Hashelt *buckets; Elf_Hashelt *chains; Elf_Rel *rel; size_t relsz; Elf_Rela *rela; size_t relasz; char *strtab; size_t strsz; int fd; caddr_t firstpage; size_t firstlen; int kernel; - u_int64_t off; + uint64_t off; } *elf_file_t; static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, - u_int64_t loadaddr); + uint64_t loadaddr); static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym); static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p, void *val, size_t len); static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p_start, Elf_Addr p_end); static symaddr_fn __elfN(symaddr); static char *fake_modname(const char *name); const char *__elfN(kerneltype) = "elf kernel"; const char *__elfN(moduletype) = "elf module"; -u_int64_t __elfN(relocation_offset) = 0; +uint64_t __elfN(relocation_offset) = 0; extern void elf_wrong_field_size(void); #define CONVERT_FIELD(b, f, e) \ switch (sizeof((b)->f)) { \ case 2: \ (b)->f = e ## 16toh((b)->f); \ break; \ case 4: \ (b)->f = e ## 32toh((b)->f); \ break; \ case 8: \ (b)->f = e ## 64toh((b)->f); \ break; \ default: \ /* Force a link time error. */ \ elf_wrong_field_size(); \ break; \ } #define CONVERT_SWITCH(h, d, f) \ switch ((h)->e_ident[EI_DATA]) { \ case ELFDATA2MSB: \ f(d, be); \ break; \ case ELFDATA2LSB: \ f(d, le); \ break; \ default: \ return (EINVAL); \ } static int elf_header_convert(Elf_Ehdr *ehdr) { /* * Fixup ELF header endianness. * * The Xhdr structure was loaded using block read call to optimize file * accesses. It might happen, that the endianness of the system memory * is different that endianness of the ELF header. Swap fields here to * guarantee that Xhdr always contain valid data regardless of * architecture. */ #define HEADER_FIELDS(b, e) \ CONVERT_FIELD(b, e_type, e); \ CONVERT_FIELD(b, e_machine, e); \ CONVERT_FIELD(b, e_version, e); \ CONVERT_FIELD(b, e_entry, e); \ CONVERT_FIELD(b, e_phoff, e); \ CONVERT_FIELD(b, e_shoff, e); \ CONVERT_FIELD(b, e_flags, e); \ CONVERT_FIELD(b, e_ehsize, e); \ CONVERT_FIELD(b, e_phentsize, e); \ CONVERT_FIELD(b, e_phnum, e); \ CONVERT_FIELD(b, e_shentsize, e); \ CONVERT_FIELD(b, e_shnum, e); \ CONVERT_FIELD(b, e_shstrndx, e) CONVERT_SWITCH(ehdr, ehdr, HEADER_FIELDS); #undef HEADER_FIELDS return (0); } static int elf_program_header_convert(const Elf_Ehdr *ehdr, Elf_Phdr *phdr) { #define PROGRAM_HEADER_FIELDS(b, e) \ CONVERT_FIELD(b, p_type, e); \ CONVERT_FIELD(b, p_flags, e); \ CONVERT_FIELD(b, p_offset, e); \ CONVERT_FIELD(b, p_vaddr, e); \ CONVERT_FIELD(b, p_paddr, e); \ CONVERT_FIELD(b, p_filesz, e); \ CONVERT_FIELD(b, p_memsz, e); \ CONVERT_FIELD(b, p_align, e) CONVERT_SWITCH(ehdr, phdr, PROGRAM_HEADER_FIELDS); #undef PROGRAM_HEADER_FIELDS return (0); } static int elf_section_header_convert(const Elf_Ehdr *ehdr, Elf_Shdr *shdr) { #define SECTION_HEADER_FIELDS(b, e) \ CONVERT_FIELD(b, sh_name, e); \ CONVERT_FIELD(b, sh_type, e); \ CONVERT_FIELD(b, sh_link, e); \ CONVERT_FIELD(b, sh_info, e); \ CONVERT_FIELD(b, sh_flags, e); \ CONVERT_FIELD(b, sh_addr, e); \ CONVERT_FIELD(b, sh_offset, e); \ CONVERT_FIELD(b, sh_size, e); \ CONVERT_FIELD(b, sh_addralign, e); \ CONVERT_FIELD(b, sh_entsize, e) CONVERT_SWITCH(ehdr, shdr, SECTION_HEADER_FIELDS); #undef SECTION_HEADER_FIELDS return (0); } #undef CONVERT_SWITCH #undef CONVERT_FIELD static int __elfN(load_elf_header)(char *filename, elf_file_t ef) { ssize_t bytes_read; Elf_Ehdr *ehdr; int err; /* * Open the image, read and validate the ELF header */ if (filename == NULL) /* can't handle nameless */ return (EFTYPE); if ((ef->fd = open(filename, O_RDONLY)) == -1) return (errno); ef->firstpage = malloc(PAGE_SIZE); if (ef->firstpage == NULL) { close(ef->fd); return (ENOMEM); } bytes_read = read(ef->fd, ef->firstpage, PAGE_SIZE); ef->firstlen = (size_t)bytes_read; if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) { err = EFTYPE; /* could be EIO, but may be small file */ goto error; } ehdr = ef->ehdr = (Elf_Ehdr *)ef->firstpage; /* Is it ELF? */ if (!IS_ELF(*ehdr)) { err = EFTYPE; goto error; } if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ ehdr->e_ident[EI_DATA] != ELF_TARG_DATA || ehdr->e_ident[EI_VERSION] != EV_CURRENT) /* Version ? */ { err = EFTYPE; goto error; } err = elf_header_convert(ehdr); if (err) goto error; if (ehdr->e_version != EV_CURRENT || ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */ err = EFTYPE; goto error; } return (0); error: if (ef->firstpage != NULL) { free(ef->firstpage); ef->firstpage = NULL; } if (ef->fd != -1) { close(ef->fd); ef->fd = -1; } return (err); } /* * Attempt to load the file (file) as an ELF module. It will be stored at * (dest), and a pointer to a module structure describing the loaded object * will be saved in (result). */ int -__elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result) +__elfN(loadfile)(char *filename, uint64_t dest, struct preloaded_file **result) { return (__elfN(loadfile_raw)(filename, dest, result, 0)); } int -__elfN(loadfile_raw)(char *filename, u_int64_t dest, +__elfN(loadfile_raw)(char *filename, uint64_t dest, struct preloaded_file **result, int multiboot) { struct preloaded_file *fp, *kfp; struct elf_file ef; Elf_Ehdr *ehdr; int err; fp = NULL; bzero(&ef, sizeof(struct elf_file)); ef.fd = -1; err = __elfN(load_elf_header)(filename, &ef); if (err != 0) return (err); ehdr = ef.ehdr; /* * Check to see what sort of module we are. */ kfp = file_findfile(NULL, __elfN(kerneltype)); #ifdef __powerpc__ /* * Kernels can be ET_DYN, so just assume the first loaded object is the * kernel. This assumption will be checked later. */ if (kfp == NULL) ef.kernel = 1; #endif if (ef.kernel || ehdr->e_type == ET_EXEC) { /* Looks like a kernel */ if (kfp != NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n"); err = EPERM; goto oerr; } /* * Calculate destination address based on kernel entrypoint. * * For ARM, the destination address is independent of any values * in the elf header (an ARM kernel can be loaded at any 2MB * boundary), so we leave dest set to the value calculated by * archsw.arch_loadaddr() and passed in to this function. */ #ifndef __arm__ if (ehdr->e_type == ET_EXEC) dest = (ehdr->e_entry & ~PAGE_MASK); #endif if ((ehdr->e_entry & ~PAGE_MASK) == 0) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: not a kernel (maybe static binary?)\n"); err = EPERM; goto oerr; } ef.kernel = 1; } else if (ehdr->e_type == ET_DYN) { /* Looks like a kld module */ if (multiboot != 0) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n"); err = EPERM; goto oerr; } if (kfp == NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n"); err = EPERM; goto oerr; } if (strcmp(__elfN(kerneltype), kfp->f_type)) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module with kernel type '%s'\n", kfp->f_type); err = EPERM; goto oerr; } /* Looks OK, got ahead */ ef.kernel = 0; } else { err = EFTYPE; goto oerr; } if (archsw.arch_loadaddr != NULL) dest = archsw.arch_loadaddr(LOAD_ELF, ehdr, dest); else dest = roundup(dest, PAGE_SIZE); /* * Ok, we think we should handle this. */ fp = file_alloc(); if (fp == NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: cannot allocate module info\n"); err = EPERM; goto out; } if (ef.kernel == 1 && multiboot == 0) setenv("kernelname", filename, 1); fp->f_name = strdup(filename); if (multiboot == 0) fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype)); else fp->f_type = strdup("elf multiboot kernel"); #ifdef ELF_VERBOSE if (ef.kernel) printf("%s entry at 0x%jx\n", filename, (uintmax_t)ehdr->e_entry); #else printf("%s ", filename); #endif fp->f_size = __elfN(loadimage)(fp, &ef, dest); if (fp->f_size == 0 || fp->f_addr == 0) goto ioerr; /* save exec header as metadata */ file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*ehdr), ehdr); /* Load OK, return module pointer */ *result = (struct preloaded_file *)fp; err = 0; goto out; ioerr: err = EIO; oerr: file_discard(fp); out: if (ef.firstpage) free(ef.firstpage); if (ef.fd != -1) close(ef.fd); return (err); } /* * With the file (fd) open on the image, and (ehdr) containing * the Elf header, load the image at (off) */ static int -__elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) +__elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off) { int i; u_int j; Elf_Ehdr *ehdr; Elf_Phdr *phdr, *php; Elf_Shdr *shdr; char *shstr; int ret; vm_offset_t firstaddr; vm_offset_t lastaddr; size_t chunk; ssize_t result; Elf_Addr ssym, esym; Elf_Dyn *dp; Elf_Addr adp; Elf_Addr ctors; int ndp; int symstrindex; int symtabindex; Elf_Size size; u_int fpcopy; Elf_Sym sym; Elf_Addr p_start, p_end; dp = NULL; shdr = NULL; ret = 0; firstaddr = lastaddr = 0; ehdr = ef->ehdr; if (ehdr->e_type == ET_EXEC) { #if defined(__i386__) || defined(__amd64__) #if __ELF_WORD_SIZE == 64 /* x86_64 relocates after locore */ off = - (off & 0xffffffffff000000ull); #else /* i386 relocates after locore */ off = - (off & 0xff000000u); #endif #elif defined(__powerpc__) /* * On the purely virtual memory machines like e500, the kernel * is linked against its final VA range, which is most often * not available at the loader stage, but only after kernel * initializes and completes its VM settings. In such cases we * cannot use p_vaddr field directly to load ELF segments, but * put them at some 'load-time' locations. */ if (off & 0xf0000000u) { off = -(off & 0xf0000000u); /* * XXX the physical load address should not be * hardcoded. Note that the Book-E kernel assumes that * it's loaded at a 16MB boundary for now... */ off += 0x01000000; ehdr->e_entry += off; #ifdef ELF_VERBOSE printf("Converted entry 0x%08x\n", ehdr->e_entry); #endif } else off = 0; #elif defined(__arm__) && !defined(EFI) /* * The elf headers in arm kernels specify virtual addresses in * all header fields, even the ones that should be physical * addresses. We assume the entry point is in the first page, * and masking the page offset will leave us with the virtual * address the kernel was linked at. We subtract that from the * load offset, making 'off' into the value which, when added * to a virtual address in an elf header, translates it to a * physical address. We do the va->pa conversion on the entry * point address in the header now, so that later we can launch * the kernel by just jumping to that address. * * When booting from UEFI the copyin and copyout functions * handle adjusting the location relative to the first virtual * address. Because of this there is no need to adjust the * offset or entry point address as these will both be handled * by the efi code. */ off -= ehdr->e_entry & ~PAGE_MASK; ehdr->e_entry += off; #ifdef ELF_VERBOSE printf("ehdr->e_entry 0x%08x, va<->pa off %llx\n", ehdr->e_entry, off); #endif #else off = 0; /* other archs use direct mapped kernels */ #endif } ef->off = off; if (ef->kernel) __elfN(relocation_offset) = off; if ((ehdr->e_phoff + ehdr->e_phnum * sizeof(*phdr)) > ef->firstlen) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: program header not within first page\n"); goto out; } phdr = (Elf_Phdr *)(ef->firstpage + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; i++) { if (elf_program_header_convert(ehdr, phdr)) continue; /* We want to load PT_LOAD segments only.. */ if (phdr[i].p_type != PT_LOAD) continue; #ifdef ELF_VERBOSE printf("Segment: 0x%lx@0x%lx -> 0x%lx-0x%lx", (long)phdr[i].p_filesz, (long)phdr[i].p_offset, (long)(phdr[i].p_vaddr + off), (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz - 1)); #else if ((phdr[i].p_flags & PF_W) == 0) { printf("text=0x%lx ", (long)phdr[i].p_filesz); } else { printf("data=0x%lx", (long)phdr[i].p_filesz); if (phdr[i].p_filesz < phdr[i].p_memsz) printf("+0x%lx", (long)(phdr[i].p_memsz - phdr[i].p_filesz)); printf(" "); } #endif fpcopy = 0; if (ef->firstlen > phdr[i].p_offset) { fpcopy = ef->firstlen - phdr[i].p_offset; archsw.arch_copyin(ef->firstpage + phdr[i].p_offset, phdr[i].p_vaddr + off, fpcopy); } if (phdr[i].p_filesz > fpcopy) { if (kern_pread(ef->fd, phdr[i].p_vaddr + off + fpcopy, phdr[i].p_filesz - fpcopy, phdr[i].p_offset + fpcopy) != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: read failed\n"); goto out; } } /* clear space from oversized segments; eg: bss */ if (phdr[i].p_filesz < phdr[i].p_memsz) { #ifdef ELF_VERBOSE printf(" (bss: 0x%lx-0x%lx)", (long)(phdr[i].p_vaddr + off + phdr[i].p_filesz), (long)(phdr[i].p_vaddr + off + phdr[i].p_memsz -1)); #endif kern_bzero(phdr[i].p_vaddr + off + phdr[i].p_filesz, phdr[i].p_memsz - phdr[i].p_filesz); } #ifdef ELF_VERBOSE printf("\n"); #endif if (archsw.arch_loadseg != NULL) archsw.arch_loadseg(ehdr, phdr + i, off); if (firstaddr == 0 || firstaddr > (phdr[i].p_vaddr + off)) firstaddr = phdr[i].p_vaddr + off; if (lastaddr == 0 || lastaddr < (phdr[i].p_vaddr + off + phdr[i].p_memsz)) lastaddr = phdr[i].p_vaddr + off + phdr[i].p_memsz; } lastaddr = roundup(lastaddr, sizeof(long)); /* * Get the section headers. We need this for finding the .ctors * section as well as for loading any symbols. Both may be hard * to do if reading from a .gz file as it involves seeking. I * think the rule is going to have to be that you must strip a * file to remove symbols before gzipping it. */ chunk = (size_t)ehdr->e_shnum * (size_t)ehdr->e_shentsize; if (chunk == 0 || ehdr->e_shoff == 0) goto nosyms; shdr = alloc_pread(ef->fd, ehdr->e_shoff, chunk); if (shdr == NULL) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: failed to read section headers"); goto nosyms; } for (i = 0; i < ehdr->e_shnum; i++) elf_section_header_convert(ehdr, &shdr[i]); file_addmetadata(fp, MODINFOMD_SHDR, chunk, shdr); /* * Read the section string table and look for the .ctors section. * We need to tell the kernel where it is so that it can call the * ctors. */ chunk = shdr[ehdr->e_shstrndx].sh_size; if (chunk) { shstr = alloc_pread(ef->fd, shdr[ehdr->e_shstrndx].sh_offset, chunk); if (shstr) { for (i = 0; i < ehdr->e_shnum; i++) { if (strcmp(shstr + shdr[i].sh_name, ".ctors") != 0) continue; ctors = shdr[i].sh_addr; file_addmetadata(fp, MODINFOMD_CTORS_ADDR, sizeof(ctors), &ctors); size = shdr[i].sh_size; file_addmetadata(fp, MODINFOMD_CTORS_SIZE, sizeof(size), &size); break; } free(shstr); } } /* * Now load any symbols. */ symtabindex = -1; symstrindex = -1; for (i = 0; i < ehdr->e_shnum; i++) { if (shdr[i].sh_type != SHT_SYMTAB) continue; for (j = 0; j < ehdr->e_phnum; j++) { if (phdr[j].p_type != PT_LOAD) continue; if (shdr[i].sh_offset >= phdr[j].p_offset && (shdr[i].sh_offset + shdr[i].sh_size <= phdr[j].p_offset + phdr[j].p_filesz)) { shdr[i].sh_offset = 0; shdr[i].sh_size = 0; break; } } if (shdr[i].sh_offset == 0 || shdr[i].sh_size == 0) continue; /* alread loaded in a PT_LOAD above */ /* Save it for loading below */ symtabindex = i; symstrindex = shdr[i].sh_link; } if (symtabindex < 0 || symstrindex < 0) goto nosyms; /* Ok, committed to a load. */ #ifndef ELF_VERBOSE printf("syms=["); #endif ssym = lastaddr; for (i = symtabindex; i >= 0; i = symstrindex) { #ifdef ELF_VERBOSE char *secname; switch(shdr[i].sh_type) { case SHT_SYMTAB: /* Symbol table */ secname = "symtab"; break; case SHT_STRTAB: /* String table */ secname = "strtab"; break; default: secname = "WHOA!!"; break; } #endif size = shdr[i].sh_size; #if defined(__powerpc__) #if __ELF_WORD_SIZE == 64 size = htobe64(size); #else size = htobe32(size); #endif #endif archsw.arch_copyin(&size, lastaddr, sizeof(size)); lastaddr += sizeof(size); #ifdef ELF_VERBOSE printf("\n%s: 0x%jx@0x%jx -> 0x%jx-0x%jx", secname, (uintmax_t)shdr[i].sh_size, (uintmax_t)shdr[i].sh_offset, (uintmax_t)lastaddr, (uintmax_t)(lastaddr + shdr[i].sh_size)); #else if (i == symstrindex) printf("+"); printf("0x%lx+0x%lx", (long)sizeof(size), (long)size); #endif if (lseek(ef->fd, (off_t)shdr[i].sh_offset, SEEK_SET) == -1) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not seek for symbols - skipped!"); lastaddr = ssym; ssym = 0; goto nosyms; } result = archsw.arch_readin(ef->fd, lastaddr, shdr[i].sh_size); if (result < 0 || (size_t)result != shdr[i].sh_size) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_loadimage: could not read symbols - skipped! " "(%ju != %ju)", (uintmax_t)result, (uintmax_t)shdr[i].sh_size); lastaddr = ssym; ssym = 0; goto nosyms; } /* Reset offsets relative to ssym */ lastaddr += shdr[i].sh_size; lastaddr = roundup(lastaddr, sizeof(size)); if (i == symtabindex) symtabindex = -1; else if (i == symstrindex) symstrindex = -1; } esym = lastaddr; #ifndef ELF_VERBOSE printf("]"); #endif #if defined(__powerpc__) /* On PowerPC we always need to provide BE data to the kernel */ #if __ELF_WORD_SIZE == 64 ssym = htobe64((uint64_t)ssym); esym = htobe64((uint64_t)esym); #else ssym = htobe32((uint32_t)ssym); esym = htobe32((uint32_t)esym); #endif #endif file_addmetadata(fp, MODINFOMD_SSYM, sizeof(ssym), &ssym); file_addmetadata(fp, MODINFOMD_ESYM, sizeof(esym), &esym); nosyms: printf("\n"); ret = lastaddr - firstaddr; fp->f_addr = firstaddr; php = NULL; for (i = 0; i < ehdr->e_phnum; i++) { if (phdr[i].p_type == PT_DYNAMIC) { php = phdr + i; adp = php->p_vaddr; file_addmetadata(fp, MODINFOMD_DYNAMIC, sizeof(adp), &adp); break; } } if (php == NULL) /* this is bad, we cannot get to symbols or _DYNAMIC */ goto out; ndp = php->p_filesz / sizeof(Elf_Dyn); if (ndp == 0) goto out; dp = malloc(php->p_filesz); if (dp == NULL) goto out; archsw.arch_copyout(php->p_vaddr + off, dp, php->p_filesz); ef->strsz = 0; for (i = 0; i < ndp; i++) { if (dp[i].d_tag == 0) break; switch (dp[i].d_tag) { case DT_HASH: ef->hashtab = (Elf_Hashelt*)(uintptr_t)(dp[i].d_un.d_ptr + off); break; case DT_STRTAB: ef->strtab = (char *)(uintptr_t)(dp[i].d_un.d_ptr + off); break; case DT_STRSZ: ef->strsz = dp[i].d_un.d_val; break; case DT_SYMTAB: ef->symtab = (Elf_Sym *)(uintptr_t)(dp[i].d_un.d_ptr + off); break; case DT_REL: ef->rel = (Elf_Rel *)(uintptr_t)(dp[i].d_un.d_ptr + off); break; case DT_RELSZ: ef->relsz = dp[i].d_un.d_val; break; case DT_RELA: ef->rela = (Elf_Rela *)(uintptr_t)(dp[i].d_un.d_ptr + off); break; case DT_RELASZ: ef->relasz = dp[i].d_un.d_val; break; default: break; } } if (ef->hashtab == NULL || ef->symtab == NULL || ef->strtab == NULL || ef->strsz == 0) goto out; COPYOUT(ef->hashtab, &ef->nbuckets, sizeof(ef->nbuckets)); COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains)); ef->buckets = ef->hashtab + 2; ef->chains = ef->buckets + ef->nbuckets; if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0) return 0; p_start = sym.st_value + ef->off; if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0) return ENOENT; p_end = sym.st_value + ef->off; if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0) goto out; if (ef->kernel) /* kernel must not depend on anything */ goto out; out: if (dp) free(dp); if (shdr) free(shdr); return ret; } static char invalid_name[] = "bad"; char * fake_modname(const char *name) { const char *sp, *ep; char *fp; size_t len; sp = strrchr(name, '/'); if (sp) sp++; else sp = name; ep = strrchr(name, '.'); if (ep) { if (ep == name) { sp = invalid_name; ep = invalid_name + sizeof(invalid_name) - 1; } } else ep = name + strlen(name); len = ep - sp; fp = malloc(len + 1); if (fp == NULL) return NULL; memcpy(fp, sp, len); fp[len] = '\0'; return fp; } #if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 struct mod_metadata64 { int md_version; /* structure version MDTV_* */ int md_type; /* type of entry MDT_* */ - u_int64_t md_data; /* specific data */ - u_int64_t md_cval; /* common string label */ + uint64_t md_data; /* specific data */ + uint64_t md_cval; /* common string label */ }; #endif #if defined(__amd64__) && __ELF_WORD_SIZE == 32 struct mod_metadata32 { int md_version; /* structure version MDTV_* */ int md_type; /* type of entry MDT_* */ - u_int32_t md_data; /* specific data */ - u_int32_t md_cval; /* common string label */ + uint32_t md_data; /* specific data */ + uint32_t md_cval; /* common string label */ }; #endif int -__elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest) +__elfN(load_modmetadata)(struct preloaded_file *fp, uint64_t dest) { struct elf_file ef; int err, i, j; Elf_Shdr *sh_meta, *shdr = NULL; Elf_Shdr *sh_data[2]; char *shstrtab = NULL; size_t size; Elf_Addr p_start, p_end; bzero(&ef, sizeof(struct elf_file)); ef.fd = -1; err = __elfN(load_elf_header)(fp->f_name, &ef); if (err != 0) goto out; if (ef.kernel == 1 || ef.ehdr->e_type == ET_EXEC) { ef.kernel = 1; } else if (ef.ehdr->e_type != ET_DYN) { err = EFTYPE; goto out; } size = (size_t)ef.ehdr->e_shnum * (size_t)ef.ehdr->e_shentsize; shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size); if (shdr == NULL) { err = ENOMEM; goto out; } /* Load shstrtab. */ shstrtab = alloc_pread(ef.fd, shdr[ef.ehdr->e_shstrndx].sh_offset, shdr[ef.ehdr->e_shstrndx].sh_size); if (shstrtab == NULL) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "load_modmetadata: unable to load shstrtab\n"); err = EFTYPE; goto out; } /* Find set_modmetadata_set and data sections. */ sh_data[0] = sh_data[1] = sh_meta = NULL; for (i = 0, j = 0; i < ef.ehdr->e_shnum; i++) { if (strcmp(&shstrtab[shdr[i].sh_name], "set_modmetadata_set") == 0) { sh_meta = &shdr[i]; } if ((strcmp(&shstrtab[shdr[i].sh_name], ".data") == 0) || (strcmp(&shstrtab[shdr[i].sh_name], ".rodata") == 0)) { sh_data[j++] = &shdr[i]; } } if (sh_meta == NULL || sh_data[0] == NULL || sh_data[1] == NULL) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "load_modmetadata: unable to find set_modmetadata_set or data sections\n"); err = EFTYPE; goto out; } /* Load set_modmetadata_set into memory */ err = kern_pread(ef.fd, dest, sh_meta->sh_size, sh_meta->sh_offset); if (err != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "load_modmetadata: unable to load set_modmetadata_set: %d\n", err); goto out; } p_start = dest; p_end = dest + sh_meta->sh_size; dest += sh_meta->sh_size; /* Load data sections into memory. */ err = kern_pread(ef.fd, dest, sh_data[0]->sh_size, sh_data[0]->sh_offset); if (err != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "load_modmetadata: unable to load data: %d\n", err); goto out; } /* * We have to increment the dest, so that the offset is the same into * both the .rodata and .data sections. */ ef.off = -(sh_data[0]->sh_addr - dest); dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr); err = kern_pread(ef.fd, dest, sh_data[1]->sh_size, sh_data[1]->sh_offset); if (err != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "load_modmetadata: unable to load data: %d\n", err); goto out; } err = __elfN(parse_modmetadata)(fp, &ef, p_start, p_end); if (err != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "load_modmetadata: unable to parse metadata: %d\n", err); goto out; } out: if (shstrtab != NULL) free(shstrtab); if (shdr != NULL) free(shdr); if (ef.firstpage != NULL) free(ef.firstpage); if (ef.fd != -1) close(ef.fd); return (err); } int __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef, Elf_Addr p_start, Elf_Addr p_end) { struct mod_metadata md; #if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 struct mod_metadata64 md64; #elif defined(__amd64__) && __ELF_WORD_SIZE == 32 struct mod_metadata32 md32; #endif struct mod_depend *mdepend; struct mod_version mver; char *s; int error, modcnt, minfolen; Elf_Addr v, p; modcnt = 0; p = p_start; while (p < p_end) { COPYOUT(p, &v, sizeof(v)); error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v)); if (error == EOPNOTSUPP) v += ef->off; else if (error != 0) return (error); #if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64 COPYOUT(v, &md64, sizeof(md64)); error = __elfN(reloc_ptr)(fp, ef, v, &md64, sizeof(md64)); if (error == EOPNOTSUPP) { md64.md_cval += ef->off; md64.md_data += ef->off; } else if (error != 0) return (error); md.md_version = md64.md_version; md.md_type = md64.md_type; md.md_cval = (const char *)(uintptr_t)md64.md_cval; md.md_data = (void *)(uintptr_t)md64.md_data; #elif defined(__amd64__) && __ELF_WORD_SIZE == 32 COPYOUT(v, &md32, sizeof(md32)); error = __elfN(reloc_ptr)(fp, ef, v, &md32, sizeof(md32)); if (error == EOPNOTSUPP) { md32.md_cval += ef->off; md32.md_data += ef->off; } else if (error != 0) return (error); md.md_version = md32.md_version; md.md_type = md32.md_type; md.md_cval = (const char *)(uintptr_t)md32.md_cval; md.md_data = (void *)(uintptr_t)md32.md_data; #else COPYOUT(v, &md, sizeof(md)); error = __elfN(reloc_ptr)(fp, ef, v, &md, sizeof(md)); if (error == EOPNOTSUPP) { md.md_cval += ef->off; md.md_data = (void *)((uintptr_t)md.md_data + (uintptr_t)ef->off); } else if (error != 0) return (error); #endif p += sizeof(Elf_Addr); switch(md.md_type) { case MDT_DEPEND: if (ef->kernel) /* kernel must not depend on anything */ break; s = strdupout((vm_offset_t)md.md_cval); minfolen = sizeof(*mdepend) + strlen(s) + 1; mdepend = malloc(minfolen); if (mdepend == NULL) return ENOMEM; COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend)); strcpy((char*)(mdepend + 1), s); free(s); file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend); free(mdepend); break; case MDT_VERSION: s = strdupout((vm_offset_t)md.md_cval); COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver)); file_addmodule(fp, s, mver.mv_version, NULL); free(s); modcnt++; break; } } if (modcnt == 0) { s = fake_modname(fp->f_name); file_addmodule(fp, s, 1, NULL); free(s); } return 0; } static unsigned long elf_hash(const char *name) { const unsigned char *p = (const unsigned char *) name; unsigned long h = 0; unsigned long g; while (*p != '\0') { h = (h << 4) + *p++; if ((g = h & 0xf0000000) != 0) h ^= g >> 24; h &= ~g; } return h; } static const char __elfN(bad_symtable)[] = "elf" __XSTRING(__ELF_WORD_SIZE) "_lookup_symbol: corrupt symbol table\n"; int __elfN(lookup_symbol)(struct preloaded_file *fp, elf_file_t ef, const char* name, Elf_Sym *symp) { Elf_Hashelt symnum; Elf_Sym sym; char *strp; unsigned long hash; hash = elf_hash(name); COPYOUT(&ef->buckets[hash % ef->nbuckets], &symnum, sizeof(symnum)); while (symnum != STN_UNDEF) { if (symnum >= ef->nchains) { printf(__elfN(bad_symtable)); return ENOENT; } COPYOUT(ef->symtab + symnum, &sym, sizeof(sym)); if (sym.st_name == 0) { printf(__elfN(bad_symtable)); return ENOENT; } strp = strdupout((vm_offset_t)(ef->strtab + sym.st_name)); if (strcmp(name, strp) == 0) { free(strp); if (sym.st_shndx != SHN_UNDEF || (sym.st_value != 0 && ELF_ST_TYPE(sym.st_info) == STT_FUNC)) { *symp = sym; return 0; } return ENOENT; } free(strp); COPYOUT(&ef->chains[symnum], &symnum, sizeof(symnum)); } return ENOENT; } /* * Apply any intra-module relocations to the value. p is the load address * of the value and val/len is the value to be modified. This does NOT modify * the image in-place, because this is done by kern_linker later on. * * Returns EOPNOTSUPP if no relocation method is supplied. */ static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p, void *val, size_t len) { size_t n; Elf_Rela a; Elf_Rel r; int error; /* * The kernel is already relocated, but we still want to apply * offset adjustments. */ if (ef->kernel) return (EOPNOTSUPP); for (n = 0; n < ef->relsz / sizeof(r); n++) { COPYOUT(ef->rel + n, &r, sizeof(r)); error = __elfN(reloc)(ef, __elfN(symaddr), &r, ELF_RELOC_REL, ef->off, p, val, len); if (error != 0) return (error); } for (n = 0; n < ef->relasz / sizeof(a); n++) { COPYOUT(ef->rela + n, &a, sizeof(a)); error = __elfN(reloc)(ef, __elfN(symaddr), &a, ELF_RELOC_RELA, ef->off, p, val, len); if (error != 0) return (error); } return (0); } static Elf_Addr __elfN(symaddr)(struct elf_file *ef, Elf_Size symidx) { /* Symbol lookup by index not required here. */ return (0); } Index: head/stand/common/load_elf_obj.c =================================================================== --- head/stand/common/load_elf_obj.c (revision 330863) +++ head/stand/common/load_elf_obj.c (revision 330864) @@ -1,541 +1,541 @@ /*- * Copyright (c) 2004 Ian Dowse * Copyright (c) 1998 Michael Smith * Copyright (c) 1998 Peter Wemm * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #define FREEBSD_ELF #include #include "bootstrap.h" #define COPYOUT(s,d,l) archsw.arch_copyout((vm_offset_t)(s), d, l) #if defined(__i386__) && __ELF_WORD_SIZE == 64 #undef ELF_TARG_CLASS #undef ELF_TARG_MACH #define ELF_TARG_CLASS ELFCLASS64 #define ELF_TARG_MACH EM_X86_64 #endif typedef struct elf_file { Elf_Ehdr hdr; Elf_Shdr *e_shdr; int symtabindex; /* Index of symbol table */ int shstrindex; /* Index of section name string table */ int fd; vm_offset_t off; } *elf_file_t; static int __elfN(obj_loadimage)(struct preloaded_file *mp, elf_file_t ef, - u_int64_t loadaddr); + uint64_t loadaddr); static int __elfN(obj_lookup_set)(struct preloaded_file *mp, elf_file_t ef, const char *name, Elf_Addr *startp, Elf_Addr *stopp, int *countp); static int __elfN(obj_reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p, void *val, size_t len); static int __elfN(obj_parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef); static Elf_Addr __elfN(obj_symaddr)(struct elf_file *ef, Elf_Size symidx); const char *__elfN(obj_kerneltype) = "elf kernel"; const char *__elfN(obj_moduletype) = "elf obj module"; /* * Attempt to load the file (file) as an ELF module. It will be stored at * (dest), and a pointer to a module structure describing the loaded object * will be saved in (result). */ int -__elfN(obj_loadfile)(char *filename, u_int64_t dest, +__elfN(obj_loadfile)(char *filename, uint64_t dest, struct preloaded_file **result) { struct preloaded_file *fp, *kfp; struct elf_file ef; Elf_Ehdr *hdr; int err; ssize_t bytes_read; fp = NULL; bzero(&ef, sizeof(struct elf_file)); /* * Open the image, read and validate the ELF header */ if (filename == NULL) /* can't handle nameless */ return(EFTYPE); if ((ef.fd = open(filename, O_RDONLY)) == -1) return(errno); hdr = &ef.hdr; bytes_read = read(ef.fd, hdr, sizeof(*hdr)); if (bytes_read != sizeof(*hdr)) { err = EFTYPE; /* could be EIO, but may be small file */ goto oerr; } /* Is it ELF? */ if (!IS_ELF(*hdr)) { err = EFTYPE; goto oerr; } if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */ hdr->e_ident[EI_DATA] != ELF_TARG_DATA || hdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */ hdr->e_version != EV_CURRENT || hdr->e_machine != ELF_TARG_MACH || /* Machine ? */ hdr->e_type != ET_REL) { err = EFTYPE; goto oerr; } if (hdr->e_shnum * hdr->e_shentsize == 0 || hdr->e_shoff == 0 || hdr->e_shentsize != sizeof(Elf_Shdr)) { err = EFTYPE; goto oerr; } kfp = file_findfile(NULL, __elfN(obj_kerneltype)); if (kfp == NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadfile: can't load module before kernel\n"); err = EPERM; goto oerr; } if (archsw.arch_loadaddr != NULL) dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest); else dest = roundup(dest, PAGE_SIZE); /* * Ok, we think we should handle this. */ fp = file_alloc(); if (fp == NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadfile: cannot allocate module info\n"); err = EPERM; goto out; } fp->f_name = strdup(filename); fp->f_type = strdup(__elfN(obj_moduletype)); printf("%s ", filename); fp->f_size = __elfN(obj_loadimage)(fp, &ef, dest); if (fp->f_size == 0 || fp->f_addr == 0) goto ioerr; /* save exec header as metadata */ file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*hdr), hdr); /* Load OK, return module pointer */ *result = (struct preloaded_file *)fp; err = 0; goto out; ioerr: err = EIO; oerr: file_discard(fp); out: close(ef.fd); if (ef.e_shdr != NULL) free(ef.e_shdr); return(err); } /* * With the file (fd) open on the image, and (ehdr) containing * the Elf header, load the image at (off) */ static int -__elfN(obj_loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off) +__elfN(obj_loadimage)(struct preloaded_file *fp, elf_file_t ef, uint64_t off) { Elf_Ehdr *hdr; Elf_Shdr *shdr, *cshdr, *lshdr; vm_offset_t firstaddr, lastaddr; int i, nsym, res, ret, shdrbytes, symstrindex; ret = 0; firstaddr = lastaddr = (vm_offset_t)off; hdr = &ef->hdr; ef->off = (vm_offset_t)off; /* Read in the section headers. */ shdrbytes = hdr->e_shnum * hdr->e_shentsize; shdr = alloc_pread(ef->fd, (off_t)hdr->e_shoff, shdrbytes); if (shdr == NULL) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadimage: read section headers failed\n"); goto out; } ef->e_shdr = shdr; /* * Decide where to load everything, but don't read it yet. * We store the load address as a non-zero sh_addr value. * Start with the code/data and bss. */ for (i = 0; i < hdr->e_shnum; i++) shdr[i].sh_addr = 0; for (i = 0; i < hdr->e_shnum; i++) { if (shdr[i].sh_size == 0) continue; switch (shdr[i].sh_type) { case SHT_PROGBITS: case SHT_NOBITS: #if defined(__i386__) || defined(__amd64__) case SHT_X86_64_UNWIND: #endif if ((shdr[i].sh_flags & SHF_ALLOC) == 0) break; lastaddr = roundup(lastaddr, shdr[i].sh_addralign); shdr[i].sh_addr = (Elf_Addr)lastaddr; lastaddr += shdr[i].sh_size; break; } } /* Symbols. */ nsym = 0; for (i = 0; i < hdr->e_shnum; i++) { switch (shdr[i].sh_type) { case SHT_SYMTAB: nsym++; ef->symtabindex = i; shdr[i].sh_addr = (Elf_Addr)lastaddr; lastaddr += shdr[i].sh_size; break; } } if (nsym != 1) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadimage: file has no valid symbol table\n"); goto out; } lastaddr = roundup(lastaddr, shdr[ef->symtabindex].sh_addralign); shdr[ef->symtabindex].sh_addr = (Elf_Addr)lastaddr; lastaddr += shdr[ef->symtabindex].sh_size; symstrindex = shdr[ef->symtabindex].sh_link; if (symstrindex < 0 || symstrindex >= hdr->e_shnum || shdr[symstrindex].sh_type != SHT_STRTAB) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadimage: file has invalid symbol strings\n"); goto out; } lastaddr = roundup(lastaddr, shdr[symstrindex].sh_addralign); shdr[symstrindex].sh_addr = (Elf_Addr)lastaddr; lastaddr += shdr[symstrindex].sh_size; /* Section names. */ if (hdr->e_shstrndx == 0 || hdr->e_shstrndx >= hdr->e_shnum || shdr[hdr->e_shstrndx].sh_type != SHT_STRTAB) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadimage: file has no section names\n"); goto out; } ef->shstrindex = hdr->e_shstrndx; lastaddr = roundup(lastaddr, shdr[ef->shstrindex].sh_addralign); shdr[ef->shstrindex].sh_addr = (Elf_Addr)lastaddr; lastaddr += shdr[ef->shstrindex].sh_size; /* Relocation tables. */ for (i = 0; i < hdr->e_shnum; i++) { switch (shdr[i].sh_type) { case SHT_REL: case SHT_RELA: if ((shdr[shdr[i].sh_info].sh_flags & SHF_ALLOC) == 0) break; lastaddr = roundup(lastaddr, shdr[i].sh_addralign); shdr[i].sh_addr = (Elf_Addr)lastaddr; lastaddr += shdr[i].sh_size; break; } } /* Clear the whole area, including bss regions. */ kern_bzero(firstaddr, lastaddr - firstaddr); /* Figure section with the lowest file offset we haven't loaded yet. */ for (cshdr = NULL; /* none */; /* none */) { /* * Find next section to load. The complexity of this loop is * O(n^2), but with the number of sections being typically * small, we do not care. */ lshdr = cshdr; for (i = 0; i < hdr->e_shnum; i++) { if (shdr[i].sh_addr == 0 || shdr[i].sh_type == SHT_NOBITS) continue; /* Skip sections that were loaded already. */ if (lshdr != NULL && lshdr->sh_offset >= shdr[i].sh_offset) continue; /* Find section with smallest offset. */ if (cshdr == lshdr || cshdr->sh_offset > shdr[i].sh_offset) cshdr = &shdr[i]; } if (cshdr == lshdr) break; if (kern_pread(ef->fd, (vm_offset_t)cshdr->sh_addr, cshdr->sh_size, (off_t)cshdr->sh_offset) != 0) { printf("\nelf" __XSTRING(__ELF_WORD_SIZE) "_obj_loadimage: read failed\n"); goto out; } } file_addmetadata(fp, MODINFOMD_SHDR, shdrbytes, shdr); res = __elfN(obj_parse_modmetadata)(fp, ef); if (res != 0) goto out; ret = lastaddr - firstaddr; fp->f_addr = firstaddr; printf("size 0x%lx at 0x%lx", (u_long)ret, (u_long)firstaddr); out: printf("\n"); return ret; } #if defined(__i386__) && __ELF_WORD_SIZE == 64 struct mod_metadata64 { int md_version; /* structure version MDTV_* */ int md_type; /* type of entry MDT_* */ - u_int64_t md_data; /* specific data */ - u_int64_t md_cval; /* common string label */ + uint64_t md_data; /* specific data */ + uint64_t md_cval; /* common string label */ }; #endif int __elfN(obj_parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef) { struct mod_metadata md; #if defined(__i386__) && __ELF_WORD_SIZE == 64 struct mod_metadata64 md64; #endif struct mod_depend *mdepend; struct mod_version mver; char *s; int error, modcnt, minfolen; Elf_Addr v, p, p_stop; if (__elfN(obj_lookup_set)(fp, ef, "modmetadata_set", &p, &p_stop, &modcnt) != 0) return 0; modcnt = 0; while (p < p_stop) { COPYOUT(p, &v, sizeof(v)); error = __elfN(obj_reloc_ptr)(fp, ef, p, &v, sizeof(v)); if (error != 0) return (error); #if defined(__i386__) && __ELF_WORD_SIZE == 64 COPYOUT(v, &md64, sizeof(md64)); error = __elfN(obj_reloc_ptr)(fp, ef, v, &md64, sizeof(md64)); if (error != 0) return (error); md.md_version = md64.md_version; md.md_type = md64.md_type; md.md_cval = (const char *)(uintptr_t)md64.md_cval; md.md_data = (void *)(uintptr_t)md64.md_data; #else COPYOUT(v, &md, sizeof(md)); error = __elfN(obj_reloc_ptr)(fp, ef, v, &md, sizeof(md)); if (error != 0) return (error); #endif p += sizeof(Elf_Addr); switch(md.md_type) { case MDT_DEPEND: s = strdupout((vm_offset_t)md.md_cval); minfolen = sizeof(*mdepend) + strlen(s) + 1; mdepend = malloc(minfolen); if (mdepend == NULL) return ENOMEM; COPYOUT((vm_offset_t)md.md_data, mdepend, sizeof(*mdepend)); strcpy((char*)(mdepend + 1), s); free(s); file_addmetadata(fp, MODINFOMD_DEPLIST, minfolen, mdepend); free(mdepend); break; case MDT_VERSION: s = strdupout((vm_offset_t)md.md_cval); COPYOUT((vm_offset_t)md.md_data, &mver, sizeof(mver)); file_addmodule(fp, s, mver.mv_version, NULL); free(s); modcnt++; break; case MDT_MODULE: case MDT_PNP_INFO: break; default: printf("unknown type %d\n", md.md_type); break; } } return 0; } static int __elfN(obj_lookup_set)(struct preloaded_file *fp, elf_file_t ef, const char* name, Elf_Addr *startp, Elf_Addr *stopp, int *countp) { Elf_Ehdr *hdr; Elf_Shdr *shdr; char *p; vm_offset_t shstrtab; int i; hdr = &ef->hdr; shdr = ef->e_shdr; shstrtab = shdr[ef->shstrindex].sh_addr; for (i = 0; i < hdr->e_shnum; i++) { if (shdr[i].sh_type != SHT_PROGBITS) continue; if (shdr[i].sh_name == 0) continue; p = strdupout(shstrtab + shdr[i].sh_name); if (strncmp(p, "set_", 4) == 0 && strcmp(p + 4, name) == 0) { *startp = shdr[i].sh_addr; *stopp = shdr[i].sh_addr + shdr[i].sh_size; *countp = (*stopp - *startp) / sizeof(Elf_Addr); free(p); return (0); } free(p); } return (ESRCH); } /* * Apply any intra-module relocations to the value. p is the load address * of the value and val/len is the value to be modified. This does NOT modify * the image in-place, because this is done by kern_linker later on. */ static int __elfN(obj_reloc_ptr)(struct preloaded_file *mp, elf_file_t ef, Elf_Addr p, void *val, size_t len) { Elf_Ehdr *hdr; Elf_Shdr *shdr; Elf_Addr off = p; Elf_Addr base; Elf_Rela a, *abase; Elf_Rel r, *rbase; int error, i, j, nrel, nrela; hdr = &ef->hdr; shdr = ef->e_shdr; for (i = 0; i < hdr->e_shnum; i++) { if (shdr[i].sh_type != SHT_RELA && shdr[i].sh_type != SHT_REL) continue; base = shdr[shdr[i].sh_info].sh_addr; if (base == 0 || shdr[i].sh_addr == 0) continue; if (off < base || off + len > base + shdr[shdr[i].sh_info].sh_size) continue; switch (shdr[i].sh_type) { case SHT_RELA: abase = (Elf_Rela *)(intptr_t)shdr[i].sh_addr; nrela = shdr[i].sh_size / sizeof(Elf_Rela); for (j = 0; j < nrela; j++) { COPYOUT(abase + j, &a, sizeof(a)); error = __elfN(reloc)(ef, __elfN(obj_symaddr), &a, ELF_RELOC_RELA, base, off, val, len); if (error != 0) return (error); } break; case SHT_REL: rbase = (Elf_Rel *)(intptr_t)shdr[i].sh_addr; nrel = shdr[i].sh_size / sizeof(Elf_Rel); for (j = 0; j < nrel; j++) { COPYOUT(rbase + j, &r, sizeof(r)); error = __elfN(reloc)(ef, __elfN(obj_symaddr), &r, ELF_RELOC_REL, base, off, val, len); if (error != 0) return (error); } break; } } return (0); } /* Look up the address of a specified symbol. */ static Elf_Addr __elfN(obj_symaddr)(struct elf_file *ef, Elf_Size symidx) { Elf_Sym sym; Elf_Addr base; if (symidx >= ef->e_shdr[ef->symtabindex].sh_size / sizeof(Elf_Sym)) return (0); COPYOUT(ef->e_shdr[ef->symtabindex].sh_addr + symidx * sizeof(Elf_Sym), &sym, sizeof(sym)); if (sym.st_shndx == SHN_UNDEF || sym.st_shndx >= ef->hdr.e_shnum) return (0); base = ef->e_shdr[sym.st_shndx].sh_addr; if (base == 0) return (0); return (base + sym.st_value); } Index: head/stand/common/metadata.c =================================================================== --- head/stand/common/metadata.c (revision 330863) +++ head/stand/common/metadata.c (revision 330864) @@ -1,475 +1,475 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: FreeBSD: src/sys/boot/sparc64/loader/metadata.c,v 1.6 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #if defined(LOADER_FDT_SUPPORT) #include #endif #ifdef __arm__ #include #endif #include #include "bootstrap.h" #if defined(__sparc64__) #include extern struct tlb_entry *dtlb_store; extern struct tlb_entry *itlb_store; extern int dtlb_slot; extern int itlb_slot; static int md_bootserial(void) { char buf[64]; ihandle_t inst; phandle_t input; phandle_t node; phandle_t output; if ((node = OF_finddevice("/options")) == -1) return(-1); if (OF_getprop(node, "input-device", buf, sizeof(buf)) == -1) return(-1); input = OF_finddevice(buf); if (OF_getprop(node, "output-device", buf, sizeof(buf)) == -1) return(-1); output = OF_finddevice(buf); if (input == -1 || output == -1 || OF_getproplen(input, "keyboard") >= 0) { if ((node = OF_finddevice("/chosen")) == -1) return(-1); if (OF_getprop(node, "stdin", &inst, sizeof(inst)) == -1) return(-1); if ((input = OF_instance_to_package(inst)) == -1) return(-1); if (OF_getprop(node, "stdout", &inst, sizeof(inst)) == -1) return(-1); if ((output = OF_instance_to_package(inst)) == -1) return(-1); } if (input != output) return(-1); if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) return(-1); if (strcmp(buf, "serial") != 0) return(-1); return(0); } #endif int md_getboothowto(char *kargs) { char *cp; int howto; int active; int i; /* Parse kargs */ howto = 0; if (kargs != NULL) { cp = kargs; active = 0; while (*cp != 0) { if (!active && (*cp == '-')) { active = 1; } else if (active) switch (*cp) { case 'a': howto |= RB_ASKNAME; break; case 'C': howto |= RB_CDROM; break; case 'd': howto |= RB_KDB; break; case 'D': howto |= RB_MULTIPLE; break; case 'm': howto |= RB_MUTE; break; case 'g': howto |= RB_GDB; break; case 'h': howto |= RB_SERIAL; break; case 'p': howto |= RB_PAUSE; break; case 'r': howto |= RB_DFLTROOT; break; case 's': howto |= RB_SINGLE; break; case 'v': howto |= RB_VERBOSE; break; default: active = 0; break; } cp++; } } /* get equivalents from the environment */ for (i = 0; howto_names[i].ev != NULL; i++) if (getenv(howto_names[i].ev) != NULL) howto |= howto_names[i].mask; #if defined(__sparc64__) if (md_bootserial() != -1) howto |= RB_SERIAL; #else if (!strcmp(getenv("console"), "comconsole")) howto |= RB_SERIAL; if (!strcmp(getenv("console"), "nullconsole")) howto |= RB_MUTE; #endif return(howto); } /* * Copy the environment into the load area starting at (addr). * Each variable is formatted as =, with a single nul * separating each variable, and a double nul terminating the environment. */ static vm_offset_t md_copyenv(vm_offset_t addr) { struct env_var *ep; /* traverse the environment */ for (ep = environ; ep != NULL; ep = ep->ev_next) { archsw.arch_copyin(ep->ev_name, addr, strlen(ep->ev_name)); addr += strlen(ep->ev_name); archsw.arch_copyin("=", addr, 1); addr++; if (ep->ev_value != NULL) { archsw.arch_copyin(ep->ev_value, addr, strlen(ep->ev_value)); addr += strlen(ep->ev_value); } archsw.arch_copyin("", addr, 1); addr++; } archsw.arch_copyin("", addr, 1); addr++; return(addr); } /* * Copy module-related data into the load area, where it can be * used as a directory for loaded modules. * * Module data is presented in a self-describing format. Each datum * is preceded by a 32-bit identifier and a 32-bit size field. * * Currently, the following data are saved: * * MOD_NAME (variable) module name (string) * MOD_TYPE (variable) module type (string) * MOD_ARGS (variable) module parameters (string) * MOD_ADDR sizeof(vm_offset_t) module load address * MOD_SIZE sizeof(size_t) module size * MOD_METADATA (variable) type-specific metadata */ static int align; #define COPY32(v, a, c) { \ - u_int32_t x = (v); \ + uint32_t x = (v); \ if (c) \ archsw.arch_copyin(&x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c) \ if (c) \ archsw.arch_copyin(s, a, strlen(s) + 1);\ a += roundup(strlen(s) + 1, align); \ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ archsw.arch_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), align); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c);\ COPY32(mm->md_size, a, c); \ if (c) \ archsw.arch_copyin(mm->md_data, a, mm->md_size);\ a += roundup(mm->md_size, align); \ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t md_copymodules(vm_offset_t addr, int kern64) { struct preloaded_file *fp; struct file_metadata *md; uint64_t scratch64; uint32_t scratch32; int c; c = addr != 0; /* start with the first module on the list, should be the kernel */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { MOD_NAME(addr, fp->f_name, c); /* this field must come first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); if (kern64) { scratch64 = fp->f_addr; MOD_ADDR(addr, scratch64, c); scratch64 = fp->f_size; MOD_SIZE(addr, scratch64, c); } else { scratch32 = fp->f_addr; #ifdef __arm__ scratch32 -= __elfN(relocation_offset); #endif MOD_ADDR(addr, scratch32, c); MOD_SIZE(addr, fp->f_size, c); } for (md = fp->f_metadata; md != NULL; md = md->md_next) { if (!(md->md_type & MODINFOMD_NOCOPY)) { MOD_METADATA(addr, md, c); } } } MOD_END(addr, c); return(addr); } /* * Load the information expected by a kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int md_load_dual(char *args, vm_offset_t *modulep, vm_offset_t *dtb, int kern64) { struct preloaded_file *kfp; struct preloaded_file *xp; struct file_metadata *md; vm_offset_t kernend; vm_offset_t addr; vm_offset_t envp; #if defined(LOADER_FDT_SUPPORT) vm_offset_t fdtp; #endif vm_offset_t size; uint64_t scratch64; char *rootdevname; int howto; #ifdef __arm__ vm_offset_t vaddr; int i; /* * These metadata addreses must be converted for kernel after * relocation. */ uint32_t mdt[] = { MODINFOMD_SSYM, MODINFOMD_ESYM, MODINFOMD_KERNEND, MODINFOMD_ENVP, #if defined(LOADER_FDT_SUPPORT) MODINFOMD_DTBP #endif }; #endif align = kern64 ? 8 : 4; howto = md_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied * device. This should perhaps go to MI code and/or have $rootdev * tested/set by MI code before launching the kernel. */ rootdevname = getenv("rootdev"); if (rootdevname == NULL) rootdevname = getenv("currdev"); /* Try reading the /etc/fstab file to select the root device */ getrootmount(rootdevname); /* Find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* Pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* Copy our environment */ envp = addr; addr = md_copyenv(addr); /* Pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); #if defined(LOADER_FDT_SUPPORT) /* Copy out FDT */ fdtp = 0; #if defined(__powerpc__) if (getenv("usefdt") != NULL) #endif { size = fdt_copy(addr); fdtp = addr; addr = roundup(addr + size, PAGE_SIZE); } #endif kernend = 0; kfp = file_findfile(NULL, kern64 ? "elf64 kernel" : "elf32 kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) panic("can't find kernel file"); file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); if (kern64) { scratch64 = envp; file_addmetadata(kfp, MODINFOMD_ENVP, sizeof scratch64, &scratch64); #if defined(LOADER_FDT_SUPPORT) if (fdtp != 0) { scratch64 = fdtp; file_addmetadata(kfp, MODINFOMD_DTBP, sizeof scratch64, &scratch64); } #endif scratch64 = kernend; file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof scratch64, &scratch64); } else { file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); #if defined(LOADER_FDT_SUPPORT) if (fdtp != 0) file_addmetadata(kfp, MODINFOMD_DTBP, sizeof fdtp, &fdtp); #endif file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); } #if defined(__sparc64__) file_addmetadata(kfp, MODINFOMD_DTLB_SLOTS, sizeof dtlb_slot, &dtlb_slot); file_addmetadata(kfp, MODINFOMD_ITLB_SLOTS, sizeof itlb_slot, &itlb_slot); file_addmetadata(kfp, MODINFOMD_DTLB, dtlb_slot * sizeof(*dtlb_store), dtlb_store); file_addmetadata(kfp, MODINFOMD_ITLB, itlb_slot * sizeof(*itlb_store), itlb_store); #endif *modulep = addr; size = md_copymodules(0, kern64); kernend = roundup(addr + size, PAGE_SIZE); md = file_findmetadata(kfp, MODINFOMD_KERNEND); if (kern64) { scratch64 = kernend; bcopy(&scratch64, md->md_data, sizeof scratch64); } else { bcopy(&kernend, md->md_data, sizeof kernend); } #ifdef __arm__ /* Convert addresses to the final VA */ *modulep -= __elfN(relocation_offset); /* Do relocation fixup on metadata of each module. */ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { for (i = 0; i < nitems(mdt); i++) { md = file_findmetadata(xp, mdt[i]); if (md) { bcopy(md->md_data, &vaddr, sizeof vaddr); vaddr -= __elfN(relocation_offset); bcopy(&vaddr, md->md_data, sizeof vaddr); } } } #endif (void)md_copymodules(addr, kern64); #if defined(LOADER_FDT_SUPPORT) if (dtb != NULL) *dtb = fdtp; #endif return(0); } int md_load(char *args, vm_offset_t *modulep, vm_offset_t *dtb) { return (md_load_dual(args, modulep, dtb, 0)); } #if defined(__mips__) || defined(__powerpc__) int md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb) { return (md_load_dual(args, modulep, dtb, 1)); } #endif Index: head/stand/common/misc.c =================================================================== --- head/stand/common/misc.c (revision 330863) +++ head/stand/common/misc.c (revision 330864) @@ -1,220 +1,220 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include /* * Concatenate the (argc) elements of (argv) into a single string, and return * a copy of same. */ char * unargv(int argc, char *argv[]) { size_t hlong; int i; char *cp; for (i = 0, hlong = 0; i < argc; i++) hlong += strlen(argv[i]) + 2; if(hlong == 0) return(NULL); cp = malloc(hlong); cp[0] = 0; for (i = 0; i < argc; i++) { strcat(cp, argv[i]); if (i < (argc - 1)) strcat(cp, " "); } return(cp); } /* * Get the length of a string in kernel space */ size_t strlenout(vm_offset_t src) { char c; size_t len; for (len = 0; ; len++) { archsw.arch_copyout(src++, &c, 1); if (c == 0) break; } return(len); } /* * Make a duplicate copy of a string in kernel space */ char * strdupout(vm_offset_t str) { char *result, *cp; result = malloc(strlenout(str) + 1); for (cp = result; ;cp++) { archsw.arch_copyout(str++, cp, 1); if (*cp == 0) break; } return(result); } /* Zero a region in kernel space. */ void kern_bzero(vm_offset_t dest, size_t len) { char buf[256]; size_t chunk, resid; bzero(buf, sizeof(buf)); resid = len; while (resid > 0) { chunk = min(sizeof(buf), resid); archsw.arch_copyin(buf, dest, chunk); resid -= chunk; dest += chunk; } } /* * Read the specified part of a file to kernel space. Unlike regular * pread, the file pointer is advanced to the end of the read data, * and it just returns 0 if successful. */ int kern_pread(int fd, vm_offset_t dest, size_t len, off_t off) { if (lseek(fd, off, SEEK_SET) == -1) { #ifdef DEBUG printf("\nlseek failed\n"); #endif return (-1); } if ((size_t)archsw.arch_readin(fd, dest, len) != len) { #ifdef DEBUG printf("\nreadin failed\n"); #endif return (-1); } return (0); } /* * Read the specified part of a file to a malloced buffer. The file * pointer is advanced to the end of the read data. */ /* coverity[ -tainted_data_return ] */ void * alloc_pread(int fd, off_t off, size_t len) { void *buf; buf = malloc(len); if (buf == NULL) { #ifdef DEBUG printf("\nmalloc(%d) failed\n", (int)len); #endif return (NULL); } if (lseek(fd, off, SEEK_SET) == -1) { #ifdef DEBUG printf("\nlseek failed\n"); #endif free(buf); return (NULL); } if ((size_t)read(fd, buf, len) != len) { #ifdef DEBUG printf("\nread failed\n"); #endif free(buf); return (NULL); } return (buf); } /* * Display a region in traditional hexdump format. */ void hexdump(caddr_t region, size_t len) { caddr_t line; int x, c; char lbuf[80]; #define emit(fmt, args...) {sprintf(lbuf, fmt , ## args); pager_output(lbuf);} pager_open(); for (line = region; line < (region + len); line += 16) { emit("%08lx ", (long) line); for (x = 0; x < 16; x++) { if ((line + x) < (region + len)) { - emit("%02x ", *(u_int8_t *)(line + x)); + emit("%02x ", *(uint8_t *)(line + x)); } else { emit("-- "); } if (x == 7) emit(" "); } emit(" |"); for (x = 0; x < 16; x++) { if ((line + x) < (region + len)) { - c = *(u_int8_t *)(line + x); + c = *(uint8_t *)(line + x); if ((c < ' ') || (c > '~')) /* !isprint(c) */ c = '.'; emit("%c", c); } else { emit(" "); } } emit("|\n"); } pager_close(); } void dev_cleanup(void) { int i; /* Call cleanup routines */ for (i = 0; devsw[i] != NULL; ++i) if (devsw[i]->dv_cleanup != NULL) (devsw[i]->dv_cleanup)(); } Index: head/stand/common/pnp.c =================================================================== --- head/stand/common/pnp.c (revision 330863) +++ head/stand/common/pnp.c (revision 330864) @@ -1,186 +1,186 @@ /* * mjs copyright * */ #include __FBSDID("$FreeBSD$"); /* * "Plug and Play" functionality. * * We use the PnP enumerators to obtain identifiers for installed hardware, * and the contents of a database to determine modules to be loaded to support * such hardware. */ #include #include #include static struct pnpinfo_stql pnp_devices; static int pnp_devices_initted = 0; static void pnp_discard(void); /* * Perform complete enumeration sweep */ COMMAND_SET(pnpscan, "pnpscan", "scan for PnP devices", pnp_scan); static int pnp_scan(int argc, char *argv[]) { struct pnpinfo *pi; int hdlr; int verbose; int ch; if (pnp_devices_initted == 0) { STAILQ_INIT(&pnp_devices); pnp_devices_initted = 1; } verbose = 0; optind = 1; optreset = 1; while ((ch = getopt(argc, argv, "v")) != -1) { switch(ch) { case 'v': verbose = 1; break; case '?': default: /* getopt has already reported an error */ return(CMD_OK); } } /* forget anything we think we knew */ pnp_discard(); /* iterate over all of the handlers */ for (hdlr = 0; pnphandlers[hdlr] != NULL; hdlr++) { if (verbose) printf("Probing %s...\n", pnphandlers[hdlr]->pp_name); pnphandlers[hdlr]->pp_enumerate(); } if (verbose) { pager_open(); if (pager_output("PNP scan summary:\n")) goto out; STAILQ_FOREACH(pi, &pnp_devices, pi_link) { pager_output(STAILQ_FIRST(&pi->pi_ident)->id_ident); /* first ident should be canonical */ if (pi->pi_desc != NULL) { pager_output(" : "); pager_output(pi->pi_desc); } if (pager_output("\n")) break; } out: pager_close(); } return(CMD_OK); } /* * Throw away anything we think we know about PnP devices. */ static void pnp_discard(void) { struct pnpinfo *pi; while (STAILQ_FIRST(&pnp_devices) != NULL) { pi = STAILQ_FIRST(&pnp_devices); STAILQ_REMOVE_HEAD(&pnp_devices, pi_link); pnp_freeinfo(pi); } } /* * Add a unique identifier to (pi) */ void pnp_addident(struct pnpinfo *pi, char *ident) { struct pnpident *id; STAILQ_FOREACH(id, &pi->pi_ident, id_link) if (!strcmp(id->id_ident, ident)) return; /* already have this one */ id = malloc(sizeof(struct pnpident)); id->id_ident = strdup(ident); STAILQ_INSERT_TAIL(&pi->pi_ident, id, id_link); } /* * Allocate a new pnpinfo struct */ struct pnpinfo * pnp_allocinfo(void) { struct pnpinfo *pi; pi = malloc(sizeof(struct pnpinfo)); bzero(pi, sizeof(struct pnpinfo)); STAILQ_INIT(&pi->pi_ident); return(pi); } /* * Release storage held by a pnpinfo struct */ void pnp_freeinfo(struct pnpinfo *pi) { struct pnpident *id; while (!STAILQ_EMPTY(&pi->pi_ident)) { id = STAILQ_FIRST(&pi->pi_ident); STAILQ_REMOVE_HEAD(&pi->pi_ident, id_link); free(id->id_ident); free(id); } if (pi->pi_desc) free(pi->pi_desc); if (pi->pi_module) free(pi->pi_module); if (pi->pi_argv) free(pi->pi_argv); free(pi); } /* * Add a new pnpinfo struct to the list. */ void pnp_addinfo(struct pnpinfo *pi) { STAILQ_INSERT_TAIL(&pnp_devices, pi, pi_link); } /* * Format an EISA id as a string in standard ISA PnP format, AAAIIRR * where 'AAA' is the EISA vendor ID, II is the product ID and RR the revision ID. */ char * -pnp_eisaformat(u_int8_t *data) +pnp_eisaformat(uint8_t *data) { static char idbuf[8]; const char hextoascii[] = "0123456789abcdef"; idbuf[0] = '@' + ((data[0] & 0x7c) >> 2); idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5)); idbuf[2] = '@' + (data[1] & 0x1f); idbuf[3] = hextoascii[(data[2] >> 4)]; idbuf[4] = hextoascii[(data[2] & 0xf)]; idbuf[5] = hextoascii[(data[3] >> 4)]; idbuf[6] = hextoascii[(data[3] & 0xf)]; idbuf[7] = 0; return(idbuf); } Index: head/stand/efi/boot1/ufs_module.c =================================================================== --- head/stand/efi/boot1/ufs_module.c (revision 330863) +++ head/stand/efi/boot1/ufs_module.c (revision 330864) @@ -1,185 +1,185 @@ /*- * Copyright (c) 1998 Robert Nordier * All rights reserved. * Copyright (c) 2001 Robert Drehmel * All rights reserved. * Copyright (c) 2014 Nathan Whitehorn * All rights reserved. * Copyright (c) 2015 Eric McCorkle * All rights reverved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include "boot_module.h" static dev_info_t *devinfo; static dev_info_t *devices; static int -dskread(void *buf, u_int64_t lba, int nblk) +dskread(void *buf, uint64_t lba, int nblk) { int size; EFI_STATUS status; lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE); size = nblk * DEV_BSIZE; status = devinfo->dev->ReadBlocks(devinfo->dev, devinfo->dev->Media->MediaId, lba, size, buf); if (status != EFI_SUCCESS) { DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, " "status: %lu\n", devinfo->dev, devinfo->dev->Media->MediaId, (uintmax_t)lba, size, EFI_ERROR_CODE(status)); return (-1); } return (0); } #include "ufsread.c" static struct dmadat __dmadat; static int init_dev(dev_info_t* dev) { devinfo = dev; dmadat = &__dmadat; return fsread(0, NULL, 0); } static EFI_STATUS probe(dev_info_t* dev) { if (init_dev(dev) < 0) return (EFI_UNSUPPORTED); add_device(&devices, dev); return (EFI_SUCCESS); } static EFI_STATUS load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize) { ufs_ino_t ino; EFI_STATUS status; size_t size; ssize_t read; void *buf; #ifdef EFI_DEBUG { CHAR16 *text = efi_devpath_name(dev->devpath); DPRINTF("Loading '%s' from %S\n", filepath, text); efi_free_devpath_name(text); } #endif if (init_dev(dev) < 0) { DPRINTF("Failed to init device\n"); return (EFI_UNSUPPORTED); } if ((ino = lookup(filepath)) == 0) { DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath); return (EFI_NOT_FOUND); } if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) { printf("Failed to read size of '%s' ino: %d\n", filepath, ino); return (EFI_INVALID_PARAMETER); } if ((status = BS->AllocatePool(EfiLoaderData, size, &buf)) != EFI_SUCCESS) { printf("Failed to allocate read buffer %zu for '%s' (%lu)\n", size, filepath, EFI_ERROR_CODE(status)); return (status); } read = fsread(ino, buf, size); if ((size_t)read != size) { printf("Failed to read '%s' (%zd != %zu)\n", filepath, read, size); (void)BS->FreePool(buf); return (EFI_INVALID_PARAMETER); } DPRINTF("Load complete\n"); *bufp = buf; *bufsize = size; return (EFI_SUCCESS); } static void status(void) { int i; dev_info_t *dev; for (dev = devices, i = 0; dev != NULL; dev = dev->next, i++) ; printf("%s found ", ufs_module.name); switch (i) { case 0: printf("no partitions\n"); break; case 1: printf("%d partition\n", i); break; default: printf("%d partitions\n", i); } } static dev_info_t * _devices(void) { return (devices); } const boot_module_t ufs_module = { .name = "UFS", .probe = probe, .load = load, .status = status, .devices = _devices }; Index: head/stand/efi/loader/arch/arm/exec.c =================================================================== --- head/stand/efi/loader/arch/arm/exec.c (revision 330863) +++ head/stand/efi/loader/arch/arm/exec.c (revision 330864) @@ -1,103 +1,103 @@ /*- * Copyright (c) 2001 Benno Rice * Copyright (c) 2007 Semihalf, Rafal Jaworowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "bootstrap.h" #include "loader_efi.h" extern vm_offset_t md_load(char *, vm_offset_t *); extern int bi_load(char *, vm_offset_t *, vm_offset_t *); static int -__elfN(arm_load)(char *filename, u_int64_t dest, +__elfN(arm_load)(char *filename, uint64_t dest, struct preloaded_file **result) { int r; r = __elfN(loadfile)(filename, dest, result); if (r != 0) return (r); return (0); } static int __elfN(arm_exec)(struct preloaded_file *fp) { struct file_metadata *fmp; vm_offset_t modulep, kernend; Elf_Ehdr *e; int error; void (*entry)(void *); if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return (EFTYPE); e = (Elf_Ehdr *)&fmp->md_data; efi_time_fini(); if ((error = bi_load(fp->f_args, &modulep, &kernend)) != 0) { efi_time_init(); return (error); } entry = efi_translate(e->e_entry); printf("Kernel entry at 0x%x...\n", (unsigned)entry); printf("Kernel args: %s\n", fp->f_args); printf("modulep: %#x\n", modulep); printf("relocation_offset %llx\n", __elfN(relocation_offset)); dev_cleanup(); (*entry)((void *)modulep); panic("exec returned"); } static struct file_format arm_elf = { __elfN(arm_load), __elfN(arm_exec) }; struct file_format *file_formats[] = { &arm_elf, NULL }; Index: head/stand/ficl/aarch64/sysdep.c =================================================================== --- head/stand/ficl/aarch64/sysdep.c (revision 330863) +++ head/stand/ficl/aarch64/sysdep.c (revision 330864) @@ -1,99 +1,99 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar(*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/ficl/amd64/sysdep.c =================================================================== --- head/stand/ficl/amd64/sysdep.c (revision 330863) +++ head/stand/ficl/amd64/sysdep.c (revision 330864) @@ -1,99 +1,99 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar((unsigned char)*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/ficl/arm/sysdep.c =================================================================== --- head/stand/ficl/arm/sysdep.c (revision 330863) +++ head/stand/ficl/arm/sysdep.c (revision 330864) @@ -1,99 +1,99 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar(*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/ficl/i386/sysdep.c =================================================================== --- head/stand/ficl/i386/sysdep.c (revision 330863) +++ head/stand/ficl/i386/sysdep.c (revision 330864) @@ -1,149 +1,149 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #ifdef __i386__ #include #endif #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar((unsigned char)*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } #ifndef TESTMAIN /* * outb ( port# c -- ) * Store a byte to I/O port number port# */ void ficlOutb(FICL_VM *pVM) { u_char c; - u_int32_t port; + uint32_t port; port=stackPopUNS(pVM->pStack); c=(u_char)stackPopINT(pVM->pStack); outb(port,c); } /* * inb ( port# -- c ) * Fetch a byte from I/O port number port# */ void ficlInb(FICL_VM *pVM) { u_char c; - u_int32_t port; + uint32_t port; port=stackPopUNS(pVM->pStack); c=inb(port); stackPushINT(pVM->pStack,c); } /* * Glue function to add the appropriate forth words to access x86 special cpu * functionality. */ static void ficlCompileCpufunc(FICL_SYSTEM *pSys) { FICL_DICT *dp = pSys->dp; assert (dp); dictAppendWord(dp, "outb", ficlOutb, FW_DEFAULT); dictAppendWord(dp, "inb", ficlInb, FW_DEFAULT); } FICL_COMPILE_SET(ficlCompileCpufunc); #endif /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/ficl/mips/sysdep.c =================================================================== --- head/stand/ficl/mips/sysdep.c (revision 330863) +++ head/stand/ficl/mips/sysdep.c (revision 330864) @@ -1,99 +1,99 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar(*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/ficl/mips64/sysdep.c =================================================================== --- head/stand/ficl/mips64/sysdep.c (revision 330863) +++ head/stand/ficl/mips64/sysdep.c (revision 330864) @@ -1,99 +1,99 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar(*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/ficl/powerpc/sysdep.c =================================================================== --- head/stand/ficl/powerpc/sysdep.c (revision 330863) +++ head/stand/ficl/powerpc/sysdep.c (revision 330864) @@ -1,99 +1,99 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar(*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/ficl/riscv/sysdep.c =================================================================== --- head/stand/ficl/riscv/sysdep.c (revision 330863) +++ head/stand/ficl/riscv/sysdep.c (revision 330864) @@ -1,99 +1,99 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar(*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/ficl/sparc64/sysdep.c =================================================================== --- head/stand/ficl/sparc64/sysdep.c (revision 330863) +++ head/stand/ficl/sparc64/sysdep.c (revision 330864) @@ -1,99 +1,99 @@ /******************************************************************* ** s y s d e p . c ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 16 Oct 1997 ** Implementations of FICL external interface functions... ** *******************************************************************/ /* $FreeBSD$ */ #ifdef TESTMAIN #include #include #else #include #endif #include "ficl.h" /* ******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith */ #if PORTABLE_LONGMULDIV == 0 DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) { DPUNS q; - u_int64_t qx; + uint64_t qx; - qx = (u_int64_t)x * (u_int64_t) y; + qx = (uint64_t)x * (uint64_t) y; - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); + q.hi = (uint32_t)( qx >> 32 ); + q.lo = (uint32_t)( qx & 0xFFFFFFFFL); return q; } UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) { UNSQR result; - u_int64_t qx, qh; + uint64_t qx, qh; qh = q.hi; qx = (qh << 32) | q.lo; result.quot = qx / y; result.rem = qx % y; return result; } #endif void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) { IGNORE(pVM); while(*msg != 0) putchar(*(msg++)); if (fNewline) putchar('\n'); return; } void *ficlMalloc (size_t size) { return malloc(size); } void *ficlRealloc (void *p, size_t size) { return realloc(p, size); } void ficlFree (void *p) { free(p); } /* ** Stub function for dictionary access control - does nothing ** by default, user can redefine to guarantee exclusive dict ** access to a single thread for updates. All dict update code ** is guaranteed to be bracketed as follows: ** ficlLockDictionary(TRUE); ** ** ficlLockDictionary(FALSE); ** ** Returns zero if successful, nonzero if unable to acquire lock ** befor timeout (optional - could also block forever) */ #if FICL_MULTITHREAD int ficlLockDictionary(short fLock) { IGNORE(fLock); return 0; } #endif /* FICL_MULTITHREAD */ Index: head/stand/i386/btx/lib/btxv86.h =================================================================== --- head/stand/i386/btx/lib/btxv86.h (revision 330863) +++ head/stand/i386/btx/lib/btxv86.h (revision 330864) @@ -1,75 +1,75 @@ /* * Copyright (c) 1998 Robert Nordier * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */ /* * $FreeBSD$ */ #ifndef _BTXV86_H_ #define _BTXV86_H_ #include #include /* * Memory buffer space for real mode IO. * Just one page is not much, but the space is rather limited. * See ../btx/btx.S for details. */ #define V86_IO_BUFFER 0x8000 #define V86_IO_BUFFER_SIZE 0x1000 #define V86_ADDR 0x10000 /* Segment:offset address */ #define V86_CALLF 0x20000 /* Emulate far call */ #define V86_FLAGS 0x40000 /* Return flags */ struct __v86 { uint32_t ctl; /* Control flags */ uint32_t addr; /* Interrupt number or address */ uint32_t es; /* V86 ES register */ uint32_t ds; /* V86 DS register */ uint32_t fs; /* V86 FS register */ uint32_t gs; /* V86 GS register */ uint32_t eax; /* V86 EAX register */ uint32_t ecx; /* V86 ECX register */ uint32_t edx; /* V86 EDX register */ uint32_t ebx; /* V86 EBX register */ uint32_t efl; /* V86 eflags register */ uint32_t ebp; /* V86 EBP register */ uint32_t esi; /* V86 ESI register */ uint32_t edi; /* V86 EDI register */ }; extern struct __v86 __v86; /* V86 interface structure */ void __v86int(void); #define v86 __v86 #define v86int __v86int -extern u_int32_t __base; -extern u_int32_t __args; +extern uint32_t __base; +extern uint32_t __args; #define PTOV(pa) ((caddr_t)(pa) - __base) #define VTOP(va) ((vm_offset_t)(va) + __base) -#define VTOPSEG(va) (u_int16_t)(VTOP((caddr_t)va) >> 4) -#define VTOPOFF(va) (u_int16_t)(VTOP((caddr_t)va) & 0xf) +#define VTOPSEG(va) (uint16_t)(VTOP((caddr_t)va) >> 4) +#define VTOPOFF(va) (uint16_t)(VTOP((caddr_t)va) & 0xf) #define V86_CY(x) ((x) & PSL_C) #define V86_ZR(x) ((x) & PSL_Z) void __exit(int) __attribute__((__noreturn__)); void __exec(caddr_t, ...); #endif /* !_BTXV86_H_ */ Index: head/stand/i386/libi386/biosacpi.c =================================================================== --- head/stand/i386/libi386/biosacpi.c (revision 330863) +++ head/stand/i386/libi386/biosacpi.c (revision 330864) @@ -1,144 +1,144 @@ /*- * Copyright (c) 2001 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "libi386.h" #include "platform/acfreebsd.h" #include "acconfig.h" #define ACPI_SYSTEM_XFACE #include "actypes.h" #include "actbl.h" /* * Detect ACPI and export information about the ACPI BIOS into the * environment. */ static ACPI_TABLE_RSDP *biosacpi_find_rsdp(void); static ACPI_TABLE_RSDP *biosacpi_search_rsdp(char *base, int length); #define RSDP_CHECKSUM_LENGTH 20 void biosacpi_detect(void) { ACPI_TABLE_RSDP *rsdp; char buf[24]; int revision; /* locate and validate the RSDP */ if ((rsdp = biosacpi_find_rsdp()) == NULL) return; /* * Report the RSDP to the kernel. While this can be found with * a BIOS boot, the RSDP may be elsewhere when booted from UEFI. * The old code used the 'hints' method to communite this to * the kernel. However, while convenient, the 'hints' method * is fragile and does not work when static hints are compiled * into the kernel. Instead, move to setting different tunables * that start with acpi. The old 'hints' can be removed before * we branch for FreeBSD 12. */ sprintf(buf, "0x%08x", VTOP(rsdp)); setenv("hint.acpi.0.rsdp", buf, 1); setenv("acpi.rsdp", buf, 1); revision = rsdp->Revision; if (revision == 0) revision = 1; sprintf(buf, "%d", revision); setenv("hint.acpi.0.revision", buf, 1); setenv("acpi.revision", buf, 1); strncpy(buf, rsdp->OemId, sizeof(rsdp->OemId)); buf[sizeof(rsdp->OemId)] = '\0'; setenv("hint.acpi.0.oem", buf, 1); setenv("acpi.oem", buf, 1); sprintf(buf, "0x%08x", rsdp->RsdtPhysicalAddress); setenv("hint.acpi.0.rsdt", buf, 1); setenv("acpi.rsdt", buf, 1); if (revision >= 2) { /* XXX extended checksum? */ sprintf(buf, "0x%016llx", rsdp->XsdtPhysicalAddress); setenv("hint.acpi.0.xsdt", buf, 1); setenv("acpi.xsdt", buf, 1); sprintf(buf, "%d", rsdp->Length); setenv("hint.acpi.0.xsdt_length", buf, 1); setenv("acpi.xsdt_length", buf, 1); } } /* * Find the RSDP in low memory. See section 5.2.2 of the ACPI spec. */ static ACPI_TABLE_RSDP * biosacpi_find_rsdp(void) { ACPI_TABLE_RSDP *rsdp; uint16_t *addr; /* EBDA is the 1 KB addressed by the 16 bit pointer at 0x40E. */ addr = (uint16_t *)PTOV(0x40E); if ((rsdp = biosacpi_search_rsdp((char *)(*addr << 4), 0x400)) != NULL) return (rsdp); /* Check the upper memory BIOS space, 0xe0000 - 0xfffff. */ if ((rsdp = biosacpi_search_rsdp((char *)0xe0000, 0x20000)) != NULL) return (rsdp); return (NULL); } static ACPI_TABLE_RSDP * biosacpi_search_rsdp(char *base, int length) { ACPI_TABLE_RSDP *rsdp; - u_int8_t *cp, sum; + uint8_t *cp, sum; int ofs, idx; /* search on 16-byte boundaries */ for (ofs = 0; ofs < length; ofs += 16) { rsdp = (ACPI_TABLE_RSDP *)PTOV(base + ofs); /* compare signature, validate checksum */ if (!strncmp(rsdp->Signature, ACPI_SIG_RSDP, strlen(ACPI_SIG_RSDP))) { - cp = (u_int8_t *)rsdp; + cp = (uint8_t *)rsdp; sum = 0; for (idx = 0; idx < RSDP_CHECKSUM_LENGTH; idx++) sum += *(cp + idx); if (sum != 0) continue; return(rsdp); } } return(NULL); } Index: head/stand/i386/libi386/biosdisk.c =================================================================== --- head/stand/i386/libi386/biosdisk.c (revision 330863) +++ head/stand/i386/libi386/biosdisk.c (revision 330864) @@ -1,1010 +1,1010 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 2012 Andrey V. Elsukov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * BIOS disk device handling. * * Ideas and algorithms from: * * - NetBSD libi386/biosdisk.c * - FreeBSD biosboot/disk.c * */ #include #include #include #include #include #include #include #include #include "disk.h" #include "libi386.h" #ifdef LOADER_GELI_SUPPORT #include "cons.h" #include "drv.h" #include "gpt.h" #include "part.h" #include struct pentry { struct ptable_entry part; uint64_t flags; union { uint8_t bsd; uint8_t mbr; uuid_t gpt; uint16_t vtoc8; } type; STAILQ_ENTRY(pentry) entry; }; struct ptable { enum ptable_type type; uint16_t sectorsize; uint64_t sectors; STAILQ_HEAD(, pentry) entries; }; #include "geliboot.c" #endif /* LOADER_GELI_SUPPORT */ CTASSERT(sizeof(struct i386_devdesc) >= sizeof(struct disk_devdesc)); #define BIOS_NUMDRIVES 0x475 #define BIOSDISK_SECSIZE 512 #define BUFSIZE (1 * BIOSDISK_SECSIZE) #define DT_ATAPI 0x10 /* disk type for ATAPI floppies */ #define WDMAJOR 0 /* major numbers for devices we frontend for */ #define WFDMAJOR 1 #define FDMAJOR 2 #define DAMAJOR 4 #ifdef DISK_DEBUG # define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args) #else # define DEBUG(fmt, args...) #endif /* * List of BIOS devices, translation from disk unit number to * BIOS unit number. */ static struct bdinfo { int bd_unit; /* BIOS unit number */ int bd_cyl; /* BIOS geometry */ int bd_hds; int bd_sec; int bd_flags; #define BD_MODEINT13 0x0000 #define BD_MODEEDD1 0x0001 #define BD_MODEEDD3 0x0002 #define BD_MODEMASK 0x0003 #define BD_FLOPPY 0x0004 int bd_type; /* BIOS 'drive type' (floppy only) */ uint16_t bd_sectorsize; /* Sector size */ uint64_t bd_sectors; /* Disk size */ int bd_open; /* reference counter */ void *bd_bcache; /* buffer cache data */ } bdinfo [MAXBDDEV]; static int nbdinfo = 0; #define BD(dev) (bdinfo[(dev)->dd.d_unit]) static int bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest); static int bd_write(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest); static int bd_int13probe(struct bdinfo *bd); static int bd_init(void); static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize); static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize); static int bd_open(struct open_file *f, ...); static int bd_close(struct open_file *f); static int bd_ioctl(struct open_file *f, u_long cmd, void *data); static int bd_print(int verbose); #ifdef LOADER_GELI_SUPPORT enum isgeli { ISGELI_UNKNOWN, ISGELI_NO, ISGELI_YES }; static enum isgeli geli_status[MAXBDDEV][MAXTBLENTS]; int bios_read(void *, void *, off_t off, void *buf, size_t bytes); #endif /* LOADER_GELI_SUPPORT */ struct devsw biosdisk = { "disk", DEVT_DISK, bd_init, bd_strategy, bd_open, bd_close, bd_ioctl, bd_print, NULL }; /* * Translate between BIOS device numbers and our private unit numbers. */ int bd_bios2unit(int biosdev) { int i; DEBUG("looking for bios device 0x%x", biosdev); for (i = 0; i < nbdinfo; i++) { DEBUG("bd unit %d is BIOS device 0x%x", i, bdinfo[i].bd_unit); if (bdinfo[i].bd_unit == biosdev) return (i); } return (-1); } int bd_unit2bios(int unit) { if ((unit >= 0) && (unit < nbdinfo)) return (bdinfo[unit].bd_unit); return (-1); } /* * Quiz the BIOS for disk devices, save a little info about them. */ static int bd_init(void) { int base, unit, nfd = 0; #ifdef LOADER_GELI_SUPPORT geli_init(); #endif /* sequence 0, 0x80 */ for (base = 0; base <= 0x80; base += 0x80) { for (unit = base; (nbdinfo < MAXBDDEV); unit++) { #ifndef VIRTUALBOX /* * Check the BIOS equipment list for number * of fixed disks. */ if(base == 0x80 && (nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES))) break; #endif bdinfo[nbdinfo].bd_open = 0; bdinfo[nbdinfo].bd_bcache = NULL; bdinfo[nbdinfo].bd_unit = unit; bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0; if (!bd_int13probe(&bdinfo[nbdinfo])) break; /* XXX we need "disk aliases" to make this simpler */ printf("BIOS drive %c: is disk%d\n", (unit < 0x80) ? ('A' + unit): ('C' + unit - 0x80), nbdinfo); nbdinfo++; if (base == 0x80) nfd++; } } bcache_add_dev(nbdinfo); return(0); } /* * Try to detect a device supported by the legacy int13 BIOS */ static int bd_int13probe(struct bdinfo *bd) { struct edd_params params; int ret = 1; /* assume success */ v86.ctl = V86_FLAGS; v86.addr = 0x13; v86.eax = 0x800; v86.edx = bd->bd_unit; v86int(); /* Don't error out if we get bad sector number, try EDD as well */ if (V86_CY(v86.efl) || /* carry set */ (v86.edx & 0xff) <= (unsigned)(bd->bd_unit & 0x7f)) /* unit # bad */ return (0); /* skip device */ if ((v86.ecx & 0x3f) == 0) /* absurd sector number */ ret = 0; /* set error */ /* Convert max cyl # -> # of cylinders */ bd->bd_cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1; /* Convert max head # -> # of heads */ bd->bd_hds = ((v86.edx & 0xff00) >> 8) + 1; bd->bd_sec = v86.ecx & 0x3f; bd->bd_type = v86.ebx & 0xff; bd->bd_flags |= BD_MODEINT13; /* Calculate sectors count from the geometry */ bd->bd_sectors = bd->bd_cyl * bd->bd_hds * bd->bd_sec; bd->bd_sectorsize = BIOSDISK_SECSIZE; DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl, bd->bd_hds, bd->bd_sec); /* Determine if we can use EDD with this device. */ v86.ctl = V86_FLAGS; v86.addr = 0x13; v86.eax = 0x4100; v86.edx = bd->bd_unit; v86.ebx = 0x55aa; v86int(); if (V86_CY(v86.efl) || /* carry set */ (v86.ebx & 0xffff) != 0xaa55 || /* signature */ (v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0) return (ret); /* return code from int13 AH=08 */ /* EDD supported */ bd->bd_flags |= BD_MODEEDD1; if ((v86.eax & 0xff00) >= 0x3000) bd->bd_flags |= BD_MODEEDD3; /* Get disk params */ params.len = sizeof(struct edd_params); v86.ctl = V86_FLAGS; v86.addr = 0x13; v86.eax = 0x4800; v86.edx = bd->bd_unit; v86.ds = VTOPSEG(¶ms); v86.esi = VTOPOFF(¶ms); v86int(); if (!V86_CY(v86.efl)) { uint64_t total; /* * Sector size must be a multiple of 512 bytes. * An alternate test would be to check power of 2, * powerof2(params.sector_size). */ if (params.sector_size % BIOSDISK_SECSIZE) bd->bd_sectorsize = BIOSDISK_SECSIZE; else bd->bd_sectorsize = params.sector_size; total = bd->bd_sectorsize * params.sectors; if (params.sectors != 0) { /* Only update if we did not overflow. */ if (total > params.sectors) bd->bd_sectors = params.sectors; } total = (uint64_t)params.cylinders * params.heads * params.sectors_per_track; if (bd->bd_sectors < total) bd->bd_sectors = total; ret = 1; } DEBUG("unit 0x%x flags %x, sectors %llu, sectorsize %u", bd->bd_unit, bd->bd_flags, bd->bd_sectors, bd->bd_sectorsize); return (ret); } /* * Print information about disks */ static int bd_print(int verbose) { static char line[80]; struct disk_devdesc dev; int i, ret = 0; if (nbdinfo == 0) return (0); printf("%s devices:", biosdisk.dv_name); if ((ret = pager_output("\n")) != 0) return (ret); for (i = 0; i < nbdinfo; i++) { snprintf(line, sizeof(line), " disk%d: BIOS drive %c (%ju X %u):\n", i, (bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit): ('C' + bdinfo[i].bd_unit - 0x80), (uintmax_t)bdinfo[i].bd_sectors, bdinfo[i].bd_sectorsize); if ((ret = pager_output(line)) != 0) break; dev.dd.d_dev = &biosdisk; dev.dd.d_unit = i; dev.d_slice = -1; dev.d_partition = -1; if (disk_open(&dev, bdinfo[i].bd_sectorsize * bdinfo[i].bd_sectors, bdinfo[i].bd_sectorsize) == 0) { snprintf(line, sizeof(line), " disk%d", i); ret = disk_print(&dev, line, verbose); disk_close(&dev); if (ret != 0) return (ret); } } return (ret); } /* * Attempt to open the disk described by (dev) for use by (f). * * Note that the philosophy here is "give them exactly what * they ask for". This is necessary because being too "smart" * about what the user might want leads to complications. * (eg. given no slice or partition value, with a disk that is * sliced - are they after the first BSD slice, or the DOS * slice before it?) */ static int bd_open(struct open_file *f, ...) { struct disk_devdesc *dev, rdev; struct disk_devdesc disk; int err, g_err; va_list ap; uint64_t size; va_start(ap, f); dev = va_arg(ap, struct disk_devdesc *); va_end(ap); if (dev->dd.d_unit < 0 || dev->dd.d_unit >= nbdinfo) return (EIO); BD(dev).bd_open++; if (BD(dev).bd_bcache == NULL) BD(dev).bd_bcache = bcache_allocate(); /* * Read disk size from partition. * This is needed to work around buggy BIOS systems returning * wrong (truncated) disk media size. * During bd_probe() we tested if the mulitplication of bd_sectors * would overflow so it should be safe to perform here. */ disk.dd.d_dev = dev->dd.d_dev; disk.dd.d_unit = dev->dd.d_unit; disk.d_slice = -1; disk.d_partition = -1; disk.d_offset = 0; if (disk_open(&disk, BD(dev).bd_sectors * BD(dev).bd_sectorsize, BD(dev).bd_sectorsize) == 0) { if (disk_ioctl(&disk, DIOCGMEDIASIZE, &size) == 0) { size /= BD(dev).bd_sectorsize; if (size > BD(dev).bd_sectors) BD(dev).bd_sectors = size; } disk_close(&disk); } err = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize, BD(dev).bd_sectorsize); #ifdef LOADER_GELI_SUPPORT static char gelipw[GELI_PW_MAXLEN]; char *passphrase; if (err) return (err); /* if we already know there is no GELI, skip the rest */ if (geli_status[dev->dd.d_unit][dev->d_slice] != ISGELI_UNKNOWN) return (err); struct dsk dskp; struct ptable *table = NULL; struct ptable_entry part; struct pentry *entry; int geli_part = 0; dskp.drive = bd_unit2bios(dev->dd.d_unit); dskp.type = dev->dd.d_dev->dv_type; dskp.unit = dev->dd.d_unit; dskp.slice = dev->d_slice; dskp.part = dev->d_partition; dskp.start = dev->d_offset; memcpy(&rdev, dev, sizeof(rdev)); /* to read the GPT table, we need to read the first sector */ rdev.d_offset = 0; /* We need the LBA of the end of the partition */ table = ptable_open(&rdev, BD(dev).bd_sectors, BD(dev).bd_sectorsize, ptblread); if (table == NULL) { DEBUG("Can't read partition table"); /* soft failure, return the exit status of disk_open */ return (err); } if (table->type == PTABLE_GPT) dskp.part = 255; STAILQ_FOREACH(entry, &table->entries, entry) { dskp.slice = entry->part.index; dskp.start = entry->part.start; if (is_geli(&dskp) == 0) { geli_status[dev->dd.d_unit][dskp.slice] = ISGELI_YES; return (0); } if (geli_taste(bios_read, &dskp, entry->part.end - entry->part.start) == 0) { if (geli_havekey(&dskp) == 0) { geli_status[dev->dd.d_unit][dskp.slice] = ISGELI_YES; geli_part++; continue; } if ((passphrase = getenv("kern.geom.eli.passphrase")) != NULL) { /* Use the cached passphrase */ bcopy(passphrase, &gelipw, GELI_PW_MAXLEN); } if (geli_passphrase(gelipw, dskp.unit, 'p', (dskp.slice > 0 ? dskp.slice : dskp.part), &dskp) == 0) { setenv("kern.geom.eli.passphrase", gelipw, 1); bzero(gelipw, sizeof(gelipw)); geli_status[dev->dd.d_unit][dskp.slice] = ISGELI_YES; geli_part++; continue; } } else geli_status[dev->dd.d_unit][dskp.slice] = ISGELI_NO; } /* none of the partitions on this disk have GELI */ if (geli_part == 0) { /* found no GELI */ geli_status[dev->dd.d_unit][dev->d_slice] = ISGELI_NO; } #endif /* LOADER_GELI_SUPPORT */ return (err); } static int bd_close(struct open_file *f) { struct disk_devdesc *dev; dev = (struct disk_devdesc *)f->f_devdata; BD(dev).bd_open--; if (BD(dev).bd_open == 0) { bcache_free(BD(dev).bd_bcache); BD(dev).bd_bcache = NULL; } return (disk_close(dev)); } static int bd_ioctl(struct open_file *f, u_long cmd, void *data) { struct disk_devdesc *dev; int rc; dev = (struct disk_devdesc *)f->f_devdata; rc = disk_ioctl(dev, cmd, data); if (rc != ENOTTY) return (rc); switch (cmd) { case DIOCGSECTORSIZE: *(u_int *)data = BD(dev).bd_sectorsize; break; case DIOCGMEDIASIZE: *(uint64_t *)data = BD(dev).bd_sectors * BD(dev).bd_sectorsize; break; default: return (ENOTTY); } return (0); } static int bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) { struct bcache_devdata bcd; struct disk_devdesc *dev; dev = (struct disk_devdesc *)devdata; bcd.dv_strategy = bd_realstrategy; bcd.dv_devdata = devdata; bcd.dv_cache = BD(dev).bd_bcache; return (bcache_strategy(&bcd, rw, dblk + dev->d_offset, size, buf, rsize)); } static int bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) { struct disk_devdesc *dev = (struct disk_devdesc *)devdata; uint64_t disk_blocks; int blks, rc; #ifdef BD_SUPPORT_FRAGS /* XXX: sector size */ char fragbuf[BIOSDISK_SECSIZE]; size_t fragsize; fragsize = size % BIOSDISK_SECSIZE; #else if (size % BD(dev).bd_sectorsize) panic("bd_strategy: %d bytes I/O not multiple of block size", size); #endif DEBUG("open_disk %p", dev); /* * Check the value of the size argument. We do have quite small * heap (64MB), but we do not know good upper limit, so we check against * INT_MAX here. This will also protect us against possible overflows * while translating block count to bytes. */ if (size > INT_MAX) { DEBUG("too large read: %zu bytes", size); return (EIO); } blks = size / BD(dev).bd_sectorsize; if (dblk > dblk + blks) return (EIO); if (rsize) *rsize = 0; /* Get disk blocks, this value is either for whole disk or for partition */ if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks)) { /* DIOCGMEDIASIZE does return bytes. */ disk_blocks /= BD(dev).bd_sectorsize; } else { /* We should not get here. Just try to survive. */ disk_blocks = BD(dev).bd_sectors - dev->d_offset; } /* Validate source block address. */ if (dblk < dev->d_offset || dblk >= dev->d_offset + disk_blocks) return (EIO); /* * Truncate if we are crossing disk or partition end. */ if (dblk + blks >= dev->d_offset + disk_blocks) { blks = dev->d_offset + disk_blocks - dblk; size = blks * BD(dev).bd_sectorsize; DEBUG("short read %d", blks); } switch (rw & F_MASK) { case F_READ: DEBUG("read %d from %lld to %p", blks, dblk, buf); if (blks && (rc = bd_read(dev, dblk, blks, buf))) { /* Filter out floppy controller errors */ if (BD(dev).bd_flags != BD_FLOPPY || rc != 0x20) { printf("read %d from %lld to %p, error: 0x%x", blks, dblk, buf, rc); } return (EIO); } #ifdef BD_SUPPORT_FRAGS /* XXX: sector size */ DEBUG("bd_strategy: frag read %d from %d+%d to %p", fragsize, dblk, blks, buf + (blks * BIOSDISK_SECSIZE)); if (fragsize && bd_read(od, dblk + blks, 1, fragsize)) { DEBUG("frag read error"); return(EIO); } bcopy(fragbuf, buf + (blks * BIOSDISK_SECSIZE), fragsize); #endif break; case F_WRITE : DEBUG("write %d from %d to %p", blks, dblk, buf); if (blks && bd_write(dev, dblk, blks, buf)) { DEBUG("write error"); return (EIO); } #ifdef BD_SUPPORT_FRAGS if(fragsize) { DEBUG("Attempted to write a frag"); return (EIO); } #endif break; default: /* DO NOTHING */ return (EROFS); } if (rsize) *rsize = size; return (0); } static int bd_edd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest, int write) { static struct edd_packet packet; packet.len = sizeof(struct edd_packet); packet.count = blks; packet.off = VTOPOFF(dest); packet.seg = VTOPSEG(dest); packet.lba = dblk; v86.ctl = V86_FLAGS; v86.addr = 0x13; if (write) /* Should we Write with verify ?? 0x4302 ? */ v86.eax = 0x4300; else v86.eax = 0x4200; v86.edx = BD(dev).bd_unit; v86.ds = VTOPSEG(&packet); v86.esi = VTOPOFF(&packet); v86int(); if (V86_CY(v86.efl)) return (v86.eax >> 8); return (0); } static int bd_chs_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest, int write) { u_int x, bpc, cyl, hd, sec; bpc = BD(dev).bd_sec * BD(dev).bd_hds; /* blocks per cylinder */ x = dblk; cyl = x / bpc; /* block # / blocks per cylinder */ x %= bpc; /* block offset into cylinder */ hd = x / BD(dev).bd_sec; /* offset / blocks per track */ sec = x % BD(dev).bd_sec; /* offset into track */ /* correct sector number for 1-based BIOS numbering */ sec++; if (cyl > 1023) /* CHS doesn't support cylinders > 1023. */ return (1); v86.ctl = V86_FLAGS; v86.addr = 0x13; if (write) v86.eax = 0x300 | blks; else v86.eax = 0x200 | blks; v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec; v86.edx = (hd << 8) | BD(dev).bd_unit; v86.es = VTOPSEG(dest); v86.ebx = VTOPOFF(dest); v86int(); if (V86_CY(v86.efl)) return (v86.eax >> 8); return (0); } static int bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest, int write) { u_int x, sec, result, resid, retry, maxfer; caddr_t p, xp, bbuf; /* Just in case some idiot actually tries to read/write -1 blocks... */ if (blks < 0) return (-1); resid = blks; p = dest; /* Decide whether we have to bounce */ if (VTOP(dest) >> 20 != 0 || (BD(dev).bd_unit < 0x80 && (VTOP(dest) >> 16) != (VTOP(dest + blks * BD(dev).bd_sectorsize) >> 16))) { /* * There is a 64k physical boundary somewhere in the * destination buffer, or the destination buffer is above * first 1MB of physical memory so we have to arrange a * suitable bounce buffer. Allocate a buffer twice as large * as we need to. Use the bottom half unless there is a break * there, in which case we use the top half. */ x = V86_IO_BUFFER_SIZE / BD(dev).bd_sectorsize; x = min(x, (unsigned)blks); bbuf = PTOV(V86_IO_BUFFER); maxfer = x; /* limit transfers to bounce region size */ } else { bbuf = NULL; maxfer = 0; } while (resid > 0) { /* * Play it safe and don't cross track boundaries. * (XXX this is probably unnecessary) */ sec = dblk % BD(dev).bd_sec; /* offset into track */ x = min(BD(dev).bd_sec - sec, resid); if (maxfer > 0) x = min(x, maxfer); /* fit bounce buffer */ /* where do we transfer to? */ xp = bbuf == NULL ? p : bbuf; /* * Put your Data In, Put your Data out, * Put your Data In, and shake it all about */ if (write && bbuf != NULL) bcopy(p, bbuf, x * BD(dev).bd_sectorsize); /* * Loop retrying the operation a couple of times. The BIOS * may also retry. */ for (retry = 0; retry < 3; retry++) { /* if retrying, reset the drive */ if (retry > 0) { v86.ctl = V86_FLAGS; v86.addr = 0x13; v86.eax = 0; v86.edx = BD(dev).bd_unit; v86int(); } if (BD(dev).bd_flags & BD_MODEEDD1) result = bd_edd_io(dev, dblk, x, xp, write); else result = bd_chs_io(dev, dblk, x, xp, write); if (result == 0) break; } if (write) DEBUG("Write %d sector(s) from %p (0x%x) to %lld %s", x, p, VTOP(p), dblk, result ? "failed" : "ok"); else DEBUG("Read %d sector(s) from %lld to %p (0x%x) %s", x, dblk, p, VTOP(p), result ? "failed" : "ok"); if (result) { return (result); } if (!write && bbuf != NULL) bcopy(bbuf, p, x * BD(dev).bd_sectorsize); p += (x * BD(dev).bd_sectorsize); dblk += x; resid -= x; } /* hexdump(dest, (blks * BD(dev).bd_sectorsize)); */ return(0); } static int bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest) { #ifdef LOADER_GELI_SUPPORT struct dsk dskp; off_t p_off, diff; daddr_t alignlba; int err, n, alignblks; char *tmpbuf; /* if we already know there is no GELI, skip the rest */ if (geli_status[dev->dd.d_unit][dev->d_slice] != ISGELI_YES) return (bd_io(dev, dblk, blks, dest, 0)); if (geli_status[dev->dd.d_unit][dev->d_slice] == ISGELI_YES) { /* * Align reads to DEV_GELIBOOT_BSIZE bytes because partial * sectors cannot be decrypted. Round the requested LBA down to * nearest multiple of DEV_GELIBOOT_BSIZE bytes. */ alignlba = rounddown2(dblk * BD(dev).bd_sectorsize, DEV_GELIBOOT_BSIZE) / BD(dev).bd_sectorsize; /* * Round number of blocks to read up to nearest multiple of * DEV_GELIBOOT_BSIZE */ diff = (dblk - alignlba) * BD(dev).bd_sectorsize; alignblks = roundup2(blks * BD(dev).bd_sectorsize + diff, DEV_GELIBOOT_BSIZE) / BD(dev).bd_sectorsize; /* * If the read is rounded up to a larger size, use a temporary * buffer here because the buffer provided by the caller may be * too small. */ if (diff == 0) { tmpbuf = dest; } else { tmpbuf = malloc(alignblks * BD(dev).bd_sectorsize); if (tmpbuf == NULL) { return (-1); } } err = bd_io(dev, alignlba, alignblks, tmpbuf, 0); if (err) return (err); dskp.drive = bd_unit2bios(dev->dd.d_unit); dskp.type = dev->dd.d_dev->dv_type; dskp.unit = dev->dd.d_unit; dskp.slice = dev->d_slice; dskp.part = dev->d_partition; dskp.start = dev->d_offset; /* GELI needs the offset relative to the partition start */ p_off = alignlba - dskp.start; err = geli_read(&dskp, p_off * BD(dev).bd_sectorsize, (u_char *)tmpbuf, alignblks * BD(dev).bd_sectorsize); if (err) return (err); if (tmpbuf != dest) { bcopy(tmpbuf + diff, dest, blks * BD(dev).bd_sectorsize); free(tmpbuf); } return (0); } #endif /* LOADER_GELI_SUPPORT */ return (bd_io(dev, dblk, blks, dest, 0)); } static int bd_write(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest) { return (bd_io(dev, dblk, blks, dest, 1)); } /* * Return the BIOS geometry of a given "fixed drive" in a format * suitable for the legacy bootinfo structure. Since the kernel is * expecting raw int 0x13/0x8 values for N_BIOS_GEOM drives, we * prefer to get the information directly, rather than rely on being * able to put it together from information already maintained for * different purposes and for a probably different number of drives. * * For valid drives, the geometry is expected in the format (31..0) * "000000cc cccccccc hhhhhhhh 00ssssss"; and invalid drives are * indicated by returning the geometry of a "1.2M" PC-format floppy * disk. And, incidentally, what is returned is not the geometry as * such but the highest valid cylinder, head, and sector numbers. */ -u_int32_t +uint32_t bd_getbigeom(int bunit) { v86.ctl = V86_FLAGS; v86.addr = 0x13; v86.eax = 0x800; v86.edx = 0x80 + bunit; v86int(); if (V86_CY(v86.efl)) return 0x4f010f; return ((v86.ecx & 0xc0) << 18) | ((v86.ecx & 0xff00) << 8) | (v86.edx & 0xff00) | (v86.ecx & 0x3f); } /* * Return a suitable dev_t value for (dev). * * In the case where it looks like (dev) is a SCSI disk, we allow the number of * IDE disks to be specified in $num_ide_disks. There should be a Better Way. */ int bd_getdev(struct i386_devdesc *d) { struct disk_devdesc *dev; int biosdev; int major; int rootdev; char *nip, *cp; int i, unit; dev = (struct disk_devdesc *)d; biosdev = bd_unit2bios(dev->dd.d_unit); DEBUG("unit %d BIOS device %d", dev->dd.d_unit, biosdev); if (biosdev == -1) /* not a BIOS device */ return(-1); if (disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize, BD(dev).bd_sectorsize) != 0) /* oops, not a viable device */ return (-1); else disk_close(dev); if (biosdev < 0x80) { /* floppy (or emulated floppy) or ATAPI device */ if (bdinfo[dev->dd.d_unit].bd_type == DT_ATAPI) { /* is an ATAPI disk */ major = WFDMAJOR; } else { /* is a floppy disk */ major = FDMAJOR; } } else { /* assume an IDE disk */ major = WDMAJOR; } /* default root disk unit number */ unit = biosdev & 0x7f; /* XXX a better kludge to set the root disk unit number */ if ((nip = getenv("root_disk_unit")) != NULL) { i = strtol(nip, &cp, 0); /* check for parse error */ if ((cp != nip) && (*cp == 0)) unit = i; } rootdev = MAKEBOOTDEV(major, dev->d_slice + 1, unit, dev->d_partition); DEBUG("dev is 0x%x\n", rootdev); return(rootdev); } #ifdef LOADER_GELI_SUPPORT int bios_read(void *vdev __unused, void *xpriv, off_t off, void *buf, size_t bytes) { struct disk_devdesc dev; struct dsk *priv = xpriv; dev.dd.d_dev = &biosdisk; dev.dd.d_unit = priv->unit; dev.d_slice = priv->slice; dev.d_partition = priv->part; dev.d_offset = priv->start; off = off / BD(&dev).bd_sectorsize; /* GELI gives us the offset relative to the partition start */ off += dev.d_offset; bytes = bytes / BD(&dev).bd_sectorsize; return (bd_io(&dev, off, bytes, buf, 0)); } #endif /* LOADER_GELI_SUPPORT */ Index: head/stand/i386/libi386/biospnp.c =================================================================== --- head/stand/i386/libi386/biospnp.c (revision 330863) +++ head/stand/i386/libi386/biospnp.c (revision 330864) @@ -1,292 +1,292 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * PnP BIOS enumerator. */ #include #include #include #include #include static int biospnp_init(void); static void biospnp_enumerate(void); struct pnphandler biospnphandler = { "PnP BIOS", biospnp_enumerate }; struct pnp_ICstructure { - u_int8_t pnp_signature[4]; - u_int8_t pnp_version; - u_int8_t pnp_length; - u_int16_t pnp_BIOScontrol; - u_int8_t pnp_checksum; - u_int32_t pnp_eventflag; - u_int16_t pnp_rmip; - u_int16_t pnp_rmcs; - u_int16_t pnp_pmip; - u_int32_t pnp_pmcs; - u_int8_t pnp_OEMdev[4]; - u_int16_t pnp_rmds; - u_int32_t pnp_pmds; + uint8_t pnp_signature[4]; + uint8_t pnp_version; + uint8_t pnp_length; + uint16_t pnp_BIOScontrol; + uint8_t pnp_checksum; + uint32_t pnp_eventflag; + uint16_t pnp_rmip; + uint16_t pnp_rmcs; + uint16_t pnp_pmip; + uint32_t pnp_pmcs; + uint8_t pnp_OEMdev[4]; + uint16_t pnp_rmds; + uint32_t pnp_pmds; } __packed; struct pnp_devNode { - u_int16_t dn_size; - u_int8_t dn_handle; - u_int8_t dn_id[4]; - u_int8_t dn_type[3]; - u_int16_t dn_attrib; - u_int8_t dn_data[1]; + uint16_t dn_size; + uint8_t dn_handle; + uint8_t dn_id[4]; + uint8_t dn_type[3]; + uint16_t dn_attrib; + uint8_t dn_data[1]; } __packed; struct pnp_isaConfiguration { - u_int8_t ic_revision; - u_int8_t ic_nCSN; - u_int16_t ic_rdport; - u_int16_t ic_reserved; + uint8_t ic_revision; + uint8_t ic_nCSN; + uint16_t ic_rdport; + uint16_t ic_reserved; } __packed; static struct pnp_ICstructure *pnp_Icheck = NULL; -static u_int16_t pnp_NumNodes; -static u_int16_t pnp_NodeSize; +static uint16_t pnp_NumNodes; +static uint16_t pnp_NodeSize; static void biospnp_scanresdata(struct pnpinfo *pi, struct pnp_devNode *dn); static int biospnp_call(int func, const char *fmt, ...); -#define vsegofs(vptr) (((u_int32_t)VTOPSEG(vptr) << 16) + VTOPOFF(vptr)) +#define vsegofs(vptr) (((uint32_t)VTOPSEG(vptr) << 16) + VTOPOFF(vptr)) -typedef void v86bios_t(u_int32_t, u_int32_t, u_int32_t, u_int32_t); +typedef void v86bios_t(uint32_t, uint32_t, uint32_t, uint32_t); v86bios_t *v86bios = (v86bios_t *)v86int; #define biospnp_f00(NumNodes, NodeSize) biospnp_call(0x00, "ll", NumNodes, NodeSize) #define biospnp_f01(Node, devNodeBuffer, Control) biospnp_call(0x01, "llw", Node, devNodeBuffer, Control) #define biospnp_f40(Configuration) biospnp_call(0x40, "l", Configuration) /* PnP BIOS return codes */ #define PNP_SUCCESS 0x00 #define PNP_FUNCTION_NOT_SUPPORTED 0x80 /* * Initialisation: locate the PnP BIOS, test that we can call it. * Returns nonzero if the PnP BIOS is not usable on this system. */ static int biospnp_init(void) { struct pnp_isaConfiguration icfg; char *sigptr; int result; /* Search for the $PnP signature */ pnp_Icheck = NULL; for (sigptr = PTOV(0xf0000); sigptr < PTOV(0xfffff); sigptr += 16) if (!bcmp(sigptr, "$PnP", 4)) { pnp_Icheck = (struct pnp_ICstructure *)sigptr; break; } /* No signature, no BIOS */ if (pnp_Icheck == NULL) return(1); /* * Fetch the system table parameters as a test of the BIOS */ result = biospnp_f00(vsegofs(&pnp_NumNodes), vsegofs(&pnp_NodeSize)); if (result != PNP_SUCCESS) { return(1); } /* * Look for the PnP ISA configuration table */ result = biospnp_f40(vsegofs(&icfg)); switch (result) { case PNP_SUCCESS: /* If the BIOS found some PnP devices, take its hint for the read port */ if ((icfg.ic_revision == 1) && (icfg.ic_nCSN > 0)) isapnp_readport = icfg.ic_rdport; break; case PNP_FUNCTION_NOT_SUPPORTED: /* The BIOS says there is no ISA bus (should we trust that this works?) */ printf("PnP BIOS claims no ISA bus\n"); isapnp_readport = -1; break; } return(0); } static void biospnp_enumerate(void) { - u_int8_t Node; + uint8_t Node; struct pnp_devNode *devNodeBuffer; int result; struct pnpinfo *pi; int count; /* Init/check state */ if (biospnp_init()) return; devNodeBuffer = (struct pnp_devNode *)alloca(pnp_NodeSize); Node = 0; count = 1000; while((Node != 0xff) && (count-- > 0)) { result = biospnp_f01(vsegofs(&Node), vsegofs(devNodeBuffer), 0x1); if (result != PNP_SUCCESS) { printf("PnP BIOS node %d: error 0x%x\n", Node, result); } else { pi = pnp_allocinfo(); pnp_addident(pi, pnp_eisaformat(devNodeBuffer->dn_id)); biospnp_scanresdata(pi, devNodeBuffer); pnp_addinfo(pi); } } } /* * Scan the resource data in the node's data area for compatible device IDs * and descriptions. */ static void biospnp_scanresdata(struct pnpinfo *pi, struct pnp_devNode *dn) { u_int tag, i, rlen, dlen; - u_int8_t *p; + uint8_t *p; char *str; p = dn->dn_data; /* point to resource data */ - dlen = dn->dn_size - (p - (u_int8_t *)dn); /* length of resource data */ + dlen = dn->dn_size - (p - (uint8_t *)dn); /* length of resource data */ for (i = 0; i < dlen; i+= rlen) { tag = p[i]; i++; if (PNP_RES_TYPE(tag) == 0) { rlen = PNP_SRES_LEN(tag); /* small resource */ switch (PNP_SRES_NUM(tag)) { case COMP_DEVICE_ID: /* got a compatible device ID */ pnp_addident(pi, pnp_eisaformat(p + i)); break; case END_TAG: return; } } else { /* large resource */ - rlen = *(u_int16_t *)(p + i); - i += sizeof(u_int16_t); + rlen = *(uint16_t *)(p + i); + i += sizeof(uint16_t); switch(PNP_LRES_NUM(tag)) { case ID_STRING_ANSI: str = malloc(rlen + 1); bcopy(p + i, str, rlen); str[rlen] = 0; if (pi->pi_desc == NULL) { pi->pi_desc = str; } else { free(str); } break; } } } } /* * Make a 16-bit realmode PnP BIOS call. * * The first argument passed is the function number, the last is the * BIOS data segment selector. Intermediate arguments may be 16 or * 32 bytes in length, and are described by the format string. * * Arguments to the BIOS functions must be packed on the stack, hence * this evil. */ static int biospnp_call(int func, const char *fmt, ...) { va_list ap; const char *p; - u_int8_t *argp; - u_int32_t args[4]; - u_int32_t i; + uint8_t *argp; + uint32_t args[4]; + uint32_t i; /* function number first */ - argp = (u_int8_t *)args; - *(u_int16_t *)argp = func; - argp += sizeof(u_int16_t); + argp = (uint8_t *)args; + *(uint16_t *)argp = func; + argp += sizeof(uint16_t); /* take args according to format */ va_start(ap, fmt); for (p = fmt; *p != 0; p++) { switch(*p) { case 'w': i = va_arg(ap, u_int); - *(u_int16_t *)argp = i; - argp += sizeof(u_int16_t); + *(uint16_t *)argp = i; + argp += sizeof(uint16_t); break; case 'l': - i = va_arg(ap, u_int32_t); - *(u_int32_t *)argp = i; - argp += sizeof(u_int32_t); + i = va_arg(ap, uint32_t); + *(uint32_t *)argp = i; + argp += sizeof(uint32_t); break; } } va_end(ap); /* BIOS segment last */ - *(u_int16_t *)argp = pnp_Icheck->pnp_rmds; - argp += sizeof(u_int16_t); + *(uint16_t *)argp = pnp_Icheck->pnp_rmds; + argp += sizeof(uint16_t); /* prepare for call */ v86.ctl = V86_ADDR | V86_CALLF; - v86.addr = ((u_int32_t)pnp_Icheck->pnp_rmcs << 16) + pnp_Icheck->pnp_rmip; + v86.addr = ((uint32_t)pnp_Icheck->pnp_rmcs << 16) + pnp_Icheck->pnp_rmip; /* call with packed stack and return */ v86bios(args[0], args[1], args[2], args[3]); return(v86.eax & 0xffff); } Index: head/stand/i386/libi386/bootinfo32.c =================================================================== --- head/stand/i386/libi386/bootinfo32.c (revision 330863) +++ head/stand/i386/libi386/bootinfo32.c (revision 330864) @@ -1,292 +1,292 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "bootstrap.h" #include "libi386.h" #include "btxv86.h" #ifdef LOADER_GELI_SUPPORT #include "geliboot.h" static const size_t keybuf_size = sizeof(struct keybuf) + (GELI_MAX_KEYS * sizeof(struct keybuf_ent)); #endif static struct bootinfo bi; /* * Copy module-related data into the load area, where it can be * used as a directory for loaded modules. * * Module data is presented in a self-describing format. Each datum * is preceded by a 32-bit identifier and a 32-bit size field. * * Currently, the following data are saved: * * MOD_NAME (variable) module name (string) * MOD_TYPE (variable) module type (string) * MOD_ARGS (variable) module parameters (string) * MOD_ADDR sizeof(vm_offset_t) module load address * MOD_SIZE sizeof(size_t) module size * MOD_METADATA (variable) type-specific metadata */ #define COPY32(v, a, c) { \ - u_int32_t x = (v); \ + uint32_t x = (v); \ if (c) \ i386_copyin(&x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c); \ if (c) \ i386_copyin(s, a, strlen(s) + 1); \ a += roundup(strlen(s) + 1, sizeof(u_long));\ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ i386_copyin(&s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(u_long)); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c); \ COPY32(mm->md_size, a, c); \ if (c) \ i386_copyin(mm->md_data, a, mm->md_size); \ a += roundup(mm->md_size, sizeof(u_long));\ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t bi_copymodules32(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; int c; c = addr != 0; /* start with the first module on the list, should be the kernel */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { MOD_NAME(addr, fp->f_name, c); /* this field must come first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); MOD_ADDR(addr, fp->f_addr, c); MOD_SIZE(addr, fp->f_size, c); for (md = fp->f_metadata; md != NULL; md = md->md_next) if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md, c); } MOD_END(addr, c); return(addr); } /* * Load the information expected by an i386 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernendp) { struct preloaded_file *xp, *kfp; struct i386_devdesc *rootdev; struct file_metadata *md; vm_offset_t addr; vm_offset_t kernend; vm_offset_t envp; vm_offset_t size; vm_offset_t ssym, esym; char *rootdevname; int bootdevnr, i, howto; char *kernelname; const char *kernelpath; #ifdef LOADER_GELI_SUPPORT char buf[keybuf_size]; struct keybuf *keybuf = (struct keybuf *)buf; #endif howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); i386_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(i386_fmtdev((void *)rootdev)); /* Do legacy rootdev guessing */ /* XXX - use a default bootdev of 0. Is this ok??? */ bootdevnr = 0; switch(rootdev->dd.d_dev->dv_type) { case DEVT_CD: /* Pass in BIOS device number. */ bi.bi_bios_dev = bc_unit2bios(rootdev->dd.d_unit); bootdevnr = bc_getdev(rootdev); break; case DEVT_DISK: /* pass in the BIOS device number of the current disk */ bi.bi_bios_dev = bd_unit2bios(rootdev->dd.d_unit); bootdevnr = bd_getdev(rootdev); break; case DEVT_NET: case DEVT_ZFS: break; default: printf("WARNING - don't know how to boot from device type %d\n", rootdev->dd.d_dev->dv_type); } if (bootdevnr == -1) { printf("root device %s invalid\n", i386_fmtdev(rootdev)); return (EINVAL); } free(rootdev); /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* copy our environment */ envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf32 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); bios_addsmapdata(kfp); #ifdef LOADER_GELI_SUPPORT geli_fill_keybuf(keybuf); file_addmetadata(kfp, MODINFOMD_KEYBUF, keybuf_size, buf); bzero(buf, sizeof(buf)); #endif /* Figure out the size and location of the metadata */ *modulep = addr; size = bi_copymodules32(0); kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* copy module list and metadata */ (void)bi_copymodules32(addr); ssym = esym = 0; md = file_findmetadata(kfp, MODINFOMD_SSYM); if (md != NULL) ssym = *((vm_offset_t *)&(md->md_data)); md = file_findmetadata(kfp, MODINFOMD_ESYM); if (md != NULL) esym = *((vm_offset_t *)&(md->md_data)); if (ssym == 0 || esym == 0) ssym = esym = 0; /* sanity */ /* legacy bootinfo structure */ kernelname = getenv("kernelname"); i386_getdev(NULL, kernelname, &kernelpath); bi.bi_version = BOOTINFO_VERSION; bi.bi_kernelname = 0; /* XXX char * -> kernel name */ bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */ bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */ for (i = 0; i < N_BIOS_GEOM; i++) bi.bi_bios_geom[i] = bd_getbigeom(i); bi.bi_size = sizeof(bi); bi.bi_memsizes_valid = 1; bi.bi_basemem = bios_basemem / 1024; bi.bi_extmem = bios_extmem / 1024; bi.bi_envp = envp; bi.bi_modulep = *modulep; bi.bi_kernend = kernend; bi.bi_kernelname = VTOP(kernelpath); bi.bi_symtab = ssym; /* XXX this is only the primary kernel symtab */ bi.bi_esymtab = esym; /* legacy boot arguments */ *howtop = howto | RB_BOOTINFO; *bootdevp = bootdevnr; *bip = VTOP(&bi); return(0); } Index: head/stand/i386/libi386/bootinfo64.c =================================================================== --- head/stand/i386/libi386/bootinfo64.c (revision 330863) +++ head/stand/i386/libi386/bootinfo64.c (revision 330864) @@ -1,280 +1,280 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "bootstrap.h" #include "libi386.h" #include "btxv86.h" #ifdef LOADER_GELI_SUPPORT #include "geliboot.h" static const size_t keybuf_size = sizeof(struct keybuf) + (GELI_MAX_KEYS * sizeof(struct keybuf_ent)); #endif /* * Copy module-related data into the load area, where it can be * used as a directory for loaded modules. * * Module data is presented in a self-describing format. Each datum * is preceded by a 32-bit identifier and a 32-bit size field. * * Currently, the following data are saved: * * MOD_NAME (variable) module name (string) * MOD_TYPE (variable) module type (string) * MOD_ARGS (variable) module parameters (string) * MOD_ADDR sizeof(vm_offset_t) module load address * MOD_SIZE sizeof(size_t) module size * MOD_METADATA (variable) type-specific metadata */ #define COPY32(v, a, c) { \ - u_int32_t x = (v); \ + uint32_t x = (v); \ if (c) \ i386_copyin(&x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c); \ if (c) \ i386_copyin(s, a, strlen(s) + 1); \ - a += roundup(strlen(s) + 1, sizeof(u_int64_t));\ + a += roundup(strlen(s) + 1, sizeof(uint64_t));\ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ i386_copyin(&s, a, sizeof(s)); \ - a += roundup(sizeof(s), sizeof(u_int64_t)); \ + a += roundup(sizeof(s), sizeof(uint64_t)); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c); \ COPY32(mm->md_size, a, c); \ if (c) \ i386_copyin(mm->md_data, a, mm->md_size); \ - a += roundup(mm->md_size, sizeof(u_int64_t));\ + a += roundup(mm->md_size, sizeof(uint64_t));\ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t bi_copymodules64(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; int c; - u_int64_t v; + uint64_t v; c = addr != 0; /* start with the first module on the list, should be the kernel */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { MOD_NAME(addr, fp->f_name, c); /* this field must come first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); v = fp->f_addr; MOD_ADDR(addr, v, c); v = fp->f_size; MOD_SIZE(addr, v, c); for (md = fp->f_metadata; md != NULL; md = md->md_next) if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md, c); } MOD_END(addr, c); return(addr); } /* * Check to see if this CPU supports long mode. */ static int bi_checkcpu(void) { char *cpu_vendor; int vendor[3]; int eflags; unsigned int regs[4]; /* Check for presence of "cpuid". */ eflags = read_eflags(); write_eflags(eflags ^ PSL_ID); if (!((eflags ^ read_eflags()) & PSL_ID)) return (0); /* Fetch the vendor string. */ do_cpuid(0, regs); vendor[0] = regs[1]; vendor[1] = regs[3]; vendor[2] = regs[2]; cpu_vendor = (char *)vendor; /* Check for vendors that support AMD features. */ if (strncmp(cpu_vendor, INTEL_VENDOR_ID, 12) != 0 && strncmp(cpu_vendor, AMD_VENDOR_ID, 12) != 0 && strncmp(cpu_vendor, CENTAUR_VENDOR_ID, 12) != 0) return (0); /* Has to support AMD features. */ do_cpuid(0x80000000, regs); if (!(regs[0] >= 0x80000001)) return (0); /* Check for long mode. */ do_cpuid(0x80000001, regs); return (regs[3] & AMDID_LM); } /* * Load the information expected by an amd64 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep, vm_offset_t *kernendp, int add_smap) { struct preloaded_file *xp, *kfp; struct i386_devdesc *rootdev; struct file_metadata *md; - u_int64_t kernend; - u_int64_t envp; - u_int64_t module; + uint64_t kernend; + uint64_t envp; + uint64_t module; vm_offset_t size; char *rootdevname; int howto; #ifdef LOADER_GELI_SUPPORT char buf[keybuf_size]; struct keybuf *keybuf = (struct keybuf *)buf; #endif if (!bi_checkcpu()) { printf("CPU doesn't support long mode\n"); return (EINVAL); } howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); i386_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(i386_fmtdev((void *)rootdev)); if (addr == 0) { /* find the last module in the chain */ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* place the metadata before anything */ module = *modulep = addr; kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf64 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); file_addmetadata(kfp, MODINFOMD_MODULEP, sizeof module, &module); if (add_smap != 0) bios_addsmapdata(kfp); #ifdef LOADER_GELI_SUPPORT geli_fill_keybuf(keybuf); file_addmetadata(kfp, MODINFOMD_KEYBUF, keybuf_size, buf); bzero(buf, sizeof(buf)); #endif size = bi_copymodules64(0); /* copy our environment */ envp = roundup(addr + size, PAGE_SIZE); addr = bi_copyenv(envp); /* set kernend */ kernend = roundup(addr, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* patch MODINFOMD_ENVP */ md = file_findmetadata(kfp, MODINFOMD_ENVP); bcopy(&envp, md->md_data, sizeof envp); /* copy module list and metadata */ (void)bi_copymodules64(*modulep); return(0); } Index: head/stand/i386/libi386/elf64_freebsd.c =================================================================== --- head/stand/i386/libi386/elf64_freebsd.c (revision 330863) +++ head/stand/i386/libi386/elf64_freebsd.c (revision 330864) @@ -1,126 +1,126 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #define __ELF_WORD_SIZE 64 #include #include #include #include #include #include #include #include "bootstrap.h" #include "libi386.h" #include "btxv86.h" static int elf64_exec(struct preloaded_file *amp); static int elf64_obj_exec(struct preloaded_file *amp); struct file_format amd64_elf = { elf64_loadfile, elf64_exec }; struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec }; #define PG_V 0x001 #define PG_RW 0x002 #define PG_U 0x004 #define PG_PS 0x080 -typedef u_int64_t p4_entry_t; -typedef u_int64_t p3_entry_t; -typedef u_int64_t p2_entry_t; +typedef uint64_t p4_entry_t; +typedef uint64_t p3_entry_t; +typedef uint64_t p2_entry_t; extern p4_entry_t PT4[]; extern p3_entry_t PT3[]; extern p2_entry_t PT2[]; -u_int32_t entry_hi; -u_int32_t entry_lo; +uint32_t entry_hi; +uint32_t entry_lo; extern void amd64_tramp(); /* * There is an ELF kernel and one or more ELF modules loaded. * We wish to start executing the kernel image, so make such * preparations as are required, and do so. */ static int elf64_exec(struct preloaded_file *fp) { struct file_metadata *md; Elf_Ehdr *ehdr; vm_offset_t modulep, kernend; int err; int i; if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); ehdr = (Elf_Ehdr *)&(md->md_data); err = bi_load64(fp->f_args, 0, &modulep, &kernend, 1); if (err != 0) return(err); bzero(PT4, PAGE_SIZE); bzero(PT3, PAGE_SIZE); bzero(PT2, PAGE_SIZE); /* * This is kinda brutal, but every single 1GB VM memory segment points to * the same first 1GB of physical memory. But it is more than adequate. */ for (i = 0; i < 512; i++) { /* Each slot of the level 4 pages points to the same level 3 page */ PT4[i] = (p4_entry_t)VTOP((uintptr_t)&PT3[0]); PT4[i] |= PG_V | PG_RW | PG_U; /* Each slot of the level 3 pages points to the same level 2 page */ PT3[i] = (p3_entry_t)VTOP((uintptr_t)&PT2[0]); PT3[i] |= PG_V | PG_RW | PG_U; /* The level 2 page slots are mapped with 2MB pages for 1GB. */ PT2[i] = i * (2 * 1024 * 1024); PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; } entry_lo = ehdr->e_entry & 0xffffffff; entry_hi = (ehdr->e_entry >> 32) & 0xffffffff; #ifdef DEBUG printf("Start @ %#llx ...\n", ehdr->e_entry); #endif dev_cleanup(); __exec((void *)VTOP(amd64_tramp), modulep, kernend); panic("exec returned"); } static int elf64_obj_exec(struct preloaded_file *fp) { return (EFTYPE); } Index: head/stand/i386/libi386/multiboot.c =================================================================== --- head/stand/i386/libi386/multiboot.c (revision 330863) +++ head/stand/i386/libi386/multiboot.c (revision 330864) @@ -1,467 +1,467 @@ /*- * Copyright (c) 2014 Roger Pau Monné * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * This multiboot implementation only implements a subset of the full * multiboot specification in order to be able to boot Xen and a * FreeBSD Dom0. Trying to use it to boot other multiboot compliant * kernels will most surely fail. * * The full multiboot specification can be found here: * http://www.gnu.org/software/grub/manual/multiboot/multiboot.html */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #define _MACHINE_ELF_WANT_32BIT #include #include #include #include "bootstrap.h" #include "multiboot.h" #include "libi386.h" #include #define MULTIBOOT_SUPPORTED_FLAGS \ (MULTIBOOT_PAGE_ALIGN|MULTIBOOT_MEMORY_INFO) #define NUM_MODULES 2 #define METADATA_FIXED_SIZE (PAGE_SIZE*4) #define METADATA_MODULE_SIZE PAGE_SIZE #define METADATA_RESV_SIZE(mod_num) \ roundup(METADATA_FIXED_SIZE + METADATA_MODULE_SIZE * mod_num, PAGE_SIZE) -extern int elf32_loadfile_raw(char *filename, u_int64_t dest, +extern int elf32_loadfile_raw(char *filename, uint64_t dest, struct preloaded_file **result, int multiboot); -extern int elf64_load_modmetadata(struct preloaded_file *fp, u_int64_t dest); -extern int elf64_obj_loadfile(char *filename, u_int64_t dest, +extern int elf64_load_modmetadata(struct preloaded_file *fp, uint64_t dest); +extern int elf64_obj_loadfile(char *filename, uint64_t dest, struct preloaded_file **result); -static int multiboot_loadfile(char *, u_int64_t, struct preloaded_file **); +static int multiboot_loadfile(char *, uint64_t, struct preloaded_file **); static int multiboot_exec(struct preloaded_file *); -static int multiboot_obj_loadfile(char *, u_int64_t, struct preloaded_file **); +static int multiboot_obj_loadfile(char *, uint64_t, struct preloaded_file **); static int multiboot_obj_exec(struct preloaded_file *fp); struct file_format multiboot = { multiboot_loadfile, multiboot_exec }; struct file_format multiboot_obj = { multiboot_obj_loadfile, multiboot_obj_exec }; extern void multiboot_tramp(); static const char mbl_name[] = "FreeBSD Loader"; static int num_modules(struct preloaded_file *kfp) { struct kernel_module *kmp; int mod_num = 0; for (kmp = kfp->f_modules; kmp != NULL; kmp = kmp->m_next) mod_num++; return (mod_num); } static vm_offset_t max_addr(void) { struct preloaded_file *fp; vm_offset_t addr = 0; for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { if (addr < (fp->f_addr + fp->f_size)) addr = fp->f_addr + fp->f_size; } return (addr); } static int -multiboot_loadfile(char *filename, u_int64_t dest, +multiboot_loadfile(char *filename, uint64_t dest, struct preloaded_file **result) { uint32_t *magic; int i, error; caddr_t header_search; ssize_t search_size; int fd; struct multiboot_header *header; char *cmdline; /* * Read MULTIBOOT_SEARCH size in order to search for the * multiboot magic header. */ if (filename == NULL) return (EFTYPE); if ((fd = open(filename, O_RDONLY)) == -1) return (errno); header_search = malloc(MULTIBOOT_SEARCH); if (header_search == NULL) { close(fd); return (ENOMEM); } search_size = read(fd, header_search, MULTIBOOT_SEARCH); magic = (uint32_t *)header_search; header = NULL; for (i = 0; i < (search_size / sizeof(uint32_t)); i++) { if (magic[i] == MULTIBOOT_HEADER_MAGIC) { header = (struct multiboot_header *)&magic[i]; break; } } if (header == NULL) { error = EFTYPE; goto out; } /* Valid multiboot header has been found, validate checksum */ if (header->magic + header->flags + header->checksum != 0) { printf( "Multiboot checksum failed, magic: 0x%x flags: 0x%x checksum: 0x%x\n", header->magic, header->flags, header->checksum); error = EFTYPE; goto out; } if ((header->flags & ~MULTIBOOT_SUPPORTED_FLAGS) != 0) { printf("Unsupported multiboot flags found: 0x%x\n", header->flags); error = EFTYPE; goto out; } error = elf32_loadfile_raw(filename, dest, result, 1); if (error != 0) { printf( "elf32_loadfile_raw failed: %d unable to load multiboot kernel\n", error); goto out; } /* * f_addr is already aligned to PAGE_SIZE, make sure * f_size it's also aligned so when the modules are loaded * they are aligned to PAGE_SIZE. */ (*result)->f_size = roundup((*result)->f_size, PAGE_SIZE); out: free(header_search); close(fd); return (error); } static int multiboot_exec(struct preloaded_file *fp) { vm_offset_t module_start, last_addr, metadata_size; vm_offset_t modulep, kernend, entry; struct file_metadata *md; Elf_Ehdr *ehdr; struct multiboot_info *mb_info = NULL; struct multiboot_mod_list *mb_mod = NULL; char *cmdline = NULL; size_t len; int error, mod_num; /* * Don't pass the memory size found by the bootloader, the memory * available to Dom0 will be lower than that. */ unsetenv("smbios.memory.enabled"); /* Allocate the multiboot struct and fill the basic details. */ mb_info = malloc(sizeof(struct multiboot_info)); if (mb_info == NULL) { error = ENOMEM; goto error; } bzero(mb_info, sizeof(struct multiboot_info)); mb_info->flags = MULTIBOOT_INFO_MEMORY|MULTIBOOT_INFO_BOOT_LOADER_NAME; mb_info->mem_lower = bios_basemem / 1024; mb_info->mem_upper = bios_extmem / 1024; mb_info->boot_loader_name = VTOP(mbl_name); /* Set the Xen command line. */ if (fp->f_args == NULL) { /* Add the Xen command line if it is set. */ cmdline = getenv("xen_cmdline"); if (cmdline != NULL) { fp->f_args = strdup(cmdline); if (fp->f_args == NULL) { error = ENOMEM; goto error; } } } if (fp->f_args != NULL) { len = strlen(fp->f_name) + 1 + strlen(fp->f_args) + 1; cmdline = malloc(len); if (cmdline == NULL) { error = ENOMEM; goto error; } snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args); mb_info->cmdline = VTOP(cmdline); mb_info->flags |= MULTIBOOT_INFO_CMDLINE; } /* Find the entry point of the Xen kernel and save it for later */ if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { printf("Unable to find %s entry point\n", fp->f_name); error = EINVAL; goto error; } ehdr = (Elf_Ehdr *)&(md->md_data); entry = ehdr->e_entry & 0xffffff; /* * Prepare the multiboot module list, Xen assumes the first * module is the Dom0 kernel, and the second one is the initramfs. * This is not optimal for FreeBSD, that doesn't have a initramfs * but instead loads modules dynamically and creates the metadata * info on-the-fly. * * As expected, the first multiboot module is going to be the * FreeBSD kernel loaded as a raw file. The second module is going * to contain the metadata info and the loaded modules. * * On native FreeBSD loads all the modules and then places the * metadata info at the end, but this is painful when running on Xen, * because it relocates the second multiboot module wherever it * likes. In order to workaround this limitation the metadata * information is placed at the start of the second module and * the original modulep value is saved together with the other * metadata, so we can relocate everything. * * Native layout: * fp->f_addr + fp->f_size * +---------+----------------+------------+ * | | | | * | Kernel | Modules | Metadata | * | | | | * +---------+----------------+------------+ * fp->f_addr modulep kernend * * Xen layout: * * Initial: * fp->f_addr + fp->f_size * +---------+----------+----------------+------------+ * | | | | | * | Kernel | Reserved | Modules | Metadata | * | | | | dry run | * +---------+----------+----------------+------------+ * fp->f_addr * * After metadata polacement (ie: final): * fp->f_addr + fp->f_size * +-----------+---------+----------+----------------+ * | | | | | * | Kernel | Free | Metadata | Modules | * | | | | | * +-----------+---------+----------+----------------+ * fp->f_addr modulep kernend * \__________/ \__________________________/ * Multiboot module 0 Multiboot module 1 */ fp = file_findfile(NULL, "elf kernel"); if (fp == NULL) { printf("No FreeBSD kernel provided, aborting\n"); error = EINVAL; goto error; } if (fp->f_metadata != NULL) { printf("FreeBSD kernel already contains metadata, aborting\n"); error = EINVAL; goto error; } mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES); if (mb_mod == NULL) { error = ENOMEM; goto error; } bzero(mb_mod, sizeof(struct multiboot_mod_list) * NUM_MODULES); /* * Calculate how much memory is needed for the metatdata. We did * an approximation of the maximum size when loading the kernel, * but now we know the exact size, so we can release some of this * preallocated memory if not needed. */ last_addr = roundup(max_addr(), PAGE_SIZE); mod_num = num_modules(fp); /* * Place the metadata after the last used address in order to * calculate it's size, this will not be used. */ error = bi_load64(fp->f_args, last_addr, &modulep, &kernend, 0); if (error != 0) { printf("bi_load64 failed: %d\n", error); goto error; } metadata_size = roundup(kernend - last_addr, PAGE_SIZE); /* Check that the size is not greater than what we have reserved */ if (metadata_size > METADATA_RESV_SIZE(mod_num)) { printf("Required memory for metadata is greater than reserved " "space, please increase METADATA_FIXED_SIZE and " "METADATA_MODULE_SIZE and rebuild the loader\n"); error = ENOMEM; goto error; } /* Clean the metadata added to the kernel in the bi_load64 dry run */ file_removemetadata(fp); /* * This is the position where the second multiboot module * will be placed. */ module_start = fp->f_addr + fp->f_size - metadata_size; error = bi_load64(fp->f_args, module_start, &modulep, &kernend, 0); if (error != 0) { printf("bi_load64 failed: %d\n", error); goto error; } mb_mod[0].mod_start = fp->f_addr; mb_mod[0].mod_end = fp->f_addr + fp->f_size; mb_mod[0].mod_end -= METADATA_RESV_SIZE(mod_num); mb_mod[1].mod_start = module_start; mb_mod[1].mod_end = last_addr; mb_info->mods_count = NUM_MODULES; mb_info->mods_addr = VTOP(mb_mod); mb_info->flags |= MULTIBOOT_INFO_MODS; dev_cleanup(); __exec((void *)VTOP(multiboot_tramp), (void *)entry, (void *)VTOP(mb_info)); panic("exec returned"); error: if (mb_mod) free(mb_mod); if (mb_info) free(mb_info); if (cmdline) free(cmdline); return (error); } static int -multiboot_obj_loadfile(char *filename, u_int64_t dest, +multiboot_obj_loadfile(char *filename, uint64_t dest, struct preloaded_file **result) { struct preloaded_file *mfp, *kfp, *rfp; struct kernel_module *kmp; int error, mod_num; /* See if there's a multiboot kernel loaded */ mfp = file_findfile(NULL, "elf multiboot kernel"); if (mfp == NULL) return (EFTYPE); /* * We have a multiboot kernel loaded, see if there's a FreeBSD * kernel loaded also. */ kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) { /* * No kernel loaded, this must be it. The kernel has to * be loaded as a raw file, it will be processed by * Xen and correctly loaded as an ELF file. */ rfp = file_loadraw(filename, "elf kernel", 0); if (rfp == NULL) { printf( "Unable to load %s as a multiboot payload kernel\n", filename); return (EINVAL); } /* Load kernel metadata... */ setenv("kernelname", filename, 1); error = elf64_load_modmetadata(rfp, rfp->f_addr + rfp->f_size); if (error) { printf("Unable to load kernel %s metadata error: %d\n", rfp->f_name, error); return (EINVAL); } /* * Save space at the end of the kernel in order to place * the metadata information. We do an approximation of the * max metadata size, this is not optimal but it's probably * the best we can do at this point. Once all modules are * loaded and the size of the metadata is known this * space will be recovered if not used. */ mod_num = num_modules(rfp); rfp->f_size = roundup(rfp->f_size, PAGE_SIZE); rfp->f_size += METADATA_RESV_SIZE(mod_num); *result = rfp; } else { /* The rest should be loaded as regular modules */ error = elf64_obj_loadfile(filename, dest, result); if (error != 0) { printf("Unable to load %s as an object file, error: %d", filename, error); return (error); } } return (0); } static int multiboot_obj_exec(struct preloaded_file *fp) { return (EFTYPE); } Index: head/stand/i386/libi386/pxe.c =================================================================== --- head/stand/i386/libi386/pxe.c (revision 330863) +++ head/stand/i386/libi386/pxe.c (revision 330864) @@ -1,540 +1,540 @@ /*- * Copyright (c) 2000 Alfred Perlstein * Copyright (c) 2000 Paul Saab * Copyright (c) 2000 John Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "btxv86.h" #include "pxe.h" /* * Allocate the PXE buffers statically instead of sticking grimy fingers into * BTX's private data area. The scratch buffer is used to send information to * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS. */ #define PXE_BUFFER_SIZE 0x2000 static char scratch_buffer[PXE_BUFFER_SIZE]; static char data_buffer[PXE_BUFFER_SIZE]; static pxenv_t *pxenv_p = NULL; /* PXENV+ */ static pxe_t *pxe_p = NULL; /* !PXE */ #ifdef PXE_DEBUG static int pxe_debug = 0; #endif void pxe_enable(void *pxeinfo); static void (*pxe_call)(int func); static void pxenv_call(int func); static void bangpxe_call(int func); static int pxe_init(void); static int pxe_print(int verbose); static void pxe_cleanup(void); static void pxe_perror(int error); static int pxe_netif_match(struct netif *nif, void *machdep_hint); static int pxe_netif_probe(struct netif *nif, void *machdep_hint); static void pxe_netif_init(struct iodesc *desc, void *machdep_hint); static ssize_t pxe_netif_get(struct iodesc *, void **, time_t); static ssize_t pxe_netif_put(struct iodesc *desc, void *pkt, size_t len); static void pxe_netif_end(struct netif *nif); extern struct netif_stats pxe_st[]; -extern u_int16_t __bangpxeseg; -extern u_int16_t __bangpxeoff; +extern uint16_t __bangpxeseg; +extern uint16_t __bangpxeoff; extern void __bangpxeentry(void); -extern u_int16_t __pxenvseg; -extern u_int16_t __pxenvoff; +extern uint16_t __pxenvseg; +extern uint16_t __pxenvoff; extern void __pxenventry(void); struct netif_dif pxe_ifs[] = { /* dif_unit dif_nsel dif_stats dif_private */ {0, 1, &pxe_st[0], 0} }; struct netif_stats pxe_st[nitems(pxe_ifs)]; struct netif_driver pxenetif = { .netif_bname = "pxenet", .netif_match = pxe_netif_match, .netif_probe = pxe_netif_probe, .netif_init = pxe_netif_init, .netif_get = pxe_netif_get, .netif_put = pxe_netif_put, .netif_end = pxe_netif_end, .netif_ifs = pxe_ifs, .netif_nifs = nitems(pxe_ifs) }; struct netif_driver *netif_drivers[] = { &pxenetif, NULL }; struct devsw pxedisk = { .dv_name = "net", .dv_type = DEVT_NET, .dv_init = pxe_init, .dv_strategy = NULL, /* Will be set in pxe_init */ .dv_open = NULL, /* Will be set in pxe_init */ .dv_close = NULL, /* Will be set in pxe_init */ .dv_ioctl = noioctl, .dv_print = pxe_print, .dv_cleanup = pxe_cleanup }; /* * This function is called by the loader to enable PXE support if we * are booted by PXE. The passed in pointer is a pointer to the PXENV+ * structure. */ void pxe_enable(void *pxeinfo) { pxenv_p = (pxenv_t *)pxeinfo; pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 + pxenv_p->PXEPtr.offset); pxe_call = NULL; } /* * return true if pxe structures are found/initialized, * also figures out our IP information via the pxe cached info struct */ static int pxe_init(void) { t_PXENV_GET_CACHED_INFO *gci_p; int counter; uint8_t checksum; uint8_t *checkptr; extern struct devsw netdev; if (pxenv_p == NULL) return (0); /* look for "PXENV+" */ if (bcmp((void *)pxenv_p->Signature, S_SIZE("PXENV+"))) { pxenv_p = NULL; return (0); } /* make sure the size is something we can handle */ if (pxenv_p->Length > sizeof(*pxenv_p)) { printf("PXENV+ structure too large, ignoring\n"); pxenv_p = NULL; return (0); } /* * do byte checksum: * add up each byte in the structure, the total should be 0 */ checksum = 0; checkptr = (uint8_t *) pxenv_p; for (counter = 0; counter < pxenv_p->Length; counter++) checksum += *checkptr++; if (checksum != 0) { printf("PXENV+ structure failed checksum, ignoring\n"); pxenv_p = NULL; return (0); } /* * PXENV+ passed, so use that if !PXE is not available or * the checksum fails. */ pxe_call = pxenv_call; if (pxenv_p->Version >= 0x0200) { for (;;) { if (bcmp((void *)pxe_p->Signature, S_SIZE("!PXE"))) { pxe_p = NULL; break; } checksum = 0; checkptr = (uint8_t *)pxe_p; for (counter = 0; counter < pxe_p->StructLength; counter++) checksum += *checkptr++; if (checksum != 0) { pxe_p = NULL; break; } pxe_call = bangpxe_call; break; } } pxedisk.dv_open = netdev.dv_open; pxedisk.dv_close = netdev.dv_close; pxedisk.dv_strategy = netdev.dv_strategy; printf("\nPXE version %d.%d, real mode entry point ", (uint8_t) (pxenv_p->Version >> 8), (uint8_t) (pxenv_p->Version & 0xFF)); if (pxe_call == bangpxe_call) printf("@%04x:%04x\n", pxe_p->EntryPointSP.segment, pxe_p->EntryPointSP.offset); else printf("@%04x:%04x\n", pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset); gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer; bzero(gci_p, sizeof(*gci_p)); gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; pxe_call(PXENV_GET_CACHED_INFO); if (gci_p->Status != 0) { pxe_perror(gci_p->Status); pxe_p = NULL; return (0); } free(bootp_response); if ((bootp_response = malloc(gci_p->BufferSize)) != NULL) { bootp_response_size = gci_p->BufferSize; bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset), bootp_response, bootp_response_size); } return (1); } static int pxe_print(int verbose) { if (pxe_call == NULL) return (0); printf("%s devices:", pxedisk.dv_name); if (pager_output("\n") != 0) return (1); printf(" %s0:", pxedisk.dv_name); if (verbose) { printf(" %s:%s", inet_ntoa(rootip), rootpath); } return (pager_output("\n")); } static void pxe_cleanup(void) { #ifdef PXE_DEBUG t_PXENV_UNLOAD_STACK *unload_stack_p = (t_PXENV_UNLOAD_STACK *)scratch_buffer; t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p = (t_PXENV_UNDI_SHUTDOWN *)scratch_buffer; #endif if (pxe_call == NULL) return; pxe_call(PXENV_UNDI_SHUTDOWN); #ifdef PXE_DEBUG if (pxe_debug && undi_shutdown_p->Status != 0) printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n", undi_shutdown_p->Status); #endif pxe_call(PXENV_UNLOAD_STACK); #ifdef PXE_DEBUG if (pxe_debug && unload_stack_p->Status != 0) printf("pxe_cleanup: UNLOAD_STACK failed %x\n", unload_stack_p->Status); #endif } void pxe_perror(int err) { return; } void pxenv_call(int func) { #ifdef PXE_DEBUG if (pxe_debug) printf("pxenv_call %x\n", func); #endif bzero(&v86, sizeof(v86)); bzero(data_buffer, sizeof(data_buffer)); __pxenvseg = pxenv_p->RMEntry.segment; __pxenvoff = pxenv_p->RMEntry.offset; v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; v86.es = VTOPSEG(scratch_buffer); v86.edi = VTOPOFF(scratch_buffer); v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry); v86.ebx = func; v86int(); v86.ctl = V86_FLAGS; } void bangpxe_call(int func) { #ifdef PXE_DEBUG if (pxe_debug) printf("bangpxe_call %x\n", func); #endif bzero(&v86, sizeof(v86)); bzero(data_buffer, sizeof(data_buffer)); __bangpxeseg = pxe_p->EntryPointSP.segment; __bangpxeoff = pxe_p->EntryPointSP.offset; v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; v86.edx = VTOPSEG(scratch_buffer); v86.eax = VTOPOFF(scratch_buffer); v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry); v86.ebx = func; v86int(); v86.ctl = V86_FLAGS; } static int pxe_netif_match(struct netif *nif, void *machdep_hint) { return (1); } static int pxe_netif_probe(struct netif *nif, void *machdep_hint) { if (pxe_call == NULL) return (-1); return (0); } static void pxe_netif_end(struct netif *nif) { t_PXENV_UNDI_CLOSE *undi_close_p; undi_close_p = (t_PXENV_UNDI_CLOSE *)scratch_buffer; bzero(undi_close_p, sizeof(*undi_close_p)); pxe_call(PXENV_UNDI_CLOSE); if (undi_close_p->Status != 0) printf("undi close failed: %x\n", undi_close_p->Status); } static void pxe_netif_init(struct iodesc *desc, void *machdep_hint) { t_PXENV_UNDI_GET_INFORMATION *undi_info_p; t_PXENV_UNDI_OPEN *undi_open_p; uint8_t *mac; int i, len; undi_info_p = (t_PXENV_UNDI_GET_INFORMATION *)scratch_buffer; bzero(undi_info_p, sizeof(*undi_info_p)); pxe_call(PXENV_UNDI_GET_INFORMATION); if (undi_info_p->Status != 0) { printf("undi get info failed: %x\n", undi_info_p->Status); return; } /* Make sure the CurrentNodeAddress is valid. */ for (i = 0; i < undi_info_p->HwAddrLen; ++i) { if (undi_info_p->CurrentNodeAddress[i] != 0) break; } if (i < undi_info_p->HwAddrLen) { for (i = 0; i < undi_info_p->HwAddrLen; ++i) { if (undi_info_p->CurrentNodeAddress[i] != 0xff) break; } } if (i < undi_info_p->HwAddrLen) mac = undi_info_p->CurrentNodeAddress; else mac = undi_info_p->PermNodeAddress; len = min(sizeof (desc->myea), undi_info_p->HwAddrLen); for (i = 0; i < len; ++i) desc->myea[i] = mac[i]; if (bootp_response != NULL) desc->xid = bootp_response->bp_xid; else desc->xid = 0; undi_open_p = (t_PXENV_UNDI_OPEN *)scratch_buffer; bzero(undi_open_p, sizeof(*undi_open_p)); undi_open_p->PktFilter = FLTR_DIRECTED | FLTR_BRDCST; pxe_call(PXENV_UNDI_OPEN); if (undi_open_p->Status != 0) printf("undi open failed: %x\n", undi_open_p->Status); } static int pxe_netif_receive(void **pkt) { t_PXENV_UNDI_ISR *isr = (t_PXENV_UNDI_ISR *)scratch_buffer; char *buf, *ptr, *frame; size_t size, rsize; bzero(isr, sizeof(*isr)); isr->FuncFlag = PXENV_UNDI_ISR_IN_START; pxe_call(PXENV_UNDI_ISR); if (isr->Status != 0) return (-1); bzero(isr, sizeof(*isr)); isr->FuncFlag = PXENV_UNDI_ISR_IN_PROCESS; pxe_call(PXENV_UNDI_ISR); if (isr->Status != 0) return (-1); while (isr->FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) { /* * Wait till transmit is done. */ bzero(isr, sizeof(*isr)); isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; pxe_call(PXENV_UNDI_ISR); if (isr->Status != 0 || isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE) return (-1); } while (isr->FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE) { if (isr->Status != 0 || isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE) { return (-1); } bzero(isr, sizeof(*isr)); isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; pxe_call(PXENV_UNDI_ISR); } size = isr->FrameLength; buf = malloc(size + ETHER_ALIGN); if (buf == NULL) return (-1); ptr = buf + ETHER_ALIGN; rsize = 0; while (rsize < size) { frame = (char *)((uintptr_t)isr->Frame.segment << 4); frame += isr->Frame.offset; bcopy(PTOV(frame), ptr, isr->BufferLength); ptr += isr->BufferLength; rsize += isr->BufferLength; bzero(isr, sizeof(*isr)); isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT; pxe_call(PXENV_UNDI_ISR); if (isr->Status != 0) { free(buf); return (-1); } /* Did we got another update? */ if (isr->FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) continue; break; } *pkt = buf; return (rsize); } static ssize_t pxe_netif_get(struct iodesc *desc, void **pkt, time_t timeout) { time_t t; void *ptr; int ret = -1; t = getsecs(); while ((getsecs() - t) < timeout) { ret = pxe_netif_receive(&ptr); if (ret != -1) { *pkt = ptr; break; } } return (ret); } static ssize_t pxe_netif_put(struct iodesc *desc, void *pkt, size_t len) { t_PXENV_UNDI_TRANSMIT *trans_p; t_PXENV_UNDI_TBD *tbd_p; char *data; trans_p = (t_PXENV_UNDI_TRANSMIT *)scratch_buffer; bzero(trans_p, sizeof(*trans_p)); tbd_p = (t_PXENV_UNDI_TBD *)(scratch_buffer + sizeof(*trans_p)); bzero(tbd_p, sizeof(*tbd_p)); data = scratch_buffer + sizeof(*trans_p) + sizeof(*tbd_p); trans_p->TBD.segment = VTOPSEG(tbd_p); trans_p->TBD.offset = VTOPOFF(tbd_p); tbd_p->ImmedLength = len; tbd_p->Xmit.segment = VTOPSEG(data); tbd_p->Xmit.offset = VTOPOFF(data); bcopy(pkt, data, len); pxe_call(PXENV_UNDI_TRANSMIT); if (trans_p->Status != 0) { return (-1); } return (len); } Index: head/stand/i386/loader/main.c =================================================================== --- head/stand/i386/loader/main.c (revision 330863) +++ head/stand/i386/loader/main.c (revision 330864) @@ -1,409 +1,409 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * MD bootstrap main() and assorted miscellaneous * commands. */ #include #include #include #include #include #include #include #include #include #include "bootstrap.h" #include "common/bootargs.h" #include "libi386/libi386.h" #include "libi386/smbios.h" #include "btxv86.h" #ifdef LOADER_ZFS_SUPPORT #include "../zfs/libzfs.h" #endif CTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE); CTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO); CTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS); CTASSERT(offsetof(struct bootinfo, bi_size) == BI_SIZE); /* Arguments passed in from the boot1/boot2 loader */ static struct bootargs *kargs; -static u_int32_t initial_howto; -static u_int32_t initial_bootdev; +static uint32_t initial_howto; +static uint32_t initial_bootdev; static struct bootinfo *initial_bootinfo; struct arch_switch archsw; /* MI/MD interface boundary */ static void extract_currdev(void); static int isa_inb(int port); static void isa_outb(int port, int value); void exit(int code); #ifdef LOADER_GELI_SUPPORT #include "geliboot.h" struct geli_boot_args *gargs; #endif #ifdef LOADER_ZFS_SUPPORT struct zfs_boot_args *zargs; static void i386_zfs_probe(void); #endif /* from vers.c */ extern char bootprog_info[]; /* XXX debugging */ extern char end[]; static void *heap_top; static void *heap_bottom; int main(void) { int i; /* Pick up arguments */ kargs = (void *)__args; initial_howto = kargs->howto; initial_bootdev = kargs->bootdev; initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL; /* Initialize the v86 register set to a known-good state. */ bzero(&v86, sizeof(v86)); v86.efl = PSL_RESERVED_DEFAULT | PSL_I; /* * Initialise the heap as early as possible. Once this is done, malloc() is usable. */ bios_getmem(); #if defined(LOADER_BZIP2_SUPPORT) || defined(LOADER_FIREWIRE_SUPPORT) || \ defined(LOADER_GPT_SUPPORT) || defined(LOADER_ZFS_SUPPORT) if (high_heap_size > 0) { heap_top = PTOV(high_heap_base + high_heap_size); heap_bottom = PTOV(high_heap_base); if (high_heap_base < memtop_copyin) memtop_copyin = high_heap_base; } else #endif { heap_top = (void *)PTOV(bios_basemem); heap_bottom = (void *)end; } setheap(heap_bottom, heap_top); /* * XXX Chicken-and-egg problem; we want to have console output early, but some * console attributes may depend on reading from eg. the boot device, which we * can't do yet. * * We can use printf() etc. once this is done. * If the previous boot stage has requested a serial console, prefer that. */ bi_setboothowto(initial_howto); if (initial_howto & RB_MULTIPLE) { if (initial_howto & RB_SERIAL) setenv("console", "comconsole vidconsole", 1); else setenv("console", "vidconsole comconsole", 1); } else if (initial_howto & RB_SERIAL) setenv("console", "comconsole", 1); else if (initial_howto & RB_MUTE) setenv("console", "nullconsole", 1); cons_probe(); /* * Initialise the block cache. Set the upper limit. */ bcache_init(32768, 512); /* * Special handling for PXE and CD booting. */ if (kargs->bootinfo == 0) { /* * We only want the PXE disk to try to init itself in the below * walk through devsw if we actually booted off of PXE. */ if (kargs->bootflags & KARGS_FLAGS_PXE) pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL); else if (kargs->bootflags & KARGS_FLAGS_CD) bc_add(initial_bootdev); } archsw.arch_autoload = i386_autoload; archsw.arch_getdev = i386_getdev; archsw.arch_copyin = i386_copyin; archsw.arch_copyout = i386_copyout; archsw.arch_readin = i386_readin; archsw.arch_isainb = isa_inb; archsw.arch_isaoutb = isa_outb; #ifdef LOADER_ZFS_SUPPORT archsw.arch_zfs_probe = i386_zfs_probe; #ifdef LOADER_GELI_SUPPORT if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) { zargs = (struct zfs_boot_args *)(kargs + 1); if (zargs != NULL && zargs->size >= offsetof(struct zfs_boot_args, gelipw)) { if (zargs->size >= offsetof(struct zfs_boot_args, keybuf_sentinel) && zargs->keybuf_sentinel == KEYBUF_SENTINEL) { geli_save_keybuf(zargs->keybuf); } if (zargs->gelipw[0] != '\0') { setenv("kern.geom.eli.passphrase", zargs->gelipw, 1); explicit_bzero(zargs->gelipw, sizeof(zargs->gelipw)); } } } #endif /* LOADER_GELI_SUPPORT */ #else /* !LOADER_ZFS_SUPPORT */ #ifdef LOADER_GELI_SUPPORT if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) { gargs = (struct geli_boot_args *)(kargs + 1); if (gargs != NULL && gargs->size >= offsetof(struct geli_boot_args, gelipw)) { if (gargs->keybuf_sentinel == KEYBUF_SENTINEL) { geli_save_keybuf(gargs->keybuf); } if (gargs->gelipw[0] != '\0') { setenv("kern.geom.eli.passphrase", gargs->gelipw, 1); explicit_bzero(gargs->gelipw, sizeof(gargs->gelipw)); } } } #endif /* LOADER_GELI_SUPPORT */ #endif /* LOADER_ZFS_SUPPORT */ /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) if (devsw[i]->dv_init != NULL) (devsw[i]->dv_init)(); printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024); if (initial_bootinfo != NULL) { initial_bootinfo->bi_basemem = bios_basemem / 1024; initial_bootinfo->bi_extmem = bios_extmem / 1024; } /* detect ACPI for future reference */ biosacpi_detect(); /* detect SMBIOS for future reference */ smbios_detect(NULL); /* detect PCI BIOS for future reference */ biospci_detect(); printf("\n%s", bootprog_info); extract_currdev(); /* set $currdev and $loaddev */ setenv("LINES", "24", 1); /* optional */ bios_getsmap(); interact(); /* if we ever get here, it is an error */ return (1); } /* * Set the 'current device' by (if possible) recovering the boot device as * supplied by the initial bootstrap. * * XXX should be extended for netbooting. */ static void extract_currdev(void) { struct i386_devdesc new_currdev; #ifdef LOADER_ZFS_SUPPORT char buf[20]; #endif int biosdev = -1; /* Assume we are booting from a BIOS disk by default */ new_currdev.dd.d_dev = &biosdisk; /* new-style boot loaders such as pxeldr and cdldr */ if (kargs->bootinfo == 0) { if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) { /* we are booting from a CD with cdboot */ new_currdev.dd.d_dev = &bioscd; new_currdev.dd.d_unit = bc_bios2unit(initial_bootdev); } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) { /* we are booting from pxeldr */ new_currdev.dd.d_dev = &pxedisk; new_currdev.dd.d_unit = 0; } else { /* we don't know what our boot device is */ new_currdev.d_kind.biosdisk.slice = -1; new_currdev.d_kind.biosdisk.partition = 0; biosdev = -1; } #ifdef LOADER_ZFS_SUPPORT } else if ((kargs->bootflags & KARGS_FLAGS_ZFS) != 0) { zargs = NULL; /* check for new style extended argument */ if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) zargs = (struct zfs_boot_args *)(kargs + 1); if (zargs != NULL && zargs->size >= offsetof(struct zfs_boot_args, primary_pool)) { /* sufficient data is provided */ new_currdev.d_kind.zfs.pool_guid = zargs->pool; new_currdev.d_kind.zfs.root_guid = zargs->root; if (zargs->size >= sizeof(*zargs) && zargs->primary_vdev != 0) { sprintf(buf, "%llu", zargs->primary_pool); setenv("vfs.zfs.boot.primary_pool", buf, 1); sprintf(buf, "%llu", zargs->primary_vdev); setenv("vfs.zfs.boot.primary_vdev", buf, 1); } } else { /* old style zfsboot block */ new_currdev.d_kind.zfs.pool_guid = kargs->zfspool; new_currdev.d_kind.zfs.root_guid = 0; } new_currdev.dd.d_dev = &zfs_dev; #endif } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) { /* The passed-in boot device is bad */ new_currdev.d_kind.biosdisk.slice = -1; new_currdev.d_kind.biosdisk.partition = 0; biosdev = -1; } else { new_currdev.d_kind.biosdisk.slice = B_SLICE(initial_bootdev) - 1; new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev); biosdev = initial_bootinfo->bi_bios_dev; /* * If we are booted by an old bootstrap, we have to guess at the BIOS * unit number. We will lose if there is more than one disk type * and we are not booting from the lowest-numbered disk type * (ie. SCSI when IDE also exists). */ if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) /* biosdev doesn't match major */ biosdev = 0x80 + B_UNIT(initial_bootdev); /* assume harddisk */ } /* * If we are booting off of a BIOS disk and we didn't succeed in determining * which one we booted off of, just use disk0: as a reasonable default. */ if ((new_currdev.dd.d_dev->dv_type == biosdisk.dv_type) && ((new_currdev.dd.d_unit = bd_bios2unit(biosdev)) == -1)) { printf("Can't work out which disk we are booting from.\n" "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev); new_currdev.dd.d_unit = 0; } #ifdef LOADER_ZFS_SUPPORT if (new_currdev.dd.d_dev->dv_type == DEVT_ZFS) init_zfs_bootenv(zfs_fmtdev(&new_currdev)); #endif env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev), i386_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset, env_nounset); } COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int command_reboot(int argc, char *argv[]) { int i; for (i = 0; devsw[i] != NULL; ++i) if (devsw[i]->dv_cleanup != NULL) (devsw[i]->dv_cleanup)(); printf("Rebooting...\n"); delay(1000000); __exit(0); } /* provide this for panic, as it's not in the startup code */ void exit(int code) { __exit(code); } COMMAND_SET(heap, "heap", "show heap usage", command_heap); static int command_heap(int argc, char *argv[]) { mallocstats(); printf("heap base at %p, top at %p, upper limit at %p\n", heap_bottom, sbrk(0), heap_top); return(CMD_OK); } /* ISA bus access functions for PnP. */ static int isa_inb(int port) { return (inb(port)); } static void isa_outb(int port, int value) { outb(port, value); } #ifdef LOADER_ZFS_SUPPORT static void i386_zfs_probe(void) { char devname[32]; int unit; /* * Open all the disks we can find and see if we can reconstruct * ZFS pools from them. */ for (unit = 0; unit < MAXBDDEV; unit++) { if (bd_unit2bios(unit) == -1) break; sprintf(devname, "disk%d:", unit); zfs_probe_dev(devname, NULL); } } #endif Index: head/stand/libsa/arp.c =================================================================== --- head/stand/libsa/arp.c (revision 330863) +++ head/stand/libsa/arp.c (revision 330864) @@ -1,305 +1,305 @@ /* $NetBSD: arp.c,v 1.18 1997/07/07 15:52:49 drochner Exp $ */ /* * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp (LBL) */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "stand.h" #include "net.h" /* Cache stuff */ #define ARP_NUM 8 /* need at most 3 arp entries */ struct arp_list { struct in_addr addr; u_char ea[6]; } arp_list[ARP_NUM] = { /* XXX - net order `INADDR_BROADCAST' must be a constant */ { {0xffffffff}, BA } }; int arp_num = 1; /* Local forwards */ static ssize_t arpsend(struct iodesc *, void *, size_t); static ssize_t arprecv(struct iodesc *, void **, void **, time_t, void *); /* Broadcast an ARP packet, asking who has addr on interface d */ u_char * arpwhohas(struct iodesc *d, struct in_addr addr) { int i; struct ether_arp *ah; struct arp_list *al; void *pkt; struct { struct ether_header eh; struct { struct ether_arp arp; u_char pad[18]; /* 60 - sizeof(...) */ } data; } wbuf; /* Try for cached answer first */ for (i = 0, al = arp_list; i < arp_num; ++i, ++al) if (addr.s_addr == al->addr.s_addr) return (al->ea); /* Don't overflow cache */ if (arp_num > ARP_NUM - 1) { arp_num = 1; /* recycle */ printf("arpwhohas: overflowed arp_list!\n"); } #ifdef ARP_DEBUG if (debug) printf("arpwhohas: send request for %s\n", inet_ntoa(addr)); #endif bzero((char*)&wbuf.data, sizeof(wbuf.data)); ah = &wbuf.data.arp; ah->arp_hrd = htons(ARPHRD_ETHER); ah->arp_pro = htons(ETHERTYPE_IP); ah->arp_hln = sizeof(ah->arp_sha); /* hardware address length */ ah->arp_pln = sizeof(ah->arp_spa); /* protocol address length */ ah->arp_op = htons(ARPOP_REQUEST); MACPY(d->myea, ah->arp_sha); bcopy(&d->myip, ah->arp_spa, sizeof(ah->arp_spa)); /* Leave zeros in arp_tha */ bcopy(&addr, ah->arp_tpa, sizeof(ah->arp_tpa)); /* Store ip address in cache (incomplete entry). */ al->addr = addr; pkt = NULL; ah = NULL; i = sendrecv(d, arpsend, &wbuf.data, sizeof(wbuf.data), arprecv, &pkt, (void **)&ah, NULL); if (i == -1) { panic("arp: no response for %s\n", inet_ntoa(addr)); } /* Store ethernet address in cache */ #ifdef ARP_DEBUG if (debug) { struct ether_header *eh; eh = (struct ether_header *)((uintptr_t)pkt + ETHER_ALIGN); printf("arp: response from %s\n", ether_sprintf(eh->ether_shost)); printf("arp: cacheing %s --> %s\n", inet_ntoa(addr), ether_sprintf(ah->arp_sha)); } #endif MACPY(ah->arp_sha, al->ea); ++arp_num; free(pkt); return (al->ea); } static ssize_t arpsend(struct iodesc *d, void *pkt, size_t len) { #ifdef ARP_DEBUG if (debug) printf("arpsend: called\n"); #endif return (sendether(d, pkt, len, bcea, ETHERTYPE_ARP)); } /* * Returns 0 if this is the packet we're waiting for * else -1 (and errno == 0) */ static ssize_t arprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft, void *extra) { ssize_t n; struct ether_arp *ah; - u_int16_t etype; /* host order */ + uint16_t etype; /* host order */ void *ptr; #ifdef ARP_DEBUG if (debug) printf("arprecv: "); #endif ptr = NULL; n = readether(d, &ptr, (void **)&ah, tleft, &etype); errno = 0; /* XXX */ if (n == -1 || n < sizeof(struct ether_arp)) { #ifdef ARP_DEBUG if (debug) printf("bad len=%d\n", n); #endif free(ptr); return (-1); } if (etype != ETHERTYPE_ARP) { #ifdef ARP_DEBUG if (debug) printf("not arp type=%d\n", etype); #endif free(ptr); return (-1); } /* Ethernet address now checked in readether() */ if (ah->arp_hrd != htons(ARPHRD_ETHER) || ah->arp_pro != htons(ETHERTYPE_IP) || ah->arp_hln != sizeof(ah->arp_sha) || ah->arp_pln != sizeof(ah->arp_spa) ) { #ifdef ARP_DEBUG if (debug) printf("bad hrd/pro/hln/pln\n"); #endif free(ptr); return (-1); } if (ah->arp_op == htons(ARPOP_REQUEST)) { #ifdef ARP_DEBUG if (debug) printf("is request\n"); #endif arp_reply(d, ah); free(ptr); return (-1); } if (ah->arp_op != htons(ARPOP_REPLY)) { #ifdef ARP_DEBUG if (debug) printf("not ARP reply\n"); #endif free(ptr); return (-1); } /* Is the reply from the source we want? */ if (bcmp(&arp_list[arp_num].addr, ah->arp_spa, sizeof(ah->arp_spa))) { #ifdef ARP_DEBUG if (debug) printf("unwanted address\n"); #endif free(ptr); return (-1); } /* We don't care who the reply was sent to. */ /* We have our answer. */ #ifdef ARP_DEBUG if (debug) printf("got it\n"); #endif *pkt = ptr; *payload = ah; return (n); } /* * Convert an ARP request into a reply and send it. * Notes: Re-uses buffer. Pad to length = 46. */ void arp_reply(struct iodesc *d, void *pkt) { struct ether_arp *arp = pkt; if (arp->arp_hrd != htons(ARPHRD_ETHER) || arp->arp_pro != htons(ETHERTYPE_IP) || arp->arp_hln != sizeof(arp->arp_sha) || arp->arp_pln != sizeof(arp->arp_spa) ) { #ifdef ARP_DEBUG if (debug) printf("arp_reply: bad hrd/pro/hln/pln\n"); #endif return; } if (arp->arp_op != htons(ARPOP_REQUEST)) { #ifdef ARP_DEBUG if (debug) printf("arp_reply: not request!\n"); #endif return; } /* If we are not the target, ignore the request. */ if (bcmp(arp->arp_tpa, &d->myip, sizeof(arp->arp_tpa))) return; #ifdef ARP_DEBUG if (debug) { printf("arp_reply: to %s\n", ether_sprintf(arp->arp_sha)); } #endif arp->arp_op = htons(ARPOP_REPLY); /* source becomes target */ bcopy(arp->arp_sha, arp->arp_tha, sizeof(arp->arp_tha)); bcopy(arp->arp_spa, arp->arp_tpa, sizeof(arp->arp_tpa)); /* here becomes source */ bcopy(d->myea, arp->arp_sha, sizeof(arp->arp_sha)); bcopy(&d->myip, arp->arp_spa, sizeof(arp->arp_spa)); /* * No need to get fancy here. If the send fails, the * requestor will just ask again. */ (void) sendether(d, pkt, sizeof(*arp) + 18, arp->arp_tha, ETHERTYPE_ARP); } Index: head/stand/libsa/bootp.c =================================================================== --- head/stand/libsa/bootp.c (revision 330863) +++ head/stand/libsa/bootp.c (revision 330864) @@ -1,781 +1,781 @@ /* $NetBSD: bootp.c,v 1.14 1998/02/16 11:10:54 drochner Exp $ */ /* * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) Header: bootp.c,v 1.4 93/09/11 03:13:51 leres Exp (LBL) */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #define BOOTP_DEBUGxx #define SUPPORT_DHCP #define DHCP_ENV_NOVENDOR 1 /* do not parse vendor options */ #define DHCP_ENV_PXE 10 /* assume pxe vendor options */ #define DHCP_ENV_FREEBSD 11 /* assume freebsd vendor options */ /* set DHCP_ENV to one of the values above to export dhcp options to kenv */ #define DHCP_ENV DHCP_ENV_NO_VENDOR #include "stand.h" #include "net.h" #include "netif.h" #include "bootp.h" struct in_addr servip; static time_t bot; static char vm_rfc1048[4] = VM_RFC1048; #ifdef BOOTP_VEND_CMU static char vm_cmu[4] = VM_CMU; #endif /* Local forwards */ static ssize_t bootpsend(struct iodesc *, void *, size_t); static ssize_t bootprecv(struct iodesc *, void **, void **, time_t, void *); static int vend_rfc1048(u_char *, u_int); #ifdef BOOTP_VEND_CMU static void vend_cmu(u_char *); #endif #ifdef DHCP_ENV /* export the dhcp response to kenv */ struct dhcp_opt; static void setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts); #else #define setenv_(a, b, c) #endif #ifdef SUPPORT_DHCP static char expected_dhcpmsgtype = -1, dhcp_ok; struct in_addr dhcp_serverip; #endif struct bootp *bootp_response; size_t bootp_response_size; static void bootp_fill_request(unsigned char *bp_vend) { /* * We are booting from PXE, we want to send the string * 'PXEClient' to the DHCP server so you have the option of * only responding to PXE aware dhcp requests. */ bp_vend[0] = TAG_CLASSID; bp_vend[1] = 9; bcopy("PXEClient", &bp_vend[2], 9); bp_vend[11] = TAG_USER_CLASS; /* len of each user class + number of user class */ bp_vend[12] = 8; /* len of the first user class */ bp_vend[13] = 7; bcopy("FreeBSD", &bp_vend[14], 7); bp_vend[21] = TAG_PARAM_REQ; bp_vend[22] = 7; bp_vend[23] = TAG_ROOTPATH; bp_vend[24] = TAG_HOSTNAME; bp_vend[25] = TAG_SWAPSERVER; bp_vend[26] = TAG_GATEWAY; bp_vend[27] = TAG_SUBNET_MASK; bp_vend[28] = TAG_INTF_MTU; bp_vend[29] = TAG_SERVERID; bp_vend[30] = TAG_END; } /* Fetch required bootp infomation */ void bootp(int sock) { void *pkt; struct iodesc *d; struct bootp *bp; struct { u_char header[HEADER_SIZE]; struct bootp wbootp; } wbuf; struct bootp *rbootp; #ifdef BOOTP_DEBUG if (debug) printf("bootp: socket=%d\n", sock); #endif if (!bot) bot = getsecs(); if (!(d = socktodesc(sock))) { printf("bootp: bad socket. %d\n", sock); return; } #ifdef BOOTP_DEBUG if (debug) printf("bootp: d=%lx\n", (long)d); #endif bp = &wbuf.wbootp; bzero(bp, sizeof(*bp)); bp->bp_op = BOOTREQUEST; bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */ bp->bp_hlen = 6; bp->bp_xid = htonl(d->xid); MACPY(d->myea, bp->bp_chaddr); strncpy(bp->bp_file, bootfile, sizeof(bp->bp_file)); bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)); #ifdef SUPPORT_DHCP bp->bp_vend[4] = TAG_DHCP_MSGTYPE; bp->bp_vend[5] = 1; bp->bp_vend[6] = DHCPDISCOVER; bootp_fill_request(&bp->bp_vend[7]); #else bp->bp_vend[4] = TAG_END; #endif d->myip.s_addr = INADDR_ANY; d->myport = htons(IPPORT_BOOTPC); d->destip.s_addr = INADDR_BROADCAST; d->destport = htons(IPPORT_BOOTPS); #ifdef SUPPORT_DHCP expected_dhcpmsgtype = DHCPOFFER; dhcp_ok = 0; #endif if(sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &pkt, (void **)&rbootp, NULL) == -1) { printf("bootp: no reply\n"); return; } #ifdef SUPPORT_DHCP if(dhcp_ok) { - u_int32_t leasetime; + uint32_t leasetime; bp->bp_vend[6] = DHCPREQUEST; bp->bp_vend[7] = TAG_REQ_ADDR; bp->bp_vend[8] = 4; bcopy(&rbootp->bp_yiaddr, &bp->bp_vend[9], 4); bp->bp_vend[13] = TAG_SERVERID; bp->bp_vend[14] = 4; bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4); bp->bp_vend[19] = TAG_LEASETIME; bp->bp_vend[20] = 4; leasetime = htonl(300); bcopy(&leasetime, &bp->bp_vend[21], 4); bootp_fill_request(&bp->bp_vend[25]); expected_dhcpmsgtype = DHCPACK; free(pkt); if(sendrecv(d, bootpsend, bp, sizeof(*bp), bootprecv, &pkt, (void **)&rbootp, NULL) == -1) { printf("DHCPREQUEST failed\n"); return; } } #endif myip = d->myip = rbootp->bp_yiaddr; servip = rbootp->bp_siaddr; if (rootip.s_addr == INADDR_ANY) rootip = servip; bcopy(rbootp->bp_file, bootfile, sizeof(bootfile)); bootfile[sizeof(bootfile) - 1] = '\0'; if (!netmask) { if (IN_CLASSA(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSA_NET); else if (IN_CLASSB(ntohl(myip.s_addr))) netmask = htonl(IN_CLASSB_NET); else netmask = htonl(IN_CLASSC_NET); #ifdef BOOTP_DEBUG if (debug) printf("'native netmask' is %s\n", intoa(netmask)); #endif } #ifdef BOOTP_DEBUG if (debug) printf("mask: %s\n", intoa(netmask)); #endif /* We need a gateway if root is on a different net */ if (!SAMENET(myip, rootip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("need gateway for root ip\n"); #endif } /* Toss gateway if on a different net */ if (!SAMENET(myip, gateip, netmask)) { #ifdef BOOTP_DEBUG if (debug) printf("gateway ip (%s) bad\n", inet_ntoa(gateip)); #endif gateip.s_addr = 0; } /* Bump xid so next request will be unique. */ ++d->xid; free(pkt); } /* Transmit a bootp request */ static ssize_t bootpsend(struct iodesc *d, void *pkt, size_t len) { struct bootp *bp; #ifdef BOOTP_DEBUG if (debug) printf("bootpsend: d=%lx called.\n", (long)d); #endif bp = pkt; bp->bp_secs = htons((u_short)(getsecs() - bot)); #ifdef BOOTP_DEBUG if (debug) printf("bootpsend: calling sendudp\n"); #endif return (sendudp(d, pkt, len)); } static ssize_t bootprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft, void *extra) { ssize_t n; struct bootp *bp; void *ptr; #ifdef BOOTP_DEBUG if (debug) printf("bootp_recvoffer: called\n"); #endif ptr = NULL; n = readudp(d, &ptr, (void **)&bp, tleft); if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE) goto bad; #ifdef BOOTP_DEBUG if (debug) printf("bootprecv: checked. bp = %p, n = %zd\n", bp, n); #endif if (bp->bp_xid != htonl(d->xid)) { #ifdef BOOTP_DEBUG if (debug) { printf("bootprecv: expected xid 0x%lx, got 0x%x\n", d->xid, ntohl(bp->bp_xid)); } #endif goto bad; } #ifdef BOOTP_DEBUG if (debug) printf("bootprecv: got one!\n"); #endif /* Suck out vendor info */ if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) { int vsize = n - offsetof(struct bootp, bp_vend); if (vend_rfc1048(bp->bp_vend, vsize) != 0) goto bad; /* Save copy of bootp reply or DHCP ACK message */ if (bp->bp_op == BOOTREPLY && ((dhcp_ok == 1 && expected_dhcpmsgtype == DHCPACK) || dhcp_ok == 0)) { free(bootp_response); bootp_response = malloc(n); if (bootp_response != NULL) { bootp_response_size = n; bcopy(bp, bootp_response, bootp_response_size); } } } #ifdef BOOTP_VEND_CMU else if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0) vend_cmu(bp->bp_vend); #endif else printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend); *pkt = ptr; *payload = bp; return (n); bad: free(ptr); errno = 0; return (-1); } static int vend_rfc1048(u_char *cp, u_int len) { u_char *ep; int size; u_char tag; const char *val; #ifdef BOOTP_DEBUG if (debug) printf("vend_rfc1048 bootp info. len=%d\n", len); #endif ep = cp + len; /* Step over magic cookie */ cp += sizeof(int); setenv_(cp, ep, NULL); while (cp < ep) { tag = *cp++; size = *cp++; if (tag == TAG_END) break; if (tag == TAG_SUBNET_MASK) { bcopy(cp, &netmask, sizeof(netmask)); } if (tag == TAG_GATEWAY) { bcopy(cp, &gateip.s_addr, sizeof(gateip.s_addr)); } if (tag == TAG_SWAPSERVER) { /* let it override bp_siaddr */ bcopy(cp, &rootip.s_addr, sizeof(rootip.s_addr)); } if (tag == TAG_ROOTPATH) { if ((val = getenv("dhcp.root-path")) == NULL) val = (const char *)cp; strlcpy(rootpath, val, sizeof(rootpath)); } if (tag == TAG_HOSTNAME) { if ((val = getenv("dhcp.host-name")) == NULL) val = (const char *)cp; strlcpy(hostname, val, sizeof(hostname)); } if (tag == TAG_INTF_MTU) { intf_mtu = 0; if ((val = getenv("dhcp.interface-mtu")) != NULL) { unsigned long tmp; char *end; errno = 0; /* * Do not allow MTU to exceed max IPv4 packet * size, max value of 16-bit word. */ tmp = strtoul(val, &end, 0); if (errno != 0 || *val == '\0' || *end != '\0' || tmp > USHRT_MAX) { printf("%s: bad value: \"%s\", " "ignoring\n", "dhcp.interface-mtu", val); } else { intf_mtu = (u_int)tmp; } } if (intf_mtu <= 0) intf_mtu = be16dec(cp); } #ifdef SUPPORT_DHCP if (tag == TAG_DHCP_MSGTYPE) { if(*cp != expected_dhcpmsgtype) return(-1); dhcp_ok = 1; } if (tag == TAG_SERVERID) { bcopy(cp, &dhcp_serverip.s_addr, sizeof(dhcp_serverip.s_addr)); } #endif cp += size; } return(0); } #ifdef BOOTP_VEND_CMU static void vend_cmu(u_char *cp) { struct cmu_vend *vp; #ifdef BOOTP_DEBUG if (debug) printf("vend_cmu bootp info.\n"); #endif vp = (struct cmu_vend *)cp; if (vp->v_smask.s_addr != 0) { netmask = vp->v_smask.s_addr; } if (vp->v_dgate.s_addr != 0) { gateip = vp->v_dgate; } } #endif #ifdef DHCP_ENV /* * Parse DHCP options and store them into kenv variables. * Original code from Danny Braniss, modifications by Luigi Rizzo. * * The parser is driven by tables which specify the type and name of * each dhcp option and how it appears in kenv. * The first entry in the list contains the prefix used to set the kenv * name (including the . if needed), the last entry must have a 0 tag. * Entries do not need to be sorted though it helps for readability. * * Certain vendor-specific tables can be enabled according to DHCP_ENV. * Set it to 0 if you don't want any. */ enum opt_fmt { __NONE = 0, __8 = 1, __16 = 2, __32 = 4, /* Unsigned fields, value=size */ __IP, /* IPv4 address */ __TXT, /* C string */ __BYTES, /* byte sequence, printed %02x */ __INDIR, /* name=value */ __ILIST, /* name=value;name=value ... */ __VE, /* vendor specific, recurse */ }; struct dhcp_opt { uint8_t tag; uint8_t fmt; const char *desc; }; static struct dhcp_opt vndr_opt[] = { /* Vendor Specific Options */ #if DHCP_ENV == DHCP_ENV_FREEBSD /* FreeBSD table in the original code */ {0, 0, "FreeBSD"}, /* prefix */ {1, __TXT, "kernel"}, {2, __TXT, "kernelname"}, {3, __TXT, "kernel_options"}, {4, __IP, "usr-ip"}, {5, __TXT, "conf-path"}, {6, __TXT, "rc.conf0"}, {7, __TXT, "rc.conf1"}, {8, __TXT, "rc.conf2"}, {9, __TXT, "rc.conf3"}, {10, __TXT, "rc.conf4"}, {11, __TXT, "rc.conf5"}, {12, __TXT, "rc.conf6"}, {13, __TXT, "rc.conf7"}, {14, __TXT, "rc.conf8"}, {15, __TXT, "rc.conf9"}, {20, __TXT, "boot.nfsroot.options"}, {245, __INDIR, ""}, {246, __INDIR, ""}, {247, __INDIR, ""}, {248, __INDIR, ""}, {249, __INDIR, ""}, {250, __INDIR, ""}, {251, __INDIR, ""}, {252, __INDIR, ""}, {253, __INDIR, ""}, {254, __INDIR, ""}, #elif DHCP_ENV == DHCP_ENV_PXE /* some pxe options, RFC4578 */ {0, 0, "pxe"}, /* prefix */ {93, __16, "system-architecture"}, {94, __BYTES, "network-interface"}, {97, __BYTES, "machine-identifier"}, #else /* default (empty) table */ {0, 0, "dhcp.vendor."}, /* prefix */ #endif {0, __TXT, "%soption-%d"} }; static struct dhcp_opt dhcp_opt[] = { /* DHCP Option names, formats and codes, from RFC2132. */ {0, 0, "dhcp."}, // prefix {1, __IP, "subnet-mask"}, {2, __32, "time-offset"}, /* this is signed */ {3, __IP, "routers"}, {4, __IP, "time-servers"}, {5, __IP, "ien116-name-servers"}, {6, __IP, "domain-name-servers"}, {7, __IP, "log-servers"}, {8, __IP, "cookie-servers"}, {9, __IP, "lpr-servers"}, {10, __IP, "impress-servers"}, {11, __IP, "resource-location-servers"}, {12, __TXT, "host-name"}, {13, __16, "boot-size"}, {14, __TXT, "merit-dump"}, {15, __TXT, "domain-name"}, {16, __IP, "swap-server"}, {17, __TXT, "root-path"}, {18, __TXT, "extensions-path"}, {19, __8, "ip-forwarding"}, {20, __8, "non-local-source-routing"}, {21, __IP, "policy-filter"}, {22, __16, "max-dgram-reassembly"}, {23, __8, "default-ip-ttl"}, {24, __32, "path-mtu-aging-timeout"}, {25, __16, "path-mtu-plateau-table"}, {26, __16, "interface-mtu"}, {27, __8, "all-subnets-local"}, {28, __IP, "broadcast-address"}, {29, __8, "perform-mask-discovery"}, {30, __8, "mask-supplier"}, {31, __8, "perform-router-discovery"}, {32, __IP, "router-solicitation-address"}, {33, __IP, "static-routes"}, {34, __8, "trailer-encapsulation"}, {35, __32, "arp-cache-timeout"}, {36, __8, "ieee802-3-encapsulation"}, {37, __8, "default-tcp-ttl"}, {38, __32, "tcp-keepalive-interval"}, {39, __8, "tcp-keepalive-garbage"}, {40, __TXT, "nis-domain"}, {41, __IP, "nis-servers"}, {42, __IP, "ntp-servers"}, {43, __VE, "vendor-encapsulated-options"}, {44, __IP, "netbios-name-servers"}, {45, __IP, "netbios-dd-server"}, {46, __8, "netbios-node-type"}, {47, __TXT, "netbios-scope"}, {48, __IP, "x-font-servers"}, {49, __IP, "x-display-managers"}, {50, __IP, "dhcp-requested-address"}, {51, __32, "dhcp-lease-time"}, {52, __8, "dhcp-option-overload"}, {53, __8, "dhcp-message-type"}, {54, __IP, "dhcp-server-identifier"}, {55, __8, "dhcp-parameter-request-list"}, {56, __TXT, "dhcp-message"}, {57, __16, "dhcp-max-message-size"}, {58, __32, "dhcp-renewal-time"}, {59, __32, "dhcp-rebinding-time"}, {60, __TXT, "vendor-class-identifier"}, {61, __TXT, "dhcp-client-identifier"}, {64, __TXT, "nisplus-domain"}, {65, __IP, "nisplus-servers"}, {66, __TXT, "tftp-server-name"}, {67, __TXT, "bootfile-name"}, {68, __IP, "mobile-ip-home-agent"}, {69, __IP, "smtp-server"}, {70, __IP, "pop-server"}, {71, __IP, "nntp-server"}, {72, __IP, "www-server"}, {73, __IP, "finger-server"}, {74, __IP, "irc-server"}, {75, __IP, "streettalk-server"}, {76, __IP, "streettalk-directory-assistance-server"}, {77, __TXT, "user-class"}, {85, __IP, "nds-servers"}, {86, __TXT, "nds-tree-name"}, {87, __TXT, "nds-context"}, {210, __TXT, "authenticate"}, /* use the following entries for arbitrary variables */ {246, __ILIST, ""}, {247, __ILIST, ""}, {248, __ILIST, ""}, {249, __ILIST, ""}, {250, __INDIR, ""}, {251, __INDIR, ""}, {252, __INDIR, ""}, {253, __INDIR, ""}, {254, __INDIR, ""}, {0, __TXT, "%soption-%d"} }; /* * parse a dhcp response, set environment variables translating options * names and values according to the tables above. Also set dhcp.tags * to the list of selected tags. */ static void setenv_(u_char *cp, u_char *ep, struct dhcp_opt *opts) { u_char *ncp; u_char tag; char tags[512], *tp; /* the list of tags */ #define FLD_SEP ',' /* separator in list of elements */ ncp = cp; tp = tags; if (opts == NULL) opts = dhcp_opt; while (ncp < ep) { unsigned int size; /* option size */ char *vp, *endv, buf[256]; /* the value buffer */ struct dhcp_opt *op; tag = *ncp++; /* extract tag and size */ size = *ncp++; cp = ncp; /* current payload */ ncp += size; /* point to the next option */ if (tag == TAG_END) break; if (tag == 0) continue; for (op = opts+1; op->tag && op->tag != tag; op++) ; /* if not found we end up on the default entry */ /* * Copy data into the buffer. libstand does not have snprintf so we * need to be careful with sprintf(). With strings, the source is * always <256 char so shorter than the buffer so we are safe; with * other arguments, the longest string is inet_ntoa which is 16 bytes * so we make sure to have always enough room in the string before * trying an sprint. */ vp = buf; *vp = '\0'; endv = buf + sizeof(buf) - 1 - 16; /* last valid write position */ switch(op->fmt) { case __NONE: break; /* should not happen */ case __VE: /* recurse, vendor specific */ setenv_(cp, cp+size, vndr_opt); break; case __IP: /* ip address */ for (; size > 0 && vp < endv; size -= 4, cp += 4) { struct in_addr in_ip; /* ip addresses */ if (vp != buf) *vp++ = FLD_SEP; bcopy(cp, &in_ip.s_addr, sizeof(in_ip.s_addr)); sprintf(vp, "%s", inet_ntoa(in_ip)); vp += strlen(vp); } break; case __BYTES: /* opaque byte string */ for (; size > 0 && vp < endv; size -= 1, cp += 1) { sprintf(vp, "%02x", *cp); vp += strlen(vp); } break; case __TXT: bcopy(cp, buf, size); /* cannot overflow */ buf[size] = 0; break; case __32: case __16: case __8: /* op->fmt is also the length of each field */ for (; size > 0 && vp < endv; size -= op->fmt, cp += op->fmt) { uint32_t v; if (op->fmt == __32) v = (cp[0]<<24) + (cp[1]<<16) + (cp[2]<<8) + cp[3]; else if (op->fmt == __16) v = (cp[0]<<8) + cp[1]; else v = cp[0]; if (vp != buf) *vp++ = FLD_SEP; sprintf(vp, "%u", v); vp += strlen(vp); } break; case __INDIR: /* name=value */ case __ILIST: /* name=value;name=value... */ bcopy(cp, buf, size); /* cannot overflow */ buf[size] = '\0'; for (endv = buf; endv; endv = vp) { u_char *s = NULL; /* semicolon ? */ /* skip leading whitespace */ while (*endv && strchr(" \t\n\r", *endv)) endv++; vp = strchr(endv, '='); /* find name=value separator */ if (!vp) break; *vp++ = 0; if (op->fmt == __ILIST && (s = strchr(vp, ';'))) *s++ = '\0'; setenv(endv, vp, 1); vp = s; /* prepare for next round */ } buf[0] = '\0'; /* option already done */ } if (tp - tags < sizeof(tags) - 5) { /* add tag to the list */ if (tp != tags) *tp++ = FLD_SEP; sprintf(tp, "%d", tag); tp += strlen(tp); } if (buf[0]) { char env[128]; /* the string name */ if (op->tag == 0) sprintf(env, op->desc, opts[0].desc, tag); else sprintf(env, "%s%s", opts[0].desc, op->desc); /* * Do not replace existing values in the environment, so that * locally-obtained values can override server-provided values. */ setenv(env, buf, 0); } } if (tp != tags) { char env[128]; /* the string name */ sprintf(env, "%stags", opts[0].desc); setenv(env, tags, 1); } } #endif /* additional dhcp */ Index: head/stand/libsa/bootparam.c =================================================================== --- head/stand/libsa/bootparam.c (revision 330863) +++ head/stand/libsa/bootparam.c (revision 330864) @@ -1,435 +1,435 @@ /* $NetBSD: bootparam.c,v 1.11 1997/06/26 19:11:32 drochner Exp $ */ /* * Copyright (c) 1995 Gordon W. Ross * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * 4. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Gordon W. Ross * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * RPC/bootparams */ #include #include #include #include #include #include #include "rpcv2.h" #include "stand.h" #include "net.h" #include "netif.h" #include "rpc.h" #include "bootparam.h" #ifdef DEBUG_RPC #define RPC_PRINTF(a) printf a #else #define RPC_PRINTF(a) #endif struct in_addr bp_server_addr; /* net order */ n_short bp_server_port; /* net order */ /* * RPC definitions for bootparamd */ #define BOOTPARAM_PROG 100026 #define BOOTPARAM_VERS 1 #define BOOTPARAM_WHOAMI 1 #define BOOTPARAM_GETFILE 2 /* * Inet address in RPC messages * (Note, really four ints, NOT chars. Blech.) */ struct xdr_inaddr { - u_int32_t atype; + uint32_t atype; int32_t addr[4]; }; int xdr_inaddr_encode(char **p, struct in_addr ia); int xdr_inaddr_decode(char **p, struct in_addr *ia); int xdr_string_encode(char **p, char *str, int len); int xdr_string_decode(char **p, char *str, int *len_p); /* * RPC: bootparam/whoami * Given client IP address, get: * client name (hostname) * domain name (domainname) * gateway address * * The hostname and domainname are set here for convenience. * * Note - bpsin is initialized to the broadcast address, * and will be replaced with the bootparam server address * after this call is complete. Have to use PMAP_PROC_CALL * to make sure we get responses only from a servers that * know about us (don't want to broadcast a getport call). */ int bp_whoami(int sockfd) { /* RPC structures for PMAPPROC_CALLIT */ struct args { - u_int32_t prog; - u_int32_t vers; - u_int32_t proc; - u_int32_t arglen; + uint32_t prog; + uint32_t vers; + uint32_t proc; + uint32_t arglen; struct xdr_inaddr xina; } *args; struct repl { - u_int16_t _pad; - u_int16_t port; - u_int32_t encap_len; + uint16_t _pad; + uint16_t port; + uint32_t encap_len; /* encapsulated data here */ n_long capsule[64]; } *repl; struct { n_long h[RPC_HEADER_WORDS]; struct args d; } sdata; char *send_tail, *recv_head; struct iodesc *d; void *pkt; int len, x, rc; RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip))); rc = -1; if (!(d = socktodesc(sockfd))) { RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd)); return (rc); } args = &sdata.d; /* * Build request args for PMAPPROC_CALLIT. */ args->prog = htonl(BOOTPARAM_PROG); args->vers = htonl(BOOTPARAM_VERS); args->proc = htonl(BOOTPARAM_WHOAMI); args->arglen = htonl(sizeof(struct xdr_inaddr)); send_tail = (char*) &args->xina; /* * append encapsulated data (client IP address) */ if (xdr_inaddr_encode(&send_tail, myip)) return (rc); /* RPC: portmap/callit */ d->myport = htons(--rpc_port); d->destip.s_addr = INADDR_BROADCAST; /* XXX: subnet bcast? */ /* rpc_call will set d->destport */ pkt = NULL; len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT, args, send_tail - (char*)args, (void **)&repl, &pkt); if (len < 8) { printf("bootparamd: 'whoami' call failed\n"); goto done; } /* Save bootparam server address (from IP header). */ rpc_fromaddr(repl, &bp_server_addr, &bp_server_port); /* * Note that bp_server_port is now 111 due to the * indirect call (using PMAPPROC_CALLIT), so get the * actual port number from the reply data. */ bp_server_port = repl->port; RPC_PRINTF(("bp_whoami: server at %s:%d\n", inet_ntoa(bp_server_addr), ntohs(bp_server_port))); /* We have just done a portmap call, so cache the portnum. */ rpc_pmap_putcache(bp_server_addr, BOOTPARAM_PROG, BOOTPARAM_VERS, (int)ntohs(bp_server_port)); /* * Parse the encapsulated results from bootparam/whoami */ x = ntohl(repl->encap_len); if (len < x) { printf("bp_whoami: short reply, %d < %d\n", len, x); goto done; } recv_head = (char*) repl->capsule; /* client name */ hostnamelen = MAXHOSTNAMELEN-1; if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) { RPC_PRINTF(("bp_whoami: bad hostname\n")); goto done; } /* domain name */ domainnamelen = MAXHOSTNAMELEN-1; if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) { RPC_PRINTF(("bp_whoami: bad domainname\n")); goto done; } /* gateway address */ if (xdr_inaddr_decode(&recv_head, &gateip)) { RPC_PRINTF(("bp_whoami: bad gateway\n")); goto done; } /* success */ rc = 0; done: free(pkt); return (rc); } /* * RPC: bootparam/getfile * Given client name and file "key", get: * server name * server IP address * server pathname */ int bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname) { struct { n_long h[RPC_HEADER_WORDS]; n_long d[64]; } sdata; void *pkt; char serv_name[FNAME_SIZE]; char *rdata, *send_tail; /* misc... */ struct iodesc *d; int rc = -1, sn_len, path_len, rlen; if (!(d = socktodesc(sockfd))) { RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd)); return (-1); } send_tail = (char*) sdata.d; /* * Build request message. */ /* client name (hostname) */ if (xdr_string_encode(&send_tail, hostname, hostnamelen)) { RPC_PRINTF(("bp_getfile: bad client\n")); return (-1); } /* key name (root or swap) */ if (xdr_string_encode(&send_tail, key, strlen(key))) { RPC_PRINTF(("bp_getfile: bad key\n")); return (-1); } /* RPC: bootparam/getfile */ d->myport = htons(--rpc_port); d->destip = bp_server_addr; /* rpc_call will set d->destport */ pkt = NULL; rlen = rpc_call(d, BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE, sdata.d, send_tail - (char*)sdata.d, (void **)&rdata, &pkt); if (rlen < 4) { RPC_PRINTF(("bp_getfile: short reply\n")); errno = EBADRPC; goto done; } /* * Parse result message. */ /* server name */ sn_len = FNAME_SIZE-1; if (xdr_string_decode(&rdata, serv_name, &sn_len)) { RPC_PRINTF(("bp_getfile: bad server name\n")); goto done; } /* server IP address (mountd/NFS) */ if (xdr_inaddr_decode(&rdata, serv_addr)) { RPC_PRINTF(("bp_getfile: bad server addr\n")); goto done; } /* server pathname */ path_len = MAXPATHLEN-1; if (xdr_string_decode(&rdata, pathname, &path_len)) { RPC_PRINTF(("bp_getfile: bad server path\n")); goto done; } /* success */ rc = 0; done: free(pkt); return (rc); } /* * eXternal Data Representation routines. * (but with non-standard args...) */ int xdr_string_encode(char **pkt, char *str, int len) { uint32_t *lenp; char *datap; int padlen = (len + 3) & ~3; /* padded length */ /* The data will be int aligned. */ lenp = (uint32_t *) *pkt; *pkt += sizeof(*lenp); *lenp = htonl(len); datap = *pkt; *pkt += padlen; bcopy(str, datap, len); return (0); } int xdr_string_decode(char **pkt, char *str, int *len_p) { uint32_t *lenp; char *datap; int slen; /* string length */ int plen; /* padded length */ /* The data will be int aligned. */ lenp = (uint32_t *) *pkt; *pkt += sizeof(*lenp); slen = ntohl(*lenp); plen = (slen + 3) & ~3; if (slen > *len_p) slen = *len_p; datap = *pkt; *pkt += plen; bcopy(datap, str, slen); str[slen] = '\0'; *len_p = slen; return (0); } int xdr_inaddr_encode(char **pkt, struct in_addr ia) { struct xdr_inaddr *xi; u_char *cp; int32_t *ip; union { n_long l; /* network order */ u_char c[4]; } uia; /* The data will be int aligned. */ xi = (struct xdr_inaddr *) *pkt; *pkt += sizeof(*xi); xi->atype = htonl(1); uia.l = ia.s_addr; cp = uia.c; ip = xi->addr; /* * Note: the htonl() calls below DO NOT * imply that uia.l is in host order. * In fact this needs it in net order. */ *ip++ = htonl((unsigned int)*cp++); *ip++ = htonl((unsigned int)*cp++); *ip++ = htonl((unsigned int)*cp++); *ip++ = htonl((unsigned int)*cp++); return (0); } int xdr_inaddr_decode(char **pkt, struct in_addr *ia) { struct xdr_inaddr *xi; u_char *cp; int32_t *ip; union { n_long l; /* network order */ u_char c[4]; } uia; /* The data will be int aligned. */ xi = (struct xdr_inaddr *) *pkt; *pkt += sizeof(*xi); if (xi->atype != htonl(1)) { RPC_PRINTF(("xdr_inaddr_decode: bad addrtype=%d\n", ntohl(xi->atype))); return(-1); } cp = uia.c; ip = xi->addr; /* * Note: the ntohl() calls below DO NOT * imply that uia.l is in host order. * In fact this needs it in net order. */ *cp++ = ntohl(*ip++); *cp++ = ntohl(*ip++); *cp++ = ntohl(*ip++); *cp++ = ntohl(*ip++); ia->s_addr = uia.l; return (0); } Index: head/stand/libsa/dosfs.h =================================================================== --- head/stand/libsa/dosfs.h (revision 330863) +++ head/stand/libsa/dosfs.h (revision 330864) @@ -1,123 +1,123 @@ /* * Copyright (c) 1996, 1998 Robert Nordier * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef DOSIO_H #define DOSIO_H /* * DOS file attributes */ #define FA_RDONLY 001 /* read-only */ #define FA_HIDDEN 002 /* hidden file */ #define FA_SYSTEM 004 /* system file */ #define FA_LABEL 010 /* volume label */ #define FA_DIR 020 /* directory */ #define FA_ARCH 040 /* archive (file modified) */ #define FA_XDE 017 /* extended directory entry */ #define FA_MASK 077 /* all attributes */ /* * Macros to convert DOS-format 16-bit and 32-bit quantities */ -#define cv2(p) ((u_int16_t)(p)[0] | \ - ((u_int16_t)(p)[1] << 010)) -#define cv4(p) ((u_int32_t)(p)[0] | \ - ((u_int32_t)(p)[1] << 010) | \ - ((u_int32_t)(p)[2] << 020) | \ - ((u_int32_t)(p)[3] << 030)) +#define cv2(p) ((uint16_t)(p)[0] | \ + ((uint16_t)(p)[1] << 010)) +#define cv4(p) ((uint32_t)(p)[0] | \ + ((uint32_t)(p)[1] << 010) | \ + ((uint32_t)(p)[2] << 020) | \ + ((uint32_t)(p)[3] << 030)) /* * Directory, filesystem, and file structures. */ typedef struct { u_char x_case; /* case */ u_char c_hsec; /* created: secs/100 */ u_char c_time[2]; /* created: time */ u_char c_date[2]; /* created: date */ u_char a_date[2]; /* accessed: date */ u_char h_clus[2]; /* clus[hi] */ } DOS_DEX; typedef struct { u_char name[8]; /* name */ u_char ext[3]; /* extension */ u_char attr; /* attributes */ DOS_DEX dex; /* VFAT/FAT32 only */ u_char time[2]; /* modified: time */ u_char date[2]; /* modified: date */ u_char clus[2]; /* starting cluster */ u_char size[4]; /* size */ } DOS_DE; typedef struct { u_char seq; /* flags */ u_char name1[5][2]; /* 1st name area */ u_char attr; /* (see fat_de) */ u_char res; /* reserved */ u_char chk; /* checksum */ u_char name2[6][2]; /* 2nd name area */ u_char clus[2]; /* (see fat_de) */ u_char name3[2][2]; /* 3rd name area */ } DOS_XDE; typedef union { DOS_DE de; /* standard directory entry */ DOS_XDE xde; /* extended directory entry */ } DOS_DIR; typedef struct { struct open_file *fd; /* file descriptor */ u_char *fatbuf; /* FAT cache buffer */ u_int fatbuf_blknum; /* number of 128K block in FAT cache buffer */ u_int links; /* active links to structure */ u_int spc; /* sectors per cluster */ u_int bsize; /* cluster size in bytes */ u_int bshift; /* cluster conversion shift */ u_int dirents; /* root directory entries */ u_int spf; /* sectors per fat */ u_int rdcl; /* root directory start cluster */ u_int lsnfat; /* start of fat */ u_int lsndir; /* start of root dir */ u_int lsndta; /* start of data area */ u_int fatsz; /* FAT entry size */ u_int xclus; /* maximum cluster number */ DOS_DE root; } DOS_FS; typedef struct { DOS_FS *fs; /* associated filesystem */ DOS_DE de; /* directory entry */ u_int offset; /* current offset */ u_int c; /* last cluster read */ } DOS_FILE; #endif /* !DOSIO_H */ Index: head/stand/libsa/ext2fs.c =================================================================== --- head/stand/libsa/ext2fs.c (revision 330863) +++ head/stand/libsa/ext2fs.c (revision 330864) @@ -1,908 +1,908 @@ /*- * Copyright (c) 1999,2000 Jonathan Lemon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * Copyright (c) 1990, 1991 Carnegie Mellon University * All Rights Reserved. * * Author: David Golub * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include #include #include "stand.h" #include "string.h" static int ext2fs_open(const char *path, struct open_file *f); static int ext2fs_close(struct open_file *f); static int ext2fs_read(struct open_file *f, void *buf, size_t size, size_t *resid); static off_t ext2fs_seek(struct open_file *f, off_t offset, int where); static int ext2fs_stat(struct open_file *f, struct stat *sb); static int ext2fs_readdir(struct open_file *f, struct dirent *d); static int dtmap[] = { DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK }; #define EXTFTODT(x) (x) > sizeof(dtmap) / sizeof(dtmap[0]) ? \ DT_UNKNOWN : dtmap[x] struct fs_ops ext2fs_fsops = { "ext2fs", ext2fs_open, ext2fs_close, ext2fs_read, null_write, ext2fs_seek, ext2fs_stat, ext2fs_readdir }; #define EXT2_SBSIZE 1024 #define EXT2_SBLOCK (1024 / DEV_BSIZE) /* block offset of superblock */ #define EXT2_MAGIC 0xef53 #define EXT2_ROOTINO 2 #define EXT2_REV0 0 /* original revision of ext2 */ #define EXT2_R0_ISIZE 128 /* inode size */ #define EXT2_R0_FIRSTINO 11 /* first inode */ #define EXT2_MINBSHIFT 10 /* mininum block shift */ #define EXT2_MINFSHIFT 10 /* mininum frag shift */ #define EXT2_NDADDR 12 /* # of direct blocks */ #define EXT2_NIADDR 3 /* # of indirect blocks */ /* * file system block to disk address */ #define fsb_to_db(fs, blk) ((blk) << (fs)->fs_fsbtodb) /* * inode to block group offset * inode to block group * inode to disk address * inode to block offset */ #define ino_to_bgo(fs, ino) (((ino) - 1) % (fs)->fs_ipg) #define ino_to_bg(fs, ino) (((ino) - 1) / (fs)->fs_ipg) #define ino_to_db(fs, bg, ino) \ fsb_to_db(fs, ((bg)[ino_to_bg(fs, ino)].bg_inotbl + \ ino_to_bgo(fs, ino) / (fs)->fs_ipb)) #define ino_to_bo(fs, ino) (ino_to_bgo(fs, ino) % (fs)->fs_ipb) #define nindir(fs) \ - ((fs)->fs_bsize / sizeof(u_int32_t)) + ((fs)->fs_bsize / sizeof(uint32_t)) #define lblkno(fs, loc) /* loc / bsize */ \ ((loc) >> (fs)->fs_bshift) #define smalllblktosize(fs, blk) /* blk * bsize */ \ ((blk) << (fs)->fs_bshift) #define blkoff(fs, loc) /* loc % bsize */ \ ((loc) & (fs)->fs_bmask) #define fragroundup(fs, size) /* roundup(size, fsize) */ \ (((size) + (fs)->fs_fmask) & ~(fs)->fs_fmask) #define dblksize(fs, dip, lbn) \ (((lbn) >= EXT2_NDADDR || (dip)->di_size >= smalllblktosize(fs, (lbn) + 1)) \ ? (fs)->fs_bsize \ : (fragroundup(fs, blkoff(fs, (dip)->di_size)))) /* * superblock describing ext2fs */ struct ext2fs_disk { - u_int32_t fd_inodes; /* # of inodes */ - u_int32_t fd_blocks; /* # of blocks */ - u_int32_t fd_resblk; /* # of reserved blocks */ - u_int32_t fd_freeblk; /* # of free blocks */ - u_int32_t fd_freeino; /* # of free inodes */ - u_int32_t fd_firstblk; /* first data block */ - u_int32_t fd_bsize; /* block size */ - u_int32_t fd_fsize; /* frag size */ - u_int32_t fd_bpg; /* blocks per group */ - u_int32_t fd_fpg; /* frags per group */ - u_int32_t fd_ipg; /* inodes per group */ - u_int32_t fd_mtime; /* mount time */ - u_int32_t fd_wtime; /* write time */ - u_int16_t fd_mount; /* # of mounts */ + uint32_t fd_inodes; /* # of inodes */ + uint32_t fd_blocks; /* # of blocks */ + uint32_t fd_resblk; /* # of reserved blocks */ + uint32_t fd_freeblk; /* # of free blocks */ + uint32_t fd_freeino; /* # of free inodes */ + uint32_t fd_firstblk; /* first data block */ + uint32_t fd_bsize; /* block size */ + uint32_t fd_fsize; /* frag size */ + uint32_t fd_bpg; /* blocks per group */ + uint32_t fd_fpg; /* frags per group */ + uint32_t fd_ipg; /* inodes per group */ + uint32_t fd_mtime; /* mount time */ + uint32_t fd_wtime; /* write time */ + uint16_t fd_mount; /* # of mounts */ int16_t fd_maxmount; /* max # of mounts */ - u_int16_t fd_magic; /* magic number */ - u_int16_t fd_state; /* state */ - u_int16_t fd_eflag; /* error flags */ - u_int16_t fd_mnrrev; /* minor revision */ - u_int32_t fd_lastchk; /* last check */ - u_int32_t fd_chkintvl; /* maximum check interval */ - u_int32_t fd_os; /* os */ - u_int32_t fd_revision; /* revision */ - u_int16_t fd_uid; /* uid for reserved blocks */ - u_int16_t fd_gid; /* gid for reserved blocks */ + uint16_t fd_magic; /* magic number */ + uint16_t fd_state; /* state */ + uint16_t fd_eflag; /* error flags */ + uint16_t fd_mnrrev; /* minor revision */ + uint32_t fd_lastchk; /* last check */ + uint32_t fd_chkintvl; /* maximum check interval */ + uint32_t fd_os; /* os */ + uint32_t fd_revision; /* revision */ + uint16_t fd_uid; /* uid for reserved blocks */ + uint16_t fd_gid; /* gid for reserved blocks */ - u_int32_t fd_firstino; /* first non-reserved inode */ - u_int16_t fd_isize; /* inode size */ - u_int16_t fd_nblkgrp; /* block group # of superblock */ - u_int32_t fd_fcompat; /* compatible features */ - u_int32_t fd_fincompat; /* incompatible features */ - u_int32_t fd_frocompat; /* read-only compatibilties */ - u_int8_t fd_uuid[16]; /* volume uuid */ + uint32_t fd_firstino; /* first non-reserved inode */ + uint16_t fd_isize; /* inode size */ + uint16_t fd_nblkgrp; /* block group # of superblock */ + uint32_t fd_fcompat; /* compatible features */ + uint32_t fd_fincompat; /* incompatible features */ + uint32_t fd_frocompat; /* read-only compatibilties */ + uint8_t fd_uuid[16]; /* volume uuid */ char fd_volname[16]; /* volume name */ char fd_fsmnt[64]; /* name last mounted on */ - u_int32_t fd_bitmap; /* compression bitmap */ + uint32_t fd_bitmap; /* compression bitmap */ - u_int8_t fd_nblkpa; /* # of blocks to preallocate */ - u_int8_t fd_ndblkpa; /* # of dir blocks to preallocate */ + uint8_t fd_nblkpa; /* # of blocks to preallocate */ + uint8_t fd_ndblkpa; /* # of dir blocks to preallocate */ }; struct ext2fs_core { int fc_bsize; /* block size */ int fc_bshift; /* block shift amount */ int fc_bmask; /* block mask */ int fc_fsize; /* frag size */ int fc_fshift; /* frag shift amount */ int fc_fmask; /* frag mask */ int fc_isize; /* inode size */ int fc_imask; /* inode mask */ int fc_firstino; /* first non-reserved inode */ int fc_ipb; /* inodes per block */ int fc_fsbtodb; /* fsb to ds shift */ }; struct ext2fs { struct ext2fs_disk fs_fd; char fs_pad[EXT2_SBSIZE - sizeof(struct ext2fs_disk)]; struct ext2fs_core fs_fc; #define fs_magic fs_fd.fd_magic #define fs_revision fs_fd.fd_revision #define fs_blocks fs_fd.fd_blocks #define fs_firstblk fs_fd.fd_firstblk #define fs_bpg fs_fd.fd_bpg #define fs_ipg fs_fd.fd_ipg #define fs_bsize fs_fc.fc_bsize #define fs_bshift fs_fc.fc_bshift #define fs_bmask fs_fc.fc_bmask #define fs_fsize fs_fc.fc_fsize #define fs_fshift fs_fc.fc_fshift #define fs_fmask fs_fc.fc_fmask #define fs_isize fs_fc.fc_isize #define fs_imask fs_fc.fc_imask #define fs_firstino fs_fc.fc_firstino #define fs_ipb fs_fc.fc_ipb #define fs_fsbtodb fs_fc.fc_fsbtodb }; struct ext2blkgrp { - u_int32_t bg_blkmap; /* block bitmap */ - u_int32_t bg_inomap; /* inode bitmap */ - u_int32_t bg_inotbl; /* inode table */ - u_int16_t bg_nfblk; /* # of free blocks */ - u_int16_t bg_nfino; /* # of free inodes */ - u_int16_t bg_ndirs; /* # of dirs */ + uint32_t bg_blkmap; /* block bitmap */ + uint32_t bg_inomap; /* inode bitmap */ + uint32_t bg_inotbl; /* inode table */ + uint16_t bg_nfblk; /* # of free blocks */ + uint16_t bg_nfino; /* # of free inodes */ + uint16_t bg_ndirs; /* # of dirs */ char bg_pad[14]; }; struct ext2dinode { - u_int16_t di_mode; /* mode */ - u_int16_t di_uid; /* uid */ - u_int32_t di_size; /* byte size */ - u_int32_t di_atime; /* access time */ - u_int32_t di_ctime; /* creation time */ - u_int32_t di_mtime; /* modification time */ - u_int32_t di_dtime; /* deletion time */ - u_int16_t di_gid; /* gid */ - u_int16_t di_nlink; /* link count */ - u_int32_t di_nblk; /* block count */ - u_int32_t di_flags; /* file flags */ + uint16_t di_mode; /* mode */ + uint16_t di_uid; /* uid */ + uint32_t di_size; /* byte size */ + uint32_t di_atime; /* access time */ + uint32_t di_ctime; /* creation time */ + uint32_t di_mtime; /* modification time */ + uint32_t di_dtime; /* deletion time */ + uint16_t di_gid; /* gid */ + uint16_t di_nlink; /* link count */ + uint32_t di_nblk; /* block count */ + uint32_t di_flags; /* file flags */ - u_int32_t di_osdep1; /* os dependent stuff */ + uint32_t di_osdep1; /* os dependent stuff */ - u_int32_t di_db[EXT2_NDADDR]; /* direct blocks */ - u_int32_t di_ib[EXT2_NIADDR]; /* indirect blocks */ - u_int32_t di_version; /* version */ - u_int32_t di_facl; /* file acl */ - u_int32_t di_dacl; /* dir acl */ - u_int32_t di_faddr; /* fragment addr */ + uint32_t di_db[EXT2_NDADDR]; /* direct blocks */ + uint32_t di_ib[EXT2_NIADDR]; /* indirect blocks */ + uint32_t di_version; /* version */ + uint32_t di_facl; /* file acl */ + uint32_t di_dacl; /* dir acl */ + uint32_t di_faddr; /* fragment addr */ - u_int8_t di_frag; /* fragment number */ - u_int8_t di_fsize; /* fragment size */ + uint8_t di_frag; /* fragment number */ + uint8_t di_fsize; /* fragment size */ char di_pad[10]; #define di_shortlink di_db }; #define EXT2_MAXNAMLEN 255 struct ext2dirent { - u_int32_t d_ino; /* inode */ - u_int16_t d_reclen; /* directory entry length */ - u_int8_t d_namlen; /* name length */ - u_int8_t d_type; /* file type */ + uint32_t d_ino; /* inode */ + uint16_t d_reclen; /* directory entry length */ + uint8_t d_namlen; /* name length */ + uint8_t d_type; /* file type */ char d_name[EXT2_MAXNAMLEN]; }; struct file { off_t f_seekp; /* seek pointer */ struct ext2fs *f_fs; /* pointer to super-block */ struct ext2blkgrp *f_bg; /* pointer to blkgrp map */ struct ext2dinode f_di; /* copy of on-disk inode */ int f_nindir[EXT2_NIADDR]; /* number of blocks mapped by indirect block at level i */ char *f_blk[EXT2_NIADDR]; /* buffer for indirect block at level i */ size_t f_blksize[EXT2_NIADDR]; /* size of buffer */ daddr_t f_blkno[EXT2_NIADDR]; /* disk address of block in buffer */ char *f_buf; /* buffer for data block */ size_t f_buf_size; /* size of data block */ daddr_t f_buf_blkno; /* block number of data block */ }; /* forward decls */ static int read_inode(ino_t inumber, struct open_file *f); static int block_map(struct open_file *f, daddr_t file_block, daddr_t *disk_block_p); static int buf_read_file(struct open_file *f, char **buf_p, size_t *size_p); static int search_directory(char *name, struct open_file *f, ino_t *inumber_p); /* * Open a file. */ static int ext2fs_open(const char *upath, struct open_file *f) { struct file *fp; struct ext2fs *fs; size_t buf_size; ino_t inumber, parent_inumber; int i, len, groups, bg_per_blk, blkgrps, mult; int nlinks = 0; int error = 0; char *cp, *ncp, *path = NULL, *buf = NULL; char namebuf[MAXPATHLEN+1]; char c; /* allocate file system specific data structure */ fp = malloc(sizeof(struct file)); if (fp == NULL) return (ENOMEM); bzero(fp, sizeof(struct file)); f->f_fsdata = (void *)fp; /* allocate space and read super block */ fs = (struct ext2fs *)malloc(sizeof(*fs)); fp->f_fs = fs; twiddle(1); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, EXT2_SBLOCK, EXT2_SBSIZE, (char *)fs, &buf_size); if (error) goto out; if (buf_size != EXT2_SBSIZE || fs->fs_magic != EXT2_MAGIC) { error = EINVAL; goto out; } /* * compute in-core values for the superblock */ fs->fs_bshift = EXT2_MINBSHIFT + fs->fs_fd.fd_bsize; fs->fs_bsize = 1 << fs->fs_bshift; fs->fs_bmask = fs->fs_bsize - 1; fs->fs_fshift = EXT2_MINFSHIFT + fs->fs_fd.fd_fsize; fs->fs_fsize = 1 << fs->fs_fshift; fs->fs_fmask = fs->fs_fsize - 1; if (fs->fs_revision == EXT2_REV0) { fs->fs_isize = EXT2_R0_ISIZE; fs->fs_firstino = EXT2_R0_FIRSTINO; } else { fs->fs_isize = fs->fs_fd.fd_isize; fs->fs_firstino = fs->fs_fd.fd_firstino; } fs->fs_imask = fs->fs_isize - 1; fs->fs_ipb = fs->fs_bsize / fs->fs_isize; fs->fs_fsbtodb = (fs->fs_bsize / DEV_BSIZE) - 1; /* * we have to load in the "group descriptors" here */ groups = howmany(fs->fs_blocks - fs->fs_firstblk, fs->fs_bpg); bg_per_blk = fs->fs_bsize / sizeof(struct ext2blkgrp); blkgrps = howmany(groups, bg_per_blk); len = blkgrps * fs->fs_bsize; fp->f_bg = malloc(len); twiddle(1); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, EXT2_SBLOCK + EXT2_SBSIZE / DEV_BSIZE, len, (char *)fp->f_bg, &buf_size); if (error) goto out; /* * XXX * validation of values? (blocksize, descriptors, etc?) */ /* * Calculate indirect block levels. */ mult = 1; for (i = 0; i < EXT2_NIADDR; i++) { mult *= nindir(fs); fp->f_nindir[i] = mult; } inumber = EXT2_ROOTINO; if ((error = read_inode(inumber, f)) != 0) goto out; path = strdup(upath); if (path == NULL) { error = ENOMEM; goto out; } cp = path; while (*cp) { /* * Remove extra separators */ while (*cp == '/') cp++; if (*cp == '\0') break; /* * Check that current node is a directory. */ if (! S_ISDIR(fp->f_di.di_mode)) { error = ENOTDIR; goto out; } /* * Get next component of path name. */ len = 0; ncp = cp; while ((c = *cp) != '\0' && c != '/') { if (++len > EXT2_MAXNAMLEN) { error = ENOENT; goto out; } cp++; } *cp = '\0'; /* * Look up component in current directory. * Save directory inumber in case we find a * symbolic link. */ parent_inumber = inumber; error = search_directory(ncp, f, &inumber); *cp = c; if (error) goto out; /* * Open next component. */ if ((error = read_inode(inumber, f)) != 0) goto out; /* * Check for symbolic link. */ if (S_ISLNK(fp->f_di.di_mode)) { int link_len = fp->f_di.di_size; int len; len = strlen(cp); if (link_len + len > MAXPATHLEN || ++nlinks > MAXSYMLINKS) { error = ENOENT; goto out; } bcopy(cp, &namebuf[link_len], len + 1); if (fp->f_di.di_nblk == 0) { bcopy(fp->f_di.di_shortlink, namebuf, link_len); } else { /* * Read file for symbolic link */ struct ext2fs *fs = fp->f_fs; daddr_t disk_block; size_t buf_size; if (! buf) buf = malloc(fs->fs_bsize); error = block_map(f, (daddr_t)0, &disk_block); if (error) goto out; twiddle(1); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsb_to_db(fs, disk_block), fs->fs_bsize, buf, &buf_size); if (error) goto out; bcopy((char *)buf, namebuf, link_len); } /* * If relative pathname, restart at parent directory. * If absolute pathname, restart at root. */ cp = namebuf; if (*cp != '/') inumber = parent_inumber; else inumber = (ino_t)EXT2_ROOTINO; if ((error = read_inode(inumber, f)) != 0) goto out; } } /* * Found terminal component. */ error = 0; fp->f_seekp = 0; out: if (buf) free(buf); if (path) free(path); if (error) { if (fp->f_buf) free(fp->f_buf); free(fp->f_fs); free(fp); } return (error); } /* * Read a new inode into a file structure. */ static int read_inode(ino_t inumber, struct open_file *f) { struct file *fp = (struct file *)f->f_fsdata; struct ext2fs *fs = fp->f_fs; struct ext2dinode *dp; char *buf; size_t rsize; int level, error = 0; /* * Read inode and save it. */ buf = malloc(fs->fs_bsize); twiddle(1); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, ino_to_db(fs, fp->f_bg, inumber), fs->fs_bsize, buf, &rsize); if (error) goto out; if (rsize != fs->fs_bsize) { error = EIO; goto out; } dp = (struct ext2dinode *)buf; fp->f_di = dp[ino_to_bo(fs, inumber)]; /* clear out old buffers */ for (level = 0; level < EXT2_NIADDR; level++) fp->f_blkno[level] = -1; fp->f_buf_blkno = -1; fp->f_seekp = 0; out: free(buf); return (error); } /* * Given an offset in a file, find the disk block number that * contains that block. */ static int block_map(struct open_file *f, daddr_t file_block, daddr_t *disk_block_p) { struct file *fp = (struct file *)f->f_fsdata; struct ext2fs *fs = fp->f_fs; daddr_t ind_block_num; int32_t *ind_p; int idx, level; int error; /* * Index structure of an inode: * * di_db[0..EXT2_NDADDR-1] hold block numbers for blocks * 0..EXT2_NDADDR-1 * * di_ib[0] index block 0 is the single indirect block * holds block numbers for blocks * EXT2_NDADDR .. EXT2_NDADDR + NINDIR(fs)-1 * * di_ib[1] index block 1 is the double indirect block * holds block numbers for INDEX blocks for blocks * EXT2_NDADDR + NINDIR(fs) .. * EXT2_NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1 * * di_ib[2] index block 2 is the triple indirect block * holds block numbers for double-indirect * blocks for blocks * EXT2_NDADDR + NINDIR(fs) + NINDIR(fs)**2 .. * EXT2_NDADDR + NINDIR(fs) + NINDIR(fs)**2 * + NINDIR(fs)**3 - 1 */ if (file_block < EXT2_NDADDR) { /* Direct block. */ *disk_block_p = fp->f_di.di_db[file_block]; return (0); } file_block -= EXT2_NDADDR; /* * nindir[0] = NINDIR * nindir[1] = NINDIR**2 * nindir[2] = NINDIR**3 * etc */ for (level = 0; level < EXT2_NIADDR; level++) { if (file_block < fp->f_nindir[level]) break; file_block -= fp->f_nindir[level]; } if (level == EXT2_NIADDR) { /* Block number too high */ return (EFBIG); } ind_block_num = fp->f_di.di_ib[level]; for (; level >= 0; level--) { if (ind_block_num == 0) { *disk_block_p = 0; /* missing */ return (0); } if (fp->f_blkno[level] != ind_block_num) { if (fp->f_blk[level] == (char *)0) fp->f_blk[level] = malloc(fs->fs_bsize); twiddle(1); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsb_to_db(fp->f_fs, ind_block_num), fs->fs_bsize, fp->f_blk[level], &fp->f_blksize[level]); if (error) return (error); if (fp->f_blksize[level] != fs->fs_bsize) return (EIO); fp->f_blkno[level] = ind_block_num; } ind_p = (int32_t *)fp->f_blk[level]; if (level > 0) { idx = file_block / fp->f_nindir[level - 1]; file_block %= fp->f_nindir[level - 1]; } else { idx = file_block; } ind_block_num = ind_p[idx]; } *disk_block_p = ind_block_num; return (0); } /* * Read a portion of a file into an internal buffer. Return * the location in the buffer and the amount in the buffer. */ static int buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) { struct file *fp = (struct file *)f->f_fsdata; struct ext2fs *fs = fp->f_fs; long off; daddr_t file_block; daddr_t disk_block; size_t block_size; int error = 0; off = blkoff(fs, fp->f_seekp); file_block = lblkno(fs, fp->f_seekp); block_size = dblksize(fs, &fp->f_di, file_block); if (file_block != fp->f_buf_blkno) { error = block_map(f, file_block, &disk_block); if (error) goto done; if (fp->f_buf == (char *)0) fp->f_buf = malloc(fs->fs_bsize); if (disk_block == 0) { bzero(fp->f_buf, block_size); fp->f_buf_size = block_size; } else { twiddle(4); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsb_to_db(fs, disk_block), block_size, fp->f_buf, &fp->f_buf_size); if (error) goto done; } fp->f_buf_blkno = file_block; } /* * Return address of byte in buffer corresponding to * offset, and size of remainder of buffer after that * byte. */ *buf_p = fp->f_buf + off; *size_p = block_size - off; /* * But truncate buffer at end of file. */ if (*size_p > fp->f_di.di_size - fp->f_seekp) *size_p = fp->f_di.di_size - fp->f_seekp; done: return (error); } /* * Search a directory for a name and return its * i_number. */ static int search_directory(char *name, struct open_file *f, ino_t *inumber_p) { struct file *fp = (struct file *)f->f_fsdata; struct ext2dirent *dp, *edp; char *buf; size_t buf_size; int namlen, length; int error; length = strlen(name); fp->f_seekp = 0; while (fp->f_seekp < fp->f_di.di_size) { error = buf_read_file(f, &buf, &buf_size); if (error) return (error); dp = (struct ext2dirent *)buf; edp = (struct ext2dirent *)(buf + buf_size); while (dp < edp) { if (dp->d_ino == (ino_t)0) goto next; namlen = dp->d_namlen; if (namlen == length && strncmp(name, dp->d_name, length) == 0) { /* found entry */ *inumber_p = dp->d_ino; return (0); } next: dp = (struct ext2dirent *)((char *)dp + dp->d_reclen); } fp->f_seekp += buf_size; } return (ENOENT); } static int ext2fs_close(struct open_file *f) { struct file *fp = (struct file *)f->f_fsdata; int level; f->f_fsdata = (void *)0; if (fp == (struct file *)0) return (0); for (level = 0; level < EXT2_NIADDR; level++) { if (fp->f_blk[level]) free(fp->f_blk[level]); } if (fp->f_buf) free(fp->f_buf); if (fp->f_bg) free(fp->f_bg); free(fp->f_fs); free(fp); return (0); } static int ext2fs_read(struct open_file *f, void *addr, size_t size, size_t *resid) { struct file *fp = (struct file *)f->f_fsdata; size_t csize, buf_size; char *buf; int error = 0; while (size != 0) { if (fp->f_seekp >= fp->f_di.di_size) break; error = buf_read_file(f, &buf, &buf_size); if (error) break; csize = size; if (csize > buf_size) csize = buf_size; bcopy(buf, addr, csize); fp->f_seekp += csize; addr = (char *)addr + csize; size -= csize; } if (resid) *resid = size; return (error); } static off_t ext2fs_seek(struct open_file *f, off_t offset, int where) { struct file *fp = (struct file *)f->f_fsdata; switch (where) { case SEEK_SET: fp->f_seekp = offset; break; case SEEK_CUR: fp->f_seekp += offset; break; case SEEK_END: fp->f_seekp = fp->f_di.di_size - offset; break; default: errno = EINVAL; return (-1); } return (fp->f_seekp); } static int ext2fs_stat(struct open_file *f, struct stat *sb) { struct file *fp = (struct file *)f->f_fsdata; /* only important stuff */ sb->st_mode = fp->f_di.di_mode; sb->st_uid = fp->f_di.di_uid; sb->st_gid = fp->f_di.di_gid; sb->st_size = fp->f_di.di_size; return (0); } static int ext2fs_readdir(struct open_file *f, struct dirent *d) { struct file *fp = (struct file *)f->f_fsdata; struct ext2dirent *ed; char *buf; size_t buf_size; int error; /* * assume that a directory entry will not be split across blocks */ again: if (fp->f_seekp >= fp->f_di.di_size) return (ENOENT); error = buf_read_file(f, &buf, &buf_size); if (error) return (error); ed = (struct ext2dirent *)buf; fp->f_seekp += ed->d_reclen; if (ed->d_ino == (ino_t)0) goto again; d->d_type = EXTFTODT(ed->d_type); strncpy(d->d_name, ed->d_name, ed->d_namlen); d->d_name[ed->d_namlen] = '\0'; return (0); } Index: head/stand/libsa/net.h =================================================================== --- head/stand/libsa/net.h (revision 330863) +++ head/stand/libsa/net.h (revision 330864) @@ -1,132 +1,132 @@ /* $NetBSD: net.h,v 1.10 1995/10/20 00:46:30 cgd Exp $ */ /* * Copyright (c) 1993 Adam Glass * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _STAND_NET_H #define _STAND_NET_H #ifndef _KERNEL /* XXX - see */ #undef __IPADDR -#define __IPADDR(x) htonl((u_int32_t)(x)) +#define __IPADDR(x) htonl((uint32_t)(x)) #endif #include "iodesc.h" #define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } enum net_proto { NET_NONE, NET_NFS, NET_TFTP }; /* Returns true if n_long's on the same net */ #define SAMENET(a1, a2, m) ((a1.s_addr & m) == (a2.s_addr & m)) #define MACPY(s, d) bcopy((char *)s, (char *)d, 6) #define MAXTMO 120 /* seconds */ #define MINTMO 2 /* seconds */ #define FNAME_SIZE 128 #define IFNAME_SIZE 16 #define RECV_SIZE 1536 /* XXX delete this */ /* * How much room to leave for headers: * 14: struct ether_header * 20: struct ip * 8: struct udphdr * That's 42 but let's pad it out to 48 bytes. */ #define ETHER_SIZE 14 #define HEADER_SIZE 48 extern u_char bcea[6]; extern char rootpath[FNAME_SIZE]; extern char bootfile[FNAME_SIZE]; extern char hostname[FNAME_SIZE]; extern int hostnamelen; extern char domainname[FNAME_SIZE]; extern int domainnamelen; extern int netproto; extern char ifname[IFNAME_SIZE]; /* All of these are in network order. */ extern struct in_addr myip; extern struct in_addr rootip; extern struct in_addr swapip; extern struct in_addr gateip; extern struct in_addr nameip; extern n_long netmask; extern u_int intf_mtu; extern int debug; /* defined in the machdep sources */ extern struct iodesc sockets[SOPEN_MAX]; /* ARP/RevARP functions: */ u_char *arpwhohas(struct iodesc *, struct in_addr); void arp_reply(struct iodesc *, void *); int rarp_getipaddress(int); /* Link functions: */ ssize_t sendether(struct iodesc *d, void *pkt, size_t len, u_char *dea, int etype); ssize_t readether(struct iodesc *, void **, void **, time_t, uint16_t *); ssize_t sendip(struct iodesc *, void *, size_t, uint8_t); ssize_t readip(struct iodesc *, void **, void **, time_t, uint8_t); ssize_t sendudp(struct iodesc *, void *, size_t); ssize_t readudp(struct iodesc *, void **, void **, time_t); ssize_t sendrecv(struct iodesc *, ssize_t (*)(struct iodesc *, void *, size_t), void *, size_t, ssize_t (*)(struct iodesc *, void **, void **, time_t, void *), void **, void **, void *); /* bootp/DHCP */ void bootp(int); /* Utilities: */ char *ether_sprintf(u_char *); int in_cksum(void *, int); char *inet_ntoa(struct in_addr); char *intoa(n_long); /* similar to inet_ntoa */ n_long inet_addr(char *); #endif /* ! _STAND_NET_H */ Index: head/stand/libsa/rpc.c =================================================================== --- head/stand/libsa/rpc.c (revision 330863) +++ head/stand/libsa/rpc.c (revision 330864) @@ -1,433 +1,433 @@ /* $NetBSD: rpc.c,v 1.18 1998/01/23 19:27:45 thorpej Exp $ */ /* * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL) */ #include __FBSDID("$FreeBSD$"); /* * RPC functions used by NFS and bootparams. * Note that bootparams requires the ability to find out the * address of the server from which its response has come. * This is supported by keeping the IP/UDP headers in the * buffer space provided by the caller. (See rpc_fromaddr) */ #include #include #include #include #include #include "rpcv2.h" #include "stand.h" #include "net.h" #include "netif.h" #include "rpc.h" struct auth_info { int32_t authtype; /* auth type */ - u_int32_t authlen; /* auth length */ + uint32_t authlen; /* auth length */ }; struct auth_unix { int32_t ua_time; int32_t ua_hostname; /* null */ int32_t ua_uid; int32_t ua_gid; int32_t ua_gidlist; /* null */ }; struct rpc_call { - u_int32_t rp_xid; /* request transaction id */ + uint32_t rp_xid; /* request transaction id */ int32_t rp_direction; /* call direction (0) */ - u_int32_t rp_rpcvers; /* rpc version (2) */ - u_int32_t rp_prog; /* program */ - u_int32_t rp_vers; /* version */ - u_int32_t rp_proc; /* procedure */ + uint32_t rp_rpcvers; /* rpc version (2) */ + uint32_t rp_prog; /* program */ + uint32_t rp_vers; /* version */ + uint32_t rp_proc; /* procedure */ }; struct rpc_reply { - u_int32_t rp_xid; /* request transaction id */ + uint32_t rp_xid; /* request transaction id */ int32_t rp_direction; /* call direction (1) */ int32_t rp_astatus; /* accept status (0: accepted) */ union { - u_int32_t rpu_errno; + uint32_t rpu_errno; struct { struct auth_info rok_auth; - u_int32_t rok_status; + uint32_t rok_status; } rpu_rok; } rp_u; }; /* Local forwards */ static ssize_t recvrpc(struct iodesc *, void **, void **, time_t, void *); static int rpc_getport(struct iodesc *, n_long, n_long); int rpc_xid; int rpc_port = 0x400; /* predecrement */ /* * Make a rpc call; return length of answer * Note: Caller must leave room for headers. */ ssize_t rpc_call(struct iodesc *d, n_long prog, n_long vers, n_long proc, void *sdata, size_t slen, void **rdata, void **pkt) { ssize_t cc, rsize; struct auth_info *auth; struct rpc_call *call; struct rpc_reply *reply; char *send_head, *send_tail; void *ptr; n_long x; int port; /* host order */ #ifdef RPC_DEBUG if (debug) printf("rpc_call: prog=0x%x vers=%d proc=%d\n", prog, vers, proc); #endif port = rpc_getport(d, prog, vers); if (port == -1) return (-1); d->destport = htons(port); /* * Prepend authorization stuff and headers. * Note, must prepend things in reverse order. */ send_head = sdata; send_tail = (char *)sdata + slen; /* Auth verifier is always auth_null */ send_head -= sizeof(*auth); auth = (struct auth_info *)send_head; auth->authtype = htonl(RPCAUTH_NULL); auth->authlen = 0; /* Auth credentials: always auth unix (as root) */ send_head -= sizeof(struct auth_unix); bzero(send_head, sizeof(struct auth_unix)); send_head -= sizeof(*auth); auth = (struct auth_info *)send_head; auth->authtype = htonl(RPCAUTH_UNIX); auth->authlen = htonl(sizeof(struct auth_unix)); /* RPC call structure. */ send_head -= sizeof(*call); call = (struct rpc_call *)send_head; rpc_xid++; call->rp_xid = htonl(rpc_xid); call->rp_direction = htonl(RPC_CALL); call->rp_rpcvers = htonl(RPC_VER2); call->rp_prog = htonl(prog); call->rp_vers = htonl(vers); call->rp_proc = htonl(proc); ptr = NULL; cc = sendrecv(d, sendudp, send_head, send_tail - send_head, recvrpc, &ptr, (void **)&reply, NULL); #ifdef RPC_DEBUG if (debug) printf("callrpc: cc=%zd\n", cc); #endif if (cc == -1) return (-1); if (cc <= sizeof(*reply)) { errno = EBADRPC; free(ptr); return (-1); } /* * Check the RPC reply status. * The xid, dir, astatus were already checked. */ auth = &reply->rp_u.rpu_rok.rok_auth; x = ntohl(auth->authlen); if (x != 0) { #ifdef RPC_DEBUG if (debug) printf("callrpc: reply auth != NULL\n"); #endif errno = EBADRPC; free(ptr); return (-1); } x = ntohl(reply->rp_u.rpu_rok.rok_status); if (x != 0) { printf("callrpc: error = %ld\n", (long)x); errno = EBADRPC; free(ptr); return (-1); } rsize = cc - sizeof(*reply); *rdata = (void *)((uintptr_t)reply + sizeof(*reply)); *pkt = ptr; return (rsize); } /* * Returns true if packet is the one we're waiting for. * This just checks the XID, direction, acceptance. * Remaining checks are done by callrpc */ static ssize_t recvrpc(struct iodesc *d, void **pkt, void **payload, time_t tleft, void *extra) { void *ptr; struct rpc_reply *reply; ssize_t n; int x; errno = 0; #ifdef RPC_DEBUG if (debug) printf("recvrpc: called\n"); #endif ptr = NULL; n = readudp(d, &ptr, (void **)&reply, tleft); if (n <= (4 * 4)) { free(ptr); return (-1); } x = ntohl(reply->rp_xid); if (x != rpc_xid) { #ifdef RPC_DEBUG if (debug) printf("recvrpc: rp_xid %d != xid %d\n", x, rpc_xid); #endif free(ptr); return (-1); } x = ntohl(reply->rp_direction); if (x != RPC_REPLY) { #ifdef RPC_DEBUG if (debug) printf("recvrpc: rp_direction %d != REPLY\n", x); #endif free(ptr); return (-1); } x = ntohl(reply->rp_astatus); if (x != RPC_MSGACCEPTED) { errno = ntohl(reply->rp_u.rpu_errno); printf("recvrpc: reject, astat=%d, errno=%d\n", x, errno); free(ptr); return (-1); } *pkt = ptr; *payload = reply; /* Return data count (thus indicating success) */ return (n); } /* * Given a pointer to a reply just received, * dig out the IP address/port from the headers. */ void rpc_fromaddr(void *pkt, struct in_addr *addr, u_short *port) { struct hackhdr { /* Tail of IP header: just IP addresses */ n_long ip_src; n_long ip_dst; /* UDP header: */ - u_int16_t uh_sport; /* source port */ - u_int16_t uh_dport; /* destination port */ + uint16_t uh_sport; /* source port */ + uint16_t uh_dport; /* destination port */ int16_t uh_ulen; /* udp length */ - u_int16_t uh_sum; /* udp checksum */ + uint16_t uh_sum; /* udp checksum */ /* RPC reply header: */ struct rpc_reply rpc; } *hhdr; hhdr = ((struct hackhdr *)pkt) - 1; addr->s_addr = hhdr->ip_src; *port = hhdr->uh_sport; } /* * RPC Portmapper cache */ #define PMAP_NUM 8 /* need at most 5 pmap entries */ int rpc_pmap_num; struct pmap_list { struct in_addr addr; /* server, net order */ u_int prog; /* host order */ u_int vers; /* host order */ int port; /* host order */ } rpc_pmap_list[PMAP_NUM]; /* * return port number in host order, or -1. * arguments are: * addr .. server, net order. * prog .. host order. * vers .. host order. */ int rpc_pmap_getcache(struct in_addr addr, u_int prog, u_int vers) { struct pmap_list *pl; for (pl = rpc_pmap_list; pl < &rpc_pmap_list[rpc_pmap_num]; pl++) { if (pl->addr.s_addr == addr.s_addr && pl->prog == prog && pl->vers == vers ) { return (pl->port); } } return (-1); } /* * arguments are: * addr .. server, net order. * prog .. host order. * vers .. host order. * port .. host order. */ void rpc_pmap_putcache(struct in_addr addr, u_int prog, u_int vers, int port) { struct pmap_list *pl; /* Don't overflow cache... */ if (rpc_pmap_num >= PMAP_NUM) { /* ... just re-use the last entry. */ rpc_pmap_num = PMAP_NUM - 1; #ifdef RPC_DEBUG printf("rpc_pmap_putcache: cache overflow\n"); #endif } pl = &rpc_pmap_list[rpc_pmap_num]; rpc_pmap_num++; /* Cache answer */ pl->addr = addr; pl->prog = prog; pl->vers = vers; pl->port = port; } /* * Request a port number from the port mapper. * Returns the port in host order. * prog and vers are host order. */ int rpc_getport(struct iodesc *d, n_long prog, n_long vers) { struct args { n_long prog; /* call program */ n_long vers; /* call version */ n_long proto; /* call protocol */ n_long port; /* call port (unused) */ } *args; struct res { n_long port; } *res; struct { n_long h[RPC_HEADER_WORDS]; struct args d; } sdata; void *pkt; ssize_t cc; int port; #ifdef RPC_DEBUG if (debug) printf("%s: prog=0x%x vers=%d\n", __func__, prog, vers); #endif /* This one is fixed forever. */ if (prog == PMAPPROG) { port = PMAPPORT; goto out; } /* Try for cached answer first */ port = rpc_pmap_getcache(d->destip, prog, vers); if (port != -1) goto out; args = &sdata.d; args->prog = htonl(prog); args->vers = htonl(vers); args->proto = htonl(IPPROTO_UDP); args->port = 0; pkt = NULL; cc = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, args, sizeof(*args), (void **)&res, &pkt); if (cc < sizeof(*res)) { printf("getport: %s", strerror(errno)); errno = EBADRPC; free(pkt); return (-1); } port = (int)ntohl(res->port); free(pkt); rpc_pmap_putcache(d->destip, prog, vers, port); out: #ifdef RPC_DEBUG if (debug) printf("%s: port=%u\n", __func__, port); #endif return (port); } Index: head/stand/ofw/libofw/openfirm.c =================================================================== --- head/stand/ofw/libofw/openfirm.c (revision 330863) +++ head/stand/ofw/libofw/openfirm.c (revision 330864) @@ -1,832 +1,832 @@ /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */ /*- * Copyright (C) 1995, 1996 Wolfgang Solfrank. * Copyright (C) 1995, 1996 TooLs GmbH. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by TooLs GmbH. * 4. The name of TooLs GmbH may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (C) 2000 Benno Rice. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include "openfirm.h" int (*openfirmware)(void *); phandle_t chosen; ihandle_t mmu; ihandle_t memory; int real_mode = 0; /* Initialiser */ void OF_init(int (*openfirm)(void *)) { phandle_t options; char mode[sizeof("true")]; openfirmware = openfirm; if ((chosen = OF_finddevice("/chosen")) == -1) OF_exit(); if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) { memory = OF_open("/memory"); if (memory == -1) memory = OF_open("/memory@0"); if (memory == -1) OF_exit(); } if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1) OF_exit(); /* * Check if we run in real mode. If so, we do not need to map * memory later on. */ options = OF_finddevice("/options"); if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 && strcmp(mode, "true") == 0) real_mode = 1; } /* * Generic functions */ /* Test to see if a service exists. */ int OF_test(char *name) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t service; cell_t missing; } args = { (cell_t)"test", 1, 1, }; args.service = (cell_t)name; if (openfirmware(&args) == -1) return (-1); return (args.missing); } /* Return firmware millisecond count. */ int OF_milliseconds() { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t ms; } args = { (cell_t)"milliseconds", 0, 1, }; openfirmware(&args); return (args.ms); } /* * Device tree functions */ /* Return the next sibling of this node or 0. */ phandle_t OF_peer(phandle_t node) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t node; cell_t next; } args = { (cell_t)"peer", 1, 1, }; args.node = node; if (openfirmware(&args) == -1) return (-1); return (args.next); } /* Return the first child of this node or 0. */ phandle_t OF_child(phandle_t node) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t node; cell_t child; } args = { (cell_t)"child", 1, 1, }; args.node = node; if (openfirmware(&args) == -1) return (-1); return (args.child); } /* Return the parent of this node or 0. */ phandle_t OF_parent(phandle_t node) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t node; cell_t parent; } args = { (cell_t)"parent", 1, 1, }; args.node = node; if (openfirmware(&args) == -1) return (-1); return (args.parent); } /* Return the package handle that corresponds to an instance handle. */ phandle_t OF_instance_to_package(ihandle_t instance) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; cell_t package; } args = { (cell_t)"instance-to-package", 1, 1, }; args.instance = instance; if (openfirmware(&args) == -1) return (-1); return (args.package); } /* Get the length of a property of a package. */ int OF_getproplen(phandle_t package, const char *propname) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t package; cell_t propname; cell_t proplen; } args = { (cell_t)"getproplen", 2, 1, }; args.package = package; args.propname = (cell_t)propname; if (openfirmware(&args) == -1) return (-1); return (args.proplen); } /* Get the value of a property of a package. */ int OF_getprop(phandle_t package, const char *propname, void *buf, int buflen) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t package; cell_t propname; cell_t buf; cell_t buflen; cell_t size; } args = { (cell_t)"getprop", 4, 1, }; args.package = package; args.propname = (cell_t)propname; args.buf = (cell_t)buf; args.buflen = buflen; if (openfirmware(&args) == -1) return (-1); return (args.size); } /* Get the next property of a package. */ int OF_nextprop(phandle_t package, const char *previous, char *buf) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t package; cell_t previous; cell_t buf; cell_t flag; } args = { (cell_t)"nextprop", 3, 1, }; args.package = package; args.previous = (cell_t)previous; args.buf = (cell_t)buf; if (openfirmware(&args) == -1) return (-1); return (args.flag); } /* Set the value of a property of a package. */ /* XXX Has a bug on FirePower */ int OF_setprop(phandle_t package, const char *propname, void *buf, int len) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t package; cell_t propname; cell_t buf; cell_t len; cell_t size; } args = { (cell_t)"setprop", 4, 1, }; args.package = package; args.propname = (cell_t)propname; args.buf = (cell_t)buf; args.len = len; if (openfirmware(&args) == -1) return (-1); return (args.size); } /* Convert a device specifier to a fully qualified pathname. */ int OF_canon(const char *device, char *buf, int len) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t device; cell_t buf; cell_t len; cell_t size; } args = { (cell_t)"canon", 3, 1, }; args.device = (cell_t)device; args.buf = (cell_t)buf; args.len = len; if (openfirmware(&args) == -1) return (-1); return (args.size); } /* Return a package handle for the specified device. */ phandle_t OF_finddevice(const char *device) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t device; cell_t package; } args = { (cell_t)"finddevice", 1, 1, }; args.device = (cell_t)device; if (openfirmware(&args) == -1) return (-1); return (args.package); } /* Return the fully qualified pathname corresponding to an instance. */ int OF_instance_to_path(ihandle_t instance, char *buf, int len) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; cell_t buf; cell_t len; cell_t size; } args = { (cell_t)"instance-to-path", 3, 1, }; args.instance = instance; args.buf = (cell_t)buf; args.len = len; if (openfirmware(&args) == -1) return (-1); return (args.size); } /* Return the fully qualified pathname corresponding to a package. */ int OF_package_to_path(phandle_t package, char *buf, int len) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t package; cell_t buf; cell_t len; cell_t size; } args = { (cell_t)"package-to-path", 3, 1, }; args.package = package; args.buf = (cell_t)buf; args.len = len; if (openfirmware(&args) == -1) return (-1); return (args.size); } /* Call the method in the scope of a given instance. */ int OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) { va_list ap; static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t method; cell_t instance; cell_t args_n_results[12]; } args = { (cell_t)"call-method", 2, 1, }; cell_t *cp; int n; if (nargs > 6) return (-1); args.nargs = nargs + 2; args.nreturns = nreturns + 1; args.method = (cell_t)method; args.instance = instance; va_start(ap, nreturns); for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;) *--cp = va_arg(ap, cell_t); if (openfirmware(&args) == -1) return (-1); if (args.args_n_results[nargs]) return (args.args_n_results[nargs]); for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns)); --n > 0;) *va_arg(ap, cell_t *) = *--cp; va_end(ap); return (0); } /* * Device I/O functions */ /* Open an instance for a device. */ ihandle_t OF_open(char *device) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t device; cell_t instance; } args = { (cell_t)"open", 1, 1, }; args.device = (cell_t)device; if (openfirmware(&args) == -1 || args.instance == 0) { return (-1); } return (args.instance); } /* Close an instance. */ void OF_close(ihandle_t instance) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; } args = { (cell_t)"close", 1, }; args.instance = instance; openfirmware(&args); } /* Read from an instance. */ int OF_read(ihandle_t instance, void *addr, int len) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; cell_t addr; cell_t len; cell_t actual; } args = { (cell_t)"read", 3, 1, }; args.instance = instance; args.addr = (cell_t)addr; args.len = len; #if defined(OPENFIRM_DEBUG) printf("OF_read: called with instance=%08x, addr=%p, len=%d\n", args.instance, args.addr, args.len); #endif if (openfirmware(&args) == -1) return (-1); #if defined(OPENFIRM_DEBUG) printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n", args.instance, args.addr, args.len, args.actual); #endif return (args.actual); } /* Write to an instance. */ int OF_write(ihandle_t instance, void *addr, int len) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; cell_t addr; cell_t len; cell_t actual; } args = { (cell_t)"write", 3, 1, }; args.instance = instance; args.addr = (cell_t)addr; args.len = len; if (openfirmware(&args) == -1) return (-1); return (args.actual); } /* Seek to a position. */ int -OF_seek(ihandle_t instance, u_int64_t pos) +OF_seek(ihandle_t instance, uint64_t pos) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; cell_t poshi; cell_t poslo; cell_t status; } args = { (cell_t)"seek", 3, 1, }; args.instance = instance; args.poshi = pos >> 32; args.poslo = pos; if (openfirmware(&args) == -1) return (-1); return (args.status); } /* Blocks. */ unsigned int OF_blocks(ihandle_t instance) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; cell_t result; cell_t blocks; } args = { (cell_t)"#blocks", 2, 1, }; args.instance = instance; if (openfirmware(&args) == -1) return ((unsigned int)-1); return (args.blocks); } /* Block size. */ int OF_block_size(ihandle_t instance) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t instance; cell_t result; cell_t size; } args = { (cell_t)"block-size", 2, 1, }; args.instance = instance; if (openfirmware(&args) == -1) return (512); return (args.size); } /* /* * Memory functions */ /* Claim an area of memory. */ void * OF_claim(void *virt, u_int size, u_int align) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t virt; cell_t size; cell_t align; cell_t baseaddr; } args = { (cell_t)"claim", 3, 1, }; args.virt = (cell_t)virt; args.size = size; args.align = align; if (openfirmware(&args) == -1) return ((void *)-1); return ((void *)args.baseaddr); } /* Release an area of memory. */ void OF_release(void *virt, u_int size) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t virt; cell_t size; } args = { (cell_t)"release", 2, }; args.virt = (cell_t)virt; args.size = size; openfirmware(&args); } /* * Control transfer functions */ /* Reset the system and call "boot ". */ void OF_boot(char *bootspec) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t bootspec; } args = { (cell_t)"boot", 1, }; args.bootspec = (cell_t)bootspec; openfirmware(&args); for (;;) /* just in case */ ; } /* Suspend and drop back to the Open Firmware interface. */ void OF_enter() { static struct { cell_t name; cell_t nargs; cell_t nreturns; } args = { (cell_t)"enter", }; openfirmware(&args); /* We may come back. */ } /* Shut down and drop back to the Open Firmware interface. */ void OF_exit() { static struct { cell_t name; cell_t nargs; cell_t nreturns; } args = { (cell_t)"exit", }; openfirmware(&args); for (;;) /* just in case */ ; } void OF_quiesce() { static struct { cell_t name; cell_t nargs; cell_t nreturns; } args = { (cell_t)"quiesce", }; openfirmware(&args); } /* Free bytes starting at , then call with . */ #if 0 void OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) { static struct { cell_t name; cell_t nargs; cell_t nreturns; cell_t virt; cell_t size; cell_t entry; cell_t arg; cell_t len; } args = { (cell_t)"chain", 5, }; args.virt = (cell_t)virt; args.size = size; args.entry = (cell_t)entry; args.arg = (cell_t)arg; args.len = len; openfirmware(&args); } #else void OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) { /* * This is a REALLY dirty hack till the firmware gets this going */ #if 0 if (size > 0) OF_release(virt, size); #endif entry(0, 0, openfirmware, arg, len); } #endif Index: head/stand/powerpc/boot1.chrp/boot1.c =================================================================== --- head/stand/powerpc/boot1.chrp/boot1.c (revision 330863) +++ head/stand/powerpc/boot1.chrp/boot1.c (revision 330864) @@ -1,776 +1,776 @@ /*- * Copyright (c) 1998 Robert Nordier * All rights reserved. * Copyright (c) 2001 Robert Drehmel * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "paths.h" #define BSIZEMAX 16384 typedef int putc_func_t(char c, void *arg); typedef int32_t ofwh_t; struct sp_data { char *sp_buf; u_int sp_len; u_int sp_size; }; static const char digits[] = "0123456789abcdef"; static char bootpath[128]; static char bootargs[128]; static ofwh_t bootdev; static struct fs fs; static char blkbuf[BSIZEMAX]; static unsigned int fsblks; static uint32_t fs_off; int main(int ac, char **av); static void exit(int) __dead2; static void load(const char *); -static int dskread(void *, u_int64_t, int); +static int dskread(void *, uint64_t, int); static void usage(void); static void bcopy(const void *src, void *dst, size_t len); static void bzero(void *b, size_t len); static int domount(const char *device, int quiet); static void panic(const char *fmt, ...) __dead2; static int printf(const char *fmt, ...); static int putchar(char c, void *arg); static int vprintf(const char *fmt, va_list ap); static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); static int __putc(char c, void *arg); static int __puts(const char *s, putc_func_t *putc, void *arg); static int __sputc(char c, void *arg); static char *__uitoa(char *buf, u_int val, int base); static char *__ultoa(char *buf, u_long val, int base); /* * Open Firmware interface functions */ -typedef u_int32_t ofwcell_t; -typedef u_int32_t u_ofwh_t; +typedef uint32_t ofwcell_t; +typedef uint32_t u_ofwh_t; typedef int (*ofwfp_t)(void *); ofwfp_t ofw; /* the prom Open Firmware entry */ ofwh_t chosenh; void ofw_init(void *, int, int (*)(void *), char *, int); static ofwh_t ofw_finddevice(const char *); static ofwh_t ofw_open(const char *); static int ofw_close(ofwh_t); static int ofw_getprop(ofwh_t, const char *, void *, size_t); static int ofw_setprop(ofwh_t, const char *, void *, size_t); static int ofw_read(ofwh_t, void *, size_t); static int ofw_write(ofwh_t, const void *, size_t); static int ofw_claim(void *virt, size_t len, u_int align); -static int ofw_seek(ofwh_t, u_int64_t); +static int ofw_seek(ofwh_t, uint64_t); static void ofw_exit(void) __dead2; ofwh_t bootdevh; ofwh_t stdinh, stdouth; __asm(" \n\ .data \n\ .align 4 \n\ stack: \n\ .space 16384 \n\ \n\ .text \n\ .globl _start \n\ _start: \n\ lis %r1,stack@ha \n\ addi %r1,%r1,stack@l \n\ addi %r1,%r1,8192 \n\ \n\ b ofw_init \n\ "); void ofw_init(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl) { char *av[16]; char *p; int ac; ofw = openfirm; chosenh = ofw_finddevice("/chosen"); ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); bootargs[sizeof(bootargs) - 1] = '\0'; bootpath[sizeof(bootpath) - 1] = '\0'; p = bootpath; while (*p != '\0') { /* Truncate partition ID */ if (*p == ':') { ofw_close(bootdev); *(++p) = '\0'; break; } p++; } ac = 0; p = bootargs; for (;;) { while (*p == ' ' && *p != '\0') p++; if (*p == '\0' || ac >= 16) break; av[ac++] = p; while (*p != ' ' && *p != '\0') p++; if (*p != '\0') *p++ = '\0'; } exit(main(ac, av)); } static ofwh_t ofw_finddevice(const char *name) { ofwcell_t args[] = { (ofwcell_t)"finddevice", 1, 1, (ofwcell_t)name, 0 }; if ((*ofw)(args)) { printf("ofw_finddevice: name=\"%s\"\n", name); return (1); } return (args[4]); } static int ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"getprop", 4, 1, (u_ofwh_t)ofwh, (ofwcell_t)name, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", ofwh, buf, len); return (1); } return (0); } static int ofw_setprop(ofwh_t ofwh, const char *name, void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"setprop", 4, 1, (u_ofwh_t)ofwh, (ofwcell_t)name, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_setprop: ofwh=0x%x buf=%p len=%u\n", ofwh, buf, len); return (1); } return (0); } static ofwh_t ofw_open(const char *path) { ofwcell_t args[] = { (ofwcell_t)"open", 1, 1, (ofwcell_t)path, 0 }; if ((*ofw)(args)) { printf("ofw_open: path=\"%s\"\n", path); return (-1); } return (args[4]); } static int ofw_close(ofwh_t devh) { ofwcell_t args[] = { (ofwcell_t)"close", 1, 0, (u_ofwh_t)devh }; if ((*ofw)(args)) { printf("ofw_close: devh=0x%x\n", devh); return (1); } return (0); } static int ofw_claim(void *virt, size_t len, u_int align) { ofwcell_t args[] = { (ofwcell_t)"claim", 3, 1, (ofwcell_t)virt, len, align, 0, 0 }; if ((*ofw)(args)) { printf("ofw_claim: virt=%p len=%u\n", virt, len); return (1); } return (0); } static int ofw_read(ofwh_t devh, void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"read", 3, 1, (u_ofwh_t)devh, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); return (1); } return (0); } static int ofw_write(ofwh_t devh, const void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"write", 3, 1, (u_ofwh_t)devh, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); return (1); } return (0); } static int -ofw_seek(ofwh_t devh, u_int64_t off) +ofw_seek(ofwh_t devh, uint64_t off) { ofwcell_t args[] = { (ofwcell_t)"seek", 3, 1, (u_ofwh_t)devh, off >> 32, off, 0 }; if ((*ofw)(args)) { printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); return (1); } return (0); } static void ofw_exit(void) { ofwcell_t args[3]; args[0] = (ofwcell_t)"exit"; args[1] = 0; args[2] = 0; for (;;) (*ofw)(args); } static void bcopy(const void *src, void *dst, size_t len) { const char *s = src; char *d = dst; while (len-- != 0) *d++ = *s++; } static void memcpy(void *dst, const void *src, size_t len) { bcopy(src, dst, len); } static void bzero(void *b, size_t len) { char *p = b; while (len-- != 0) *p++ = 0; } static int strcmp(const char *s1, const char *s2) { for (; *s1 == *s2 && *s1; s1++, s2++) ; return ((u_char)*s1 - (u_char)*s2); } #include "ufsread.c" int main(int ac, char **av) { const char *path; char bootpath_full[255]; int i, len; path = PATH_LOADER; for (i = 0; i < ac; i++) { switch (av[i][0]) { case '-': switch (av[i][1]) { default: usage(); } break; default: path = av[i]; break; } } printf(" \n>> FreeBSD/powerpc Open Firmware boot block\n" " Boot path: %s\n" " Boot loader: %s\n", bootpath, path); len = 0; while (bootpath[len] != '\0') len++; memcpy(bootpath_full,bootpath,len+1); if (bootpath_full[len-1] != ':') { /* First try full volume */ if (domount(bootpath_full,1) == 0) goto out; /* Add a : so that we try partitions if that fails */ if (bootdev > 0) ofw_close(bootdev); bootpath_full[len] = ':'; len += 1; } /* Loop through first 16 partitions to find a UFS one */ for (i = 0; i < 16; i++) { if (i < 10) { bootpath_full[len] = i + '0'; bootpath_full[len+1] = '\0'; } else { bootpath_full[len] = '1'; bootpath_full[len+1] = i - 10 + '0'; bootpath_full[len+2] = '\0'; } if (domount(bootpath_full,1) >= 0) break; if (bootdev > 0) ofw_close(bootdev); } if (i >= 16) panic("domount"); out: printf(" Boot volume: %s\n",bootpath_full); ofw_setprop(chosenh, "bootargs", bootpath_full, len+2); load(path); return (1); } static void usage(void) { printf("usage: boot device [/path/to/loader]\n"); exit(1); } static void exit(int code) { ofw_exit(); } static struct dmadat __dmadat; static int domount(const char *device, int quiet) { dmadat = &__dmadat; if ((bootdev = ofw_open(device)) == -1) { printf("domount: can't open device\n"); return (-1); } if (fsread(0, NULL, 0)) { if (!quiet) printf("domount: can't read superblock\n"); return (-1); } return (0); } static void load(const char *fname) { Elf32_Ehdr eh; Elf32_Phdr ph; caddr_t p; ufs_ino_t ino; int i; if ((ino = lookup(fname)) == 0) { printf("File %s not found\n", fname); return; } if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) { printf("Can't read elf header\n"); return; } if (!IS_ELF(eh)) { printf("Not an ELF file\n"); return; } for (i = 0; i < eh.e_phnum; i++) { fs_off = eh.e_phoff + i * eh.e_phentsize; if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) { printf("Can't read program header %d\n", i); return; } if (ph.p_type != PT_LOAD) continue; fs_off = ph.p_offset; p = (caddr_t)ph.p_vaddr; ofw_claim(p,(ph.p_filesz > ph.p_memsz) ? ph.p_filesz : ph.p_memsz,0); if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { printf("Can't read content of section %d\n", i); return; } if (ph.p_filesz != ph.p_memsz) bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); __syncicache(p, ph.p_memsz); } ofw_close(bootdev); (*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0, ofw,NULL,0); } static int -dskread(void *buf, u_int64_t lba, int nblk) +dskread(void *buf, uint64_t lba, int nblk) { /* * The Open Firmware should open the correct partition for us. * That means, if we read from offset zero on an open instance handle, * we should read from offset zero of that partition. */ ofw_seek(bootdev, lba * DEV_BSIZE); ofw_read(bootdev, buf, nblk * DEV_BSIZE); return (0); } static void panic(const char *fmt, ...) { char buf[128]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof buf, fmt, ap); printf("panic: %s\n", buf); va_end(ap); exit(1); } static int printf(const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = vprintf(fmt, ap); va_end(ap); return (ret); } static int putchar(char c, void *arg) { char buf; if (c == '\n') { buf = '\r'; ofw_write(stdouth, &buf, 1); } buf = c; ofw_write(stdouth, &buf, 1); return (1); } static int vprintf(const char *fmt, va_list ap) { int ret; ret = __printf(fmt, putchar, 0, ap); return (ret); } static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) { struct sp_data sp; int ret; sp.sp_buf = str; sp.sp_len = 0; sp.sp_size = sz; ret = __printf(fmt, __sputc, &sp, ap); return (ret); } static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) { char buf[(sizeof(long) * 8) + 1]; char *nbuf; u_long ul; u_int ui; int lflag; int sflag; char *s; int pad; int ret; int c; nbuf = &buf[sizeof buf - 1]; ret = 0; while ((c = *fmt++) != 0) { if (c != '%') { ret += putc(c, arg); continue; } lflag = 0; sflag = 0; pad = 0; reswitch: c = *fmt++; switch (c) { case '#': sflag = 1; goto reswitch; case '%': ret += putc('%', arg); break; case 'c': c = va_arg(ap, int); ret += putc(c, arg); break; case 'd': if (lflag == 0) { ui = (u_int)va_arg(ap, int); if (ui < (int)ui) { ui = -ui; ret += putc('-', arg); } s = __uitoa(nbuf, ui, 10); } else { ul = (u_long)va_arg(ap, long); if (ul < (long)ul) { ul = -ul; ret += putc('-', arg); } s = __ultoa(nbuf, ul, 10); } ret += __puts(s, putc, arg); break; case 'l': lflag = 1; goto reswitch; case 'o': if (lflag == 0) { ui = (u_int)va_arg(ap, u_int); s = __uitoa(nbuf, ui, 8); } else { ul = (u_long)va_arg(ap, u_long); s = __ultoa(nbuf, ul, 8); } ret += __puts(s, putc, arg); break; case 'p': ul = (u_long)va_arg(ap, void *); s = __ultoa(nbuf, ul, 16); ret += __puts("0x", putc, arg); ret += __puts(s, putc, arg); break; case 's': s = va_arg(ap, char *); ret += __puts(s, putc, arg); break; case 'u': if (lflag == 0) { ui = va_arg(ap, u_int); s = __uitoa(nbuf, ui, 10); } else { ul = va_arg(ap, u_long); s = __ultoa(nbuf, ul, 10); } ret += __puts(s, putc, arg); break; case 'x': if (lflag == 0) { ui = va_arg(ap, u_int); s = __uitoa(nbuf, ui, 16); } else { ul = va_arg(ap, u_long); s = __ultoa(nbuf, ul, 16); } if (sflag) ret += __puts("0x", putc, arg); ret += __puts(s, putc, arg); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': pad = pad * 10 + c - '0'; goto reswitch; default: break; } } return (ret); } static int __sputc(char c, void *arg) { struct sp_data *sp; sp = arg; if (sp->sp_len < sp->sp_size) sp->sp_buf[sp->sp_len++] = c; sp->sp_buf[sp->sp_len] = '\0'; return (1); } static int __puts(const char *s, putc_func_t *putc, void *arg) { const char *p; int ret; ret = 0; for (p = s; *p != '\0'; p++) ret += putc(*p, arg); return (ret); } static char * __uitoa(char *buf, u_int ui, int base) { char *p; p = buf; *p = '\0'; do *--p = digits[ui % base]; while ((ui /= base) != 0); return (p); } static char * __ultoa(char *buf, u_long ul, int base) { char *p; p = buf; *p = '\0'; do *--p = digits[ul % base]; while ((ul /= base) != 0); return (p); } Index: head/stand/powerpc/kboot/ppc64_elf_freebsd.c =================================================================== --- head/stand/powerpc/kboot/ppc64_elf_freebsd.c (revision 330863) +++ head/stand/powerpc/kboot/ppc64_elf_freebsd.c (revision 330864) @@ -1,171 +1,171 @@ /*- * Copyright (c) 2001 Benno Rice * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #define __ELF_WORD_SIZE 64 #include #include #include #include #include #include #include "bootstrap.h" #include "host_syscall.h" extern char end[]; extern void *kerneltramp; extern size_t szkerneltramp; struct trampoline_data { uint32_t kernel_entry; uint32_t dtb; uint32_t phys_mem_offset; uint32_t of_entry; uint32_t mdp; uint32_t mdp_size; }; vm_offset_t md_load64(char *args, vm_offset_t *modulep, vm_offset_t *dtb); int -ppc64_elf_loadfile(char *filename, u_int64_t dest, +ppc64_elf_loadfile(char *filename, uint64_t dest, struct preloaded_file **result) { int r; r = __elfN(loadfile)(filename, dest, result); if (r != 0) return (r); return (0); } int ppc64_elf_exec(struct preloaded_file *fp) { struct file_metadata *fmp; vm_offset_t mdp, dtb; Elf_Ehdr *e; int error; uint32_t *trampoline; uint64_t entry; uint64_t trampolinebase; struct trampoline_data *trampoline_data; int nseg; void *kseg; if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { return(EFTYPE); } e = (Elf_Ehdr *)&fmp->md_data; /* * Figure out where to put it. * * Linux does not allow to do kexec_load into * any part of memory. Ask arch_loadaddr to * resolve the first available chunk of physical * memory where loading is possible (load_addr). * * Memory organization is shown below. * It is assumed, that text segment offset of * kernel ELF (KERNPHYSADDR) is non-zero, * which is true for PPC/PPC64 architectures, * where default is 0x100000. * * load_addr: trampoline code * load_addr + KERNPHYSADDR: kernel text segment */ trampolinebase = archsw.arch_loadaddr(LOAD_RAW, NULL, 0); printf("Load address at %#jx\n", (uintmax_t)trampolinebase); printf("Relocation offset is %#jx\n", (uintmax_t)elf64_relocation_offset); /* Set up loader trampoline */ trampoline = malloc(szkerneltramp); memcpy(trampoline, &kerneltramp, szkerneltramp); /* Parse function descriptor for ELFv1 kernels */ if ((e->e_flags & 3) == 2) entry = e->e_entry; else { archsw.arch_copyout(e->e_entry + elf64_relocation_offset, &entry, 8); entry = be64toh(entry); } /* * Placeholder for trampoline data is at trampolinebase + 0x08 * CAUTION: all data must be Big Endian */ trampoline_data = (void*)&trampoline[2]; trampoline_data->kernel_entry = htobe32(entry + elf64_relocation_offset); trampoline_data->phys_mem_offset = htobe32(0); trampoline_data->of_entry = htobe32(0); if ((error = md_load64(fp->f_args, &mdp, &dtb)) != 0) return (error); trampoline_data->dtb = htobe32(dtb); trampoline_data->mdp = htobe32(mdp); trampoline_data->mdp_size = htobe32(0xfb5d104d); printf("Kernel entry at %#jx (%#x) ...\n", entry, be32toh(trampoline_data->kernel_entry)); printf("DTB at %#x, mdp at %#x\n", be32toh(trampoline_data->dtb), be32toh(trampoline_data->mdp)); dev_cleanup(); archsw.arch_copyin(trampoline, trampolinebase, szkerneltramp); free(trampoline); if (archsw.arch_kexec_kseg_get == NULL) panic("architecture did not provide kexec segment mapping"); archsw.arch_kexec_kseg_get(&nseg, &kseg); error = kexec_load(trampolinebase, nseg, (uintptr_t)kseg); if (error != 0) panic("kexec_load returned error: %d", error); error = host_reboot(0xfee1dead, 672274793, 0x45584543 /* LINUX_REBOOT_CMD_KEXEC */, (uintptr_t)NULL); if (error != 0) panic("reboot returned error: %d", error); while (1) {} } struct file_format ppc_elf64 = { ppc64_elf_loadfile, ppc64_elf_exec }; Index: head/stand/powerpc/ofw/elf_freebsd.c =================================================================== --- head/stand/powerpc/ofw/elf_freebsd.c (revision 330863) +++ head/stand/powerpc/ofw/elf_freebsd.c (revision 330864) @@ -1,106 +1,106 @@ /*- * Copyright (c) 2001 Benno Rice * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #if defined(__powerpc__) #include #endif #include #include "bootstrap.h" #include "libofw.h" #include "openfirm.h" extern char end[]; extern vm_offset_t reloc; /* From /conf.c */ int -__elfN(ofw_loadfile)(char *filename, u_int64_t dest, +__elfN(ofw_loadfile)(char *filename, uint64_t dest, struct preloaded_file **result) { int r; r = __elfN(loadfile)(filename, dest, result); if (r != 0) return (r); #if defined(__powerpc__) /* * No need to sync the icache for modules: this will * be done by the kernel after relocation. */ if (!strcmp((*result)->f_type, "elf kernel")) __syncicache((void *) (*result)->f_addr, (*result)->f_size); #endif return (0); } int __elfN(ofw_exec)(struct preloaded_file *fp) { struct file_metadata *fmp; vm_offset_t mdp, dtbp; Elf_Ehdr *e; int error; intptr_t entry; if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { return(EFTYPE); } e = (Elf_Ehdr *)&fmp->md_data; entry = e->e_entry; if ((error = md_load(fp->f_args, &mdp, &dtbp)) != 0) return (error); printf("Kernel entry at 0x%lx ...\n", e->e_entry); dev_cleanup(); if (dtbp != 0) { OF_quiesce(); ((int (*)(u_long, u_long, u_long, void *, u_long))entry)(dtbp, 0, 0, (void *)mdp, 0xfb5d104d); } else { OF_chain((void *)reloc, end - (char *)reloc, (void *)entry, (void *)mdp, 0xfb5d104d); } panic("exec returned"); } struct file_format ofw_elf = { __elfN(ofw_loadfile), __elfN(ofw_exec) }; Index: head/stand/powerpc/ofw/main.c =================================================================== --- head/stand/powerpc/ofw/main.c (revision 330863) +++ head/stand/powerpc/ofw/main.c (revision 330864) @@ -1,200 +1,200 @@ /*- * Copyright (c) 2000 Benno Rice * Copyright (c) 2000 Stephane Potvin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include "openfirm.h" #include "libofw.h" #include "bootstrap.h" #include struct arch_switch archsw; /* MI/MD interface boundary */ extern char end[]; extern char bootprog_info[]; -u_int32_t acells, scells; +uint32_t acells, scells; static char bootargs[128]; #define HEAP_SIZE 0x800000 static char heap[HEAP_SIZE]; // In BSS, so uses no space #define OF_puts(fd, text) OF_write(fd, text, strlen(text)) static __inline register_t mfmsr(void) { register_t value; __asm __volatile ("mfmsr %0" : "=r"(value)); return (value); } void init_heap(void) { bzero(heap, HEAP_SIZE); setheap(heap, (void *)((int)heap + HEAP_SIZE)); } uint64_t memsize(void) { phandle_t memoryp; cell_t reg[24]; int i, sz; - u_int64_t memsz; + uint64_t memsz; memsz = 0; memoryp = OF_instance_to_package(memory); sz = OF_getprop(memoryp, "reg", ®, sizeof(reg)); sz /= sizeof(reg[0]); for (i = 0; i < sz; i += (acells + scells)) { if (scells > 1) memsz += (uint64_t)reg[i + acells] << 32; memsz += reg[i + acells + scells - 1]; } return (memsz); } int main(int (*openfirm)(void *)) { phandle_t root; int i; char bootpath[64]; char *ch; int bargc; char **bargv; /* * Initialise the Open Firmware routines by giving them the entry point. */ OF_init(openfirm); root = OF_finddevice("/"); scells = acells = 1; OF_getprop(root, "#address-cells", &acells, sizeof(acells)); OF_getprop(root, "#size-cells", &scells, sizeof(scells)); /* * Initialise the heap as early as possible. Once this is done, * alloc() is usable. The stack is buried inside us, so this is * safe. */ init_heap(); /* * Set up console. */ cons_probe(); /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) if (devsw[i]->dv_init != NULL) (devsw[i]->dv_init)(); printf("\n%s", bootprog_info); printf("Memory: %lldKB\n", memsize() / 1024); OF_getprop(chosen, "bootpath", bootpath, 64); ch = strchr(bootpath, ':'); *ch = '\0'; printf("Booted from: %s\n", bootpath); printf("\n"); /* * Only parse the first bootarg if present. It should * be simple to handle extra arguments */ OF_getprop(chosen, "bootargs", bootargs, sizeof(bootargs)); bargc = 0; parse(&bargc, &bargv, bootargs); if (bargc == 1) env_setenv("currdev", EV_VOLATILE, bargv[0], ofw_setcurrdev, env_nounset); else env_setenv("currdev", EV_VOLATILE, bootpath, ofw_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset, env_nounset); setenv("LINES", "24", 1); /* optional */ /* * On non-Apple hardware, where it works reliably, pass flattened * device trees to the kernel by default instead of OF CI pointers. * Apple hardware is the only virtual-mode OF implementation in * existence, so far as I am aware, so use that as a flag. */ if (!(mfmsr() & PSL_DR)) setenv("usefdt", "1", 1); archsw.arch_getdev = ofw_getdev; archsw.arch_copyin = ofw_copyin; archsw.arch_copyout = ofw_copyout; archsw.arch_readin = ofw_readin; archsw.arch_autoload = ofw_autoload; interact(); /* doesn't return */ OF_exit(); return 0; } COMMAND_SET(halt, "halt", "halt the system", command_halt); static int command_halt(int argc, char *argv[]) { OF_exit(); return (CMD_OK); } COMMAND_SET(memmap, "memmap", "print memory map", command_memmap); int command_memmap(int argc, char **argv) { ofw_memmap(acells); return (CMD_OK); } Index: head/stand/powerpc/ofw/ppc64_elf_freebsd.c =================================================================== --- head/stand/powerpc/ofw/ppc64_elf_freebsd.c (revision 330863) +++ head/stand/powerpc/ofw/ppc64_elf_freebsd.c (revision 330864) @@ -1,110 +1,110 @@ /*- * Copyright (c) 2001 Benno Rice * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #define __ELF_WORD_SIZE 64 #include #include #include #include #include #include #include "bootstrap.h" #include "libofw.h" #include "openfirm.h" extern char end[]; extern vm_offset_t reloc; /* From /conf.c */ int -ppc64_ofw_elf_loadfile(char *filename, u_int64_t dest, +ppc64_ofw_elf_loadfile(char *filename, uint64_t dest, struct preloaded_file **result) { int r; r = __elfN(loadfile)(filename, dest, result); if (r != 0) return (r); /* * No need to sync the icache for modules: this will * be done by the kernel after relocation. */ if (!strcmp((*result)->f_type, "elf kernel")) __syncicache((void *) (*result)->f_addr, (*result)->f_size); return (0); } int ppc64_ofw_elf_exec(struct preloaded_file *fp) { struct file_metadata *fmp; vm_offset_t mdp, dtbp; Elf_Ehdr *e; int error; intptr_t entry; if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) { return(EFTYPE); } e = (Elf_Ehdr *)&fmp->md_data; /* Handle function descriptor for ELFv1 kernels */ if ((e->e_flags & 3) == 2) entry = e->e_entry; else entry = *(uint64_t *)(intptr_t)e->e_entry; if ((error = md_load64(fp->f_args, &mdp, &dtbp)) != 0) return (error); printf("Kernel entry at 0x%lx ...\n", entry); dev_cleanup(); if (dtbp != 0) { OF_quiesce(); ((int (*)(u_long, u_long, u_long, void *, u_long))entry)(dtbp, 0, 0, (void *)mdp, 0xfb5d104d); } else { OF_chain((void *)reloc, end - (char *)reloc, (void *)entry, (void *)mdp, 0xfb5d104d); } panic("exec returned"); } struct file_format ofw_elf64 = { ppc64_ofw_elf_loadfile, ppc64_ofw_elf_exec }; Index: head/stand/sparc64/boot1/boot1.c =================================================================== --- head/stand/sparc64/boot1/boot1.c (revision 330863) +++ head/stand/sparc64/boot1/boot1.c (revision 330864) @@ -1,751 +1,751 @@ /*- * Copyright (c) 1998 Robert Nordier * All rights reserved. * Copyright (c) 2001 Robert Drehmel * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include "paths.h" #define READ_BUF_SIZE 8192 typedef int putc_func_t(char c, void *arg); typedef int32_t ofwh_t; struct sp_data { char *sp_buf; u_int sp_len; u_int sp_size; }; static const char digits[] = "0123456789abcdef"; static char bootpath[128]; static char bootargs[128]; static ofwh_t bootdev; static uint32_t fs_off; int main(int ac, char **av); static void exit(int) __dead2; static void usage(void); #ifdef ZFSBOOT static void loadzfs(void); static int zbread(char *buf, off_t off, size_t bytes); #else static void load(const char *); #endif static void bcopy(const void *src, void *dst, size_t len); static void bzero(void *b, size_t len); static int domount(const char *device); -static int dskread(void *buf, u_int64_t lba, int nblk); +static int dskread(void *buf, uint64_t lba, int nblk); static void panic(const char *fmt, ...) __dead2; static int printf(const char *fmt, ...); static int putchar(char c, void *arg); static int vprintf(const char *fmt, va_list ap); static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); static int __puts(const char *s, putc_func_t *putc, void *arg); static int __sputc(char c, void *arg); static char *__uitoa(char *buf, u_int val, int base); static char *__ultoa(char *buf, u_long val, int base); /* * Open Firmware interface functions */ -typedef u_int64_t ofwcell_t; -typedef u_int32_t u_ofwh_t; +typedef uint64_t ofwcell_t; +typedef uint32_t u_ofwh_t; typedef int (*ofwfp_t)(ofwcell_t []); static ofwfp_t ofw; /* the PROM Open Firmware entry */ void ofw_init(int, int, int, int, ofwfp_t); static ofwh_t ofw_finddevice(const char *); static ofwh_t ofw_open(const char *); static int ofw_getprop(ofwh_t, const char *, void *, size_t); static int ofw_read(ofwh_t, void *, size_t); static int ofw_write(ofwh_t, const void *, size_t); -static int ofw_seek(ofwh_t, u_int64_t); +static int ofw_seek(ofwh_t, uint64_t); static void ofw_exit(void) __dead2; static ofwh_t stdinh, stdouth; /* * This has to stay here, as the PROM seems to ignore the * entry point specified in the a.out header. (or elftoaout is broken) */ void ofw_init(int d, int d1, int d2, int d3, ofwfp_t ofwaddr) { ofwh_t chosenh; char *av[16]; char *p; int ac; ofw = ofwaddr; chosenh = ofw_finddevice("/chosen"); ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh)); ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth)); ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs)); ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath)); bootargs[sizeof(bootargs) - 1] = '\0'; bootpath[sizeof(bootpath) - 1] = '\0'; ac = 0; p = bootargs; for (;;) { while (*p == ' ' && *p != '\0') p++; if (*p == '\0' || ac >= 16) break; av[ac++] = p; while (*p != ' ' && *p != '\0') p++; if (*p != '\0') *p++ = '\0'; } exit(main(ac, av)); } static ofwh_t ofw_finddevice(const char *name) { ofwcell_t args[] = { (ofwcell_t)"finddevice", 1, 1, (ofwcell_t)name, 0 }; if ((*ofw)(args)) { printf("ofw_finddevice: name=\"%s\"\n", name); return (1); } return (args[4]); } static int ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"getprop", 4, 1, (u_ofwh_t)ofwh, (ofwcell_t)name, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n", ofwh, buf, len); return (1); } return (0); } static ofwh_t ofw_open(const char *path) { ofwcell_t args[] = { (ofwcell_t)"open", 1, 1, (ofwcell_t)path, 0 }; if ((*ofw)(args)) { printf("ofw_open: path=\"%s\"\n", path); return (-1); } return (args[4]); } static int ofw_close(ofwh_t devh) { ofwcell_t args[] = { (ofwcell_t)"close", 1, 0, (u_ofwh_t)devh }; if ((*ofw)(args)) { printf("ofw_close: devh=0x%x\n", devh); return (1); } return (0); } static int ofw_read(ofwh_t devh, void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"read", 3, 1, (u_ofwh_t)devh, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len); return (1); } return (0); } static int ofw_write(ofwh_t devh, const void *buf, size_t len) { ofwcell_t args[] = { (ofwcell_t)"write", 3, 1, (u_ofwh_t)devh, (ofwcell_t)buf, len, 0 }; if ((*ofw)(args)) { printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len); return (1); } return (0); } static int -ofw_seek(ofwh_t devh, u_int64_t off) +ofw_seek(ofwh_t devh, uint64_t off) { ofwcell_t args[] = { (ofwcell_t)"seek", 3, 1, (u_ofwh_t)devh, off >> 32, off, 0 }; if ((*ofw)(args)) { printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off); return (1); } return (0); } static void ofw_exit(void) { ofwcell_t args[3]; args[0] = (ofwcell_t)"exit"; args[1] = 0; args[2] = 0; for (;;) (*ofw)(args); } static void bcopy(const void *src, void *dst, size_t len) { const char *s = src; char *d = dst; while (len-- != 0) *d++ = *s++; } static void memcpy(void *dst, const void *src, size_t len) { bcopy(src, dst, len); } static void bzero(void *b, size_t len) { char *p = b; while (len-- != 0) *p++ = 0; } static int strcmp(const char *s1, const char *s2) { for (; *s1 == *s2 && *s1; s1++, s2++) ; return ((u_char)*s1 - (u_char)*s2); } int main(int ac, char **av) { const char *path; int i; path = PATH_LOADER; for (i = 0; i < ac; i++) { switch (av[i][0]) { case '-': switch (av[i][1]) { default: usage(); } break; default: path = av[i]; break; } } #ifdef ZFSBOOT printf(" \n>> FreeBSD/sparc64 ZFS boot block\n Boot path: %s\n", bootpath); #else printf(" \n>> FreeBSD/sparc64 boot block\n Boot path: %s\n" " Boot loader: %s\n", bootpath, path); #endif if (domount(bootpath) == -1) panic("domount"); #ifdef ZFSBOOT loadzfs(); #else load(path); #endif return (1); } static void usage(void) { printf("usage: boot device [/path/to/loader]\n"); exit(1); } static void exit(int code) { ofw_exit(); } #ifdef ZFSBOOT #define VDEV_BOOT_OFFSET (2 * 256 * 1024) static char zbuf[READ_BUF_SIZE]; static int zbread(char *buf, off_t off, size_t bytes) { size_t len; off_t poff; off_t soff; char *p; unsigned int nb; unsigned int lb; p = buf; soff = VDEV_BOOT_OFFSET + off; lb = howmany(soff + bytes, DEV_BSIZE); poff = soff; while (poff < soff + bytes) { nb = lb - poff / DEV_BSIZE; if (nb > READ_BUF_SIZE / DEV_BSIZE) nb = READ_BUF_SIZE / DEV_BSIZE; if (dskread(zbuf, poff / DEV_BSIZE, nb)) break; if ((poff / DEV_BSIZE + nb) * DEV_BSIZE > soff + bytes) len = soff + bytes - poff; else len = (poff / DEV_BSIZE + nb) * DEV_BSIZE - poff; memcpy(p, zbuf + poff % DEV_BSIZE, len); p += len; poff += len; } return (poff - soff); } static void loadzfs(void) { Elf64_Ehdr eh; Elf64_Phdr ph; caddr_t p; int i; if (zbread((char *)&eh, 0, sizeof(eh)) != sizeof(eh)) { printf("Can't read elf header\n"); return; } if (!IS_ELF(eh)) { printf("Not an ELF file\n"); return; } for (i = 0; i < eh.e_phnum; i++) { fs_off = eh.e_phoff + i * eh.e_phentsize; if (zbread((char *)&ph, fs_off, sizeof(ph)) != sizeof(ph)) { printf("Can't read program header %d\n", i); return; } if (ph.p_type != PT_LOAD) continue; fs_off = ph.p_offset; p = (caddr_t)ph.p_vaddr; if (zbread(p, fs_off, ph.p_filesz) != ph.p_filesz) { printf("Can't read content of section %d\n", i); return; } if (ph.p_filesz != ph.p_memsz) bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); } ofw_close(bootdev); (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } #else #include "ufsread.c" static struct dmadat __dmadat; static void load(const char *fname) { Elf64_Ehdr eh; Elf64_Phdr ph; caddr_t p; ufs_ino_t ino; int i; if ((ino = lookup(fname)) == 0) { printf("File %s not found\n", fname); return; } if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) { printf("Can't read elf header\n"); return; } if (!IS_ELF(eh)) { printf("Not an ELF file\n"); return; } for (i = 0; i < eh.e_phnum; i++) { fs_off = eh.e_phoff + i * eh.e_phentsize; if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) { printf("Can't read program header %d\n", i); return; } if (ph.p_type != PT_LOAD) continue; fs_off = ph.p_offset; p = (caddr_t)ph.p_vaddr; if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) { printf("Can't read content of section %d\n", i); return; } if (ph.p_filesz != ph.p_memsz) bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz); } ofw_close(bootdev); (*(void (*)(int, int, int, int, ofwfp_t))eh.e_entry)(0, 0, 0, 0, ofw); } #endif /* ZFSBOOT */ static int domount(const char *device) { if ((bootdev = ofw_open(device)) == -1) { printf("domount: can't open device\n"); return (-1); } #ifndef ZFSBOOT dmadat = &__dmadat; if (fsread(0, NULL, 0)) { printf("domount: can't read superblock\n"); return (-1); } #endif return (0); } static int -dskread(void *buf, u_int64_t lba, int nblk) +dskread(void *buf, uint64_t lba, int nblk) { /* * The Open Firmware should open the correct partition for us. * That means, if we read from offset zero on an open instance handle, * we should read from offset zero of that partition. */ ofw_seek(bootdev, lba * DEV_BSIZE); ofw_read(bootdev, buf, nblk * DEV_BSIZE); return (0); } static void panic(const char *fmt, ...) { char buf[128]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof buf, fmt, ap); printf("panic: %s\n", buf); va_end(ap); exit(1); } static int printf(const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = vprintf(fmt, ap); va_end(ap); return (ret); } static int putchar(char c, void *arg) { char buf; if (c == '\n') { buf = '\r'; ofw_write(stdouth, &buf, 1); } buf = c; ofw_write(stdouth, &buf, 1); return (1); } static int vprintf(const char *fmt, va_list ap) { int ret; ret = __printf(fmt, putchar, 0, ap); return (ret); } static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) { struct sp_data sp; int ret; sp.sp_buf = str; sp.sp_len = 0; sp.sp_size = sz; ret = __printf(fmt, __sputc, &sp, ap); return (ret); } static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) { char buf[(sizeof(long) * 8) + 1]; char *nbuf; u_long ul; u_int ui; int lflag; int sflag; char *s; int pad; int ret; int c; nbuf = &buf[sizeof buf - 1]; ret = 0; while ((c = *fmt++) != 0) { if (c != '%') { ret += putc(c, arg); continue; } lflag = 0; sflag = 0; pad = 0; reswitch: c = *fmt++; switch (c) { case '#': sflag = 1; goto reswitch; case '%': ret += putc('%', arg); break; case 'c': c = va_arg(ap, int); ret += putc(c, arg); break; case 'd': if (lflag == 0) { ui = (u_int)va_arg(ap, int); if (ui < (int)ui) { ui = -ui; ret += putc('-', arg); } s = __uitoa(nbuf, ui, 10); } else { ul = (u_long)va_arg(ap, long); if (ul < (long)ul) { ul = -ul; ret += putc('-', arg); } s = __ultoa(nbuf, ul, 10); } ret += __puts(s, putc, arg); break; case 'l': lflag = 1; goto reswitch; case 'o': if (lflag == 0) { ui = (u_int)va_arg(ap, u_int); s = __uitoa(nbuf, ui, 8); } else { ul = (u_long)va_arg(ap, u_long); s = __ultoa(nbuf, ul, 8); } ret += __puts(s, putc, arg); break; case 'p': ul = (u_long)va_arg(ap, void *); s = __ultoa(nbuf, ul, 16); ret += __puts("0x", putc, arg); ret += __puts(s, putc, arg); break; case 's': s = va_arg(ap, char *); ret += __puts(s, putc, arg); break; case 'u': if (lflag == 0) { ui = va_arg(ap, u_int); s = __uitoa(nbuf, ui, 10); } else { ul = va_arg(ap, u_long); s = __ultoa(nbuf, ul, 10); } ret += __puts(s, putc, arg); break; case 'x': if (lflag == 0) { ui = va_arg(ap, u_int); s = __uitoa(nbuf, ui, 16); } else { ul = va_arg(ap, u_long); s = __ultoa(nbuf, ul, 16); } if (sflag) ret += __puts("0x", putc, arg); ret += __puts(s, putc, arg); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': pad = pad * 10 + c - '0'; goto reswitch; default: break; } } return (ret); } static int __sputc(char c, void *arg) { struct sp_data *sp; sp = arg; if (sp->sp_len < sp->sp_size) sp->sp_buf[sp->sp_len++] = c; sp->sp_buf[sp->sp_len] = '\0'; return (1); } static int __puts(const char *s, putc_func_t *putc, void *arg) { const char *p; int ret; ret = 0; for (p = s; *p != '\0'; p++) ret += putc(*p, arg); return (ret); } static char * __uitoa(char *buf, u_int ui, int base) { char *p; p = buf; *p = '\0'; do *--p = digits[ui % base]; while ((ui /= base) != 0); return (p); } static char * __ultoa(char *buf, u_long ul, int base) { char *p; p = buf; *p = '\0'; do *--p = digits[ul % base]; while ((ul /= base) != 0); return (p); } Index: head/stand/sparc64/loader/main.c =================================================================== --- head/stand/sparc64/loader/main.c (revision 330863) +++ head/stand/sparc64/loader/main.c (revision 330864) @@ -1,988 +1,988 @@ /*- * Initial implementation: * Copyright (c) 2001 Robert Drehmel * All rights reserved. * * As long as the above copyright statement and this notice remain * unchanged, you can do what ever you want with this file. */ /*- * Copyright (c) 2008 - 2012 Marius Strobl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * FreeBSD/sparc64 kernel loader - machine dependent part * * - implements copyin and readin functions that map kernel * pages on demand. The machine independent code does not * know the size of the kernel early enough to pre-enter * TTEs and install just one 4MB mapping seemed to limiting * to me. */ #include #include #include #include #include #include #ifdef LOADER_ZFS_SUPPORT #include #include "../zfs/libzfs.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "bootstrap.h" #include "libofw.h" #include "dev_net.h" extern char bootprog_info[]; enum { HEAPVA = 0x800000, HEAPSZ = 0x1000000, LOADSZ = 0x1000000 /* for kernel and modules */ }; /* At least Sun Fire V1280 require page sized allocations to be claimed. */ CTASSERT(HEAPSZ % PAGE_SIZE == 0); static struct mmu_ops { void (*tlb_init)(void); int (*mmu_mapin)(vm_offset_t va, vm_size_t len); } *mmu_ops; typedef void kernel_entry_t(vm_offset_t mdp, u_long o1, u_long o2, u_long o3, void *openfirmware); static inline u_long dtlb_get_data_sun4u(u_int, u_int); static int dtlb_enter_sun4u(u_int, u_long data, vm_offset_t); static vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t); static inline u_long itlb_get_data_sun4u(u_int, u_int); static int itlb_enter_sun4u(u_int, u_long data, vm_offset_t); static vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t); static void itlb_relocate_locked0_sun4u(void); static int sparc64_autoload(void); static ssize_t sparc64_readin(const int, vm_offset_t, const size_t); static ssize_t sparc64_copyin(const void *, vm_offset_t, size_t); static vm_offset_t claim_virt(vm_offset_t, size_t, int); static vm_offset_t alloc_phys(size_t, int); static int map_phys(int, size_t, vm_offset_t, vm_offset_t); static void release_phys(vm_offset_t, u_int); static int __elfN(exec)(struct preloaded_file *); static int mmu_mapin_sun4u(vm_offset_t, vm_size_t); static vm_offset_t init_heap(void); static phandle_t find_bsp_sun4u(phandle_t, uint32_t); const char *cpu_cpuid_prop_sun4u(void); uint32_t cpu_get_mid_sun4u(void); static void tlb_init_sun4u(void); #ifdef LOADER_DEBUG -typedef u_int64_t tte_t; +typedef uint64_t tte_t; static void pmap_print_tlb_sun4u(void); static void pmap_print_tte_sun4u(tte_t, tte_t); #endif static struct mmu_ops mmu_ops_sun4u = { tlb_init_sun4u, mmu_mapin_sun4u }; /* sun4u */ struct tlb_entry *dtlb_store; struct tlb_entry *itlb_store; u_int dtlb_slot; u_int itlb_slot; static int cpu_impl; static u_int dtlb_slot_max; static u_int itlb_slot_max; static u_int tlb_locked; static vm_offset_t curkva = 0; static vm_offset_t heapva; static char bootpath[64]; static phandle_t root; #ifdef LOADER_ZFS_SUPPORT static struct zfs_devdesc zfs_currdev; #endif /* * Machine dependent structures that the machine independent * loader part uses. */ struct devsw *devsw[] = { #ifdef LOADER_DISK_SUPPORT &ofwdisk, #endif #ifdef LOADER_NET_SUPPORT &netdev, #endif #ifdef LOADER_ZFS_SUPPORT &zfs_dev, #endif NULL }; struct arch_switch archsw; static struct file_format sparc64_elf = { __elfN(loadfile), __elfN(exec) }; struct file_format *file_formats[] = { &sparc64_elf, NULL }; struct fs_ops *file_system[] = { #ifdef LOADER_ZFS_SUPPORT &zfs_fsops, #endif #ifdef LOADER_UFS_SUPPORT &ufs_fsops, #endif #ifdef LOADER_CD9660_SUPPORT &cd9660_fsops, #endif #ifdef LOADER_ZIP_SUPPORT &zipfs_fsops, #endif #ifdef LOADER_GZIP_SUPPORT &gzipfs_fsops, #endif #ifdef LOADER_BZIP2_SUPPORT &bzipfs_fsops, #endif #ifdef LOADER_NFS_SUPPORT &nfs_fsops, #endif #ifdef LOADER_TFTP_SUPPORT &tftp_fsops, #endif NULL }; struct netif_driver *netif_drivers[] = { #ifdef LOADER_NET_SUPPORT &ofwnet, #endif NULL }; extern struct console ofwconsole; struct console *consoles[] = { &ofwconsole, NULL }; #ifdef LOADER_DEBUG static int watch_phys_set_mask(vm_offset_t pa, u_long mask) { u_long lsucr; stxa(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3)); lsucr = ldxa(0, ASI_LSU_CTL_REG); lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) | (mask << LSU_PM_SHIFT); stxa(0, ASI_LSU_CTL_REG, lsucr); return (0); } static int watch_phys_set(vm_offset_t pa, int sz) { u_long off; off = (u_long)pa & 7; /* Test for misaligned watch points. */ if (off + sz > 8) return (-1); return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off)); } static int watch_virt_set_mask(vm_offset_t va, u_long mask) { u_long lsucr; stxa(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3)); lsucr = ldxa(0, ASI_LSU_CTL_REG); lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) | (mask << LSU_VM_SHIFT); stxa(0, ASI_LSU_CTL_REG, lsucr); return (0); } static int watch_virt_set(vm_offset_t va, int sz) { u_long off; off = (u_long)va & 7; /* Test for misaligned watch points. */ if (off + sz > 8) return (-1); return (watch_virt_set_mask(va, ((1 << sz) - 1) << off)); } #endif /* * archsw functions */ static int sparc64_autoload(void) { return (0); } static ssize_t sparc64_readin(const int fd, vm_offset_t va, const size_t len) { mmu_ops->mmu_mapin(va, len); return (read(fd, (void *)va, len)); } static ssize_t sparc64_copyin(const void *src, vm_offset_t dest, size_t len) { mmu_ops->mmu_mapin(dest, len); memcpy((void *)dest, src, len); return (len); } /* * other MD functions */ static vm_offset_t claim_virt(vm_offset_t virt, size_t size, int align) { vm_offset_t mva; if (OF_call_method("claim", mmu, 3, 1, virt, size, align, &mva) == -1) return ((vm_offset_t)-1); return (mva); } static vm_offset_t alloc_phys(size_t size, int align) { cell_t phys_hi, phys_low; if (OF_call_method("claim", memory, 2, 2, size, align, &phys_low, &phys_hi) == -1) return ((vm_offset_t)-1); return ((vm_offset_t)phys_hi << 32 | phys_low); } static int map_phys(int mode, size_t size, vm_offset_t virt, vm_offset_t phys) { return (OF_call_method("map", mmu, 5, 0, (uint32_t)phys, (uint32_t)(phys >> 32), virt, size, mode)); } static void release_phys(vm_offset_t phys, u_int size) { (void)OF_call_method("release", memory, 3, 0, (uint32_t)phys, (uint32_t)(phys >> 32), size); } static int __elfN(exec)(struct preloaded_file *fp) { struct file_metadata *fmp; vm_offset_t mdp, dtbp; Elf_Addr entry; Elf_Ehdr *e; int error; if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == 0) return (EFTYPE); e = (Elf_Ehdr *)&fmp->md_data; if ((error = md_load(fp->f_args, &mdp, &dtbp)) != 0) return (error); printf("jumping to kernel entry at %#lx.\n", e->e_entry); #ifdef LOADER_DEBUG pmap_print_tlb_sun4u(); #endif dev_cleanup(); entry = e->e_entry; OF_release((void *)heapva, HEAPSZ); ((kernel_entry_t *)entry)(mdp, 0, 0, 0, openfirmware); panic("%s: exec returned", __func__); } static inline u_long dtlb_get_data_sun4u(u_int tlb, u_int slot) { u_long data, pstate; slot = TLB_DAR_SLOT(tlb, slot); /* * We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to * work around errata of USIII and beyond. */ pstate = rdpr(pstate); wrpr(pstate, pstate & ~PSTATE_IE, 0); (void)ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); data = ldxa(slot, ASI_DTLB_DATA_ACCESS_REG); wrpr(pstate, pstate, 0); return (data); } static inline u_long itlb_get_data_sun4u(u_int tlb, u_int slot) { u_long data, pstate; slot = TLB_DAR_SLOT(tlb, slot); /* * We read ASI_DTLB_DATA_ACCESS_REG twice back-to-back in order to * work around errata of USIII and beyond. */ pstate = rdpr(pstate); wrpr(pstate, pstate & ~PSTATE_IE, 0); (void)ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); data = ldxa(slot, ASI_ITLB_DATA_ACCESS_REG); wrpr(pstate, pstate, 0); return (data); } static vm_offset_t dtlb_va_to_pa_sun4u(vm_offset_t va) { u_long pstate, reg; u_int i, tlb; pstate = rdpr(pstate); wrpr(pstate, pstate & ~PSTATE_IE, 0); for (i = 0; i < dtlb_slot_max; i++) { reg = ldxa(TLB_DAR_SLOT(tlb_locked, i), ASI_DTLB_TAG_READ_REG); if (TLB_TAR_VA(reg) != va) continue; reg = dtlb_get_data_sun4u(tlb_locked, i); wrpr(pstate, pstate, 0); reg >>= TD_PA_SHIFT; if (cpu_impl == CPU_IMPL_SPARC64V || cpu_impl >= CPU_IMPL_ULTRASPARCIII) return (reg & TD_PA_CH_MASK); return (reg & TD_PA_SF_MASK); } wrpr(pstate, pstate, 0); return (-1); } static vm_offset_t itlb_va_to_pa_sun4u(vm_offset_t va) { u_long pstate, reg; int i; pstate = rdpr(pstate); wrpr(pstate, pstate & ~PSTATE_IE, 0); for (i = 0; i < itlb_slot_max; i++) { reg = ldxa(TLB_DAR_SLOT(tlb_locked, i), ASI_ITLB_TAG_READ_REG); if (TLB_TAR_VA(reg) != va) continue; reg = itlb_get_data_sun4u(tlb_locked, i); wrpr(pstate, pstate, 0); reg >>= TD_PA_SHIFT; if (cpu_impl == CPU_IMPL_SPARC64V || cpu_impl >= CPU_IMPL_ULTRASPARCIII) return (reg & TD_PA_CH_MASK); return (reg & TD_PA_SF_MASK); } wrpr(pstate, pstate, 0); return (-1); } static int dtlb_enter_sun4u(u_int index, u_long data, vm_offset_t virt) { return (OF_call_method("SUNW,dtlb-load", mmu, 3, 0, index, data, virt)); } static int itlb_enter_sun4u(u_int index, u_long data, vm_offset_t virt) { if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp && index == 0 && (data & TD_L) != 0) panic("%s: won't enter locked TLB entry at index 0 on USIII+", __func__); return (OF_call_method("SUNW,itlb-load", mmu, 3, 0, index, data, virt)); } static void itlb_relocate_locked0_sun4u(void) { u_long data, pstate, tag; int i; if (cpu_impl != CPU_IMPL_ULTRASPARCIIIp) return; pstate = rdpr(pstate); wrpr(pstate, pstate & ~PSTATE_IE, 0); data = itlb_get_data_sun4u(tlb_locked, 0); if ((data & (TD_V | TD_L)) != (TD_V | TD_L)) { wrpr(pstate, pstate, 0); return; } /* Flush the mapping of slot 0. */ tag = ldxa(TLB_DAR_SLOT(tlb_locked, 0), ASI_ITLB_TAG_READ_REG); stxa(TLB_DEMAP_VA(TLB_TAR_VA(tag)) | TLB_DEMAP_PRIMARY | TLB_DEMAP_PAGE, ASI_IMMU_DEMAP, 0); flush(0); /* The USIII-family ignores the address. */ /* * Search a replacement slot != 0 and enter the data and tag * that formerly were in slot 0. */ for (i = 1; i < itlb_slot_max; i++) { if ((itlb_get_data_sun4u(tlb_locked, i) & TD_V) != 0) continue; stxa(AA_IMMU_TAR, ASI_IMMU, tag); stxa(TLB_DAR_SLOT(tlb_locked, i), ASI_ITLB_DATA_ACCESS_REG, data); flush(0); /* The USIII-family ignores the address. */ break; } wrpr(pstate, pstate, 0); if (i == itlb_slot_max) panic("%s: could not find a replacement slot", __func__); } static int mmu_mapin_sun4u(vm_offset_t va, vm_size_t len) { vm_offset_t pa, mva; u_long data; u_int index; if (va + len > curkva) curkva = va + len; pa = (vm_offset_t)-1; len += va & PAGE_MASK_4M; va &= ~PAGE_MASK_4M; while (len) { if (dtlb_va_to_pa_sun4u(va) == (vm_offset_t)-1 || itlb_va_to_pa_sun4u(va) == (vm_offset_t)-1) { /* Allocate a physical page, claim the virtual area. */ if (pa == (vm_offset_t)-1) { pa = alloc_phys(PAGE_SIZE_4M, PAGE_SIZE_4M); if (pa == (vm_offset_t)-1) panic("%s: out of memory", __func__); mva = claim_virt(va, PAGE_SIZE_4M, 0); if (mva != va) panic("%s: can't claim virtual page " "(wanted %#lx, got %#lx)", __func__, va, mva); /* * The mappings may have changed, be paranoid. */ continue; } /* * Actually, we can only allocate two pages less at * most (depending on the kernel TSB size). */ if (dtlb_slot >= dtlb_slot_max) panic("%s: out of dtlb_slots", __func__); if (itlb_slot >= itlb_slot_max) panic("%s: out of itlb_slots", __func__); data = TD_V | TD_4M | TD_PA(pa) | TD_L | TD_CP | TD_CV | TD_P | TD_W; dtlb_store[dtlb_slot].te_pa = pa; dtlb_store[dtlb_slot].te_va = va; index = dtlb_slot_max - dtlb_slot - 1; if (dtlb_enter_sun4u(index, data, va) < 0) panic("%s: can't enter dTLB slot %d data " "%#lx va %#lx", __func__, index, data, va); dtlb_slot++; itlb_store[itlb_slot].te_pa = pa; itlb_store[itlb_slot].te_va = va; index = itlb_slot_max - itlb_slot - 1; if (itlb_enter_sun4u(index, data, va) < 0) panic("%s: can't enter iTLB slot %d data " "%#lx va %#lxd", __func__, index, data, va); itlb_slot++; pa = (vm_offset_t)-1; } len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len; va += PAGE_SIZE_4M; } if (pa != (vm_offset_t)-1) release_phys(pa, PAGE_SIZE_4M); return (0); } static vm_offset_t init_heap(void) { /* There is no need for continuous physical heap memory. */ heapva = (vm_offset_t)OF_claim((void *)HEAPVA, HEAPSZ, 32); return (heapva); } static phandle_t find_bsp_sun4u(phandle_t node, uint32_t bspid) { char type[sizeof("cpu")]; phandle_t child; uint32_t cpuid; for (; node > 0; node = OF_peer(node)) { child = OF_child(node); if (child > 0) { child = find_bsp_sun4u(child, bspid); if (child > 0) return (child); } else { if (OF_getprop(node, "device_type", type, sizeof(type)) <= 0) continue; if (strcmp(type, "cpu") != 0) continue; if (OF_getprop(node, cpu_cpuid_prop_sun4u(), &cpuid, sizeof(cpuid)) <= 0) continue; if (cpuid == bspid) return (node); } } return (0); } const char * cpu_cpuid_prop_sun4u(void) { switch (cpu_impl) { case CPU_IMPL_SPARC64: case CPU_IMPL_SPARC64V: case CPU_IMPL_ULTRASPARCI: case CPU_IMPL_ULTRASPARCII: case CPU_IMPL_ULTRASPARCIIi: case CPU_IMPL_ULTRASPARCIIe: return ("upa-portid"); case CPU_IMPL_ULTRASPARCIII: case CPU_IMPL_ULTRASPARCIIIp: case CPU_IMPL_ULTRASPARCIIIi: case CPU_IMPL_ULTRASPARCIIIip: return ("portid"); case CPU_IMPL_ULTRASPARCIV: case CPU_IMPL_ULTRASPARCIVp: return ("cpuid"); default: return (""); } } uint32_t cpu_get_mid_sun4u(void) { switch (cpu_impl) { case CPU_IMPL_SPARC64: case CPU_IMPL_SPARC64V: case CPU_IMPL_ULTRASPARCI: case CPU_IMPL_ULTRASPARCII: case CPU_IMPL_ULTRASPARCIIi: case CPU_IMPL_ULTRASPARCIIe: return (UPA_CR_GET_MID(ldxa(0, ASI_UPA_CONFIG_REG))); case CPU_IMPL_ULTRASPARCIII: case CPU_IMPL_ULTRASPARCIIIp: return (FIREPLANE_CR_GET_AID(ldxa(AA_FIREPLANE_CONFIG, ASI_FIREPLANE_CONFIG_REG))); case CPU_IMPL_ULTRASPARCIIIi: case CPU_IMPL_ULTRASPARCIIIip: return (JBUS_CR_GET_JID(ldxa(0, ASI_JBUS_CONFIG_REG))); case CPU_IMPL_ULTRASPARCIV: case CPU_IMPL_ULTRASPARCIVp: return (INTR_ID_GET_ID(ldxa(AA_INTR_ID, ASI_INTR_ID))); default: return (0); } } static void tlb_init_sun4u(void) { phandle_t bsp; cpu_impl = VER_IMPL(rdpr(ver)); switch (cpu_impl) { case CPU_IMPL_SPARC64: case CPU_IMPL_ULTRASPARCI: case CPU_IMPL_ULTRASPARCII: case CPU_IMPL_ULTRASPARCIIi: case CPU_IMPL_ULTRASPARCIIe: tlb_locked = TLB_DAR_T32; break; case CPU_IMPL_ULTRASPARCIII: case CPU_IMPL_ULTRASPARCIIIp: case CPU_IMPL_ULTRASPARCIIIi: case CPU_IMPL_ULTRASPARCIIIip: case CPU_IMPL_ULTRASPARCIV: case CPU_IMPL_ULTRASPARCIVp: tlb_locked = TLB_DAR_T16; break; case CPU_IMPL_SPARC64V: tlb_locked = TLB_DAR_FTLB; break; } bsp = find_bsp_sun4u(OF_child(root), cpu_get_mid_sun4u()); if (bsp == 0) panic("%s: no node for bootcpu?!?!", __func__); if (OF_getprop(bsp, "#dtlb-entries", &dtlb_slot_max, sizeof(dtlb_slot_max)) == -1 || OF_getprop(bsp, "#itlb-entries", &itlb_slot_max, sizeof(itlb_slot_max)) == -1) panic("%s: can't get TLB slot max.", __func__); if (cpu_impl == CPU_IMPL_ULTRASPARCIIIp) { #ifdef LOADER_DEBUG printf("pre fixup:\n"); pmap_print_tlb_sun4u(); #endif /* * Relocate the locked entry in it16 slot 0 (if existent) * as part of working around Cheetah+ erratum 34. */ itlb_relocate_locked0_sun4u(); #ifdef LOADER_DEBUG printf("post fixup:\n"); pmap_print_tlb_sun4u(); #endif } dtlb_store = malloc(dtlb_slot_max * sizeof(*dtlb_store)); itlb_store = malloc(itlb_slot_max * sizeof(*itlb_store)); if (dtlb_store == NULL || itlb_store == NULL) panic("%s: can't allocate TLB store", __func__); } #ifdef LOADER_ZFS_SUPPORT static void sparc64_zfs_probe(void) { struct vtoc8 vtoc; char alias[64], devname[sizeof(alias) + sizeof(":x") - 1]; char type[sizeof("device_type")]; char *bdev, *dev, *odev; uint64_t guid, *guidp; int fd, len, part; phandle_t aliases, options; guid = 0; /* * Get the GUIDs of the ZFS pools on any additional disks listed in * the boot-device environment variable. */ if ((aliases = OF_finddevice("/aliases")) == -1) goto out; options = OF_finddevice("/options"); len = OF_getproplen(options, "boot-device"); if (len <= 0) goto out; bdev = odev = malloc(len + 1); if (bdev == NULL) goto out; if (OF_getprop(options, "boot-device", bdev, len) <= 0) goto out; bdev[len] = '\0'; while ((dev = strsep(&bdev, " ")) != NULL) { if (*dev == '\0') continue; strcpy(alias, dev); (void)OF_getprop(aliases, dev, alias, sizeof(alias)); if (OF_getprop(OF_finddevice(alias), "device_type", type, sizeof(type)) == -1) continue; if (strcmp(type, "block") != 0) continue; /* Find freebsd-zfs slices in the VTOC. */ fd = open(alias, O_RDONLY); if (fd == -1) continue; lseek(fd, 0, SEEK_SET); if (read(fd, &vtoc, sizeof(vtoc)) != sizeof(vtoc)) { close(fd); continue; } close(fd); for (part = 0; part < 8; part++) { if (part == 2 || vtoc.part[part].tag != VTOC_TAG_FREEBSD_ZFS) continue; (void)sprintf(devname, "%s:%c", alias, part + 'a'); /* Get the GUID of the ZFS pool on the boot device. */ if (strcmp(devname, bootpath) == 0) guidp = &guid; else guidp = NULL; if (zfs_probe_dev(devname, guidp) == ENXIO) break; } } free(odev); out: if (guid != 0) { zfs_currdev.pool_guid = guid; zfs_currdev.root_guid = 0; zfs_currdev.dd.d_dev = &zfs_dev; } } #endif /* LOADER_ZFS_SUPPORT */ int main(int (*openfirm)(void *)) { char compatible[32]; struct devsw **dp; /* * Tell the Open Firmware functions where they find the OFW gate. */ OF_init(openfirm); archsw.arch_getdev = ofw_getdev; archsw.arch_copyin = sparc64_copyin; archsw.arch_copyout = ofw_copyout; archsw.arch_readin = sparc64_readin; archsw.arch_autoload = sparc64_autoload; #ifdef LOADER_ZFS_SUPPORT archsw.arch_zfs_probe = sparc64_zfs_probe; #endif if (init_heap() == (vm_offset_t)-1) OF_exit(); setheap((void *)heapva, (void *)(heapva + HEAPSZ)); /* * Probe for a console. */ cons_probe(); if ((root = OF_peer(0)) == -1) panic("%s: can't get root phandle", __func__); OF_getprop(root, "compatible", compatible, sizeof(compatible)); mmu_ops = &mmu_ops_sun4u; mmu_ops->tlb_init(); /* * Set up the current device. */ OF_getprop(chosen, "bootpath", bootpath, sizeof(bootpath)); /* * Initialize devices. */ for (dp = devsw; *dp != NULL; dp++) if ((*dp)->dv_init != 0) (*dp)->dv_init(); #ifdef LOADER_ZFS_SUPPORT if (zfs_currdev.pool_guid != 0) { (void)strncpy(bootpath, zfs_fmtdev(&zfs_currdev), sizeof(bootpath) - 1); bootpath[sizeof(bootpath) - 1] = '\0'; } else #endif /* * Sun compatible bootable CD-ROMs have a disk label placed before * the ISO 9660 data, with the actual file system being in the first * partition, while the other partitions contain pseudo disk labels * with embedded boot blocks for different architectures, which may * be followed by UFS file systems. * The firmware will set the boot path to the partition it boots from * ('f' in the sun4u/sun4v case), but we want the kernel to be loaded * from the ISO 9660 file system ('a'), so the boot path needs to be * altered. */ if (bootpath[strlen(bootpath) - 2] == ':' && bootpath[strlen(bootpath) - 1] == 'f') bootpath[strlen(bootpath) - 1] = 'a'; env_setenv("currdev", EV_VOLATILE, bootpath, ofw_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset, env_nounset); printf("\n%s", bootprog_info); printf("bootpath=\"%s\"\n", bootpath); /* Give control to the machine independent loader code. */ interact(); return (1); } COMMAND_SET(heap, "heap", "show heap usage", command_heap); static int command_heap(int argc, char *argv[]) { mallocstats(); printf("heap base at %p, top at %p, upper limit at %p\n", heapva, sbrk(0), heapva + HEAPSZ); return(CMD_OK); } COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int command_reboot(int argc, char *argv[]) { int i; for (i = 0; devsw[i] != NULL; ++i) if (devsw[i]->dv_cleanup != NULL) (devsw[i]->dv_cleanup)(); printf("Rebooting...\n"); OF_exit(); } /* provide this for panic, as it's not in the startup code */ void exit(int code) { OF_exit(); } #ifdef LOADER_DEBUG static const char *const page_sizes[] = { " 8k", " 64k", "512k", " 4m" }; static void pmap_print_tte_sun4u(tte_t tag, tte_t tte) { printf("%s %s ", page_sizes[(tte >> TD_SIZE_SHIFT) & TD_SIZE_MASK], tag & TD_G ? "G" : " "); printf(tte & TD_W ? "W " : " "); printf(tte & TD_P ? "\e[33mP\e[0m " : " "); printf(tte & TD_E ? "E " : " "); printf(tte & TD_CV ? "CV " : " "); printf(tte & TD_CP ? "CP " : " "); printf(tte & TD_L ? "\e[32mL\e[0m " : " "); printf(tte & TD_IE ? "IE " : " "); printf(tte & TD_NFO ? "NFO " : " "); printf("pa=0x%lx va=0x%lx ctx=%ld\n", TD_PA(tte), TLB_TAR_VA(tag), TLB_TAR_CTX(tag)); } static void pmap_print_tlb_sun4u(void) { tte_t tag, tte; u_long pstate; int i; pstate = rdpr(pstate); for (i = 0; i < itlb_slot_max; i++) { wrpr(pstate, pstate & ~PSTATE_IE, 0); tte = itlb_get_data_sun4u(tlb_locked, i); wrpr(pstate, pstate, 0); if (!(tte & TD_V)) continue; tag = ldxa(TLB_DAR_SLOT(tlb_locked, i), ASI_ITLB_TAG_READ_REG); printf("iTLB-%2u: ", i); pmap_print_tte_sun4u(tag, tte); } for (i = 0; i < dtlb_slot_max; i++) { wrpr(pstate, pstate & ~PSTATE_IE, 0); tte = dtlb_get_data_sun4u(tlb_locked, i); wrpr(pstate, pstate, 0); if (!(tte & TD_V)) continue; tag = ldxa(TLB_DAR_SLOT(tlb_locked, i), ASI_DTLB_TAG_READ_REG); printf("dTLB-%2u: ", i); pmap_print_tte_sun4u(tag, tte); } } #endif Index: head/stand/uboot/lib/elf_freebsd.c =================================================================== --- head/stand/uboot/lib/elf_freebsd.c (revision 330863) +++ head/stand/uboot/lib/elf_freebsd.c (revision 330864) @@ -1,100 +1,100 @@ /*- * Copyright (c) 2001 Benno Rice * Copyright (c) 2007 Semihalf, Rafal Jaworowski * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #ifdef __mips__ #include #include #endif #include #include #include #include #include "bootstrap.h" #include "libuboot.h" extern vm_offset_t md_load(char *, vm_offset_t *, vm_offset_t *); int -__elfN(uboot_load)(char *filename, u_int64_t dest, +__elfN(uboot_load)(char *filename, uint64_t dest, struct preloaded_file **result) { int r; r = __elfN(loadfile)(filename, dest, result); if (r != 0) return (r); #if defined(__powerpc__) /* * No need to sync the icache for modules: this will * be done by the kernel after relocation. */ if (!strcmp((*result)->f_type, "elf kernel")) __syncicache((void *) (*result)->f_addr, (*result)->f_size); #endif return (0); } int __elfN(uboot_exec)(struct preloaded_file *fp) { struct file_metadata *fmp; vm_offset_t mdp; Elf_Ehdr *e; int error; void (*entry)(void *); if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return (EFTYPE); e = (Elf_Ehdr *)&fmp->md_data; if ((error = md_load(fp->f_args, &mdp, NULL)) != 0) return (error); entry = (void *)e->e_entry; printf("Kernel entry at %p...\n", entry); dev_cleanup(); printf("Kernel args: %s\n", fp->f_args); (*entry)((void *)mdp); panic("exec returned"); } struct file_format uboot_elf = { __elfN(uboot_load), __elfN(uboot_exec) }; Index: head/stand/userboot/userboot/bootinfo32.c =================================================================== --- head/stand/userboot/userboot/bootinfo32.c (revision 330863) +++ head/stand/userboot/userboot/bootinfo32.c (revision 330864) @@ -1,262 +1,262 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "bootstrap.h" #include "libuserboot.h" static struct bootinfo bi; /* * Copy module-related data into the load area, where it can be * used as a directory for loaded modules. * * Module data is presented in a self-describing format. Each datum * is preceded by a 32-bit identifier and a 32-bit size field. * * Currently, the following data are saved: * * MOD_NAME (variable) module name (string) * MOD_TYPE (variable) module type (string) * MOD_ARGS (variable) module parameters (string) * MOD_ADDR sizeof(vm_offset_t) module load address * MOD_SIZE sizeof(size_t) module size * MOD_METADATA (variable) type-specific metadata */ #define COPY32(v, a, c) { \ - u_int32_t x = (v); \ + uint32_t x = (v); \ if (c) \ CALLBACK(copyin, &x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c); \ if (c) \ CALLBACK(copyin, s, a, strlen(s) + 1); \ a += roundup(strlen(s) + 1, sizeof(uint32_t));\ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ CALLBACK(copyin, &s, a, sizeof(s)); \ a += roundup(sizeof(s), sizeof(uint32_t)); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c); \ COPY32(mm->md_size, a, c); \ if (c) \ CALLBACK(copyin, mm->md_data, a, mm->md_size); \ a += roundup(mm->md_size, sizeof(uint32_t));\ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t bi_copymodules32(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; int c; c = addr != 0; /* start with the first module on the list, should be the kernel */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { MOD_NAME(addr, fp->f_name, c); /* this field must come first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); MOD_ADDR(addr, fp->f_addr, c); MOD_SIZE(addr, fp->f_size, c); for (md = fp->f_metadata; md != NULL; md = md->md_next) if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md, c); } MOD_END(addr, c); return(addr); } /* * Load the information expected by an i386 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernendp) { struct preloaded_file *xp, *kfp; struct i386_devdesc *rootdev; struct file_metadata *md; vm_offset_t addr; vm_offset_t kernend; vm_offset_t envp; vm_offset_t size; vm_offset_t ssym, esym; char *rootdevname; int bootdevnr, howto; char *kernelname; const char *kernelpath; uint64_t lowmem, highmem; howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); userboot_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(userboot_fmtdev((void *)rootdev)); bootdevnr = 0; #if 0 if (bootdevnr == -1) { printf("root device %s invalid\n", i386_fmtdev(rootdev)); return (EINVAL); } #endif free(rootdev); /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* copy our environment */ envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf32 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); bios_addsmapdata(kfp); /* Figure out the size and location of the metadata */ *modulep = addr; size = bi_copymodules32(0); kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* copy module list and metadata */ (void)bi_copymodules32(addr); ssym = esym = 0; md = file_findmetadata(kfp, MODINFOMD_SSYM); if (md != NULL) ssym = *((vm_offset_t *)&(md->md_data)); md = file_findmetadata(kfp, MODINFOMD_ESYM); if (md != NULL) esym = *((vm_offset_t *)&(md->md_data)); if (ssym == 0 || esym == 0) ssym = esym = 0; /* sanity */ /* legacy bootinfo structure */ kernelname = getenv("kernelname"); userboot_getdev(NULL, kernelname, &kernelpath); bi.bi_version = BOOTINFO_VERSION; bi.bi_kernelname = 0; /* XXX char * -> kernel name */ bi.bi_nfs_diskless = 0; /* struct nfs_diskless * */ bi.bi_n_bios_used = 0; /* XXX would have to hook biosdisk driver for these */ #if 0 for (i = 0; i < N_BIOS_GEOM; i++) bi.bi_bios_geom[i] = bd_getbigeom(i); #endif bi.bi_size = sizeof(bi); CALLBACK(getmem, &lowmem, &highmem); bi.bi_memsizes_valid = 1; bi.bi_basemem = 640; bi.bi_extmem = (lowmem - 0x100000) / 1024; bi.bi_envp = envp; bi.bi_modulep = *modulep; bi.bi_kernend = kernend; bi.bi_symtab = ssym; /* XXX this is only the primary kernel symtab */ bi.bi_esymtab = esym; /* * Copy the legacy bootinfo and kernel name to the guest at 0x2000 */ bi.bi_kernelname = 0x2000 + sizeof(bi); CALLBACK(copyin, &bi, 0x2000, sizeof(bi)); CALLBACK(copyin, kernelname, 0x2000 + sizeof(bi), strlen(kernelname) + 1); /* legacy boot arguments */ *howtop = howto | RB_BOOTINFO; *bootdevp = bootdevnr; *bip = 0x2000; return(0); } Index: head/stand/userboot/userboot/bootinfo64.c =================================================================== --- head/stand/userboot/userboot/bootinfo64.c (revision 330863) +++ head/stand/userboot/userboot/bootinfo64.c (revision 330864) @@ -1,257 +1,257 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include "bootstrap.h" #include "libuserboot.h" /* * Copy module-related data into the load area, where it can be * used as a directory for loaded modules. * * Module data is presented in a self-describing format. Each datum * is preceded by a 32-bit identifier and a 32-bit size field. * * Currently, the following data are saved: * * MOD_NAME (variable) module name (string) * MOD_TYPE (variable) module type (string) * MOD_ARGS (variable) module parameters (string) * MOD_ADDR sizeof(vm_offset_t) module load address * MOD_SIZE sizeof(size_t) module size * MOD_METADATA (variable) type-specific metadata */ #define COPY32(v, a, c) { \ - u_int32_t x = (v); \ + uint32_t x = (v); \ if (c) \ CALLBACK(copyin, &x, a, sizeof(x)); \ a += sizeof(x); \ } #define MOD_STR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(strlen(s) + 1, a, c); \ if (c) \ CALLBACK(copyin, s, a, strlen(s) + 1); \ - a += roundup(strlen(s) + 1, sizeof(u_int64_t));\ + a += roundup(strlen(s) + 1, sizeof(uint64_t));\ } #define MOD_NAME(a, s, c) MOD_STR(MODINFO_NAME, a, s, c) #define MOD_TYPE(a, s, c) MOD_STR(MODINFO_TYPE, a, s, c) #define MOD_ARGS(a, s, c) MOD_STR(MODINFO_ARGS, a, s, c) #define MOD_VAR(t, a, s, c) { \ COPY32(t, a, c); \ COPY32(sizeof(s), a, c); \ if (c) \ CALLBACK(copyin, &s, a, sizeof(s)); \ - a += roundup(sizeof(s), sizeof(u_int64_t)); \ + a += roundup(sizeof(s), sizeof(uint64_t)); \ } #define MOD_ADDR(a, s, c) MOD_VAR(MODINFO_ADDR, a, s, c) #define MOD_SIZE(a, s, c) MOD_VAR(MODINFO_SIZE, a, s, c) #define MOD_METADATA(a, mm, c) { \ COPY32(MODINFO_METADATA | mm->md_type, a, c); \ COPY32(mm->md_size, a, c); \ if (c) \ CALLBACK(copyin, mm->md_data, a, mm->md_size); \ - a += roundup(mm->md_size, sizeof(u_int64_t));\ + a += roundup(mm->md_size, sizeof(uint64_t));\ } #define MOD_END(a, c) { \ COPY32(MODINFO_END, a, c); \ COPY32(0, a, c); \ } static vm_offset_t bi_copymodules64(vm_offset_t addr) { struct preloaded_file *fp; struct file_metadata *md; int c; - u_int64_t v; + uint64_t v; c = addr != 0; /* start with the first module on the list, should be the kernel */ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) { MOD_NAME(addr, fp->f_name, c); /* this field must come first */ MOD_TYPE(addr, fp->f_type, c); if (fp->f_args) MOD_ARGS(addr, fp->f_args, c); v = fp->f_addr; MOD_ADDR(addr, v, c); v = fp->f_size; MOD_SIZE(addr, v, c); for (md = fp->f_metadata; md != NULL; md = md->md_next) if (!(md->md_type & MODINFOMD_NOCOPY)) MOD_METADATA(addr, md, c); } MOD_END(addr, c); return(addr); } /* * Check to see if this CPU supports long mode. */ static int bi_checkcpu(void) { #if 0 char *cpu_vendor; int vendor[3]; int eflags, regs[4]; /* Check for presence of "cpuid". */ eflags = read_eflags(); write_eflags(eflags ^ PSL_ID); if (!((eflags ^ read_eflags()) & PSL_ID)) return (0); /* Fetch the vendor string. */ do_cpuid(0, regs); vendor[0] = regs[1]; vendor[1] = regs[3]; vendor[2] = regs[2]; cpu_vendor = (char *)vendor; /* Check for vendors that support AMD features. */ if (strncmp(cpu_vendor, INTEL_VENDOR_ID, 12) != 0 && strncmp(cpu_vendor, AMD_VENDOR_ID, 12) != 0 && strncmp(cpu_vendor, CENTAUR_VENDOR_ID, 12) != 0) return (0); /* Has to support AMD features. */ do_cpuid(0x80000000, regs); if (!(regs[0] >= 0x80000001)) return (0); /* Check for long mode. */ do_cpuid(0x80000001, regs); return (regs[3] & AMDID_LM); #else return (1); #endif } /* * Load the information expected by an amd64 kernel. * * - The 'boothowto' argument is constructed * - The 'bootdev' argument is constructed * - The 'bootinfo' struct is constructed, and copied into the kernel space. * - The kernel environment is copied into kernel space. * - Module metadata are formatted and placed in kernel space. */ int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp) { struct preloaded_file *xp, *kfp; struct userboot_devdesc *rootdev; struct file_metadata *md; vm_offset_t addr; - u_int64_t kernend; - u_int64_t envp; + uint64_t kernend; + uint64_t envp; vm_offset_t size; char *rootdevname; int howto; if (!bi_checkcpu()) { printf("CPU doesn't support long mode\n"); return (EINVAL); } howto = bi_getboothowto(args); /* * Allow the environment variable 'rootdev' to override the supplied device * This should perhaps go to MI code and/or have $rootdev tested/set by * MI code before launching the kernel. */ rootdevname = getenv("rootdev"); userboot_getdev((void **)(&rootdev), rootdevname, NULL); if (rootdev == NULL) { /* bad $rootdev/$currdev */ printf("can't determine root device\n"); return(EINVAL); } /* Try reading the /etc/fstab file to select the root device */ getrootmount(userboot_fmtdev((void *)rootdev)); /* find the last module in the chain */ addr = 0; for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) { if (addr < (xp->f_addr + xp->f_size)) addr = xp->f_addr + xp->f_size; } /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); /* copy our environment */ envp = addr; addr = bi_copyenv(addr); /* pad to a page boundary */ addr = roundup(addr, PAGE_SIZE); kfp = file_findfile(NULL, "elf kernel"); if (kfp == NULL) kfp = file_findfile(NULL, "elf64 kernel"); if (kfp == NULL) panic("can't find kernel file"); kernend = 0; /* fill it in later */ file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto); file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp); file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend); bios_addsmapdata(kfp); /* Figure out the size and location of the metadata */ *modulep = addr; size = bi_copymodules64(0); kernend = roundup(addr + size, PAGE_SIZE); *kernendp = kernend; /* patch MODINFOMD_KERNEND */ md = file_findmetadata(kfp, MODINFOMD_KERNEND); bcopy(&kernend, md->md_data, sizeof kernend); /* copy module list and metadata */ (void)bi_copymodules64(addr); return(0); } Index: head/stand/userboot/userboot/elf64_freebsd.c =================================================================== --- head/stand/userboot/userboot/elf64_freebsd.c (revision 330863) +++ head/stand/userboot/userboot/elf64_freebsd.c (revision 330864) @@ -1,172 +1,172 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #define __ELF_WORD_SIZE 64 #include #include #include #include #include #include #include #include "bootstrap.h" #include "libuserboot.h" static int elf64_exec(struct preloaded_file *amp); static int elf64_obj_exec(struct preloaded_file *amp); struct file_format amd64_elf = { elf64_loadfile, elf64_exec }; struct file_format amd64_elf_obj = { elf64_obj_loadfile, elf64_obj_exec }; #define MSR_EFER 0xc0000080 #define EFER_LME 0x00000100 #define EFER_LMA 0x00000400 /* Long mode active (R) */ #define CR4_PAE 0x00000020 #define CR4_VMXE (1UL << 13) #define CR4_PSE 0x00000010 #define CR0_PG 0x80000000 #define CR0_PE 0x00000001 /* Protected mode Enable */ #define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ #define PG_V 0x001 #define PG_RW 0x002 #define PG_U 0x004 #define PG_PS 0x080 -typedef u_int64_t p4_entry_t; -typedef u_int64_t p3_entry_t; -typedef u_int64_t p2_entry_t; +typedef uint64_t p4_entry_t; +typedef uint64_t p3_entry_t; +typedef uint64_t p2_entry_t; #define GUEST_NULL_SEL 0 #define GUEST_CODE_SEL 1 #define GUEST_DATA_SEL 2 #define GUEST_GDTR_LIMIT (3 * 8 - 1) static void setup_freebsd_gdt(uint64_t *gdtr) { gdtr[GUEST_NULL_SEL] = 0; gdtr[GUEST_CODE_SEL] = 0x0020980000000000; gdtr[GUEST_DATA_SEL] = 0x0000900000000000; } /* * There is an ELF kernel and one or more ELF modules loaded. * We wish to start executing the kernel image, so make such * preparations as are required, and do so. */ static int elf64_exec(struct preloaded_file *fp) { struct file_metadata *md; Elf_Ehdr *ehdr; vm_offset_t modulep, kernend; int err; int i; uint32_t stack[1024]; p4_entry_t PT4[512]; p3_entry_t PT3[512]; p2_entry_t PT2[512]; uint64_t gdtr[3]; if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); ehdr = (Elf_Ehdr *)&(md->md_data); err = bi_load64(fp->f_args, &modulep, &kernend); if (err != 0) return(err); bzero(PT4, PAGE_SIZE); bzero(PT3, PAGE_SIZE); bzero(PT2, PAGE_SIZE); /* * Build a scratch stack at physical 0x1000, page tables: * PT4 at 0x2000, * PT3 at 0x3000, * PT2 at 0x4000, * gdtr at 0x5000, */ /* * This is kinda brutal, but every single 1GB VM memory segment * points to the same first 1GB of physical memory. But it is * more than adequate. */ for (i = 0; i < 512; i++) { /* Each slot of the level 4 pages points to the same level 3 page */ PT4[i] = (p4_entry_t) 0x3000; PT4[i] |= PG_V | PG_RW | PG_U; /* Each slot of the level 3 pages points to the same level 2 page */ PT3[i] = (p3_entry_t) 0x4000; PT3[i] |= PG_V | PG_RW | PG_U; /* The level 2 page slots are mapped with 2MB pages for 1GB. */ PT2[i] = i * (2 * 1024 * 1024); PT2[i] |= PG_V | PG_RW | PG_PS | PG_U; } #ifdef DEBUG printf("Start @ %#llx ...\n", ehdr->e_entry); #endif dev_cleanup(); stack[0] = 0; /* return address */ stack[1] = modulep; stack[2] = kernend; CALLBACK(copyin, stack, 0x1000, sizeof(stack)); CALLBACK(copyin, PT4, 0x2000, sizeof(PT4)); CALLBACK(copyin, PT3, 0x3000, sizeof(PT3)); CALLBACK(copyin, PT2, 0x4000, sizeof(PT2)); CALLBACK(setreg, 4, 0x1000); CALLBACK(setmsr, MSR_EFER, EFER_LMA | EFER_LME); CALLBACK(setcr, 4, CR4_PAE | CR4_VMXE); CALLBACK(setcr, 3, 0x2000); CALLBACK(setcr, 0, CR0_PG | CR0_PE | CR0_NE); setup_freebsd_gdt(gdtr); CALLBACK(copyin, gdtr, 0x5000, sizeof(gdtr)); CALLBACK(setgdt, 0x5000, sizeof(gdtr)); CALLBACK(exec, ehdr->e_entry); panic("exec returned"); } static int elf64_obj_exec(struct preloaded_file *fp) { return (EFTYPE); }