diff options
author | Tom Cosgrove <tom@cvs.openbsd.org> | 2004-03-21 21:37:42 +0000 |
---|---|---|
committer | Tom Cosgrove <tom@cvs.openbsd.org> | 2004-03-21 21:37:42 +0000 |
commit | b6bedfcd017a291b7e736a57597a5dbeb552cd1d (patch) | |
tree | 149286d1847005927bde0e9a93f2efa1c1a6278a /sys/arch/amd64/stand/pxeboot | |
parent | 8c6e84988022919eccc722f39a6b132f873506d7 (diff) |
Enter pxeboot on amd64. Initially intended to support network installs
using bsd.rd over TFTP.
ok deraadt@
Diffstat (limited to 'sys/arch/amd64/stand/pxeboot')
-rw-r--r-- | sys/arch/amd64/stand/pxeboot/Makefile | 66 | ||||
-rw-r--r-- | sys/arch/amd64/stand/pxeboot/conf.c | 127 | ||||
-rw-r--r-- | sys/arch/amd64/stand/pxeboot/devopen.c | 217 | ||||
-rw-r--r-- | sys/arch/amd64/stand/pxeboot/net.c | 290 | ||||
-rw-r--r-- | sys/arch/amd64/stand/pxeboot/open.c | 136 | ||||
-rw-r--r-- | sys/arch/amd64/stand/pxeboot/pxeboot.8 | 187 | ||||
-rw-r--r-- | sys/arch/amd64/stand/pxeboot/srt0.S | 223 |
7 files changed, 1246 insertions, 0 deletions
diff --git a/sys/arch/amd64/stand/pxeboot/Makefile b/sys/arch/amd64/stand/pxeboot/Makefile new file mode 100644 index 00000000000..f41cb437009 --- /dev/null +++ b/sys/arch/amd64/stand/pxeboot/Makefile @@ -0,0 +1,66 @@ +# $OpenBSD: Makefile,v 1.1 2004/03/21 21:37:41 tom Exp $ + +.include "${.CURDIR}/../Makefile.inc" + +MAN= pxeboot.8 + +.if ${MACHINE} == "amd64" +S =${.CURDIR}/../../../.. +SADIR= ${.CURDIR}/.. + +PROG= pxeboot +SRCS= srt0.S conf.c devopen.c net.c open.c +LD?= ld +SIZE?= size +LDFLAGS+=-melf_i386 -nostdlib -Bstatic -Ttext $(LINKADDR) -N -x -noinhibit-exec +INSTALL_STRIP= + +.PATH: ${SADIR}/libsa +# i386 stuff (so, it will possibly load in the same 64k) +SRCS+= machdep.c exec_i386.c cmd_i386.c +SRCS+= gidt.S alloca.S biosdev.c bioscons.c gateA20.c \ + memprobe.c diskprobe.c time.c biosprobe.c +SRCS+= pxe.c pxe_call.S pxe_net.c + +.PATH: ${S}/stand/boot +SRCS+= boot.c cmd.c vars.c bootarg.c + +.PATH: ${S}/lib/libsa +.PATH: ${S}/lib/libkern # for strl* +# stand routines +SRCS+= alloc.c exit.c getfile.c gets.c globals.c strcmp.c strlen.c \ + strncmp.c memcmp.c memcpy.c memset.c printf.c snprintf.c \ + strerror.c strncpy.c strtol.c ctime.c strlcpy.c strlcat.c +# io routines +SRCS+= close.c closeall.c dev.c disklabel.c dkcksum.c fstat.c ioctl.c lseek.c \ + read.c stat.c write.c cread.c readdir.c cons.c loadfile.c +# network routines +SRCS+= ether.c netif.c rpc.c +# network info services +SRCS+= bootp.c bootparam.c +# boot filesystems +SRCS+= ufs.c nfs.c tftp.c + +.PATH: ${S}/lib/libz +SRCS+= adler32.c crc32.c inflate.c inftrees.c + +${PROG}: $(OBJS) + $(LD) $(LDFLAGS) -o ${PROG} $(OBJS) + @if [ -x ${.OBJDIR}/${PROG} ]; then \ + objcopy -O binary ${PROG} ${.OBJDIR}/.tmp;\ + mv -f ${.OBJDIR}/.tmp ${.OBJDIR}/${PROG}; \ + ls -l ${.OBJDIR}/${PROG}; \ + fi + +.else +NOPROG= +.endif + +.include <bsd.prog.mk> + +CPPFLAGS+=-DBOOTMAGIC=$(BOOTMAGIC) ${DEBUGFLAGS} -DLINKADDR=${LINKADDR} +CPPFLAGS+=-DSLOW -DSMALL -DNOBYFOUR -DNO_GZIP -DDYNAMIC_CRC_TABLE +CPPFLAGS+=-DHEAP_LIMIT=${HEAP_LIMIT} -I${S}/stand/boot #-DCOMPAT_UFS +CFLAGS+=-m32 $(SACFLAGS) -D__INTERNAL_LIBSA_CREAD +AFLAGS+=-m32 # -Wa,-R +# AFLAGS+=-Wa,-a diff --git a/sys/arch/amd64/stand/pxeboot/conf.c b/sys/arch/amd64/stand/pxeboot/conf.c new file mode 100644 index 00000000000..4344babdf2a --- /dev/null +++ b/sys/arch/amd64/stand/pxeboot/conf.c @@ -0,0 +1,127 @@ +/* $OpenBSD: conf.c,v 1.1 2004/03/21 21:37:41 tom Exp $ */ + +/* + * Copyright (c) 2004 Tom Cosgrove + * Copyright (c) 1996 Michael Shalayeff + * 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 ``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. + * + */ + +#include <sys/types.h> +#include <netinet/in.h> +#include <libsa.h> +#include <lib/libsa/ufs.h> +#ifdef notdef +#include <lib/libsa/cd9660.h> +#include <lib/libsa/fat.h> +#endif +#include <lib/libsa/nfs.h> +#include <lib/libsa/tftp.h> +#include <lib/libsa/netif.h> +#include <lib/libsa/unixdev.h> +#include <biosdev.h> +#include <dev/cons.h> +#include "pxeboot.h" +#include "pxe_net.h" + +const char version[] = "1.00"; +int debug = 0; + +#undef _TEST + + +void (*sa_cleanup)(void) = pxe_shutdown; + + +void (*i386_probe1[])(void) = { + gateA20on, cninit, pxeprobe, memprobe +}; +void (*i386_probe2[])(void) = { + diskprobe +}; +void (*i386_probe3[])(void) = { + pxeinfo +/* netprobe_pxe, netprobe_mac, netprobe_inet4, netprobe_bootdev */ +}; + +struct i386_boot_probes probe_list[] = { + { "probing", i386_probe1, NENTS(i386_probe1) }, + { "disk", i386_probe2, NENTS(i386_probe2) }, + { "net", i386_probe3, NENTS(i386_probe3) }, +}; +int nibprobes = NENTS(probe_list); + +/* This next list must match file_system[]. */ +char *fs_name[] = { + NULL, "tftp", "nfs" +}; +int nfsname = NENTS(fs_name); + +struct fs_ops file_system[] = { + { ufs_open, ufs_close, ufs_read, ufs_write, ufs_seek, + ufs_stat, ufs_readdir }, + { tftp_open, tftp_close, tftp_read, tftp_write, tftp_seek, + tftp_stat, tftp_readdir }, + { nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, + nfs_stat, nfs_readdir }, +#ifdef notdef + { fat_open, fat_close, fat_read, fat_write, fat_seek, + fat_stat, fat_readdir }, + { cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek, + cd9660_stat, cd9660_readdir }, +#endif +#ifdef _TEST + { null_open, null_close, null_read, null_write, null_seek, + null_stat, null_readdir } +#endif +}; +int nfsys = NENTS(file_system); + +struct devsw devsw[] = { +#ifdef _TEST + { "UNIX", unixstrategy, unixopen, unixclose, unixioctl }, +#else + { "BIOS", biosstrategy, biosopen, biosclose, biosioctl }, +#endif +}; +int ndevs = NENTS(devsw); + +struct devsw netsw[] = { + { "net", net_strategy, net_open, net_close, net_ioctl }, +}; + +struct netif_driver *netif_drivers[] = { +}; +int n_netif_drivers = NENTS(netif_drivers); + +struct consdev constab[] = { +#ifdef _TEST + { unix_probe, unix_init, unix_getc, unix_putc }, +#else + { pc_probe, pc_init, pc_getc, pc_putc }, + { com_probe, com_init, com_getc, com_putc }, +#endif + { NULL } +}; +struct consdev *cn_tab = constab; diff --git a/sys/arch/amd64/stand/pxeboot/devopen.c b/sys/arch/amd64/stand/pxeboot/devopen.c new file mode 100644 index 00000000000..264edfecab9 --- /dev/null +++ b/sys/arch/amd64/stand/pxeboot/devopen.c @@ -0,0 +1,217 @@ +/* $OpenBSD: devopen.c,v 1.1 2004/03/21 21:37:41 tom Exp $ */ + +/* + * Copyright (c) 1994 Tom Cosgrove + * Copyright (c) 1996-1999 Michael Shalayeff + * 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 ``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 HIS RELATIVES 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 MIND, 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 "libsa.h" +#include "biosdev.h" +#include <sys/param.h> +#include <dev/cons.h> + +extern int debug; + +extern char *fs_name[]; +extern int nfsname; +extern struct devsw netsw[]; + +/* XXX use slot for 'rd' for 'hd' pseudo-device */ +const char bdevs[][4] = { + "wd", "", "fd", "wt", "sd", "st", "cd", "mcd", + "", "", "", "", "", "", "", "scd", "", "hd", "" +}; +const int nbdevs = NENTS(bdevs); + +const char cdevs[][4] = { + "cn", "", "", "", "", "", "", "", + "com", "", "", "", "pc" +}; +const int ncdevs = NENTS(cdevs); + +/* pass dev_t to the open routines */ +int +devopen(struct open_file *f, const char *fname, char **file) +{ + struct devsw *dp = devsw; + char *p; + char *stripdev; + int i, l; + int rc = 1; + + *file = (char *)fname; + +#ifdef DEBUG + if (debug) + printf("devopen(%s):", fname); +#endif + + /* Make sure we have a prefix, e.g. hd0a: or tftp:. */ + for (p = (char *)fname; *p != ':' && *p != '\0'; ) p++; + if (*p != ':') + return 1; + stripdev = p + 1; + + l = p - fname; /* Length of device prefix. */ + for (i = 0; i < nfsname; i++) { + if ((fs_name[i] != NULL) && + (strncmp(fname, fs_name[i], l) == 0)) { + + /* Force oopen() etc to use this filesystem. */ + f->f_ops = &file_system[i]; + f->f_dev = dp = &netsw[0]; + + rc = (*dp->dv_open)(f, NULL); + if (rc == 0) + *file = stripdev; + else + f->f_dev = NULL; +#ifdef DEBUG + if (debug) + putchar('\n'); +#endif + return rc; + } + } + + for (i = 0; i < ndevs && rc != 0; dp++, i++) { +#ifdef DEBUG + if (debug) + printf(" %s: ", dp->dv_name); +#endif + if ((rc = (*dp->dv_open)(f, file)) == 0) { + f->f_dev = dp; + return 0; + } +#ifdef DEBUG + else if (debug) + printf("%d", rc); +#endif + + } +#ifdef DEBUG + if (debug) + putchar('\n'); +#endif + + if ((f->f_flags & F_NODEV) == 0) + f->f_dev = dp; + + return rc; +} + +void +devboot(dev_t bootdev, char *p) +{ + *p++ = 't'; + *p++ = 'f'; + *p++ = 't'; + *p++ = 'p'; + *p = '\0'; +} + +int pch_pos = 0; + +void +putchar(int c) +{ + switch (c) { + case '\177': /* DEL erases */ + cnputc('\b'); + cnputc(' '); + case '\b': + cnputc('\b'); + if (pch_pos) + pch_pos--; + break; + case '\t': + do + cnputc(' '); + while (++pch_pos % 8); + break; + case '\n': + case '\r': + cnputc(c); + pch_pos=0; + break; + default: + cnputc(c); + pch_pos++; + break; + } +} + +int +getchar(void) +{ + register int c = cngetc(); + + if (c == '\r') + c = '\n'; + + if ((c < ' ' && c != '\n') || c == '\177') + return c; + + putchar(c); + + return c; +} + +char ttyname_buf[8]; + +char * +ttyname(int fd) +{ + snprintf(ttyname_buf, sizeof ttyname_buf, "%s%d", + cdevs[major(cn_tab->cn_dev)], minor(cn_tab->cn_dev)); + + return ttyname_buf; +} + +dev_t +ttydev(char *name) +{ + int i, unit = -1; + char *no = name + strlen(name) - 1; + + while (no >= name && *no >= '0' && *no <= '9') + unit = (unit < 0 ? 0 : (unit * 10)) + *no-- - '0'; + if (no < name || unit < 0) + return NODEV; + for (i = 0; i < ncdevs; i++) + if (strncmp(name, cdevs[i], no - name + 1) == 0) + return (makedev(i, unit)); + return NODEV; +} + +int +cnspeed(dev_t dev, int sp) +{ + if (major(dev) == 8) /* comN */ + return (comspeed(dev, sp)); + + /* pc0 and anything else */ + return 9600; +} diff --git a/sys/arch/amd64/stand/pxeboot/net.c b/sys/arch/amd64/stand/pxeboot/net.c new file mode 100644 index 00000000000..ef2ecb3a9e8 --- /dev/null +++ b/sys/arch/amd64/stand/pxeboot/net.c @@ -0,0 +1,290 @@ +/* $OpenBSD: net.c,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD: net.c,v 1.14 1996/10/13 02:29:02 christos 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. 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, Lawrence Berkeley Laboratory 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. + * + * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) + */ + +#include <sys/param.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> + +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_var.h> +#include <netinet/udp.h> +#include <netinet/udp_var.h> + +#include <lib/libsa/stand.h> +#include <lib/libsa/net.h> + +#include <pxeboot.h> + +/* Caller must leave room for ethernet, ip and udp headers in front!! */ +ssize_t +sendudp(struct iodesc *d, void *pkt, size_t len) +{ + return pxesendudp(d, pkt, len); +} + +/* + * Receive a UDP packet and validate it is for us. + * Caller leaves room for the headers (Ether, IP, UDP) + */ +ssize_t +readudp(struct iodesc *d, void *pkt, size_t len, time_t tleft) +{ + return pxereadudp(d, pkt, len, tleft); +} + +/* + * Send a packet and wait for a reply, with exponential backoff. + * + * The send routine must return the actual number of bytes written. + * + * The receive routine can indicate success by returning the number of + * bytes read; it can return 0 to indicate EOF; it can return -1 with a + * non-zero errno to indicate failure; finally, it can return -1 with a + * zero errno to indicate it isn't done yet. + */ +ssize_t +sendrecv(struct iodesc *d, ssize_t (*sproc)(struct iodesc *, void *, size_t), + void *sbuf, size_t ssize, + ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t), + void *rbuf, size_t rsize) +{ + ssize_t cc; + time_t t, tmo, tlast; + long tleft; + +#ifdef NET_DEBUG + if (debug) + printf("sendrecv: called\n"); +#endif + + tmo = MINTMO; + tlast = tleft = 0; + t = getsecs(); + for (;;) { + if (tleft <= 0) { + if (tmo >= MAXTMO) { + errno = ETIMEDOUT; + return -1; + } + cc = (*sproc)(d, sbuf, ssize); + if (cc < 0 || (size_t)cc < ssize) + panic("sendrecv: short write! (%d < %d)", + cc, ssize); + + tleft = tmo; + tmo <<= 1; + if (tmo > MAXTMO) + tmo = MAXTMO; + tlast = t; + } + + /* Try to get a packet and process it. */ + cc = (*rproc)(d, rbuf, rsize, tleft); + /* Return on data, EOF or real error. */ + if (cc != -1 || errno != 0) + return (cc); + + /* Timed out or didn't get the packet we're waiting for */ + t = getsecs(); + tleft -= t - tlast; + tlast = t; + } +} + +/* + * Like inet_addr() in the C library, but we only accept base-10. + * Return values are in network order. + */ +n_long +inet_addr(char *cp) +{ + u_long val; + int n; + char c; + u_int parts[4]; + u_int *pp = parts; + + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, other=decimal. + */ + val = 0; + while ((c = *cp) != '\0') { + if (c >= '0' && c <= '9') { + val = (val * 10) + (c - '0'); + cp++; + continue; + } + break; + } + if (*cp == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16-bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3 || val > 0xff) + goto bad; + *pp++ = val, cp++; + } else + break; + } + /* + * Check for trailing characters. + */ + if (*cp != '\0') + goto bad; + + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + goto bad; + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + goto bad; + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + goto bad; + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + return (htonl(val)); + bad: + return (htonl(INADDR_NONE)); +} + +char * +inet_ntoa(struct in_addr ia) +{ + return (intoa(ia.s_addr)); +} + +/* Similar to inet_ntoa() */ +char * +intoa(n_long addr) +{ + char *cp; + u_int byte; + int n; + static char buf[sizeof(".255.255.255.255")]; + + NTOHL(addr); + cp = &buf[sizeof buf]; + *--cp = '\0'; + + n = 4; + do { + byte = addr & 0xff; + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) { + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) + *--cp = byte + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + return (cp+1); +} + +static char * +number(char *s, int *n) +{ + for (*n = 0; isdigit(*s); s++) + *n = (*n * 10) + *s - '0'; + return s; +} + +n_long +ip_convertaddr(char *p) +{ +#define IP_ANYADDR 0 + n_long addr = 0, n; + + if (p == (char *)0 || *p == '\0') + return IP_ANYADDR; + p = number(p, &n); + addr |= (n << 24) & 0xff000000; + if (*p == '\0' || *p++ != '.') + return IP_ANYADDR; + p = number(p, &n); + addr |= (n << 16) & 0xff0000; + if (*p == '\0' || *p++ != '.') + return IP_ANYADDR; + p = number(p, &n); + addr |= (n << 8) & 0xff00; + if (*p == '\0' || *p++ != '.') + return IP_ANYADDR; + p = number(p, &n); + addr |= n & 0xff; + if (*p != '\0') + return IP_ANYADDR; + + return htonl(addr); +} diff --git a/sys/arch/amd64/stand/pxeboot/open.c b/sys/arch/amd64/stand/pxeboot/open.c new file mode 100644 index 00000000000..02c7f2dd8a6 --- /dev/null +++ b/sys/arch/amd64/stand/pxeboot/open.c @@ -0,0 +1,136 @@ +/* $OpenBSD: open.c,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD: open.c,v 1.12 1996/09/30 16:01:21 ws Exp $ */ + +/*- + * 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. 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. + * + * @(#)open.c 8.1 (Berkeley) 6/11/93 + * + * + * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University + * All Rights Reserved. + * + * Author: Alessandro Forin + * + * 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 <lib/libsa/stand.h> + +struct open_file files[SOPEN_MAX]; + +/* + * File primitives proper + */ + +int +#ifndef __INTERNAL_LIBSA_CREAD +open(const char *fname, int mode) +#else +oopen(const char *fname, int mode) +#endif +{ + struct open_file *f; + int fd, i, error; + char *file; + + /* find a free file descriptor */ + for (fd = 0, f = files; fd < SOPEN_MAX; fd++, f++) + if (f->f_flags == 0) + goto fnd; + errno = EMFILE; + return -1; +fnd: + /* + * Try to open the device. + * Convert open mode (0,1,2) to F_READ, F_WRITE. + */ + f->f_flags = mode + 1; + f->f_dev = (struct devsw *)0; + f->f_ops = (struct fs_ops *)0; + file = (char *)0; + error = devopen(f, fname, &file); + if (error || + (((f->f_flags & F_NODEV) == 0) && f->f_dev == (struct devsw *)0)) + goto err; + + /* see if we opened a raw device; otherwise, 'file' is the file name. */ + if (file == (char *)0 || *file == '\0') { + f->f_flags |= F_RAW; + return fd; + } + + /* Allow f->f_ops to be set by devopen routine. */ + if (f->f_ops != NULL) { + error = f->f_ops->open(file, f); + if (error == 0) + return fd; + } + else { + /* pass file name to the different filesystem open routines */ + for (i = 0; i < nfsys; i++) { + /* convert mode (0,1,2) to FREAD, FWRITE. */ + error = (file_system[i].open)(file, f); + if (error == 0) { + f->f_ops = &file_system[i]; + return (fd); + } + if (error == ENOENT || error == ENOTDIR) + break; + } + } + if (error == 0) + error = ENOENT; + + f->f_dev->dv_close(f); +err: + f->f_flags = 0; + errno = error; + return -1; +} diff --git a/sys/arch/amd64/stand/pxeboot/pxeboot.8 b/sys/arch/amd64/stand/pxeboot/pxeboot.8 new file mode 100644 index 00000000000..68999b67498 --- /dev/null +++ b/sys/arch/amd64/stand/pxeboot/pxeboot.8 @@ -0,0 +1,187 @@ +.\" $OpenBSD: pxeboot.8,v 1.1 2004/03/21 21:37:41 tom Exp $ +.\" Copyright (c) 2004 Tom Cosgrove +.\" Copyright (c) 2003 Matthias Drochner +.\" Copyright (c) 1999 Doug White +.\" 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. +.\" +.Dd March 18, 2004 +.Dt PXEBOOT 8 amd64 +.Os +.Sh NAME +.Nm pxeboot +.Nd +amd64-specific second-stage PXE bootstrap +.Sh DESCRIPTION +.Nm +is a modified version of the amd64 second-stage bootstrap program, +.Xr boot 8 , +configured to run under Intel's Preboot Execution Environment (PXE). +PXE is a form of smart boot ROM, built into many Ethernet cards from Intel, +3Com, and other manufacturers. +.Pp +The computer's PXE boot ROM contacts a DHCP server by broadcasting a request +on the network. +It gets an IP address from the DHCP server, +then it is told the name of the boot program to download \(em +in this case, the boot program is +.Nm . +The ROM downloads the boot program using TFTP, then executes it. +.Pp +The +.Nm +boot program will look for an +.Pa /etc/boot.conf +configuration +file on the TFTP server. +If it finds one, it processes the commands within it. +.Pp +.Nm +then sits in a loop, +processing commands given by the user. +It accepts all the commands accepted by +.Xr boot 8 . +.Pp +If no commands are given for a short time, +.Nm +will then attempt to load the +.Ox +kernel +.Pa bsd +via TFTP. +It may be told to boot an alternative kernel, +either by commands in the +.Pa boot.conf +file, +or by commands typed by the user at the +.Ic boot> +prompt. +At this time, +it is expected that pxeboot will be used to load the +.Pa bsd.rd +install kernel, +for network installs, +although this is not the default kernel. +.Pp +To prepare a server to support network installs, +the +.Xr dhcpd 8 +and +.Xr tftpd 8 +services should be enabled and configured. +It may help to use the +.Fl s +option with +.Xr tftpd 8 , +to avoid confusion between files for the server's system +and files for the client system. +(Note that +.Fl s +is set by default in +OpenBSD.) +.Xr ftpd 8 +or +.Xr httpd 8 +should be enabled, depending on how the install sets will be made available. +.Pp +.Nm +and the kernel should be copied into the TFTP server's root directory +(typically +.Pa /tftpboot ) . +A +.Pa boot.conf +file may be created if required +(e.g.\& +.Pa /tftpboot/etc/boot.conf ) . +.Pp +A sample configuration file for +.Xr dhcpd 8 +might be as follows: +.Bd -literal -offset indent +option domain-name "example.com"; +option routers 10.0.0.1; +option subnet-mask 255.255.255.0; +option broadcast-address 10.0.0.255; +option domain-name-servers 10.0.0.1; +server-name "DHCPserver"; +server-identifier 10.0.0.1; + +default-lease-time 120; +max-lease-time 120; + +subnet 10.0.0.0 netmask 255.255.255.0 { + filename "pxeboot"; + range 10.0.0.10 10.0.0.254; +} +.Ed +.Pp +Since amd64 systems boot up as i386 systems, +their PXE ROMs typically set the PXE client system architecture +to be the same as for i386. +This means that the DHCP option +.Ic vendor-class-identifier +cannot, therefore, be used to distinguish between i386 and amd64 systems. +.Pp +Instead, the client machine identifier (UUID) or +hardware ethernet address (MAC) should be used. +See +.Xr dhcpd 8 +and +.Xr dhcpd.conf 5 +for more information. +.Sh FILES +.Bl -tag -width /usr/mdec/pxebootxx -compact +.It Pa /usr/mdec/pxeboot +PXE-specific second-stage bootstrap +.It Pa /etc/boot.conf +.Nm +configuration file (read from TFTP server) +.It Pa /tftpboot +Default root directory for +.Xr tftpd 8 +.El +.Sh EXAMPLES +Boot the install kernel: +.Pp +.Dl boot> bsd.rd +.Pp +The same thing: +.Pp +.Dl boot> boot tftp:bsd.rd +.Sh SEE ALSO +.Xr dhcpd.conf 5 , +.Xr boot 8 , +.Xr boot_amd64 8 , +.Xr dhcpd 8 , +.Xr httpd 8 , +.Xr tftpd 8 +.Rs +.%T Preboot Execution Environment (PXE) Specification +.%N Version 2.1 +.%D September 20, 1999 +.%A Intel Corporation +.Re +.Sh HISTORY +.Nm +first appeared in +.Ox 3.5 . diff --git a/sys/arch/amd64/stand/pxeboot/srt0.S b/sys/arch/amd64/stand/pxeboot/srt0.S new file mode 100644 index 00000000000..b7138558475 --- /dev/null +++ b/sys/arch/amd64/stand/pxeboot/srt0.S @@ -0,0 +1,223 @@ +/* $OpenBSD: srt0.S,v 1.1 2004/03/21 21:37:41 tom Exp $ */ + +/* + * Copyright (c) 1997 Michael Shalayeff + * 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 ``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. + * + */ +#include <machine/asm.h> +#include <assym.h> + +#define BOOTSTACK 0xfffc + + .globl _C_LABEL(end) + .globl _C_LABEL(edata) + .globl _C_LABEL(boot) + .globl _C_LABEL(_rtt) + .globl _C_LABEL(bios_bootdev) + .globl _ASM_LABEL(pmm_init) + .globl Gdtr + + .text + .code16 + .globl _start +_start: +#ifdef DEBUG + movl $0xb80a0, %ebx + addr32 movl $0x07420742, (%ebx) +#endif + +/* Clobbers %ax, maybe more */ +#define putc(c) movb $c, %al; call Lchr + + /* + * We are loaded by the PXE loader at location 0x7C00. Like + * the standard /boot, we are linked to run at 0x40120 (load + * address 0x40000), so we relocate to there. + * + * From 0x7C00 to 0x40000 is 0x38400 (230400) bytes, so don't + * have to worry about an overlapping copy until pxeboot is + * over 225 KB. + * + * Note that there are other reasons to be worried if + * sizeof(/boot) > 64 KB. So currently we copy a maximum of 64 KB. + * + * PXE loads us with a stack that grows down from 0x80000 (512 KB). + * While it is unlikely that this will clash with our code that + * we're copying up, we create a temporary stack just below us + * before the relocate. We also set the entire %esp register, to + * be on the safe side. + */ +#define PXEBOOTADDR 0x7c00 /* Address where we are loaded by PXE */ + xorw %ax, %ax + movw %ax, %ss /* CPU disables interrupts till.. */ + movl $PXEBOOTADDR-4, %esp /* after this instruction */ + + movw $(PXEBOOTADDR >> 4), %ax + movw %ax, %ds + xorw %si, %si /* Where we're coming from */ + + movw $(LINKADDR >> 4), %ax + movw %ax, %es /* Set %es = 0x4000 */ + xorw %di, %di /* Where we're going to */ + + movl $_C_LABEL(end), %ecx + subl $_C_LABEL(_start), %ecx /* How big are we? */ + + cld + rep; movsb /* Copy into place */ + + jmpl $(LINKADDR >> 4), $(relocated-_start) /* Now relocate */ + +relocated: + /* + * In 16-bit mode, we have segment registers == 0x4012, and + * offsets work from here, with offset(_start) == 0. + * + * In 32-bit mode, we have a flat memory model, where + * offset(_start) == 0x40120. This is how we're linked. + * + * Now transition to protected mode. + * + * First, initialise the global descriptor table. + */ + cli + push %cs + pop %ds + addr32 data32 lgdt (Gdtr - LINKADDR) + + movl %cr0, %eax + orl $CR0_PE, %eax + data32 movl %eax, %cr0 + data32 ljmp $8, $1f /* Seg sel 0x08 is flat 32-bit code */ +1: + .code32 + movl $0x10, %eax /* Seg sel 0x10 is flat 32-bit data */ + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss + movl $BOOTSTACK, %esp +#ifdef DEBUG + movl $0xb8000, %ebx + movl $0x07420742, (%ebx) +#endif + + xorl %edx, %edx + movl %edx, _C_LABEL(bios_bootdev) + pushl %edx /* boot() takes this as a parameter */ + + /* Set up an interrupt descriptor table for protected mode. */ + call _ASM_LABEL(pmm_init) +#ifdef DEBUG + movl $0xb80a4, %ebx + movl $0x07520752, (%ebx) +#endif + + /* Zero .bss */ + xorl %eax, %eax + movl $_C_LABEL(end), %ecx + subl $_C_LABEL(edata), %ecx + movl $_C_LABEL(edata), %edi + cld + rep; stosb + + /* Set our program name ("PXEBOOT", not "BOOT"). */ + movl $pxe_progname, %eax + movl %eax, progname + + /* + * Now call "main()". + * + * We run in flat 32-bit protected mode, with no address mapping. + */ +#ifdef DEBUG + movl $0xb8004, %ebx + movl $0x07410741, (%ebx) +#endif + call _C_LABEL(boot) + + /* boot() should not return. If it does, reset computer. */ + jmp _C_LABEL(_rtt) + +ENTRY(debugchar) + pushl %ebx + movl 8(%esp), %ebx + addl %ebx, %ebx + addl $0xb8000, %ebx + + xorl %eax, %eax + movb 12(%esp), %al + + andl $0xfffffffe, %ebx + movb %al, (%ebx) + popl %ebx + ret + + .code16 + +/* + * Write out value in %ax in hex + */ +hex_word: + pushw %ax + mov %ah, %al + call hex_byte + popw %ax + /* fall thru */ +/* + * Write out value in %al in hex + */ +hex_byte: + pushw %ax + shrb $4, %al + call hex_nibble + popw %ax + /* fall thru */ + +/* Write out nibble in %al */ +hex_nibble: + and $0x0F, %al + add $'0', %al + cmpb $'9', %al + jbe Lchr + addb $'A'-'9'-1, %al + /* fall thru to Lchr */ +/* + * Lchr: write the character in %al to console + */ +Lchr: + pushw %bx + movb $0x0e, %ah + xorw %bx, %bx + incw %bx /* movw $0x01, %bx */ + int $0x10 + popw %bx + ret + +pxe_progname: + .asciz "PXEBOOT" + + .end |