aboutsummaryrefslogtreecommitdiff
path: root/common/hwconfig.c
diff options
context:
space:
mode:
authorKumar Gala2011-01-09 11:37:00 -0600
committerKumar Gala2011-01-19 22:58:23 -0600
commitdd50af2515ad39fa2f6c09ab621f69fef4f5fceb (patch)
tree53efcd705316bc268507d110e26d9712f9fae17f /common/hwconfig.c
parentf193e3da9817dc4892bc25967954d98838f84386 (diff)
powerpc/8xxx: Add hwconfig APIs to address early parsing used by DDR init
There are several users of the hwconfig APIs (8xxx DDR) before we have the environment properly setup. This causes issues because of the numerous ways the environment might be accessed because of the non-volatile memory it might be stored in. Additionally the access might be so early that memory isn't even properly setup for us. Towards resolving these issues we provide versions of all the hwconfig APIs that can be passed in a buffer to parse and leave it to the caller to determine how to allocate and populate the buffer. We use the _f naming convention for these new APIs even though they are perfectly useable after relocation and the environment being ready. We also now warn if the non-f APIs are called before the environment is ready to allow users to address the issues. Finally, we convert the 8xxx DDR code to utilize the new APIs to hopefully address the issue once and for all. We have the 8xxx DDR code create a buffer on the stack and populate it via getenv_f(). Signed-off-by: Kumar Gala <galak@kernel.crashing.org> Acked-by: Wolfgang Denk <wd@denx.de>
Diffstat (limited to 'common/hwconfig.c')
-rw-r--r--common/hwconfig.c86
1 files changed, 44 insertions, 42 deletions
diff --git a/common/hwconfig.c b/common/hwconfig.c
index 193863a9701..515074808dd 100644
--- a/common/hwconfig.c
+++ b/common/hwconfig.c
@@ -2,6 +2,7 @@
* An inteface for configuring a hardware via u-boot environment.
*
* Copyright (c) 2009 MontaVista Software, Inc.
+ * Copyright 2011 Freescale Semiconductor, Inc.
*
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
*
@@ -71,25 +72,19 @@ next:
const char cpu_hwconfig[] __attribute__((weak)) = "";
const char board_hwconfig[] __attribute__((weak)) = "";
-#define HWCONFIG_PRE_RELOC_BUF_SIZE 128
-
-static const char *__hwconfig(const char *opt, size_t *arglen)
+static const char *__hwconfig(const char *opt, size_t *arglen,
+ const char *env_hwconfig)
{
- const char *env_hwconfig = NULL, *ret;
- char buf[HWCONFIG_PRE_RELOC_BUF_SIZE];
+ const char *ret;
- if (gd->flags & GD_FLG_ENV_READY) {
+ /* if we are passed a buffer use it, otherwise try the environment */
+ if (!env_hwconfig) {
+ if (!(gd->flags & GD_FLG_ENV_READY)) {
+ printf("WARNING: Calling __hwconfig without a buffer "
+ "and before environment is ready\n");
+ return NULL;
+ }
env_hwconfig = getenv("hwconfig");
- } else {
- /*
- * Use our own on stack based buffer before relocation to allow
- * accessing longer hwconfig strings that might be in the
- * environment before we've relocated. This is pretty fragile
- * on both the use of stack and if the buffer is big enough.
- * However we will get a warning from getenv_f for the later.
- */
- if ((getenv_f("hwconfig", buf, sizeof(buf))) > 0)
- env_hwconfig = buf;
}
if (env_hwconfig) {
@@ -109,8 +104,9 @@ static const char *__hwconfig(const char *opt, size_t *arglen)
}
/*
- * hwconfig - query if a particular hwconfig option is specified
+ * hwconfig_f - query if a particular hwconfig option is specified
* @opt: a string representing an option
+ * @buf: if non-NULL use this buffer to parse, otherwise try env
*
* This call can be used to find out whether U-Boot should configure
* a particular hardware option.
@@ -127,34 +123,36 @@ static const char *__hwconfig(const char *opt, size_t *arglen)
* that the board file only calls things that are actually used, so
* hwconfig() will always return true result.
*/
-int hwconfig(const char *opt)
+int hwconfig_f(const char *opt, char *buf)
{
- return !!__hwconfig(opt, NULL);
+ return !!__hwconfig(opt, NULL, buf);
}
/*
- * hwconfig_arg - get hwconfig option's argument
+ * hwconfig_arg_f - get hwconfig option's argument
* @opt: a string representing an option
* @arglen: a pointer to an allocated size_t variable
+ * @buf: if non-NULL use this buffer to parse, otherwise try env
*
- * Unlike hwconfig() function, this function returns a pointer to the
+ * Unlike hwconfig_f() function, this function returns a pointer to the
* start of the hwconfig arguments, if option is not found or it has
* no specified arguments, the function returns NULL pointer.
*
* If CONFIG_HWCONFIG is undefined, the function returns "", and
* arglen is set to 0.
*/
-const char *hwconfig_arg(const char *opt, size_t *arglen)
+const char *hwconfig_arg_f(const char *opt, size_t *arglen, char *buf)
{
- return __hwconfig(opt, arglen);
+ return __hwconfig(opt, arglen, buf);
}
/*
- * hwconfig_arg_cmp - compare hwconfig option's argument
+ * hwconfig_arg_cmp_f - compare hwconfig option's argument
* @opt: a string representing an option
* @arg: a string for comparing an option's argument
+ * @buf: if non-NULL use this buffer to parse, otherwise try env
*
- * This call is similar to hwconfig_arg, but instead of returning
+ * This call is similar to hwconfig_arg_f, but instead of returning
* hwconfig argument and its length, it is comparing it to @arg.
*
* Returns non-zero value if @arg matches, 0 otherwise.
@@ -162,12 +160,12 @@ const char *hwconfig_arg(const char *opt, size_t *arglen)
* If CONFIG_HWCONFIG is undefined, the function returns a non-zero
* value, i.e. the argument matches.
*/
-int hwconfig_arg_cmp(const char *opt, const char *arg)
+int hwconfig_arg_cmp_f(const char *opt, const char *arg, char *buf)
{
const char *argstr;
size_t arglen;
- argstr = hwconfig_arg(opt, &arglen);
+ argstr = hwconfig_arg_f(opt, &arglen, buf);
if (!argstr || arglen != strlen(arg))
return 0;
@@ -175,63 +173,67 @@ int hwconfig_arg_cmp(const char *opt, const char *arg)
}
/*
- * hwconfig_sub - query if a particular hwconfig sub-option is specified
+ * hwconfig_sub_f - query if a particular hwconfig sub-option is specified
* @opt: a string representing an option
* @subopt: a string representing a sub-option
+ * @buf: if non-NULL use this buffer to parse, otherwise try env
*
- * This call is similar to hwconfig(), except that it takes additional
+ * This call is similar to hwconfig_f(), except that it takes additional
* argument @subopt. In this example:
* "dr_usb:mode=peripheral"
* "dr_usb" is an option, "mode" is a sub-option, and "peripheral" is its
* argument.
*/
-int hwconfig_sub(const char *opt, const char *subopt)
+int hwconfig_sub_f(const char *opt, const char *subopt, char *buf)
{
size_t arglen;
const char *arg;
- arg = __hwconfig(opt, &arglen);
+ arg = __hwconfig(opt, &arglen, buf);
if (!arg)
return 0;
return !!hwconfig_parse(arg, arglen, subopt, ",;", '=', NULL);
}
/*
- * hwconfig_subarg - get hwconfig sub-option's argument
+ * hwconfig_subarg_f - get hwconfig sub-option's argument
* @opt: a string representing an option
* @subopt: a string representing a sub-option
* @subarglen: a pointer to an allocated size_t variable
+ * @buf: if non-NULL use this buffer to parse, otherwise try env
*
- * This call is similar to hwconfig_arg(), except that it takes an additional
- * argument @subopt, and so works with sub-options.
+ * This call is similar to hwconfig_arg_f(), except that it takes an
+ * additional argument @subopt, and so works with sub-options.
*/
-const char *hwconfig_subarg(const char *opt, const char *subopt,
- size_t *subarglen)
+const char *hwconfig_subarg_f(const char *opt, const char *subopt,
+ size_t *subarglen, char *buf)
{
size_t arglen;
const char *arg;
- arg = __hwconfig(opt, &arglen);
+ arg = __hwconfig(opt, &arglen, buf);
if (!arg)
return NULL;
return hwconfig_parse(arg, arglen, subopt, ",;", '=', subarglen);
}
/*
- * hwconfig_arg_cmp - compare hwconfig sub-option's argument
+ * hwconfig_arg_cmp_f - compare hwconfig sub-option's argument
* @opt: a string representing an option
* @subopt: a string representing a sub-option
* @subarg: a string for comparing an sub-option's argument
+ * @buf: if non-NULL use this buffer to parse, otherwise try env
*
- * This call is similar to hwconfig_arg_cmp, except that it takes an additional
- * argument @subopt, and so works with sub-options.
+ * This call is similar to hwconfig_arg_cmp_f, except that it takes an
+ * additional argument @subopt, and so works with sub-options.
*/
-int hwconfig_subarg_cmp(const char *opt, const char *subopt, const char *subarg)
+int hwconfig_subarg_cmp_f(const char *opt, const char *subopt,
+ const char *subarg, char *buf)
{
const char *argstr;
size_t arglen;
- argstr = hwconfig_subarg(opt, subopt, &arglen);
+ argstr = hwconfig_subarg_f(opt, subopt, &arglen, buf);
if (!argstr || arglen != strlen(subarg))
return 0;