* [PATCH 1/2] add 'global' command
2012-05-14 7:24 [PATCH] global shell variables and more flexible bootargs Sascha Hauer
@ 2012-05-14 7:24 ` Sascha Hauer
2012-05-14 7:24 ` [PATCH 2/2] booting: more flexible Linux bootargs generation Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2012-05-14 7:24 UTC (permalink / raw)
To: barebox
This implements global shell variable support. This is done by registering
a new device named 'global', so global variables are just plain device
parameters.
Global variables are useful for storing the global state in the environment.
Currently we do this by sourcing scripts instead of executing them which is
quite limiting.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/Kconfig | 7 ++++++
commands/Makefile | 1 +
commands/global.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++
common/Kconfig | 7 ++++++
common/Makefile | 1 +
common/globalvar.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/globalvar.h | 12 ++++++++++
7 files changed, 155 insertions(+)
create mode 100644 commands/global.c
create mode 100644 common/globalvar.c
create mode 100644 include/globalvar.h
diff --git a/commands/Kconfig b/commands/Kconfig
index 49a56ca..1c15294 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -113,6 +113,13 @@ config CMD_LINUX_EXEC
help
This command executes a command on the Linux host.
+config CMD_GLOBAL
+ select GLOBALVAR
+ tristate
+ prompt "global"
+ help
+ The global command allows to create global variables
+
endmenu
menu "file commands "
diff --git a/commands/Makefile b/commands/Makefile
index f02b5ca..4c8a0a9 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -65,3 +65,4 @@ obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o
obj-$(CONFIG_CMD_IOMEM) += iomem.o
obj-$(CONFIG_CMD_LINUX_EXEC) += linux_exec.o
obj-$(CONFIG_CMD_AUTOMOUNT) += automount.o
+obj-$(CONFIG_CMD_GLOBAL) += global.o
diff --git a/commands/global.c b/commands/global.c
new file mode 100644
index 0000000..de6b13e
--- /dev/null
+++ b/commands/global.c
@@ -0,0 +1,62 @@
+/*
+ * global.c - global shell variables
+ *
+ * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <common.h>
+#include <malloc.h>
+#include <command.h>
+#include <globalvar.h>
+#include <environment.h>
+
+static int do_global(int argc, char *argv[])
+{
+ int ret;
+ char *value;
+
+ if (argc != 2)
+ return COMMAND_ERROR_USAGE;
+
+ value = strchr(argv[1], '=');
+ if (value) {
+ *value = 0;
+ value++;
+ }
+
+ ret = globalvar_add_simple(argv[1]);
+
+ if (value) {
+ char *name = asprintf("global.%s", argv[1]);
+ ret = setenv(name, value);
+ free(name);
+ }
+
+ return ret ? 1 : 0;
+}
+
+BAREBOX_CMD_HELP_START(global)
+BAREBOX_CMD_HELP_USAGE("global <var>[=<value]\n")
+BAREBOX_CMD_HELP_SHORT("add a new global variable named <var>, optionally set to <value>\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(global)
+ .cmd = do_global,
+ .usage = "create global variables",
+ BAREBOX_CMD_HELP(cmd_global_help)
+BAREBOX_CMD_END
diff --git a/common/Kconfig b/common/Kconfig
index 73d620a..81e3acb 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -47,6 +47,9 @@ config BINFMT
bool
select FILETYPE
+config GLOBALVAR
+ bool
+
menu "General Settings "
config LOCALVERSION
@@ -493,6 +496,7 @@ config DEFAULT_ENVIRONMENT_GENERIC
select HUSH_GETOPT
select CMD_CRC
select CMD_CRC_CMP
+ select CMD_AUTOMOUNT if HAVE_DEFAULT_ENVIRONMENT_NEW
prompt "Default environment generic"
help
With this option barebox will use the generic default
@@ -502,6 +506,9 @@ config DEFAULT_ENVIRONMENT_GENERIC
at least contain a /env/config file.
This will be able to overwrite the files from defaultenv.
+config HAVE_DEFAULT_ENVIRONMENT_NEW
+ bool
+
config DEFAULT_ENVIRONMENT_PATH
string
depends on DEFAULT_ENVIRONMENT
diff --git a/common/Makefile b/common/Makefile
index a58aef9..d842a2e 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_CMD_BOOTM) += uimage.o
obj-y += startup.o
obj-y += misc.o
obj-y += memsize.o
+obj-$(CONFIG_GLOBALVAR) += globalvar.o
obj-$(CONFIG_FILETYPE) += filetype.o
obj-y += resource.o
obj-$(CONFIG_MENU) += menu.o
diff --git a/common/globalvar.c b/common/globalvar.c
new file mode 100644
index 0000000..71296ff
--- /dev/null
+++ b/common/globalvar.c
@@ -0,0 +1,65 @@
+#include <common.h>
+#include <malloc.h>
+#include <globalvar.h>
+#include <init.h>
+
+static struct device_d global_device = {
+ .name = "global",
+ .id = DEVICE_ID_SINGLE,
+};
+
+int globalvar_add(const char *name,
+ int (*set)(struct device_d *dev, struct param_d *p, const char *val),
+ const char *(*get)(struct device_d *, struct param_d *p),
+ unsigned long flags)
+{
+ return dev_add_param(&global_device, name, set, get, flags);
+}
+
+/*
+ * globalvar_get_match
+ *
+ * get a concatenated string of all globalvars beginning with 'match'.
+ * This adds whitespaces between the different globalvars
+ */
+char *globalvar_get_match(const char *match, const char *seperator)
+{
+ char *val = NULL;
+ struct param_d *param;
+
+ list_for_each_entry(param, &global_device.parameters, list) {
+ if (!strncmp(match, param->name, strlen(match))) {
+ const char *p = dev_get_param(&global_device, param->name);
+ if (val) {
+ char *new = asprintf("%s%s%s", val, seperator, p);
+ free(val);
+ val = new;
+ } else {
+ val = xstrdup(p);
+ }
+ }
+ }
+
+ if (!val)
+ val = xstrdup("");
+
+ return val;
+}
+
+/*
+ * globalvar_add_simple
+ *
+ * add a new globalvar named 'name'
+ */
+int globalvar_add_simple(const char *name)
+{
+ return globalvar_add(name, NULL, NULL, 0);
+}
+
+static int globalvar_init(void)
+{
+ register_device(&global_device);
+
+ return 0;
+}
+postconsole_initcall(globalvar_init);
diff --git a/include/globalvar.h b/include/globalvar.h
new file mode 100644
index 0000000..7cc3976
--- /dev/null
+++ b/include/globalvar.h
@@ -0,0 +1,12 @@
+#ifndef __GLOBALVAR_H
+#define __GLOBALVAR_H
+
+int globalvar_add_simple(const char *name);
+
+int globalvar_add(const char *name,
+ int (*set)(struct device_d *dev, struct param_d *p, const char *val),
+ const char *(*get)(struct device_d *, struct param_d *p),
+ unsigned long flags);
+char *globalvar_get_match(const char *match, const char *seperator);
+
+#endif /* __GLOBALVAR_H */
--
1.7.10
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 2/2] booting: more flexible Linux bootargs generation
2012-05-14 7:24 [PATCH] global shell variables and more flexible bootargs Sascha Hauer
2012-05-14 7:24 ` [PATCH 1/2] add 'global' command Sascha Hauer
@ 2012-05-14 7:24 ` Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2012-05-14 7:24 UTC (permalink / raw)
To: barebox
We currently use the environment variable 'bootargs' to get the
Linux bootargs. This patch allows for a more flexible bootargs
generation using global variables. With it the Linux bootargs
are concatenated from multiple variables. This allows to replace
parts of the bootargs string without having to reconstruct it
completely.
With this bootargs can be constructed like:
global linux.bootargs.base="console=ttyS0,115200"
global linux.bootargs.ip="ip=dhcp"
global linux.mtdparts="physmap-flash.0:512K(nor0.barebox),-(root)"
This will then automatically be combined into a kernel bootargs
string during boot.
If the 'linux.bootargs.' variables are all empty the old standard
'bootargs' way will be used.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/lib/armlinux.c | 2 +-
arch/arm/lib/bootm.c | 3 +-
arch/blackfin/lib/blackfin_linux.c | 2 +-
arch/nios2/lib/bootm.c | 2 +-
commands/Kconfig | 12 ++++++
commands/linux16.c | 2 +-
common/Makefile | 1 +
common/bootargs.c | 79 ++++++++++++++++++++++++++++++++++++
common/oftree.c | 3 +-
include/boot.h | 16 ++++++++
10 files changed, 116 insertions(+), 6 deletions(-)
create mode 100644 common/bootargs.c
diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c
index a167036..9f9dea8 100644
--- a/arch/arm/lib/armlinux.c
+++ b/arch/arm/lib/armlinux.c
@@ -227,7 +227,7 @@ static void setup_end_tag (void)
static void setup_tags(unsigned long initrd_address,
unsigned long initrd_size, int swap)
{
- const char *commandline = getenv("bootargs");
+ const char *commandline = linux_bootargs_get();
setup_start_tag();
setup_memory_tags();
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index c4a50c3..033e2eb 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -394,7 +394,7 @@ static int do_bootm_aimage(struct image_data *data)
}
if (!getenv("aimage_noverwrite_bootargs"))
- setenv("bootargs", header->cmdline);
+ linux_bootargs_overwrite(header->cmdline);
if (!getenv("aimage_noverwrite_tags"))
armlinux_set_bootparams((void*)header->tags_addr);
@@ -432,6 +432,7 @@ static int do_bootm_aimage(struct image_data *data)
return __do_bootm_linux(data, 0);
err_out:
+ linux_bootargs_overwrite(NULL);
close(fd);
return ret;
diff --git a/arch/blackfin/lib/blackfin_linux.c b/arch/blackfin/lib/blackfin_linux.c
index 458d1b1..7798bbd 100644
--- a/arch/blackfin/lib/blackfin_linux.c
+++ b/arch/blackfin/lib/blackfin_linux.c
@@ -43,7 +43,7 @@
static int do_bootm_linux(struct image_data *idata)
{
int (*appl)(char *cmdline);
- const char *cmdline = getenv("bootargs");
+ const char *cmdline = linux_bootargs_get();
char *cmdlinedest = (char *) CMD_LINE_ADDR;
if (!idata->os_res)
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index 1cd43c8..5713a89 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -39,7 +39,7 @@
static int do_bootm_linux(struct image_data *idata)
{
void (*kernel)(int, int, int, const char *);
- const char *commandline = getenv ("bootargs");
+ const char *commandline = linux_bootargs_get();
if (!idata->os_res)
return -EINVAL;
diff --git a/commands/Kconfig b/commands/Kconfig
index 1c15294..1839538 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -396,6 +396,18 @@ config CMD_BOOTU
compile in the 'bootu' command to start raw (uncompressed)
Linux images
+config FLEXIBLE_BOOTARGS
+ bool
+ prompt "flexible Linux bootargs generation"
+ depends on CMD_GLOBAL
+ help
+ Select this to get a more flexible bootargs generation. With this
+ option the bootargs are concatenated together from global variables
+ beginning with 'global.linux.bootargs.' and 'global.linux.mtdparts.'
+ This allows for more flexible scripting since with it it's possible
+ to replace parts of the bootargs string without reconstructing it
+ completely
+
config CMD_LINUX16
tristate
depends on X86
diff --git a/commands/linux16.c b/commands/linux16.c
index 20413b6..eccafa8 100644
--- a/commands/linux16.c
+++ b/commands/linux16.c
@@ -162,7 +162,7 @@ static int do_linux16(int argc, char *argv[])
unsigned real_mode_size;
int vid_mode = NORMAL_VGA;
size_t image_size;
- const char *cmdline = getenv("bootargs");
+ const char *cmdline = linux_bootargs_get();
const char *kernel_file;
while((opt = getopt(argc, argv, "v:")) > 0) {
diff --git a/common/Makefile b/common/Makefile
index d842a2e..b49e6e0 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -35,6 +35,7 @@ obj-y += resource.o
obj-$(CONFIG_MENU) += menu.o
obj-$(CONFIG_PASSWORD) += password.o
obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_FLEXIBLE_BOOTARGS) += bootargs.o
extra-$(CONFIG_MODULES) += module.lds
ifdef CONFIG_DEFAULT_ENVIRONMENT
diff --git a/common/bootargs.c b/common/bootargs.c
new file mode 100644
index 0000000..b17e6d1
--- /dev/null
+++ b/common/bootargs.c
@@ -0,0 +1,79 @@
+/*
+ * bootargs.c - concatenate Linux bootargs
+ *
+ * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <common.h>
+#include <boot.h>
+#include <malloc.h>
+#include <globalvar.h>
+#include <environment.h>
+
+static char *linux_bootargs;
+static int linux_bootargs_overwritten;
+
+/*
+ * This returns the Linux bootargs
+ *
+ * There are two ways to handle bootargs. The old legacy way is to use the
+ * 'bootargs' environment variable. The new and more flexible way is to use
+ * global variables beginning with "global.linux.bootargs." and
+ * "global.linux.mtdparts.". These variables will be concatenated together to
+ * the resulting bootargs. If there are no "global.linux.bootargs." variables
+ * we fall back to "bootargs"
+ */
+const char *linux_bootargs_get(void)
+{
+ char *bootargs, *mtdparts;
+
+ if (linux_bootargs_overwritten)
+ return linux_bootargs;
+
+ free(linux_bootargs);
+
+ bootargs = globalvar_get_match("linux.bootargs.", " ");
+ if (!strlen(bootargs))
+ return getenv("bootargs");
+
+ mtdparts = globalvar_get_match("linux.mtdparts.", ";");
+
+ if (strlen(mtdparts)) {
+ linux_bootargs = asprintf("%s mtdparts=%s", bootargs, mtdparts);
+ free(bootargs);
+ free(mtdparts);
+ } else {
+ free(mtdparts);
+ linux_bootargs = bootargs;
+ }
+
+ return linux_bootargs;
+}
+
+int linux_bootargs_overwrite(const char *bootargs)
+{
+ if (bootargs) {
+ free(linux_bootargs);
+ linux_bootargs = xstrdup(bootargs);
+ linux_bootargs_overwritten = 1;
+ } else {
+ linux_bootargs_overwritten = 0;
+ }
+
+ return 0;
+}
diff --git a/common/oftree.c b/common/oftree.c
index a657d31..49758a9 100644
--- a/common/oftree.c
+++ b/common/oftree.c
@@ -11,6 +11,7 @@
#include <errno.h>
#include <getopt.h>
#include <init.h>
+#include <boot.h>
#define MAX_LEVEL 32 /* how deeply nested we will go */
@@ -257,7 +258,7 @@ static int of_fixup_bootargs(struct fdt_header *fdt)
if (nodeoffset < 0)
return nodeoffset;
- str = getenv("bootargs");
+ str = linux_bootargs_get();
if (str) {
err = fdt_setprop(fdt, nodeoffset,
"bootargs", str, strlen(str)+1);
diff --git a/include/boot.h b/include/boot.h
index a17bf25..3ce0de1 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -5,6 +5,7 @@
#include <filetype.h>
#include <of.h>
#include <linux/list.h>
+#include <environment.h>
struct image_data {
/* simplest case. barebox has already loaded the os here */
@@ -71,4 +72,19 @@ static inline int bootm_verbose(struct image_data *data)
}
#endif
+#ifdef CONFIG_FLEXIBLE_BOOTARGS
+const char *linux_bootargs_get(void);
+int linux_bootargs_overwrite(const char *bootargs);
+#else
+static inline const char *linux_bootargs_get(void)
+{
+ return getenv("bootargs");
+}
+
+static inline int linux_bootargs_overwrite(const char *bootargs)
+{
+ return setenv("bootargs", bootargs);
+}
+#endif
+
#endif /* __BOOT_H */
--
1.7.10
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply [flat|nested] 3+ messages in thread