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.
16 #include <bcmendian.h>
20 extern struct nvram_tuple * BCMINIT(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value);
21 extern void BCMINIT(_nvram_free)(struct nvram_tuple *t);
22 extern int BCMINIT(_nvram_read)(void *buf);
24 char * BCMINIT(_nvram_get)(const char *name);
25 int BCMINIT(_nvram_set)(const char *name, const char *value);
26 int BCMINIT(_nvram_unset)(const char *name);
27 int BCMINIT(_nvram_getall)(char *buf, int count);
28 int BCMINIT(_nvram_commit)(struct nvram_header *header);
29 int BCMINIT(_nvram_init)(void);
30 void BCMINIT(_nvram_exit)(void);
32 static struct nvram_tuple * BCMINITDATA(nvram_hash)[257];
33 static struct nvram_tuple * nvram_dead;
35 /* Free all tuples. Should be locked. */
37 BCMINITFN(nvram_free)(void)
40 struct nvram_tuple *t, *next;
43 for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
44 for (t = BCMINIT(nvram_hash)[i]; t; t = next) {
46 BCMINIT(_nvram_free)(t);
48 BCMINIT(nvram_hash)[i] = NULL;
52 for (t = nvram_dead; t; t = next) {
54 BCMINIT(_nvram_free)(t);
58 /* Indicate to per-port code that all tuples have been freed */
59 BCMINIT(_nvram_free)(NULL);
69 hash = 31 * hash + *s++;
74 /* (Re)initialize the hash table. Should be locked. */
76 BCMINITFN(nvram_rehash)(struct nvram_header *header)
78 char buf[] = "0xXXXXXXXX", *name, *value, *end, *eq;
80 /* (Re)initialize hash table */
81 BCMINIT(nvram_free)();
83 /* Parse and set "name=value\0 ... \0\0" */
84 name = (char *) &header[1];
85 end = (char *) header + NVRAM_SPACE - 2;
86 end[0] = end[1] = '\0';
87 for (; *name; name = value + strlen(value) + 1) {
88 if (!(eq = strchr(name, '=')))
92 BCMINIT(_nvram_set)(name, value);
96 /* Set special SDRAM parameters */
97 if (!BCMINIT(_nvram_get)("sdram_init")) {
98 sprintf(buf, "0x%04X", (uint16)(header->crc_ver_init >> 16));
99 BCMINIT(_nvram_set)("sdram_init", buf);
101 if (!BCMINIT(_nvram_get)("sdram_config")) {
102 sprintf(buf, "0x%04X", (uint16)(header->config_refresh & 0xffff));
103 BCMINIT(_nvram_set)("sdram_config", buf);
105 if (!BCMINIT(_nvram_get)("sdram_refresh")) {
106 sprintf(buf, "0x%04X", (uint16)((header->config_refresh >> 16) & 0xffff));
107 BCMINIT(_nvram_set)("sdram_refresh", buf);
109 if (!BCMINIT(_nvram_get)("sdram_ncdl")) {
110 sprintf(buf, "0x%08X", header->config_ncdl);
111 BCMINIT(_nvram_set)("sdram_ncdl", buf);
117 /* Get the value of an NVRAM variable. Should be locked. */
119 BCMINITFN(_nvram_get)(const char *name)
122 struct nvram_tuple *t;
129 i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
131 /* Find the associated tuple in the hash table */
132 for (t = BCMINIT(nvram_hash)[i]; t && strcmp(t->name, name); t = t->next);
134 value = t ? t->value : NULL;
139 /* Get the value of an NVRAM variable. Should be locked. */
141 BCMINITFN(_nvram_set)(const char *name, const char *value)
144 struct nvram_tuple *t, *u, **prev;
147 i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
149 /* Find the associated tuple in the hash table */
150 for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev);
152 /* (Re)allocate tuple */
153 if (!(u = BCMINIT(_nvram_realloc)(t, name, value)))
154 return -12; /* -ENOMEM */
156 /* Value reallocated */
160 /* Move old tuple to the dead table */
163 t->next = nvram_dead;
167 /* Add new tuple to the hash table */
168 u->next = BCMINIT(nvram_hash)[i];
169 BCMINIT(nvram_hash)[i] = u;
174 /* Unset the value of an NVRAM variable. Should be locked. */
176 BCMINITFN(_nvram_unset)(const char *name)
179 struct nvram_tuple *t, **prev;
185 i = hash(name) % ARRAYSIZE(BCMINIT(nvram_hash));
187 /* Find the associated tuple in the hash table */
188 for (prev = &BCMINIT(nvram_hash)[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev);
190 /* Move it to the dead table */
193 t->next = nvram_dead;
200 /* Get all NVRAM variables. Should be locked. */
202 BCMINITFN(_nvram_getall)(char *buf, int count)
205 struct nvram_tuple *t;
210 /* Write name=value\0 ... \0\0 */
211 for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
212 for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) {
213 if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1))
214 len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1;
223 /* Regenerate NVRAM. Should be locked. */
225 BCMINITFN(_nvram_commit)(struct nvram_header *header)
227 char *init, *config, *refresh, *ncdl;
230 struct nvram_tuple *t;
231 struct nvram_header tmp;
234 /* Regenerate header */
235 header->magic = NVRAM_MAGIC;
236 header->crc_ver_init = (NVRAM_VERSION << 8);
237 if (!(init = BCMINIT(_nvram_get)("sdram_init")) ||
238 !(config = BCMINIT(_nvram_get)("sdram_config")) ||
239 !(refresh = BCMINIT(_nvram_get)("sdram_refresh")) ||
240 !(ncdl = BCMINIT(_nvram_get)("sdram_ncdl"))) {
241 header->crc_ver_init |= SDRAM_INIT << 16;
242 header->config_refresh = SDRAM_CONFIG;
243 header->config_refresh |= SDRAM_REFRESH << 16;
244 header->config_ncdl = 0;
246 header->crc_ver_init |= (simple_strtoul(init, NULL, 0) & 0xffff) << 16;
247 header->config_refresh = simple_strtoul(config, NULL, 0) & 0xffff;
248 header->config_refresh |= (simple_strtoul(refresh, NULL, 0) & 0xffff) << 16;
249 header->config_ncdl = simple_strtoul(ncdl, NULL, 0);
252 /* Clear data area */
253 ptr = (char *) header + sizeof(struct nvram_header);
254 bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header));
256 /* Leave space for a double NUL at the end */
257 end = (char *) header + NVRAM_SPACE - 2;
259 /* Write out all tuples */
260 for (i = 0; i < ARRAYSIZE(BCMINIT(nvram_hash)); i++) {
261 for (t = BCMINIT(nvram_hash)[i]; t; t = t->next) {
262 if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end)
264 ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1;
268 /* End with a double NUL */
272 header->len = ROUNDUP(ptr - (char *) header, 4);
274 /* Little-endian CRC8 over the last 11 bytes of the header */
275 tmp.crc_ver_init = htol32(header->crc_ver_init);
276 tmp.config_refresh = htol32(header->config_refresh);
277 tmp.config_ncdl = htol32(header->config_ncdl);
278 crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, 0xff);
280 /* Continue CRC8 over data bytes */
281 crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc);
284 header->crc_ver_init |= crc;
286 /* Reinitialize hash table */
287 return BCMINIT(nvram_rehash)(header);
290 /* Initialize hash table. Should be locked. */
292 BCMINITFN(_nvram_init)(void)
294 struct nvram_header *header;
297 if (!(header = (struct nvram_header *) kmalloc(NVRAM_SPACE, GFP_ATOMIC))) {
298 return -12; /* -ENOMEM */
301 if ((ret = BCMINIT(_nvram_read)(header)) == 0 &&
302 header->magic == NVRAM_MAGIC)
303 BCMINIT(nvram_rehash)(header);
309 /* Free hash table. Should be locked. */
311 BCMINITFN(_nvram_exit)(void)
313 BCMINIT(nvram_free)();
317 * Search the name=value vars for a specific one and return its value.
318 * Returns NULL if not found.
321 getvar(char *vars, const char *name)
328 /* first look in vars[] */
329 for (s = vars; s && *s;) {
331 if ((memcmp(s, name, len) == 0) && (s[len] == '='))
338 /* then query nvram */
339 return (nvram_get(name));
343 * Search the vars for a specific one and return its value as
344 * an integer. Returns 0 if not found.
347 getintvar(char *vars, const char *name)
351 if ((val = getvar(vars, name)) == NULL)
354 return (simple_strtoul(val, NULL, 0));