summaryrefslogtreecommitdiffstats
path: root/common/env.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:01:26 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:01:26 +0200
commit8945b0589efd1d1b19bb1b380fb4e1b3f37b1b15 (patch)
treeb7dde7d034cad2bbc4be7b3c867523372c7cb657 /common/env.c
parent5d23db21756e12a159d4af5d9c59fb1e4ba1e048 (diff)
downloadbarebox-8945b0589efd1d1b19bb1b380fb4e1b3f37b1b15.tar.gz
svn_rev_137
new env functions
Diffstat (limited to 'common/env.c')
-rw-r--r--common/env.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/common/env.c b/common/env.c
new file mode 100644
index 0000000..241110f
--- /dev/null
+++ b/common/env.c
@@ -0,0 +1,296 @@
+#include <common.h>
+#include <command.h>
+#include <driver.h>
+#include <malloc.h>
+#include <asm-generic/errno.h>
+
+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)
+{
+ return &var->data[strlen(var->data) + 2];
+}
+
+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);
+ strcpy(&newvar->data[strlen(name) + 2], value);
+ 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;
+
+ err = read(info.device, env, env_size, info.start, 0);
+ 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));
+
+ ret = erase(info.device, info.size, info.start);
+ if (ret) {
+ printf("unable to erase\n");
+ goto err_out;
+ }
+
+ ret = write(info.device, env, info.size, info.start, 0);
+ 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, CFG_MAXARGS, 1, do_printenv,
+ "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, CFG_MAXARGS, 0, do_setenv,
+ "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
+);
+