1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Environment variable subroutines File: carmel_env.c
6 * This is a special hacked copy of env_subr.c to store environment
7 * variables in the ID EEPROM. Sure, we could go and enhance
8 * CFE to support multiple environment devices, but this is
11 * Author: Mitch Lichtenberg (mpl@broadcom.com)
13 *********************************************************************
15 * Copyright 2000,2001,2002,2003
16 * Broadcom Corporation. All rights reserved.
18 * This software is furnished under license and may be used and
19 * copied only in accordance with the following terms and
20 * conditions. Subject to these conditions, you may download,
21 * copy, install, use, modify and distribute modified or unmodified
22 * copies of this software in source and/or binary form. No title
23 * or ownership is transferred hereby.
25 * 1) Any source code used, modified or distributed must reproduce
26 * and retain this copyright notice and list of conditions
27 * as they appear in the source file.
29 * 2) No right is granted to use any trade name, trademark, or
30 * logo of Broadcom Corporation. The "Broadcom Corporation"
31 * name may not be used to endorse or promote products derived
32 * from this software without the prior written permission of
33 * Broadcom Corporation.
35 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
36 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
37 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
39 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
40 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
41 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
43 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
46 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
47 * THE POSSIBILITY OF SUCH DAMAGE.
48 ********************************************************************* */
50 #include "lib_types.h"
51 #include "lib_string.h"
52 #include "lib_queue.h"
53 #include "lib_malloc.h"
54 #include "lib_printf.h"
57 #include "carmel_env.h"
60 #include "cfe_devfuncs.h"
61 #include "cfe_ioctl.h"
63 #include "cfe_error.h"
66 /* *********************************************************************
68 ********************************************************************* */
70 typedef struct cfe_envvar_s
{
75 /* name and value go here */
78 /* *********************************************************************
80 ********************************************************************* */
82 queue_t carmel_envvars
= {&carmel_envvars
,&carmel_envvars
};
83 extern unsigned int cfe_startflags
;
84 char *carmel_envdev
= NULL
;
86 /* *********************************************************************
87 * carmel_findenv(name)
89 * Locate an environment variable in the in-memory list
92 * name - name of env var to find
95 * cfe_envvar_t pointer, or NULL if not found
96 ********************************************************************* */
98 static cfe_envvar_t
*carmel_findenv(const char *name
)
103 for (qb
= carmel_envvars
.q_next
; qb
!= &carmel_envvars
; qb
= qb
->q_next
) {
104 env
= (cfe_envvar_t
*) qb
;
105 if (strcmp(env
->name
,name
) == 0) break;
108 if (qb
== &carmel_envvars
) return NULL
;
110 return (cfe_envvar_t
*) qb
;
114 /* *********************************************************************
115 * carmel_enumenv(idx,name,namelen,val,vallen)
117 * Enumerate environment variables. This routine locates
118 * the nth environment variable and copies its name and value
121 * The namelen and vallen variables must be preinitialized to
122 * the maximum size of the output buffer.
125 * idx - variable index to find (starting with zero)
126 * name,namelen - name buffer and length
127 * val,vallen - value buffer and length
132 ********************************************************************* */
134 int carmel_enumenv(int idx
,char *name
,int *namelen
,char *val
,int *vallen
)
139 for (qb
= carmel_envvars
.q_next
; qb
!= &carmel_envvars
; qb
= qb
->q_next
) {
144 if (qb
== &carmel_envvars
) return CFE_ERR_ENVNOTFOUND
;
145 env
= (cfe_envvar_t
*) qb
;
147 *namelen
= xstrncpy(name
,env
->name
,*namelen
);
148 *vallen
= xstrncpy(val
,env
->value
,*vallen
);
155 /* *********************************************************************
156 * carmel_delenv(name)
158 * Delete an environment variable
161 * name - environment variable to delete
166 ********************************************************************* */
168 int carmel_delenv(const char *name
)
172 env
= carmel_findenv(name
);
176 q_dequeue((queue_t
*) env
);
181 /* *********************************************************************
182 * carmel_getenv(name)
184 * Retrieve the value of an environment variable
187 * name - name of environment variable to find
190 * value, or NULL if variable is not found
191 ********************************************************************* */
193 char *carmel_getenv(const char *name
)
197 env
= carmel_findenv(name
);
207 /* *********************************************************************
208 * carmel_setenv(name,value,flags)
210 * Set the value of an environment variable
213 * name - name of variable
214 * value - value of variable
215 * flags - flags for variable (ENV_FLG_xxx)
220 ********************************************************************* */
222 int carmel_setenv(const char *name
,char *value
,int flags
)
227 env
= carmel_findenv(name
);
229 q_dequeue((queue_t
*) env
);
233 namelen
= strlen(name
);
235 env
= KMALLOC(sizeof(cfe_envvar_t
) + namelen
+ 1 + strlen(value
) + 1,0);
236 if (!env
) return CFE_ERR_NOMEM
;
238 env
->name
= (char *) (env
+1);
239 env
->value
= env
->name
+ namelen
+ 1;
240 env
->flags
= (flags
& ENV_FLG_MASK
);
242 strcpy(env
->name
,name
);
243 strcpy(env
->value
,value
);
245 q_enqueue(&carmel_envvars
,(queue_t
*) env
);
251 /* *********************************************************************
254 * Load the environment from the NVRAM device.
262 ********************************************************************* */
265 int carmel_loadenv(void)
268 unsigned char *buffer
;
270 unsigned char *envval
;
272 unsigned int rectype
;
280 * If in 'safe mode', don't read the environment the first time.
283 if (cfe_startflags
& CFE_INIT_SAFE
) {
284 cfe_startflags
&= ~CFE_INIT_SAFE
;
288 if (!carmel_envdev
) return -1;
289 fh
= cfe_open(carmel_envdev
);
290 if (fh
< 0) return fh
;
293 buffer
= KMALLOC(size
,0);
295 if (buffer
== NULL
) return CFE_ERR_NOMEM
;
300 /* Read the record type and length */
301 if (cfe_readblk(fh
,offset
,ptr
,1) != 1) {
302 retval
= CFE_ERR_IOERR
;
306 while ((*ptr
!= ENV_TLV_TYPE_END
) && (size
> 1)) {
308 /* Adjust pointer for TLV type */
314 * Read the length. It can be either 1 or 2 bytes
315 * depending on the code
317 if (rectype
& ENV_LENGTH_8BITS
) {
318 /* Read the record type and length - 8 bits */
319 if (cfe_readblk(fh
,offset
,ptr
,1) != 1) {
320 retval
= CFE_ERR_IOERR
;
328 /* Read the record type and length - 16 bits, MSB first */
329 if (cfe_readblk(fh
,offset
,ptr
,2) != 2) {
330 retval
= CFE_ERR_IOERR
;
333 reclen
= (((unsigned int) *(ptr
)) << 8) + (unsigned int) *(ptr
+1);
338 if (reclen
> size
) break; /* should not happen, bad NVRAM */
341 case ENV_TLV_TYPE_ENV
:
342 /* Read the TLV data */
343 if (cfe_readblk(fh
,offset
,ptr
,reclen
) != reclen
) goto error
;
345 envval
= (unsigned char *) strnchr(ptr
,'=',(reclen
-1));
348 memcpy(valuestr
,envval
,(reclen
-1)-(envval
-ptr
));
349 valuestr
[(reclen
-1)-(envval
-ptr
)] = '\0';
350 carmel_setenv(ptr
,valuestr
,flg
);
355 /* Unknown TLV type, skip it. */
360 * Advance to next TLV
366 /* Read the next record type */
368 if (cfe_readblk(fh
,offset
,ptr
,1) != 1) goto error
;
371 retval
= 0; /* success! */
383 /* *********************************************************************
386 * Write the environment to the NVRAM device.
392 * 0 if ok, else error code
393 ********************************************************************* */
395 int carmel_saveenv(void)
398 unsigned char *buffer
;
399 unsigned char *buffer_end
;
407 if (carmel_envdev
== NULL
) return -1;
408 fh
= cfe_open(carmel_envdev
);
409 if (fh
< 0) return fh
;
412 buffer
= KMALLOC(size
,0);
414 if (buffer
== NULL
) return CFE_ERR_NOMEM
;
416 buffer_end
= buffer
+ size
;
420 for (qb
= carmel_envvars
.q_next
; qb
!= &carmel_envvars
; qb
= qb
->q_next
) {
421 env
= (cfe_envvar_t
*) qb
;
423 if (env
->flags
& (ENV_FLG_BUILTIN
)) continue;
425 namelen
= strlen(env
->name
);
426 valuelen
= strlen(env
->value
);
428 if ((ptr
+ 2 + namelen
+ valuelen
+ 1 + 1 + 1) > buffer_end
) break;
430 *ptr
++ = ENV_TLV_TYPE_ENV
; /* TLV record type */
431 *ptr
++ = (namelen
+ valuelen
+ 1 + 1); /* TLV record length */
433 *ptr
++ = (unsigned char)env
->flags
;
434 memcpy(ptr
,env
->name
,namelen
); /* TLV record data */
437 memcpy(ptr
,env
->value
,valuelen
);
442 *ptr
++ = ENV_TLV_TYPE_END
;
444 size
= cfe_writeblk(fh
,0,buffer
,ptr
-buffer
);
450 return (size
== (ptr
-buffer
)) ? 0 : CFE_ERR_IOERR
;
454 /* *********************************************************************
455 * carmel_envtype(name)
457 * Return the type of the environment variable
460 * name - name of environment variable
463 * flags, or <0 if error occured
464 ********************************************************************* */
465 int carmel_envtype(const char *name
)
469 env
= carmel_findenv(name
);
475 return CFE_ERR_ENVNOTFOUND
;