diff options
author | Michael Brown | 2006-12-04 20:06:07 +0100 |
---|---|---|
committer | Michael Brown | 2006-12-04 20:06:07 +0100 |
commit | 2d8d21fe7416871920c96b53b7d3ae5d02964575 (patch) | |
tree | 99ffe79573045f96ab75593bafc6478bcf05cd22 /src/drivers/nvs | |
parent | Added generic SPI protocol handler with read and write support. (diff) | |
download | ipxe-2d8d21fe7416871920c96b53b7d3ae5d02964575.tar.gz ipxe-2d8d21fe7416871920c96b53b7d3ae5d02964575.tar.xz ipxe-2d8d21fe7416871920c96b53b7d3ae5d02964575.zip |
Added the generic block-splitting code to nvs.c
Diffstat (limited to 'src/drivers/nvs')
-rw-r--r-- | src/drivers/nvs/nvs.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/drivers/nvs/nvs.c b/src/drivers/nvs/nvs.c index 55cd8283..3f22a0ee 100644 --- a/src/drivers/nvs/nvs.c +++ b/src/drivers/nvs/nvs.c @@ -17,6 +17,7 @@ */ #include <stdint.h> +#include <assert.h> #include <gpxe/nvs.h> /** @file @@ -25,7 +26,45 @@ * */ +/** + * Read from non-volatile storage device + * + * @v nvs NVS device + * @v address Address from which to read + * @v data Data buffer + * @v len Length of data buffer + * @ret rc Return status code + */ int nvs_read ( struct nvs_device *nvs, unsigned int address, void *data, size_t len ) { - return nvs->read ( nvs, address, data, len ); + size_t frag_len; + int rc; + + /* We don't even attempt to handle buffer lengths that aren't + * an integral number of words. + */ + assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 ); + + while ( len ) { + + /* Calculate space remaining up to next block boundary */ + frag_len = ( ( nvs->block_size - + ( address & ( nvs->block_size - 1 ) ) ) + << nvs->word_len_log2 ); + + /* Limit to space remaining in buffer */ + if ( frag_len > len ) + frag_len = len; + + /* Read this portion of the buffer from the device */ + if ( ( rc = nvs->read ( nvs, address, data, frag_len ) ) != 0 ) + return rc; + + /* Update parameters */ + data += frag_len; + address += ( frag_len >> nvs->word_len_log2 ); + len -= frag_len; + } + + return 0; } |