Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Feb 2018 04:56:07 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r329100 - in stable/11: lib/libstand share/mk sys/boot/common sys/boot/efi sys/boot/efi/boot1 sys/boot/efi/fdt sys/boot/efi/include sys/boot/efi/libefi sys/boot/efi/loader sys/boot/efi/...
Message-ID:  <201802100456.w1A4u7QV018955@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Sat Feb 10 04:56:07 2018
New Revision: 329100
URL: https://svnweb.freebsd.org/changeset/base/329100

Log:
  MFC Loader Fixes 2017q2: r316437,r316577,r316578,r316585,r316590,r316612,
  r316625,r316628,r316654,r316682,r316704,r316771,r317092,r317097,r317099,
  r317652,r317785,r317886,r317887,r318142,r318320,r318356,r318678,r318754,
  r318982,r318986,r318987,r318988,r318989,r318990,r318991,r318992,r318993,
  r318994,r318999,r319083,r319084,r319085,r320011,r320234,r320288,r320304,
  r320467,r320482
  
  r316437: Small cleanup to make i386/loader match efi/loader boot environment
  code
  
  r316577: loader: part.c cstyle cleanup
  
  r316578: loader: want mechanism to avoid RA with bcache
  
  r316585: loader: zfs reader should check all labels
  
  r316590: libstand/dosfs: cache FAT32 in 128 Kb blocks to save loader memory
  
  r316612: In r298230 the value of HEAP_MIN was changed from 3MB to 64MB.
  Correct a comment.
  
  r316625: Do not use -msoft-float with intention of disabling FP on aarch64
  
  r316628: Silence GCC warning by initializing the local variable.
  
  r316654: loader: r316585 did miss userboot update
  
  r316682: loader: r316585 did miss sparc/ofw
  
  r316704: loader.efi: only fetch zfs pool guid for the actual boot device
  
  r316771: loader: Avoid possible overflow via environment variable
  
  r317092: loader: zfs reader vdev_probe should check for minimum device size
  
  r317097: loader: F_READ/F_WRITE should be checked against masked flag
  
  r317099: loader: uboot disk ioctl should call disk_ioctl
  
  r317652: loader.efi: ResetSystem does not use data with EFI_SUCCESS
  
  r317785: zfsboot: drvsize() may be unusable on some systems
  
  r317886: distinguish NFS versus TFTP boot by rootpath
  
  r317887: loader: network read rework
  
  r318142: libstand: NULL pointer dereference in rarp
  
  r318320: loader: add ip layer code into libstand
  
  r318356: libstand: increase nfs max read size to 16k
  
  r318678: Replacing iterating over rootpath by strsep(3).
  
  r318754: Pass -N directly to ld via -Wl rather than passing it to the
  compiler driver.
  
  r318982: Pass a "FREEBSD" user-class in PXE dhcp request
  
  r318986: add a comment on vendor index 19 and 20 to avoid confusion
  
  r318987: Support URI scheme for root-path in netbooting
  
  r318988: Always build tftpfs support along with nfs for pxeboot
  
  r318989: Always issue the pxe request
  
  r318990: Partially revert r314948
  
  r318991: Document recent changes on pxeboot
  
  r318992: Capitalize DHCP
  
  r318993: Use the usual FreeBSD spelling for the DHCP user class
  
  r318994: Catch with the change in the user class
  
  r318999: Update the comments concerning net_parse_rootpath to reflect what
  it is now
  
  r319083: Followup on the user-class changes
  
  r319084: Small cleanup in dev_net.c
  
  r319085: use the same option list for dhcp discovery and request
  
  r320011: Add chain loader support for loader
  
  r320234: Make structure padding explicit in EFI_MEMORY_DESCRIPTOR
  
  r320288: Allow Clang's integrated assembler to assemble boot0
  
  r320304: loader.efi: Disable smbios for arm
  
  r320467: loader: chain load relocate data declaration is bad
  
  r320482: As with arm64 mark the EFI PE header as allocated on arm.
  
  PR:		218473

Added:
  stable/11/lib/libstand/ip.c
     - copied unchanged from r318320, head/lib/libstand/ip.c
  stable/11/sys/boot/i386/libi386/relocater_tramp.S
     - copied unchanged from r320011, head/sys/boot/i386/libi386/relocater_tramp.S
  stable/11/sys/boot/i386/loader/chain.c
     - copied, changed from r320011, head/sys/boot/i386/loader/chain.c
Modified:
  stable/11/lib/libstand/Makefile
  stable/11/lib/libstand/arp.c
  stable/11/lib/libstand/bootp.c
  stable/11/lib/libstand/bootp.h
  stable/11/lib/libstand/bootparam.c
  stable/11/lib/libstand/dosfs.c
  stable/11/lib/libstand/dosfs.h
  stable/11/lib/libstand/ether.c
  stable/11/lib/libstand/globals.c
  stable/11/lib/libstand/net.c
  stable/11/lib/libstand/net.h
  stable/11/lib/libstand/netif.c
  stable/11/lib/libstand/netif.h
  stable/11/lib/libstand/nfs.c
  stable/11/lib/libstand/rarp.c
  stable/11/lib/libstand/rpc.c
  stable/11/lib/libstand/rpc.h
  stable/11/lib/libstand/stand.h
  stable/11/lib/libstand/tftp.c
  stable/11/lib/libstand/udp.c
  stable/11/share/mk/bsd.stand.mk
  stable/11/sys/boot/common/bcache.c
  stable/11/sys/boot/common/commands.c
  stable/11/sys/boot/common/dev_net.c
  stable/11/sys/boot/common/disk.c
  stable/11/sys/boot/common/md.c
  stable/11/sys/boot/common/part.c
  stable/11/sys/boot/efi/Makefile.inc
  stable/11/sys/boot/efi/boot1/Makefile
  stable/11/sys/boot/efi/boot1/boot1.c
  stable/11/sys/boot/efi/boot1/zfs_module.c
  stable/11/sys/boot/efi/fdt/Makefile
  stable/11/sys/boot/efi/include/efidef.h
  stable/11/sys/boot/efi/libefi/Makefile
  stable/11/sys/boot/efi/libefi/efinet.c
  stable/11/sys/boot/efi/libefi/efipart.c
  stable/11/sys/boot/efi/libefi/time.c
  stable/11/sys/boot/efi/loader/Makefile
  stable/11/sys/boot/efi/loader/arch/arm/start.S
  stable/11/sys/boot/efi/loader/arch/arm64/Makefile.inc
  stable/11/sys/boot/efi/loader/main.c
  stable/11/sys/boot/forth/menu.rc
  stable/11/sys/boot/i386/boot0/Makefile
  stable/11/sys/boot/i386/common/drv.h
  stable/11/sys/boot/i386/libi386/Makefile
  stable/11/sys/boot/i386/libi386/bioscd.c
  stable/11/sys/boot/i386/libi386/biosdisk.c
  stable/11/sys/boot/i386/libi386/biosmem.c
  stable/11/sys/boot/i386/libi386/libi386.h
  stable/11/sys/boot/i386/libi386/pxe.c
  stable/11/sys/boot/i386/libi386/pxe.h
  stable/11/sys/boot/i386/loader/Makefile
  stable/11/sys/boot/i386/loader/help.i386
  stable/11/sys/boot/i386/loader/main.c
  stable/11/sys/boot/i386/pxeldr/pxeboot.8
  stable/11/sys/boot/i386/zfsboot/zfsboot.c
  stable/11/sys/boot/mips/beri/boot2/Makefile
  stable/11/sys/boot/mips/beri/loader/beri_disk_cfi.c
  stable/11/sys/boot/mips/beri/loader/beri_disk_sdcard.c
  stable/11/sys/boot/ofw/libofw/ofw_disk.c
  stable/11/sys/boot/ofw/libofw/ofw_net.c
  stable/11/sys/boot/ofw/libofw/openfirm.c
  stable/11/sys/boot/ofw/libofw/openfirm.h
  stable/11/sys/boot/powerpc/ps3/ps3cdrom.c
  stable/11/sys/boot/powerpc/ps3/ps3disk.c
  stable/11/sys/boot/sparc64/loader/main.c
  stable/11/sys/boot/uboot/lib/disk.c
  stable/11/sys/boot/uboot/lib/net.c
  stable/11/sys/boot/usb/storage/umass_loader.c
  stable/11/sys/boot/userboot/userboot/main.c
  stable/11/sys/boot/userboot/userboot/userboot_disk.c
  stable/11/sys/boot/zfs/libzfs.h
  stable/11/sys/boot/zfs/zfsimpl.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/lib/libstand/Makefile
==============================================================================
--- stable/11/lib/libstand/Makefile	Sat Feb 10 04:37:44 2018	(r329099)
+++ stable/11/lib/libstand/Makefile	Sat Feb 10 04:56:07 2018	(r329100)
@@ -141,7 +141,7 @@ SRCS+=	closeall.c dev.c ioctl.c nullfs.c stat.c \
 	fstat.c close.c lseek.c open.c read.c write.c readdir.c
 
 # network routines
-SRCS+=	arp.c ether.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c
+SRCS+=	arp.c ether.c ip.c inet_ntoa.c in_cksum.c net.c udp.c netif.c rpc.c
 
 # network info services:
 SRCS+=	bootp.c rarp.c bootparam.c

Modified: stable/11/lib/libstand/arp.c
==============================================================================
--- stable/11/lib/libstand/arp.c	Sat Feb 10 04:37:44 2018	(r329099)
+++ stable/11/lib/libstand/arp.c	Sat Feb 10 04:56:07 2018	(r329100)
@@ -65,17 +65,16 @@ int arp_num = 1;
 
 /* Local forwards */
 static	ssize_t arpsend(struct iodesc *, void *, size_t);
-static	ssize_t arprecv(struct iodesc *, void *, size_t, time_t);
+static	ssize_t arprecv(struct iodesc *, void **, void **, time_t);
 
 /* Broadcast an ARP packet, asking who has addr on interface d */
 u_char *
-arpwhohas(d, addr)
-	struct iodesc *d;
-	struct in_addr addr;
+arpwhohas(struct iodesc *d, struct in_addr addr)
 {
 	int i;
 	struct ether_arp *ah;
 	struct arp_list *al;
+	void *pkt;
 	struct {
 		struct ether_header eh;
 		struct {
@@ -83,13 +82,6 @@ arpwhohas(d, addr)
 			u_char pad[18]; 	/* 60 - sizeof(...) */
 		} data;
 	} wbuf;
-	struct {
-		struct ether_header eh;
-		struct {
-			struct ether_arp arp;
-			u_char pad[24]; 	/* extra space */
-		} data;
-	} rbuf;
 
 	/* Try for cached answer first */
 	for (i = 0, al = arp_list; i < arp_num; ++i, ++al)
@@ -122,20 +114,24 @@ arpwhohas(d, addr)
 	/* Store ip address in cache (incomplete entry). */
 	al->addr = addr;
 
+	pkt = NULL;
+	ah = NULL;
 	i = sendrecv(d,
 	    arpsend, &wbuf.data, sizeof(wbuf.data),
-	    arprecv, &rbuf.data, sizeof(rbuf.data));
+	    arprecv, &pkt, (void **)&ah);
 	if (i == -1) {
 		panic("arp: no response for %s\n",
 			  inet_ntoa(addr));
 	}
 
 	/* Store ethernet address in cache */
-	ah = &rbuf.data.arp;
 #ifdef ARP_DEBUG
  	if (debug) {
+		struct ether_header *eh;
+
+		eh = (struct ether_header *)((uintptr_t)pkt + ETHER_ALIGN);
 		printf("arp: response from %s\n",
-		    ether_sprintf(rbuf.eh.ether_shost));
+		    ether_sprintf(eh->ether_shost));
 		printf("arp: cacheing %s --> %s\n",
 		    inet_ntoa(addr), ether_sprintf(ah->arp_sha));
 	}
@@ -143,14 +139,12 @@ arpwhohas(d, addr)
 	MACPY(ah->arp_sha, al->ea);
 	++arp_num;
 
+	free(pkt);
 	return (al->ea);
 }
 
 static ssize_t
-arpsend(d, pkt, len)
-	struct iodesc *d;
-	void *pkt;
-	size_t len;
+arpsend(struct iodesc *d, void *pkt, size_t len)
 {
 
 #ifdef ARP_DEBUG
@@ -166,28 +160,27 @@ arpsend(d, pkt, len)
  * else -1 (and errno == 0)
  */
 static ssize_t
-arprecv(d, pkt, len, tleft)
-	struct iodesc *d;
-	void *pkt;
-	size_t len;
-	time_t tleft;
+arprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft)
 {
 	ssize_t n;
 	struct ether_arp *ah;
 	u_int16_t etype;	/* host order */
+	void *ptr;
 
 #ifdef ARP_DEBUG
  	if (debug)
 		printf("arprecv: ");
 #endif
 
-	n = readether(d, pkt, len, tleft, &etype);
+	ptr = NULL;
+	n = readether(d, &ptr, (void **)&ah, tleft, &etype);
 	errno = 0;	/* XXX */
 	if (n == -1 || n < sizeof(struct ether_arp)) {
 #ifdef ARP_DEBUG
 		if (debug)
 			printf("bad len=%d\n", n);
 #endif
+		free(ptr);
 		return (-1);
 	}
 
@@ -196,12 +189,11 @@ arprecv(d, pkt, len, tleft)
 		if (debug)
 			printf("not arp type=%d\n", etype);
 #endif
+		free(ptr);
 		return (-1);
 	}
 
 	/* Ethernet address now checked in readether() */
-
-	ah = (struct ether_arp *)pkt;
 	if (ah->arp_hrd != htons(ARPHRD_ETHER) ||
 	    ah->arp_pro != htons(ETHERTYPE_IP) ||
 	    ah->arp_hln != sizeof(ah->arp_sha) ||
@@ -211,6 +203,7 @@ arprecv(d, pkt, len, tleft)
 		if (debug)
 			printf("bad hrd/pro/hln/pln\n");
 #endif
+		free(ptr);
 		return (-1);
 	}
 
@@ -220,6 +213,7 @@ arprecv(d, pkt, len, tleft)
 			printf("is request\n");
 #endif
 		arp_reply(d, ah);
+		free(ptr);
 		return (-1);
 	}
 
@@ -228,6 +222,7 @@ arprecv(d, pkt, len, tleft)
 		if (debug)
 			printf("not ARP reply\n");
 #endif
+		free(ptr);
 		return (-1);
 	}
 
@@ -239,6 +234,7 @@ arprecv(d, pkt, len, tleft)
 		if (debug)
 			printf("unwanted address\n");
 #endif
+		free(ptr);
 		return (-1);
 	}
 	/* We don't care who the reply was sent to. */
@@ -248,6 +244,8 @@ arprecv(d, pkt, len, tleft)
  	if (debug)
 		printf("got it\n");
 #endif
+	*pkt = ptr;
+	*payload = ah;
 	return (n);
 }
 
@@ -256,9 +254,7 @@ arprecv(d, pkt, len, tleft)
  * Notes:  Re-uses buffer.  Pad to length = 46.
  */
 void
-arp_reply(d, pkt)
-	struct iodesc *d;
-	void *pkt;		/* the request */
+arp_reply(struct iodesc *d, void *pkt)
 {
 	struct ether_arp *arp = pkt;
 

Modified: stable/11/lib/libstand/bootp.c
==============================================================================
--- stable/11/lib/libstand/bootp.c	Sat Feb 10 04:37:44 2018	(r329099)
+++ stable/11/lib/libstand/bootp.c	Sat Feb 10 04:56:07 2018	(r329100)
@@ -38,6 +38,7 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <stddef.h>
 #include <sys/types.h>
 #include <sys/limits.h>
 #include <sys/endian.h>
@@ -72,7 +73,7 @@ static	char vm_cmu[4] = VM_CMU;
 
 /* Local forwards */
 static	ssize_t bootpsend(struct iodesc *, void *, size_t);
-static	ssize_t bootprecv(struct iodesc *, void *, size_t, time_t);
+static	ssize_t bootprecv(struct iodesc *, void **, void **, time_t);
 static	int vend_rfc1048(u_char *, u_int);
 #ifdef BOOTP_VEND_CMU
 static	void vend_cmu(u_char *);
@@ -89,23 +90,50 @@ static void setenv_(u_char *cp,  u_char *ep, struct dh
 static char expected_dhcpmsgtype = -1, dhcp_ok;
 struct in_addr dhcp_serverip;
 #endif
+struct bootp *bootp_response;
+size_t bootp_response_size;
 
+static void
+bootp_fill_request(unsigned char *bp_vend)
+{
+	/*
+	 * We are booting from PXE, we want to send the string
+	 * 'PXEClient' to the DHCP server so you have the option of
+	 * only responding to PXE aware dhcp requests.
+	 */
+	bp_vend[0] = TAG_CLASSID;
+	bp_vend[1] = 9;
+	bcopy("PXEClient", &bp_vend[2], 9);
+	bp_vend[11] = TAG_USER_CLASS;
+	/* len of each user class + number of user class */
+	bp_vend[12] = 8;
+	/* len of the first user class */
+	bp_vend[13] = 7;
+	bcopy("FreeBSD", &bp_vend[14], 7);
+	bp_vend[21] = TAG_PARAM_REQ;
+	bp_vend[22] = 7;
+	bp_vend[23] = TAG_ROOTPATH;
+	bp_vend[24] = TAG_HOSTNAME;
+	bp_vend[25] = TAG_SWAPSERVER;
+	bp_vend[26] = TAG_GATEWAY;
+	bp_vend[27] = TAG_SUBNET_MASK;
+	bp_vend[28] = TAG_INTF_MTU;
+	bp_vend[29] = TAG_SERVERID;
+	bp_vend[30] = TAG_END;
+}
+
 /* Fetch required bootp infomation */
 void
-bootp(sock, flag)
-	int sock;
-	int flag;
+bootp(int sock)
 {
+	void *pkt;
 	struct iodesc *d;
 	struct bootp *bp;
 	struct {
 		u_char header[HEADER_SIZE];
 		struct bootp wbootp;
 	} wbuf;
-	struct {
-		u_char header[HEADER_SIZE];
-		struct bootp rbootp;
-	} rbuf;
+	struct bootp *rbootp;
 
 #ifdef BOOTP_DEBUG
  	if (debug)
@@ -137,29 +165,8 @@ bootp(sock, flag)
 	bp->bp_vend[4] = TAG_DHCP_MSGTYPE;
 	bp->bp_vend[5] = 1;
 	bp->bp_vend[6] = DHCPDISCOVER;
+	bootp_fill_request(&bp->bp_vend[7]);
 
-	/*
-	 * If we are booting from PXE, we want to send the string
-	 * 'PXEClient' to the DHCP server so you have the option of
-	 * only responding to PXE aware dhcp requests.
-	 */
-	if (flag & BOOTP_PXE) {
-		bp->bp_vend[7] = TAG_CLASSID;
-		bp->bp_vend[8] = 9;
-		bcopy("PXEClient", &bp->bp_vend[9], 9);
-		bp->bp_vend[18] = TAG_PARAM_REQ;
-		bp->bp_vend[19] = 8;
-		bp->bp_vend[20] = TAG_ROOTPATH;
-		bp->bp_vend[21] = TAG_TFTP_SERVER;
-		bp->bp_vend[22] = TAG_HOSTNAME;
-		bp->bp_vend[23] = TAG_SWAPSERVER;
-		bp->bp_vend[24] = TAG_GATEWAY;
-		bp->bp_vend[25] = TAG_SUBNET_MASK;
-		bp->bp_vend[26] = TAG_INTF_MTU;
-		bp->bp_vend[27] = TAG_SERVERID;
-		bp->bp_vend[28] = TAG_END;
-	} else
-		bp->bp_vend[7] = TAG_END;
 #else
 	bp->bp_vend[4] = TAG_END;
 #endif
@@ -176,8 +183,7 @@ bootp(sock, flag)
 
 	if(sendrecv(d,
 		    bootpsend, bp, sizeof(*bp),
-		    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
-	   == -1) {
+		    bootprecv, &pkt, (void **)&rbootp) == -1) {
 	    printf("bootp: no reply\n");
 	    return;
 	}
@@ -188,7 +194,7 @@ bootp(sock, flag)
 		bp->bp_vend[6] = DHCPREQUEST;
 		bp->bp_vend[7] = TAG_REQ_ADDR;
 		bp->bp_vend[8] = 4;
-		bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4);
+		bcopy(&rbootp->bp_yiaddr, &bp->bp_vend[9], 4);
 		bp->bp_vend[13] = TAG_SERVERID;
 		bp->bp_vend[14] = 4;
 		bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4);
@@ -196,30 +202,25 @@ bootp(sock, flag)
 		bp->bp_vend[20] = 4;
 		leasetime = htonl(300);
 		bcopy(&leasetime, &bp->bp_vend[21], 4);
-		if (flag & BOOTP_PXE) {
-			bp->bp_vend[25] = TAG_CLASSID;
-			bp->bp_vend[26] = 9;
-			bcopy("PXEClient", &bp->bp_vend[27], 9);
-			bp->bp_vend[36] = TAG_END;
-		} else
-			bp->bp_vend[25] = TAG_END;
+		bootp_fill_request(&bp->bp_vend[25]);
 
 		expected_dhcpmsgtype = DHCPACK;
 
+		free(pkt);
 		if(sendrecv(d,
 			    bootpsend, bp, sizeof(*bp),
-			    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
-		   == -1) {
+			    bootprecv, &pkt, (void **)&rbootp) == -1) {
 			printf("DHCPREQUEST failed\n");
 			return;
 		}
 	}
 #endif
 
-	myip = d->myip = rbuf.rbootp.bp_yiaddr;
-	servip = rbuf.rbootp.bp_siaddr;
-	if(rootip.s_addr == INADDR_ANY) rootip = servip;
-	bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile));
+	myip = d->myip = rbootp->bp_yiaddr;
+	servip = rbootp->bp_siaddr;
+	if (rootip.s_addr == INADDR_ANY)
+		rootip = servip;
+	bcopy(rbootp->bp_file, bootfile, sizeof(bootfile));
 	bootfile[sizeof(bootfile) - 1] = '\0';
 
 	if (!netmask) {
@@ -259,14 +260,12 @@ bootp(sock, flag)
 
 	/* Bump xid so next request will be unique. */
 	++d->xid;
+	free(pkt);
 }
 
 /* Transmit a bootp request */
 static ssize_t
-bootpsend(d, pkt, len)
-	struct iodesc *d;
-	void *pkt;
-	size_t len;
+bootpsend(struct iodesc *d, void *pkt, size_t len)
 {
 	struct bootp *bp;
 
@@ -287,30 +286,25 @@ bootpsend(d, pkt, len)
 }
 
 static ssize_t
-bootprecv(d, pkt, len, tleft)
-struct iodesc *d;
-void *pkt;
-size_t len;
-time_t tleft;
+bootprecv(struct iodesc *d, void **pkt, void **payload, time_t tleft)
 {
 	ssize_t n;
 	struct bootp *bp;
+	void *ptr;
 
-#ifdef BOOTP_DEBUGx
+#ifdef BOOTP_DEBUG
 	if (debug)
 		printf("bootp_recvoffer: called\n");
 #endif
 
-	n = readudp(d, pkt, len, tleft);
+	ptr = NULL;
+	n = readudp(d, &ptr, (void **)&bp, tleft);
 	if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE)
 		goto bad;
 
-	bp = (struct bootp *)pkt;
-	
 #ifdef BOOTP_DEBUG
 	if (debug)
-		printf("bootprecv: checked.  bp = 0x%lx, n = %d\n",
-		    (long)bp, (int)n);
+		printf("bootprecv: checked.  bp = %p, n = %zd\n", bp, n);
 #endif
 	if (bp->bp_xid != htonl(d->xid)) {
 #ifdef BOOTP_DEBUG
@@ -329,8 +323,21 @@ time_t tleft;
 
 	/* 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)
+		int vsize = n - offsetof(struct bootp, bp_vend);
+		if (vend_rfc1048(bp->bp_vend, vsize) != 0)
 		    goto bad;
+
+		/* Save copy of bootp reply or DHCP ACK message */
+		if (bp->bp_op == BOOTREPLY &&
+		    ((dhcp_ok == 1 && expected_dhcpmsgtype == DHCPACK) ||
+		    dhcp_ok == 0)) {
+			free(bootp_response);
+			bootp_response = malloc(n);
+			if (bootp_response != NULL) {
+				bootp_response_size = n;
+				bcopy(bp, bootp_response, bootp_response_size);
+			}
+		}
 	}
 #ifdef BOOTP_VEND_CMU
 	else if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
@@ -339,8 +346,11 @@ time_t tleft;
 	else
 		printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend);
 
-	return(n);
+	*pkt = ptr;
+	*payload = bp;
+	return (n);
 bad:
+	free(ptr);
 	errno = 0;
 	return (-1);
 }
@@ -357,9 +367,7 @@ dhcp_try_rfc1048(u_char *cp, u_int len)
 }
 
 static int
-vend_rfc1048(cp, len)
-	u_char *cp;
-	u_int len;
+vend_rfc1048(u_char *cp, u_int len)
 {
 	u_char *ep;
 	int size;
@@ -438,10 +446,6 @@ vend_rfc1048(cp, len)
 			bcopy(cp, &dhcp_serverip.s_addr,
 			      sizeof(dhcp_serverip.s_addr));
 		}
-		if (tag == TAG_TFTP_SERVER) {
-			bcopy(cp, &tftpip.s_addr,
-			      sizeof(tftpip.s_addr));
-		}
 #endif
 		cp += size;
 	}
@@ -450,8 +454,7 @@ vend_rfc1048(cp, len)
 
 #ifdef BOOTP_VEND_CMU
 static void
-vend_cmu(cp)
-	u_char *cp;
+vend_cmu(u_char *cp)
 {
 	struct cmu_vend *vp;
 

Modified: stable/11/lib/libstand/bootp.h
==============================================================================
--- stable/11/lib/libstand/bootp.h	Sat Feb 10 04:37:44 2018	(r329099)
+++ stable/11/lib/libstand/bootp.h	Sat Feb 10 04:56:07 2018	(r329100)
@@ -108,7 +108,7 @@ struct bootp {
 #define TAG_T2			((unsigned char)  59)
 #define TAG_CLASSID		((unsigned char)  60)
 #define TAG_CLIENTID		((unsigned char)  61)
-#define TAG_TFTP_SERVER		((unsigned char) 150)
+#define TAG_USER_CLASS		((unsigned char)  77)
 #endif
 
 #define TAG_END			((unsigned char) 255)
@@ -124,12 +124,6 @@ struct bootp {
 #endif
 
 /*
- * bootp flags
- */
-#define	BOOTP_NONE		0x0000		/* No flags */
-#define	BOOTP_PXE		0x0001		/* Booting from PXE. */
-
-/*
  * "vendor" data permitted for CMU bootp clients.
  */
 
@@ -147,6 +141,10 @@ struct cmu_vend {
 
 /* v_flags values */
 #define VF_SMASK	1	/* Subnet mask field contains valid data */
+
+/* cached bootp response/dhcp ack */
+extern struct bootp *bootp_response;
+extern size_t bootp_response_size;
 
 int	dhcp_try_rfc1048(u_char *cp, u_int len);
 

Modified: stable/11/lib/libstand/bootparam.c
==============================================================================
--- stable/11/lib/libstand/bootparam.c	Sat Feb 10 04:37:44 2018	(r329099)
+++ stable/11/lib/libstand/bootparam.c	Sat Feb 10 04:56:07 2018	(r329100)
@@ -104,8 +104,7 @@ int xdr_string_decode(char **p, char *str, int *len_p)
  * know about us (don't want to broadcast a getport call).
  */
 int
-bp_whoami(sockfd)
-	int sockfd;
+bp_whoami(int sockfd)
 {
 	/* RPC structures for PMAPPROC_CALLIT */
 	struct args {
@@ -126,22 +125,19 @@ bp_whoami(sockfd)
 		n_long	h[RPC_HEADER_WORDS];
 		struct args d;
 	} sdata;
-	struct {
-		n_long	h[RPC_HEADER_WORDS];
-		struct repl d;
-	} rdata;
 	char *send_tail, *recv_head;
 	struct iodesc *d;
-	int len, x;
+	void *pkt;
+	int len, x, rc;
 
 	RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));
 
+	rc = -1;
 	if (!(d = socktodesc(sockfd))) {
 		RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
-		return (-1);
+		return (rc);
 	}
 	args = &sdata.d;
-	repl = &rdata.d;
 
 	/*
 	 * Build request args for PMAPPROC_CALLIT.
@@ -156,19 +152,19 @@ bp_whoami(sockfd)
 	 * append encapsulated data (client IP address)
 	 */
 	if (xdr_inaddr_encode(&send_tail, myip))
-		return (-1);
+		return (rc);
 
 	/* RPC: portmap/callit */
 	d->myport = htons(--rpc_port);
 	d->destip.s_addr = INADDR_BROADCAST;	/* XXX: subnet bcast? */
 	/* rpc_call will set d->destport */
 
+	pkt = NULL;
 	len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
-				  args, send_tail - (char*)args,
-				  repl, sizeof(*repl));
+	    args, send_tail - (char*)args, (void **)&repl, &pkt);
 	if (len < 8) {
 		printf("bootparamd: 'whoami' call failed\n");
-		return (-1);
+		goto done;
 	}
 
 	/* Save bootparam server address (from IP header). */
@@ -196,7 +192,7 @@ bp_whoami(sockfd)
 	x = ntohl(repl->encap_len);
 	if (len < x) {
 		printf("bp_whoami: short reply, %d < %d\n", len, x);
-		return (-1);
+		goto done;
 	}
 	recv_head = (char*) repl->capsule;
 
@@ -204,24 +200,27 @@ bp_whoami(sockfd)
 	hostnamelen = MAXHOSTNAMELEN-1;
 	if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
 		RPC_PRINTF(("bp_whoami: bad hostname\n"));
-		return (-1);
+		goto done;
 	}
 
 	/* domain name */
 	domainnamelen = MAXHOSTNAMELEN-1;
 	if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
 		RPC_PRINTF(("bp_whoami: bad domainname\n"));
-		return (-1);
+		goto done;
 	}
 
 	/* gateway address */
 	if (xdr_inaddr_decode(&recv_head, &gateip)) {
 		RPC_PRINTF(("bp_whoami: bad gateway\n"));
-		return (-1);
+		goto done;
 	}
 
 	/* success */
-	return(0);
+	rc = 0;
+done:
+	free(pkt);
+	return (rc);
 }
 
 
@@ -233,25 +232,18 @@ bp_whoami(sockfd)
  *	server pathname
  */
 int
-bp_getfile(sockfd, key, serv_addr, pathname)
-	int sockfd;
-	char *key;
-	char *pathname;
-	struct in_addr *serv_addr;
+bp_getfile(int sockfd, char *key, struct in_addr *serv_addr, char *pathname)
 {
 	struct {
 		n_long	h[RPC_HEADER_WORDS];
 		n_long  d[64];
 	} sdata;
-	struct {
-		n_long	h[RPC_HEADER_WORDS];
-		n_long  d[128];
-	} rdata;
+	void *pkt;
 	char serv_name[FNAME_SIZE];
-	char *send_tail, *recv_head;
+	char *rdata, *send_tail;
 	/* misc... */
 	struct iodesc *d;
-	int sn_len, path_len, rlen;
+	int rc = -1, sn_len, path_len, rlen;
 
 	if (!(d = socktodesc(sockfd))) {
 		RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
@@ -259,7 +251,6 @@ bp_getfile(sockfd, key, serv_addr, pathname)
 	}
 
 	send_tail = (char*) sdata.d;
-	recv_head = (char*) rdata.d;
 
 	/*
 	 * Build request message.
@@ -281,17 +272,16 @@ bp_getfile(sockfd, key, serv_addr, pathname)
 	d->myport = htons(--rpc_port);
 	d->destip   = bp_server_addr;
 	/* rpc_call will set d->destport */
-
+	pkt = NULL;
 	rlen = rpc_call(d,
 		BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
 		sdata.d, send_tail - (char*)sdata.d,
-		rdata.d, sizeof(rdata.d));
+		(void **)&rdata, &pkt);
 	if (rlen < 4) {
 		RPC_PRINTF(("bp_getfile: short reply\n"));
 		errno = EBADRPC;
-		return (-1);
+		goto done;
 	}
-	recv_head = (char*) rdata.d;
 
 	/*
 	 * Parse result message.
@@ -299,26 +289,29 @@ bp_getfile(sockfd, key, serv_addr, pathname)
 
 	/* server name */
 	sn_len = FNAME_SIZE-1;
-	if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
+	if (xdr_string_decode(&rdata, serv_name, &sn_len)) {
 		RPC_PRINTF(("bp_getfile: bad server name\n"));
-		return (-1);
+		goto done;
 	}
 
 	/* server IP address (mountd/NFS) */
-	if (xdr_inaddr_decode(&recv_head, serv_addr)) {
+	if (xdr_inaddr_decode(&rdata, serv_addr)) {
 		RPC_PRINTF(("bp_getfile: bad server addr\n"));
-		return (-1);
+		goto done;
 	}
 
 	/* server pathname */
 	path_len = MAXPATHLEN-1;
-	if (xdr_string_decode(&recv_head, pathname, &path_len)) {
+	if (xdr_string_decode(&rdata, pathname, &path_len)) {
 		RPC_PRINTF(("bp_getfile: bad server path\n"));
-		return (-1);
+		goto done;
 	}
 
 	/* success */
-	return(0);
+	rc = 0;
+done:
+	free(pkt);
+	return (rc);
 }
 
 
@@ -329,17 +322,14 @@ bp_getfile(sockfd, key, serv_addr, pathname)
 
 
 int
-xdr_string_encode(pkt, str, len)
-	char **pkt;
-	char *str;
-	int len;
+xdr_string_encode(char **pkt, char *str, int len)
 {
-	u_int32_t *lenp;
+	uint32_t *lenp;
 	char *datap;
 	int padlen = (len + 3) & ~3;	/* padded length */
 
 	/* The data will be int aligned. */
-	lenp = (u_int32_t*) *pkt;
+	lenp = (uint32_t *) *pkt;
 	*pkt += sizeof(*lenp);
 	*lenp = htonl(len);
 
@@ -351,18 +341,15 @@ xdr_string_encode(pkt, str, len)
 }
 
 int
-xdr_string_decode(pkt, str, len_p)
-	char **pkt;
-	char *str;
-	int *len_p;		/* bufsize - 1 */
+xdr_string_decode(char **pkt, char *str, int *len_p)
 {
-	u_int32_t *lenp;
+	uint32_t *lenp;
 	char *datap;
 	int slen;	/* string length */
 	int plen;	/* padded length */
 
 	/* The data will be int aligned. */
-	lenp = (u_int32_t*) *pkt;
+	lenp = (uint32_t *) *pkt;
 	*pkt += sizeof(*lenp);
 	slen = ntohl(*lenp);
 	plen = (slen + 3) & ~3;
@@ -381,9 +368,7 @@ xdr_string_decode(pkt, str, len_p)
 
 
 int
-xdr_inaddr_encode(pkt, ia)
-	char **pkt;
-	struct in_addr ia;		/* network order */
+xdr_inaddr_encode(char **pkt, struct in_addr ia)
 {
 	struct xdr_inaddr *xi;
 	u_char *cp;
@@ -414,9 +399,7 @@ xdr_inaddr_encode(pkt, ia)
 }
 
 int
-xdr_inaddr_decode(pkt, ia)
-	char **pkt;
-	struct in_addr *ia;		/* network order */
+xdr_inaddr_decode(char **pkt, struct in_addr *ia)
 {
 	struct xdr_inaddr *xi;
 	u_char *cp;

Modified: stable/11/lib/libstand/dosfs.c
==============================================================================
--- stable/11/lib/libstand/dosfs.c	Sat Feb 10 04:37:44 2018	(r329099)
+++ stable/11/lib/libstand/dosfs.c	Sat Feb 10 04:56:07 2018	(r329100)
@@ -65,6 +65,7 @@ struct fs_ops dosfs_fsops = {
 #define DEPSEC   16             /* directory entries per sector */
 #define DSHIFT    4             /* DEPSEC shift */
 #define LOCLUS    2             /* lowest cluster number */
+#define FATBLKSZ  0x20000       /* size of block in the FAT cache buffer */
 
 /* DOS "BIOS Parameter Block" */
 typedef struct {
@@ -132,18 +133,6 @@ static DOS_DE dot[2] = {
                          ((u_int)cv2((de)->dex.h_clus) << 16) |  \
 			 cv2((de)->clus))
 
-/*
- * fat cache metadata
- */
-struct fatcache {
-	int unit;	/* disk unit number */
-	int size;	/* buffer (and fat) size in sectors */
-	u_char *buf;
-};
-
-static struct fatcache fat;
-
-static int dosunmount(DOS_FS *);
 static int parsebs(DOS_FS *, DOS_BS *);
 static int namede(DOS_FS *, const char *, DOS_DE **);
 static int lookup(DOS_FS *, u_int, const char *, DOS_DE **);
@@ -153,36 +142,37 @@ static off_t fsize(DOS_FS *, DOS_DE *);
 static int fatcnt(DOS_FS *, u_int);
 static int fatget(DOS_FS *, u_int *);
 static int fatend(u_int, u_int);
-static int ioread(DOS_FS *, u_int, void *, u_int);
-static int ioget(struct open_file *, daddr_t, void *, u_int);
+static int ioread(DOS_FS *, u_int, void *, size_t);
+static int ioget(struct open_file *, daddr_t, void *, size_t);
 
-static void
-dos_read_fat(DOS_FS *fs, struct open_file *fd)
+static int
+dos_read_fatblk(DOS_FS *fs, struct open_file *fd, u_int blknum)
 {
-    struct devdesc *dd = fd->f_devdata;
+    int err;
+    size_t io_size;
+    daddr_t offset_in_fat, max_offset_in_fat;
 
-    if (fat.buf != NULL) {		/* can we reuse old buffer? */
-	if (fat.size != fs->spf) {
-	    free(fat.buf);		/* no, free old buffer */
-	    fat.buf = NULL;
-	}
-    }
+    offset_in_fat = ((daddr_t)blknum) * FATBLKSZ;
+    max_offset_in_fat = secbyt(fs->spf);
+    io_size = FATBLKSZ;
+    if (offset_in_fat > max_offset_in_fat)
+        offset_in_fat = max_offset_in_fat;
+    if (offset_in_fat + io_size > max_offset_in_fat)
+        io_size = ((size_t)(max_offset_in_fat - offset_in_fat));
 
-    if (fat.buf == NULL)
-	fat.buf = malloc(secbyt(fs->spf));
-
-    if (fat.buf != NULL) {
-	if (ioget(fd, fs->lsnfat, fat.buf, secbyt(fs->spf)) == 0) {
-	    fat.size = fs->spf;
-	    fat.unit = dd->d_unit;
-	    return;
-	}
+    if (io_size != 0) {
+        err = ioget(fd, fs->lsnfat + bytsec(offset_in_fat),
+            fs->fatbuf, io_size);
+        if (err != 0) {
+            fs->fatbuf_blknum = ((u_int)(-1));
+            return (err);
+        }
     }
-    if (fat.buf != NULL)	/* got IO error */
-	free(fat.buf);
-    fat.buf = NULL;
-    fat.unit = -1;	/* impossible unit */
-    fat.size = 0;
+    if (io_size < FATBLKSZ)
+        memset(fs->fatbuf + io_size, 0, FATBLKSZ - io_size);
+
+    fs->fatbuf_blknum = blknum;
+    return (0);
 }
 
 /*
@@ -192,24 +182,27 @@ static int
 dos_mount(DOS_FS *fs, struct open_file *fd)
 {
     int err;
-    struct devdesc *dd = fd->f_devdata;
     u_char *buf;
 
     bzero(fs, sizeof(DOS_FS));
     fs->fd = fd;
 
-    if ((err = !(buf = malloc(secbyt(1))) ? errno : 0) ||
-        (err = ioget(fs->fd, 0, buf, secbyt(1))) ||
+    if ((buf = malloc(secbyt(1))) == NULL)
+        return (errno);
+    if ((err = ioget(fs->fd, 0, buf, secbyt(1))) ||
         (err = parsebs(fs, (DOS_BS *)buf))) {
-	if (buf != NULL)
-	    free(buf);
-        (void)dosunmount(fs);
+        free(buf);
         return (err);
     }
     free(buf);
 
-    if (fat.buf == NULL || fat.unit != dd->d_unit)
-	dos_read_fat(fs, fd);
+    if ((fs->fatbuf = malloc(FATBLKSZ)) == NULL)
+        return (errno);
+    err = dos_read_fatblk(fs, fd, 0);
+    if (err != 0) {
+        free(fs->fatbuf);
+        return (err);
+    }
 
     fs->root = dot[0];
     fs->root.name[0] = ' ';
@@ -228,21 +221,9 @@ dos_mount(DOS_FS *fs, struct open_file *fd)
 static int
 dos_unmount(DOS_FS *fs)
 {
-    int err;
-
     if (fs->links)
         return (EBUSY);
-    if ((err = dosunmount(fs)))
-        return (err);
-    return (0);
-}
-
-/*
- * Common code shared by dos_mount() and dos_unmount()
- */
-static int
-dosunmount(DOS_FS *fs)
-{
+    free(fs->fatbuf);
     free(fs);
     return (0);
 }
@@ -257,16 +238,20 @@ dos_open(const char *path, struct open_file *fd)
     DOS_FILE *f;
     DOS_FS *fs;
     u_int size, clus;
-    int err = 0;
+    int err;
 
     /* Allocate mount structure, associate with open */
-    fs = malloc(sizeof(DOS_FS));
-    
-    if ((err = dos_mount(fs, fd)))
-	goto out;
+    if ((fs = malloc(sizeof(DOS_FS))) == NULL)
+        return (errno);
+    if ((err = dos_mount(fs, fd))) {
+        free(fs);
+        return (err);
+    }
 
-    if ((err = namede(fs, path, &de)))
-	goto out;
+    if ((err = namede(fs, path, &de))) {
+        dos_unmount(fs);
+        return (err);
+    }
 
     clus = stclus(fs->fatsz, de);
     size = cv4(de->size);
@@ -274,18 +259,20 @@ dos_open(const char *path, struct open_file *fd)
     if ((!(de->attr & FA_DIR) && (!clus != !size)) ||
 	((de->attr & FA_DIR) && size) ||
 	(clus && !okclus(fs, clus))) {
-        err = EINVAL;
-	goto out;
+        dos_unmount(fs);
+        return (EINVAL);
     }
-    f = malloc(sizeof(DOS_FILE));
+    if ((f = malloc(sizeof(DOS_FILE))) == NULL) {
+        err = errno;
+        dos_unmount(fs);
+        return (err);
+    }
     bzero(f, sizeof(DOS_FILE));
     f->fs = fs;
     fs->links++;
     f->de = *de;
     fd->f_fsdata = (void *)f;
-
- out:
-    return (err);
+    return (0);
 }
 
 /*
@@ -761,34 +748,57 @@ fatcnt(DOS_FS *fs, u_int c)
 }
 
 /*
- * Get next cluster in cluster chain. Use in core fat cache unless another
- * device replaced it.
+ * Get next cluster in cluster chain. Use in core fat cache unless
+ * the number of current 128K block in FAT has changed.
  */
 static int
 fatget(DOS_FS *fs, u_int *c)
 {
-    u_char buf[4];

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802100456.w1A4u7QV018955>