2 * NVRAM variable manipulation (common)
4 * Copyright 2004, Broadcom Corporation
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.
17 #include <bcmendian.h>
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);
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);
34 static struct nvram_tuple * nvram_hash[257];
35 static struct nvram_tuple * nvram_dead;
37 /* Free all tuples. Should be locked. */
42 struct nvram_tuple *t, *next;
45 for (i = 0; i < ARRAYSIZE(nvram_hash); i++) {
46 for (t = nvram_hash[i]; t; t = next) {
54 for (t = nvram_dead; t; t = next) {
60 /* Indicate to per-port code that all tuples have been freed */
71 hash = 31 * hash + *s++;
76 /* (Re)initialize the hash table. Should be locked. */
78 nvram_rehash(struct nvram_header *header)
80 char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq;
82 /* (Re)initialize hash table */
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, '=')))
94 _nvram_set(name, value);
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);
103 if (!_nvram_get("sdram_config")) {
104 sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff));
105 _nvram_set("sdram_config", buf);
107 if (!_nvram_get("sdram_refresh")) {
108 sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff));
109 _nvram_set("sdram_refresh", buf);
111 if (!_nvram_get("sdram_ncdl")) {
112 sprintf(buf, "0x%08X", header->config_ncdl);
113 _nvram_set("sdram_ncdl", buf);
119 /* Get the value of an NVRAM variable. Should be locked. */
121 _nvram_get(const char *name)
124 struct nvram_tuple *t;
131 i = hash(name) % ARRAYSIZE(nvram_hash);
133 /* Find the associated tuple in the hash table */
134 for (t = nvram_hash[i]; t && strcmp(t->name, name); t = t->next);
136 value = t ? t->value : NULL;
141 /* Get the value of an NVRAM variable. Should be locked. */
143 _nvram_set(const char *name, const char *value)
146 struct nvram_tuple *t, *u, **prev;
149 i = hash(name) % ARRAYSIZE(nvram_hash);
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);
154 /* (Re)allocate tuple */
155 if (!(u = _nvram_realloc(t, name, value)))
156 return -12; /* -ENOMEM */
158 /* Value reallocated */
162 /* Move old tuple to the dead table */
165 t->next = nvram_dead;
169 /* Add new tuple to the hash table */
170 u->next = nvram_hash[i];
176 /* Unset the value of an NVRAM variable. Should be locked. */
178 _nvram_unset(const char *name)
181 struct nvram_tuple *t, **prev;
187 i = hash(name) % ARRAYSIZE(nvram_hash);
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);
192 /* Move it to the dead table */
195 t->next = nvram_dead;
202 /* Get all NVRAM variables. Should be locked. */
204 _nvram_getall(char *buf, int count)
207 struct nvram_tuple *t;
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;
225 /* Regenerate NVRAM. Should be locked. */
227 _nvram_commit(struct nvram_header *header)
229 char *init, *config, *refresh, *ncdl;
232 struct nvram_tuple *t;
233 struct nvram_header tmp;
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;
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);
254 /* Clear data area */
255 ptr = (char *) header + sizeof(struct nvram_header);
256 bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header));
258 /* Leave space for a double NUL at the end */
259 end = (char *) header + NVRAM_SPACE - 2;
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)
266 ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1;
270 /* End with a double NUL */
274 header->len = ROUNDUP(ptr - (char *) header, 4);
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);
282 /* Continue CRC8 over data bytes */
283 crc = crc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc);
286 header->crc_ver_init |= crc;
288 /* Reinitialize hash table */
289 return nvram_rehash(header);
292 /* Initialize hash table. Should be locked. */
296 struct nvram_header *header;
299 if (!(header = (struct nvram_header *) MALLOC(NVRAM_SPACE))) {
300 printf("nvram_init: out of memory\n");
301 return -12; /* -ENOMEM */
304 if ((ret = _nvram_read(header)) == 0 &&
305 header->magic == NVRAM_MAGIC)
306 nvram_rehash(header);
308 MFREE(header, NVRAM_SPACE);
312 /* Free hash table. Should be locked. */