summaryrefslogtreecommitdiffstats
path: root/src/drivers/nvs
diff options
context:
space:
mode:
authorMichael Brown2006-12-04 23:06:54 +0100
committerMichael Brown2006-12-04 23:06:54 +0100
commit052ef6dc5a4ed2444aeda90af7b97c0a92e98e54 (patch)
treefc797c253eae123786d32f7eec1136e3d8868392 /src/drivers/nvs
parentAdded nvo_save() (diff)
downloadipxe-052ef6dc5a4ed2444aeda90af7b97c0a92e98e54.tar.gz
ipxe-052ef6dc5a4ed2444aeda90af7b97c0a92e98e54.tar.xz
ipxe-052ef6dc5a4ed2444aeda90af7b97c0a92e98e54.zip
Added nvs_write(). This shares a lot of code in common with nvs_read();
this can probably be optimised down quite a lot.
Diffstat (limited to 'src/drivers/nvs')
-rw-r--r--src/drivers/nvs/nvs.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/drivers/nvs/nvs.c b/src/drivers/nvs/nvs.c
index 3f22a0ee..a566cdfd 100644
--- a/src/drivers/nvs/nvs.c
+++ b/src/drivers/nvs/nvs.c
@@ -68,3 +68,46 @@ int nvs_read ( struct nvs_device *nvs, unsigned int address,
return 0;
}
+
+/**
+ * Write to non-volatile storage device
+ *
+ * @v nvs NVS device
+ * @v address Address to which to write
+ * @v data Data buffer
+ * @v len Length of data buffer
+ * @ret rc Return status code
+ */
+int nvs_write ( struct nvs_device *nvs, unsigned int address,
+ const void *data, size_t 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->write ( 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;
+}