1/*
2 * NVRAM variable manipulation (Linux user mode half)
3 *
4 * Copyright (C) 2010, 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,v 1.12 2008/04/03 02:55:46 Exp $
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#define PATH_DEV_NVRAM "/dev/nvram"
38
39/* wklin added, 12/13/2006 */
40#include <sys/types.h>
41#include <sys/ipc.h>
42#include <sys/sem.h>
43
44#define LOCK            -1
45#define UNLOCK          1
46#define NVRAM_SAVE_KEY  0x12345678
47static int lock_shm (int semkey, int op)
48{
49    struct sembuf lockop = { 0, 0, SEM_UNDO } /* sem operation */ ;
50    int semid;
51
52    if (semkey == 0)
53        return -1;
54
55    /* create/init sem */
56    if ((semid = semget (semkey, 1, IPC_CREAT | IPC_EXCL | 0666)) >= 0)
57    {
58        /* initialize the sem vaule to 1 */
59        if (semctl (semid, 0, SETVAL, 1) < 0)
60        {
61            return -1;
62        }
63    }
64    else
65    {
66        /* sem maybe has createdAget the semid */
67        if ((semid = semget (semkey, 1, 0666)) < 0)
68        {
69            return -1;
70        }
71    }
72
73    lockop.sem_op = op;
74    if (semop (semid, &lockop, 1) < 0)
75        return -1;
76
77    return 0;
78}
79
80#define NVRAM_LOCK()    //lock_shm(NVRAM_SAVE_KEY, LOCK)
81#define NVRAM_UNLOCK()    //lock_shm(NVRAM_SAVE_KEY, UNLOCK)
82/* wklin added, 12/13/2006 */
83
84
85
86/* Globals */
87static int nvram_fd = -1;
88static char *nvram_buf = NULL;
89
90int
91nvram_init(void *unused)
92{
93	if (nvram_fd >= 0)
94		return 0;
95
96	if ((nvram_fd = open(PATH_DEV_NVRAM, O_RDWR)) < 0)
97		goto err;
98
99	/* Map kernel string buffer into user space */
100	if ((nvram_buf = mmap(NULL, NVRAM_SPACE, PROT_READ, MAP_SHARED, nvram_fd, 0)) == MAP_FAILED) {
101		close(nvram_fd);
102		nvram_fd = -1;
103		goto err;
104	}
105
106	return 0;
107
108 err:
109	perror(PATH_DEV_NVRAM);
110	return errno;
111}
112
113char *
114nvram_get(const char *name)
115{
116	size_t count = strlen(name) + 1;
117	char tmp[100], *value;
118	unsigned long *off = (unsigned long *) tmp;
119
120	if (nvram_init(NULL))
121		return NULL;
122
123	if (count > sizeof(tmp)) {
124		if (!(off = malloc(count)))
125			return NULL;
126	}
127
128	/* Get offset into mmap() space */
129	strcpy((char *) off, name);
130
131	count = read(nvram_fd, off, count);
132
133	if (count == sizeof(unsigned long))
134		value = &nvram_buf[*off];
135	else
136		value = NULL;
137
138	if (count < 0)
139		perror(PATH_DEV_NVRAM);
140
141	if (off != (unsigned long *) tmp)
142		free(off);
143
144	return value;
145}
146
147int
148nvram_getall(char *buf, int count)
149{
150	int ret;
151
152	if (nvram_fd < 0)
153		if ((ret = nvram_init(NULL)))
154			return ret;
155
156	if (count == 0)
157		return 0;
158
159	/* Get all variables */
160	*buf = '\0';
161
162	ret = read(nvram_fd, buf, count);
163
164	if (ret < 0)
165		perror(PATH_DEV_NVRAM);
166
167	return (ret == count) ? 0 : ret;
168}
169
170static int
171_nvram_set(const char *name, const char *value)
172{
173	size_t count = strlen(name) + 1;
174	char tmp[100], *buf = tmp;
175	int ret;
176
177	if ((ret = nvram_init(NULL)))
178		return ret;
179
180	/* Unset if value is NULL */
181	if (value)
182		count += strlen(value) + 1;
183
184	if (count > sizeof(tmp)) {
185		if (!(buf = malloc(count)))
186			return -ENOMEM;
187	}
188
189	if (value)
190		sprintf(buf, "%s=%s", name, value);
191	else
192		strcpy(buf, name);
193
194	ret = write(nvram_fd, buf, count);
195
196	if (ret < 0)
197		perror(PATH_DEV_NVRAM);
198
199	if (buf != tmp)
200		free(buf);
201
202	return (ret == count) ? 0 : ret;
203}
204
205int
206nvram_set(const char *name, const char *value)
207{
208	return _nvram_set(name, value);
209}
210
211int
212nvram_unset(const char *name)
213{
214	return _nvram_set(name, NULL);
215}
216
217int
218nvram_commit(void)
219{
220	int ret;
221
222    /* foxconn wklin added start, 11/02/2010, show messag when doing commit */
223    {
224        FILE *fp;
225        fp = fopen("/dev/console", "w");
226        if (fp) {
227            fprintf(fp, "Doing nvram commit by pid %d !\n",getpid());
228            fclose(fp);
229        }
230    }
231    /* foxconn wklin added end , 11/02/2010 */
232	if ((ret = nvram_init(NULL)))
233		return ret;
234
235	ret = ioctl(nvram_fd, NVRAM_MAGIC, NULL);
236
237	if (ret < 0)
238		perror(PATH_DEV_NVRAM);
239
240	return ret;
241}
242
243/* Foxconn added start Peter Ling 12/05/2005 */
244#ifdef ACOS_MODULES_ENABLE
245extern struct nvram_tuple router_defaults[];
246
247int nvram_loaddefault (void)
248{
249    /* Foxconn add start, FredPeng, 04/14/2009 */
250    char cmd[128];
251    memset(cmd, 0, sizeof(cmd));
252    /* Foxconn add end, FredPeng, 04/14/2009 */
253
254    system("rm /tmp/ppp/ip-down"); /* added by EricHuang, 01/12/2007 */
255
256    /* Foxconn modify start, FredPeng, 04/14/2009 */
257    sprintf(cmd, "erase %s", NVRAM_MTD_WR);
258    system(cmd);
259    /* Foxconn modify end, FredPeng, 04/14/2009 */
260
261    printf("Load default done!\n");
262
263    return (0);
264}
265#endif
266/* Foxconn added end Peter Ling 12/05/2005 */
267