aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2015-07-20 12:15:21 +0100
committerMichael Brown <mcb30@ipxe.org>2015-07-22 21:17:47 +0100
commit07b0d4fa30d021322efa8a423295a0677325ec8d (patch)
tree92ae1c8e37930a89835b77c488067b91bb0c52e2
parentcbbd6b761ed315ab6df82f1434657ef76bb3e676 (diff)
downloadipxe-07b0d4fa30d021322efa8a423295a0677325ec8d.zip
ipxe-07b0d4fa30d021322efa8a423295a0677325ec8d.tar.gz
ipxe-07b0d4fa30d021322efa8a423295a0677325ec8d.tar.bz2
[xferbuf] Add xfer_buffer() to provide direct access to underlying buffer
Allow data transfer buffer users to provide direct access to their underlying data transfer buffer. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/core/xferbuf.c39
-rw-r--r--src/include/ipxe/xferbuf.h5
2 files changed, 44 insertions, 0 deletions
diff --git a/src/core/xferbuf.c b/src/core/xferbuf.c
index 7f9780b..afc72ae 100644
--- a/src/core/xferbuf.c
+++ b/src/core/xferbuf.c
@@ -283,3 +283,42 @@ struct xfer_buffer_operations xferbuf_umalloc_operations = {
.write = xferbuf_umalloc_write,
.read = xferbuf_umalloc_read,
};
+
+/**
+ * Get underlying data transfer buffer
+ *
+ * @v interface Data transfer interface
+ * @ret xferbuf Data transfer buffer, or NULL on error
+ *
+ * This call will check that the xfer_buffer() handler belongs to the
+ * destination interface which also provides xfer_deliver() for this
+ * interface.
+ *
+ * This is done to prevent accidental accesses to a data transfer
+ * buffer which may be located behind a non-transparent datapath via a
+ * series of pass-through interfaces.
+ */
+struct xfer_buffer * xfer_buffer ( struct interface *intf ) {
+ struct interface *dest;
+ xfer_buffer_TYPE ( void * ) *op =
+ intf_get_dest_op ( intf, xfer_buffer, &dest );
+ void *object = intf_object ( dest );
+ struct interface *xfer_deliver_dest;
+ struct xfer_buffer *xferbuf;
+
+ /* Check that this operation is provided by the same interface
+ * which handles xfer_deliver().
+ */
+ intf_get_dest_op ( intf, xfer_deliver, &xfer_deliver_dest );
+
+ if ( op && ( dest == xfer_deliver_dest ) ) {
+ xferbuf = op ( object );
+ } else {
+ /* Default is to not have a data transfer buffer */
+ xferbuf = NULL;
+ }
+
+ intf_put ( xfer_deliver_dest );
+ intf_put ( dest );
+ return xferbuf;
+}
diff --git a/src/include/ipxe/xferbuf.h b/src/include/ipxe/xferbuf.h
index f2f3362..cb0b1a0 100644
--- a/src/include/ipxe/xferbuf.h
+++ b/src/include/ipxe/xferbuf.h
@@ -12,6 +12,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/iobuf.h>
#include <ipxe/uaccess.h>
+#include <ipxe/interface.h>
#include <ipxe/xfer.h>
/** A data transfer buffer */
@@ -97,4 +98,8 @@ extern int xferbuf_deliver ( struct xfer_buffer *xferbuf,
struct io_buffer *iobuf,
struct xfer_metadata *meta );
+extern struct xfer_buffer * xfer_buffer ( struct interface *intf );
+#define xfer_buffer_TYPE( object_type ) \
+ typeof ( struct xfer_buffer * ( object_type ) )
+
#endif /* _IPXE_XFERBUF_H */