|
@@ -17,6 +17,8 @@
|
17
|
17
|
*/
|
18
|
18
|
|
19
|
19
|
#include <stdint.h>
|
|
20
|
+#include <string.h>
|
|
21
|
+#include <errno.h>
|
20
|
22
|
#include <assert.h>
|
21
|
23
|
#include <gpxe/nvs.h>
|
22
|
24
|
|
|
@@ -69,6 +71,34 @@ int nvs_read ( struct nvs_device *nvs, unsigned int address,
|
69
|
71
|
return 0;
|
70
|
72
|
}
|
71
|
73
|
|
|
74
|
+/**
|
|
75
|
+ * Verify content of non-volatile storage device
|
|
76
|
+ *
|
|
77
|
+ * @v nvs NVS device
|
|
78
|
+ * @v address Address from which to read
|
|
79
|
+ * @v data Data to compare against
|
|
80
|
+ * @v len Length of data buffer
|
|
81
|
+ * @ret rc Return status code
|
|
82
|
+ */
|
|
83
|
+static int nvs_verify ( struct nvs_device *nvs, unsigned int address,
|
|
84
|
+ const void *data, size_t len ) {
|
|
85
|
+ uint8_t read_data[len];
|
|
86
|
+ int rc;
|
|
87
|
+
|
|
88
|
+ /* Read data into temporary buffer */
|
|
89
|
+ if ( ( rc = nvs_read ( nvs, address, read_data, len ) ) != 0 )
|
|
90
|
+ return rc;
|
|
91
|
+
|
|
92
|
+ /* Compare data */
|
|
93
|
+ if ( memcmp ( data, read_data, len ) != 0 ) {
|
|
94
|
+ DBG ( "NVS %p verification failed at %#04x+%d\n",
|
|
95
|
+ nvs, address, len );
|
|
96
|
+ return -EINVAL;
|
|
97
|
+ }
|
|
98
|
+
|
|
99
|
+ return 0;
|
|
100
|
+}
|
|
101
|
+
|
72
|
102
|
/**
|
73
|
103
|
* Write to non-volatile storage device
|
74
|
104
|
*
|
|
@@ -99,10 +129,14 @@ int nvs_write ( struct nvs_device *nvs, unsigned int address,
|
99
|
129
|
if ( frag_len > len )
|
100
|
130
|
frag_len = len;
|
101
|
131
|
|
102
|
|
- /* Read this portion of the buffer from the device */
|
|
132
|
+ /* Write this portion of the buffer to the device */
|
103
|
133
|
if ( ( rc = nvs->write ( nvs, address, data, frag_len ) ) != 0)
|
104
|
134
|
return rc;
|
105
|
135
|
|
|
136
|
+ /* Read back and verify data */
|
|
137
|
+ if ( ( rc = nvs_verify ( nvs, address, data, frag_len ) ) != 0)
|
|
138
|
+ return rc;
|
|
139
|
+
|
106
|
140
|
/* Update parameters */
|
107
|
141
|
data += frag_len;
|
108
|
142
|
address += ( frag_len >> nvs->word_len_log2 );
|