mirror of
https://github.com/ipxe/ipxe
synced 2025-12-25 17:12:40 +03:00
[interface] Convert all data-xfer interfaces to generic interfaces
Remove data-xfer as an interface type, and replace data-xfer interfaces with generic interfaces supporting the data-xfer methods. Filter interfaces (as used by the TLS layer) are handled using the generic pass-through interface capability. A side-effect of this is that deliver_raw() no longer exists as a data-xfer method. (In practice this doesn't lose any efficiency, since there are no instances within the current codebase where xfer_deliver_raw() is used to pass data to an interface supporting the deliver_raw() method.) Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
#include <ipxe/uaccess.h>
|
||||
#include <ipxe/in.h>
|
||||
#include <ipxe/tftp.h>
|
||||
#include <ipxe/iobuf.h>
|
||||
#include <ipxe/xfer.h>
|
||||
#include <ipxe/open.h>
|
||||
#include <ipxe/process.h>
|
||||
@@ -39,7 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
/** A PXE TFTP connection */
|
||||
struct pxe_tftp_connection {
|
||||
/** Data transfer interface */
|
||||
struct xfer_interface xfer;
|
||||
struct interface xfer;
|
||||
/** Data buffer */
|
||||
userptr_t buffer;
|
||||
/** Size of data buffer */
|
||||
@@ -58,93 +59,84 @@ struct pxe_tftp_connection {
|
||||
int rc;
|
||||
};
|
||||
|
||||
/** The PXE TFTP connection */
|
||||
static struct pxe_tftp_connection pxe_tftp = {
|
||||
.xfer = XFER_INIT ( &null_xfer_ops ),
|
||||
};
|
||||
|
||||
/**
|
||||
* Close PXE TFTP connection
|
||||
*
|
||||
* @v pxe_tftp PXE TFTP connection
|
||||
* @v rc Final status code
|
||||
*/
|
||||
static void pxe_tftp_close ( int rc ) {
|
||||
xfer_nullify ( &pxe_tftp.xfer );
|
||||
xfer_close ( &pxe_tftp.xfer, rc );
|
||||
pxe_tftp.rc = rc;
|
||||
static void pxe_tftp_close ( struct pxe_tftp_connection *pxe_tftp, int rc ) {
|
||||
intf_shutdown ( &pxe_tftp->xfer, rc );
|
||||
pxe_tftp->rc = rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive new data
|
||||
*
|
||||
* @v xfer Data transfer interface
|
||||
* @v pxe_tftp PXE TFTP connection
|
||||
* @v iobuf I/O buffer
|
||||
* @v meta Transfer metadata
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int pxe_tftp_xfer_deliver_iob ( struct xfer_interface *xfer __unused,
|
||||
struct io_buffer *iobuf,
|
||||
struct xfer_metadata *meta ) {
|
||||
static int pxe_tftp_xfer_deliver ( struct pxe_tftp_connection *pxe_tftp,
|
||||
struct io_buffer *iobuf,
|
||||
struct xfer_metadata *meta ) {
|
||||
size_t len = iob_len ( iobuf );
|
||||
int rc = 0;
|
||||
|
||||
/* Calculate new buffer position */
|
||||
if ( meta->whence != SEEK_CUR )
|
||||
pxe_tftp.offset = 0;
|
||||
pxe_tftp.offset += meta->offset;
|
||||
pxe_tftp->offset = 0;
|
||||
pxe_tftp->offset += meta->offset;
|
||||
|
||||
/* Copy data block to buffer */
|
||||
if ( len == 0 ) {
|
||||
/* No data (pure seek); treat as success */
|
||||
} else if ( pxe_tftp.offset < pxe_tftp.start ) {
|
||||
} else if ( pxe_tftp->offset < pxe_tftp->start ) {
|
||||
DBG ( " buffer underrun at %zx (min %zx)",
|
||||
pxe_tftp.offset, pxe_tftp.start );
|
||||
pxe_tftp->offset, pxe_tftp->start );
|
||||
rc = -ENOBUFS;
|
||||
} else if ( ( pxe_tftp.offset + len ) >
|
||||
( pxe_tftp.start + pxe_tftp.size ) ) {
|
||||
} else if ( ( pxe_tftp->offset + len ) >
|
||||
( pxe_tftp->start + pxe_tftp->size ) ) {
|
||||
DBG ( " buffer overrun at %zx (max %zx)",
|
||||
( pxe_tftp.offset + len ),
|
||||
( pxe_tftp.start + pxe_tftp.size ) );
|
||||
( pxe_tftp->offset + len ),
|
||||
( pxe_tftp->start + pxe_tftp->size ) );
|
||||
rc = -ENOBUFS;
|
||||
} else {
|
||||
copy_to_user ( pxe_tftp.buffer,
|
||||
( pxe_tftp.offset - pxe_tftp.start ),
|
||||
copy_to_user ( pxe_tftp->buffer,
|
||||
( pxe_tftp->offset - pxe_tftp->start ),
|
||||
iobuf->data, len );
|
||||
}
|
||||
|
||||
/* Calculate new buffer position */
|
||||
pxe_tftp.offset += len;
|
||||
pxe_tftp->offset += len;
|
||||
|
||||
/* Record maximum offset as the file size */
|
||||
if ( pxe_tftp.max_offset < pxe_tftp.offset )
|
||||
pxe_tftp.max_offset = pxe_tftp.offset;
|
||||
if ( pxe_tftp->max_offset < pxe_tftp->offset )
|
||||
pxe_tftp->max_offset = pxe_tftp->offset;
|
||||
|
||||
/* Terminate transfer on error */
|
||||
if ( rc != 0 )
|
||||
pxe_tftp_close ( rc );
|
||||
pxe_tftp_close ( pxe_tftp, rc );
|
||||
|
||||
free_iob ( iobuf );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle close() event
|
||||
*
|
||||
* @v xfer Data transfer interface
|
||||
* @v rc Reason for close
|
||||
*/
|
||||
static void pxe_tftp_xfer_close ( struct xfer_interface *xfer __unused,
|
||||
int rc ) {
|
||||
pxe_tftp_close ( rc );
|
||||
}
|
||||
/** PXE TFTP connection interface operations */
|
||||
static struct interface_operation pxe_tftp_xfer_ops[] = {
|
||||
INTF_OP ( xfer_deliver, struct pxe_tftp_connection *,
|
||||
pxe_tftp_xfer_deliver ),
|
||||
INTF_OP ( intf_close, struct pxe_tftp_connection *, pxe_tftp_close ),
|
||||
};
|
||||
|
||||
static struct xfer_interface_operations pxe_tftp_xfer_ops = {
|
||||
.close = pxe_tftp_xfer_close,
|
||||
.vredirect = xfer_vreopen,
|
||||
.window = unlimited_xfer_window,
|
||||
.alloc_iob = default_xfer_alloc_iob,
|
||||
.deliver_iob = pxe_tftp_xfer_deliver_iob,
|
||||
.deliver_raw = xfer_deliver_as_iob,
|
||||
/** PXE TFTP connection interface descriptor */
|
||||
static struct interface_descriptor pxe_tftp_xfer_desc =
|
||||
INTF_DESC ( struct pxe_tftp_connection, xfer, pxe_tftp_xfer_ops );
|
||||
|
||||
/** The PXE TFTP connection */
|
||||
static struct pxe_tftp_connection pxe_tftp = {
|
||||
.xfer = INTF_INIT ( pxe_tftp_xfer_desc ),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -173,7 +165,7 @@ static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
|
||||
|
||||
/* Reset PXE TFTP connection structure */
|
||||
memset ( &pxe_tftp, 0, sizeof ( pxe_tftp ) );
|
||||
xfer_init ( &pxe_tftp.xfer, &pxe_tftp_xfer_ops, NULL );
|
||||
intf_init ( &pxe_tftp.xfer, &pxe_tftp_xfer_desc, NULL );
|
||||
pxe_tftp.rc = -EINPROGRESS;
|
||||
|
||||
/* Construct URI string */
|
||||
@@ -247,7 +239,7 @@ PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
|
||||
DBG ( "PXENV_TFTP_OPEN" );
|
||||
|
||||
/* Guard against callers that fail to close before re-opening */
|
||||
pxe_tftp_close ( 0 );
|
||||
pxe_tftp_close ( &pxe_tftp, 0 );
|
||||
|
||||
/* Open connection */
|
||||
if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress,
|
||||
@@ -296,7 +288,7 @@ PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
|
||||
PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) {
|
||||
DBG ( "PXENV_TFTP_CLOSE" );
|
||||
|
||||
pxe_tftp_close ( 0 );
|
||||
pxe_tftp_close ( &pxe_tftp, 0 );
|
||||
tftp_close->Status = PXENV_STATUS_SUCCESS;
|
||||
return PXENV_EXIT_SUCCESS;
|
||||
}
|
||||
@@ -491,7 +483,7 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
|
||||
tftp_read_file->BufferSize = pxe_tftp.max_offset;
|
||||
|
||||
/* Close TFTP file */
|
||||
pxe_tftp_close ( rc );
|
||||
pxe_tftp_close ( &pxe_tftp, rc );
|
||||
|
||||
tftp_read_file->Status = PXENV_STATUS ( rc );
|
||||
return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
|
||||
@@ -565,7 +557,7 @@ PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
|
||||
rc = 0;
|
||||
|
||||
/* Close TFTP file */
|
||||
pxe_tftp_close ( rc );
|
||||
pxe_tftp_close ( &pxe_tftp, rc );
|
||||
|
||||
tftp_get_fsize->Status = PXENV_STATUS ( rc );
|
||||
return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <byteswap.h>
|
||||
#include <ipxe/iobuf.h>
|
||||
#include <ipxe/xfer.h>
|
||||
#include <ipxe/udp.h>
|
||||
#include <ipxe/uaccess.h>
|
||||
@@ -35,7 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
||||
/** A PXE UDP connection */
|
||||
struct pxe_udp_connection {
|
||||
/** Data transfer interface to UDP stack */
|
||||
struct xfer_interface xfer;
|
||||
struct interface xfer;
|
||||
/** Local address */
|
||||
struct sockaddr_in local;
|
||||
/** Current PXENV_UDP_READ parameter block */
|
||||
@@ -45,7 +46,7 @@ struct pxe_udp_connection {
|
||||
/**
|
||||
* Receive PXE UDP data
|
||||
*
|
||||
* @v xfer Data transfer interface
|
||||
* @v pxe_udp PXE UDP connection
|
||||
* @v iobuf I/O buffer
|
||||
* @v meta Data transfer metadata
|
||||
* @ret rc Return status code
|
||||
@@ -53,11 +54,9 @@ struct pxe_udp_connection {
|
||||
* Receives a packet as part of the current pxenv_udp_read()
|
||||
* operation.
|
||||
*/
|
||||
static int pxe_udp_deliver_iob ( struct xfer_interface *xfer,
|
||||
struct io_buffer *iobuf,
|
||||
struct xfer_metadata *meta ) {
|
||||
struct pxe_udp_connection *pxe_udp =
|
||||
container_of ( xfer, struct pxe_udp_connection, xfer );
|
||||
static int pxe_udp_deliver ( struct pxe_udp_connection *pxe_udp,
|
||||
struct io_buffer *iobuf,
|
||||
struct xfer_metadata *meta ) {
|
||||
struct s_PXENV_UDP_READ *pxenv_udp_read = pxe_udp->pxenv_udp_read;
|
||||
struct sockaddr_in *sin_src;
|
||||
struct sockaddr_in *sin_dest;
|
||||
@@ -102,18 +101,17 @@ static int pxe_udp_deliver_iob ( struct xfer_interface *xfer,
|
||||
}
|
||||
|
||||
/** PXE UDP data transfer interface operations */
|
||||
static struct xfer_interface_operations pxe_udp_xfer_operations = {
|
||||
.close = ignore_xfer_close,
|
||||
.vredirect = ignore_xfer_vredirect,
|
||||
.window = unlimited_xfer_window,
|
||||
.alloc_iob = default_xfer_alloc_iob,
|
||||
.deliver_iob = pxe_udp_deliver_iob,
|
||||
.deliver_raw = xfer_deliver_as_iob,
|
||||
static struct interface_operation pxe_udp_xfer_operations[] = {
|
||||
INTF_OP ( xfer_deliver, struct pxe_udp_connection *, pxe_udp_deliver ),
|
||||
};
|
||||
|
||||
/** PXE UDP data transfer interface descriptor */
|
||||
static struct interface_descriptor pxe_udp_xfer_desc =
|
||||
INTF_DESC ( struct pxe_udp_connection, xfer, pxe_udp_xfer_operations );
|
||||
|
||||
/** The PXE UDP connection */
|
||||
static struct pxe_udp_connection pxe_udp = {
|
||||
.xfer = XFER_INIT ( &pxe_udp_xfer_operations ),
|
||||
.xfer = INTF_INIT ( pxe_udp_xfer_desc ),
|
||||
.local = {
|
||||
.sin_family = AF_INET,
|
||||
},
|
||||
@@ -171,7 +169,7 @@ PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
|
||||
DBG ( " %s", inet_ntoa ( pxe_udp.local.sin_addr ) );
|
||||
|
||||
/* Open promiscuous UDP connection */
|
||||
xfer_close ( &pxe_udp.xfer, 0 );
|
||||
intf_restart ( &pxe_udp.xfer, 0 );
|
||||
if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) {
|
||||
pxenv_udp_open->Status = PXENV_STATUS ( rc );
|
||||
return PXENV_EXIT_FAILURE;
|
||||
@@ -206,7 +204,7 @@ PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) {
|
||||
DBG ( "PXENV_UDP_CLOSE" );
|
||||
|
||||
/* Close UDP connection */
|
||||
xfer_close ( &pxe_udp.xfer, 0 );
|
||||
intf_restart ( &pxe_udp.xfer, 0 );
|
||||
|
||||
pxenv_udp_close->Status = PXENV_STATUS_SUCCESS;
|
||||
return PXENV_EXIT_SUCCESS;
|
||||
@@ -304,8 +302,7 @@ PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
|
||||
ntohs ( pxenv_udp_write->dst_port ) );
|
||||
|
||||
/* Transmit packet */
|
||||
if ( ( rc = xfer_deliver_iob_meta ( &pxe_udp.xfer, iobuf,
|
||||
&meta ) ) != 0 ) {
|
||||
if ( ( rc = xfer_deliver ( &pxe_udp.xfer, iobuf, &meta ) ) != 0 ) {
|
||||
pxenv_udp_write->Status = PXENV_STATUS ( rc );
|
||||
return PXENV_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user