1/* 2 * NVRAM variable manipulation (direct mapped flash) 3 * 4 * Copyright 2007, Broadcom Corporation 5 * All Rights Reserved. 6 * 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. 11 * 12 * $Id: nvram_rw.c,v 1.1.1.1 2008/10/15 03:31:34 james26_jang Exp $ 13 */ 14 15#include <typedefs.h> 16#include <bcmdefs.h> 17#include <osl.h> 18#include <bcmutils.h> 19#include <sbutils.h> 20#include <mipsinc.h> 21#include <bcmnvram.h> 22#include <bcmendian.h> 23#include <flashutl.h> 24#include <sbconfig.h> 25#include <sbchipc.h> 26 27struct nvram_tuple * _nvram_realloc(struct nvram_tuple *t, const char *name, const char *value); 28void _nvram_free(struct nvram_tuple *t); 29int _nvram_read(void *buf); 30 31extern char *_nvram_get(const char *name); 32extern int _nvram_set(const char *name, const char *value); 33extern int _nvram_unset(const char *name); 34extern int _nvram_getall(char *buf, int count); 35extern int _nvram_commit(struct nvram_header *header); 36extern int _nvram_init(void *sb); 37extern void _nvram_exit(void); 38 39static struct nvram_header *nvram_header = NULL; 40static bool nvram_do_reset = FALSE; 41 42#define NVRAM_LOCK() do {} while (0) 43#define NVRAM_UNLOCK() do {} while (0) 44 45/* Convenience */ 46#define KB * 1024 47#define MB * 1024 * 1024 48 49char * 50nvram_get(const char *name) 51{ 52 char *value; 53 54 NVRAM_LOCK(); 55 value = _nvram_get(name); 56 NVRAM_UNLOCK(); 57 58 return value; 59} 60 61int 62nvram_getall(char *buf, int count) 63{ 64 int ret; 65 66 NVRAM_LOCK(); 67 ret = _nvram_getall(buf, count); 68 NVRAM_UNLOCK(); 69 70 return ret; 71} 72 73int 74BCMINITFN(nvram_set)(const char *name, const char *value) 75{ 76 int ret; 77 78 NVRAM_LOCK(); 79 ret = _nvram_set(name, value); 80 NVRAM_UNLOCK(); 81 82 return ret; 83} 84 85int 86BCMINITFN(nvram_unset)(const char *name) 87{ 88 int ret; 89 90 NVRAM_LOCK(); 91 ret = _nvram_unset(name); 92 NVRAM_UNLOCK(); 93 94 return ret; 95} 96 97int 98BCMINITFN(nvram_resetgpio_init)(void *sb) 99{ 100 char *value; 101 int gpio; 102 sb_t *sbh; 103 104 sbh = (sb_t *)sb; 105 106 value = nvram_get("reset_gpio"); 107 if (!value) 108 return -1; 109 110 gpio = (int) bcm_atoi(value); 111 if (gpio > 7) 112 return -1; 113 114 /* Setup GPIO input */ 115 sb_gpioouten(sbh, ((uint32) 1 << gpio), 0, GPIO_DRV_PRIORITY); 116 117 return gpio; 118} 119 120bool 121BCMINITFN(nvram_reset)(void *sb) 122{ 123 int gpio; 124 uint msec; 125 sb_t * sbh = (sb_t *)sb; 126 127 if ((gpio = nvram_resetgpio_init((void *)sbh)) < 0) 128 return FALSE; 129 130 /* GPIO reset is asserted low */ 131 for (msec = 0; msec < 5000; msec++) { 132 if (sb_gpioin(sbh) & ((uint32) 1 << gpio)) 133 return FALSE; 134 OSL_DELAY(1000); 135 } 136 137 nvram_do_reset = TRUE; 138 return TRUE; 139} 140 141extern unsigned char embedded_nvram[]; 142 143static struct nvram_header * 144BCMINITFN(find_nvram)(bool embonly, bool *isemb) 145{ 146 struct nvram_header *nvh; 147 uint32 off, lim; 148 149 150 if (!embonly) { 151 *isemb = FALSE; 152 lim = SB_FLASH2_SZ; 153 off = FLASH_MIN; 154 while (off <= lim) { 155 nvh = (struct nvram_header *)KSEG1ADDR(SB_FLASH2 + off - NVRAM_SPACE); 156 if (nvh->magic == NVRAM_MAGIC) 157 /* if (nvram_calc_crc(nvh) == (uint8) nvh->crc_ver_init) */{ 158 return (nvh); 159 } 160 off <<= 1; 161 }; 162 } 163 164 /* Now check embedded nvram */ 165 *isemb = TRUE; 166 nvh = (struct nvram_header *)KSEG1ADDR(SB_FLASH2 + (4 * 1024)); 167 if (nvh->magic == NVRAM_MAGIC) 168 return (nvh); 169 nvh = (struct nvram_header *)KSEG1ADDR(SB_FLASH2 + 1024); 170 if (nvh->magic == NVRAM_MAGIC) 171 return (nvh); 172#ifdef _CFE_ 173 nvh = (struct nvram_header *)embedded_nvram; 174 if (nvh->magic == NVRAM_MAGIC) 175 return (nvh); 176#endif 177 printf("find_nvram: no nvram found\n"); 178 return (NULL); 179} 180 181int 182BCMINITFN(nvram_init)(void *sb) 183{ 184 bool isemb; 185 int ret; 186 sb_t *sbh; 187 static int nvram_status = -1; 188 189 /* Check for previous 'restore defaults' condition */ 190 if (nvram_status == 1) 191 return 1; 192 193 /* Check whether nvram already initilized */ 194 if (nvram_status == 0 && !nvram_do_reset) 195 return 0; 196 197 sbh = (sb_t *)sb; 198 199 /* Restore defaults from embedded NVRAM if button held down */ 200 if (nvram_do_reset) { 201 /* Initialize with embedded NVRAM */ 202 nvram_header = find_nvram(TRUE, &isemb); 203 ret = _nvram_init(sb); 204 if (ret == 0) { 205 nvram_status = 1; 206 return 1; 207 } 208 nvram_status = -1; 209 _nvram_exit(); 210 } 211 212 /* Find NVRAM */ 213 nvram_header = find_nvram(FALSE, &isemb); 214 ret = _nvram_init(sb); 215 if (ret == 0) { 216 /* Restore defaults if embedded NVRAM used */ 217 if (nvram_header && isemb) { 218 ret = 1; 219 } 220 } 221 nvram_status = ret; 222 return ret; 223} 224 225int 226BCMINITFN(nvram_append)(void *sb, char *vars, uint varsz) 227{ 228 return 0; 229} 230 231void 232BCMINITFN(nvram_exit)(void *sb) 233{ 234 sb_t *sbh; 235 236 sbh = (sb_t *)sb; 237 238 _nvram_exit(); 239} 240 241int 242BCMINITFN(_nvram_read)(void *buf) 243{ 244 uint32 *src, *dst; 245 uint i; 246 247 if (!nvram_header) 248 return -19; /* -ENODEV */ 249 250 src = (uint32 *) nvram_header; 251 dst = (uint32 *) buf; 252 253 for (i = 0; i < sizeof(struct nvram_header); i += 4) 254 *dst++ = *src++; 255 256 for (; i < nvram_header->len && i < NVRAM_SPACE; i += 4) 257 *dst++ = ltoh32(*src++); 258 259 return 0; 260} 261 262struct nvram_tuple * 263BCMINITFN(_nvram_realloc)(struct nvram_tuple *t, const char *name, const char *value) 264{ 265 if (!(t = MALLOC(NULL, sizeof(struct nvram_tuple) + strlen(name) + 1 + 266 strlen(value) + 1))) { 267 printf("_nvram_realloc: our of memory\n"); 268 return NULL; 269 } 270 271 /* Copy name */ 272 t->name = (char *) &t[1]; 273 strcpy(t->name, name); 274 275 /* Copy value */ 276 t->value = t->name + strlen(name) + 1; 277 strcpy(t->value, value); 278 279 return t; 280} 281 282void 283BCMINITFN(_nvram_free)(struct nvram_tuple *t) 284{ 285 if (t) 286 MFREE(NULL, t, sizeof(struct nvram_tuple) + strlen(t->name) + 1 + 287 strlen(t->value) + 1); 288} 289 290int 291BCMINITFN(nvram_commit)(void) 292{ 293 struct nvram_header *header; 294 int ret; 295 uint32 *src, *dst; 296 uint i; 297 298 if (!(header = (struct nvram_header *) MALLOC(NULL, NVRAM_SPACE))) { 299 printf("nvram_commit: out of memory\n"); 300 return -12; /* -ENOMEM */ 301 } 302 303 NVRAM_LOCK(); 304 305 /* Regenerate NVRAM */ 306 ret = _nvram_commit(header); 307 if (ret) 308 goto done; 309 310 src = (uint32 *) &header[1]; 311 dst = src; 312 313 for (i = sizeof(struct nvram_header); i < header->len && i < NVRAM_SPACE; i += 4) 314 *dst++ = htol32(*src++); 315 316#ifdef _CFE_ 317 if ((ret = cfe_open("flash0.nvram")) >= 0) { 318 cfe_writeblk(ret, 0, (unsigned char *) header, header->len); 319 cfe_close(ret); 320 } 321#else 322 if (sysFlashInit(NULL) == 0) { 323 /* set/write invalid MAGIC # (in case writing image fails/is interrupted) 324 write the NVRAM image to flash(with invalid magic) 325 set/write valid MAGIC # 326 */ 327 header->magic = NVRAM_CLEAR_MAGIC; 328 nvWriteChars((unsigned char *)&header->magic, sizeof(header->magic)); 329 330 header->magic = NVRAM_INVALID_MAGIC; 331 nvWrite((unsigned short *) header, NVRAM_SPACE); 332 333 header->magic = NVRAM_MAGIC; 334 nvWriteChars((unsigned char *)&header->magic, sizeof(header->magic)); 335 } 336#endif /* ifdef _CFE_ */ 337 338done: 339 NVRAM_UNLOCK(); 340 MFREE(NULL, header, NVRAM_SPACE); 341 return ret; 342} 343