diff options
| author | Simon Rettberg | 2026-01-28 12:53:53 +0100 |
|---|---|---|
| committer | Simon Rettberg | 2026-01-28 12:53:53 +0100 |
| commit | 8e82785c584dc13e20f9229decb95bd17bbe9cd1 (patch) | |
| tree | a8b359e59196be5b2e3862bed189107f4bc9975f /src/core/xferbuf.c | |
| parent | Merge branch 'master' into openslx (diff) | |
| parent | [prefix] Make unlzma.S compatible with 386 class CPUs (diff) | |
| download | ipxe-openslx.tar.gz ipxe-openslx.tar.xz ipxe-openslx.zip | |
Merge branch 'master' into openslxopenslx
Diffstat (limited to 'src/core/xferbuf.c')
| -rw-r--r-- | src/core/xferbuf.c | 127 |
1 files changed, 66 insertions, 61 deletions
diff --git a/src/core/xferbuf.c b/src/core/xferbuf.c index 240118557..ca3baaab5 100644 --- a/src/core/xferbuf.c +++ b/src/core/xferbuf.c @@ -22,6 +22,7 @@ */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); +FILE_SECBOOT ( PERMITTED ); #include <stdlib.h> #include <string.h> @@ -51,6 +52,21 @@ static struct profiler xferbuf_read_profiler __profiler = { .name = "xferbuf.read" }; /** + * Detach data from data transfer buffer + * + * @v xferbuf Data transfer buffer + * + * The caller assumes responsibility for eventually freeing the data + * previously owned by the data transfer buffer. + */ +void xferbuf_detach ( struct xfer_buffer *xferbuf ) { + + xferbuf->data = NULL; + xferbuf->len = 0; + xferbuf->pos = 0; +} + +/** * Free data transfer buffer * * @v xferbuf Data transfer buffer @@ -58,8 +74,7 @@ static struct profiler xferbuf_read_profiler __profiler = void xferbuf_free ( struct xfer_buffer *xferbuf ) { xferbuf->op->realloc ( xferbuf, 0 ); - xferbuf->len = 0; - xferbuf->pos = 0; + xferbuf_detach ( xferbuf ); } /** @@ -109,9 +124,13 @@ int xferbuf_write ( struct xfer_buffer *xferbuf, size_t offset, if ( ( rc = xferbuf_ensure_size ( xferbuf, max_len ) ) != 0 ) return rc; + /* Check that buffer is non-void */ + if ( len && ( ! xferbuf->data ) ) + return -ENOTTY; + /* Copy data to buffer */ profile_start ( &xferbuf_write_profiler ); - xferbuf->op->write ( xferbuf, offset, data, len ); + memcpy ( ( xferbuf->data + offset ), data, len ); profile_stop ( &xferbuf_write_profiler ); return 0; @@ -133,9 +152,13 @@ int xferbuf_read ( struct xfer_buffer *xferbuf, size_t offset, ( len > ( xferbuf->len - offset ) ) ) return -ENOENT; + /* Check that buffer is non-void */ + if ( len && ( ! xferbuf->data ) ) + return -ENOTTY; + /* Copy data from buffer */ profile_start ( &xferbuf_read_profiler ); - xferbuf->op->read ( xferbuf, offset, data, len ); + memcpy ( data, ( xferbuf->data + offset ), len ); profile_stop ( &xferbuf_read_profiler ); return 0; @@ -178,7 +201,7 @@ int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf, } /** - * Reallocate malloc()-based data buffer + * Reallocate malloc()-based data transfer buffer * * @v xferbuf Data transfer buffer * @v len New length (or zero to free buffer) @@ -194,94 +217,76 @@ static int xferbuf_malloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) { return 0; } -/** - * Write data to malloc()-based data buffer - * - * @v xferbuf Data transfer buffer - * @v offset Starting offset - * @v data Data to copy - * @v len Length of data - */ -static void xferbuf_malloc_write ( struct xfer_buffer *xferbuf, size_t offset, - const void *data, size_t len ) { - - memcpy ( ( xferbuf->data + offset ), data, len ); -} - -/** - * Read data from malloc()-based data buffer - * - * @v xferbuf Data transfer buffer - * @v offset Starting offset - * @v data Data to read - * @v len Length of data - */ -static void xferbuf_malloc_read ( struct xfer_buffer *xferbuf, size_t offset, - void *data, size_t len ) { - - memcpy ( data, ( xferbuf->data + offset ), len ); -} - /** malloc()-based data buffer operations */ struct xfer_buffer_operations xferbuf_malloc_operations = { .realloc = xferbuf_malloc_realloc, - .write = xferbuf_malloc_write, - .read = xferbuf_malloc_read, }; /** - * Reallocate umalloc()-based data buffer + * Reallocate umalloc()-based data transfer buffer * * @v xferbuf Data transfer buffer * @v len New length (or zero to free buffer) * @ret rc Return status code */ static int xferbuf_umalloc_realloc ( struct xfer_buffer *xferbuf, size_t len ) { - userptr_t *udata = xferbuf->data; - userptr_t new_udata; + void *new_udata; - new_udata = urealloc ( *udata, len ); + new_udata = urealloc ( xferbuf->data, len ); if ( ! new_udata ) return -ENOSPC; - *udata = new_udata; + xferbuf->data = new_udata; return 0; } +/** umalloc()-based data buffer operations */ +struct xfer_buffer_operations xferbuf_umalloc_operations = { + .realloc = xferbuf_umalloc_realloc, +}; + /** - * Write data to umalloc()-based data buffer + * Reallocate fixed-size data transfer buffer * * @v xferbuf Data transfer buffer - * @v offset Starting offset - * @v data Data to copy - * @v len Length of data + * @v len New length (or zero to free buffer) + * @ret rc Return status code */ -static void xferbuf_umalloc_write ( struct xfer_buffer *xferbuf, size_t offset, - const void *data, size_t len ) { - userptr_t *udata = xferbuf->data; +static int xferbuf_fixed_realloc ( struct xfer_buffer *xferbuf, size_t len ) { + + /* Refuse to allocate extra space */ + if ( len > xferbuf->len ) { + /* Note that EFI relies upon this error mapping to + * EFI_BUFFER_TOO_SMALL. + */ + return -ERANGE; + } - copy_to_user ( *udata, offset, data, len ); + return 0; } +/** Fixed-size data buffer operations */ +struct xfer_buffer_operations xferbuf_fixed_operations = { + .realloc = xferbuf_fixed_realloc, +}; + /** - * Read data from umalloc()-based data buffer + * Reallocate void data transfer buffer * * @v xferbuf Data transfer buffer - * @v offset Starting offset - * @v data Data to read - * @v len Length of data + * @v len New length (or zero to free buffer) + * @ret rc Return status code */ -static void xferbuf_umalloc_read ( struct xfer_buffer *xferbuf, size_t offset, - void *data, size_t len ) { - userptr_t *udata = xferbuf->data; +static int xferbuf_void_realloc ( struct xfer_buffer *xferbuf, + size_t len __unused ) { - copy_from_user ( data, *udata, offset, len ); + /* Succeed without ever allocating data */ + assert ( xferbuf->data == NULL ); + return 0; } -/** umalloc()-based data buffer operations */ -struct xfer_buffer_operations xferbuf_umalloc_operations = { - .realloc = xferbuf_umalloc_realloc, - .write = xferbuf_umalloc_write, - .read = xferbuf_umalloc_read, +/** Void data buffer operations */ +struct xfer_buffer_operations xferbuf_void_operations = { + .realloc = xferbuf_void_realloc, }; /** |
