2 * Read-only support for NVRAM on flash and otp.
4 * Copyright (C) 2012, Broadcom Corporation
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 $
20 #include <bcmendian.h>
30 #define NVR_MSG(x) printf x
33 #endif /* BCMDBG_ERR */
35 typedef struct _vars
{
37 int bufsz
; /* allocated size */
38 int size
; /* actual vars size */
42 #define VARS_T_OH sizeof(vars_t)
44 static vars_t
*vars
= NULL
;
46 #if !defined(DONGLEBUILD) && !defined(BCM_BOOTLOADER)
51 static int nvram_file_init(void* sih
);
52 static int initvars_file(si_t
*sih
, osl_t
*osh
, char **nvramp
, int *nvraml
);
55 static char *findvar(char *vars_arg
, char *lim
, const char *name
);
56 extern void nvram_get_global_vars(char **varlst
, uint
*varsz
);
59 /* copy flash to ram */
61 BCMINITFN(get_flash_nvram
)(si_t
*sih
, struct nvram_header
*nvh
)
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"));
76 new->vars
= (char *)new + VARS_T_OH
;
84 if (BUSTYPE(sih
->bustype
) == JTAG_BUS
) {
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
++));
101 char b
[sizeof(uint32
)];
104 char *dst
= (char *)d
;
106 data
.w
= ltoh32(R_REG(osh
, s
));
107 for (i
= 0; i
< sz
; i
++)
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
));
119 #if defined(BCMUSBDEV) || defined(BCMHOSTVARS)
120 #if defined(BCMHOSTVARS)
125 extern uint8 embedded_nvram
[];
130 BCMATTACHFN(nvram_init
)(void *si
)
138 struct nvram_header
*nvh
= NULL
;
141 uint32 cap
= 0, off
, flsz
;
144 /* Make sure we read nvram in flash just once before freeing the memory */
146 NVR_MSG(("nvram_init: called again without calling nvram_exit()\n"));
154 /* Check for flash */
155 idx
= si_coreidx(sih
);
156 cc
= si_setcoreidx(sih
, SI_CC_IDX
);
159 flbase
= (uintptr
)OSL_UNCACHED((void *)SI_FLASH2
);
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
) {
173 if ((info
= sflash_init(sih
, cc
)) == NULL
)
183 /* If we found flash, see if there is nvram there */
187 while (off
<= flsz
) {
188 nvh
= (struct nvram_header
*)(flbase
+ off
- NVRAM_SPACE
);
189 if (R_REG(osh
, &nvh
->magic
) == NVRAM_MAGIC
)
196 get_flash_nvram(sih
, nvh
);
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
);
205 new->vars
= (char *)new + VARS_T_OH
;
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
);
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
);
230 nvh
= (struct nvram_header
*)(flbase
+ 4096);
231 if (R_REG(osh
, &nvh
->magic
) == NVRAM_MAGIC
)
232 get_flash_nvram(sih
, nvh
);
237 si_setcoreidx(sih
, idx
);
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
);
247 #endif /* CONFIG_XIP */
251 if (BUSTYPE(((si_t
*)si
)->bustype
) == PCI_BUS
) {
252 if (nvram_file_init(si
) != 0)
255 #endif /* NVRAM_FILE */
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
);
271 /* Init nvram from nvram file if they exist */
272 err
= initvars_file(sih
, si_osh((si_t
*)sih
), &nvp
, (int*)&nvlen
);
274 NVR_MSG(("No NVRAM file present!!!\n"));
278 flvars
= MALLOC(si_osh((si_t
*)sih
), nvlen
);
285 bcopy(base
, flvars
, nvlen
);
286 err
= nvram_append(sih
, flvars
, nvlen
);
289 MFREE(si_osh((si_t
*)sih
), base
, MAXSZ_NVRAM_VARS
);
294 /* NVRAM file read for pcie NIC's */
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
)))
310 NVR_MSG(("Could not open nvram.txt file\n"));
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')) {
327 *nvraml
= len
+1; /* add one for the null character */
331 osl_os_close_image(nvram_fp
);
334 #else /* BCMDRIVER */
336 #endif /* BCMDRIVER */
338 #endif /* NVRAM_FILE */
341 BCMATTACHFN(nvram_append
)(void *si
, char *varlst
, uint varsz
)
343 uint bufsz
= VARS_T_OH
;
346 if ((new = MALLOC(si_osh((si_t
*)si
), bufsz
)) == NULL
)
359 nvram_get_global_vars(char **varlst
, uint
*varsz
)
361 *varlst
= vars
->vars
;
366 BCMUNINITFN(nvram_exit
)(void *si
)
376 MFREE(si_osh(sih
), this->vars
, this->size
);
377 #endif /* DONGLEBUILD */
381 MFREE(si_osh(sih
), this, this->bufsz
);
388 findvar(char *vars_arg
, char *lim
, const char *name
)
395 for (s
= vars_arg
; (s
< lim
) && *s
;) {
396 if ((bcmp(s
, name
, len
) == 0) && (s
[len
] == '='))
407 char *defvars
= "il0macaddr=00:11:22:33:44:55\0"
413 #define DEFVARSLEN 89 /* Length of *defvars */
414 #else /* !BCMSPACE */
416 #endif /* BCMSPACE */
419 nvram_get(const char *name
)
424 for (cur
= vars
; cur
; cur
= cur
->next
)
425 if ((v
= findvar(cur
->vars
, cur
->vars
+ cur
->size
, name
)))
430 v
= findvar(defvars
, defvars
+ DEFVARSLEN
, name
);
432 NVR_MSG(("%s: variable %s defaulted to %s\n",
433 __FUNCTION__
, name
, v
));
435 #endif /* BCMSPACE */
441 BCMATTACHFN(nvram_set
)(const char *name
, const char *value
)
447 BCMATTACHFN(nvram_unset
)(const char *name
)
453 BCMATTACHFN(nvram_reset
)(void *si
)
459 BCMATTACHFN(nvram_commit
)(void)
465 nvram_getall(char *buf
, int count
)
467 int len
, resid
= count
;
472 char *from
, *lim
, *to
;
476 lim
= (char *)((uintptr
)this->vars
+ this->size
);
479 while ((from
< lim
) && (*from
)) {
480 len
= strlen(from
) + 1;
481 if (resid
< (acc
+ len
))
482 return BCME_BUFTOOSHORT
;
483 bcopy(from
, to
, len
);
494 return BCME_BUFTOOSHORT
;
500 extern void nvram_printall(void);
501 /* QT: print nvram w/o a big buffer - helps w/memory consumption evaluation of USB bootloader */
512 lim
= (char *)((uintptr
)this->vars
+ this->size
);
513 while ((from
< lim
) && (*from
)) {
514 printf("%s\n", from
);
515 from
+= strlen(from
) + 1;