Add libevent package
[openwrt.git] / openwrt / package / linux / kernel-source / arch / mips / brcm-boards / bcm947xx / nvram.c
1 /*
2 * NVRAM variable manipulation (common)
3 *
4 * Copyright 2004, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 * $Id$
13 */
14
15 #include <typedefs.h>
16 #include <osl.h>
17 #include <bcmendian.h>
18 #include <bcmnvram.h>
19 #include <bcmutils.h>
20 #include <sbsdram.h>
21
22 extern struct nvram_tuple * _nvram_realloc(struct nvram_tuple *t, const char *name, const char *value);
23 extern void _nvram_free(struct nvram_tuple *t);
24 extern int _nvram_read(void *buf);
25
26 char * _nvram_get(const char *name);
27 int _nvram_set(const char *name, const char *value);
28 int _nvram_unset(const char *name);
29 int _nvram_getall(char *buf, int count);
30 int _nvram_commit(struct nvram_header *header);
31 int _nvram_init(void);
32 void _nvram_exit(void);
33
34 static struct nvram_tuple * nvram_hash[257];
35 static struct nvram_tuple * nvram_dead;
36
37 /* Free all tuples. Should be locked. */
38 static void
39 nvram_free(void)
40 {
41 uint i;
42 struct nvram_tuple *t, *next;
43
44 /* Free hash table */
45 for (i = 0; i < ARRAYSIZE(nvram_hash); i++) {
46 for (t = nvram_hash[i]; t; t = next) {
47 next = t->next;
48 _nvram_free(t);
49 }
50 nvram_hash[i] = NULL;
51 }
52
53 /* Free dead table */
54 for (t = nvram_dead; t; t = next) {
55 next = t->next;
56 _nvram_free(t);
57 }
58 nvram_dead = NULL;
59
60 /* Indicate to per-port code that all tuples have been freed */
61 _nvram_free(NULL);
62 }
63
64 /* String hash */
65 static INLINE uint
66 hash(const char *s)
67 {
68 uint hash = 0;
69
70 while (*s)
71 hash = 31 * hash + *s++;
72
73 return hash;
74 }
75
76 /* (Re)initialize the hash table. Should be locked. */
77 static int
78 nvram_rehash(struct nvram_header *header)
79 {
80 char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq;
81
82 /* (Re)initialize hash table */
83 nvram_free();
84
85 /* Parse and set "name=value\0 ... \0\0" */
86 name = (char *) &header[1];
87 end = (char *) header + NVRAM_SPACE - 2;
88 end[0] = end[1] = '\0';
89 for (; *name; name = value + strlen(value) + 1) {
90 if (!(eq = strchr(name, '=')))
91 break;
92 *eq = '\0';
93 value = eq + 1;
94 _nvram_set(name, value);
95 *eq = '=';
96 }
97
98 /* Set special SDRAM parameters */
99 if (!_nvram_get("sdram_init")) {
100 sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16));
101 _nvram_set("sdram_init", buf);
102 }
103 if (!_nvram_get("sdram_config")) {
104 sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff));
105 _nvram_set("sdram_config", buf);
106 }
107 if (!_nvram_get("sdram_refresh")) {
108 sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff));
109 _nvram_set("sdram_refresh", buf);
110 }
111 if (!_nvram_get("sdram_ncdl")) {
112 sprintf(buf, "0x%08X", header->config_ncdl);
113 _nvram_set("sdram_ncdl", buf);
114 }
115
116 return 0;
117 }
118
119 /* Get the value of an NVRAM variable. Should be locked. */
120 char *
121 _nvram_get(const char *name)
122 {
123 uint i;
124 struct nvram_tuple *t;
125 char *value;
126
127 if (!name)
128 return NULL;
129
130 /* Hash the name */
131 i = hash(name) % ARRAYSIZE(nvram_hash);
132
133 /* Find the associated tuple in the hash table */
134 for (t = nvram_hash[i]; t && strcmp(t->name, name); t = t->next);
135
136 value = t ? t->value : NULL;
137
138 return value;
139 }
140
141 /* Get the value of an NVRAM variable. Should be locked. */
142 int
143 _nvram_set(const char *name, const char *value)
144 {
145 uint i;
146 struct nvram_tuple *t, *u, **prev;
147
148 /* Hash the name */
149 i = hash(name) % ARRAYSIZE(nvram_hash);
150
151 /* Find the associated tuple in the hash table */
152 for (prev = &nvram_hash[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev);
153
154 /* (Re)allocate tuple */
155 if (!(u = _nvram_realloc(t, name, value)))
156 return -12; /* -ENOMEM */
157
158 /* Value reallocated */
159 if (t && t == u)
160 return 0;
161
162 /* Move old tuple to the dead table */
163 if (t) {
164 *prev = t->next;
165 t->next = nvram_dead;
166 nvram_dead = t;
167 }
168
169 /* Add new tuple to the hash table */
170 u->next = nvram_hash[i];
171 nvram_hash[i] = u;
172
173 return 0;
174 }
175
176 /* Unset the value of an NVRAM variable. Should be locked. */
177 int
178 _nvram_unset(const char *name)
179 {
180 uint i;
181 struct nvram_tuple *t, **prev;
182
183 if (!name)
184 return 0;
185
186 /* Hash the name */
187 i = hash(name) % ARRAYSIZE(nvram_hash);
188
189 /* Find the associated tuple in the hash table */
190 for (prev = &nvram_hash[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev);
191
192 /* Move it to the dead table */
193 if (t) {
194 *prev = t->next;
195 t->next = nvram_dead;
196 nvram_dead = t;
197 }
198
199 return 0;
200 }
201
202 /* Get all NVRAM variables. Should be locked. */
203 int
204 _nvram_getall(char *buf, int count)
205 {
206 uint i;
207 struct nvram_tuple *t;
208 int len = 0;
209
210 bzero(buf, count);
211
212 /* Write name=value\0 ... \0\0 */
213 for (i = 0; i < ARRAYSIZE(nvram_hash); i++) {
214 for (t = nvram_hash[i]; t; t = t->next) {
215 if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1))
216 len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1;
217 else
218 break;
219 }
220 }
221
222 return 0;
223 }
224
225 /* Regenerate NVRAM. Should be locked. */
226 int
227 _nvram_commit(struct nvram_header *header)
228 {
229 char *init, *config, *refresh, *ncdl;
230 char *ptr, *end;
231 int i;
232 struct nvram_tuple *t;
233 struct nvram_header tmp;
234 uint8 crc;
235
236 /* Regenerate header */
237 header->magic = NVRAM_MAGIC;
238 header->crc_ver_init = (NVRAM_VERSION << 8);
239 if (!(init = _nvram_get("sdram_init")) ||
240 !(config = _nvram_get("sdram_config")) ||
241 !(refresh = _nvram_get("sdram_refresh")) ||
242 !(ncdl = _nvram_get("sdram_ncdl"))) {
243 header->crc_ver_init |= SDRAM_INIT << 16;
244 header->config_refresh = SDRAM_CONFIG;
245 header->config_refresh |= SDRAM_REFRESH << 16;
246 header->config_ncdl = 0;
247 } else {
248 header->crc_ver_init |= (bcm_strtoul(init, NULL, 0) & 0xffff) << 16;
249 header->config_refresh = bcm_strtoul(config, NULL, 0) & 0xffff;
250 header->config_refresh |= (bcm_strtoul(refresh, NULL, 0) & 0xffff) << 16;
251 header->config_ncdl = bcm_strtoul(ncdl, NULL, 0);
252 }
253
254 /* Clear data area */
255 ptr = (char *) header + sizeof(struct nvram_header);
256 bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header));
257
258 /* Leave space for a double NUL at the end */
259 end = (char *) header + NVRAM_SPACE - 2;
260
261 /* Write out all tuples */
262 for (i = 0; i < ARRAYSIZE(nvram_hash); i++) {
263 for (t = nvram_hash[i]; t; t = t->next) {
264 if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end)
265 break;
266 ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1;
267 }
268 }
269
270 /* End with a double NUL */
271 ptr += 2;
272
273 /* Set new length */
274 header->len = ROUNDUP(ptr - (char *) header, 4);
275
276 /* Little-endian CRC8 over the last 11 bytes of the header */
277 tmp.crc_ver_init = htol32(header->crc_ver_init);
278 tmp.config_refresh = htol32(header->config_refresh);
279 tmp.config_ncdl = htol32(header->config_ncdl);
280 crc = crc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, CRC8_INIT_VALUE);
281
282 /* Continue CRC8 over data bytes */
283 crc = crc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc);
284
285 /* Set new CRC8 */
286 header->crc_ver_init |= crc;
287
288 /* Reinitialize hash table */
289 return nvram_rehash(header);
290 }
291
292 /* Initialize hash table. Should be locked. */
293 int
294 _nvram_init(void)
295 {
296 struct nvram_header *header;
297 int ret;
298
299 if (!(header = (struct nvram_header *) MALLOC(NVRAM_SPACE))) {
300 printf("nvram_init: out of memory\n");
301 return -12; /* -ENOMEM */
302 }
303
304 if ((ret = _nvram_read(header)) == 0 &&
305 header->magic == NVRAM_MAGIC)
306 nvram_rehash(header);
307
308 MFREE(header, NVRAM_SPACE);
309 return ret;
310 }
311
312 /* Free hash table. Should be locked. */
313 void
314 _nvram_exit(void)
315 {
316 nvram_free();
317 }
This page took 0.055218 seconds and 5 git commands to generate.