2 * NVRAM variable manipulation (direct mapped flash)
4 * Copyright (C) 2010, 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_rw.c 258972 2011-05-11 08:57:26Z simonk $
29 #include <bcmendian.h>
36 #endif /* NFLASH_SUPPORT */
38 struct nvram_tuple
*_nvram_realloc(struct nvram_tuple
*t
, const char *name
, const char *value
);
39 void _nvram_free(struct nvram_tuple
*t
);
40 int _nvram_read(void *buf
);
42 extern char *_nvram_get(const char *name
);
43 extern int _nvram_set(const char *name
, const char *value
);
44 extern int _nvram_unset(const char *name
);
45 extern int _nvram_getall(char *buf
, int count
);
46 extern int _nvram_commit(struct nvram_header
*header
);
47 extern int _nvram_init(void *si
);
48 extern void _nvram_exit(void);
51 extern int kernel_initial
;
54 static struct nvram_header
*nvram_header
= NULL
;
55 static int nvram_do_reset
= FALSE
;
58 /* For NAND boot, flash0.nvram will be changed to nflash0.nvram */
59 char *flashdrv_nvram
= "flash0.nvram";
62 #define NVRAM_LOCK() do {} while (0)
63 #define NVRAM_UNLOCK() do {} while (0)
67 #define MB * 1024 * 1024
70 nvram_get(const char *name
)
80 value
= _nvram_get(name
);
87 nvram_getall(char *buf
, int count
)
92 ret
= _nvram_getall(buf
, count
);
99 BCMINITFN(nvram_set
)(const char *name
, const char *value
)
104 ret
= _nvram_set(name
, value
);
111 BCMINITFN(nvram_unset
)(const char *name
)
116 ret
= _nvram_unset(name
);
123 BCMINITFN(nvram_resetgpio_init
)(void *si
)
131 value
= nvram_get("reset_gpio");
135 gpio
= (int) bcm_atoi(value
);
139 /* Setup GPIO input */
140 si_gpioouten(sih
, ((uint32
) 1 << gpio
), 0, GPIO_DRV_PRIORITY
);
146 BCMINITFN(nvram_reset
)(void *si
)
150 si_t
* sih
= (si_t
*)si
;
152 if ((gpio
= nvram_resetgpio_init((void *)sih
)) < 0)
155 /* GPIO reset is asserted low */
156 for (msec
= 0; msec
< 5000; msec
++) {
157 if (si_gpioin(sih
) & ((uint32
) 1 << gpio
))
162 nvram_do_reset
= TRUE
;
166 extern unsigned char embedded_nvram
[];
168 static struct nvram_header
*
169 BCMINITFN(find_nvram
)(si_t
*sih
, bool embonly
, bool *isemb
)
171 struct nvram_header
*nvh
;
173 uint32 flbase
= SI_FLASH2
;
174 #ifdef NFLASH_SUPPORT
176 chipcregs_t
*cc
= NULL
;
177 struct nflash
*nfl_info
;
179 if ((sih
->ccrev
== 38) && ((sih
->chipst
& (1 << 4)) != 0)) {
183 #endif /* NFLASH_SUPPORT */
187 #ifdef NFLASH_SUPPORT
189 if ((cc
= (chipcregs_t
*)si_setcoreidx(sih
, SI_CC_IDX
))) {
190 nfl_info
= nflash_init(sih
, cc
);
192 off
= nfl_info
->blocksize
;
193 for (; off
< SI_FLASH1_SZ
; off
+= nfl_info
->blocksize
) {
194 if (nflash_checkbadb(sih
, cc
, off
) != 0)
196 nvh
= (struct nvram_header
*)KSEG1ADDR(flbase
+off
);
197 if (nvh
->magic
== NVRAM_MAGIC
)
203 #endif /* NFLASH_SUPPORT */
208 nvh
= (struct nvram_header
*)KSEG1ADDR(flbase
+ off
- NVRAM_SPACE
);
209 if (nvh
->magic
== NVRAM_MAGIC
)
210 /* if (nvram_calc_crc(nvh) == (uint8) nvh->crc_ver_init) */{
217 printf("find_nvram: nvram not found, trying embedded nvram next\n");
221 /* Now check embedded nvram */
223 nvh
= (struct nvram_header
*)KSEG1ADDR(flbase
+ (4 * 1024));
224 if (nvh
->magic
== NVRAM_MAGIC
)
226 nvh
= (struct nvram_header
*)KSEG1ADDR(flbase
+ 1024);
227 if (nvh
->magic
== NVRAM_MAGIC
)
230 nvh
= (struct nvram_header
*)embedded_nvram
;
231 if (nvh
->magic
== NVRAM_MAGIC
)
234 printf("find_nvram: no nvram found\n");
239 BCMATTACHFN(nvram_init
)(void *si
)
244 static int nvram_status
= -1;
251 /* Check for previous 'restore defaults' condition */
252 if (nvram_status
== 1)
255 /* Check whether nvram already initilized */
256 if (nvram_status
== 0 && !nvram_do_reset
)
261 /* Restore defaults from embedded NVRAM if button held down */
262 if (nvram_do_reset
) {
263 /* Initialize with embedded NVRAM */
264 nvram_header
= find_nvram(sih
, TRUE
, &isemb
);
265 ret
= _nvram_init(si
);
275 nvram_header
= find_nvram(sih
, FALSE
, &isemb
);
276 ret
= _nvram_init(si
);
278 /* Restore defaults if embedded NVRAM used */
279 if (nvram_header
&& isemb
) {
288 BCMINITFN(nvram_append
)(void *si
, char *vars
, uint varsz
)
294 BCMINITFN(nvram_exit
)(void *si
)
304 BCMINITFN(_nvram_read
)(void *buf
)
310 return -19; /* -ENODEV */
312 src
= (uint32
*) nvram_header
;
313 dst
= (uint32
*) buf
;
315 for (i
= 0; i
< sizeof(struct nvram_header
); i
+= 4)
318 for (; i
< nvram_header
->len
&& i
< NVRAM_SPACE
; i
+= 4)
319 *dst
++ = ltoh32(*src
++);
325 BCMINITFN(_nvram_realloc
)(struct nvram_tuple
*t
, const char *name
, const char *value
)
327 if (!(t
= MALLOC(NULL
, sizeof(struct nvram_tuple
) + strlen(name
) + 1 +
328 strlen(value
) + 1))) {
329 printf("_nvram_realloc: our of memory\n");
334 t
->name
= (char *) &t
[1];
335 strcpy(t
->name
, name
);
338 t
->value
= t
->name
+ strlen(name
) + 1;
339 strcpy(t
->value
, value
);
345 BCMINITFN(_nvram_free
)(struct nvram_tuple
*t
)
348 MFREE(NULL
, t
, sizeof(struct nvram_tuple
) + strlen(t
->name
) + 1 +
349 strlen(t
->value
) + 1);
353 BCMINITFN(nvram_commit
)(void)
355 struct nvram_header
*header
;
360 if (!(header
= (struct nvram_header
*) MALLOC(NULL
, NVRAM_SPACE
))) {
361 printf("nvram_commit: out of memory\n");
362 return -12; /* -ENOMEM */
367 /* Regenerate NVRAM */
368 ret
= _nvram_commit(header
);
372 src
= (uint32
*) &header
[1];
375 for (i
= sizeof(struct nvram_header
); i
< header
->len
&& i
< NVRAM_SPACE
; i
+= 4)
376 *dst
++ = htol32(*src
++);
379 if ((ret
= cfe_open(flashdrv_nvram
)) >= 0) {
380 cfe_writeblk(ret
, 0, (unsigned char *) header
, header
->len
);
384 if (sysFlashInit(NULL
) == 0) {
385 /* set/write invalid MAGIC # (in case writing image fails/is interrupted)
386 * write the NVRAM image to flash(with invalid magic)
387 * set/write valid MAGIC #
389 header
->magic
= NVRAM_CLEAR_MAGIC
;
390 nvWriteChars((unsigned char *)&header
->magic
, sizeof(header
->magic
));
392 header
->magic
= NVRAM_INVALID_MAGIC
;
393 nvWrite((unsigned short *) header
, NVRAM_SPACE
);
395 header
->magic
= NVRAM_MAGIC
;
396 nvWriteChars((unsigned char *)&header
->magic
, sizeof(header
->magic
));
398 #endif /* ifdef _CFE_ */
402 MFREE(NULL
, header
, NVRAM_SPACE
);