diff options
Diffstat (limited to 'sys/arch/amd64/stand/libsa')
-rw-r--r-- | sys/arch/amd64/stand/libsa/diskprobe.c | 5 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/exec_i386.c | 5 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/gateA20.c | 14 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/gidt.S | 10 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/gidt.h | 35 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/libsa.h | 15 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/machdep.c | 35 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/pxe.c | 547 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/pxe.h | 528 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/pxe_call.S | 202 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/pxe_net.c | 183 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/pxe_net.h | 44 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/pxe_netif.h | 43 | ||||
-rw-r--r-- | sys/arch/amd64/stand/libsa/pxeboot.h | 53 |
14 files changed, 1691 insertions, 28 deletions
diff --git a/sys/arch/amd64/stand/libsa/diskprobe.c b/sys/arch/amd64/stand/libsa/diskprobe.c index 117e1ebad98..501fa402c9f 100644 --- a/sys/arch/amd64/stand/libsa/diskprobe.c +++ b/sys/arch/amd64/stand/libsa/diskprobe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: diskprobe.c,v 1.1 2004/02/03 12:09:47 mickey Exp $ */ +/* $OpenBSD: diskprobe.c,v 1.2 2004/03/21 21:37:41 tom Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -170,7 +170,6 @@ diskprobe(void) bios_diskinfo_t *bios_diskinfo; /* Init stuff */ - printf("disk:"); TAILQ_INIT(&disklist); /* Do probes */ @@ -199,8 +198,6 @@ diskprobe(void) /* Register for kernel use */ addbootarg(BOOTARG_CKSUMLEN, sizeof(u_int32_t), &bios_cksumlen); addbootarg(BOOTARG_DISKINFO, i * sizeof(bios_diskinfo_t), bios_diskinfo); - - printf("\n"); } diff --git a/sys/arch/amd64/stand/libsa/exec_i386.c b/sys/arch/amd64/stand/libsa/exec_i386.c index c14b5b8c240..f5559048a01 100644 --- a/sys/arch/amd64/stand/libsa/exec_i386.c +++ b/sys/arch/amd64/stand/libsa/exec_i386.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_i386.c,v 1.3 2004/02/25 00:16:42 deraadt Exp $ */ +/* $OpenBSD: exec_i386.c,v 1.4 2004/03/21 21:37:41 tom Exp $ */ /* * Copyright (c) 1997-1998 Michael Shalayeff @@ -53,6 +53,9 @@ run_loadfile(u_long *marks, int howto) bios_consdev_t cd; extern int com_speed; /* from bioscons.c */ + if (sa_cleanup != NULL) + (*sa_cleanup)(); + cd.consdev = cn_tab->cn_dev; cd.conspeed = com_speed; addbootarg(BOOTARG_CONSDEV, sizeof(cd), &cd); diff --git a/sys/arch/amd64/stand/libsa/gateA20.c b/sys/arch/amd64/stand/libsa/gateA20.c index 26cfb3539cb..66a11a08cdd 100644 --- a/sys/arch/amd64/stand/libsa/gateA20.c +++ b/sys/arch/amd64/stand/libsa/gateA20.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gateA20.c,v 1.1 2004/02/03 12:09:47 mickey Exp $ */ +/* $OpenBSD: gateA20.c,v 1.2 2004/03/21 21:37:41 tom Exp $ */ /* * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 @@ -36,6 +36,8 @@ #include "libsa.h" +int ps2model = 0; /* Not set in amd64 */ + #define KB_A20 0xdf /* enable A20, enable output buffer full interrupt enable data line @@ -43,6 +45,16 @@ /* + * "Probe"-style routine (no parameters) to turn A20 on + */ +void +gateA20on(void) +{ + gateA20(1); +} + + +/* * Gate A20 for high memory */ void diff --git a/sys/arch/amd64/stand/libsa/gidt.S b/sys/arch/amd64/stand/libsa/gidt.S index c280c64a9ab..fefd7890778 100644 --- a/sys/arch/amd64/stand/libsa/gidt.S +++ b/sys/arch/amd64/stand/libsa/gidt.S @@ -1,4 +1,4 @@ -/* $OpenBSD: gidt.S,v 1.1 2004/02/03 12:09:47 mickey Exp $ */ +/* $OpenBSD: gidt.S,v 1.2 2004/03/21 21:37:41 tom Exp $ */ /* * Copyright (c) 1997 Michael Shalayeff @@ -35,11 +35,7 @@ #undef _LOCORE #include <assym.h> -#define SNULL 0x00 -#define S32TEXT 0x08 -#define S32DATA 0x10 -#define S16TEXT 0x18 -#define S16DATA 0x20 +#include "gidt.h" #ifdef GIDT_DEBUG #define gidt_debug0 ; \ @@ -203,11 +199,13 @@ idt: idtb(36); idtb(37); idtb(38); idtb(39); idtb(40); idtb(41) idtb(42); idtb(43); idtb(44); idtb(45); idtb(46); idtb(47) #undef idte + .globl Idtr Idtr: .word . - idt - 1 .long idt .word 0 .align 8 + .globl Idtr_real Idtr_real: .word 1023 .long 0 .word 0 diff --git a/sys/arch/amd64/stand/libsa/gidt.h b/sys/arch/amd64/stand/libsa/gidt.h new file mode 100644 index 00000000000..03b80e81826 --- /dev/null +++ b/sys/arch/amd64/stand/libsa/gidt.h @@ -0,0 +1,35 @@ +/* $OpenBSD: gidt.h,v 1.1 2004/03/21 21:37:41 tom Exp $ */ + +/* + * Copyright (c) 2004 Tom Cosgrove + * 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. + * + */ + +#define SNULL 0x00 +#define S32TEXT 0x08 +#define S32DATA 0x10 +#define S16TEXT 0x18 +#define S16DATA 0x20 diff --git a/sys/arch/amd64/stand/libsa/libsa.h b/sys/arch/amd64/stand/libsa/libsa.h index 4c587852017..b61adea1107 100644 --- a/sys/arch/amd64/stand/libsa/libsa.h +++ b/sys/arch/amd64/stand/libsa/libsa.h @@ -1,4 +1,4 @@ -/* $OpenBSD: libsa.h,v 1.1 2004/02/03 12:09:47 mickey Exp $ */ +/* $OpenBSD: libsa.h,v 1.2 2004/03/21 21:37:41 tom Exp $ */ /* * Copyright (c) 1996-1999 Michael Shalayeff @@ -31,7 +31,16 @@ #define DEFAULT_KERNEL_ADDRESS 0 +struct i386_boot_probes { + char *name; + void (**probes)(void); + int count; +}; + +extern void (*sa_cleanup)(void); + void gateA20(int); +void gateA20on(void); void smpprobe(void); void pciprobe(void); @@ -55,6 +64,10 @@ extern const int nbdevs; extern u_int cnvmem, extmem; /* XXX global pass memprobe()->machdep_start() */ extern int ps2model; +extern struct i386_boot_probes probe_list[]; +extern int nibprobes; +extern void (*devboot_p)(dev_t, char *); + /* diskprobe.c */ extern bios_diskinfo_t bios_diskinfo[]; extern u_int32_t bios_cksumlen; diff --git a/sys/arch/amd64/stand/libsa/machdep.c b/sys/arch/amd64/stand/libsa/machdep.c index ffc1f8e52d8..97ec8d544e5 100644 --- a/sys/arch/amd64/stand/libsa/machdep.c +++ b/sys/arch/amd64/stand/libsa/machdep.c @@ -1,6 +1,7 @@ -/* $OpenBSD: machdep.c,v 1.2 2004/02/23 01:19:52 tom Exp $ */ +/* $OpenBSD: machdep.c,v 1.3 2004/03/21 21:37:41 tom Exp $ */ /* + * Copyright (c) 2004 Tom Cosgrove * Copyright (c) 1997-1999 Michael Shalayeff * All rights reserved. * @@ -38,21 +39,25 @@ volatile struct BIOS_regs BIOS_regs; #define CKPT(c) /* c */ #endif -extern int debug; -int ps2model; - void machdep(void) { - /* here */ CKPT('0'); - printf("probing:"); - /* probe for a model number, gateA20() neds ps2model */ - gateA20(1); CKPT('1'); - /* initialise a console (and probe for com* devices) */ - cninit(); CKPT('2'); - memprobe(); CKPT('3'); - printf("\n"); - - diskprobe(); CKPT('4'); - CKPT('Z'); + int i, j; + struct i386_boot_probes *pr; + + /* + * The list of probe routines is now in conf.c. + */ + for (i = 0; i < nibprobes; i++) { + pr = &probe_list[i]; + if (pr != NULL) { + printf("%s:", pr->name); + + for (j = 0; j < pr->count; j++) { + (*(pr->probes)[j])(); + } + + printf("\n"); + } + } } diff --git a/sys/arch/amd64/stand/libsa/pxe.c b/sys/arch/amd64/stand/libsa/pxe.c new file mode 100644 index 00000000000..205428662f4 --- /dev/null +++ b/sys/arch/amd64/stand/libsa/pxe.c @@ -0,0 +1,547 @@ +/* $OpenBSD: pxe.c,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD: pxe.c,v 1.5 2003/03/11 18:29:00 drochner Exp $ */ + +/* + * Copyright 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * 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 for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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 Alfred Perlstein <alfred@freebsd.org> + * All rights reserved. + * Copyright (c) 2000 Paul Saab <ps@freebsd.org> + * All rights reserved. + * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> + * 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. + */ + +/* + * Support for the Intel Preboot Execution Environment (PXE). + * + * PXE provides a UDP implementation as well as a UNDI network device + * driver. UNDI is much more complicated to use than PXE UDP, so we + * use PXE UDP as a cheap and easy way to get PXE support. + */ + +#include <sys/param.h> +#include <sys/socket.h> + +#ifdef _STANDALONE +#include <lib/libkern/libkern.h> +#else +#include <string.h> +#endif + +#include <net/if.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 <lib/libsa/bootp.h> + +#include "pxeboot.h" +#include "pxe.h" +#include "pxe_netif.h" + +void (*pxe_call)(u_int16_t); + +void pxecall_bangpxe(u_int16_t); /* pxe_call.S */ +void pxecall_pxenv(u_int16_t); /* pxe_call.S */ + +char pxe_command_buf[256]; + +BOOTPLAYER bootplayer; + +struct in_addr servip; /* for tftp */ /* XXX init this */ + +/* static struct btinfo_netif bi_netif; */ + +/***************************************************************************** + * This section is a replacement for libsa/udp.c + *****************************************************************************/ + +/* Caller must leave room for ethernet, ip, and udp headers in front!! */ +ssize_t +pxesendudp(struct iodesc *d, void *pkt, size_t len) +{ + t_PXENV_UDP_WRITE *uw = (void *) pxe_command_buf; + + uw->status = 0; + + uw->ip = d->destip.s_addr; + uw->gw = gateip.s_addr; + uw->src_port = d->myport; + uw->dst_port = d->destport; + uw->buffer_size = len; + uw->buffer.segment = VTOPSEG(pkt); + uw->buffer.offset = VTOPOFF(pkt); + + pxe_call(PXENV_UDP_WRITE); + + if (uw->status != PXENV_STATUS_SUCCESS) { + /* XXX This happens a lot; it shouldn't. */ + if (uw->status != PXENV_STATUS_FAILURE) + printf("sendudp: PXENV_UDP_WRITE failed: 0x%x\n", + uw->status); + return -1; + } + + return len; +} + +/* + * Receive a UDP packet and validate it for us. + * Caller leaves room for the headers (Ether, IP, UDP). + */ +ssize_t +pxereadudp(struct iodesc *d, void *pkt, size_t len, time_t tleft) +{ + t_PXENV_UDP_READ *ur = (void *) pxe_command_buf; + struct udphdr *uh; + struct ip *ip; + + uh = (struct udphdr *)pkt - 1; + ip = (struct ip *)uh - 1; + + bzero(ur, sizeof(*ur)); + + ur->dest_ip = d->myip.s_addr; + ur->d_port = d->myport; + ur->buffer_size = len; + ur->buffer.segment = VTOPSEG(pkt); + ur->buffer.offset = VTOPOFF(pkt); + + /* XXX Timeout unused. */ + + pxe_call(PXENV_UDP_READ); + + if (ur->status != PXENV_STATUS_SUCCESS) { + /* XXX This happens a lot; it shouldn't. */ + if (ur->status != PXENV_STATUS_FAILURE) + printf("readudp: PXENV_UDP_READ_failed: 0x%0x\n", + ur->status); + return -1; + } + + ip->ip_src.s_addr = ur->src_ip; + uh->uh_sport = ur->s_port; + uh->uh_dport = d->myport; + + return ur->buffer_size; +} + +/* + * netif layer: + * open, close, shutdown: called from dev_net.c + * socktodesc: called by network protocol modules + * + * We only allow one open socket. + */ + +static int pxe_inited; +static struct iodesc desc; + +int +pxe_netif_open() +{ + t_PXENV_UDP_OPEN *uo = (void *) pxe_command_buf; + +#ifdef NETIF_DEBUG + printf("pxe_netif_open()\n"); +#endif + if (!pxe_inited) { + if (pxe_init(0) != 0) + return -1; + pxe_inited = 1; + } + /* BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif)); */ + + bzero(uo, sizeof(*uo)); + + uo->src_ip = bootplayer.yip; + + pxe_call(PXENV_UDP_OPEN); + + if (uo->status != PXENV_STATUS_SUCCESS) { + printf("pxe_netif_open: PXENV_UDP_OPEN failed: 0x%x\n", + uo->status); + return -1; + } + + bcopy(bootplayer.CAddr, desc.myea, ETHER_ADDR_LEN); + + /* + * Since the PXE BIOS has already done DHCP, make sure we + * don't reuse any of its transaction IDs. + */ + desc.xid = bootplayer.ident; + + return 0; +} + +void +pxe_netif_close(sock) + int sock; +{ + t_PXENV_UDP_CLOSE *uc = (void *) pxe_command_buf; + +#ifdef NETIF_DEBUG + if (sock != 0) + printf("pxe_netif_close: sock=%d\n", sock); +#endif + + uc->status = 0; + + pxe_call(PXENV_UDP_CLOSE); + + if (uc->status != PXENV_STATUS_SUCCESS) + printf("pxe_netif_end: PXENV_UDP_CLOSE failed: 0x%x\n", + uc->status); +} + +void +pxe_netif_shutdown() +{ +#ifdef NETIF_DEBUG + printf("pxe_netif_shutdown()\n"); +#endif + + pxe_shutdown(); +} + +struct iodesc * +pxesocktodesc(sock) + int sock; +{ + +#ifdef NETIF_DEBUG + if (sock != 0) + return 0; + else +#endif + return &desc; +} + +/***************************************************************************** + * PXE initialization and support routines + *****************************************************************************/ + +u_int16_t pxe_command_buf_seg; +u_int16_t pxe_command_buf_off; + +extern u_int16_t bangpxe_off, bangpxe_seg; +extern u_int16_t pxenv_off, pxenv_seg; + +/* static struct btinfo_netif bi_netif; */ + +void +pxeprobe(void) +{ + if (!pxe_inited) { + if (pxe_init(1) == 0) { + pxe_inited = 1; + } + } +} + +int +pxe_init(int quiet) +{ + t_PXENV_GET_CACHED_INFO *gci = (void *) pxe_command_buf; + pxenv_t *pxenv; + pxe_t *pxe; + char *cp; + int i; + u_int8_t cksum, *ucp; + + /* + * Checking for the presence of PXE is a machine-dependent + * operation. On the IA-32, this can be done two ways: + * + * Int 0x1a function 0x5650 + * + * Scan memory for the !PXE or PXENV+ signatures + * + * We do the latter, since the Int method returns a pointer + * to a deprecated structure (PXENV+). + */ + + pxenv = NULL; + pxe = NULL; + + for (cp = (char *)0xa0000; cp > (char *)0x10000; cp -= 2) { + if (pxenv == NULL) { + pxenv = (pxenv_t *)cp; + if (memcmp(pxenv->Signature, S_SIZE("PXENV+")) != 0) + pxenv = NULL; + else { + for (i = 0, ucp = (u_int8_t *)cp, cksum = 0; + i < pxenv->Length; i++) + cksum += ucp[i]; + if (cksum != 0) { + printf("\npxe_init: bad cksum (0x%x) " + "for PXENV+ at 0x%lx\n", cksum, + (u_long) cp); + pxenv = NULL; + } + } + } + + if (pxe == NULL) { + pxe = (pxe_t *)cp; + if (memcmp(pxe->Signature, S_SIZE("!PXE")) != 0) + pxe = NULL; + else { + for (i = 0, ucp = (u_int8_t *)cp, cksum = 0; + i < pxe->StructLength; i++) + cksum += ucp[i]; + if (cksum != 0) { + printf("pxe_init: bad cksum (0x%x) " + "for !PXE at 0x%lx\n", cksum, + (u_long) cp); + pxe = NULL; + } + } + } + + if (pxe != NULL && pxenv != NULL) + break; + } + + if (pxe == NULL && pxenv == NULL) { + if (!quiet) printf("pxe_init: No PXE BIOS found.\n"); + return 1; + } + + if (pxenv == NULL) { + /* assert(pxe != NULL); */ + + printf(quiet ? " pxe!" : "PXE present\n"); + } + else { /* pxenv != NULL */ + int bang = 0; + + if (pxenv->Version >= 0x0201 && pxe != NULL) { + /* 2.1 or greater -- don't use PXENV+ */ + bang = 1; + } + + if (quiet) { + printf(" pxe%c[%d.%d]", + (bang ? '!' : '+'), + (pxenv->Version >> 8) & 0xff, + pxenv->Version & 0xff); + } + else { + printf("PXE BIOS Version %d.%d\n", + (pxenv->Version >> 8) & 0xff, + pxenv->Version & 0xff); + } + + if (bang) { + pxenv = NULL; + } + } + + if (pxe != NULL) { + pxe_call = pxecall_bangpxe; + bangpxe_off = pxe->EntryPointSP.offset; + bangpxe_seg = pxe->EntryPointSP.segment; + } else { + pxe_call = pxecall_pxenv; + pxenv_off = pxenv->RMEntry.offset; + pxenv_seg = pxenv->RMEntry.segment; + } + + /* + * Pre-compute the segment/offset of the pxe_command_buf + * to make things nicer in the low-level calling glue. + */ + pxe_command_buf_seg = VTOPSEG(pxe_command_buf); + pxe_command_buf_off = VTOPOFF(pxe_command_buf); + + /* + * Get the cached info from the server's Discovery reply packet. + */ + bzero(gci, sizeof(*gci)); + gci->PacketType = PXENV_PACKET_TYPE_CACHED_REPLY; + pxe_call(PXENV_GET_CACHED_INFO); + + if (gci->Status != PXENV_STATUS_SUCCESS) { + printf("\npxeinfo: PXENV_GET_CACHED_INFO failed: 0x%x\n", + gci->Status); + return 1; + } + + memcpy(&bootplayer, + SEGOFF2FLAT(gci->Buffer.segment, gci->Buffer.offset), + gci->BufferSize); + + bcopy(&bootplayer.yip, &myip.s_addr, sizeof(myip.s_addr)); + bcopy(&bootplayer.sip, &servip.s_addr, sizeof(servip.s_addr)); + + /* Compute our "natural" netmask. */ + if (IN_CLASSA(myip.s_addr)) + netmask = IN_CLASSA_NET; + else if (IN_CLASSB(myip.s_addr)) + netmask = IN_CLASSB_NET; + else + netmask = IN_CLASSC_NET; + + return 0; +} + +void +pxeinfo(void) +{ + u_int8_t *p; +#ifdef PXE_DEBUG + t_PXENV_UNDI_GET_NIC_TYPE *gnt = (void *) pxe_command_buf; +#endif + + printf(" mac %s", ether_sprintf(bootplayer.CAddr)); + p = (u_int8_t *)&myip.s_addr; + printf(", ip %d.%d.%d.%d", p[0], p[1], p[2], p[3]); + p = (u_int8_t *)&servip.s_addr; + printf(", server %d.%d.%d.%d", p[0], p[1], p[2], p[3]); + +#ifdef PXE_DEBUG + /* + * Get network interface information. + */ + bzero(gnt, sizeof(*gnt)); + pxe_call(PXENV_UNDI_GET_NIC_TYPE); + + if (gnt->Status != PXENV_STATUS_SUCCESS) { + printf("\npxeinfo: PXENV_UNDI_GET_NIC_TYPE failed: 0x%x\n", + gnt->Status); + return; + } + + switch (gnt->NicType) { + case PCI_NIC: + case CardBus_NIC: + /* strncpy(bi_netif.ifname, "pxe", sizeof(bi_netif.ifname)); */ + /* bi_netif.bus = BI_BUS_PCI; */ + /* bi_netif.addr.tag = gnt->info.pci.BusDevFunc; */ + + printf("\nPXE: Using %s device at bus %d device %d function %d\n", + gnt->NicType == PCI_NIC ? "PCI" : "CardBus", + (gnt->info.pci.BusDevFunc >> 8) & 0xff, + (gnt->info.pci.BusDevFunc >> 3) & 0x1f, + gnt->info.pci.BusDevFunc & 0x7); + break; + + case PnP_NIC: + /* XXX Make bootinfo work with this. */ + printf("\nPXE: Using PnP device at 0x%x\n", + gnt->info.pnp.CardSelNum); + } +#endif +} + +void +pxe_shutdown(void) +{ + int try; + t_PXENV_UNLOAD_STACK *unload = (void *) pxe_command_buf; + t_PXENV_UNDI_SHUTDOWN *shutdown = (void *) pxe_command_buf; +#ifdef PXE_DEBUG + t_PXENV_UDP_CLOSE *close = (void *) pxe_command_buf; +#endif + + if (pxe_call == NULL) + return; + + /* Close any open UDP connections. Ignore return value. */ + pxe_call(PXENV_UDP_CLOSE); +#ifdef PXE_DEBUG + printf("pxe_shutdown: PXENV_UDP_CLOSE returned 0x%x\n", close->status); +#endif + + /* Sometimes PXENV_UNDI_SHUTDOWN doesn't work at first */ + for (try = 3; try > 0; try--) { + pxe_call(PXENV_UNDI_SHUTDOWN); + + if (shutdown->Status == PXENV_STATUS_SUCCESS) + break; + + printf("pxe_shutdown: PXENV_UNDI_SHUTDOWN failed: 0x%x\n", + shutdown->Status); + + if (try != 1) + sleep(1); + } + + /* Have multiple attempts at PXENV_UNLOAD_STACK, too */ + for (try = 3; try > 0; try--) { + pxe_call(PXENV_UNLOAD_STACK); + + if (unload->Status == PXENV_STATUS_SUCCESS) + break; + + printf("pxe_shutdown: PXENV_UNLOAD_STACK failed: 0x%x\n", + unload->Status); + + if (try != 1) + sleep(1); + } +} diff --git a/sys/arch/amd64/stand/libsa/pxe.h b/sys/arch/amd64/stand/libsa/pxe.h new file mode 100644 index 00000000000..5af5a2068c2 --- /dev/null +++ b/sys/arch/amd64/stand/libsa/pxe.h @@ -0,0 +1,528 @@ +/* $OpenBSD: pxe.h,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD: pxe.h,v 1.1 2002/02/16 03:37:40 thorpej Exp $ */ + +/* + * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org> + * All rights reserved. + * Copyright (c) 2000 Paul Saab <ps@freebsd.org> + * All rights reserved. + * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> + * 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. + */ + +/* + * Note that these structures and types are named according to + * the Intel PXE documentation. + */ + +#define S_SIZE(s) s, sizeof(s) - 1 + +#define IP_STR "%d.%d.%d.%d" +#define IP_ARGS(ip) \ + (int)(ip >> 24) & 0xff, (int)(ip >> 16) & 0xff, \ + (int)(ip >> 8) & 0xff, (int)ip & 0xff + +#define MAC_STR "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ARGS(mac) \ + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] + +typedef struct { + uint16_t offset; + uint16_t segment; +} SEGOFF16_t __attribute__((__packed__)); + +typedef struct { + uint16_t Seg_Addr; + uint32_t Phy_Addr; + uint16_t Seg_Size; +} SEGDESC_t __attribute__((__packed__)); + +typedef uint16_t SEGSEL_t; +typedef uint16_t PXENV_STATUS_t; +typedef uint32_t IP4_t; +typedef uint32_t ADDR32_t; +typedef uint16_t UDP_PORT_t; + +#define MAC_ADDR_LEN 16 +typedef uint8_t MAC_ADDR[MAC_ADDR_LEN]; + +/* PXENV+ */ +typedef struct { + uint8_t Signature[6]; /* 'PXENV+' */ + uint16_t Version; /* MSB = major, LSB = minor */ + uint8_t Length; /* structure length */ + uint8_t Checksum; /* checksum pad */ + SEGOFF16_t RMEntry; /* SEG:OFF to PXE entry point */ + /* don't use PMOffset and PMSelector (from the 2.1 PXE manual) */ + uint32_t PMOffset; /* Protected mode entry */ + SEGSEL_t PMSelector; /* Protected mode selector */ + SEGSEL_t StackSeg; /* Stack segment address */ + uint16_t StackSize; /* Stack segment size (bytes) */ + SEGSEL_t BC_CodeSeg; /* BC Code segment address */ + uint16_t BC_CodeSize; /* BC Code segment size (bytes) */ + SEGSEL_t BC_DataSeg; /* BC Data segment address */ + uint16_t BC_DataSize; /* BC Data segment size (bytes) */ + SEGSEL_t UNDIDataSeg; /* UNDI Data segment address */ + uint16_t UNDIDataSize; /* UNDI Data segment size (bytes) */ + SEGSEL_t UNDICodeSeg; /* UNDI Code segment address */ + uint16_t UNDICodeSize; /* UNDI Code segment size (bytes) */ + SEGOFF16_t PXEPtr; /* SEG:OFF to !PXE struct, + only present when Version > 2.1 */ +} __attribute__((__packed__)) pxenv_t; + +/* !PXE */ +typedef struct { + uint8_t Signature[4]; + uint8_t StructLength; + uint8_t StructCksum; + uint8_t StructRev; + uint8_t reserved_1; + SEGOFF16_t UNDIROMID; + SEGOFF16_t BaseROMID; + SEGOFF16_t EntryPointSP; + SEGOFF16_t EntryPointESP; + SEGOFF16_t StatusCallout; + uint8_t reserved_2; + uint8_t SegDescCn; + SEGSEL_t FirstSelector; + SEGDESC_t Stack; + SEGDESC_t UNDIData; + SEGDESC_t UNDICode; + SEGDESC_t UNDICodeWrite; + SEGDESC_t BC_Data; + SEGDESC_t BC_Code; + SEGDESC_t BC_CodeWrite; +} __attribute__((__packed__)) pxe_t; + +#define PXENV_START_UNDI 0x0000 +typedef struct { + PXENV_STATUS_t Status; + uint16_t ax; + uint16_t bx; + uint16_t dx; + uint16_t di; + uint16_t es; +} __attribute__((__packed__)) t_PXENV_START_UNDI; + +#define PXENV_UNDI_STARTUP 0x0001 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_UNDI_STARTUP; + +#define PXENV_UNDI_CLEANUP 0x0002 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_UNDI_CLEANUP; + +#define PXENV_UNDI_INITIALIZE 0x0003 +typedef struct { + PXENV_STATUS_t Status; + ADDR32_t ProtocolIni; /* Phys addr of a copy of the + driver module */ + uint8_t reserved[8]; +} __attribute__((__packed__)) t_PXENV_UNDI_INITALIZE; + + +#define MAXNUM_MCADDR 8 +typedef struct { + PXENV_STATUS_t Status; + uint16_t MCastAddrCount; + MAC_ADDR McastAddr[MAXNUM_MCADDR]; +} __attribute__((__packed__)) t_PXENV_UNDI_MCAST_ADDRESS; + +#define PXENV_UNDI_RESET_ADAPTER 0x0004 +typedef struct { + PXENV_STATUS_t Status; + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __attribute__((__packed__)) t_PXENV_UNDI_RESET; + +#define PXENV_UNDI_SHUTDOWN 0x0005 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_UNDI_SHUTDOWN; + +#define PXENV_UNDI_OPEN 0x0006 +typedef struct { + PXENV_STATUS_t Status; + uint16_t OpenFlag; + uint16_t PktFilter; +# define FLTR_DIRECTED 0x0001 +# define FLTR_BRDCST 0x0002 +# define FLTR_PRMSCS 0x0003 +# define FLTR_SRC_RTG 0x0004 + + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __attribute__((__packed__)) t_PXENV_UNDI_OPEN; + +#define PXENV_UNDI_CLOSE 0x0007 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_UNDI_CLOSE; + +#define PXENV_UNDI_TRANSMIT 0x0008 +typedef struct { + PXENV_STATUS_t Status; + uint8_t Protocol; +# define P_UNKNOWN 0 +# define P_IP 1 +# define P_ARP 2 +# define P_RARP 3 + + uint8_t XmitFlag; +# define XMT_DESTADDR 0x0000 +# define XMT_BROADCAST 0x0001 + + SEGOFF16_t DestAddr; + SEGOFF16_t TBD; + uint32_t Reserved[2]; +} __attribute__((__packed__)) t_PXENV_UNDI_TRANSMIT; + +#define MAX_DATA_BLKS 8 +typedef struct { + uint16_t ImmedLength; + SEGOFF16_t Xmit; + uint16_t DataBlkCount; + struct DataBlk { + uint8_t TDPtrType; + uint8_t TDRsvdByte; + uint16_t TDDataLen; + SEGOFF16_t TDDataPtr; + } DataBlock[MAX_DATA_BLKS]; +} __attribute__((__packed__)) t_PXENV_UNDI_TBD; + +#define PXENV_UNDI_SET_MCAST_ADDRESS 0x0009 +typedef struct { + PXENV_STATUS_t Status; + t_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf; +} __attribute__((__packed__)) t_PXENV_UNDI_SET_MCAST_ADDR; + +#define PXENV_UNDI_SET_STATION_ADDRESS 0x000A +typedef struct { + PXENV_STATUS_t Status; + MAC_ADDR StationAddress; /* Temp MAC addres to use */ +} __attribute__((__packed__)) t_PXENV_UNDI_SET_STATION_ADDR; + +#define PXENV_UNDI_SET_PACKET_FILTER 0x000B +typedef struct { + PXENV_STATUS_t Status; + uint8_t filter; /* see UNDI_OPEN (0x0006) */ +} __attribute__((__packed__)) t_PXENV_UNDI_SET_PACKET_FILTER; + +#define PXENV_UNDI_GET_INFORMATION 0x000C +typedef struct { + PXENV_STATUS_t Status; + uint16_t BaseIo; /* Adapter base I/O address */ + uint16_t IntNumber; /* Adapter IRQ number */ + uint16_t MaxTranUnit; /* Adapter maximum transmit + unit */ + uint16_t HwType; /* Type of protocol at the + hardware addr */ +# define ETHER_TYPE 1 +# define EXP_ETHER_TYPE 2 +# define IEEE_TYPE 6 +# define ARCNET_TYPE 7 + + uint16_t HwAddrLen; /* Length of hardware address */ + MAC_ADDR CurrentNodeAddress; /* Current hardware address */ + MAC_ADDR PermNodeAddress; /* Permanent hardware address */ + SEGSEL_t ROMAddress; /* Real mode ROM segment + address */ + uint16_t RxBufCt; /* Receive queue length */ + uint16_t TxBufCt; /* Transmit queue length */ +} __attribute__((__packed__)) t_PXENV_UNDI_GET_INFORMATION; + +#define PXENV_UNDI_GET_STATISTICS 0x000D +typedef struct { + PXENV_STATUS_t Status; + uint32_t XmitGoodFrames; /* Number of successful + transmissions */ + uint32_t RcvGoodFrames; /* Number of good frames + received */ + uint32_t RcvCRCErrors; /* Number of frames with + CRC errors */ + uint32_t RcvResourceErrors; /* Number of frames dropped */ +} __attribute__((__packed__)) t_PXENV_UNDI_GET_STATISTICS; + +#define PXENV_UNDI_CLEAR_STATISTICS 0x000E +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_UNDI_CLEAR_STATISTICS; + +#define PXENV_UNDI_INITIATE_DIAGS 0x000F +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_UNDI_INITIATE_DIAGS; + +#define PXENV_UNDI_FORCE_INTERRUPT 0x0010 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_UNDI_FORCE_INTERRUPT; + +#define PXENV_UNDI_GET_MCAST_ADDRESS 0x0011 +typedef struct { + PXENV_STATUS_t Status; + IP4_t InetAddr; /* IP mulicast address */ + MAC_ADDR MediaAddr; /* MAC multicast address */ +} __attribute__((__packed__)) t_PXENV_UNDI_GET_MCAST_ADDR; + +#define PXENV_UNDI_GET_NIC_TYPE 0x0012 +typedef struct { + PXENV_STATUS_t Status; + uint8_t NicType; /* Type of NIC */ +# define PCI_NIC 2 +# define PnP_NIC 3 +# define CardBus_NIC 4 + + union { + struct { + uint16_t Vendor_ID; + uint16_t Dev_ID; + uint8_t Base_Class; + uint8_t Sub_Class; + uint8_t Prog_Intf; + uint8_t Rev; + uint16_t BusDevFunc; + uint16_t SubVendor_ID; + uint16_t SubDevice_ID; + } pci, cardbus; + struct { + uint32_t EISA_Dev_ID; + uint8_t Base_Class; + uint8_t Sub_Class; + uint8_t Prog_Intf; + uint16_t CardSelNum; + } pnp; + } info; +} __attribute__((__packed__)) t_PXENV_UNDI_GET_NIC_TYPE; + +#define PXENV_UNDI_GET_IFACE_INFO 0x0013 +typedef struct { + PXENV_STATUS_t Status; + uint8_t IfaceType[16]; /* Name of MAC type in ASCII. */ + uint32_t LinkSpeed; /* Defined in NDIS 2.0 spec */ + uint32_t ServiceFlags; /* Defined in NDIS 2.0 spec */ + uint32_t Reserved[4]; /* must be 0 */ +} __attribute__((__packed__)) t_PXENV_UNDI_GET_NDIS_INFO; + +#define PXENV_UNDI_ISR 0x0014 +typedef struct { + PXENV_STATUS_t Status; + uint16_t FuncFlag; /* PXENV_UNDI_ISR_OUT_xxx */ + uint16_t BufferLength; /* Length of Frame */ + uint16_t FrameLength; /* Total length of reciever + frame */ + uint16_t FrameHeaderLength; /* Length of the media header + in Frame */ + SEGOFF16_t Frame; /* receive buffer */ + uint8_t ProtType; /* Protocol type */ + uint8_t PktType; /* Packet Type */ +# define PXENV_UNDI_ISR_IN_START 1 +# define PXENV_UNDI_ISR_IN_PROCESS 2 +# define PXENV_UNDI_ISR_IN_GET_NEXT 3 + + /* one of these will be returned for PXENV_UNDI_ISR_IN_START */ +# define PXENV_UNDI_ISR_OUT_OURS 0 +# define PXENV_UNDI_ISR_OUT_NOT_OUTS 1 + + /* + * one of these will bre returnd for PXEND_UNDI_ISR_IN_PROCESS + * and PXENV_UNDI_ISR_IN_GET_NEXT + */ +# define PXENV_UNDI_ISR_OUT_DONE 0 +# define PXENV_UNDI_ISR_OUT_TRANSMIT 2 +# define PXENV_UNDI_ISR_OUT_RECIEVE 3 +# define PXENV_UNDI_ISR_OUT_BUSY 4 +} __attribute__((__packed__)) t_PXENV_UNDI_ISR; + +#define PXENV_STOP_UNDI 0x0015 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_STOP_UNDI; + +#define PXENV_TFTP_OPEN 0x0020 +typedef struct { + PXENV_STATUS_t Status; + IP4_t ServerIPAddress; + IP4_t GatewayIPAddress; + uint8_t FileName[128]; + UDP_PORT_t TFTPPort; + uint16_t PacketSize; +} __attribute__((__packed__)) t_PXENV_TFTP_OPEN; + +#define PXENV_TFTP_CLOSE 0x0021 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_TFTP_CLOSE; + +#define PXENV_TFTP_READ 0x0022 +typedef struct { + PXENV_STATUS_t Status; + uint16_t PacketNumber; + uint16_t BufferSize; + SEGOFF16_t Buffer; +} __attribute__((__packed__)) t_PXENV_TFTP_READ; + +#define PXENV_TFTP_READ_FILE 0x0023 +typedef struct { + PXENV_STATUS_t Status; + uint8_t FileName[128]; + uint32_t BufferSize; + ADDR32_t Buffer; + IP4_t ServerIPAddress; + IP4_t GatewayIPAddress; + IP4_t McastIPAddress; + UDP_PORT_t TFTPClntPort; + UDP_PORT_t TFTPSrvPort; + uint16_t TFTPOpenTimeOut; + uint16_t TFTPReopenDelay; +} __attribute__((__packed__)) t_PXENV_TFTP_READ_FILE; + +#define PXENV_TFTP_GET_FSIZE 0x0025 +typedef struct { + PXENV_STATUS_t Status; + IP4_t ServerIPAddress; + IP4_t GatewayIPAddress; + uint8_t FileName[128]; + uint32_t FileSize; +} __attribute__((__packed__)) t_PXENV_TFTP_GET_FSIZE; + +#define PXENV_UDP_OPEN 0x0030 +typedef struct { + PXENV_STATUS_t status; + IP4_t src_ip; /* IP address of this station */ +} __attribute__((__packed__)) t_PXENV_UDP_OPEN; + +#define PXENV_UDP_CLOSE 0x0031 +typedef struct { + PXENV_STATUS_t status; +} __attribute__((__packed__)) t_PXENV_UDP_CLOSE; + +#define PXENV_UDP_READ 0x0032 +typedef struct { + PXENV_STATUS_t status; + IP4_t src_ip; /* IP of sender */ + IP4_t dest_ip; /* Only accept packets sent to + this IP */ + UDP_PORT_t s_port; /* UDP source port of sender */ + UDP_PORT_t d_port; /* Only accept packets sent to + this port */ + uint16_t buffer_size; /* Size of the packet buffer */ + SEGOFF16_t buffer; /* SEG:OFF to the packet buffer */ +} __attribute__((__packed__)) t_PXENV_UDP_READ; + +#define PXENV_UDP_WRITE 0x0033 +typedef struct { + PXENV_STATUS_t status; + IP4_t ip; /* dest ip addr */ + IP4_t gw; /* ip gateway */ + UDP_PORT_t src_port; /* source udp port */ + UDP_PORT_t dst_port; /* destination udp port */ + uint16_t buffer_size; /* Size of the packet buffer */ + SEGOFF16_t buffer; /* SEG:OFF to the packet buffer */ +} __attribute__((__packed__)) t_PXENV_UDP_WRITE; + +#define PXENV_UNLOAD_STACK 0x0070 +typedef struct { + PXENV_STATUS_t Status; + uint8_t reserved[10]; +} __attribute__((__packed__)) t_PXENV_UNLOAD_STACK; + + +#define PXENV_GET_CACHED_INFO 0x0071 +typedef struct { + PXENV_STATUS_t Status; + uint16_t PacketType; /* type (defined right here) */ +# define PXENV_PACKET_TYPE_DHCP_DISCOVER 1 +# define PXENV_PACKET_TYPE_DHCP_ACK 2 +# define PXENV_PACKET_TYPE_CACHED_REPLY 3 + uint16_t BufferSize; /* max to copy, leave at 0 for + pointer */ + SEGOFF16_t Buffer; /* copy to, leave at 0 for pointer */ + uint16_t BufferLimit; /* max size of buffer in BC dataseg ? */ +} __attribute__((__packed__)) t_PXENV_GET_CACHED_INFO; + + +/* structure filled in by PXENV_GET_CACHED_INFO + * (how we determine which IP we downloaded the initial bootstrap from) + * words can't describe... + */ +typedef struct { + uint8_t opcode; +# define BOOTP_REQ 1 +# define BOOTP_REP 2 + uint8_t Hardware; /* hardware type */ + uint8_t Hardlen; /* hardware addr len */ + uint8_t Gatehops; /* zero it */ + uint32_t ident; /* random number chosen by client */ + uint16_t seconds; /* seconds since did initial + bootstrap */ + uint16_t Flags; /* seconds since did initial + bootstrap */ +# define BOOTP_BCAST 0x8000 /* ? */ + IP4_t cip; /* Client IP */ + IP4_t yip; /* Your IP */ + IP4_t sip; /* IP to use for next boot stage */ + IP4_t gip; /* Relay IP ? */ + MAC_ADDR CAddr; /* Client hardware address */ + uint8_t Sname[64]; /* Server's hostname (Optional) */ + uint8_t bootfile[128]; /* boot filename */ + union { +# if 1 +# define BOOTP_DHCPVEND 1024 /* DHCP extended vendor + field size */ +# else +# define BOOTP_DHCPVEND 312 /* DHCP standard vendor + field size */ +# endif + uint8_t d[BOOTP_DHCPVEND]; /* raw array of + vendor/dhcp options */ + struct { + uint8_t magic[4]; /* DHCP magic cookie */ +# ifndef VM_RFC1048 +# define VM_RFC1048 0x63825363L /* ? */ +# endif + uint32_t flags; /* bootp flags/opcodes */ + uint8_t pad[56]; /* I don't think intel + knows what a union + does... */ + } v; + } vendor; +} __attribute__((__packed__)) BOOTPLAYER; + +#define PXENV_RESTART_TFTP 0x0073 +#define t_PXENV_RESTART_TFTP t_PXENV_TFTP_READ_FILE + +#define PXENV_START_BASE 0x0075 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_START_BASE; + +#define PXENV_STOP_BASE 0x0076 +typedef struct { + PXENV_STATUS_t Status; +} __attribute__((__packed__)) t_PXENV_STOP_BASE; + +#define PXENV_STATUS_SUCCESS 0 +#define PXENV_STATUS_FAILURE 1 +/* ...there are tons more, but we don't really care about them right now... */ diff --git a/sys/arch/amd64/stand/libsa/pxe_call.S b/sys/arch/amd64/stand/libsa/pxe_call.S new file mode 100644 index 00000000000..81247ebe423 --- /dev/null +++ b/sys/arch/amd64/stand/libsa/pxe_call.S @@ -0,0 +1,202 @@ +/* $OpenBSD: pxe_call.S,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD: pxe_call.S,v 1.2 2002/03/27 17:24:22 kanaoka Exp $ */ + +/* + * Copyright 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * 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 for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* + * Low level PXE BIOS call glue. + */ + +#include <machine/asm.h> +#include <assym.h> + +#include "gidt.h" + +ENTRY(pxecall_bangpxe) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + + /* For simplicity, just move all 32 bits. */ + movl 8(%ebp), %ebx + + pushw _C_LABEL(pxe_command_buf_seg) + pushw _C_LABEL(pxe_command_buf_off) + pushw %bx + + call prot_to_real /* Enter real mode */ + .code16 + + sti + /* The encoding is: 0x9a offlo offhi seglo seghi */ + lcall $0, $0xffff + .globl _C_LABEL(bangpxe_off) +_C_LABEL(bangpxe_off) = . - 4 + .globl _C_LABEL(bangpxe_seg) +_C_LABEL(bangpxe_seg) = . - 2 + + cli + call real_to_prot /* Leave real mode */ + .code32 + + add $6, %esp + + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +ENTRY(pxecall_pxenv) + .code32 + pushl %ebp + movl %esp, %ebp + pushl %ebx + pushl %ecx + pushl %edx + pushl %edi + + /* For simplicity, just move all 32 bits. */ + movl 8(%ebp), %ebx + + call prot_to_real /* Enter real mode */ + .code16 + + /* prot_to_real() has already set %es to BOOTSEG */ + lea _C_LABEL(pxe_command_buf), %di + + /* The encoding is: 0x9a offlo offhi seglo seghi */ + lcall $0, $0xffff + .globl _C_LABEL(pxenv_off) +_C_LABEL(pxenv_off) = . - 4 + .globl _C_LABEL(pxenv_seg) +_C_LABEL(pxenv_seg) = . - 2 + + call real_to_prot /* Leave real mode */ + .code32 + + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %ebp + ret + +/* + * prot_to_real() + * + * Switch the processor back into real mode. + */ + .globl prot_to_real +prot_to_real: + .code32 + ljmp $S16TEXT, $p2r16 - LINKADDR +p2r16: + .code16 + + movw $S16DATA, %ax + movw %ax, %ds + movw %ax, %es + + movl %cr0, %eax /* Disable protected mode */ + andl $~CR0_PE, %eax + movl %eax, %cr0 + + /* reload real cs:ip */ + data32 ljmp $(LINKADDR >> 4), $p2r16real - LINKADDR +p2r16real: + xorw %ax, %ax /* Reset segment registers: */ + movw %ax, %ds /* %ds: so we can get at Idtr_real */ + movw %ax, %ss /* %ss: for our stack */ + + .extern Idtr_real + data32 addr32 lidt Idtr_real; /* Set up IDT for real mode */ + + movw %cs, %ax + movw %ax, %ds + movw %ax, %es /* Set %ds = %es = %cs */ + + /* + * We were called from 32-bit mode, so there's a 32-bit + * return address on the stack. No segment. This is within + * the flat memory model, so we need to adjust it back so + * that it's relative to our 16-bit %cs. + */ + popl %eax + subl $LINKADDR, %eax + pushw %ax + ret + +/* + * real_to_prot() + * + * Switch the processor back into protected mode. + */ + .globl real_to_prot +real_to_prot: + .code16 + + xorw %ax, %ax + movw %ax, %ds /* Load %ds so we can get at Gdtr */ + data32 addr32 lgdt Gdtr /* Load the GDT */ + + movl %cr0, %eax /* Enable protected mode */ + orl $CR0_PE, %eax + movl %eax, %cr0 + + data32 ljmp $S32TEXT, $r2p32 /* Reload %cs, flush pipeline */ +r2p32: + .code32 + /* Reload 32-bit %ds, %ss, %es */ + movl $S32DATA, %eax + mov %ax, %ds + mov %ax, %ss + mov %ax, %es + + /* Load IDT for debugger and DOS/BIOS interface */ + .extern Idtr + lidt Idtr + + xorl %eax, %eax + popw %ax /* 16-bit return addr on stack */ + addl $LINKADDR, %eax + pushl %eax /* Now have correct 32-bit ret addr */ + ret + + .end diff --git a/sys/arch/amd64/stand/libsa/pxe_net.c b/sys/arch/amd64/stand/libsa/pxe_net.c new file mode 100644 index 00000000000..310df6d4d39 --- /dev/null +++ b/sys/arch/amd64/stand/libsa/pxe_net.c @@ -0,0 +1,183 @@ +/* $OpenBSD: pxe_net.c,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD: dev_net.c,v 1.4 2003/03/12 13:15:08 drochner Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Gordon W. Ross. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 module implements a "raw device" interface suitable for + * use by the stand-alone I/O library NFS and TFTP code. This interface + * does not support any "block" access, and exists only for the + * purpose of initializing the network interface and getting boot + * parameters. + * + * At open time, this does: + * + * find interface - netif_open() + * BOOTP for IP address - bootp() + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> + +#include <lib/libkern/libkern.h> + +#include <lib/libsa/stand.h> +#include <lib/libsa/net.h> +#include "pxe_netif.h" +#include "pxe_net.h" + +static int netdev_sock = -1; +static int netdev_opens; + +int net_getparams(int); + +/* + * Called by devopen after it sets f->f_dev to our devsw entry. + * This opens the low-level device and sets f->f_devdata. + * This is declared with variable arguments... + */ +int +net_open(struct open_file *f, ...) +{ + int error = 0; + +#ifdef NETIF_DEBUG + if (debug) + printf("net_open()\n"); +#endif + + /* On first open, do netif open, mount, etc. */ + if (netdev_opens == 0) { + /* Find network interface. */ + if (netdev_sock < 0) { + netdev_sock = pxe_netif_open(); + if (netdev_sock < 0) { + printf("net_open: netif_open() failed\n"); + return ENXIO; + } +#ifdef NETIF_DEBUG + if (debug) + printf("net_open: netif_open() succeeded\n"); +#endif + } +#ifdef notyet + if (rootip.s_addr == 0) { + /* Get root IP address, and path, etc. */ + error = net_getparams(netdev_sock); + if (error) { + /* getparams makes its own noise */ + pxe_netif_close(netdev_sock); + netdev_sock = -1; + return error; + } + } +#endif + } + netdev_opens++; + f->f_devdata = &netdev_sock; + return error; +} + +int +net_close(struct open_file *f) +{ +#ifdef NETIF_DEBUG + if (debug) + printf("net_close: opens=%d\n", netdev_opens); +#endif + + /* On last close, do netif close, etc. */ + f->f_devdata = NULL; + /* Extra close call? */ + if (netdev_opens <= 0) + return 0; + netdev_opens--; + /* Not last close? */ + if (netdev_opens > 0) + return 0; + rootip.s_addr = 0; + if (netdev_sock >= 0) { +#ifdef NETIF_DEBUG + if (debug) + printf("net_close: calling netif_close()\n"); +#endif + pxe_netif_close(netdev_sock); + netdev_sock = -1; + } + return 0; +} + +int +net_ioctl(struct open_file *f, u_long cmd, void *data) +{ + return EIO; +} + +int +net_strategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf, + size_t *rsize) +{ + return EIO; +} + + +/* + * Get info for network boot: our IP address, our hostname, + * server IP address, and our root path on the server. + */ +extern int bootp(int); + +int +net_getparams(int sock) +{ + /* + * Try to get boot info using BOOTP. If we succeed, then + * the server IP address, gateway, and root path will all + * be initialized. If any remain uninitialized, we will + * use RARP and RPC/bootparam (the Sun way) to get them. + */ + bootp(sock); + if (myip.s_addr != 0) + return 0; + if (debug) + printf("net_getparams: BOOTP failed\n"); + + return EIO; +} diff --git a/sys/arch/amd64/stand/libsa/pxe_net.h b/sys/arch/amd64/stand/libsa/pxe_net.h new file mode 100644 index 00000000000..59d61fba3bf --- /dev/null +++ b/sys/arch/amd64/stand/libsa/pxe_net.h @@ -0,0 +1,44 @@ +/* $OpenBSD: pxe_net.h,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD$ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Gordon W. Ross. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* pxe_net.c */ +int net_open(struct open_file *, ...); +int net_close(struct open_file *); +int net_ioctl(struct open_file *, u_long, void *); +int net_strategy(void *, int , daddr_t , size_t, void *, size_t *); diff --git a/sys/arch/amd64/stand/libsa/pxe_netif.h b/sys/arch/amd64/stand/libsa/pxe_netif.h new file mode 100644 index 00000000000..a987e1ad78b --- /dev/null +++ b/sys/arch/amd64/stand/libsa/pxe_netif.h @@ -0,0 +1,43 @@ +/* $OpenBSD: pxe_netif.h,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD$ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Gordon W. Ross. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +/* pxe.c */ +int pxe_netif_open(void); +void pxe_netif_close(int); +void pxe_netif_shutdown(void); diff --git a/sys/arch/amd64/stand/libsa/pxeboot.h b/sys/arch/amd64/stand/libsa/pxeboot.h new file mode 100644 index 00000000000..1930635d049 --- /dev/null +++ b/sys/arch/amd64/stand/libsa/pxeboot.h @@ -0,0 +1,53 @@ +/* $OpenBSD: pxeboot.h,v 1.1 2004/03/21 21:37:41 tom Exp $ */ +/* $NetBSD$ */ + +/* + * Copyright 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * 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 for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC + * 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. + */ + +/* Flat address space for [pxe]boot in protected mode */ +#define VTOPSEG(vaddr) (((u_int32_t) vaddr) >> 4) +#define VTOPOFF(vaddr) (((u_int32_t) vaddr) & 0xf) + +#define SEGOFF2FLAT(seg, off) ((void *)((((u_int32_t)(seg))<<4) + \ + ((u_int32_t)(off)))) + +void pxeprobe(void); +void pxeinfo(void); + +ssize_t pxesendudp(struct iodesc *, void *, size_t); +ssize_t pxereadudp(struct iodesc *, void *, size_t, time_t); + +int pxe_init(int); +void pxe_shutdown(void); |