2 * NVRAM variable manipulation (common)
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
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.
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 gmo $
26 #include <bcmendian.h>
30 extern struct nvram_tuple
*_nvram_realloc(struct nvram_tuple
*t
, const char *name
,
32 extern void _nvram_free(struct nvram_tuple
*t
);
33 extern int _nvram_read(void *buf
);
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
);
41 void _nvram_exit(void);
42 uint8
nvram_calc_crc(struct nvram_header
*nvh
);
44 static struct nvram_tuple
*BCMINITDATA(nvram_hash
)[257];
45 static struct nvram_tuple
*nvram_dead
;
47 /* Free all tuples. Should be locked. */
49 BCMINITFN(nvram_free
)(void)
52 struct nvram_tuple
*t
, *next
;
55 for (i
= 0; i
< ARRAYSIZE(nvram_hash
); i
++) {
56 for (t
= nvram_hash
[i
]; t
; t
= next
) {
64 for (t
= nvram_dead
; t
; t
= next
) {
70 /* Indicate to per-port code that all tuples have been freed */
81 hashval
= 31 *hashval
+ *s
++;
86 //#define NVRAM2HANDLER 1
89 * separte nvram into two part, for those bootloader can't handle large nvram well models
98 struct nvram_header
*find_next_header(struct nvram_header
*header
, char *ptr
)
100 struct nvram_header
*hdr
;
103 hdrptr
= (char *)header
;
106 if((ptr
-hdrptr
)%16) {
107 hdrptr
= ptr
+ (16-(ptr
-hdrptr
)%16);
113 hdr
= (struct nvram_header
*)hdrptr
;
115 printk("header : %x %x %x\n", header
, ptr
, hdr
);
120 /* (Re)initialize the hash table. Should be locked. */
122 BCMINITFN(nvram_rehash
)(struct nvram_header
*header
)
124 char buf
[] = "0xXXXXXXXX", *name
, *value
, *end
, *eq
;
125 struct nvram_header
*hdrptr
;
126 /* (Re)initialize hash table */
131 /* Parse and set "name=value\0 ... \0\0" */
132 name
= (char *) &hdrptr
[1];
133 end
= (char *) hdrptr
+ NVRAM_SPACE
- 2;
134 end
[0] = end
[1] = '\0';
137 for (; *name
; name
= value
+ strlen(value
) + 1) {
138 if (!(eq
= strchr(name
, '=')))
142 _nvram_set(name
, value
);
146 printk("rehash %x %x\n", header
, name
);
151 if(j
%16==0) printk("\n");
152 printk("%x ", *(name
-32+j
));
156 hdrptr
= find_next_header(header
, name
+2);
159 printk("magic: %x\n", hdrptr
->magic
);
161 if(hdrptr
&& hdrptr
->magic
==NVRAM_MAGIC
) {
162 name
= (char *)&hdrptr
[1];
166 /* Set special SDRAM parameters */
167 if (!_nvram_get("sdram_init")) {
168 sprintf(buf
, "0x%04X", (uint16
)(header
->crc_ver_init
>> 16));
169 _nvram_set("sdram_init", buf
);
171 if (!_nvram_get("sdram_config")) {
172 sprintf(buf
, "0x%04X", (uint16
)(header
->config_refresh
& 0xffff));
173 _nvram_set("sdram_config", buf
);
175 if (!_nvram_get("sdram_refresh")) {
176 sprintf(buf
, "0x%04X", (uint16
)((header
->config_refresh
>> 16) & 0xffff));
177 _nvram_set("sdram_refresh", buf
);
179 if (!_nvram_get("sdram_ncdl")) {
180 sprintf(buf
, "0x%08X", header
->config_ncdl
);
181 _nvram_set("sdram_ncdl", buf
);
187 /* (Re)initialize the hash table. Should be locked. */
189 BCMINITFN(nvram_rehash
)(struct nvram_header
*header
)
191 char buf
[] = "0xXXXXXXXX", *name
, *value
, *end
, *eq
;
193 /* (Re)initialize hash table */
196 /* Parse and set "name=value\0 ... \0\0" */
197 name
= (char *) &header
[1];
198 end
= (char *) header
+ NVRAM_SPACE
- 2;
199 end
[0] = end
[1] = '\0';
200 for (; *name
; name
= value
+ strlen(value
) + 1) {
201 if (!(eq
= strchr(name
, '=')))
205 _nvram_set(name
, value
);
209 /* Set special SDRAM parameters */
210 if (!_nvram_get("sdram_init")) {
211 sprintf(buf
, "0x%04X", (uint16
)(header
->crc_ver_init
>> 16));
212 _nvram_set("sdram_init", buf
);
214 if (!_nvram_get("sdram_config")) {
215 sprintf(buf
, "0x%04X", (uint16
)(header
->config_refresh
& 0xffff));
216 _nvram_set("sdram_config", buf
);
218 if (!_nvram_get("sdram_refresh")) {
219 sprintf(buf
, "0x%04X", (uint16
)((header
->config_refresh
>> 16) & 0xffff));
220 _nvram_set("sdram_refresh", buf
);
222 if (!_nvram_get("sdram_ncdl")) {
223 sprintf(buf
, "0x%08X", header
->config_ncdl
);
224 _nvram_set("sdram_ncdl", buf
);
231 /* Get the value of an NVRAM variable. Should be locked. */
233 _nvram_get(const char *name
)
236 struct nvram_tuple
*t
;
243 i
= hash(name
) % ARRAYSIZE(nvram_hash
);
245 /* Find the associated tuple in the hash table */
246 for (t
= nvram_hash
[i
]; t
&& strcmp(t
->name
, name
); t
= t
->next
);
248 value
= t
? t
->value
: NULL
;
253 /* Set the value of an NVRAM variable. Should be locked. */
255 BCMINITFN(_nvram_set
)(const char *name
, const char *value
)
258 struct nvram_tuple
*t
, *u
, **prev
;
261 i
= hash(name
) % ARRAYSIZE(nvram_hash
);
263 /* Find the associated tuple in the hash table */
264 for (prev
= &nvram_hash
[i
], t
= *prev
; t
&& strcmp(t
->name
, name
);
265 prev
= &t
->next
, t
= *prev
);
267 /* (Re)allocate tuple */
268 if (!(u
= _nvram_realloc(t
, name
, value
)))
269 return -12; /* -ENOMEM */
271 /* Value reallocated */
275 /* Move old tuple to the dead table */
278 t
->next
= nvram_dead
;
282 /* Add new tuple to the hash table */
283 u
->next
= nvram_hash
[i
];
289 /* Unset the value of an NVRAM variable. Should be locked. */
291 BCMINITFN(_nvram_unset
)(const char *name
)
294 struct nvram_tuple
*t
, **prev
;
300 i
= hash(name
) % ARRAYSIZE(nvram_hash
);
302 /* Find the associated tuple in the hash table */
303 for (prev
= &nvram_hash
[i
], t
= *prev
; t
&& strcmp(t
->name
, name
);
304 prev
= &t
->next
, t
= *prev
);
306 /* Move it to the dead table */
309 t
->next
= nvram_dead
;
316 /* Get all NVRAM variables. Should be locked. */
318 _nvram_getall(char *buf
, int count
)
321 struct nvram_tuple
*t
;
326 /* Write name=value\0 ... \0\0 */
327 for (i
= 0; i
< ARRAYSIZE(nvram_hash
); i
++) {
328 for (t
= nvram_hash
[i
]; t
; t
= t
->next
) {
329 if ((count
- len
) > (strlen(t
->name
) + 1 + strlen(t
->value
) + 1))
330 len
+= sprintf(buf
+ len
, "%s=%s", t
->name
, t
->value
) + 1;
340 /* Regenerate NVRAM. Should be locked. */
342 BCMINITFN(_nvram_commit
)(struct nvram_header
*header
)
344 char *init
, *config
, *refresh
, *ncdl
;
347 struct nvram_tuple
*t
;
348 struct nvram_header
*hdrptr
;
352 bzero(hdrptr
, NVRAM_SPACE
);
353 /* Leave space for a double NUL at the end */
354 end
= (char *) header
+ NVRAM_SPACE
- 2;
360 /* Regenerate header */
361 hdrptr
->magic
= NVRAM_MAGIC
;
362 hdrptr
->crc_ver_init
= (NVRAM_VERSION
<< 8);
363 if (!(init
= _nvram_get("sdram_init")) ||
364 !(config
= _nvram_get("sdram_config")) ||
365 !(refresh
= _nvram_get("sdram_refresh")) ||
366 !(ncdl
= _nvram_get("sdram_ncdl"))) {
367 hdrptr
->crc_ver_init
|= SDRAM_INIT
<< 16;
368 hdrptr
->config_refresh
= SDRAM_CONFIG
;
369 hdrptr
->config_refresh
|= SDRAM_REFRESH
<< 16;
370 hdrptr
->config_ncdl
= 0;
372 hdrptr
->crc_ver_init
|= (bcm_strtoul(init
, NULL
, 0) & 0xffff) << 16;
373 hdrptr
->config_refresh
= bcm_strtoul(config
, NULL
, 0) & 0xffff;
374 hdrptr
->config_refresh
|= (bcm_strtoul(refresh
, NULL
, 0) & 0xffff) << 16;
375 hdrptr
->config_ncdl
= bcm_strtoul(ncdl
, NULL
, 0);
378 /* Clear data area */
379 ptr
= (char *) hdrptr
+ sizeof(struct nvram_header
);
381 /* Write out all tuples */
382 for (i
= starti
; i
< ARRAYSIZE(nvram_hash
); i
++) {
383 for (t
= nvram_hash
[i
]; t
; t
= t
->next
) {
384 if ((ptr
+ strlen(t
->name
) + 1 + strlen(t
->value
) + 1) > end
)
386 ptr
+= sprintf(ptr
, "%s=%s", t
->name
, t
->value
) + 1;
388 if(starti
==0 && (ptr
-(char *)hdrptr
)>(NVRAM_SPACE
/2)) {
390 printk("next hash table: %x\n", i
);
395 /* End with a double NUL */
399 hdrptr
->len
= ROUNDUP(ptr
- (char *) hdrptr
, 4);
402 hdrptr
->crc_ver_init
|= nvram_calc_crc(hdrptr
);
404 printk("commit %x %x %d\n", header
, ptr
, i
);
405 hdrptr
= find_next_header(header
, ptr
);
407 if(hdrptr
&& i
<ARRAYSIZE(nvram_hash
)) {
411 /* Reinitialize hash table */
412 return nvram_rehash(header
);
415 /* Regenerate NVRAM. Should be locked. */
417 BCMINITFN(_nvram_commit
)(struct nvram_header
*header
)
419 char *init
, *config
, *refresh
, *ncdl
;
422 struct nvram_tuple
*t
;
424 /* Regenerate header */
425 header
->magic
= NVRAM_MAGIC
;
426 header
->crc_ver_init
= (NVRAM_VERSION
<< 8);
427 if (!(init
= _nvram_get("sdram_init")) ||
428 !(config
= _nvram_get("sdram_config")) ||
429 !(refresh
= _nvram_get("sdram_refresh")) ||
430 !(ncdl
= _nvram_get("sdram_ncdl"))) {
431 header
->crc_ver_init
|= SDRAM_INIT
<< 16;
432 header
->config_refresh
= SDRAM_CONFIG
;
433 header
->config_refresh
|= SDRAM_REFRESH
<< 16;
434 header
->config_ncdl
= 0;
436 header
->crc_ver_init
|= (bcm_strtoul(init
, NULL
, 0) & 0xffff) << 16;
437 header
->config_refresh
= bcm_strtoul(config
, NULL
, 0) & 0xffff;
438 header
->config_refresh
|= (bcm_strtoul(refresh
, NULL
, 0) & 0xffff) << 16;
439 header
->config_ncdl
= bcm_strtoul(ncdl
, NULL
, 0);
442 /* Clear data area */
443 ptr
= (char *) header
+ sizeof(struct nvram_header
);
444 bzero(ptr
, NVRAM_SPACE
- sizeof(struct nvram_header
));
446 /* Leave space for a double NUL at the end */
447 end
= (char *) header
+ NVRAM_SPACE
- 2;
449 /* Write out all tuples */
450 for (i
= 0; i
< ARRAYSIZE(nvram_hash
); i
++) {
451 for (t
= nvram_hash
[i
]; t
; t
= t
->next
) {
452 if ((ptr
+ strlen(t
->name
) + 1 + strlen(t
->value
) + 1) > end
)
454 ptr
+= sprintf(ptr
, "%s=%s", t
->name
, t
->value
) + 1;
458 /* End with a double NUL */
462 header
->len
= ROUNDUP(ptr
- (char *) header
, 4);
465 header
->crc_ver_init
|= nvram_calc_crc(header
);
467 /* Reinitialize hash table */
468 return nvram_rehash(header
);
472 /* Initialize hash table. Should be locked. */
474 BCMINITFN(_nvram_init
)(void *sih
)
476 struct nvram_header
*header
;
480 if (!(header
= (struct nvram_header
*) MALLOC(si_osh(sih
), NVRAM_SPACE
))) {
481 printf("nvram_init: out of memory\n");
482 return -12; /* -ENOMEM */
484 printf("_nvram_init: allocat header: %lu, size= %lu\n", header
, NVRAM_SPACE
);
485 if ((ret
= _nvram_read(header
)) == 0 &&
486 header
->magic
== NVRAM_MAGIC
)
487 nvram_rehash(header
);
489 MFREE(si_osh(sih
), header
, NVRAM_SPACE
);
493 /* Free hash table. Should be locked. */
495 BCMINITFN(_nvram_exit
)(void)
500 /* returns the CRC8 of the nvram */
502 BCMINITFN(nvram_calc_crc
)(struct nvram_header
*nvh
)
504 struct nvram_header tmp
;
507 /* Little-endian CRC8 over the last 11 bytes of the header */
508 tmp
.crc_ver_init
= htol32((nvh
->crc_ver_init
& NVRAM_CRC_VER_MASK
));
509 tmp
.config_refresh
= htol32(nvh
->config_refresh
);
510 tmp
.config_ncdl
= htol32(nvh
->config_ncdl
);
512 crc
= hndcrc8((uint8
*) &tmp
+ NVRAM_CRC_START_POSITION
,
513 sizeof(struct nvram_header
) - NVRAM_CRC_START_POSITION
,
516 /* Continue CRC8 over data bytes */
517 crc
= hndcrc8((uint8
*) &nvh
[1], nvh
->len
- sizeof(struct nvram_header
), crc
);