Commit 81f022a0 authored by Mike Hibler's avatar Mike Hibler
Browse files

Diffs for FreeBSD 4.10 libstand and boot loader necessary to produce our

pxeboot program.
parent f1b17f60
This directory contains diffs for a clean FreeBSD 4.10 RELEASE tree.
These diffs, for the lib/libstand and sys/boot source directories,
are necessary to build the "pxeboot" first-stage boot loader used on
Emulab nodes.
libstand.diffs:
These are primarily robustness changes for the standalone TFTP code.
There is also a bug fix or two, and a patch to have bootp/dhcp recognize
and respect the TFTP server name option (66). To apply this patch:
(cd <yoursrcdir>; patch -p2) < libstand.diffs
Install the new version of the library with:
cd <yoursrcdir>/lib/libstand
make
make install
These changes are compatible with, and should not effect, any other
boot programs.
sysboot.diffs:
Primarily this patch adds a subdirectory (sys/boot/i386/emuboot) for
the PXE-loaded first-stage boot loader we use.
Most of the other diffs are in support of this loader (typically
conditionally compiled/assembled via the 'TESTBED' symbol). There
are new options in sys/boot/i386/Makefile.inc for forcing the serial
console, or changing its speed or port number, make sure these are
correct for your site. The ETHERBOOT_* conditionals are a hack to
get our pxeboot to load and run when booted via an older, modified
version of etherboot. These changes no longer for newer versions
of etherboot.
There is also a directory (sys/boot/i386/emuboot0) which is a slightly
modified version of boot0 (the MBR-resident boot loader) that just
reboots the machine unless explicitly told what to do after a short time.
This is a fall-back in case PXE booting fails (due to a transient load
on the network) and the BIOS falls back to booting from disk. This will
force the machine to keep rebooting and retrying PXE until it works.
Apply this patch with:
(cd <yoursrcdir>; patch -p2) < sysboot.diffs
Then modify the i386/Makefile.inc file as appropriate and build with:
cd <yoursrcdir>/sys/boot
make
DON'T DO AN INSTALL HERE. I am less certain that these changes are
compatible with all existing boot code. Instead:
cp -p /tftpboot/pxeboot.emu /tftpboot/pxeboot.emu.bak
cp <yoursrcdir>/sys/boot/i386/emuboot/pxeboot /tftpboot/pxeboot.emu
diff -ru 4.10-release/src/lib/libstand/bootp.c 4.10/src/lib/libstand/bootp.c
--- 4.10-release/src/lib/libstand/bootp.c Wed Sep 20 12:37:25 2000
+++ 4.10/src/lib/libstand/bootp.c Wed Oct 13 12:37:32 2004
@@ -158,6 +158,7 @@
bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
== -1) {
printf("bootp: no reply\n");
+ ++d->xid;
return;
}
@@ -190,6 +191,7 @@
bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
== -1) {
printf("DHCPREQUEST failed\n");
+ ++d->xid;
return;
}
}
@@ -292,8 +294,13 @@
#endif
n = readudp(d, pkt, len, tleft);
- if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE)
+ if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE) {
+#ifdef BOOTP_DEBUG
+ if (debug && n != -1)
+ printf("bootprecv: short pkt %d\n", n);
+#endif
goto bad;
+ }
bp = (struct bootp *)pkt;
@@ -319,8 +326,13 @@
/* Suck out vendor info */
if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) {
- if(vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend)) != 0)
+ if(vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend)) != 0) {
+#ifdef BOOTP_DEBUG
+ if (debug)
+ printf("bootprecv: bad vend_rfc1048\n");
+#endif
goto bad;
+ }
}
#ifdef BOOTP_VEND_CMU
else if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
@@ -341,7 +353,7 @@
u_int len;
{
register u_char *ep;
- register int size;
+ register int size, n;
register u_char tag;
#ifdef BOOTP_DEBUG
@@ -369,13 +381,22 @@
/* let it override bp_siaddr */
bcopy(cp, &rootip.s_addr, sizeof(swapip.s_addr));
}
+ if (tag == TAG_TFTPSERVER) {
+ char ipbuf[17];
+ n = size < sizeof(ipbuf)? size : sizeof(ipbuf)-1;
+ bcopy(cp, ipbuf, n);
+ ipbuf[n] = '\0';
+ tftpip.s_addr = inet_addr(ipbuf);
+ }
if (tag == TAG_ROOTPATH) {
- strncpy(rootpath, (char *)cp, sizeof(rootpath));
- rootpath[size] = '\0';
+ n = size < sizeof(rootpath)? size : sizeof(rootpath)-1;
+ bcopy(cp, rootpath, n);
+ rootpath[n] = '\0';
}
if (tag == TAG_HOSTNAME) {
- strncpy(hostname, (char *)cp, sizeof(hostname));
- hostname[size] = '\0';
+ n = size < sizeof(hostname)? size : sizeof(hostname)-1;
+ bcopy(cp, hostname, n);
+ hostname[n] = '\0';
}
#ifdef SUPPORT_DHCP
if (tag == TAG_DHCP_MSGTYPE) {
diff -ru 4.10-release/src/lib/libstand/bootp.h 4.10/src/lib/libstand/bootp.h
--- 4.10-release/src/lib/libstand/bootp.h Sat Sep 9 20:52:19 2000
+++ 4.10/src/lib/libstand/bootp.h Wed Oct 13 12:37:32 2004
@@ -106,6 +106,7 @@
#define TAG_CLASSID ((unsigned char) 60)
#define TAG_CLIENTID ((unsigned char) 61)
#endif
+#define TAG_TFTPSERVER ((unsigned char) 66)
#define TAG_END ((unsigned char) 255)
diff -ru 4.10-release/src/lib/libstand/close.c 4.10/src/lib/libstand/close.c
--- 4.10-release/src/lib/libstand/close.c Sat Sep 9 19:32:06 2000
+++ 4.10/src/lib/libstand/close.c Thu May 27 14:00:18 2004
@@ -77,8 +77,10 @@
errno = EBADF;
return (-1);
}
- if (f->f_rabuf != NULL)
+ if (f->f_rabuf != NULL) {
free(f->f_rabuf);
+ f->f_rabuf = NULL;
+ }
if (!(f->f_flags & F_RAW) && f->f_ops)
err1 = (f->f_ops->fo_close)(f);
if (!(f->f_flags & F_NODEV) && f->f_dev)
diff -ru 4.10-release/src/lib/libstand/globals.c 4.10/src/lib/libstand/globals.c
--- 4.10-release/src/lib/libstand/globals.c Thu Aug 20 02:19:55 1998
+++ 4.10/src/lib/libstand/globals.c Wed Oct 13 12:37:32 2004
@@ -28,6 +28,7 @@
struct in_addr rootip; /* root ip address */
struct in_addr swapip; /* swap ip address */
struct in_addr gateip; /* swap ip address */
+struct in_addr tftpip; /* tftp server ip address */
n_long netmask = 0xffffff00; /* subnet or net mask */
int errno; /* our old friend */
diff -ru 4.10-release/src/lib/libstand/net.c 4.10/src/lib/libstand/net.c
--- 4.10-release/src/lib/libstand/net.c Fri Apr 14 21:09:28 2000
+++ 4.10/src/lib/libstand/net.c Thu May 27 14:00:18 2004
@@ -70,14 +70,16 @@
* zero errno to indicate it isn't done yet.
*/
ssize_t
-sendrecv(d, sproc, sbuf, ssize, rproc, rbuf, rsize)
- register struct iodesc *d;
- register ssize_t (*sproc)(struct iodesc *, void *, size_t);
- register void *sbuf;
- register size_t ssize;
- register ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t);
- register void *rbuf;
- register size_t rsize;
+sendrecv_timo(d, sproc, sbuf, ssize, rproc, rbuf, rsize, mintmo, maxtmo)
+ struct iodesc *d;
+ ssize_t (*sproc)(struct iodesc *, void *, size_t);
+ void *sbuf;
+ size_t ssize;
+ ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t);
+ void *rbuf;
+ size_t rsize;
+ int mintmo;
+ int maxtmo;
{
register ssize_t cc;
register time_t t, tmo, tlast;
@@ -88,12 +90,12 @@
printf("sendrecv: called\n");
#endif
- tmo = MINTMO;
+ tmo = mintmo;
tlast = tleft = 0;
t = getsecs();
for (;;) {
if (tleft <= 0) {
- if (tmo >= MAXTMO) {
+ if (tmo >= maxtmo) {
errno = ETIMEDOUT;
return -1;
}
@@ -104,8 +106,8 @@
tleft = tmo;
tmo <<= 1;
- if (tmo > MAXTMO)
- tmo = MAXTMO;
+ if (tmo > maxtmo)
+ tmo = maxtmo;
if (cc == -1) {
/* Error on transmit; wait before retrying */
@@ -116,6 +118,11 @@
tlast = t;
}
+ errno = 0;
+
+ /* Just send */
+ if (rproc == NULL)
+ return (ssize);
/* Try to get a packet and process it. */
cc = (*rproc)(d, rbuf, rsize, tleft);
@@ -128,6 +135,20 @@
tleft -= t - tlast;
tlast = t;
}
+}
+
+ssize_t
+sendrecv(d, sproc, sbuf, ssize, rproc, rbuf, rsize)
+ struct iodesc *d;
+ ssize_t (*sproc)(struct iodesc *, void *, size_t);
+ void *sbuf;
+ size_t ssize;
+ ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t);
+ void *rbuf;
+ size_t rsize;
+{
+ return sendrecv_timo(d, sproc, sbuf, ssize, rproc, rbuf, rsize,
+ MINTMO, MAXTMO);
}
/*
diff -ru 4.10-release/src/lib/libstand/net.h 4.10/src/lib/libstand/net.h
--- 4.10-release/src/lib/libstand/net.h Sun Mar 4 23:27:18 2001
+++ 4.10/src/lib/libstand/net.h Wed Oct 13 12:37:32 2004
@@ -86,6 +86,7 @@
extern struct in_addr swapip;
extern struct in_addr gateip;
extern struct in_addr nameip;
+extern struct in_addr tftpip;
extern n_long netmask;
extern int debug; /* defined in the machdep sources */
@@ -110,6 +111,11 @@
void *, size_t,
ssize_t (*)(struct iodesc *, void *, size_t, time_t),
void *, size_t);
+ssize_t sendrecv_timo(struct iodesc *,
+ ssize_t (*)(struct iodesc *, void *, size_t),
+ void *, size_t,
+ ssize_t (*)(struct iodesc *, void *, size_t, time_t),
+ void *, size_t, int, int);
/* bootp/DHCP */
void bootp(int, int);
diff -ru 4.10-release/src/lib/libstand/sbrk.c 4.10/src/lib/libstand/sbrk.c
--- 4.10-release/src/lib/libstand/sbrk.c Thu May 18 02:00:57 2000
+++ 4.10/src/lib/libstand/sbrk.c Thu May 27 14:00:18 2004
@@ -51,6 +51,20 @@
if ((heapsize + incr) <= maxheap) {
ret = heapbase + heapsize;
+#ifdef __i386__
+ /*
+ * Check for stack overrun
+ * XXX makes a couple of assumptions: stack frows downward,
+ * and stack starts above the heap.
+ */
+ if (ret+incr > (char *)&ret) {
+ static int beentheredonethat;
+ if (!beentheredonethat) {
+ beentheredonethat = 1;
+ printf("sbrk: heap overruns stack!\n");
+ }
+ }
+#endif
bzero(ret, incr);
heapsize += incr;
return(ret);
diff -ru 4.10-release/src/lib/libstand/tftp.c 4.10/src/lib/libstand/tftp.c
--- 4.10-release/src/lib/libstand/tftp.c Sat Jul 14 08:00:03 2001
+++ 4.10/src/lib/libstand/tftp.c Wed Oct 13 12:37:32 2004
@@ -79,7 +79,7 @@
extern struct in_addr servip;
-static int tftpport = 2000;
+static int tftpport = 2050; /* note: after nfs (2049) */
#define RSPACE 520 /* max data packet, rounded up */
@@ -129,7 +129,7 @@
case DATA: {
int got;
- if (htons(t->th_block) != d->xid) {
+ if (ntohs(t->th_block) != d->xid) {
/*
* Expected block?
*/
@@ -139,7 +139,7 @@
/*
* First data packet from new port.
*/
- register struct udphdr *uh;
+ struct udphdr *uh;
uh = (struct udphdr *) pkt - 1;
d->destport = uh->uh_sport;
} /* else check uh_sport has not changed??? */
@@ -160,11 +160,47 @@
default:
#ifdef DEBUG
printf("tftp type %d not handled\n", ntohs(t->th_opcode));
+ errno = 0;
#endif
return (-1);
}
}
+static int
+tftp_stop(h)
+ struct tftp_handle *h;
+{
+ struct {
+ u_char header[HEADER_SIZE];
+ struct tftphdr t;
+ } wbuf;
+ int res;
+
+
+ /*
+ * Attempt to ensure that the server doesn't hang around.
+ *
+ * If we got the entire file, send the final ACK
+ *
+ * If we are aborting early (e.g., a "stat"), send an error.
+ * This might not be a good thing to do...
+ */
+ if (h->islastblock) {
+ wbuf.t.th_opcode = htons((u_short) ACK);
+ wbuf.t.th_block = htons((u_short) h->currblock);
+ } else {
+ wbuf.t.th_opcode = htons((u_short) ERROR);
+ wbuf.t.th_block = 0;
+ }
+ res = sendrecv(h->iodesc, sendudp, &wbuf.t, 2 * sizeof(u_short),
+ NULL, NULL, 0);
+ if (res == -1)
+ return (errno);
+
+ return (0);
+}
+
+
/* send request, expect first block (or error) */
static int
tftp_makereq(h)
@@ -179,10 +215,13 @@
int l;
ssize_t res;
struct tftphdr *t;
+ static int lastport;
wbuf.t.th_opcode = htons((u_short) RRQ);
wtail = wbuf.t.th_stuff;
l = strlen(h->path);
+ if (l >= FNAME_SIZE)
+ return (ENAMETOOLONG);
bcopy(h->path, wtail, l + 1);
wtail += l + 1;
bcopy("octet", wtail, 6);
@@ -190,14 +229,22 @@
t = &h->lastdata.t;
- /* h->iodesc->myport = htons(--tftpport); */
- h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff));
+ l = getsecs() & 0x3ff;
+ if (l <= lastport)
+ l = lastport + 1;
+ lastport = l;
+ h->iodesc->myport = htons(tftpport + l);
h->iodesc->destport = htons(IPPORT_TFTP);
h->iodesc->xid = 1; /* expected block */
- res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
- recvtftp, t, sizeof(*t) + RSPACE);
-
+ /*
+ * Be more liberal with timeout, it might take longer
+ * to handle the initial request (e.g., server might fork/exec)
+ */
+ res = sendrecv_timo(h->iodesc,
+ sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
+ recvtftp, t, sizeof(*t) + RSPACE,
+ MINTMO*2, MAXTMO);
if (res == -1)
return (errno);
@@ -261,15 +308,20 @@
if (io == NULL)
return (EINVAL);
- io->destip = servip;
+ if (tftpip.s_addr != 0)
+ io->destip = tftpip;
+ else
+ io->destip = servip;
tftpfile->off = 0;
- tftpfile->path = strdup(path);
+ tftpfile->path = malloc(strlen(rootpath) + strlen(path) + 2);
if (tftpfile->path == NULL) {
free(tftpfile);
return(ENOMEM);
}
+ strcpy(tftpfile->path, rootpath);
+ strcat(tftpfile->path, path);
- res = tftp_makereq(tftpfile, path);
+ res = tftp_makereq(tftpfile);
if (res) {
free(tftpfile->path);
@@ -309,7 +361,7 @@
res = tftp_getnextblock(tftpfile);
if (res) { /* no answer */
#ifdef DEBUG
- printf("tftp: read error\n");
+ printf("tftp: read error %d\n", res);
#endif
return (res);
}
@@ -346,7 +398,6 @@
#endif
return (EINVAL);
}
-
}
if (resid)
@@ -361,9 +412,8 @@
struct tftp_handle *tftpfile;
tftpfile = (struct tftp_handle *) f->f_fsdata;
- /* let it time out ... */
-
if (tftpfile) {
+ tftp_stop(tftpfile);
free(tftpfile->path);
free(tftpfile);
}
diff -ru 4.10-release/src/lib/libstand/zipfs.c 4.10/src/lib/libstand/zipfs.c
--- 4.10-release/src/lib/libstand/zipfs.c Mon Apr 8 07:50:09 2002
+++ 4.10/src/lib/libstand/zipfs.c Thu May 27 14:00:18 2004
@@ -169,9 +169,18 @@
int error;
struct stat sb;
+ /*
+ * XXX this F_READ check is a bad idea.
+ * If both version of the file exist, opening for write would not get
+ * the .gz version while a following open for read would get the now
+ * stale .gz version. Better to fail on write for the .gz version
+ * and force the caller to remove it.
+ */
+#if 0
/* Have to be in "just read it" mode */
if (f->f_flags != F_READ)
return(EPERM);
+#endif
/* If the name already ends in .gz or .bz2, ignore it */
if ((cp = strrchr(fname, '.')) && (!strcmp(cp, ".gz")
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment