|
@@ -29,34 +29,35 @@
|
29
|
29
|
*/
|
30
|
30
|
|
31
|
31
|
/**
|
32
|
|
- * Calculate total length of non-volatile stored options
|
|
32
|
+ * Calculate checksum over non-volatile stored options
|
33
|
33
|
*
|
34
|
34
|
* @v nvo Non-volatile options block
|
35
|
|
- * @ret total_len Total length of all fragments
|
|
35
|
+ * @ret sum Checksum
|
36
|
36
|
*/
|
37
|
|
-static size_t nvo_total_len ( struct nvo_block *nvo ) {
|
38
|
|
- struct nvo_fragment *fragment = nvo->fragments;
|
39
|
|
- size_t total_len = 0;
|
|
37
|
+static unsigned int nvo_checksum ( struct nvo_block *nvo ) {
|
|
38
|
+ uint8_t *data = nvo->options->data;
|
|
39
|
+ uint8_t sum = 0;
|
|
40
|
+ unsigned int i;
|
40
|
41
|
|
41
|
|
- for ( ; fragment->len ; fragment++ ) {
|
42
|
|
- total_len += fragment->len;
|
|
42
|
+ for ( i = 0 ; i < nvo->total_len ; i++ ) {
|
|
43
|
+ sum += *(data++);
|
43
|
44
|
}
|
44
|
|
-
|
45
|
|
- return total_len;
|
|
45
|
+ return sum;
|
46
|
46
|
}
|
47
|
47
|
|
48
|
48
|
/**
|
49
|
|
- * Read non-volatile stored options from non-volatile storage device
|
|
49
|
+ * Load non-volatile stored options from non-volatile storage device
|
50
|
50
|
*
|
51
|
51
|
* @v nvo Non-volatile options block
|
52
|
52
|
* @ret rc Return status code
|
53
|
53
|
*/
|
54
|
|
-static int nvo_read ( struct nvo_block *nvo ) {
|
55
|
|
- struct nvo_fragment *fragment = nvo->fragments;
|
|
54
|
+static int nvo_load ( struct nvo_block *nvo ) {
|
56
|
55
|
void *data = nvo->options->data;
|
|
56
|
+ struct nvo_fragment *fragment;
|
57
|
57
|
int rc;
|
58
|
58
|
|
59
|
|
- for ( ; fragment->len ; fragment++ ) {
|
|
59
|
+ /* Read data a fragment at a time */
|
|
60
|
+ for ( fragment = nvo->fragments ; fragment->len ; fragment++ ) {
|
60
|
61
|
if ( ( rc = nvs_read ( nvo->nvs, fragment->address,
|
61
|
62
|
data, fragment->len ) ) != 0 ) {
|
62
|
63
|
DBG ( "NVO %p could not read %zd bytes at %#04x\n",
|
|
@@ -69,32 +70,55 @@ static int nvo_read ( struct nvo_block *nvo ) {
|
69
|
70
|
return 0;
|
70
|
71
|
}
|
71
|
72
|
|
|
73
|
+/**
|
|
74
|
+ * Save non-volatile stored options back to non-volatile storage device
|
|
75
|
+ *
|
|
76
|
+ * @v nvo Non-volatile options block
|
|
77
|
+ * @ret rc Return status code
|
|
78
|
+ */
|
|
79
|
+int nvo_save ( struct nvo_block *nvo ) {
|
|
80
|
+ void *data = nvo->options->data;
|
|
81
|
+ uint8_t *checksum = ( data + nvo->total_len - 1 );
|
|
82
|
+ struct nvo_fragment *fragment;
|
|
83
|
+ int rc;
|
|
84
|
+
|
|
85
|
+ /* Recalculate checksum */
|
|
86
|
+ checksum -= nvo_checksum ( nvo );
|
|
87
|
+
|
|
88
|
+ /* Write data a fragment at a time */
|
|
89
|
+ for ( fragment = nvo->fragments ; fragment->len ; fragment++ ) {
|
|
90
|
+ if ( ( rc = nvs_write ( nvo->nvs, fragment->address,
|
|
91
|
+ data, fragment->len ) ) != 0 ) {
|
|
92
|
+ DBG ( "NVO %p could not write %zd bytes at %#04x\n",
|
|
93
|
+ nvo, fragment->len, fragment->address );
|
|
94
|
+ return rc;
|
|
95
|
+ }
|
|
96
|
+ data += fragment->len;
|
|
97
|
+ }
|
|
98
|
+
|
|
99
|
+ return 0;
|
|
100
|
+}
|
|
101
|
+
|
72
|
102
|
/**
|
73
|
103
|
* Parse stored options
|
74
|
104
|
*
|
75
|
105
|
* @v nvo Non-volatile options block
|
76
|
|
- * @v total_len Total length of options data
|
77
|
106
|
*
|
78
|
107
|
* Verifies that the options data is valid, and configures the DHCP
|
79
|
108
|
* options block. If the data is not valid, it is replaced with an
|
80
|
109
|
* empty options block.
|
81
|
110
|
*/
|
82
|
|
-static void nvo_init_dhcp ( struct nvo_block *nvo, size_t total_len ) {
|
|
111
|
+static void nvo_init_dhcp ( struct nvo_block *nvo ) {
|
83
|
112
|
struct dhcp_option_block *options = nvo->options;
|
84
|
113
|
struct dhcp_option *option;
|
85
|
|
- uint8_t sum;
|
86
|
|
- unsigned int i;
|
87
|
114
|
|
88
|
115
|
/* Steal one byte for the checksum */
|
89
|
|
- options->max_len = ( total_len - 1 );
|
|
116
|
+ options->max_len = ( nvo->total_len - 1 );
|
90
|
117
|
|
91
|
118
|
/* Verify checksum over whole block */
|
92
|
|
- for ( sum = 0, i = 0 ; i < total_len ; i++ ) {
|
93
|
|
- sum += * ( ( uint8_t * ) ( options->data + i ) );
|
94
|
|
- }
|
95
|
|
- if ( sum != 0 ) {
|
|
119
|
+ if ( nvo_checksum ( nvo ) != 0 ) {
|
96
|
120
|
DBG ( "NVO %p has bad checksum %02x; assuming empty\n",
|
97
|
|
- nvo, sum );
|
|
121
|
+ nvo, nvo_checksum ( nvo ) );
|
98
|
122
|
goto empty;
|
99
|
123
|
}
|
100
|
124
|
|
|
@@ -134,24 +158,28 @@ static void nvo_init_dhcp ( struct nvo_block *nvo, size_t total_len ) {
|
134
|
158
|
* @ret rc Return status code
|
135
|
159
|
*/
|
136
|
160
|
int nvo_register ( struct nvo_block *nvo ) {
|
137
|
|
- size_t total_len;
|
|
161
|
+ struct nvo_fragment *fragment = nvo->fragments;
|
138
|
162
|
int rc;
|
139
|
163
|
|
|
164
|
+ /* Calculate total length of all fragments */
|
|
165
|
+ nvo->total_len = 0;
|
|
166
|
+ for ( fragment = nvo->fragments ; fragment->len ; fragment++ ) {
|
|
167
|
+ nvo->total_len += fragment->len;
|
|
168
|
+ }
|
|
169
|
+
|
140
|
170
|
/* Allocate memory for options and read in from NVS */
|
141
|
|
- total_len = nvo_total_len ( nvo );
|
142
|
|
- nvo->options = alloc_dhcp_options ( total_len );
|
|
171
|
+ nvo->options = alloc_dhcp_options ( nvo->total_len );
|
143
|
172
|
if ( ! nvo->options ) {
|
144
|
173
|
DBG ( "NVO %p could not allocate %zd bytes\n",
|
145
|
|
- nvo, total_len );
|
|
174
|
+ nvo, nvo->total_len );
|
146
|
175
|
rc = -ENOMEM;
|
147
|
176
|
goto err;
|
148
|
177
|
}
|
149
|
|
-
|
150
|
|
- if ( ( rc = nvo_read ( nvo ) ) != 0 )
|
|
178
|
+ if ( ( rc = nvo_load ( nvo ) ) != 0 )
|
151
|
179
|
goto err;
|
152
|
180
|
|
153
|
181
|
/* Verify and register options */
|
154
|
|
- nvo_init_dhcp ( nvo, total_len );
|
|
182
|
+ nvo_init_dhcp ( nvo );
|
155
|
183
|
register_dhcp_options ( nvo->options );
|
156
|
184
|
|
157
|
185
|
return 0;
|