Root/target/linux/brcm-2.4/files/arch/mips/bcm947xx/cfe_env.c

1/*
2 * NVRAM variable manipulation (Linux kernel half)
3 *
4 * Copyright 2001-2003, 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 */
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/string.h>
19#include <asm/io.h>
20#include <asm/uaccess.h>
21
22#include <typedefs.h>
23#include <osl.h>
24#include <bcmendian.h>
25
26#define NVRAM_SIZE (0x1ff0)
27static char _nvdata[NVRAM_SIZE] __initdata;
28static char _valuestr[256] __initdata;
29
30/*
31 * TLV types. These codes are used in the "type-length-value"
32 * encoding of the items stored in the NVRAM device (flash or EEPROM)
33 *
34 * The layout of the flash/nvram is as follows:
35 *
36 * <type> <length> <data ...> <type> <length> <data ...> <type_end>
37 *
38 * The type code of "ENV_TLV_TYPE_END" marks the end of the list.
39 * The "length" field marks the length of the data section, not
40 * including the type and length fields.
41 *
42 * Environment variables are stored as follows:
43 *
44 * <type_env> <length> <flags> <name> = <value>
45 *
46 * If bit 0 (low bit) is set, the length is an 8-bit value.
47 * If bit 0 (low bit) is clear, the length is a 16-bit value
48 *
49 * Bit 7 set indicates "user" TLVs. In this case, bit 0 still
50 * indicates the size of the length field.
51 *
52 * Flags are from the constants below:
53 *
54 */
55#define ENV_LENGTH_16BITS 0x00 /* for low bit */
56#define ENV_LENGTH_8BITS 0x01
57
58#define ENV_TYPE_USER 0x80
59
60#define ENV_CODE_SYS(n,l) (((n)<<1)|(l))
61#define ENV_CODE_USER(n,l) ((((n)<<1)|(l)) | ENV_TYPE_USER)
62
63/*
64 * The actual TLV types we support
65 */
66
67#define ENV_TLV_TYPE_END 0x00
68#define ENV_TLV_TYPE_ENV ENV_CODE_SYS(0,ENV_LENGTH_8BITS)
69
70/*
71 * Environment variable flags
72 */
73
74#define ENV_FLG_NORMAL 0x00 /* normal read/write */
75#define ENV_FLG_BUILTIN 0x01 /* builtin - not stored in flash */
76#define ENV_FLG_READONLY 0x02 /* read-only - cannot be changed */
77
78#define ENV_FLG_MASK 0xFF /* mask of attributes we keep */
79#define ENV_FLG_ADMIN 0x100 /* lets us internally override permissions */
80
81
82/* *********************************************************************
83    * _nvram_read(buffer,offset,length)
84    *
85    * Read data from the NVRAM device
86    *
87    * Input parameters:
88    * buffer - destination buffer
89    * offset - offset of data to read
90    * length - number of bytes to read
91    *
92    * Return value:
93    * number of bytes read, or <0 if error occured
94    ********************************************************************* */
95static int
96_nvram_read(unsigned char *nv_buf, unsigned char *buffer, int offset, int length)
97{
98    int i;
99    if (offset > NVRAM_SIZE)
100    return -1;
101
102    for ( i = 0; i < length; i++) {
103    buffer[i] = ((volatile unsigned char*)nv_buf)[offset + i];
104    }
105    return length;
106}
107
108
109static char*
110_strnchr(const char *dest,int c,size_t cnt)
111{
112    while (*dest && (cnt > 0)) {
113    if (*dest == c) return (char *) dest;
114    dest++;
115    cnt--;
116    }
117    return NULL;
118}
119
120
121
122/*
123 * Core support API: Externally visible.
124 */
125
126/*
127 * Get the value of an NVRAM variable
128 * @param name name of variable to get
129 * @return value of variable or NULL if undefined
130 */
131
132char*
133cfe_env_get(unsigned char *nv_buf, char* name)
134{
135    int size;
136    unsigned char *buffer;
137    unsigned char *ptr;
138    unsigned char *envval;
139    unsigned int reclen;
140    unsigned int rectype;
141    int offset;
142    int flg;
143    
144    size = NVRAM_SIZE;
145    buffer = &_nvdata[0];
146
147    ptr = buffer;
148    offset = 0;
149
150    /* Read the record type and length */
151    if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
152    goto error;
153    }
154    
155    while ((*ptr != ENV_TLV_TYPE_END) && (size > 1)) {
156
157    /* Adjust pointer for TLV type */
158    rectype = *(ptr);
159    offset++;
160    size--;
161
162    /*
163     * Read the length. It can be either 1 or 2 bytes
164     * depending on the code
165     */
166    if (rectype & ENV_LENGTH_8BITS) {
167        /* Read the record type and length - 8 bits */
168        if (_nvram_read(nv_buf, ptr,offset,1) != 1) {
169        goto error;
170        }
171        reclen = *(ptr);
172        size--;
173        offset++;
174    }
175    else {
176        /* Read the record type and length - 16 bits, MSB first */
177        if (_nvram_read(nv_buf, ptr,offset,2) != 2) {
178        goto error;
179        }
180        reclen = (((unsigned int) *(ptr)) << 8) + (unsigned int) *(ptr+1);
181        size -= 2;
182        offset += 2;
183    }
184
185    if (reclen > size)
186        break; /* should not happen, bad NVRAM */
187
188    switch (rectype) {
189        case ENV_TLV_TYPE_ENV:
190        /* Read the TLV data */
191        if (_nvram_read(nv_buf, ptr,offset,reclen) != reclen)
192            goto error;
193        flg = *ptr++;
194        envval = (unsigned char *) _strnchr(ptr,'=',(reclen-1));
195        if (envval) {
196            *envval++ = '\0';
197            memcpy(_valuestr,envval,(reclen-1)-(envval-ptr));
198            _valuestr[(reclen-1)-(envval-ptr)] = '\0';
199#if 0
200            printk(KERN_INFO "NVRAM:%s=%s\n", ptr, _valuestr);
201#endif
202            if(!strcmp(ptr, name)){
203            return _valuestr;
204            }
205            if((strlen(ptr) > 1) && !strcmp(&ptr[1], name))
206            return _valuestr;
207        }
208        break;
209        
210        default:
211        /* Unknown TLV type, skip it. */
212        break;
213        }
214
215    /*
216     * Advance to next TLV
217     */
218        
219    size -= (int)reclen;
220    offset += reclen;
221
222    /* Read the next record type */
223    ptr = buffer;
224    if (_nvram_read(nv_buf, ptr,offset,1) != 1)
225        goto error;
226    }
227
228error:
229    return NULL;
230
231}
232
233

Archive Download this file



interactive