2007-07-05 16:01:26 +00:00
|
|
|
#include <common.h>
|
|
|
|
#include <command.h>
|
|
|
|
#include <driver.h>
|
|
|
|
#include <malloc.h>
|
2007-07-05 16:01:47 +00:00
|
|
|
#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(
|
2007-07-05 16:01:33 +00:00
|
|
|
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(
|
2007-07-05 16:01:33 +00:00
|
|
|
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
|
|
|
|
);
|
|
|
|
|