summaryrefslogtreecommitdiffstats
path: root/src/core/buffer.c
diff options
context:
space:
mode:
authorMichael Brown2005-05-19 02:17:48 +0200
committerMichael Brown2005-05-19 02:17:48 +0200
commita2915ad06d2582444779ca5c9de211073c6ddb29 (patch)
treee2835682f2ec2fafa8d00da420f32c318adffc96 /src/core/buffer.c
parentMore doxygen docs (diff)
downloadipxe-a2915ad06d2582444779ca5c9de211073c6ddb29.tar.gz
ipxe-a2915ad06d2582444779ca5c9de211073c6ddb29.tar.xz
ipxe-a2915ad06d2582444779ca5c9de211073c6ddb29.zip
Added preliminary doxygen documentation
Diffstat (limited to 'src/core/buffer.c')
-rw-r--r--src/core/buffer.c133
1 files changed, 117 insertions, 16 deletions
diff --git a/src/core/buffer.c b/src/core/buffer.c
index b300d4ec..e2b94db7 100644
--- a/src/core/buffer.c
+++ b/src/core/buffer.c
@@ -1,6 +1,10 @@
-/*
- * Routines for filling a buffer with data received piecemeal, where
- * the size of the data is not necessarily known in advance.
+/** @file
+ *
+ * Buffers for loading files.
+ *
+ * This file provides routines for filling a buffer with data received
+ * piecemeal, where the size of the data is not necessarily known in
+ * advance.
*
* Some protocols do not provide a mechanism for us to know the size
* of the file before we happen to receive a particular block
@@ -14,6 +18,40 @@
* which assemble a file into a single contiguous block. The whole
* block is then passed to the image loader.
*
+ * Example usage:
+ *
+ * @code
+ *
+ * struct buffer my_buffer;
+ * void *data;
+ * off_t offset;
+ * size_t len;
+ *
+ * // We have an area of memory [buf_start,buf_end) into which we want
+ * // to load a file, where buf_start and buf_end are physical addresses.
+ * buffer->start = buf_start;
+ * buffer->end = buf_end;
+ * init_buffer ( &buffer );
+ * ...
+ * while ( get_file_block ( ... ) ) {
+ * // Downloaded block is stored in [data,data+len), and represents
+ * // the portion of the file at offsets [offset,offset+len)
+ * if ( ! fill_buffer ( &buffer, data, offset, len ) ) {
+ * // An error occurred
+ * return 0;
+ * }
+ * ...
+ * }
+ * ...
+ * // The whole file is now present at [buf_start,buf_start+filesize),
+ * // where buf_start is a physical address. The struct buffer can simply
+ * // be discarded; there is no done_buffer() call.
+ *
+ * @endcode
+ *
+ */
+
+/** @package Internals
*
* Note that the rather convoluted way of manipulating the buffer
* descriptors (using copy_{to,from}_phys rather than straightforward
@@ -28,8 +66,16 @@
#include "io.h"
#include "buffer.h"
-/*
- * Initialise a buffer
+/**
+ * Initialise a buffer.
+ *
+ * @v buffer The buffer to be initialised
+ * @ret None
+ * @err None
+ *
+ * Set @c buffer->start and @c buffer->end before calling init_buffer().
+ * init_buffer() will initialise the buffer to the state of being
+ * empty.
*
*/
void init_buffer ( struct buffer *buffer ) {
@@ -42,8 +88,27 @@ void init_buffer ( struct buffer *buffer ) {
DBG ( "BUFFER [%x,%x) initialised\n", buffer->start, buffer->end );
}
-/*
- * Split a free block
+/**
+ * Split a free block.
+ *
+ * @v desc A descriptor for the free block
+ * @v block Start address of the block
+ * @v split Address at which to split the block
+ * @ret None
+ * @err None
+ *
+ * Split a free block into two separate free blocks. If the split
+ * point lies outside the block, no action is taken; this is not an
+ * error.
+ *
+ * @b NOTE: It is the reponsibility of the caller to ensure that there
+ * is enough room in each of the two portions for a free block
+ * descriptor (a @c struct @c buffer_free_block, except in the case of
+ * a tail block which requires only a one byte descriptor). If the
+ * caller fails to do this, data corruption will occur.
+ *
+ * In practice, this means that the granularity at which blocks are
+ * split must be at least @c sizeof(struct @c buffer_free_block).
*
*/
static void split_free_block ( struct buffer_free_block *desc,
@@ -71,8 +136,16 @@ static void split_free_block ( struct buffer_free_block *desc,
copy_to_phys ( block, desc, sizeof ( *desc ) );
}
-/*
- * Mark a free block as used
+/**
+ * Mark a free block as used.
+ *
+ * @v buffer The buffer containing the block
+ * @v desc A descriptor for the free block
+ * @v prev_block Address of the previous block
+ * @ret None
+ * @err None
+ *
+ * Marks a free block as used, i.e. removes it from the free list.
*
*/
static inline void unfree_block ( struct buffer *buffer,
@@ -99,15 +172,42 @@ static inline void unfree_block ( struct buffer *buffer,
copy_to_phys ( prev_block, &prev_desc, sizeof ( prev_desc ) );
}
-/*
- * Write data into a buffer
+/**
+ * Write data into a buffer.
+ *
+ * @v buffer The buffer into which to write the data
+ * @v data The data to be written
+ * @v offset Offset within the buffer at which to write the data
+ * @v len Length of data to be written
+ * @ret True Data was successfully written
+ * @ret False Data was not written
+ * @err ENOMEM Buffer is too small to contain the data
+ *
+ * Writes a block of data into the buffer. The block need not be
+ * aligned to any particular boundary, or be of any particular size,
+ * and it may overlap blocks already in the buffer (i.e. duplicate
+ * calls to fill_buffer() are explicitly permitted).
+ *
+ * @c buffer->fill will be updated to indicate the fill level of the
+ * buffer, i.e. the offset to the first gap within the buffer. If the
+ * filesize is known (e.g. as with the SLAM protocol), you can test
+ * for end-of-file by checking for @c buffer->fill==filesize. If the
+ * filesize is not known, but there is a well-defined end-of-file test
+ * (e.g. as with the TFTP protocol), you can read @c buffer->fill to
+ * determine the final filesize. If blocks are known to be delivered
+ * in a strictly sequential order with no packet loss or duplication,
+ * then you can pass in @c offset==buffer->fill.
+ *
+ * @b NOTE: It is the caller's responsibility to ensure that the
+ * boundaries between data blocks are more than @c sizeof(struct @c
+ * buffer_free_block) apart. If this condition is not satisfied, data
+ * corruption will occur. (See split_free_block() for details.)
*
- * It is the caller's responsibility to ensure that the boundaries
- * between data blocks are more than sizeof(struct buffer_free_block)
- * apart. If this condition is not satisfied, data corruption will
- * occur.
+ * @att In practice this is not a problem. Callers of fill_buffer()
+ * will be download protocols such as TFTP, and very few protocols
+ * have a block size smaller than @c sizeof(struct @c
+ * buffer_free_block).
*
- * Returns 1 for success, 0 for failure (e.g. buffer too small).
*/
int fill_buffer ( struct buffer *buffer, const void *data,
off_t offset, size_t len ) {
@@ -125,6 +225,7 @@ int fill_buffer ( struct buffer *buffer, const void *data,
if ( data_end > buffer->end ) {
DBG ( "BUFFER [%x,%x) too small for data!\n",
buffer->start, buffer->end );
+ errno = ENOMEM;
return 0;
}