GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / shared / nvram_ro.c
blob5f68bb29f6a3c57951d9573244807a5a47d7f71c
1 /*
2 * Read-only support for NVRAM on flash and otp.
4 * Copyright (C) 2012, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
8 * the contents of this file may not be disclosed to third parties, copied
9 * or duplicated in any form, in whole or in part, without the prior
10 * written permission of Broadcom Corporation.
12 * $Id: nvram_ro.c 290190 2011-10-17 18:13:26Z $
15 #include <typedefs.h>
16 #include <bcmdefs.h>
17 #include <osl.h>
18 #include <bcmutils.h>
19 #include <siutils.h>
20 #include <bcmendian.h>
21 #include <bcmnvram.h>
22 #include <sbchipc.h>
23 #include <bcmsrom.h>
24 #include <bcmotp.h>
25 #include <bcmdevs.h>
26 #include <sflash.h>
27 #include <hndsoc.h>
29 #ifdef BCMDBG_ERR
30 #define NVR_MSG(x) printf x
31 #else
32 #define NVR_MSG(x)
33 #endif /* BCMDBG_ERR */
35 typedef struct _vars {
36 struct _vars *next;
37 int bufsz; /* allocated size */
38 int size; /* actual vars size */
39 char *vars;
40 } vars_t;
42 #define VARS_T_OH sizeof(vars_t)
44 static vars_t *vars = NULL;
46 #if !defined(DONGLEBUILD) && !defined(BCM_BOOTLOADER)
47 #define NVRAM_FILE 1
48 #endif
50 #ifdef NVRAM_FILE
51 static int nvram_file_init(void* sih);
52 static int initvars_file(si_t *sih, osl_t *osh, char **nvramp, int *nvraml);
53 #endif
55 static char *findvar(char *vars_arg, char *lim, const char *name);
56 extern void nvram_get_global_vars(char **varlst, uint *varsz);
58 #if defined(FLASH)
59 /* copy flash to ram */
60 static void
61 BCMINITFN(get_flash_nvram)(si_t *sih, struct nvram_header *nvh)
63 osl_t *osh;
64 uint nvs, bufsz;
65 vars_t *new;
67 osh = si_osh(sih);
69 nvs = R_REG(osh, &nvh->len) - sizeof(struct nvram_header);
70 bufsz = nvs + VARS_T_OH;
72 if ((new = (vars_t *)MALLOC(osh, bufsz)) == NULL) {
73 NVR_MSG(("Out of memory for flash vars\n"));
74 return;
76 new->vars = (char *)new + VARS_T_OH;
78 new->bufsz = bufsz;
79 new->size = nvs;
80 new->next = vars;
81 vars = new;
83 #ifdef BCMJTAG
84 if (BUSTYPE(sih->bustype) == JTAG_BUS) {
85 uint32 *s, *d;
86 uint sz = nvs;
88 s = (uint32 *)(&nvh[1]);
89 d = (uint32 *)new->vars;
91 ASSERT(ISALIGNED((uintptr)s, sizeof(uint32)));
92 ASSERT(ISALIGNED((uintptr)d, sizeof(uint32)));
94 while (sz >= sizeof(uint32)) {
95 *d++ = ltoh32(R_REG(osh, s++));
96 sz -= sizeof(uint32);
98 if (sz) {
99 union {
100 uint32 w;
101 char b[sizeof(uint32)];
102 } data;
103 uint i;
104 char *dst = (char *)d;
106 data.w = ltoh32(R_REG(osh, s));
107 for (i = 0; i < sz; i++)
108 *dst++ = data.b[i];
110 } else
111 #endif /* BCMJTAG */
112 bcopy((char *)(&nvh[1]), new->vars, nvs);
114 NVR_MSG(("%s: flash nvram @ %p, copied %d bytes to %p\n", __FUNCTION__,
115 nvh, nvs, new->vars));
117 #endif /* FLASH */
119 #if defined(BCMUSBDEV) || defined(BCMHOSTVARS)
120 #if defined(BCMHOSTVARS)
121 extern char *_vars;
122 extern uint _varsz;
123 #endif
124 #ifndef CONFIG_XIP
125 extern uint8 embedded_nvram[];
126 #endif
127 #endif
130 BCMATTACHFN(nvram_init)(void *si)
132 #if defined(FLASH)
133 uint idx;
134 chipcregs_t *cc;
135 si_t *sih;
136 osl_t *osh;
137 void *oh;
138 struct nvram_header *nvh = NULL;
139 uintptr flbase;
140 struct sflash *info;
141 uint32 cap = 0, off, flsz;
142 #endif /* FLASH */
144 /* Make sure we read nvram in flash just once before freeing the memory */
145 if (vars != NULL) {
146 NVR_MSG(("nvram_init: called again without calling nvram_exit()\n"));
147 return 0;
150 #if defined(FLASH)
151 sih = (si_t *)si;
152 osh = si_osh(sih);
154 /* Check for flash */
155 idx = si_coreidx(sih);
156 cc = si_setcoreidx(sih, SI_CC_IDX);
157 ASSERT(cc);
159 flbase = (uintptr)OSL_UNCACHED((void *)SI_FLASH2);
160 flsz = 0;
161 cap = R_REG(osh, &cc->capabilities);
163 if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0))
164 cap &= ~CC_CAP_FLASH_MASK;
166 switch (cap & CC_CAP_FLASH_MASK) {
167 case PFLASH:
168 flsz = SI_FLASH2_SZ;
169 break;
171 case SFLASH_ST:
172 case SFLASH_AT:
173 if ((info = sflash_init(sih, cc)) == NULL)
174 break;
175 flsz = info->size;
176 break;
178 case FLASH_NONE:
179 default:
180 break;
183 /* If we found flash, see if there is nvram there */
184 if (flsz != 0) {
185 off = FLASH_MIN;
186 nvh = NULL;
187 while (off <= flsz) {
188 nvh = (struct nvram_header *)(flbase + off - NVRAM_SPACE);
189 if (R_REG(osh, &nvh->magic) == NVRAM_MAGIC)
190 break;
191 off <<= 1;
192 nvh = NULL;
195 if (nvh != NULL)
196 get_flash_nvram(sih, nvh);
199 /* Check for otp */
200 if ((oh = otp_init(sih)) != NULL) {
201 uint sz = otp_size(oh);
202 uint bufsz = sz + VARS_T_OH;
203 vars_t *new = (vars_t *)MALLOC(osh, bufsz);
204 if (new != NULL)
205 new->vars = (char *)new + VARS_T_OH;
206 if (new == NULL) {
207 NVR_MSG(("Out of memory for otp\n"));
208 } else if (otp_nvread(oh, new->vars, &sz)) {
209 NVR_MSG(("otp_nvread error\n"));
210 MFREE(osh, new, bufsz);
211 } else {
212 new->bufsz = bufsz;
213 new->size = sz;
214 new->next = vars;
215 vars = new;
219 /* Last, if we do have flash but no regular nvram was found in it,
220 * try for embedded nvram.
221 * Note that since we are doing this last, embedded nvram will override
222 * otp, a change from the normal precedence in the designs that use
223 * the full read/write nvram support.
225 if ((flsz != 0) && (nvh == NULL)) {
226 nvh = (struct nvram_header *)(flbase + 1024);
227 if (R_REG(osh, &nvh->magic) == NVRAM_MAGIC)
228 get_flash_nvram(sih, nvh);
229 else {
230 nvh = (struct nvram_header *)(flbase + 4096);
231 if (R_REG(osh, &nvh->magic) == NVRAM_MAGIC)
232 get_flash_nvram(sih, nvh);
236 /* All done */
237 si_setcoreidx(sih, idx);
238 #endif /* FLASH */
240 #if defined(BCMUSBDEV) || defined(BCMHOSTVARS)
241 #if defined(BCMHOSTVARS)
242 /* Honor host supplied variables and make them global */
243 if (_vars != NULL && _varsz != 0)
244 nvram_append(si, _vars, _varsz);
245 #endif
246 #ifndef CONFIG_XIP
247 #endif /* CONFIG_XIP */
248 #endif
250 #ifdef NVRAM_FILE
251 if (BUSTYPE(((si_t *)si)->bustype) == PCI_BUS) {
252 if (nvram_file_init(si) != 0)
253 return BCME_ERROR;
255 #endif /* NVRAM_FILE */
257 return 0;
260 #ifdef NVRAM_FILE
261 static int
262 nvram_file_init(void* sih)
264 char *base = NULL, *nvp = NULL, *flvars = NULL;
265 int err = 0, nvlen = 0;
267 base = nvp = MALLOC(si_osh((si_t *)sih), MAXSZ_NVRAM_VARS);
268 if (base == NULL)
269 return BCME_NOMEM;
271 /* Init nvram from nvram file if they exist */
272 err = initvars_file(sih, si_osh((si_t *)sih), &nvp, (int*)&nvlen);
273 if (err != 0) {
274 NVR_MSG(("No NVRAM file present!!!\n"));
275 goto exit;
277 if (nvlen) {
278 flvars = MALLOC(si_osh((si_t *)sih), nvlen);
279 if (flvars == NULL)
280 goto exit;
282 else
283 goto exit;
285 bcopy(base, flvars, nvlen);
286 err = nvram_append(sih, flvars, nvlen);
288 exit:
289 MFREE(si_osh((si_t *)sih), base, MAXSZ_NVRAM_VARS);
291 return err;
294 /* NVRAM file read for pcie NIC's */
295 static int
296 initvars_file(si_t *sih, osl_t *osh, char **nvramp, int *nvraml)
298 #if defined(BCMDRIVER)
299 /* Init nvram from nvram file if they exist */
300 char *nvram_buf = *nvramp;
301 void *nvram_fp = NULL;
302 int nv_len = 0, ret = 0, i = 0, len = 0;
304 nvram_fp = (void*)osl_os_open_image("nvram.txt");
305 if (nvram_fp != NULL) {
306 while ((nv_len = osl_os_get_image_block(nvram_buf, MAXSZ_NVRAM_VARS, nvram_fp)))
307 len = nv_len;
309 else {
310 NVR_MSG(("Could not open nvram.txt file\n"));
311 ret = -1;
312 goto exit;
315 /* Make array of strings */
316 for (i = 0; i < len; i++) {
317 if ((*nvram_buf == ' ') || (*nvram_buf == '\t') || (*nvram_buf == '\n') ||
318 (*nvram_buf == '\0')) {
319 *nvram_buf = '\0';
320 nvram_buf++;
322 else
323 nvram_buf++;
325 *nvram_buf++ = '\0';
326 *nvramp = nvram_buf;
327 *nvraml = len+1; /* add one for the null character */
329 exit:
330 if (nvram_fp)
331 osl_os_close_image(nvram_fp);
333 return ret;
334 #else /* BCMDRIVER */
335 return BCME_ERROR
336 #endif /* BCMDRIVER */
338 #endif /* NVRAM_FILE */
341 BCMATTACHFN(nvram_append)(void *si, char *varlst, uint varsz)
343 uint bufsz = VARS_T_OH;
344 vars_t *new;
346 if ((new = MALLOC(si_osh((si_t *)si), bufsz)) == NULL)
347 return BCME_NOMEM;
349 new->vars = varlst;
350 new->bufsz = bufsz;
351 new->size = varsz;
352 new->next = vars;
353 vars = new;
355 return BCME_OK;
358 void
359 nvram_get_global_vars(char **varlst, uint *varsz)
361 *varlst = vars->vars;
362 *varsz = vars->size;
365 void
366 BCMUNINITFN(nvram_exit)(void *si)
368 vars_t *this, *next;
369 si_t *sih;
371 sih = (si_t *)si;
372 this = vars;
374 #ifndef DONGLEBUILD
375 if (this)
376 MFREE(si_osh(sih), this->vars, this->size);
377 #endif /* DONGLEBUILD */
379 while (this) {
380 next = this->next;
381 MFREE(si_osh(sih), this, this->bufsz);
382 this = next;
384 vars = NULL;
387 static char *
388 findvar(char *vars_arg, char *lim, const char *name)
390 char *s;
391 int len;
393 len = strlen(name);
395 for (s = vars_arg; (s < lim) && *s;) {
396 if ((bcmp(s, name, len) == 0) && (s[len] == '='))
397 return (&s[len+1]);
399 while (*s++)
403 return NULL;
406 #ifdef BCMSPACE
407 char *defvars = "il0macaddr=00:11:22:33:44:55\0"
408 "boardtype=0xffff\0"
409 "boardrev=0x10\0"
410 "boardflags=8\0"
411 "aa0=3\0"
412 "sromrev=2";
413 #define DEFVARSLEN 89 /* Length of *defvars */
414 #else /* !BCMSPACE */
415 char *defvars = "";
416 #endif /* BCMSPACE */
418 char *
419 nvram_get(const char *name)
421 char *v = NULL;
422 vars_t *cur;
424 for (cur = vars; cur; cur = cur->next)
425 if ((v = findvar(cur->vars, cur->vars + cur->size, name)))
426 break;
428 #ifdef BCMSPACE
429 if (v == NULL) {
430 v = findvar(defvars, defvars + DEFVARSLEN, name);
431 if (v)
432 NVR_MSG(("%s: variable %s defaulted to %s\n",
433 __FUNCTION__, name, v));
435 #endif /* BCMSPACE */
437 return v;
441 BCMATTACHFN(nvram_set)(const char *name, const char *value)
443 return 0;
447 BCMATTACHFN(nvram_unset)(const char *name)
449 return 0;
453 BCMATTACHFN(nvram_reset)(void *si)
455 return 0;
459 BCMATTACHFN(nvram_commit)(void)
461 return 0;
465 nvram_getall(char *buf, int count)
467 int len, resid = count;
468 vars_t *this;
470 this = vars;
471 while (this) {
472 char *from, *lim, *to;
473 int acc;
475 from = this->vars;
476 lim = (char *)((uintptr)this->vars + this->size);
477 to = buf;
478 acc = 0;
479 while ((from < lim) && (*from)) {
480 len = strlen(from) + 1;
481 if (resid < (acc + len))
482 return BCME_BUFTOOSHORT;
483 bcopy(from, to, len);
484 acc += len;
485 from += len;
486 to += len;
489 resid -= acc;
490 buf += acc;
491 this = this->next;
493 if (resid < 1)
494 return BCME_BUFTOOSHORT;
495 *buf = '\0';
496 return 0;
499 #ifdef BCMQT
500 extern void nvram_printall(void);
501 /* QT: print nvram w/o a big buffer - helps w/memory consumption evaluation of USB bootloader */
502 void
503 nvram_printall(void)
505 vars_t *this;
507 this = vars;
508 while (this) {
509 char *from, *lim;
511 from = this->vars;
512 lim = (char *)((uintptr)this->vars + this->size);
513 while ((from < lim) && (*from)) {
514 printf("%s\n", from);
515 from += strlen(from) + 1;
517 this = this->next;
520 #endif /* BCMQT */