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