1/* 2 * NVRAM variable manipulation (Linux user mode half) 3 * 4 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved. 5 * 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. 9 * 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. 17 * 18 * $Id: nvram_linux.c 496107 2014-08-11 09:29:41Z $ 19 */ 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <unistd.h> 24#include <errno.h> 25#include <error.h> 26#include <string.h> 27#include <sys/ioctl.h> 28#include <sys/types.h> 29#include <sys/stat.h> 30#include <fcntl.h> 31#include <sys/mman.h> 32 33#include <typedefs.h> 34#include <bcmnvram.h> 35 36#include "ambitCfg.h" //Foxconn add, FredPeng, 04/17/2009 37 38#define CODE_BUFF 16 39#define HEX_BASE 16 40 41#define VALIDATE_BIT(bit) do { if ((bit < 0) || (bit > 31)) return NULL; } while (0) 42 43 44#define PATH_DEV_NVRAM "/dev/nvram" 45 46/* wklin added, 12/13/2006 */ 47#include <sys/types.h> 48#include <sys/ipc.h> 49#include <sys/sem.h> 50 51#define LOCK -1 52#define UNLOCK 1 53#define NVRAM_SAVE_KEY 0x12345678 54static int lock_shm (int semkey, int op) 55{ 56 struct sembuf lockop = { 0, 0, SEM_UNDO } /* sem operation */ ; 57 int semid; 58 59 if (semkey == 0) 60 return -1; 61 62 /* create/init sem */ 63 if ((semid = semget (semkey, 1, IPC_CREAT | IPC_EXCL | 0666)) >= 0) 64 { 65 /* initialize the sem vaule to 1 */ 66 if (semctl (semid, 0, SETVAL, 1) < 0) 67 { 68 return -1; 69 } 70 } 71 else 72 { 73 /* sem maybe has createdAget the semid */ 74 if ((semid = semget (semkey, 1, 0666)) < 0) 75 { 76 return -1; 77 } 78 } 79 80 lockop.sem_op = op; 81 if (semop (semid, &lockop, 1) < 0) 82 return -1; 83 84 return 0; 85} 86 87#define NVRAM_LOCK() //lock_shm(NVRAM_SAVE_KEY, LOCK) 88#define NVRAM_UNLOCK() //lock_shm(NVRAM_SAVE_KEY, UNLOCK) 89/* wklin added, 12/13/2006 */ 90 91 92 93/* Globals */ 94static int nvram_fd = -1; 95static char *nvram_buf = NULL; 96 97int 98nvram_init(void *unused) 99{ 100 101 if (nvram_fd >= 0) 102 return 0; 103 104 if ((nvram_fd = open(PATH_DEV_NVRAM, O_RDWR)) < 0) 105 goto err; 106 107 /* Map kernel string buffer into user space */ 108 nvram_buf = mmap(NULL, MAX_NVRAM_SPACE, PROT_READ, MAP_SHARED, nvram_fd, 0); 109 if (nvram_buf == MAP_FAILED) { 110 close(nvram_fd); 111 nvram_fd = -1; 112 goto err; 113 } 114 115 (void)fcntl(nvram_fd, F_SETFD, FD_CLOEXEC); 116 117 return 0; 118 119err: 120 perror(PATH_DEV_NVRAM); 121 return errno; 122} 123 124char * 125nvram_get(const char *name) 126{ 127 ssize_t count = strlen(name) + 1; 128 char tmp[100], *value; 129 unsigned long *off = (unsigned long *) tmp; 130 131 if (nvram_init(NULL)) 132 return NULL; 133 134 if (count > sizeof(tmp)) { 135 if (!(off = malloc(count))) 136 return NULL; 137 } 138 139 /* Get offset into mmap() space */ 140 strcpy((char *) off, name); 141 142 count = read(nvram_fd, off, count); 143 144 if (count == sizeof(unsigned long)) 145 value = &nvram_buf[*off]; 146 else 147 value = NULL; 148 149 if (count < 0) 150 perror(PATH_DEV_NVRAM); 151 152 if (off != (unsigned long *) tmp) 153 free(off); 154 155 return value; 156} 157 158 159char * 160nvram_get_bitflag(const char *name, const int bit) 161{ 162 VALIDATE_BIT(bit); 163 char *ptr = nvram_get(name); 164 unsigned long nvramvalue = 0; 165 unsigned long bitflagvalue = 1; 166 167 if (ptr) { 168 bitflagvalue = bitflagvalue << bit; 169 nvramvalue = strtoul(ptr, NULL, HEX_BASE); 170 if (nvramvalue) { 171 nvramvalue = nvramvalue & bitflagvalue; 172 } 173 } 174 return ptr ? (nvramvalue ? "1" : "0") : NULL; 175} 176 177int 178nvram_set_bitflag(const char *name, const int bit, const int value) 179{ 180 VALIDATE_BIT(bit); 181 char nvram_val[CODE_BUFF]; 182 char *ptr = nvram_get(name); 183 unsigned long nvramvalue = 0; 184 unsigned long bitflagvalue = 1; 185 186 memset(nvram_val, 0, sizeof(nvram_val)); 187 188 if (ptr) { 189 bitflagvalue = bitflagvalue << bit; 190 nvramvalue = strtoul(ptr, NULL, HEX_BASE); 191 if (value) { 192 nvramvalue |= bitflagvalue; 193 } else { 194 nvramvalue &= (~bitflagvalue); 195 } 196 } 197 snprintf(nvram_val, sizeof(nvram_val)-1, "%lx", nvramvalue); 198 return nvram_set(name, nvram_val); 199} 200 201int 202nvram_getall(char *buf, int count) 203{ 204 int ret; 205 206 if (nvram_fd < 0) 207 if ((ret = nvram_init(NULL))) 208 return ret; 209 210 if (count == 0) 211 return 0; 212 213 /* Get all variables */ 214 *buf = '\0'; 215 216 ret = read(nvram_fd, buf, count); 217 218 if (ret < 0) 219 perror(PATH_DEV_NVRAM); 220 221 return (ret == count) ? 0 : ret; 222} 223 224static int 225_nvram_set(const char *name, const char *value) 226{ 227 size_t count = strlen(name) + 1; 228 char tmp[100], *buf = tmp; 229 int ret; 230 231 if ((ret = nvram_init(NULL))) 232 return ret; 233 234 /* Unset if value is NULL */ 235 if (value) 236 count += strlen(value) + 1; 237 238 if (count > sizeof(tmp)) { 239 if (!(buf = malloc(count))) 240 return -ENOMEM; 241 } 242 243 if (value) 244 sprintf(buf, "%s=%s", name, value); 245 else 246 strcpy(buf, name); 247 248 ret = write(nvram_fd, buf, count); 249 250 if (ret < 0) 251 perror(PATH_DEV_NVRAM); 252 253 if (buf != tmp) 254 free(buf); 255 256 return (ret == count) ? 0 : ret; 257} 258 259int 260nvram_set(const char *name, const char *value) 261{ 262 return _nvram_set(name, value); 263} 264 265int 266nvram_unset(const char *name) 267{ 268 return _nvram_set(name, NULL); 269} 270 271int 272nvram_commit(void) 273{ 274 int ret; 275 276 /* foxconn wklin added start, 11/02/2010, show messag when doing commit */ 277 { 278 FILE *fp; 279 fp = fopen("/dev/console", "w"); 280 if (fp) { 281 fprintf(fp, "Doing nvram commit by pid %d !\n",getpid()); 282 fclose(fp); 283 } 284 } 285 /* foxconn wklin added end , 11/02/2010 */ 286 if ((ret = nvram_init(NULL))) 287 return ret; 288 289 ret = ioctl(nvram_fd, NVRAM_MAGIC, NULL); 290 291 if (ret < 0) 292 perror(PATH_DEV_NVRAM); 293 294 return ret; 295} 296 297/* Foxconn added start Peter Ling 12/05/2005 */ 298#ifdef ACOS_MODULES_ENABLE 299extern struct nvram_tuple router_defaults[]; 300 301int nvram_loaddefault (void) 302{ 303 /* Foxconn add start, FredPeng, 04/14/2009 */ 304 char cmd[128]; 305 memset(cmd, 0, sizeof(cmd)); 306 /* Foxconn add end, FredPeng, 04/14/2009 */ 307 308 system("rm /tmp/ppp/ip-down"); /* added by EricHuang, 01/12/2007 */ 309 310 /* Foxconn modify start, FredPeng, 04/14/2009 */ 311 sprintf(cmd, "erase %s", NVRAM_MTD_WR); 312 system(cmd); 313 /* Foxconn modify end, FredPeng, 04/14/2009 */ 314 315 printf("Load default done!\n"); 316 317 return (0); 318} 319#endif 320/* Foxconn added end Peter Ling 12/05/2005 */ 321