[xferbuf] Simplify and generalise data transfer buffers

Since all data transfer buffer contents are now accessible via direct
pointer dereferences, remove the unnecessary abstractions for read and
write operations and create two new data transfer buffer types: a
fixed-size buffer, and a void buffer that records its size but can
never receive non-zero lengths of data.  These replace the custom data
buffer types currently implemented for EFI PXE TFTP downloads and for
block device translations.

A new operation xferbuf_detach() is required to take ownership of the
data accumulated in the data transfer buffer, since we no longer rely
on the existence of an independently owned external data pointer for
data transfer buffers allocated via umalloc().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-04-29 09:16:41 +01:00
parent 43fc516298
commit 837b77293b
7 changed files with 130 additions and 245 deletions

View File

@@ -25,8 +25,6 @@ struct block_translator {
/** Data transfer buffer */
struct xfer_buffer xferbuf;
/** Data buffer */
void *buffer;
/** Block size */
size_t blksize;
};

View File

@@ -35,41 +35,19 @@ struct xfer_buffer_operations {
* @ret rc Return status code
*/
int ( * realloc ) ( struct xfer_buffer *xferbuf, size_t len );
/** Write data to buffer
*
* @v xferbuf Data transfer buffer
* @v offset Starting offset
* @v data Data to write
* @v len Length of data
*
* This call is simply a wrapper for the appropriate
* memcpy()-like operation: the caller is responsible for
* ensuring that the write does not exceed the buffer length.
*/
void ( * write ) ( struct xfer_buffer *xferbuf, size_t offset,
const void *data, size_t len );
/** Read data from buffer
*
* @v xferbuf Data transfer buffer
* @v offset Starting offset
* @v data Data to read
* @v len Length of data
*
* This call is simply a wrapper for the appropriate
* memcpy()-like operation: the caller is responsible for
* ensuring that the read does not exceed the buffer length.
*/
void ( * read ) ( struct xfer_buffer *xferbuf, size_t offset,
void *data, size_t len );
};
extern struct xfer_buffer_operations xferbuf_malloc_operations;
extern struct xfer_buffer_operations xferbuf_umalloc_operations;
extern struct xfer_buffer_operations xferbuf_fixed_operations;
extern struct xfer_buffer_operations xferbuf_void_operations;
/**
* Initialise malloc()-based data transfer buffer
*
* @v xferbuf Data transfer buffer
*
* Data will be automatically allocated using malloc().
*/
static inline __attribute__ (( always_inline )) void
xferbuf_malloc_init ( struct xfer_buffer *xferbuf ) {
@@ -80,14 +58,45 @@ xferbuf_malloc_init ( struct xfer_buffer *xferbuf ) {
* Initialise umalloc()-based data transfer buffer
*
* @v xferbuf Data transfer buffer
* @v data User pointer
*
* Data will be automatically allocated using umalloc() (and may
* therefore alter the system memory map).
*/
static inline __attribute__ (( always_inline )) void
xferbuf_umalloc_init ( struct xfer_buffer *xferbuf, void **data ) {
xferbuf->data = data;
xferbuf_umalloc_init ( struct xfer_buffer *xferbuf ) {
xferbuf->op = &xferbuf_umalloc_operations;
}
/**
* Initialise fixed-size data transfer buffer
*
* @v xferbuf Data transfer buffer
* @v data Data buffer
* @v len Length of data buffer
*
* Data will be never be automatically allocated.
*/
static inline __attribute__ (( always_inline )) void
xferbuf_fixed_init ( struct xfer_buffer *xferbuf, void *data, size_t len ) {
xferbuf->data = data;
xferbuf->len = len;
xferbuf->op = &xferbuf_fixed_operations;
}
/**
* Initialise void data transfer buffer
*
* @v xferbuf Data transfer buffer
*
* No data will be allocated, but the length will be recorded. This
* can be used to capture xfer_seek() results.
*/
static inline __attribute__ (( always_inline )) void
xferbuf_void_init ( struct xfer_buffer *xferbuf ) {
xferbuf->op = &xferbuf_void_operations;
}
extern void xferbuf_detach ( struct xfer_buffer *xferbuf );
extern void xferbuf_free ( struct xfer_buffer *xferbuf );
extern int xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset,
const void *data, size_t len );