From owner-svn-src-all@freebsd.org Sun Dec 30 09:35:49 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D788A14206BB; Sun, 30 Dec 2018 09:35:48 +0000 (UTC) (envelope-from tsoome@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 7CD3076BA0; Sun, 30 Dec 2018 09:35:48 +0000 (UTC) (envelope-from tsoome@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 6C58721189; Sun, 30 Dec 2018 09:35:48 +0000 (UTC) (envelope-from tsoome@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id wBU9ZmMd052669; Sun, 30 Dec 2018 09:35:48 GMT (envelope-from tsoome@FreeBSD.org) Received: (from tsoome@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id wBU9Zlwg052665; Sun, 30 Dec 2018 09:35:47 GMT (envelope-from tsoome@FreeBSD.org) Message-Id: <201812300935.wBU9Zlwg052665@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: tsoome set sender to tsoome@FreeBSD.org using -f From: Toomas Soome Date: Sun, 30 Dec 2018 09:35:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r342619 - head/stand/i386/libi386 X-SVN-Group: head X-SVN-Commit-Author: tsoome X-SVN-Commit-Paths: head/stand/i386/libi386 X-SVN-Commit-Revision: 342619 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 7CD3076BA0 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.93 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.93)[-0.933,0]; NEURAL_HAM_LONG(-1.00)[-0.998,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 30 Dec 2018 09:35:49 -0000 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 +__FBSDID("$FreeBSD$"); + +#include +#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 #include +#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); }