2 * NVRAM variable manipulation (common)
4 * Copyright (C) 2012, 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 $
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
, 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
)
64 curr_nvram_hash
= devinfo_hash
;
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. */
75 BCMINITFN(nvram_free
)(void)
78 struct nvram_tuple
*t
, *next
;
81 for (i
= 0; i
< NVRAM_HASH_TABLE_SIZE
; i
++) {
82 for (t
= curr_nvram_hash
[i
]; t
; t
= next
) {
86 curr_nvram_hash
[i
] = NULL
;
90 for (t
= nvram_dead
; t
; t
= next
) {
96 /* Indicate to per-port code that all tuples have been freed */
107 hashval
= 31 *hashval
+ *s
++;
112 /* (Re)initialize the hash table. Should be locked. */
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
;
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 */
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
, '=')))
138 _nvram_set(name
, value
);
142 #if defined(_CFE_) && defined(BCM_DEVINFO)
143 if (curr_nvram_hash
!= nvram_hash
) {
144 /* init devinfo nvram variables */
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
);
170 /* Get the value of an NVRAM variable. Should be locked. */
172 _nvram_get(const char *name
)
175 struct nvram_tuple
*t
;
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
;
192 /* Set the value of an NVRAM variable. Should be locked. */
194 BCMINITFN(_nvram_set
)(const char *name
, const char *value
)
197 struct nvram_tuple
*t
, *u
, **prev
;
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 */
214 /* Move old tuple to the dead table */
217 t
->next
= nvram_dead
;
221 /* Add new tuple to the hash table */
222 u
->next
= curr_nvram_hash
[i
];
223 curr_nvram_hash
[i
] = u
;
228 /* Unset the value of an NVRAM variable. Should be locked. */
230 BCMINITFN(_nvram_unset
)(const char *name
)
233 struct nvram_tuple
*t
, **prev
;
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 */
248 t
->next
= nvram_dead
;
255 /* Get all NVRAM variables. Should be locked. */
257 _nvram_getall(char *buf
, int count
)
260 struct nvram_tuple
*t
;
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;
278 /* Regenerate NVRAM. Should be locked. */
280 BCMINITFN(_nvram_commit
)(struct nvram_header
*header
)
282 char *init
, *config
, *refresh
, *ncdl
;
285 struct nvram_tuple
*t
;
286 char *nvram_space_str
= _nvram_get("nvram_space");
287 unsigned long nvram_space
= DEF_NVRAM_SPACE
;
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;
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
)
325 ptr
+= sprintf(ptr
, "%s=%s", t
->name
, t
->value
) + 1;
329 /* End with a double NUL */
333 header
->len
= ROUNDUP(ptr
- (char *) header
, 4);
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
;
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
);
363 /* Free hash table. Should be locked. */
365 BCMINITFN(_nvram_exit
)(void)
369 #if defined(_CFE_) && defined(BCM_DEVINFO)
370 /* free up devinfo hash table, etc */
371 _nvram_hash_select(1);
373 _nvram_hash_select(0);
374 #endif /* _CFE_ && BCM_DEVINFO */
377 /* returns the CRC8 of the nvram */
379 BCMINITFN(nvram_calc_crc
)(struct nvram_header
*nvh
)
381 struct nvram_header tmp
;
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
,
393 /* Continue CRC8 over data bytes */
394 crc
= hndcrc8((uint8
*) &nvh
[1], nvh
->len
- sizeof(struct nvram_header
), crc
);
399 #if defined(_CFE_) && defined(BCM_DEVINFO)
400 /* sync nvram hash table with devinfo nvram hash table */
402 BCMINITFN(_nvram_hash_sync
)(void)
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
);
418 #endif /* _CFE_ && BCM_DEVINFO */