1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Environment variable subroutines File: env_subr.c
6 * This module contains routines to muck with environment variables
7 * (manage the list, read/write to nvram, etc.)
9 * Author: Mitch Lichtenberg (mpl@broadcom.com)
11 *********************************************************************
13 * Copyright 2000,2001,2002,2003
14 * Broadcom Corporation. All rights reserved.
16 * This software is furnished under license and may be used and
17 * copied only in accordance with the following terms and
18 * conditions. Subject to these conditions, you may download,
19 * copy, install, use, modify and distribute modified or unmodified
20 * copies of this software in source and/or binary form. No title
21 * or ownership is transferred hereby.
23 * 1) Any source code used, modified or distributed must reproduce
24 * and retain this copyright notice and list of conditions
25 * as they appear in the source file.
27 * 2) No right is granted to use any trade name, trademark, or
28 * logo of Broadcom Corporation. The "Broadcom Corporation"
29 * name may not be used to endorse or promote products derived
30 * from this software without the prior written permission of
31 * Broadcom Corporation.
33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGE.
46 ********************************************************************* */
48 #include "lib_types.h"
49 #include "lib_string.h"
50 #include "lib_queue.h"
51 #include "lib_malloc.h"
52 #include "lib_printf.h"
55 #include "nvram_subr.h"
57 #include "cfe_error.h"
61 extern void setenv (char *e
, char *v
, int rewrite
);
63 /* *********************************************************************
65 ********************************************************************* */
67 typedef struct cfe_envvar_s
{
72 /* name and value go here */
75 /* *********************************************************************
77 ********************************************************************* */
79 queue_t env_envvars
= {&env_envvars
,&env_envvars
};
80 extern unsigned int cfe_startflags
;
82 /* *********************************************************************
85 * Locate an environment variable in the in-memory list
88 * name - name of env var to find
91 * cfe_envvar_t pointer, or NULL if not found
92 ********************************************************************* */
94 static cfe_envvar_t
*env_findenv(const char *name
)
99 for (qb
= env_envvars
.q_next
; qb
!= &env_envvars
; qb
= qb
->q_next
) {
100 env
= (cfe_envvar_t
*) qb
;
101 if (strcmp(env
->name
,name
) == 0) break;
104 if (qb
== &env_envvars
) return NULL
;
106 return (cfe_envvar_t
*) qb
;
110 /* *********************************************************************
111 * env_enum(idx,name,namelen,val,vallen)
113 * Enumerate environment variables. This routine locates
114 * the nth environment variable and copies its name and value
117 * The namelen and vallen variables must be preinitialized to
118 * the maximum size of the output buffer.
121 * idx - variable index to find (starting with zero)
122 * name,namelen - name buffer and length
123 * val,vallen - value buffer and length
128 ********************************************************************* */
130 int env_enum(int idx
,char *name
,int *namelen
,char *val
,int *vallen
)
135 for (qb
= env_envvars
.q_next
; qb
!= &env_envvars
; qb
= qb
->q_next
) {
140 if (qb
== &env_envvars
) return CFE_ERR_ENVNOTFOUND
;
141 env
= (cfe_envvar_t
*) qb
;
143 *namelen
= xstrncpy(name
,env
->name
,*namelen
);
144 *vallen
= xstrncpy(val
,env
->value
,*vallen
);
150 /* *********************************************************************
153 * Return the type of the environment variable
156 * name - name of environment variable
159 * flags, or <0 if error occured
160 ********************************************************************* */
161 int env_envtype(const char *name
)
165 env
= env_findenv(name
);
171 return CFE_ERR_ENVNOTFOUND
;
176 /* *********************************************************************
179 * Delete an environment variable
182 * name - environment variable to delete
187 ********************************************************************* */
189 int env_delenv(const char *name
)
193 env
= env_findenv(name
);
197 if (!(env
->flags
& ENV_FLG_READONLY
)) {
198 q_dequeue((queue_t
*) env
);
203 return CFE_ERR_ENVNOTFOUND
;
206 /* *********************************************************************
209 * Retrieve the value of an environment variable
212 * name - name of environment variable to find
215 * value, or NULL if variable is not found
216 ********************************************************************* */
218 char *env_getenv(const char *name
)
222 env
= env_findenv(name
);
232 /* *********************************************************************
233 * env_setenv(name,value,flags)
235 * Set the value of an environment variable
238 * name - name of variable
239 * value - value of variable
240 * flags - flags for variable (ENV_FLG_xxx)
245 ********************************************************************* */
247 int env_setenv(const char *name
,char *value
,int flags
)
252 env
= env_findenv(name
);
254 if (!(flags
& ENV_FLG_ADMIN
)) {
255 if (env
->flags
& ENV_FLG_READONLY
) return CFE_ERR_ENVREADONLY
;
257 q_dequeue((queue_t
*) env
);
261 namelen
= strlen(name
);
263 env
= KMALLOC(sizeof(cfe_envvar_t
) + namelen
+ 1 + strlen(value
) + 1,0);
264 if (!env
) return CFE_ERR_NOMEM
;
266 env
->name
= (char *) (env
+1);
267 env
->value
= env
->name
+ namelen
+ 1;
268 env
->flags
= (flags
& ENV_FLG_MASK
);
270 strcpy(env
->name
,name
);
271 strcpy(env
->value
,value
);
273 q_enqueue(&env_envvars
,(queue_t
*) env
);
279 /* *********************************************************************
282 * Load the environment from the NVRAM device.
290 ********************************************************************* */
300 unsigned int rectype
;
307 * If in 'safe mode', don't read the environment the first time.
310 if (cfe_startflags
& CFE_INIT_SAFE
) {
311 cfe_startflags
&= ~CFE_INIT_SAFE
;
316 if (flg
< 0) return flg
;
318 size
= nvram_getsize();
319 buffer
= KMALLOC(size
,0);
321 if (buffer
== NULL
) return CFE_ERR_NOMEM
;
326 /* Read the record type and length */
327 if (nvram_read(ptr
,offset
,1) != 1) {
328 retval
= CFE_ERR_IOERR
;
332 while ((*ptr
!= ENV_TLV_TYPE_END
) && (size
> 1)) {
334 /* Adjust pointer for TLV type */
340 * Read the length. It can be either 1 or 2 bytes
341 * depending on the code
343 if (rectype
& ENV_LENGTH_8BITS
) {
344 /* Read the record type and length - 8 bits */
345 if (nvram_read(ptr
,offset
,1) != 1) {
346 retval
= CFE_ERR_IOERR
;
354 /* Read the record type and length - 16 bits, MSB first */
355 if (nvram_read(ptr
,offset
,2) != 2) {
356 retval
= CFE_ERR_IOERR
;
359 reclen
= (((unsigned int) *(ptr
)) << 8) + (unsigned int) *(ptr
+1);
364 if (reclen
> size
) break; /* should not happen, bad NVRAM */
367 case ENV_TLV_TYPE_ENV
:
368 /* Read the TLV data */
369 if (nvram_read(ptr
,offset
,reclen
) != reclen
) goto error
;
371 envval
= strnchr((char *)ptr
,'=',(reclen
-1));
374 memcpy(valuestr
,envval
,(reclen
-1)-(envval
-ptr
));
375 valuestr
[(reclen
-1)-(envval
-ptr
)] = '\0';
376 env_setenv((char *)ptr
,valuestr
,flg
);
381 /* Unknown TLV type, skip it. */
386 * Advance to next TLV
392 /* Read the next record type */
394 if (nvram_read(ptr
,offset
,1) != 1) goto error
;
397 retval
= 0; /* success! */
408 /* *********************************************************************
411 * Write the environment to the NVRAM device.
417 * 0 if ok, else error code
418 ********************************************************************* */
423 unsigned char *buffer
;
424 unsigned char *buffer_end
;
433 if (flg
< 0) return flg
;
437 size
= nvram_getsize();
438 buffer
= KMALLOC(size
,0);
440 if (buffer
== NULL
) return CFE_ERR_NOMEM
;
442 buffer_end
= buffer
+ size
;
446 for (qb
= env_envvars
.q_next
; qb
!= &env_envvars
; qb
= qb
->q_next
) {
447 env
= (cfe_envvar_t
*) qb
;
449 if (env
->flags
& (ENV_FLG_BUILTIN
)) continue;
451 namelen
= strlen(env
->name
);
452 valuelen
= strlen(env
->value
);
454 if ((ptr
+ 2 + namelen
+ valuelen
+ 1 + 1 + 1) > buffer_end
) break;
456 *ptr
++ = ENV_TLV_TYPE_ENV
; /* TLV record type */
457 *ptr
++ = (namelen
+ valuelen
+ 1 + 1); /* TLV record length */
459 *ptr
++ = (unsigned char)env
->flags
;
460 memcpy(ptr
,env
->name
,namelen
); /* TLV record data */
463 memcpy(ptr
,env
->value
,valuelen
);
466 setenv(env
->name
, env
->value
, 1);
471 *ptr
++ = ENV_TLV_TYPE_END
;
473 size
= nvram_write((char *)buffer
,0,ptr
-buffer
);
479 return (size
== (ptr
-buffer
)) ? 0 : CFE_ERR_IOERR
;