GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / shared / nvram.c
blobadb25a9653b87746848eb9a31b9bb93c769c3512
1 /*
2 * NVRAM variable manipulation (common)
4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: nvram.c 241182 2011-02-17 21:50:03Z $
21 #include <typedefs.h>
22 #include <bcmdefs.h>
23 #include <osl.h>
24 #include <bcmutils.h>
25 #include <siutils.h>
26 #include <bcmendian.h>
27 #include <bcmnvram.h>
28 #include <sbsdram.h>
30 extern struct nvram_tuple *_nvram_realloc(struct nvram_tuple *t, const char *name,
31 const char *value);
32 extern void _nvram_free(struct nvram_tuple *t);
33 extern int _nvram_read(void *buf, int idx);
35 char *_nvram_get(const char *name);
36 int _nvram_set(const char *name, const char *value);
37 int _nvram_unset(const char *name);
38 int _nvram_getall(char *buf, int count);
39 int _nvram_commit(struct nvram_header *header);
40 int _nvram_init(void *sih, int idx);
41 void _nvram_exit(void);
42 uint8 nvram_calc_crc(struct nvram_header *nvh);
44 #define NVRAM_HASH_TABLE_SIZE 257
46 static struct nvram_tuple *BCMINITDATA(nvram_hash)[NVRAM_HASH_TABLE_SIZE];
47 static struct nvram_tuple *nvram_dead;
49 /* curr_nvram_hash is used to reference for either nvram_hash or */
50 /* nvram_hash array */
51 /* default to nvram_hash */
52 struct nvram_tuple **BCMINITDATA(curr_nvram_hash) = nvram_hash;
55 #if defined(_CFE_) && defined(BCM_DEVINFO)
56 void _nvram_hash_select(int idx);
57 int _nvram_hash_sync(void);
59 static struct nvram_tuple *BCMINITDATA(devinfo_hash)[NVRAM_HASH_TABLE_SIZE];
61 void _nvram_hash_select(int idx)
63 if (idx == 1) {
64 curr_nvram_hash = devinfo_hash;
65 return;
68 /* alll others, default to nvram_hash */
69 curr_nvram_hash = nvram_hash;
71 #endif /* _CFE_ && BCM_DEVINFO */
73 /* Free all tuples. Should be locked. */
74 static void
75 BCMINITFN(nvram_free)(void)
77 uint i;
78 struct nvram_tuple *t, *next;
80 /* Free hash table */
81 for (i = 0; i < NVRAM_HASH_TABLE_SIZE; i++) {
82 for (t = curr_nvram_hash[i]; t; t = next) {
83 next = t->next;
84 _nvram_free(t);
86 curr_nvram_hash[i] = NULL;
89 /* Free dead table */
90 for (t = nvram_dead; t; t = next) {
91 next = t->next;
92 _nvram_free(t);
94 nvram_dead = NULL;
96 /* Indicate to per-port code that all tuples have been freed */
97 _nvram_free(NULL);
100 /* String hash */
101 static INLINE uint
102 hash(const char *s)
104 uint hashval = 0;
106 while (*s)
107 hashval = 31 *hashval + *s++;
109 return hashval;
112 /* (Re)initialize the hash table. Should be locked. */
113 static int
114 BCMINITFN(nvram_rehash)(struct nvram_header *header)
116 char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq;
117 char *nvram_space_str = _nvram_get("nvram_space");
118 unsigned long nvram_space = DEF_NVRAM_SPACE;
120 if (nvram_space_str)
121 nvram_space = bcm_strtoul(nvram_space_str, NULL, 0);
123 if (nvram_space < DEF_NVRAM_SPACE)
124 nvram_space = DEF_NVRAM_SPACE;
126 /* (Re)initialize hash table */
127 nvram_free();
129 /* Parse and set "name=value\0 ... \0\0" */
130 name = (char *) &header[1];
131 end = (char *) header + nvram_space - 2;
132 end[0] = end[1] = '\0';
133 for (; *name; name = value + strlen(value) + 1) {
134 if (!(eq = strchr(name, '=')))
135 break;
136 *eq = '\0';
137 value = eq + 1;
138 _nvram_set(name, value);
139 *eq = '=';
142 #if defined(_CFE_) && defined(BCM_DEVINFO)
143 if (curr_nvram_hash != nvram_hash) {
144 /* init devinfo nvram variables */
145 return 0;
147 #endif /* _CFE_ && BCM_DEVINFO */
149 /* Set special SDRAM parameters */
150 if (!_nvram_get("sdram_init")) {
151 sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16));
152 _nvram_set("sdram_init", buf);
154 if (!_nvram_get("sdram_config")) {
155 sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff));
156 _nvram_set("sdram_config", buf);
158 if (!_nvram_get("sdram_refresh")) {
159 sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff));
160 _nvram_set("sdram_refresh", buf);
162 if (!_nvram_get("sdram_ncdl")) {
163 sprintf(buf, "0x%08X", header->config_ncdl);
164 _nvram_set("sdram_ncdl", buf);
167 return 0;
170 /* Get the value of an NVRAM variable. Should be locked. */
171 char *
172 _nvram_get(const char *name)
174 uint i;
175 struct nvram_tuple *t;
176 char *value;
178 if (!name)
179 return NULL;
181 /* Hash the name */
182 i = hash(name) % NVRAM_HASH_TABLE_SIZE;
184 /* Find the associated tuple in the hash table */
185 for (t = curr_nvram_hash[i]; t && strcmp(t->name, name); t = t->next);
187 value = t ? t->value : NULL;
189 return value;
192 /* Set the value of an NVRAM variable. Should be locked. */
194 BCMINITFN(_nvram_set)(const char *name, const char *value)
196 uint i;
197 struct nvram_tuple *t, *u, **prev;
199 /* Hash the name */
200 i = hash(name) % NVRAM_HASH_TABLE_SIZE;
202 /* Find the associated tuple in the hash table */
203 for (prev = &curr_nvram_hash[i], t = *prev; t && strcmp(t->name, name);
204 prev = &t->next, t = *prev);
206 /* (Re)allocate tuple */
207 if (!(u = _nvram_realloc(t, name, value)))
208 return -12; /* -ENOMEM */
210 /* Value reallocated */
211 if (t && t == u)
212 return 0;
214 /* Move old tuple to the dead table */
215 if (t) {
216 *prev = t->next;
217 t->next = nvram_dead;
218 nvram_dead = t;
221 /* Add new tuple to the hash table */
222 u->next = curr_nvram_hash[i];
223 curr_nvram_hash[i] = u;
225 return 0;
228 /* Unset the value of an NVRAM variable. Should be locked. */
230 BCMINITFN(_nvram_unset)(const char *name)
232 uint i;
233 struct nvram_tuple *t, **prev;
235 if (!name)
236 return 0;
238 /* Hash the name */
239 i = hash(name) % NVRAM_HASH_TABLE_SIZE;
241 /* Find the associated tuple in the hash table */
242 for (prev = &curr_nvram_hash[i], t = *prev; t && strcmp(t->name, name);
243 prev = &t->next, t = *prev);
245 /* Move it to the dead table */
246 if (t) {
247 *prev = t->next;
248 t->next = nvram_dead;
249 nvram_dead = t;
252 return 0;
255 /* Get all NVRAM variables. Should be locked. */
257 _nvram_getall(char *buf, int count)
259 uint i;
260 struct nvram_tuple *t;
261 int len = 0;
263 bzero(buf, count);
265 /* Write name=value\0 ... \0\0 */
266 for (i = 0; i < NVRAM_HASH_TABLE_SIZE; i++) {
267 for (t = curr_nvram_hash[i]; t; t = t->next) {
268 if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1))
269 len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1;
270 else
271 break;
275 return 0;
278 /* Regenerate NVRAM. Should be locked. */
280 BCMINITFN(_nvram_commit)(struct nvram_header *header)
282 char *init, *config, *refresh, *ncdl;
283 char *ptr, *end;
284 int i;
285 struct nvram_tuple *t;
286 char *nvram_space_str = _nvram_get("nvram_space");
287 unsigned long nvram_space = DEF_NVRAM_SPACE;
289 if (nvram_space_str)
290 nvram_space = bcm_strtoul(nvram_space_str, NULL, 0);
292 if (nvram_space < DEF_NVRAM_SPACE)
293 nvram_space = DEF_NVRAM_SPACE;
295 /* Regenerate header */
296 header->magic = NVRAM_MAGIC;
297 header->crc_ver_init = (NVRAM_VERSION << 8);
298 if (!(init = _nvram_get("sdram_init")) ||
299 !(config = _nvram_get("sdram_config")) ||
300 !(refresh = _nvram_get("sdram_refresh")) ||
301 !(ncdl = _nvram_get("sdram_ncdl"))) {
302 header->crc_ver_init |= SDRAM_INIT << 16;
303 header->config_refresh = SDRAM_CONFIG;
304 header->config_refresh |= SDRAM_REFRESH << 16;
305 header->config_ncdl = 0;
306 } else {
307 header->crc_ver_init |= (bcm_strtoul(init, NULL, 0) & 0xffff) << 16;
308 header->config_refresh = bcm_strtoul(config, NULL, 0) & 0xffff;
309 header->config_refresh |= (bcm_strtoul(refresh, NULL, 0) & 0xffff) << 16;
310 header->config_ncdl = bcm_strtoul(ncdl, NULL, 0);
313 /* Clear data area */
314 ptr = (char *) header + sizeof(struct nvram_header);
315 bzero(ptr, nvram_space - sizeof(struct nvram_header));
317 /* Leave space for a double NUL at the end */
318 end = (char *) header + nvram_space - 2;
320 /* Write out all tuples */
321 for (i = 0; i < NVRAM_HASH_TABLE_SIZE; i++) {
322 for (t = curr_nvram_hash[i]; t; t = t->next) {
323 if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end)
324 break;
325 ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1;
329 /* End with a double NUL */
330 ptr += 2;
332 /* Set new length */
333 header->len = ROUNDUP(ptr - (char *) header, 4);
335 /* Set new CRC8 */
336 header->crc_ver_init |= nvram_calc_crc(header);
338 /* Reinitialize hash table */
339 return nvram_rehash(header);
342 /* Initialize hash table. Should be locked. */
344 BCMINITFN(_nvram_init)(void *sih, int idx)
346 struct nvram_header *header;
347 int ret;
350 if (!(header = (struct nvram_header *) MALLOC(si_osh(sih), MAX_NVRAM_SPACE))) {
351 printf("nvram_init: out of memory\n");
352 return -12; /* -ENOMEM */
355 if ((ret = _nvram_read(header, idx)) == 0 &&
356 header->magic == NVRAM_MAGIC)
357 nvram_rehash(header);
359 MFREE(si_osh(sih), header, MAX_NVRAM_SPACE);
360 return ret;
363 /* Free hash table. Should be locked. */
364 void
365 BCMINITFN(_nvram_exit)(void)
367 nvram_free();
369 #if defined(_CFE_) && defined(BCM_DEVINFO)
370 /* free up devinfo hash table, etc */
371 _nvram_hash_select(1);
372 nvram_free();
373 _nvram_hash_select(0);
374 #endif /* _CFE_ && BCM_DEVINFO */
377 /* returns the CRC8 of the nvram */
378 uint8
379 BCMINITFN(nvram_calc_crc)(struct nvram_header *nvh)
381 struct nvram_header tmp;
382 uint8 crc;
384 /* Little-endian CRC8 over the last 11 bytes of the header */
385 tmp.crc_ver_init = htol32((nvh->crc_ver_init & NVRAM_CRC_VER_MASK));
386 tmp.config_refresh = htol32(nvh->config_refresh);
387 tmp.config_ncdl = htol32(nvh->config_ncdl);
389 crc = hndcrc8((uint8 *) &tmp + NVRAM_CRC_START_POSITION,
390 sizeof(struct nvram_header) - NVRAM_CRC_START_POSITION,
391 CRC8_INIT_VALUE);
393 /* Continue CRC8 over data bytes */
394 crc = hndcrc8((uint8 *) &nvh[1], nvh->len - sizeof(struct nvram_header), crc);
396 return crc;
399 #if defined(_CFE_) && defined(BCM_DEVINFO)
400 /* sync nvram hash table with devinfo nvram hash table */
402 BCMINITFN(_nvram_hash_sync)(void)
404 uint i;
405 struct nvram_tuple *t, *next;
407 /* traverse and _nvram_set() devinfo's entry to default hash table */
408 _nvram_hash_select(0);
409 for (i = 0; i < NVRAM_HASH_TABLE_SIZE; i++) {
410 for (t = devinfo_hash[i]; t; t = next) {
411 _nvram_set(t->name, t->value);
412 next = t->next;
416 return (0);
418 #endif /* _CFE_ && BCM_DEVINFO */