summaryrefslogtreecommitdiff
path: root/sys/arch/amd64/stand/pxeboot
diff options
context:
space:
mode:
authorTom Cosgrove <tom@cvs.openbsd.org>2004-03-21 21:37:42 +0000
committerTom Cosgrove <tom@cvs.openbsd.org>2004-03-21 21:37:42 +0000
commitb6bedfcd017a291b7e736a57597a5dbeb552cd1d (patch)
tree149286d1847005927bde0e9a93f2efa1c1a6278a /sys/arch/amd64/stand/pxeboot
parent8c6e84988022919eccc722f39a6b132f873506d7 (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/Makefile66
-rw-r--r--sys/arch/amd64/stand/pxeboot/conf.c127
-rw-r--r--sys/arch/amd64/stand/pxeboot/devopen.c217
-rw-r--r--sys/arch/amd64/stand/pxeboot/net.c290
-rw-r--r--sys/arch/amd64/stand/pxeboot/open.c136
-rw-r--r--sys/arch/amd64/stand/pxeboot/pxeboot.8187
-rw-r--r--sys/arch/amd64/stand/pxeboot/srt0.S223
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