Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 30 Dec 2018 09:35:47 +0000 (UTC)
From:      Toomas Soome <tsoome@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r342619 - head/stand/i386/libi386
Message-ID:  <201812300935.wBU9Zlwg052665@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tsoome
Date: Sun Dec 30 09:35:47 2018
New Revision: 342619
URL: https://svnweb.freebsd.org/changeset/base/342619

Log:
  loader: create bio_alloc and bio_free for bios bounce buffer
  
  We do have 16KB buffer space defined in pxe.c, move it to bio.c and implement
  bio_alloc()/bio_free() interface to make it possible to use this space for
  other BIOS calls (notably, from biosdisk.c).
  
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D17131

Added:
  head/stand/i386/libi386/bio.c   (contents, props changed)
Modified:
  head/stand/i386/libi386/Makefile
  head/stand/i386/libi386/biosdisk.c
  head/stand/i386/libi386/libi386.h
  head/stand/i386/libi386/pxe.c

Modified: head/stand/i386/libi386/Makefile
==============================================================================
--- head/stand/i386/libi386/Makefile	Sun Dec 30 09:13:38 2018	(r342618)
+++ head/stand/i386/libi386/Makefile	Sun Dec 30 09:35:47 2018	(r342619)
@@ -4,7 +4,7 @@
 
 LIB=			i386
 
-SRCS=	biosacpi.c biosdisk.c biosmem.c biospnp.c \
+SRCS=	bio.c biosacpi.c biosdisk.c biosmem.c biospnp.c \
 	biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \
 	comconsole.c devicename.c elf32_freebsd.c \
 	elf64_freebsd.c multiboot.c multiboot_tramp.S relocater_tramp.S \

Added: head/stand/i386/libi386/bio.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/stand/i386/libi386/bio.c	Sun Dec 30 09:35:47 2018	(r342619)
@@ -0,0 +1,65 @@
+/*-
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stand.h>
+#include "libi386.h"
+
+/*
+ * The idea is borrowed from pxe.c and zfsimpl.c. The original buffer
+ * space in pxe.c was 2x 0x2000. Allocating it from BSS will give us needed
+ * memory below 1MB and usable for real mode calls.
+ *
+ * Note the allocations and frees are to be done in reverse order (LIFO).
+ */
+
+static char bio_buffer[BIO_BUFFER_SIZE];
+static char *bio_buffer_end = bio_buffer + BIO_BUFFER_SIZE;
+static char *bio_buffer_ptr = bio_buffer;
+
+void *
+bio_alloc(size_t size)
+{
+	char *ptr;
+
+	ptr = bio_buffer_ptr;
+	if (ptr + size > bio_buffer_end)
+		return (NULL);
+	bio_buffer_ptr += size;
+
+	return (ptr);
+}
+
+void
+bio_free(void *ptr, size_t size)
+{
+
+	if (ptr == NULL)
+		return;
+
+	bio_buffer_ptr -= size;
+	if (bio_buffer_ptr != ptr)
+		panic("bio_alloc()/bio_free() mismatch\n");
+}

Modified: head/stand/i386/libi386/biosdisk.c
==============================================================================
--- head/stand/i386/libi386/biosdisk.c	Sun Dec 30 09:13:38 2018	(r342618)
+++ head/stand/i386/libi386/biosdisk.c	Sun Dec 30 09:35:47 2018	(r342619)
@@ -469,10 +469,10 @@ bd_get_diskinfo_ext(struct bdinfo *bd)
 	 * Sector size must be a multiple of 512 bytes.
 	 * An alternate test would be to check power of 2,
 	 * powerof2(params.sector_size).
-	 * 4K is largest read buffer we can use at this time.
+	 * 16K is largest read buffer we can use at this time.
 	 */
 	if (params.sector_size >= 512 &&
-	    params.sector_size <= 4096 &&
+	    params.sector_size <= 16384 &&
 	    (params.sector_size % BIOSDISK_SECSIZE) == 0)
 		bd->bd_sectorsize = params.sector_size;
 
@@ -861,8 +861,8 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 	struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
 	bdinfo_t *bd;
 	uint64_t disk_blocks, offset, d_offset;
-	size_t blks, blkoff, bsize, rest;
-	caddr_t bbuf;
+	size_t blks, blkoff, bsize, bio_size, rest;
+	caddr_t bbuf = NULL;
 	int rc;
 
 	bd = bd_get_bdinfo(&dev->dd);
@@ -937,14 +937,25 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 		DEBUG("short I/O %d", blks);
 	}
 
-	if (V86_IO_BUFFER_SIZE / bd->bd_sectorsize == 0)
-		panic("BUG: Real mode buffer is too small");
+	bio_size = min(BIO_BUFFER_SIZE, size);
+	while (bio_size > bd->bd_sectorsize) {
+		bbuf = bio_alloc(bio_size);
+		if (bbuf != NULL)
+			break;
+		bio_size -= bd->bd_sectorsize;
+	}
+	if (bbuf == NULL) {
+		bio_size = V86_IO_BUFFER_SIZE;
+		if (bio_size / bd->bd_sectorsize == 0)
+			panic("BUG: Real mode buffer is too small");
 
-	bbuf = PTOV(V86_IO_BUFFER);
+		/* Use alternate 4k buffer */
+		bbuf = PTOV(V86_IO_BUFFER);
+	}
 	rest = size;
-
+	rc = 0;
 	while (blks > 0) {
-		int x = min(blks, V86_IO_BUFFER_SIZE / bd->bd_sectorsize);
+		int x = min(blks, bio_size / bd->bd_sectorsize);
 
 		switch (rw & F_MASK) {
 		case F_READ:
@@ -953,8 +964,10 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 			if (rest < bsize)
 				bsize = rest;
 
-			if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD)) != 0)
-				return (EIO);
+			if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_RD)) != 0) {
+				rc = EIO;
+				goto error;
+			}
 
 			bcopy(bbuf + blkoff, buf, bsize);
 			break;
@@ -986,13 +999,16 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 			 * Put your Data In, and shake it all about
 			 */
 			bcopy(buf, bbuf + blkoff, bsize);
-			if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_WR)) != 0)
-				return (EIO);
+			if ((rc = bd_io(dev, bd, dblk, x, bbuf, BD_WR)) != 0) {
+				rc = EIO;
+				goto error;
+			}
 
 			break;
 		default:
 			/* DO NOTHING */
-			return (EROFS);
+			rc = EROFS;
+			goto error;
 		}
 
 		blkoff = 0;
@@ -1004,7 +1020,10 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, s
 
 	if (rsize != NULL)
 		*rsize = size;
-	return (0);
+error:
+	if (bbuf != PTOV(V86_IO_BUFFER))
+		bio_free(bbuf, bio_size);
+	return (rc);
 }
 
 static int

Modified: head/stand/i386/libi386/libi386.h
==============================================================================
--- head/stand/i386/libi386/libi386.h	Sun Dec 30 09:13:38 2018	(r342618)
+++ head/stand/i386/libi386/libi386.h	Sun Dec 30 09:35:47 2018	(r342619)
@@ -121,6 +121,11 @@ extern vm_offset_t	memtop_copyin;	/* memtop less heap 
 extern uint32_t		high_heap_size;	/* extended memory region available */
 extern vm_offset_t	high_heap_base;	/* for use as the heap */
 
+/* 16KB buffer space for real mode data transfers. */
+#define	BIO_BUFFER_SIZE 0x4000
+void *bio_alloc(size_t size);
+void bio_free(void *ptr, size_t size);
+
 /*
  * Values for width parameter to biospci_{read,write}_config
  */

Modified: head/stand/i386/libi386/pxe.c
==============================================================================
--- head/stand/i386/libi386/pxe.c	Sun Dec 30 09:13:38 2018	(r342618)
+++ head/stand/i386/libi386/pxe.c	Sun Dec 30 09:35:47 2018	(r342619)
@@ -48,18 +48,10 @@ __FBSDID("$FreeBSD$");
 
 #include <bootp.h>
 #include <bootstrap.h>
+#include "libi386.h"
 #include "btxv86.h"
 #include "pxe.h"
 
-/*
- * Allocate the PXE buffers statically instead of sticking grimy fingers into
- * BTX's private data area. The scratch buffer is used to send information to
- * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS.
- */
-#define	PXE_BUFFER_SIZE		0x2000
-static char	scratch_buffer[PXE_BUFFER_SIZE];
-static char	data_buffer[PXE_BUFFER_SIZE];
-
 static pxenv_t *pxenv_p = NULL;	/* PXENV+ */
 static pxe_t *pxe_p = NULL;		/* !PXE */
 
@@ -68,9 +60,9 @@ static int	pxe_debug = 0;
 #endif
 
 void		pxe_enable(void *pxeinfo);
-static void	(*pxe_call)(int func);
-static void	pxenv_call(int func);
-static void	bangpxe_call(int func);
+static void	(*pxe_call)(int func, void *ptr);
+static void	pxenv_call(int func, void *ptr);
+static void	bangpxe_call(int func, void *ptr);
 
 static int	pxe_init(void);
 static int	pxe_print(int verbose);
@@ -225,12 +217,17 @@ pxe_init(void)
 		printf("@%04x:%04x\n",
 		    pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset);
 
-	gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer;
+	gci_p = bio_alloc(sizeof(*gci_p));
+	if (gci_p == NULL) {
+		pxe_p = NULL;
+		return (0);
+	}
 	bzero(gci_p, sizeof(*gci_p));
 	gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY;
-	pxe_call(PXENV_GET_CACHED_INFO);
+	pxe_call(PXENV_GET_CACHED_INFO, gci_p);
 	if (gci_p->Status != 0) {
 		pxe_perror(gci_p->Status);
+		bio_free(gci_p, sizeof(*gci_p));
 		pxe_p = NULL;
 		return (0);
 	}
@@ -240,6 +237,7 @@ pxe_init(void)
 		bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset),
 		    bootp_response, bootp_response_size);
 	}
+	bio_free(gci_p, sizeof(*gci_p));
 	return (1);
 }
 
@@ -262,31 +260,37 @@ pxe_print(int verbose)
 static void
 pxe_cleanup(void)
 {
-#ifdef PXE_DEBUG
-	t_PXENV_UNLOAD_STACK *unload_stack_p =
-		(t_PXENV_UNLOAD_STACK *)scratch_buffer;
-	t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p =
-		(t_PXENV_UNDI_SHUTDOWN *)scratch_buffer;
-#endif
+	t_PXENV_UNLOAD_STACK *unload_stack_p;
+	t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p;
 
 	if (pxe_call == NULL)
 		return;
 
-	pxe_call(PXENV_UNDI_SHUTDOWN);
+	undi_shutdown_p = bio_alloc(sizeof(*undi_shutdown_p));
+	if (undi_shutdown_p != NULL) {
+		bzero(undi_shutdown_p, sizeof(*undi_shutdown_p));
+		pxe_call(PXENV_UNDI_SHUTDOWN, undi_shutdown_p);
 
 #ifdef PXE_DEBUG
-	if (pxe_debug && undi_shutdown_p->Status != 0)
-		printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n",
-		    undi_shutdown_p->Status);
+		if (pxe_debug && undi_shutdown_p->Status != 0)
+			printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n",
+			    undi_shutdown_p->Status);
 #endif
+		bio_free(undi_shutdown_p, sizeof(*undi_shutdown_p));
+	}
 
-	pxe_call(PXENV_UNLOAD_STACK);
+	unload_stack_p = bio_alloc(sizeof(*unload_stack_p));
+	if (unload_stack_p != NULL) {
+		bzero(unload_stack_p, sizeof(*unload_stack_p));
+		pxe_call(PXENV_UNLOAD_STACK, unload_stack_p);
 
 #ifdef PXE_DEBUG
-	if (pxe_debug && unload_stack_p->Status != 0)
-		printf("pxe_cleanup: UNLOAD_STACK failed %x\n",
-		    unload_stack_p->Status);
+		if (pxe_debug && unload_stack_p->Status != 0)
+			printf("pxe_cleanup: UNLOAD_STACK failed %x\n",
+			    unload_stack_p->Status);
 #endif
+		bio_free(unload_stack_p, sizeof(*unload_stack_p));
+	}
 }
 
 void
@@ -296,7 +300,7 @@ pxe_perror(int err)
 }
 
 void
-pxenv_call(int func)
+pxenv_call(int func, void *ptr)
 {
 #ifdef PXE_DEBUG
 	if (pxe_debug)
@@ -304,14 +308,13 @@ pxenv_call(int func)
 #endif
 	
 	bzero(&v86, sizeof(v86));
-	bzero(data_buffer, sizeof(data_buffer));
 
 	__pxenvseg = pxenv_p->RMEntry.segment;
 	__pxenvoff = pxenv_p->RMEntry.offset;
 	
 	v86.ctl  = V86_ADDR | V86_CALLF | V86_FLAGS;
-	v86.es   = VTOPSEG(scratch_buffer);
-	v86.edi  = VTOPOFF(scratch_buffer);
+	v86.es   = VTOPSEG(ptr);
+	v86.edi  = VTOPOFF(ptr);
 	v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry);
 	v86.ebx  = func;
 	v86int();
@@ -319,7 +322,7 @@ pxenv_call(int func)
 }
 
 void
-bangpxe_call(int func)
+bangpxe_call(int func, void *ptr)
 {
 #ifdef PXE_DEBUG
 	if (pxe_debug)
@@ -327,14 +330,13 @@ bangpxe_call(int func)
 #endif
 
 	bzero(&v86, sizeof(v86));
-	bzero(data_buffer, sizeof(data_buffer));
 
 	__bangpxeseg = pxe_p->EntryPointSP.segment;
 	__bangpxeoff = pxe_p->EntryPointSP.offset;
 
 	v86.ctl  = V86_ADDR | V86_CALLF | V86_FLAGS;
-	v86.edx  = VTOPSEG(scratch_buffer);
-	v86.eax  = VTOPOFF(scratch_buffer);
+	v86.edx  = VTOPSEG(ptr);
+	v86.eax  = VTOPOFF(ptr);
 	v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry);
 	v86.ebx  = func;
 	v86int();
@@ -362,11 +364,14 @@ pxe_netif_end(struct netif *nif)
 {
 	t_PXENV_UNDI_CLOSE *undi_close_p;
 
-	undi_close_p = (t_PXENV_UNDI_CLOSE *)scratch_buffer;
-	bzero(undi_close_p, sizeof(*undi_close_p));
-	pxe_call(PXENV_UNDI_CLOSE);
-	if (undi_close_p->Status != 0)
-		printf("undi close failed: %x\n", undi_close_p->Status);
+	undi_close_p = bio_alloc(sizeof(*undi_close_p));
+	if (undi_close_p != NULL) {
+		bzero(undi_close_p, sizeof(*undi_close_p));
+		pxe_call(PXENV_UNDI_CLOSE, undi_close_p);
+		if (undi_close_p->Status != 0)
+			printf("undi close failed: %x\n", undi_close_p->Status);
+		bio_free(undi_close_p, sizeof(*undi_close_p));
+	}
 }
 
 static void
@@ -377,11 +382,15 @@ pxe_netif_init(struct iodesc *desc, void *machdep_hint
 	uint8_t *mac;
 	int i, len;
 
-	undi_info_p = (t_PXENV_UNDI_GET_INFORMATION *)scratch_buffer;
+	undi_info_p = bio_alloc(sizeof(*undi_info_p));
+	if (undi_info_p == NULL)
+		return;
+
 	bzero(undi_info_p, sizeof(*undi_info_p));
-	pxe_call(PXENV_UNDI_GET_INFORMATION);
+	pxe_call(PXENV_UNDI_GET_INFORMATION, undi_info_p);
 	if (undi_info_p->Status != 0) {
 		printf("undi get info failed: %x\n", undi_info_p->Status);
+		bio_free(undi_info_p, sizeof(*undi_info_p));
 		return;
 	}
 
@@ -410,32 +419,44 @@ pxe_netif_init(struct iodesc *desc, void *machdep_hint
 	else
 		desc->xid = 0;
 
-	undi_open_p = (t_PXENV_UNDI_OPEN *)scratch_buffer;
+	bio_free(undi_info_p, sizeof(*undi_info_p));
+	undi_open_p = bio_alloc(sizeof(*undi_open_p));
+	if (undi_open_p == NULL)
+		return;
 	bzero(undi_open_p, sizeof(*undi_open_p));
 	undi_open_p->PktFilter = FLTR_DIRECTED | FLTR_BRDCST;
-	pxe_call(PXENV_UNDI_OPEN);
+	pxe_call(PXENV_UNDI_OPEN, undi_open_p);
 	if (undi_open_p->Status != 0)
 		printf("undi open failed: %x\n", undi_open_p->Status);
+	bio_free(undi_open_p, sizeof(*undi_open_p));
 }
 
 static int
 pxe_netif_receive(void **pkt)
 {
-	t_PXENV_UNDI_ISR *isr = (t_PXENV_UNDI_ISR *)scratch_buffer;
+	t_PXENV_UNDI_ISR *isr;
 	char *buf, *ptr, *frame;
 	size_t size, rsize;
 
+	isr = bio_alloc(sizeof(*isr));
+	if (isr == NULL)
+		return (-1);
+
 	bzero(isr, sizeof(*isr));
 	isr->FuncFlag = PXENV_UNDI_ISR_IN_START;
-	pxe_call(PXENV_UNDI_ISR);
-	if (isr->Status != 0)
+	pxe_call(PXENV_UNDI_ISR, isr);
+	if (isr->Status != 0) {
+		bio_free(isr, sizeof(*isr));
 		return (-1);
+	}
 
 	bzero(isr, sizeof(*isr));
 	isr->FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
-	pxe_call(PXENV_UNDI_ISR);
-	if (isr->Status != 0)
+	pxe_call(PXENV_UNDI_ISR, isr);
+	if (isr->Status != 0) {
+		bio_free(isr, sizeof(*isr));
 		return (-1);
+	}
 
 	while (isr->FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) {
 		/*
@@ -443,26 +464,31 @@ pxe_netif_receive(void **pkt)
 		 */
 		bzero(isr, sizeof(*isr));
 		isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
-		pxe_call(PXENV_UNDI_ISR);
+		pxe_call(PXENV_UNDI_ISR, isr);
 		if (isr->Status != 0 ||
-		    isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE)
+		    isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE) {
+			bio_free(isr, sizeof(*isr));
 			return (-1);
+		}
 	}
 
 	while (isr->FuncFlag != PXENV_UNDI_ISR_OUT_RECEIVE) {
 		if (isr->Status != 0 ||
 		    isr->FuncFlag == PXENV_UNDI_ISR_OUT_DONE) {
+			bio_free(isr, sizeof(*isr));
 			return (-1);
 		}
 		bzero(isr, sizeof(*isr));
 		isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
-		pxe_call(PXENV_UNDI_ISR);
+		pxe_call(PXENV_UNDI_ISR, isr);
 	}
 
 	size = isr->FrameLength;
 	buf = malloc(size + ETHER_ALIGN);
-	if (buf == NULL)
+	if (buf == NULL) {
+		bio_free(isr, sizeof(*isr));
 		return (-1);
+	}
 	ptr = buf + ETHER_ALIGN;
 	rsize = 0;
 
@@ -475,8 +501,9 @@ pxe_netif_receive(void **pkt)
 
 		bzero(isr, sizeof(*isr));
 		isr->FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
-		pxe_call(PXENV_UNDI_ISR);
+		pxe_call(PXENV_UNDI_ISR, isr);
 		if (isr->Status != 0) {
+			bio_free(isr, sizeof(*isr));
 			free(buf);
 			return (-1);
 		}
@@ -488,6 +515,7 @@ pxe_netif_receive(void **pkt)
 	}
 
 	*pkt = buf;
+	bio_free(isr, sizeof(*isr));
 	return (rsize);
 }
 
@@ -515,26 +543,31 @@ pxe_netif_put(struct iodesc *desc, void *pkt, size_t l
 	t_PXENV_UNDI_TRANSMIT *trans_p;
 	t_PXENV_UNDI_TBD *tbd_p;
 	char *data;
+	ssize_t rv = -1;
 
-	trans_p = (t_PXENV_UNDI_TRANSMIT *)scratch_buffer;
-	bzero(trans_p, sizeof(*trans_p));
-	tbd_p = (t_PXENV_UNDI_TBD *)(scratch_buffer + sizeof(*trans_p));
-	bzero(tbd_p, sizeof(*tbd_p));
+	trans_p = bio_alloc(sizeof(*trans_p));
+	tbd_p = bio_alloc(sizeof(*tbd_p));
+	data = bio_alloc(len);
 
-	data = scratch_buffer + sizeof(*trans_p) + sizeof(*tbd_p);
+	if (trans_p != NULL && tbd_p != NULL && data != NULL) {
+		bzero(trans_p, sizeof(*trans_p));
+		bzero(tbd_p, sizeof(*tbd_p));
 
-	trans_p->TBD.segment = VTOPSEG(tbd_p);
-	trans_p->TBD.offset  = VTOPOFF(tbd_p);
+		trans_p->TBD.segment = VTOPSEG(tbd_p);
+		trans_p->TBD.offset  = VTOPOFF(tbd_p);
 
-	tbd_p->ImmedLength = len;
-	tbd_p->Xmit.segment = VTOPSEG(data);
-	tbd_p->Xmit.offset  = VTOPOFF(data);
-	bcopy(pkt, data, len);
+		tbd_p->ImmedLength = len;
+		tbd_p->Xmit.segment = VTOPSEG(data);
+		tbd_p->Xmit.offset  = VTOPOFF(data);
+		bcopy(pkt, data, len);
 
-	pxe_call(PXENV_UNDI_TRANSMIT);
-	if (trans_p->Status != 0) {
-		return (-1);
+		pxe_call(PXENV_UNDI_TRANSMIT, trans_p);
+		if (trans_p->Status == 0)
+			rv = len;
 	}
 
-	return (len);
+	bio_free(data, len);
+	bio_free(tbd_p, sizeof(*tbd_p));
+	bio_free(trans_p, sizeof(*trans_p));
+	return (rv);
 }



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