]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/env_common.c
x86: Add CBMEM console driver for coreboot
[karo-tx-uboot.git] / common / env_common.c
index 77f99441a1cc1d20b986d9cb36776cfcd60d1bf6..3d3cb70a6d60a21de660a20b260a20c447270ed9 100644 (file)
@@ -1,10 +1,10 @@
 /*
- * (C) Copyright 2000-2002
+ * (C) Copyright 2000-2010
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  * Andreas Heppel <aheppel@sysgo.de>
-
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
 #include <command.h>
 #include <environment.h>
 #include <linux/stddef.h>
+#include <search.h>
+#include <errno.h>
 #include <malloc.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-#ifdef CONFIG_AMIGAONEG3SE
-       extern void enable_nvram(void);
-       extern void disable_nvram(void);
-#endif
-
-#undef DEBUG_ENV
-#ifdef DEBUG_ENV
-#define DEBUGF(fmt,args...) printf(fmt ,##args)
-#else
-#define DEBUGF(fmt,args...)
-#endif
-
-extern env_t *env_ptr;
-
-extern void env_relocate_spec (void);
-extern uchar env_get_char_spec(int);
-
-static uchar env_get_char_init (int index);
-
 /************************************************************************
  * Default settings to be used when no valid environment is found
  */
-#define XMK_STR(x)     #x
-#define MK_STR(x)      XMK_STR(x)
+#include <env_default.h>
 
-uchar default_environment[] = {
-#ifdef CONFIG_BOOTARGS
-       "bootargs="     CONFIG_BOOTARGS                 "\0"
-#endif
-#ifdef CONFIG_BOOTCOMMAND
-       "bootcmd="      CONFIG_BOOTCOMMAND              "\0"
-#endif
-#ifdef CONFIG_RAMBOOTCOMMAND
-       "ramboot="      CONFIG_RAMBOOTCOMMAND           "\0"
-#endif
-#ifdef CONFIG_NFSBOOTCOMMAND
-       "nfsboot="      CONFIG_NFSBOOTCOMMAND           "\0"
-#endif
-#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
-       "bootdelay="    MK_STR(CONFIG_BOOTDELAY)        "\0"
-#endif
-#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
-       "baudrate="     MK_STR(CONFIG_BAUDRATE)         "\0"
-#endif
-#ifdef CONFIG_LOADS_ECHO
-       "loads_echo="   MK_STR(CONFIG_LOADS_ECHO)       "\0"
-#endif
-#ifdef CONFIG_ETHADDR
-       "ethaddr="      MK_STR(CONFIG_ETHADDR)          "\0"
-#endif
-#ifdef CONFIG_ETH1ADDR
-       "eth1addr="     MK_STR(CONFIG_ETH1ADDR)         "\0"
-#endif
-#ifdef CONFIG_ETH2ADDR
-       "eth2addr="     MK_STR(CONFIG_ETH2ADDR)         "\0"
-#endif
-#ifdef CONFIG_ETH3ADDR
-       "eth3addr="     MK_STR(CONFIG_ETH3ADDR)         "\0"
-#endif
-#ifdef CONFIG_IPADDR
-       "ipaddr="       MK_STR(CONFIG_IPADDR)           "\0"
-#endif
-#ifdef CONFIG_SERVERIP
-       "serverip="     MK_STR(CONFIG_SERVERIP)         "\0"
-#endif
-#ifdef CFG_AUTOLOAD
-       "autoload="     CFG_AUTOLOAD                    "\0"
-#endif
-#ifdef CONFIG_PREBOOT
-       "preboot="      CONFIG_PREBOOT                  "\0"
-#endif
-#ifdef CONFIG_ROOTPATH
-       "rootpath="     MK_STR(CONFIG_ROOTPATH)         "\0"
-#endif
-#ifdef CONFIG_GATEWAYIP
-       "gatewayip="    MK_STR(CONFIG_GATEWAYIP)        "\0"
-#endif
-#ifdef CONFIG_NETMASK
-       "netmask="      MK_STR(CONFIG_NETMASK)          "\0"
-#endif
-#ifdef CONFIG_HOSTNAME
-       "hostname="     MK_STR(CONFIG_HOSTNAME)         "\0"
-#endif
-#ifdef CONFIG_BOOTFILE
-       "bootfile="     MK_STR(CONFIG_BOOTFILE)         "\0"
-#endif
-#ifdef CONFIG_LOADADDR
-       "loadaddr="     MK_STR(CONFIG_LOADADDR)         "\0"
-#endif
-#ifdef  CONFIG_CLOCKS_IN_MHZ
-       "clocks_in_mhz=1\0"
-#endif
-#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0)
-       "pcidelay="     MK_STR(CONFIG_PCI_BOOTDELAY)    "\0"
-#endif
-#ifdef  CONFIG_EXTRA_ENV_SETTINGS
-       CONFIG_EXTRA_ENV_SETTINGS
-#endif
-       "\0"
+struct hsearch_data env_htab = {
+       .apply = env_check_apply,
 };
 
-#if defined(CONFIG_ENV_IS_IN_NAND)             /* Environment is in Nand Flash */ \
-       || defined(CONFIG_ENV_IS_IN_SPI_FLASH)
-int default_environment_size = sizeof(default_environment);
-#endif
-
-void env_crc_update (void)
+static uchar __env_get_char_spec(int index)
 {
-       env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE);
+       return *((uchar *)(gd->env_addr + index));
 }
+uchar env_get_char_spec(int)
+       __attribute__((weak, alias("__env_get_char_spec")));
 
-static uchar env_get_char_init (int index)
+static uchar env_get_char_init(int index)
 {
-       uchar c;
-
        /* if crc was bad, use the default environment */
        if (gd->env_valid)
-       {
-               c = env_get_char_spec(index);
-       } else {
-               c = default_environment[index];
-       }
-
-       return (c);
+               return env_get_char_spec(index);
+       else
+               return default_environment[index];
 }
 
-#ifdef CONFIG_AMIGAONEG3SE
-uchar env_get_char_memory (int index)
-{
-       uchar retval;
-       enable_nvram();
-       if (gd->env_valid) {
-               retval = ( *((uchar *)(gd->env_addr + index)) );
-       } else {
-               retval = ( default_environment[index] );
-       }
-       disable_nvram();
-       return retval;
-}
-#else
-uchar env_get_char_memory (int index)
+uchar env_get_char_memory(int index)
 {
-       if (gd->env_valid) {
-               return ( *((uchar *)(gd->env_addr + index)) );
-       } else {
-               return ( default_environment[index] );
-       }
+       return *env_get_addr(index);
 }
-#endif
 
-uchar env_get_char (int index)
+uchar env_get_char(int index)
 {
-       uchar c;
-
        /* if relocated to RAM */
        if (gd->flags & GD_FLG_RELOC)
-               c = env_get_char_memory(index);
+               return env_get_char_memory(index);
        else
-               c = env_get_char_init(index);
-
-       return (c);
+               return env_get_char_init(index);
 }
 
-uchar *env_get_addr (int index)
+const uchar *env_get_addr(int index)
 {
-       if (gd->env_valid) {
-               return ( ((uchar *)(gd->env_addr + index)) );
-       } else {
-               return (&default_environment[index]);
-       }
+       if (gd->env_valid)
+               return (uchar *)(gd->env_addr + index);
+       else
+               return &default_environment[index];
 }
 
-void set_default_env(void)
+void set_default_env(const char *s)
 {
+       /*
+        * By default, do not apply changes as they will eventually
+        * be applied by someone else
+        */
+       int do_apply = 0;
        if (sizeof(default_environment) > ENV_SIZE) {
-               puts ("*** Error - default environment is too large\n\n");
+               puts("*** Error - default environment is too large\n\n");
                return;
        }
 
-       memset(env_ptr, 0, sizeof(env_t));
-       memcpy(env_ptr->data, default_environment,
-              sizeof(default_environment));
-#ifdef CFG_REDUNDAND_ENVIRONMENT
-       env_ptr->flags = 0xFF;
-#endif
-       env_crc_update ();
-       gd->env_valid = 1;
-}
+       if (s) {
+               if (*s == '!') {
+                       printf("*** Warning - %s, "
+                               "using default environment\n\n",
+                               s + 1);
+               } else {
+                       /*
+                        * This set_to_default was explicitly asked for
+                        * by the user, as opposed to being a recovery
+                        * mechanism.  Therefore we check every single
+                        * variable and apply changes to the system
+                        * right away (e.g. baudrate, console).
+                        */
+                       do_apply = 1;
+                       puts(s);
+               }
+       } else {
+               puts("Using default environment\n\n");
+       }
 
-void env_relocate (void)
-{
-       DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__,
-               gd->reloc_off);
+       if (himport_r(&env_htab, (char *)default_environment,
+                       sizeof(default_environment), '\0', 0,
+                       0, NULL, do_apply) == 0)
+               error("Environment import failed: errno = %d\n", errno);
 
-#ifdef CONFIG_AMIGAONEG3SE
-       enable_nvram();
-#endif
+       gd->flags |= GD_FLG_ENV_READY;
+}
 
-#ifdef ENV_IS_EMBEDDED
-       /*
-        * The environment buffer is embedded with the text segment,
-        * just relocate the environment pointer
-        */
-       env_ptr = (env_t *)((ulong)env_ptr + gd->reloc_off);
-       DEBUGF ("%s[%d] embedded ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
-#else
+
+/* [re]set individual variables to their value in the default environment */
+int set_default_vars(int nvars, char * const vars[])
+{
        /*
-        * We must allocate a buffer for the environment
+        * Special use-case: import from default environment
+        * (and use \0 as a separator)
         */
-       env_ptr = (env_t *)malloc (CONFIG_ENV_SIZE);
-       DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
+       return himport_r(&env_htab, (const char *)default_environment,
+                               sizeof(default_environment), '\0', H_NOCLEAR,
+                               nvars, vars, 1 /* do_apply */);
+}
+
+#ifndef CONFIG_SPL_BUILD
+/*
+ * Check if CRC is valid and (if yes) import the environment.
+ * Note that "buf" may or may not be aligned.
+ */
+int env_import(const char *buf, int check)
+{
+       env_t *ep = (env_t *)buf;
+
+       if (check) {
+               uint32_t crc;
+
+               memcpy(&crc, &ep->crc, sizeof(crc));
+
+               if (crc32(0, ep->data, ENV_SIZE) != crc) {
+                       set_default_env("!bad CRC");
+                       return 0;
+               }
+       }
+
+       if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0,
+                       0, NULL, 0 /* do_apply */)) {
+               gd->flags |= GD_FLG_ENV_READY;
+               return 1;
+       }
+
+       error("Cannot import environment: errno = %d\n", errno);
+
+       set_default_env("!import failed");
+
+       return 0;
+}
 #endif
 
+void env_relocate(void)
+{
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
+       env_reloc();
+#endif
        if (gd->env_valid == 0) {
-#if defined(CONFIG_GTH)        || defined(CONFIG_ENV_IS_NOWHERE)       /* Environment not changable */
-               puts ("Using default environment\n\n");
+#if defined(CONFIG_ENV_IS_NOWHERE) || defined(CONFIG_SPL_BUILD)
+               /* Environment not changable */
+               set_default_env(NULL);
 #else
-               puts ("*** Warning - bad CRC, using default environment\n\n");
-               show_boot_progress (-60);
+               bootstage_error(BOOTSTAGE_ID_NET_CHECKSUM);
+               set_default_env("!bad CRC");
 #endif
-               set_default_env();
-       }
-       else {
-               env_relocate_spec ();
+       } else {
+               env_relocate_spec();
        }
-       gd->env_addr = (ulong)&(env_ptr->data);
-
-#ifdef CONFIG_AMIGAONEG3SE
-       disable_nvram();
-#endif
 }
 
-#ifdef CONFIG_AUTO_COMPLETE
+#if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD)
 int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf)
 {
-       int i, nxt, len, vallen, found;
-       const char *lval, *rval;
+       ENTRY *match;
+       int found, idx;
 
+       idx = 0;
        found = 0;
        cmdv[0] = NULL;
 
-       len = strlen(var);
-       /* now iterate over the variables and select those that match */
-       for (i=0; env_get_char(i) != '\0'; i=nxt+1) {
-
-               for (nxt=i; env_get_char(nxt) != '\0'; ++nxt)
-                       ;
+       while ((idx = hmatch_r(var, idx, &match, &env_htab))) {
+               int vallen = strlen(match->key) + 1;
 
-               lval = (char *)env_get_addr(i);
-               rval = strchr(lval, '=');
-               if (rval != NULL) {
-                       vallen = rval - lval;
-                       rval++;
-               } else
-                       vallen = strlen(lval);
-
-               if (len > 0 && (vallen < len || memcmp(lval, var, len) != 0))
-                       continue;
-
-               if (found >= maxv - 2 || bufsz < vallen + 1) {
-                       cmdv[found++] = "...";
+               if (found >= maxv - 2 || bufsz < vallen)
                        break;
-               }
+
                cmdv[found++] = buf;
-               memcpy(buf, lval, vallen); buf += vallen; bufsz -= vallen;
-               *buf++ = '\0'; bufsz--;
+               memcpy(buf, match->key, vallen);
+               buf += vallen;
+               bufsz -= vallen;
        }
 
+       qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar);
+
+       if (idx)
+               cmdv[found++] = "...";
+
        cmdv[found] = NULL;
        return found;
 }