9
0
Fork 0
barebox/common/env.c

296 lines
7.1 KiB
C
Raw Normal View History

2007-07-05 16:01:26 +00:00
#include <common.h>
#include <command.h>
#include <driver.h>
#include <malloc.h>
#include <errno.h>
2007-07-05 16:01:26 +00:00
static ulong env_size;
static char *env_name_spec;
struct variable_d {
struct variable_d *next;
char data[0];
};
#define VARIABLE_D_SIZE(name, value) (sizeof(struct variable_d) + strlen(name) + strlen(value) + 2)
static struct variable_d *env_list;
static char *var_val(struct variable_d *var)
{
2007-07-05 16:01:34 +00:00
return &var->data[strlen(var->data) + 1];
2007-07-05 16:01:26 +00:00
}
static char *var_name(struct variable_d *var)
{
return var->data;
}
char *getenv (const char *name)
{
struct variable_d *var;
if (!env_list) {
printf("getenv(%s): not initialized\n",name);
return NULL;
}
var = env_list->next;
while (var) {
if (!strcmp(var_name(var), name))
return var_val(var);
var = var->next;
}
return 0;
}
void setenv (const char *name, const char *value)
{
struct variable_d *var = env_list;
struct variable_d *newvar = NULL;
if (!env_list) {
printf("setenv(%s): not initialized\n",name);
return;
}
if (value) {
newvar = malloc(VARIABLE_D_SIZE(name, value));
if (!newvar) {
printf("cannot setenv: out of mem\n");
return;
}
strcpy(&newvar->data[0], name);
2007-07-05 16:01:34 +00:00
strcpy(&newvar->data[strlen(name) + 1], value);
2007-07-05 16:01:26 +00:00
newvar->next = NULL;
}
while (var->next) {
if (!strcmp(var->next->data, name)) {
if (value) {
newvar->next = var->next->next;
free(var->next);
var->next = newvar;
return;
} else {
struct variable_d *tmp;
tmp = var->next;
var->next = var->next->next;
free(var->next);
return;
}
}
var = var->next;
}
var->next = newvar;
}
int add_env_spec(char *spec)
{
char *env;
char *data;
int err;
unsigned long crc;
struct memarea_info info;
printf("%s\n",__FUNCTION__);
if (spec_str_to_info(spec, &info)) {
printf("-ENOPARSE\n");
return -1;
}
/* Do it the simple way for now: Assume that the whole
* environment sector plus the environment list fits in
* memory.
*/
env_size = info.size;
env_name_spec = spec;
env = malloc(env_size);
if (!env) {
err = -ENOMEM;
goto err_out;
}
env_list = malloc(sizeof(struct variable_d));
if (!env_list) {
err = -ENOMEM;
goto err_out;
}
env_list->next = NULL;
2007-07-05 16:01:38 +00:00
err = dev_read(info.device, env, env_size, info.start, 0);
2007-07-05 16:01:26 +00:00
if (err != env_size)
goto err_out;
/* Make sure we don't go crazy with a corrupted environment */
*(env + env_size - 1) = 0;
*(env + env_size - 2) = 0;
crc = *(ulong *)env;
if (crc != crc32(0, env + sizeof(ulong), env_size - sizeof(ulong))) {
printf("environment is corrupt\n");
err = -ENODEV;
goto err_out;
}
data = env + sizeof(env);
while(*data) {
char *delim = strchr(data, '=');
int len = strlen(data);
printf("data: %s\n", data);
if (!delim)
goto err_out;
*delim = 0;
setenv(data, delim + 1);
data += len + 1;
}
free(env);
return 0;
err_out:
printf("error\n");
return -1;
}
int saveenv(void)
{
struct variable_d *var = env_list->next;
struct memarea_info info;
unsigned char *env;
int left, ret = 0, ofs;
if (spec_str_to_info(env_name_spec, &info)) {
printf("-ENOPARSE\n");
return -1;
}
env = malloc(env_size);
if (!env) {
printf("out of memory\n");
ret = -ENOMEM;
goto err_out;
}
memset(env, 0, env_size);
left = env_size - 2;
ofs = 4;
while (var) {
int nlen = strlen(var_name(var));
int vlen = strlen(var_val(var));
if (ofs + nlen + 1 + vlen + 2 >= env_size) {
printf("no space left in environment\n");
ret = -ENOSPC;
goto err_out;
}
strcpy(env + ofs, var_name(var));
ofs += nlen;
*(env + ofs) = '=';
ofs++;
strcpy(env + ofs, var_val(var));
ofs += vlen + 1;
var = var->next;
}
*(ulong *)env = crc32(0, env + sizeof(ulong), env_size - sizeof(ulong));
2007-07-05 16:01:38 +00:00
ret = dev_erase(info.device, info.size, info.start);
2007-07-05 16:01:26 +00:00
if (ret) {
printf("unable to erase\n");
goto err_out;
}
2007-07-05 16:01:38 +00:00
ret = dev_write(info.device, env, info.size, info.start, 0);
2007-07-05 16:01:26 +00:00
if (ret < 0) {
printf("unable to write\n");
goto err_out;
}
free(env);
return 0;
err_out:
if (env)
free(env);
return ret;
}
int do_printenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
struct variable_d *var = env_list->next;
if (argc == 2) {
char *val = getenv(argv[1]);
if (val) {
printf("%s=%s\n", argv[1], val);
return 0;
}
printf("## Error: \"%s\" not defined\n", argv[1]);
return -EINVAL;
}
while (var) {
printf("%s=%s\n", var_name(var), var_val(var));
var = var->next;
}
return 0;
}
U_BOOT_CMD(
printenv, CONFIG_MAXARGS, 1, do_printenv,
2007-07-05 16:01:26 +00:00
"printenv- print environment variables\n",
"\n - print values of all environment variables\n"
"printenv name ...\n"
" - print value of environment variable 'name'\n"
);
int do_setenv ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
if (argc < 2) {
printf ("Usage:\n%s\n", cmdtp->usage);
return 1;
}
setenv(argv[1], argv[2]);
return 0;
}
U_BOOT_CMD(
setenv, CONFIG_MAXARGS, 0, do_setenv,
2007-07-05 16:01:26 +00:00
"setenv - set environment variables\n",
"name value ...\n"
" - set environment variable 'name' to 'value ...'\n"
"setenv name\n"
" - delete environment variable 'name'\n"
);
int do_saveenv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
printf ("Saving Environment to %s...\n", env_name_spec);
return saveenv();
}
U_BOOT_CMD(
saveenv, 1, 0, do_saveenv,
"saveenv - save environment variables to persistent storage\n",
NULL
);