|
|
@@ -17,6 +17,7 @@
|
|
17
|
17
|
*/
|
|
18
|
18
|
|
|
19
|
19
|
#include <stdint.h>
|
|
|
20
|
+#include <assert.h>
|
|
20
|
21
|
#include <gpxe/nvs.h>
|
|
21
|
22
|
|
|
22
|
23
|
/** @file
|
|
|
@@ -25,7 +26,45 @@
|
|
25
|
26
|
*
|
|
26
|
27
|
*/
|
|
27
|
28
|
|
|
|
29
|
+/**
|
|
|
30
|
+ * Read from non-volatile storage device
|
|
|
31
|
+ *
|
|
|
32
|
+ * @v nvs NVS device
|
|
|
33
|
+ * @v address Address from which to read
|
|
|
34
|
+ * @v data Data buffer
|
|
|
35
|
+ * @v len Length of data buffer
|
|
|
36
|
+ * @ret rc Return status code
|
|
|
37
|
+ */
|
|
28
|
38
|
int nvs_read ( struct nvs_device *nvs, unsigned int address,
|
|
29
|
39
|
void *data, size_t len ) {
|
|
30
|
|
- return nvs->read ( nvs, address, data, len );
|
|
|
40
|
+ size_t frag_len;
|
|
|
41
|
+ int rc;
|
|
|
42
|
+
|
|
|
43
|
+ /* We don't even attempt to handle buffer lengths that aren't
|
|
|
44
|
+ * an integral number of words.
|
|
|
45
|
+ */
|
|
|
46
|
+ assert ( ( len & ( ( 1 << nvs->word_len_log2 ) - 1 ) ) == 0 );
|
|
|
47
|
+
|
|
|
48
|
+ while ( len ) {
|
|
|
49
|
+
|
|
|
50
|
+ /* Calculate space remaining up to next block boundary */
|
|
|
51
|
+ frag_len = ( ( nvs->block_size -
|
|
|
52
|
+ ( address & ( nvs->block_size - 1 ) ) )
|
|
|
53
|
+ << nvs->word_len_log2 );
|
|
|
54
|
+
|
|
|
55
|
+ /* Limit to space remaining in buffer */
|
|
|
56
|
+ if ( frag_len > len )
|
|
|
57
|
+ frag_len = len;
|
|
|
58
|
+
|
|
|
59
|
+ /* Read this portion of the buffer from the device */
|
|
|
60
|
+ if ( ( rc = nvs->read ( nvs, address, data, frag_len ) ) != 0 )
|
|
|
61
|
+ return rc;
|
|
|
62
|
+
|
|
|
63
|
+ /* Update parameters */
|
|
|
64
|
+ data += frag_len;
|
|
|
65
|
+ address += ( frag_len >> nvs->word_len_log2 );
|
|
|
66
|
+ len -= frag_len;
|
|
|
67
|
+ }
|
|
|
68
|
+
|
|
|
69
|
+ return 0;
|
|
31
|
70
|
}
|