netboot is now in the tree. the argument that finally resulted in it being here

will also keep netboot from compiling until fixes are made.
This commit is contained in:
glass 1993-10-12 06:02:08 +00:00
parent b9e5a43208
commit 428bb7f594
18 changed files with 2473 additions and 0 deletions

5
sys/boot/Makefile Normal file
View File

@ -0,0 +1,5 @@
CFLAGS = -g -I../../../ -I../../../../include
PROG = netboot
SRCS = arp.c bootp.c conf.c exec.c in_cksum.c netif.c net.c nfsboot.c rpc.c ut
.PATH: ../../common/netboot
+

12
sys/boot/TODO Normal file
View File

@ -0,0 +1,12 @@
Necessary:
need support for bootparam
small printf
hooks for bootstrapping
multiple ethernets
nfs diskless stuff, i.e do we change the thing, and how.
High Priority:
Low Priority:
remove ether-orientation? FDDI support?

191
sys/boot/arp.c Normal file
View File

@ -0,0 +1,191 @@
/*
* 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: /cvsroot/src/sys/boot/Attic/arp.c,v 1.1 1993/10/12 06:02:14 glass Exp $ (LBL)
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <errno.h>
#include "config.h"
#include "netboot.h"
#include "bootbootp.h"
/* Cache stuff */
#define ARP_NUM 8 /* need at most 3 arp entries */
static struct arp_list {
n_long addr;
u_char ea[6];
} arp_list[ARP_NUM] = {
{ INADDR_BROADCAST, BA }
};
static int arp_num = 1;
/* Local forwards */
static int arpsend __P((struct iodesc *, void *, int));
static int arprecv __P((struct iodesc *, void *, int));
/* Broadcast an ARP packet, asking who has addr on interface d */
u_char *
arpwhohas(d, addr)
register struct iodesc *d;
n_long addr;
{
register int i;
register struct ether_arp *ah;
register struct arp_list *al;
struct {
u_char header[ETHER_SIZE];
struct ether_arp warp;
} wbuf;
union {
u_char buffer[RECV_SIZE];
struct {
u_char header[ETHER_SIZE];
struct ether_arp rarp;
} ru;
} rbuf;
if (debug)
printf("arpwhohas: called\n");
/* Try for cached answer first */
for (i = 0, al = arp_list; i < arp_num; ++i, ++al)
if (addr == al->addr)
return (al->ea);
/* Don't overflow cache */
if (arp_num > ARP_NUM - 1)
panic("arpwhohas: overflowed arp_list!");
if (debug)
printf("arpwhohas: not cached\n");
ah = &wbuf.warp;
bzero(ah, sizeof(*ah));
ah->arp_hrd = htons(ARPHRD_ETHER);
ah->arp_pro = htons(ETHERTYPE_IP);
ah->arp_hln = sizeof(ah->arp_sha); /* hardware address length */
ah->arp_pln = sizeof(ah->arp_spa); /* protocol address length */
ah->arp_op = htons(ARPOP_REQUEST);
MACPY(d->myea, ah->arp_sha);
bcopy(&d->myip, ah->arp_spa, sizeof(ah->arp_spa));
bcopy(&addr, ah->arp_tpa, sizeof(ah->arp_tpa));
/* Store ip address in cache */
al->addr = addr;
(void)sendrecv(d, arpsend, ah, sizeof(*ah), arprecv,
((u_char *)&rbuf.ru.rarp) - ETHER_SIZE,
ETHER_SIZE + sizeof(rbuf.ru.rarp));
/* Store ethernet address in cache */
MACPY(rbuf.ru.rarp.arp_sha, al->ea);
++arp_num;
return (al->ea);
}
static int
arpsend(d, pkt, len)
register struct iodesc *d;
register void *pkt;
register int len;
{
if (debug)
printf("arpsend: called\n");
return (sendether(d, pkt, len, bcea, ETHERTYPE_ARP));
}
/* Returns 0 if this is the packet we're waiting for else -1 (and errno == 0) */
static int
arprecv(d, pkt, len)
register struct iodesc *d;
register void *pkt;
register int len;
{
register struct ether_header *eh;
register struct ether_arp *ah;
if (debug)
printf("arprecv: called\n");
if (len < sizeof(*eh) + sizeof(*ah)) {
errno = 0;
return (-1);
}
eh = (struct ether_header *)pkt;
/* Must be to us */
if (bcmp(d->myea, eh->ether_dhost, 6) != 0 &&
bcmp(bcea, eh->ether_dhost, 6) != 0) {
errno = 0;
return (-1);
}
if (eh->ether_type != ETHERTYPE_ARP) {
errno = 0;
return (-1);
}
ah = (struct ether_arp *)(eh + 1);
HTONS(ah->arp_hrd);
HTONS(ah->arp_pro);
HTONS(ah->arp_op);
if (ah->arp_hrd != ARPHRD_ETHER || ah->arp_pro != ETHERTYPE_IP ||
ah->arp_hln != sizeof(ah->arp_sha) ||
ah->arp_pln != sizeof(ah->arp_spa) || ah->arp_op != ARPOP_REPLY) {
errno = 0;
return (-1);
}
if (bcmp(&arp_list[arp_num].addr, ah->arp_spa, sizeof(long)) != 0 ||
bcmp(&d->myip, ah->arp_tpa, sizeof(d->myip)) != 0) {
errno = 0;
return (-1);
}
return (0);
}

41
sys/boot/bootbootp.h Normal file
View File

@ -0,0 +1,41 @@
/*
* 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: /cvsroot/src/sys/boot/Attic/bootbootp.h,v 1.1 1993/10/12 06:02:15 glass Exp $ (LBL)
*/
void bootp __P((struct iodesc *));

18
sys/boot/bootinfo.c Normal file
View File

@ -0,0 +1,18 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/cdefs.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include "netboot.h"
#include "config.h"
#include "bootbootp.h"
#include "bootp.h"
#include "netif.h"
void get_bootinfo(desc)
struct iodesc *desc;
{
bootp(desc);
}

237
sys/boot/bootp.c Normal file
View File

@ -0,0 +1,237 @@
/*
* 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: /cvsroot/src/sys/boot/Attic/bootp.c,v 1.1 1993/10/12 06:02:18 glass Exp $ (LBL)
*/
#include <sys/param.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <errno.h>
#include "netboot.h"
#include "config.h"
#include "bootbootp.h"
#include "bootp.h"
/* Machinery used to insure we don't stop until we have everything we need */
#define BOOT_MYIP 0x01
#define BOOT_ROOT 0x02
#define BOOT_SWAP 0x04
#define BOOT_GATEIP 0x08 /* optional */
#define BOOT_SMASK 0x10 /* optional */
#define BOOT_UCRED 0x20 /* not implemented */
static int have;
static int need = BOOT_MYIP | BOOT_ROOT | BOOT_SWAP;
/* Local forwards */
static int bootpsend __P((struct iodesc *, void *, int));
static int bootprecv __P((struct iodesc*, void *, int));
/* Fetch required bootp infomation */
void
bootp(d)
register struct iodesc *d;
{
register struct bootp *bp;
register void *pkt;
struct {
u_char header[HEADER_SIZE];
struct bootp wbootp;
} wbuf;
union {
u_char buffer[RECV_SIZE];
struct {
u_char header[HEADER_SIZE];
struct bootp xrbootp;
}xrbuf;
#define rbootp xrbuf.xrbootp
} rbuf;
if (debug)
printf("bootp: called\n");
have = 0;
bp = &wbuf.wbootp;
pkt = &rbuf.rbootp;
pkt = (((char *) pkt) - HEADER_SIZE);
bzero(bp, sizeof(*bp));
bp->bp_op = BOOTREQUEST;
bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */
bp->bp_hlen = 6;
MACPY(d->myea, bp->bp_chaddr);
d->myport = IPPORT_BOOTPC;
d->destport = IPPORT_BOOTPS;
d->destip = INADDR_BROADCAST;
while ((have & need) != need) {
if (debug)
printf("bootp: sendrecv\n");
(void)sendrecv(d, bootpsend, bp, sizeof(*bp),
bootprecv, pkt, RECV_SIZE);
}
}
/* Transmit a bootp request */
static int
bootpsend(d, pkt, len)
register struct iodesc *d;
register void *pkt;
register int len;
{
register struct bootp *bp;
if (debug)
printf("bootpsend: called\n");
bp = pkt;
bzero(bp->bp_file, sizeof(bp->bp_file));
if ((have & BOOT_ROOT) == 0)
strcpy((char *)bp->bp_file, "root");
else if ((have & BOOT_SWAP) == 0)
strcpy((char *)bp->bp_file, "swap");
bp->bp_xid = d->xid;
bp->bp_secs = (u_long)(getsecs() - bot);
if (debug)
printf("bootpsend: calling sendudp\n");
return (sendudp(d, pkt, len));
}
/* Returns 0 if this is the packet we're waiting for else -1 (and errno == 0) */
static int
bootprecv(d, pkt, len)
register struct iodesc *d;
register void *pkt;
int len;
{
register struct bootp *bp;
register struct cmu_vend *vp;
if (debug)
printf("bootprecv: called\n");
bp = (struct bootp *)checkudp(d, pkt, &len);
if (bp == NULL || len < sizeof(*bp)) {
errno = 0;
return (-1);
}
if (bp->bp_xid != d->xid) {
errno = 0;
return (-1);
}
vp = (struct cmu_vend *)bp->bp_vend;
if (bcmp(VM_CMU, vp->v_magic, sizeof(vp->v_magic)) != 0) {
printf("bootprecv: not cmu magic\n");
vp = NULL;
}
/* Suck out all we can */
if (bp->bp_yiaddr.s_addr != 0 && (have & BOOT_MYIP) == 0) {
have |= BOOT_MYIP;
d->myip = bp->bp_yiaddr.s_addr;
if (IN_CLASSA(d->myip))
nmask = IN_CLASSA_NET;
else if (IN_CLASSB(d->myip))
nmask = IN_CLASSB_NET;
else
nmask = IN_CLASSC_NET;
}
if (vp && vp->v_smask.s_addr != 0 && (have & BOOT_SMASK) == 0) {
have |= BOOT_SMASK;
smask = vp->v_smask.s_addr;
}
if (vp && vp->v_dgate.s_addr != 0 && (have & BOOT_GATEIP) == 0) {
have |= BOOT_GATEIP;
gateip = vp->v_dgate.s_addr;
}
if (bp->bp_giaddr.s_addr != 0 && bp->bp_file[0] != '\0') {
if ((have & BOOT_ROOT) == 0) {
have |= BOOT_ROOT;
rootip = bp->bp_giaddr.s_addr;
strncpy(rootpath, (char *)bp->bp_file,
sizeof(rootpath));
rootpath[sizeof(rootpath) - 1] = '\0';
/* Bump xid so next request will be unique */
++d->xid;
} else if ((have & BOOT_SWAP) == 0) {
have |= BOOT_SWAP;
swapip = bp->bp_giaddr.s_addr;
strncpy(swappath, (char *)bp->bp_file,
sizeof(swappath));
swappath[sizeof(swappath) - 1] = '\0';
/* Bump xid so next request will be unique */
++d->xid;
}
}
/* Done if we don't know our ip address yet */
if ((have & BOOT_MYIP) == 0) {
errno = 0;
return (-1);
}
/* Check subnet mask against net mask; toss if bogus */
if ((have & BOOT_SMASK) != 0 && (nmask & smask) != nmask) {
smask = 0;
have &= ~BOOT_SMASK;
}
/* Get subnet (or net) mask */
mask = nmask;
if ((have & BOOT_SMASK) != 0)
mask = smask;
/* We need a gateway if root or swap is on a different net */
if ((have & BOOT_ROOT) != 0 && !SAMENET(d->myip, rootip, mask))
need |= BOOT_GATEIP;
if ((have & BOOT_SWAP) != 0 && !SAMENET(d->myip, swapip, mask))
need |= BOOT_GATEIP;
/* Toss gateway if on a different net */
if ((have & BOOT_GATEIP) != 0 && !SAMENET(d->myip, gateip, mask)) {
gateip = 0;
have &= ~BOOT_GATEIP;
}
return (0);
}

103
sys/boot/bootp.h Normal file
View File

@ -0,0 +1,103 @@
/* @(#) $Header: /cvsroot/src/sys/boot/Attic/bootp.h,v 1.1 1993/10/12 06:02:20 glass Exp $ (LBL) */
/*
* Bootstrap Protocol (BOOTP). RFC951 and RFC1048.
*
* This file specifies the "implementation-independent" BOOTP protocol
* information which is common to both client and server.
*
* Copyright 1988 by Carnegie Mellon.
*
* Permission to use, copy, modify, and distribute this program for any
* purpose and without fee is hereby granted, provided that this copyright
* and permission notice appear on all copies and supporting documentation,
* the name of Carnegie Mellon not be used in advertising or publicity
* pertaining to distribution of the program without specific prior
* permission, and notice be given in supporting documentation that copying
* and distribution is by permission of Carnegie Mellon and Stanford
* University. Carnegie Mellon makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
struct bootp {
unsigned char bp_op; /* packet opcode type */
unsigned char bp_htype; /* hardware addr type */
unsigned char bp_hlen; /* hardware addr length */
unsigned char bp_hops; /* gateway hops */
unsigned long bp_xid; /* transaction ID */
unsigned short bp_secs; /* seconds since boot began */
unsigned short bp_unused;
struct in_addr bp_ciaddr; /* client IP address */
struct in_addr bp_yiaddr; /* 'your' IP address */
struct in_addr bp_siaddr; /* server IP address */
struct in_addr bp_giaddr; /* gateway IP address */
unsigned char bp_chaddr[16]; /* client hardware address */
unsigned char bp_sname[64]; /* server host name */
unsigned char bp_file[128]; /* boot file name */
unsigned char bp_vend[64]; /* vendor-specific area */
};
/*
* UDP port numbers, server and client.
*/
#define IPPORT_BOOTPS 67
#define IPPORT_BOOTPC 68
#define BOOTREPLY 2
#define BOOTREQUEST 1
/*
* Vendor magic cookie (v_magic) for CMU
*/
#define VM_CMU "CMU"
/*
* Vendor magic cookie (v_magic) for RFC1048
*/
#define VM_RFC1048 { 99, 130, 83, 99 }
/*
* RFC1048 tag values used to specify what information is being supplied in
* the vendor field of the packet.
*/
#define TAG_PAD ((unsigned char) 0)
#define TAG_SUBNET_MASK ((unsigned char) 1)
#define TAG_TIME_OFFSET ((unsigned char) 2)
#define TAG_GATEWAY ((unsigned char) 3)
#define TAG_TIME_SERVER ((unsigned char) 4)
#define TAG_NAME_SERVER ((unsigned char) 5)
#define TAG_DOMAIN_SERVER ((unsigned char) 6)
#define TAG_LOG_SERVER ((unsigned char) 7)
#define TAG_COOKIE_SERVER ((unsigned char) 8)
#define TAG_LPR_SERVER ((unsigned char) 9)
#define TAG_IMPRESS_SERVER ((unsigned char) 10)
#define TAG_RLP_SERVER ((unsigned char) 11)
#define TAG_HOSTNAME ((unsigned char) 12)
#define TAG_BOOTSIZE ((unsigned char) 13)
#define TAG_END ((unsigned char) 255)
/*
* "vendor" data permitted for CMU bootp clients.
*/
struct cmu_vend {
unsigned char v_magic[4]; /* magic number */
unsigned long v_flags; /* flags/opcodes, etc. */
struct in_addr v_smask; /* Subnet mask */
struct in_addr v_dgate; /* Default gateway */
struct in_addr v_dns1, v_dns2; /* Domain name servers */
struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */
struct in_addr v_ts1, v_ts2; /* Time servers */
unsigned char v_unused[25]; /* currently unused */
};
/* v_flags values */
#define VF_SMASK 1 /* Subnet mask field contains valid data */

35
sys/boot/bootparam.c Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 1993 Adam Glass
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Adam Glass.
* 4. The name of the Author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Adam Glass ``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: /cvsroot/src/sys/boot/Attic/bootparam.c,v 1.1 1993/10/12 06:02:23 glass Exp $
*/
#include "netboot.h"
#include "config.h"

206
sys/boot/exec.c Normal file
View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 1993 Adam Glass
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Adam Glass.
* 4. The name of the Author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Adam Glass ``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: /cvsroot/src/sys/boot/Attic/exec.c,v 1.1 1993/10/12 06:02:25 glass Exp $
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/cdefs.h>
#include <sys/mount.h>
#include <sys/exec.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <a.out.h>
#include "netboot.h"
#include "config.h"
#include "netif.h"
#include "exec_var.h"
char *kern_names[] = {
"netbsd", "onetbsd", "netbsd.old",
MACHINE "bsd", "o" MACHINE "bsd", MACHINE "bsd.old"
"vmunix", "ovmunix", "vmunix.old", NULL
};
void nfs_load_image(desc, image, ev)
struct iodesc *desc;
char *image;
struct exec_var *ev;
{
u_long t;
t = gettenths();
printf("%s: ", image);
readseg(desc, ev->text_info.file_offset,
ev->text_info.segment_size, ev->text_info.segment_va);
printf("%d", ev->text_info.segment_size);
readseg(desc, ev->data_info.file_offset,
ev->data_info.segment_size, ev->data_info.segment_va);
printf("+%d", ev->data_info.segment_size);
printf("+%d", ev->bss_info.segment_size);
t = gettenths() - t;
printf(" [%d.%d seconds]\n", t/10, t%10);
}
unsigned int nfs_load(desc, nfsdp, image)
struct iodesc *desc;
struct nfs_diskless **nfsdp;
char *image;
{
struct exec_var ev;
/* get fundamental parameters */
if (machdep_exec_override(desc, &ev))
if (netbsd_exec(desc, &ev))
if (machdep_exec(desc, &ev))
panic("nfs_load: unable to understand image");
machdep_exec_setup(&ev);
nfs_load_image(desc, image, &ev);
if (ev.nfs_disklessp)
*nfsdp = (struct nfs_diskless *) ev.nfs_disklessp;
return ev.real_entry_point;
}
int netbsd_exec_compute(exec, ev)
struct exec exec;
struct exec_var *ev;
{
bzero(ev, sizeof(*ev));
ev->text_info.file_offset = N_TXTOFF(exec);
ev->text_info.segment_size = exec.a_text;
ev->text_info.segment_addr = N_TXTADDR(exec) + exec.a_entry;
ev->data_info.file_offset = N_DATOFF(exec);
ev->data_info.segment_size = exec.a_data;
ev->data_info.segment_addr = N_DATADDR(exec) + exec.a_entry;
ev->bss_info.file_offset = 0;
ev->bss_info.segment_size = exec.a_bss;
ev->bss_info.segment_addr = N_DATADDR(exec)+exec.a_data + exec.a_entry;
ev->entry_point = exec.a_entry;
return 0;
}
int netbsd_exec(desc, ev)
struct iodesc *desc;
struct exec_var *ev;
{
int cc, error;
u_long midmag, magic;
u_short mid;
struct exec exec;
cc = readdata(desc, 0, &exec, sizeof(exec));
if (cc != sizeof(exec))
panic("netbsd_exec: image appears truncated\n");
if (cc < 0)
panic("netbsd_exec: bad exec read\n");
if (N_GETMID(exec) != MID_MACHINE) {
error = 1;
goto failed;
}
if (N_BADMAG(exec)) {
error = 1;
goto failed;
}
error = netbsd_exec_compute(exec, ev);
failed:
if (error)
printf("netbsd_exec: bad exec? code %d\n", error);
return error;
}
void nfs_exec(desc, kernel_override)
struct iodesc *desc;
char *kernel_override;
{
time_t tenths;
char *image;
u_long ftype, bytes;
u_char image_fh[NFS_FHSIZE];
struct nfs_diskless *nfsd;
unsigned int call_addr;
nfsd = NULL;
image = NULL;
if (kernel_override) {
image = kernel_override;
/* Get image file handle and size */
if (lookupfh(desc, image, image_fh, NULL, &bytes, &ftype) < 0)
panic("nfs_exec: lookup failed %s: %s", image, strerror(errno));
if (ftype != NFREG)
panic("nfs_exec: bad image ftype %d", ftype);
}
else {
int i;
for (i = 0; kern_names[i]; i++) {
if (lookupfh(desc, kern_names[i], image_fh, NULL,
&bytes, &ftype) < 0)
continue;
if (ftype != NFREG)
panic("nfs_exec: %s, bad image ftype %d",
kern_names[i], ftype);
image = kern_names[i];
break;
}
if (!image)
panic("nfs_exec: couldn't find kernel");
}
printf("nfs_exec: %s\n", image);
desc->fh = image_fh;
call_addr = nfs_load(desc, &nfsd, image);
#if 0
if (nfsd)
nfs_diskless_munge(nfsd);
#endif
/* Now we're ready to fill in the nfs_diskless struct */
#if 0
if (nfsd)
diskless_setup(desc, (struct nfs_diskless_v1 *)sym);
#endif
}

50
sys/boot/exec_var.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 1993 Adam Glass
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Adam Glass.
* 4. The name of the Author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Adam Glass ``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: /cvsroot/src/sys/boot/Attic/exec_var.h,v 1.1 1993/10/12 06:02:26 glass Exp $
*/
struct exec_var_addr {
unsigned int file_offset;
unsigned int segment_size;
unsigned int segment_addr;
unsigned int segment_va;
};
typedef struct exec_var_addr exec_var_addr;
struct exec_var {
unsigned int entry_point;
unsigned int real_entry_point;
caddr_t nfs_disklessp;
exec_var_addr text_info;
exec_var_addr data_info;
exec_var_addr bss_info;
};

81
sys/boot/in_cksum.c Normal file
View File

@ -0,0 +1,81 @@
/*
* 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: /cvsroot/src/sys/boot/Attic/in_cksum.c,v 1.1 1993/10/12 06:02:28 glass Exp $ (LBL)
*/
#include <sys/types.h>
/*
* Checksum routine for Internet Protocol family headers.
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
* In particular, it should not be this one.
*/
int
in_cksum(p, len)
register void *p;
register int len;
{
register int sum = 0, oddbyte = 0, v = 0;
register u_char *cp = p;
/* we assume < 2^16 bytes being summed */
while (len > 0) {
if (oddbyte) {
sum += v + *cp++;
len--;
}
if (((int)cp & 1) == 0) {
while ((len -= 2) >= 0) {
sum += *(u_short *)cp;
cp += 2;
}
} else {
while ((len -= 2) >= 0) {
sum += *cp++ << 8;
sum += *cp++;
}
}
if ((oddbyte = len & 1) != 0)
v = *cp << 8;
}
if (oddbyte)
sum += v;
sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */
sum += sum >> 16; /* add potential last carry */
return (0xffff & ~sum);
}

290
sys/boot/net.c Normal file
View File

@ -0,0 +1,290 @@
/*
* 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: /cvsroot/src/sys/boot/Attic/net.c,v 1.1 1993/10/12 06:02:29 glass Exp $ (LBL)
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <errno.h>
#include "netboot.h"
#include "config.h"
#include "netif.h"
/* Caller must leave room for ethernet, ip and udp headers in front!! */
int
sendudp(d, buf, len)
register struct iodesc *d;
register void *buf;
register int len;
{
register int cc;
register struct ip *ip;
register struct udphdr *up;
register u_char *ea;
if (debug)
printf("sendudp: called\n");
up = ((struct udphdr *)buf) - 1;
ip = ((struct ip *)up) - 1;
len += sizeof(*ip) + sizeof(*up);
bzero(ip, sizeof(*ip) + sizeof(*up));
ip->ip_v = IPVERSION;
ip->ip_hl = sizeof(*ip) >> 2;
ip->ip_len = htons(len);
ip->ip_p = IPPROTO_UDP;
ip->ip_ttl = IP_TTL;
ip->ip_src.s_addr = d->myip;
ip->ip_dst.s_addr = d->destip;
ip->ip_sum = in_cksum(ip, sizeof(*ip));
up->uh_sport = htons(d->myport);
up->uh_dport = htons(d->destport);
up->uh_ulen = htons(len - sizeof(*ip));
up->uh_sum = in_cksum(up, len - sizeof(*ip));
if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 ||
mask == 0 || SAMENET(ip->ip_src.s_addr, ip->ip_dst.s_addr, mask))
ea = arpwhohas(d, ip->ip_dst.s_addr);
else
ea = arpwhohas(d, gateip);
cc = sendether(d, ip, len, ea, ETHERTYPE_IP);
if (cc < 0)
return (cc);
if (cc != len)
panic("sendudp: bad write (%d != %d)", cc, len);
return (cc - (sizeof(*ip) + sizeof(*up)));
}
/* Caller must leave room for ethernet header in front!! */
int
sendether(d, buf, len, dea, etype)
register struct iodesc *d;
register void *buf;
register int len;
register u_char *dea;
register int etype;
{
register struct ether_header *eh;
if (debug)
printf("sendether: called\n");
eh = ((struct ether_header *)buf) - 1;
len += ETHER_SIZE;
MACPY(d->myea, eh->ether_shost);
MACPY(dea, eh->ether_dhost);
eh->ether_type = etype;
return (ethernet_put(d, eh, len) - ETHER_SIZE);
}
/* Check that packet is a valid udp packet for us */
void *
checkudp(d, pkt, lenp)
register struct iodesc *d;
register void *pkt;
register int *lenp;
{
register int hlen, len;
register struct ether_header *eh;
register struct ip *ip;
register struct udphdr *up;
if (debug)
printf("checkudp: called\n");
eh = pkt;
ip = (struct ip *)(eh + 1);
up = (struct udphdr *)(ip + 1);
/* Must be to us */
if (bcmp(d->myea, eh->ether_dhost, 6) != 0 &&
bcmp(bcea, eh->ether_dhost, 6) != 0)
return (NULL);
/* And ip */
if (eh->ether_type != ETHERTYPE_IP)
return (NULL);
/* Check ip header */
if (ip->ip_v != IPVERSION || ip->ip_p != IPPROTO_UDP)
return (NULL);
hlen = ip->ip_hl << 2;
if (hlen < sizeof(*ip) || in_cksum(ip, hlen) != 0)
return (NULL);
NTOHS(ip->ip_len);
if (*lenp - sizeof(*eh) < ip->ip_len)
return (NULL);
if (d->myip && ip->ip_dst.s_addr != d->myip)
return (NULL);
/* If there were ip options, make them go away */
if (hlen != sizeof(*ip)) {
bcopy(((u_char *)ip) + hlen, up,
*lenp - (sizeof(*eh) + hlen));
ip->ip_len = sizeof(*ip);
*lenp -= hlen - sizeof(*ip);
}
if (ntohs(up->uh_dport) != d->myport)
return (NULL);
if (up->uh_sum) {
len = ntohs(up->uh_ulen);
if (len > RECV_SIZE - (sizeof(*eh) + sizeof(*ip))) {
printf("checkudp: huge packet, udp len %lu\n", len);
return (NULL);
}
if (in_cksum(up, len) != 0)
return (NULL);
}
NTOHS(up->uh_dport);
NTOHS(up->uh_sport);
NTOHS(up->uh_ulen);
if (up->uh_ulen < sizeof(*up))
return (NULL);
*lenp -= sizeof(*eh) + sizeof(*ip) + sizeof(*up);
return (up + 1);
}
/*
* 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.
*/
int
sendrecv(d, sproc, sbuf, ssize, rproc, rbuf, rsize)
register struct iodesc *d;
register int (*sproc)(struct iodesc *, void *, int);
register void *sbuf;
register int ssize;
register int (*rproc)(struct iodesc *, void *, int);
register void *rbuf;
register int rsize;
{
register int cc;
register time_t t, tmo, tlast, tleft;
if (debug)
printf("sendrecv: called\n");
tmo = MINTMO;
tlast = tleft = 0;
t = getsecs();
for (;;) {
if (tleft <= 0) {
cc = (*sproc)(d, sbuf, ssize);
if (cc < ssize)
panic("sendrecv: short write! (%d < %d)",
cc, ssize);
tleft = tmo;
tmo <<= 1;
if (tmo > MAXTMO)
tmo = MAXTMO;
tlast = t;
}
cc = ethernet_get(d, rbuf, rsize, tleft);
if (cc >= 0) {
/* Got a packet, process it */
cc = (*rproc)(d, rbuf, cc);
/* Return on data, EOF or real error */
if (cc >= 0 || errno != 0)
return (cc);
}
/* Timed out or didn't get the packet we're waiting for */
t = getsecs();
tleft -= t - tlast;
tlast = t;
}
}
int ethernet_get(desc, pkt, len, timeout)
struct iodesc *desc;
void *pkt;
int len;
time_t timeout;
{
int val;
val = desc->io_netif->netif_get(desc, pkt, len, timeout);
if (debug)
printf("ethernet_get: received %d\n", val);
return val;
}
int ethernet_put(desc, pkt, len)
struct iodesc *desc;
void *pkt;
int len;
{
int count, val;
if (debug) {
struct ether_header *eh;
printf("ethernet_put: called\n");
eh = pkt;
printf("ethernet_put: ether_dhost %s\n",
ether_sprintf(eh->ether_dhost));
printf("ethernet_put: ether_shost %s\n",
ether_sprintf(eh->ether_shost));
printf("ethernet_put: ether_type %x\n", eh->ether_type);
}
if (!desc->io_netif)
panic("ethernet_put: no netif_put support");
val = desc->io_netif->netif_put(desc, pkt, len);
return val;
}

111
sys/boot/netboot.h Normal file
View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 1993 Adam Glass
* Copyright (c) 1992 Regents of the University of California.
* All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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: /cvsroot/src/sys/boot/Attic/netboot.h,v 1.1 1993/10/12 06:02:31 glass Exp $ (LBL)
*/
#define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
/* Returns true if n_long's on the same net */
#define SAMENET(a1, a2, m) ((a1 & m) == (a2 & m))
#define MACPY(s, d) bcopy((char *)s, (char *)d, 6)
#define MAXTMO 20 /* seconds */
#define MINTMO 2 /* seconds */
#define FNAME_SIZE 128
#define IFNAME_SIZE 16
#define RECV_SIZE 1536 /* XXX delete this */
/* Size of struct ether_header + struct ip + struct udphdr */
#define ETHER_SIZE 14
#define HEADER_SIZE (ETHER_SIZE + 20 + 8)
struct iodesc {
n_long destip; /* destination ip address */
n_long myip; /* my ip address */
u_short destport; /* destination port */
u_short myport; /* destination port */
u_long xid; /* transaction identification */
u_char myea[6]; /* my ethernet address */
u_char *fh; /* pointer to file handle */
struct netif *io_netif;
};
extern u_char bcea[6];
extern char rootpath[FNAME_SIZE];
extern char swappath[FNAME_SIZE];
extern char ifname[IFNAME_SIZE];
extern n_long rootip;
extern n_long swapip;
extern n_long gateip;
extern n_long smask;
extern n_long nmask;
extern n_long mask;
extern time_t bot;
extern int debug;
u_char *arpwhohas __P((struct iodesc *, n_long));
void getnfsfh __P((struct iodesc *, char *, u_char *));
void getnfsinfo __P((struct iodesc *, time_t *, u_long *, u_long *));
int lookupfh __P((struct iodesc *, char *, u_char *, time_t *,
u_long *, u_long *));
int readdata __P((struct iodesc *, u_long, void *, u_long));
void readseg __P((struct iodesc *, u_long, u_long, u_long));
void ethernet_init __P((struct iodesc *));
int ethernet_put __P((struct iodesc *, void *, int));
int ethernet_poll __P((struct iodesc *, void *, int));
int ethernet_get __P((struct iodesc *, void *, int, time_t));
void ethernet_macaddr __P((struct iodesc *, int, u_char *));
time_t getsecs __P((void));
u_long gettenths __P((void));
int sendether __P((struct iodesc *, void *, int, u_char *, int));
int sendudp __P((struct iodesc *, void *, int));
int recvudp __P((struct iodesc *, void *, int, time_t));
int sendrecv __P((struct iodesc *, int (*)(struct iodesc *, void *, int),
void *, int, int (*)(struct iodesc *, void *, int), void *, int));
void *checkudp __P((struct iodesc *, void *, int *));
void panic __P((const char *, ...));
char *ether_sprintf __P((u_char *));
int in_cksum __P((void *, int));
void call __P((u_long));

127
sys/boot/netif.c Normal file
View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 1993 Adam Glass
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Adam Glass.
* 4. The name of the Author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Adam Glass ``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: /cvsroot/src/sys/boot/Attic/netif.c,v 1.1 1993/10/12 06:02:33 glass Exp $
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/cdefs.h>
#include <sys/mount.h>
#include <time.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include "netboot.h"
#include "config.h"
#include "netif.h"
static int netif_newp = 0; /* an optimization to skip over exhausted netifs */
void netif_init()
{
int i;
if (debug)
printf("netif_init: called\n");
for (i =0; i < n_netif; i++) {
netiftab[i]->netif_unit;
netiftab[i]->netif_exhausted = 0;
}
}
int netif_match(nif, machdep_hint, unitp)
struct netif *nif;
void *machdep_hint;
int *unitp;
{
if (debug)
printf("netif_match: called\n");
return nif->netif_match(machdep_hint, unitp);
}
struct netif *netif_select(machdep_hint)
void *machdep_hint;
{
int i;
struct netif *best_if = NULL;
int best_unit;
int best_val;
int val, unit;
best_val = 0;
if (debug)
printf("network interfaces: %d\n", n_netif);
for (i = netif_newp; i < n_netif; i++) {
val = netif_match(netiftab[i], machdep_hint, &unit);
if (val == 0) {
netiftab[i]->netif_exhausted = 1;
continue;
}
if (debug)
printf("netif_select: %s%d = %d\n", netiftab[i]->netif_bname,
netiftab[i]->netif_unit, val);
if (val > best_val) {
best_if = netiftab[i];
best_unit = unit;
}
}
if (!best_if) return NULL;
best_if->netif_unit = best_unit;
return best_if;
}
int netif_probe(nif, machdep_hint)
struct netif *nif;
void *machdep_hint;
{
if (debug)
printf("netif_probe: called\n");
return nif->netif_probe(machdep_hint);
}
void netif_attach(nif, desc, machdep_hint)
struct netif *nif;
struct iodesc *desc;
void *machdep_hint;
{
if (debug)
printf("netif_attach: called\n");
nif->netif_init(desc, machdep_hint);
desc->io_netif = nif;
bzero(desc->io_netif->netif_stats, *desc->io_netif->netif_stats);
}
void netif_detach(nif)
struct netif *nif;
{
if (debug)
printf("netif_detach: called\n");
nif->netif_end();
}

32
sys/boot/netif.h Normal file
View File

@ -0,0 +1,32 @@
struct netif {
char *netif_bname;
int netif_unit;
int netif_exhausted;
int (*netif_match) __P((void *, int *));
int (*netif_probe) __P((void *));
void (*netif_init) __P((struct iodesc *, void *));
int (*netif_get) __P((struct iodesc *, void *, int, time_t));
int (*netif_put) __P((struct iodesc *, void *, int));
void (*netif_end) __P((void));
struct netif_stats *netif_stats;
};
struct netif_stats {
int collisions;
int collision_error;
int missed;
int sent;
int received;
int deferred;
int overflow;
};
extern struct netif *netiftab[];
extern int n_netif;
void netif_init __P((void));
struct netif *netif_select __P((void *));
int netif_probe __P((struct netif *, void *));
void netif_attach __P((struct netif *, struct iodesc *, void *));
void netif_detach __P((struct netif *));

201
sys/boot/nfsboot.c Normal file
View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 1993 Adam Glass
* All rights reserved.
*
* A lot of this code is derived material from the LBL bootbootp release,
* thus their copyright below.
*
* 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 Adam Glass.
* 4. The name of the Author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Adam Glass ``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: /cvsroot/src/sys/boot/Attic/nfsboot.c,v 1.1 1993/10/12 06:02:38 glass 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: /cvsroot/src/sys/boot/Attic/nfsboot.c,v 1.1 1993/10/12 06:02:38 glass Exp $ (LBL)
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/cdefs.h>
#include <sys/mount.h>
#include <time.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include "netboot.h"
#include "config.h"
#include "bootbootp.h"
#include "bootp.h"
#include "netif.h"
/* Globals */
u_char bcea[6] = BA; /* broadcast ethernet address */
char rootpath[FNAME_SIZE]; /* root mount path */
char swappath[FNAME_SIZE]; /* swap mount path */
char ifname[IFNAME_SIZE]; /* name of interface (e.g. "le0") */
n_long rootip; /* root ip address */
n_long swapip; /* swap ip address */
n_long gateip; /* swap ip address */
n_long smask; /* subnet mask */
n_long nmask; /* net mask */
n_long mask; /* subnet or net mask */
time_t bot; /* beginning of time in seconds */
#ifdef DEBUG
int debug = 1;
#else
int debug = 0;
#endif
static u_char rootfh[NFS_FHSIZE];
static u_char swapfh[NFS_FHSIZE];
static u_long swapblks;
static time_t roottime;
void nfs_setup(desc)
struct iodesc *desc;
{
u_long ftype, bytes;
bcopy(&desc->myea[4], &desc->myport, 2);
printf("myip: %s", intoa(desc->myip));
if (gateip)
printf(", gateip: %s", intoa(gateip));
if (mask)
printf(", mask: %s", intoa(mask));
printf("\n");
printf("root: %s:%s\n", intoa(rootip), rootpath);
printf("swap: %s:%s\n", intoa(swapip), swappath);
/* Get root file handle and timestamp */
desc->destip = rootip;
getnfsfh(desc, rootpath, rootfh);
desc->fh = rootfh;
getnfsinfo(desc, &roottime, NULL, &ftype);
if (ftype != NFDIR)
panic("bad root ftype %d", ftype);
if (debug)
printf("nfs_setup: got root fh\n");
desc->destip = swapip;
getnfsfh(desc, swappath, swapfh);
desc->fh = swapfh;
getnfsinfo(desc, NULL, &bytes, &ftype);
if (bytes % 512)
printf("warning: swap is odd sized\n");
if (ftype != NFREG)
panic("bad swap ftype %d\n", ftype);
swapblks = bytes / 512;
if (debug)
printf("nfs_setup: got swap fh\n");
printf("swap: %d (%d blocks)\n", bytes, swapblks);
desc->destip = rootip;
desc->fh = rootfh;
}
unsigned int nfs_boot(kernel_override, machdep_hint)
char *kernel_override;
void *machdep_hint;
{
/*
* 0. get common ether addr if exists
* 1. choose interface
* 2. set up interface
* 3. bootp or bootparam
* 4. get filesystem fh information
* 5. get swap information
* 6. load kernel
* 7. if nfs_diskless crud, do the right thign
* 8. run kernel
*/
struct iodesc *desc;
struct iodesc desc_store;
struct netif *nif;
desc = &desc_store;
netif_init();
while (1) {
bzero(desc, sizeof(*desc));
#ifdef COMMON_ETHERADDR
machdep_common_ether(desc->myea);
#endif
nif = netif_select(machdep_hint);
if (!nif)
panic("netboot: no interfaces left untried");
if (netif_probe(nif, machdep_hint)) {
printf("netboot: couldn't probe %s%d\n",
nif->netif_bname, nif->netif_unit);
continue;
}
netif_attach(nif, desc, machdep_hint);
get_bootinfo(desc);
nfs_setup(desc);
nfs_exec(desc, kernel_override);
failed: netif_detach(nif);
}
}

617
sys/boot/rpc.c Normal file
View File

@ -0,0 +1,617 @@
/*
* 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: /cvsroot/src/sys/boot/Attic/rpc.c,v 1.1 1993/10/12 06:02:40 glass Exp $ (LBL)
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <errno.h>
#include "netboot.h"
#include "netif.h"
#include "config.h"
#include "bootbootp.h"
/* XXX defines we can't easily get from system includes */
#define PMAPPORT 111
#define PMAPPROG 100000
#define PMAPVERS 2
#define PMAPPROC_GETPORT 3
#define RPC_MSG_VERSION 2
#define MSG_ACCEPTED 0
#define CALL 0
#define REPLY 1
/* Null rpc auth info */
struct auth_info {
int rp_atype; /* zero (really AUTH_NULL) */
u_long rp_alen; /* zero (size of auth struct) */
};
/* Generic rpc call header */
struct rpc_call {
u_long rp_xid; /* request transaction id */
int rp_direction; /* call direction */
u_long rp_rpcvers; /* rpc version (2) */
u_long rp_prog; /* program */
u_long rp_vers; /* version */
u_long rp_proc; /* procedure */
struct auth_info rp_auth; /* AUTH_NULL */
struct auth_info rp_verf; /* AUTH_NULL */
};
/* Generic rpc reply header */
struct rpc_reply {
u_long rp_xid; /* request transaction id */
int rp_direction; /* call direction */
int rp_stat; /* accept status */
u_long rp_prog; /* program (unused) */
u_long rp_vers; /* version (unused) */
u_long rp_proc; /* procedure (unused) */
};
struct nfs_call_data {
u_char fh[NFS_FHSIZE];
u_long off;
u_long len;
u_long xxx; /* XXX what's this for? */
};
/* Data part of nfs rpc reply (also the largest thing we receive) */
struct nfs_reply_data {
u_long errno;
struct nfsv2_fattr fa;
u_long count;
u_char data[1200];
};
#define NFSREAD_SIZE sizeof(((struct nfs_reply_data *)0)->data)
/* Cache stuff */
#define PMAP_NUM 8 /* need at most 5 pmap entries */
static struct pmap_list {
u_long addr; /* address of server */
u_long prog;
u_long vers;
u_short port; /* cached port for service */
} pmap_list[PMAP_NUM] = {
{ 0, PMAPPROG, PMAPVERS, PMAPPORT }
};
static int pmap_num = 1;
/* Local forwards */
static int callrpc __P((struct iodesc *, u_long, u_long, u_long,
void *, int, void *, int));
static int recvrpc __P((struct iodesc *, void *, int));
static u_short getport __P((struct iodesc *, u_long, u_long));
/* Make a rpc call; return length of answer */
static int
callrpc(d, prog, vers, proc, sdata, slen, rdata, rlen)
register struct iodesc *d;
register u_long prog, vers, proc;
register void *sdata;
register int slen;
register void *rdata;
register int rlen;
{
register int cc;
register struct rpc_call *rpc;
struct {
u_char header[HEADER_SIZE];
struct rpc_call wrpc;
u_char data[sizeof(struct nfs_reply_data)]; /* XXX */
} wbuf;
struct {
u_char header[HEADER_SIZE];
struct rpc_reply rrpc;
union {
u_long errno;
u_char data[sizeof(struct nfs_reply_data)];
} ru;
} rbuf;
if (debug)
printf("callrpc: called\n");
if (rlen > sizeof(rbuf.ru.data))
panic("callrpc: huge read (%d > %d)",
rlen, sizeof(rbuf.ru.data));
d->destport = getport(d, prog, vers);
rpc = &wbuf.wrpc;
bzero(rpc, sizeof(*rpc));
rpc->rp_xid = d->xid;
rpc->rp_rpcvers = htonl(RPC_MSG_VERSION);
rpc->rp_prog = htonl(prog);
rpc->rp_vers = htonl(vers);
rpc->rp_proc = htonl(proc);
bcopy(sdata, wbuf.data, slen);
cc = sendrecv(d, sendudp, rpc, sizeof(*rpc) + slen, recvrpc,
((u_char *)&rbuf.rrpc) - HEADER_SIZE, sizeof(rbuf) - HEADER_SIZE);
if (cc < rlen) {
/* Check for an error return */
if (cc >= sizeof(rbuf.ru.errno) && rbuf.ru.errno != 0) {
errno = ntohl(rbuf.ru.errno);
return (-1);
}
panic("callrpc: missing data (%d < %d)", cc, rlen);
}
if (cc > sizeof(rbuf.ru.data))
panic("callrpc: huge return (%d > %d)",
cc, sizeof(rbuf.ru.data));
bcopy(rbuf.ru.data, rdata, cc);
return (cc);
}
/* Returns true if packet is the one we're waiting for */
static int
recvrpc(d, pkt, len)
register struct iodesc *d;
register void *pkt;
int len;
{
register struct rpc_reply *rpc;
if (debug)
printf("recvrpc: called\n");
rpc = (struct rpc_reply *)checkudp(d, pkt, &len);
if (rpc == NULL || len < sizeof(*rpc)) {
errno = 0;
return (-1);
}
NTOHL(rpc->rp_direction);
NTOHL(rpc->rp_stat);
if (rpc->rp_xid != d->xid || rpc->rp_direction != REPLY ||
rpc->rp_stat != MSG_ACCEPTED) {
errno = 0;
return (-1);
}
/* Bump xid so next request will be unique */
++d->xid;
/* Return data count (thus indicating success) */
return (len - sizeof(*rpc));
}
/* Request a port number from the port mapper */
static u_short
getport(d, prog, vers)
register struct iodesc *d;
u_long prog;
u_long vers;
{
register int i;
register struct pmap_list *pl;
u_long port;
struct {
u_long prog; /* call program */
u_long vers; /* call version */
u_long proto; /* call protocol */
u_long port; /* call port (unused) */
} sdata;
if (debug)
printf("getport: called\n");
/* Try for cached answer first */
for (i = 0, pl = pmap_list; i < pmap_num; ++i, ++pl)
if ((pl->addr == d->destip || pl->addr == 0) &&
pl->prog == prog && pl->vers == vers)
return (pl->port);
/* Don't overflow cache */
if (pmap_num > PMAP_NUM - 1)
panic("getport: overflowed pmap_list!");
sdata.prog = htonl(prog);
sdata.vers = htonl(vers);
sdata.proto = htonl(IPPROTO_UDP);
sdata.port = 0;
if (callrpc(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
&sdata, sizeof(sdata), &port, sizeof(port)) < 0)
panic("getport: %s", strerror(errno));
/* Cache answer */
pl->addr = d->destip;
pl->prog = prog;
pl->vers = vers;
pl->port = port;
++pmap_num;
return ((u_short)port);
}
/* Fetch file handle */
void
getnfsfh(d, path, fhp)
register struct iodesc *d;
char *path;
u_char *fhp;
{
register int len;
struct {
u_long len;
char path[FNAME_SIZE];
} sdata;
struct {
u_long errno;
u_char fh[NFS_FHSIZE];
} rdata;
if (debug)
printf("getnfsfh: called\n");
bzero(&sdata, sizeof(sdata));
len = strlen(path);
if (len > sizeof(sdata.path))
len = sizeof(sdata.path);
bcopy(path, sdata.path, len);
sdata.len = htonl(len);
len = sizeof(sdata) - sizeof(sdata.path) + roundup(len, sizeof(long));
if (callrpc(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
&sdata, len, &rdata, sizeof(rdata)) < 0)
panic("getnfsfh: %s", strerror(errno));
bcopy(rdata.fh, fhp, sizeof(rdata.fh));
}
/* Fetch file timestamp and size */
void
getnfsinfo(d, tp, sp, fp)
register struct iodesc *d;
register time_t *tp;
register u_long *sp, *fp;
{
struct {
u_long errno;
struct nfsv2_fattr fa;
} rdata;
if (debug)
printf("getnfsinfo: called\n");
if (callrpc(d, NFS_PROG, NFS_VER2, NFSPROC_GETATTR,
d->fh, NFS_FHSIZE, &rdata, sizeof(rdata)) < 0)
panic("getnfsfh: %s", strerror(errno));
if (tp)
*tp = ntohl(rdata.fa.fa_ctime.tv_sec);
if (sp)
*sp = ntohl(rdata.fa.fa_size);
if (fp)
*fp = ntohl(rdata.fa.fa_type);
}
/* Lookup a file. Optionally return timestamp and size */
int
lookupfh(d, name, fhp, tp, sp, fp)
register struct iodesc *d;
register char *name;
register u_char *fhp;
register time_t *tp;
register u_long *sp, *fp;
{
register int len;
struct {
u_char fh[NFS_FHSIZE];
u_long len;
char name[FNAME_SIZE];
} sdata;
struct {
u_long errno;
u_char fh[NFS_FHSIZE];
struct nfsv2_fattr fa;
} rdata;
if (debug)
printf("lookupfh: called\n");
bzero(&sdata, sizeof(sdata));
bcopy(d->fh, sdata.fh, sizeof(sdata.fh));
len = strlen(name);
if (len > sizeof(sdata.name))
len = sizeof(sdata.name);
bcopy(name, sdata.name, len);
sdata.len = htonl(len);
len = sizeof(sdata) - sizeof(sdata.name) + roundup(len, sizeof(long));
if (callrpc(d, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
&sdata, len, &rdata, sizeof(rdata)) < 0)
return (-1);
bcopy(rdata.fh, fhp, sizeof(rdata.fh));
if (tp)
*tp = ntohl(rdata.fa.fa_ctime.tv_sec);
if (sp)
*sp = ntohl(rdata.fa.fa_size);
if (fp)
*fp = ntohl(rdata.fa.fa_type);
return (0);
}
static int sendreaddata __P((struct iodesc *, void *, int));
static int recvreaddata __P((struct iodesc *, void *, int));
/* max number of nfs reads pending */
#define NFS_COUNT 10
static struct nfsstate {
u_long off;
u_long len;
int done;
void *addr;
u_long xid;
} nfsstate[NFS_COUNT];
static u_long nfscc;
static int
sendreaddata(d, pkt, len)
register struct iodesc *d;
register void *pkt;
register int len;
{
register int i;
register u_long cc;
register struct rpc_call *rpc;
register struct nfs_call_data *nfs;
register struct nfsstate *ns;
if (debug)
printf("sendreaddata: called\n");
if (len != sizeof(*rpc) + sizeof(*nfs))
panic("sendreaddata: bad buffer (%d != %d)",
len, sizeof(*rpc) + sizeof(*nfs));
rpc = pkt;
nfs = (struct nfs_call_data *)(rpc + 1);
for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns) {
if (ns->done)
continue;
rpc->rp_xid = ns->xid;
nfs->off = htonl(ns->off);
nfs->len = htonl(ns->len);
cc = sendudp(d, rpc, len);
if (cc != len)
panic("sendreaddata: short write (%d != %d)", cc, len);
}
/* XXX we may have actually sent a lot more bytes... */
return (len);
}
/* Returns char count if done else -1 (and errno == 0) */
static int
recvreaddata(d, pkt, len)
register struct iodesc *d;
register void *pkt;
int len;
{
register int i;
register struct rpc_reply *rpc;
register struct nfs_reply_data *nfs;
register struct nfsstate *ns;
if (debug)
printf("recvreaddata: called\n");
rpc = (struct rpc_reply *)checkudp(d, pkt, &len);
if (rpc == NULL || len < sizeof(*rpc)) {
errno = 0;
return (-1);
}
len -= sizeof(*rpc);
NTOHL(rpc->rp_direction);
NTOHL(rpc->rp_stat);
if (rpc->rp_direction != REPLY || rpc->rp_stat != MSG_ACCEPTED) {
errno = 0;
return (-1);
}
for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns)
if (rpc->rp_xid == ns->xid)
break;
if (i >= NFS_COUNT) {
errno = 0;
return (-1);
}
if (ns->done) {
errno = 0;
return (-1);
}
nfs = (struct nfs_reply_data *)(rpc + 1);
if (len < sizeof(nfs->errno))
panic("recvreaddata: bad read %d", len);
if (nfs->errno) {
errno = ntohl(nfs->errno);
return (-1);
}
if (len < sizeof(*nfs) - sizeof(nfs->data))
panic("recvreaddata: less than nfs sized %d", len);
len -= sizeof(*nfs) - sizeof(nfs->data);
if (len < nfs->count)
panic("recvreaddata: short read (%d < %d)", len, nfs->count);
len = nfs->count;
if (len > ns->len)
panic("recvreaddata: huge read (%d > %d)", len, ns->len);
bcopy(nfs->data, ns->addr, len);
ns->done = 1;
nfscc += len;
if (len < ns->len) {
/* If first packet assume no more data to read */
if (i == 0)
return (0);
/* Short read, assume we are at EOF */
++i;
++ns;
while (i < NFS_COUNT) {
ns->done = 1;
++i;
++ns;
}
}
for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns)
if (!ns->done) {
errno = 0;
return (-1);
}
/* Return data count (thus indicating success) */
return (nfscc);
}
/* Read data from a file */
int
readdata(d, off, addr, len)
register struct iodesc *d;
register u_long off;
register void *addr;
register u_long len;
{
register int i, cc;
register struct rpc_call *rpc;
register struct nfsstate *ns;
struct {
u_char header[HEADER_SIZE];
struct rpc_call rpc;
struct nfs_call_data nfs;
} sdata;
struct {
u_char header[HEADER_SIZE];
struct rpc_call rpc;
struct nfs_reply_data nfs;
} rdata;
if (debug)
printf("readdata: called\n");
if (len == 0)
return (0);
d->destport = getport(d, NFS_PROG, NFS_VER2);
bzero(&sdata, sizeof(sdata));
for (i = 0, ns = nfsstate; i < NFS_COUNT; ++i, ++ns) {
if (len <= 0) {
ns->done = 1;
continue;
}
ns->done = 0;
ns->xid = d->xid;
++d->xid;
ns->off = off;
ns->len = len;
if (ns->len > NFSREAD_SIZE)
ns->len = NFSREAD_SIZE;
#ifdef notdef
/* XXX to align or not align? It doesn't seem to speed things up... */
if ((ns->off % NFSREAD_SIZE) != 0)
ns->len -= off % NFSREAD_SIZE;
#endif
off += ns->len;
len -= ns->len;
ns->addr = addr;
addr += NFSREAD_SIZE;
}
rpc = &sdata.rpc;
rpc->rp_rpcvers = htonl(RPC_MSG_VERSION);
rpc->rp_prog = htonl(NFS_PROG);
rpc->rp_vers = htonl(NFS_VER2);
rpc->rp_proc = htonl(NFSPROC_READ);
bcopy(d->fh, sdata.nfs.fh, sizeof(sdata.nfs.fh));
nfscc = 0;
cc = sendrecv(d, sendreaddata,
&sdata.rpc,
sizeof(struct rpc_call) + sizeof(struct nfs_call_data),
recvreaddata,
((u_char *)&rdata.rpc) - HEADER_SIZE, HEADER_SIZE +
sizeof(struct rpc_call) + sizeof(struct nfs_reply_data));
return (cc);
}
void readseg(d, off, size, addr)
register struct iodesc * d;
register u_long off, size, addr;
{
register int i, cc;
i = 0;
while (size > 0) {
cc = readdata(d, off, (void *)addr, size);
if (cc <= 0) {
/* XXX maybe should retry on certain errors */
if (cc < 0)
panic("\nreadseg: read: %s",
strerror(errno));
panic("\nreadseg: hit EOF unexpectantly");
}
off += cc;
addr += cc;
size -= cc;
i = ~i;
printf("%c\010", i ? '-' : '=');
}
}

116
sys/boot/util.c Normal file
View File

@ -0,0 +1,116 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include "config.h"
#include "../include/stdarg.h"
void
#ifdef __STDC__
panic(const char *fmt, ...)
#else
panic(fmt /*, va_alist */)
char *fmt;
#endif
{
va_list ap;
va_start(ap, fmt);
printf(fmt, ap);
printf("\n");
va_end(ap);
machdep_stop();
}
/* Similar to inet_ntoa() */
char *
intoa(addr)
n_long addr;
{
register char *cp;
register u_int byte;
register int n;
static char buf[sizeof(".xxx.xxx.xxx.xxx")];
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);
}
char *strerror(errnum)
int errnum;
{
char ebuf[1024] = "Unknown error: code ";
char *p;
int length;
switch (errnum) {
case EPERM:
return "Permission Denied";
case ENOENT:
return "No such file or directory";
case ESTALE:
return "Stale NFS file handle";
default:
length = strlen(ebuf);
p = ebuf+length;
do {
*p++ = "0123456789"[errnum %10];
} while (errnum /= 10);
*p = '\0';
return ebuf;
}
}
/*
* Convert Ethernet address to printable (loggable) representation.
*/
static char digits[] = "0123456789abcdef";
char *
ether_sprintf(ap)
register u_char *ap;
{
register i;
static char etherbuf[18];
register char *cp = etherbuf;
for (i = 0; i < 6; i++) {
*cp++ = digits[*ap >> 4];
*cp++ = digits[*ap++ & 0xf];
*cp++ = ':';
}
*--cp = 0;
return (etherbuf);
}
void bzero(addr, len)
char *addr;
int len;
{
while (len--)
*addr++ = '\0';
}