9
0
Fork 0

Merge branch 'for-next/persistent-vars'

Conflicts:
	arch/arm/boards/efika-mx-smartbook/defaultenv-efikasb/config
This commit is contained in:
Sascha Hauer 2014-12-08 14:54:09 +01:00
commit 3eade89c75
90 changed files with 877 additions and 334 deletions

View File

@ -25,6 +25,47 @@ other variable. You can also directly assign a value during creation::
to assigning a value with ``global.myvar1=foobar``, but the latter fails when
a variable has not been created before.
.. _config_device:
Non volatile variables
----------------------
Additionally to global variables barebox also has non volatile (nv) variables.
Unlike the global variables the config variables are persistent over reboots.
Each nv variable is linked with the global variable of the same name.
Whenever the nv variable changes its value the corresponding global
variable also changes its value. The other way round though is not true:
Changing a global variable does not change the corresponding nv variable.
This means that changing a global variable changes the behaviour for the
currently running barebox, while changing a nv variable changes the
behaviour persistently over reboots.
nv variables can be created or removed with the :ref:`command_nv`
command. The nv variables are made persistent using the environment
facilities of barebox, so a :ref:`saveenv` must be issued to store the actual
values.
examples:
.. code-block:: sh
barebox@Phytec phyCARD-i.MX27:/ devinfo nv
barebox@Phytec phyCARD-i.MX27:/ nv model=myboard
barebox@myboard:/ devinfo nv
Parameters:
model: myboard
barebox@myboard:/ devinfo global
Parameters:
[...]
model: myboard
[...]
barebox@myboard:/ global.model=yourboard
barebox@yourboard:/ devinfo nv
Parameters:
model: myboard
barebox@yourboard:/
.. _magicvars:
Magic variables

View File

@ -1,5 +1,9 @@
#!/bin/sh
if [ -n "$nv.boot.default" ]; then
exit
fi
if [ -f /mnt/sd/zImage ]; then
global.boot.default=sd-card-linux
elif [ -f /mnt/sd/android ]; then

View File

@ -1,19 +0,0 @@
#!/bin/sh
# change network settings in /env/network/eth0
# change mtd partition settings and automountpoints in /env/init/*
# set to false if you do not want to have colors
global.allow_color=true
# user (used for network filenames)
global.user=none
# timeout in seconds before the default boot entry is started
global.autoboot_timeout=3
# default boot entry (one of /env/boot/*)
global.boot.default=android
# base bootargs
#global.linux.bootargs.base="console=ttyS0,115200"

View File

@ -1,8 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.hostname=at91sam9m10ihd
global.linux.bootargs.base="console=ttyS0,115200"
global.boot.default=android

View File

@ -0,0 +1 @@
android

View File

@ -0,0 +1 @@
at91sam9m10ihd

View File

@ -0,0 +1 @@
console=ttyS0,115200

View File

@ -1,6 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.linux.bootargs.base="console=ttyPS1,115200"

View File

@ -0,0 +1 @@
console=ttyPS1,115200

View File

@ -1,6 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.linux.bootargs.base="console=ttyO2,115200"

View File

@ -0,0 +1 @@
console=ttyO2,115200

View File

@ -1,10 +0,0 @@
#!/bin/sh
# Timeout in seconds before the default boot entry is started
global.autoboot_timeout=2
# Default boot entry (one of /env/boot/*)
global.boot.default=nand
# Board bootargs
global.linux.bootargs.base="earlyprintk console=ttymxc0,115200n8"

View File

@ -0,0 +1 @@
2

View File

@ -0,0 +1 @@
nand

View File

@ -0,0 +1 @@
earlyprintk console=ttymxc0,115200n8

View File

@ -1,12 +0,0 @@
#!/bin/sh
# Timeout in seconds before the default boot entry is started
global.autoboot_timeout=2
# Default boot entry (one of /env/boot/*)
if [ -e /dev/nor0 ]; then
global.boot.default=nor
fi
# Board bootargs
global.linux.bootargs.base="earlyprintk console=ttyCL0,57600n8"

View File

@ -0,0 +1,9 @@
#!/bin/sh
if [ -n "$nv.boot.default" ]; then
exit
fi
if [ -e /dev/nor0 ]; then
global.boot.default=nor
fi

View File

@ -0,0 +1 @@
2

View File

@ -0,0 +1 @@
earlyprintk console=ttyCL0,57600n8

View File

@ -1,6 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.linux.bootargs.base="console=ttyAMA0,115200"

View File

@ -1,12 +0,0 @@
#!/bin/sh
if [ "$1" = menu ]; then
init-menu-add-entry "$0" "general config settings"
exit
fi
# timeout in seconds before the default boot entry is started
global.autoboot_timeout=3
# default boot entry (one of /env/boot/*)
global.boot.default=mmc-ext3

View File

@ -0,0 +1 @@
mmc-ext3

View File

@ -0,0 +1 @@
console=ttyAMA0,115200

View File

@ -1,29 +0,0 @@
#!/bin/sh
# change network settings in /env/network/eth0
# change mtd partition settings and automountpoints in /env/init/*
#global.hostname=
# set to false if you do not want to have colors
global.allow_color=true
# user (used for network filenames)
global.user=none
# timeout in seconds before the default boot entry is started
global.autoboot_timeout=1
# default boot entry (one of /env/boot/*)
# (if not overwritten here, the bootdevice barebox comes from
# is used)
#global.boot.default=net
# base bootargs
global.linux.bootargs.base="console=tty1"
# suitable for 800MHz
global linux.bootargs.lpj="lpj=3997696"
# speed up booting by being more quiet
global linux.bootargs.quiet="quiet"

View File

@ -1,5 +1,9 @@
#!/bin/sh
if [ -n "$nv.boot.default" ]; then
exit
fi
# by default pick kernel from MMC card if booting from
# it, otherwise default to boot from internal harddisk

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
console=tty1

View File

@ -0,0 +1 @@
lpj=3997696

View File

@ -0,0 +1 @@
quiet

View File

@ -1,7 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.hostname=e9
global.boot.default=$bootsource$bootsource_instance

View File

@ -0,0 +1,7 @@
#!/bin/sh
if [ -n "$nv.boot.default" ]; then
exit
fi
global.boot.default=$bootsource$bootsource_instance

View File

@ -0,0 +1 @@
e9

View File

@ -1,6 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.linux.bootargs.base="console=ttymxc3,115200"

View File

@ -1,7 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.hostname=vincell
global.linux.bootargs.base="console=ttymxc0,115200"

View File

@ -0,0 +1 @@
vincell

View File

@ -0,0 +1 @@
console=ttymxc0,115200

View File

@ -1,10 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.allow_color=true
global.autoboot_timeout=3
global.bootm.oftree="/dev/dtb"
global.linux.bootargs.base="console=ttyAMA0,115200n8 CONSOLE=/dev/ttyAMA0"
global.boot.default=/env/boot.d

View File

@ -0,0 +1 @@
/env/boot.d

View File

@ -0,0 +1 @@
console=ttyAMA0,115200n8 CONSOLE=/dev/ttyAMA0

View File

@ -0,0 +1 @@
/dev/dtb

View File

@ -1,7 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.boot.default="usbmsd sd nor"
global.linux.bootargs.base="console=ttymxc0,921600"

View File

@ -0,0 +1 @@
usbmsd sd nor

View File

@ -0,0 +1 @@
console=ttymxc0,921600

View File

@ -1,6 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.linux.bootargs.base="console=ttyO2,115200"

View File

@ -0,0 +1 @@
console=ttyO2,115200

View File

@ -1,9 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.boot.default=nand
global.hostname=phyCARD-i.MX6
global.linux.bootargs.base="console=ttymxc2,115200"

View File

@ -0,0 +1 @@
console=ttymxc2,115200

View File

@ -0,0 +1 @@
phyCARD-i.MX6

View File

@ -1,10 +1,8 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.hostname=pcm051
global.linux.bootargs.base="console=ttyO0,115200"
if [ -n "$nv.boot.default" ]; then
exit
fi
if [ $bootsource = mmc ]; then
global.boot.default="mmc nand spi net"

View File

@ -0,0 +1,4 @@
#!/bin/sh
#otg1.mode=peripheral
usbgadget -a -A /dev/nand0.kernel.bb(kernel)

View File

@ -0,0 +1 @@
console=ttyO0,115200

View File

@ -1,6 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.linux.bootargs.base="console=ttymxc0,115200"

View File

@ -0,0 +1 @@
console=ttymxc0,115200

View File

@ -1,6 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.linux.bootargs.base="console=ttymxc0,115200"

View File

@ -0,0 +1 @@
console=ttymxc0,115200

View File

@ -1,10 +1,8 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.hostname=pfla03
global.linux.bootargs.base="console=ttyO0,115200"
if [ -n "$nv.boot.default" ]; then
exit
fi
if [ $bootsource = mmc ]; then
global.boot.default="mmc nand spi net"

View File

@ -0,0 +1 @@
console=ttyO0,115200

View File

@ -1,9 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.boot.default=nand
global.hostname=phyFLEX-i.MX6
global.linux.bootargs.base="console=ttymxc3,115200"

View File

@ -0,0 +1 @@
phyFLEX-i.MX6

View File

@ -0,0 +1 @@
console=ttymxc3,115200

View File

@ -1,6 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.linux.bootargs.base="console=ttyS2,115200"

View File

@ -0,0 +1 @@
console=ttyS2,115200

View File

@ -1,8 +0,0 @@
#!/bin/sh
# board defaults, do not change in running system. Change /env/config
# instead
global.hostname=evk-pro3
global.linux.bootargs.base="console=ttyS0,115200"
global.boot.default=nand-ubi

View File

@ -0,0 +1 @@
nand-ubi

View File

@ -0,0 +1 @@
console=ttyS0,115200

View File

@ -0,0 +1 @@
evk-pro3

View File

@ -674,6 +674,20 @@ endmenu
menu "Environment"
config CMD_NV
select GLOBALVAR
tristate
prompt "nv"
help
create, set or remove non volatile variables.
Usage: nv [-r] VAR[=VALUE]
Add a new config non volatile named VAR, optionally set to VALUE.
Options:
-r remove a non volatile variable
config CMD_EXPORT
depends on ENVIRONMENT_VARIABLES
tristate
@ -685,6 +699,13 @@ config CMD_EXPORT
Export an environment variable to subsequently executed scripts.
config CMD_DEFAULTENV
tristate
select ENV_HANDLING
prompt "defaultenv"
help
restore environment from default environment
config CMD_GLOBAL
select GLOBALVAR
tristate

View File

@ -107,3 +107,5 @@ obj-$(CONFIG_CMD_HWCLOCK) += hwclock.o
obj-$(CONFIG_CMD_USBGADGET) += usbgadget.o
obj-$(CONFIG_CMD_FIRMWARELOAD) += firmwareload.o
obj-$(CONFIG_CMD_CMP) += cmp.o
obj-$(CONFIG_CMD_NV) += nv.o
obj-$(CONFIG_CMD_DEFAULTENV) += defaultenv.o

View File

@ -39,14 +39,17 @@ static int do_cp(int argc, char *argv[])
int last_is_dir = 0;
int i;
int opt;
int verbose = 0;
int verbose = 0, recursive = 0;
int argc_min;
while ((opt = getopt(argc, argv, "v")) > 0) {
while ((opt = getopt(argc, argv, "vr")) > 0) {
switch (opt) {
case 'v':
verbose = 1;
break;
case 'r':
recursive = 1;
break;
}
}
@ -60,24 +63,31 @@ static int do_cp(int argc, char *argv[])
last_is_dir = 1;
}
if (argc > argc_min && !last_is_dir) {
if (((recursive && argc - optind > 2) || (argc > argc_min)) && !last_is_dir) {
printf("cp: target `%s' is not a directory\n", argv[argc - 1]);
return 1;
}
if (recursive && argc - optind == 2 && !last_is_dir) {
ret = make_directory(argv[argc - 1]);
if (ret)
goto out;
}
for (i = optind; i < argc - 1; i++) {
if (last_is_dir) {
char *dst;
dst = concat_path_file(argv[argc - 1], basename(argv[i]));
char *dst;
dst = concat_path_file(argv[argc - 1], basename(argv[i]));
if (recursive)
ret = copy_recursive(argv[i], dst);
else if (last_is_dir)
ret = copy_file(argv[i], dst, verbose);
free(dst);
if (ret)
goto out;
} else {
else
ret = copy_file(argv[i], argv[argc - 1], verbose);
if (ret)
goto out;
}
free(dst);
if (ret)
goto out;
}
ret = 0;

95
commands/defaultenv.c Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2014 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.
*
*/
#include <common.h>
#include <getopt.h>
#include <command.h>
#include <envfs.h>
#include <errno.h>
#include <fs.h>
#include <libfile.h>
#include <malloc.h>
#include <globalvar.h>
static int do_defaultenv(int argc, char *argv[])
{
char *dirname;
int opt, ret;
char *restorepath = "/";
char *from, *to;
int restore = 0, scrub = 0;
while ((opt = getopt(argc, argv, "p:rs")) > 0) {
switch (opt) {
case 'r':
restore = 1;
break;
case 'p':
restorepath = optarg;
break;
case 's':
scrub = 1;
break;
default:
return COMMAND_ERROR_USAGE;
}
}
if (!restore || argc != optind)
return COMMAND_ERROR_USAGE;
dirname = "/env";
make_directory(dirname);
ret = defaultenv_load("/.defaultenv", 0);
if (ret)
return ret;
from = asprintf("/.defaultenv/%s", restorepath);
to = asprintf("%s/%s", dirname, restorepath);
printf("Restoring %s from default environment\n", restorepath);
if (scrub)
unlink_recursive(to, NULL);
ret = copy_recursive(from, to);
free(from);
free(to);
nvvar_load();
unlink_recursive("/.defaultenv", NULL);
return ret;
}
BAREBOX_CMD_HELP_START(defaultenv)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-r", "restore default environment")
BAREBOX_CMD_HELP_OPT("-s", "scrub, remove files not in default environment")
BAREBOX_CMD_HELP_OPT("-p <PATH>", "limit to <PATH>")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(defaultenv)
.cmd = do_defaultenv,
BAREBOX_CMD_DESC("Restore environment from default environment")
BAREBOX_CMD_OPTS("[-rs] [-p <PATH>]")
BAREBOX_CMD_GROUP(CMD_GRP_ENV)
BAREBOX_CMD_HELP(cmd_defaultenv_help)
BAREBOX_CMD_END

View File

@ -37,6 +37,11 @@ static int do_global(int argc, char *argv[])
}
}
if (argc == optind) {
globalvar_print();
return 0;
}
argc -= optind;
argv += optind;

View File

@ -27,12 +27,13 @@
#include <errno.h>
#include <fs.h>
#include <malloc.h>
#include <globalvar.h>
static int do_loadenv(int argc, char *argv[])
{
char *filename = NULL, *dirname;
unsigned flags = 0;
int opt;
int opt, ret;
int scrub = 0;
int defaultenv = 0;
@ -97,9 +98,13 @@ static int do_loadenv(int argc, char *argv[])
printf("loading environment from %s\n", defaultenv ? "defaultenv" : filename);
if (defaultenv)
return defaultenv_load(dirname, flags);
ret = defaultenv_load(dirname, flags);
else
return envfs_load(filename, dirname, flags);
ret = envfs_load(filename, dirname, flags);
nvvar_load();
return ret;
}
BAREBOX_CMD_HELP_START(loadenv)

View File

@ -3,34 +3,118 @@
#include <getopt.h>
#include <environment.h>
#include <magicvar.h>
#include <malloc.h>
static LIST_HEAD(magicvars);
struct magicvar_dyn {
char *name;
char *description;
struct list_head list;
};
static void magicvar_print_one(struct magicvar_dyn *md, int verbose)
{
printf("%-32s %s\n", md->name, md->description);
if (verbose) {
const char *val = getenv(md->name);
if (val && strlen(val))
printf(" %s\n", val);
}
}
struct magicvar_dyn *magicvar_find(const char *name)
{
struct magicvar_dyn *md;
list_for_each_entry(md, &magicvars, list)
if (!strcmp(md->name, name))
return md;
return NULL;
}
static void magicvar_remove(struct magicvar_dyn *md)
{
free(md->name);
free(md->description);
list_del(&md->list);
free(md);
}
static int compare(struct list_head *a, struct list_head *b)
{
char *na = (char*)list_entry(a, struct magicvar_dyn, list)->name;
char *nb = (char*)list_entry(b, struct magicvar_dyn, list)->name;
return strcmp(na, nb);
}
static int magicvar_add(const char *name, const char *description)
{
struct magicvar_dyn *md;
md = magicvar_find(name);
if (md)
magicvar_remove(md);
md = xzalloc(sizeof(*md));
md->name = xstrdup(name);
md->description = xstrdup(description);
list_add_sort(&md->list, &magicvars, compare);
return 0;
}
static void magicvar_build(void)
{
static int first = 1;
struct magicvar *m;
if (!first)
return;
for (m = &__barebox_magicvar_start;
m != &__barebox_magicvar_end;
m++)
magicvar_add(m->name, m->description);
first = 0;
}
static int do_magicvar(int argc, char *argv[])
{
struct magicvar *m;
struct magicvar_dyn *md;
int opt;
int verbose = 0;
int verbose = 0, add = 0;
while ((opt = getopt(argc, argv, "v")) > 0) {
magicvar_build();
while ((opt = getopt(argc, argv, "va")) > 0) {
switch (opt) {
case 'v':
verbose = 1;
break;
case 'a':
add = 1;
break;
default:
return COMMAND_ERROR_USAGE;
}
}
for (m = &__barebox_magicvar_start;
m != &__barebox_magicvar_end;
m++) {
printf("%-32s %s\n", m->name, m->description);
if (verbose) {
const char *val = getenv(m->name);
if (val && strlen(val))
printf(" %s\n", val);
}
if (add) {
if (optind + 2 != argc)
return COMMAND_ERROR_USAGE;
return magicvar_add(argv[optind], argv[optind + 1]);
}
list_for_each_entry(md, &magicvars, list)
magicvar_print_one(md, verbose);
return 0;
}
@ -38,12 +122,13 @@ static int do_magicvar(int argc, char *argv[])
BAREBOX_CMD_HELP_START(magicvar)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-v", "verbose (list all value if there is one)")
BAREBOX_CMD_HELP_OPT ("-a <NAME> <DESC>", "Add a new magicvar")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(magicvar)
.cmd = do_magicvar,
BAREBOX_CMD_DESC("list information about magic variables")
BAREBOX_CMD_OPTS("[-v]")
BAREBOX_CMD_OPTS("[-va]")
BAREBOX_CMD_HELP(cmd_magicvar_help)
BAREBOX_CMD_GROUP(CMD_GRP_ENV)
BAREBOX_CMD_END

84
commands/nv.c Normal file
View File

@ -0,0 +1,84 @@
/*
* nv.c - non volatile shell variables
*
* Copyright (c) 2014 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.
*
*/
#include <common.h>
#include <malloc.h>
#include <command.h>
#include <globalvar.h>
#include <environment.h>
#include <getopt.h>
static int do_nv(int argc, char *argv[])
{
int opt;
int do_remove = 0;
int ret;
char *value;
while ((opt = getopt(argc, argv, "r")) > 0) {
switch (opt) {
case 'r':
do_remove = 1;
break;
default:
return COMMAND_ERROR_USAGE;
}
}
if (argc == optind) {
nvvar_print();
return 0;
}
argc -= optind;
argv += optind;
if (argc != 1)
return COMMAND_ERROR_USAGE;
value = strchr(argv[0], '=');
if (value) {
*value = 0;
value++;
}
if (do_remove)
ret = nvvar_remove(argv[0]);
else
ret = nvvar_add(argv[0], value);
return ret;
}
BAREBOX_CMD_HELP_START(nv)
BAREBOX_CMD_HELP_TEXT("Add a new non volatile variable named VAR, optionally set to VALUE.")
BAREBOX_CMD_HELP_TEXT("non volatile variables are persistent variables that overwrite the")
BAREBOX_CMD_HELP_TEXT("global variables of the same name. Their value is saved with")
BAREBOX_CMD_HELP_TEXT("'saveenv'.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-r", "remove a non volatile variable")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(nv)
.cmd = do_nv,
BAREBOX_CMD_DESC("create or set non volatile variables")
BAREBOX_CMD_OPTS("[-r] VAR[=VALUE]")
BAREBOX_CMD_GROUP(CMD_GRP_ENV)
BAREBOX_CMD_HELP(cmd_nv_help)
BAREBOX_CMD_END

View File

@ -632,6 +632,7 @@ config DEFAULT_ENVIRONMENT_GENERIC_NEW
select CMD_BASENAME
select CMD_READLINK
select CMD_DIRNAME
select CMD_NV
select FLEXIBLE_BOOTARGS
select CMD_BOOT
select NET_CMD_IFUP if NET

View File

@ -36,19 +36,32 @@
#include <libbb.h>
#include <libgen.h>
#include <environment.h>
#include <globalvar.h>
#include <libfile.h>
#else
# define errno_str(x) ("void")
#define EXPORT_SYMBOL(x)
#endif
struct envfs_entry {
char *name;
void *buf;
int size;
struct envfs_entry *next;
mode_t mode;
};
struct action_data {
int fd;
const char *base;
void *writep;
struct envfs_entry *env;
};
#define PAD4(x) ((x + 3) & ~3)
#ifdef __BAREBOX__
#define TMPDIR "/.defaultenv"
static char *default_environment_path = "/dev/env0";
void default_environment_path_set(char *path)
@ -60,6 +73,21 @@ char *default_environment_path_get(void)
{
return default_environment_path;
}
static int do_compare_file(const char *filename, const char *base)
{
int ret;
char *cmp;
const char *relname = filename + strlen(base) + 1;
cmp = asprintf("%s/%s", TMPDIR, relname);
ret = compare_file(cmp, filename);
free(cmp);
return ret;
}
#else
static inline int protect(int fd, size_t count, unsigned long offset, int prot)
{
@ -70,96 +98,140 @@ static inline int erase(int fd, size_t count, unsigned long offset)
{
return 0;
}
static int do_compare_file(const char *filename, const char *base)
{
return 1;
}
#endif
static int file_size_action(const char *filename, struct stat *statbuf,
static int file_action(const char *filename, struct stat *statbuf,
void *userdata, int depth)
{
struct action_data *data = userdata;
struct envfs_entry *env;
int fd, ret;
if (!do_compare_file(filename, data->base))
return 1;
env = xzalloc(sizeof(*env));
env->name = strdup(filename + strlen(data->base));
env->size = statbuf->st_size;
env->buf = calloc(env->size + 1, 1);
if (!env->buf)
goto out;
env->mode = S_IRWXU | S_IRWXG | S_IRWXO;
data->writep += sizeof(struct envfs_inode);
data->writep += PAD4(strlen(filename) + 1 - strlen(data->base));
data->writep += sizeof(struct envfs_inode_end);
if (S_ISLNK(statbuf->st_mode)) {
char path[PATH_MAX];
env->size++;
memset(path, 0, PATH_MAX);
if (readlink(filename, path, PATH_MAX - 1) < 0) {
ret = readlink(filename, env->buf, env->size);
if (ret < 0) {
perror("read");
return 0;
goto out;
}
data->writep += PAD4(strlen(path) + 1);
env->mode |= S_IFLNK;
} else {
data->writep += PAD4(statbuf->st_size);
fd = open(filename, O_RDONLY);
if (fd < 0)
return fd;
ret = read(fd, env->buf, env->size);
close(fd);
if (ret < env->size) {
perror("read");
goto out;
}
}
env->next = data->env;
data->env = env;
out:
return 1;
}
static int file_save_action(const char *filename, struct stat *statbuf,
void *userdata, int depth)
static void envfs_save_inode(struct action_data *data, struct envfs_entry *env)
{
struct action_data *data = userdata;
struct envfs_inode *inode;
struct envfs_inode_end *inode_end;
int fd;
int namelen = strlen(filename) + 1 - strlen(data->base);
int namelen = strlen(env->name) + 1;
inode = (struct envfs_inode*)data->writep;
inode = data->writep;
inode->magic = ENVFS_32(ENVFS_INODE_MAGIC);
inode->headerlen = ENVFS_32(PAD4(namelen + sizeof(struct envfs_inode_end)));
inode->headerlen = ENVFS_32(PAD4(namelen) + sizeof(struct envfs_inode_end));
inode->size = ENVFS_32(env->size);
data->writep += sizeof(struct envfs_inode);
strcpy(data->writep, filename + strlen(data->base));
strcpy(data->writep, env->name);
data->writep += PAD4(namelen);
inode_end = (struct envfs_inode_end*)data->writep;
data->writep += sizeof(struct envfs_inode_end);
inode_end = data->writep;
inode_end->magic = ENVFS_32(ENVFS_INODE_END_MAGIC);
inode_end->mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO);
inode_end->mode = ENVFS_32(env->mode);
data->writep += sizeof(struct envfs_inode_end);
if (S_ISLNK(statbuf->st_mode)) {
char path[PATH_MAX];
int len;
memcpy(data->writep, env->buf, env->size);
data->writep += PAD4(env->size);
}
memset(path, 0, PATH_MAX);
#ifdef __BAREBOX__
static int file_remove_action(const char *filename, struct stat *statbuf,
void *userdata, int depth)
{
struct action_data *data = userdata;
char *envname;
struct stat s;
int ret;
struct envfs_entry *env;
if (readlink(filename, path, PATH_MAX - 1) < 0) {
perror("read");
filename += sizeof(TMPDIR) - 1;
envname = asprintf("%s/%s", data->base, filename);
ret = stat(envname, &s);
if (ret) {
char *base;
base = basename(envname);
env = xzalloc(sizeof(*env));
env->name = strdup(filename);
env->size = strlen(base) + 1;
env->buf = strdup(base);
if (!env->buf)
goto out;
}
len = strlen(path) + 1;
inode_end->mode |= ENVFS_32(S_IFLNK);
env->mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFLNK;
memcpy(data->writep, path, len);
inode->size = ENVFS_32(len);
data->writep += PAD4(len);
debug("handling symlink %s size %d namelen %d headerlen %d\n",
filename + strlen(data->base),
len, namelen, ENVFS_32(inode->headerlen));
} else {
debug("handling file %s size %lld namelen %d headerlen %d\n",
filename + strlen(data->base),
statbuf->st_size, namelen, ENVFS_32(inode->headerlen));
inode->size = ENVFS_32(statbuf->st_size);
fd = open(filename, O_RDONLY);
if (fd < 0) {
printf("Open %s %s\n", filename, errno_str());
goto out;
}
if (read(fd, data->writep, statbuf->st_size) < statbuf->st_size) {
perror("read");
goto out;
}
close(fd);
data->writep += PAD4(statbuf->st_size);
env->next = data->env;
data->env = env;
}
out:
free(envname);
return 1;
}
#else
static int file_remove_action(const char *filename, struct stat *statbuf,
void *userdata, int depth)
{
return 0;
}
#endif
static int dir_remove_action(const char *filename, struct stat *statbuf,
void *userdata, int depth)
{
rmdir(filename);
return 1;
}
@ -177,26 +249,39 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
{
struct envfs_super *super;
int envfd, size, ret;
struct action_data data;
struct action_data data = {};
void *buf = NULL, *wbuf;
struct envfs_entry *env;
data.writep = NULL;
data.base = dirname;
#ifdef __BAREBOX__
defaultenv_load(TMPDIR, 0);
#endif
if (flags & ENVFS_FLAGS_FORCE_BUILT_IN) {
size = 0; /* force no content */
} else {
/* first pass: calculate size */
recursive_action(dirname, ACTION_RECURSE, file_size_action,
recursive_action(dirname, ACTION_RECURSE, file_action,
NULL, &data, 0);
recursive_action("/.defaultenv", ACTION_RECURSE,
file_remove_action, NULL, &data, 0);
size = 0;
size = (unsigned long)data.writep;
for (env = data.env; env; env = env->next) {
size += PAD4(env->size);
size += sizeof(struct envfs_inode);
size += PAD4(strlen(env->name) + 1);
size += sizeof(struct envfs_inode_end);
}
}
buf = xzalloc(size + sizeof(struct envfs_super));
data.writep = buf + sizeof(struct envfs_super);
super = (struct envfs_super *)buf;
super = buf;
super->magic = ENVFS_32(ENVFS_MAGIC);
super->major = ENVFS_MAJOR;
super->minor = ENVFS_MINOR;
@ -205,8 +290,17 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
if (!(flags & ENVFS_FLAGS_FORCE_BUILT_IN)) {
/* second pass: copy files to buffer */
recursive_action(dirname, ACTION_RECURSE, file_save_action,
NULL, &data, 0);
env = data.env;
while (env) {
struct envfs_entry *next = env->next;
envfs_save_inode(&data, env);
free(env->buf);
free(env->name);
free(env);
env = next;
}
}
super->crc = ENVFS_32(crc32(0, buf + sizeof(struct envfs_super), size));
@ -264,6 +358,9 @@ out:
close(envfd);
out1:
free(buf);
#ifdef __BAREBOX__
unlink_recursive(TMPDIR, NULL);
#endif
return ret;
}
EXPORT_SYMBOL(envfs_save);
@ -320,7 +417,7 @@ static int envfs_load_data(struct envfs_super *super, void *buf, size_t size,
struct envfs_inode_end *inode_end;
uint32_t inode_size, inode_headerlen, namelen;
inode = (struct envfs_inode *)buf;
inode = buf;
buf += sizeof(struct envfs_inode);
if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) {
@ -334,15 +431,12 @@ static int envfs_load_data(struct envfs_super *super, void *buf, size_t size,
if (super->major < 1)
inode_end = &inode_end_dummy;
else
inode_end = (struct envfs_inode_end *)(buf + PAD4(namelen));
inode_end = buf + PAD4(namelen);
debug("loading %s size %d namelen %d headerlen %d\n", inode->data,
inode_size, namelen, inode_headerlen);
str = concat_path_file(dir, inode->data);
tmp = strdup(str);
make_directory(dirname(tmp));
free(tmp);
headerlen_full = PAD4(inode_headerlen);
buf += headerlen_full;
@ -353,11 +447,19 @@ static int envfs_load_data(struct envfs_super *super, void *buf, size_t size,
goto out;
}
tmp = strdup(str);
make_directory(dirname(tmp));
free(tmp);
if (S_ISLNK(ENVFS_32(inode_end->mode))) {
debug("symlink: %s -> %s\n", str, (char*)buf);
if (symlink((char*)buf, str) < 0) {
printf("symlink: %s -> %s :", str, (char*)buf);
perror("");
if (!strcmp(buf, basename(str))) {
unlink(str);
} else {
ret = symlink(buf, str);
if (ret < 0)
printf("symlink: %s -> %s : %s\n",
str, (char*)buf, strerror(-errno));
}
free(str);
} else {
@ -392,6 +494,9 @@ skip:
sizeof(struct envfs_inode);
}
recursive_action(dir, ACTION_RECURSE | ACTION_DEPTHFIRST, NULL,
dir_remove_action, NULL, 0);
ret = 0;
out:
return ret;
@ -498,6 +603,7 @@ int envfs_load(const char *filename, const char *dir, unsigned flags)
goto out;
ret = 0;
out:
close(envfd);
free(buf);

View File

@ -5,6 +5,9 @@
#include <init.h>
#include <environment.h>
#include <magicvar.h>
#include <fs.h>
#include <fcntl.h>
#include <libfile.h>
#include <generated/utsrelease.h>
struct device_d global_device = {
@ -12,6 +15,11 @@ struct device_d global_device = {
.id = DEVICE_ID_SINGLE,
};
struct device_d nv_device = {
.name = "nv",
.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),
@ -25,6 +33,175 @@ int globalvar_add(const char *name,
return 0;
}
static int nv_save(const char *name, const char *val)
{
int fd, ret;
char *fname;
ret = make_directory("/env/nv");
if (ret)
return ret;
fname = asprintf("/env/nv/%s", name);
fd = open(fname, O_CREAT | O_WRONLY | O_TRUNC);
free(fname);
if (fd < 0)
return fd;
fprintf(fd, "%s", val);
close(fd);
return 0;
}
static int nv_set(struct device_d *dev, struct param_d *p, const char *val)
{
struct param_d *gp;
int ret;
if (!val)
val = "";
gp = get_param_by_name(&global_device, p->name);
if (!gp)
return -EINVAL;
ret = gp->set(&global_device, gp, val);
if (ret)
return ret;
free(p->value);
p->value = xstrdup(val);
return nv_save(p->name, val);
}
static const char *nv_get(struct device_d *dev, struct param_d *p)
{
return p->value ? p->value : "";
}
int nvvar_add(const char *name, const char *value)
{
struct param_d *p, *gp;
int ret;
gp = get_param_by_name(&nv_device, name);
if (gp) {
ret = dev_set_param(&global_device, name, value);
if (ret)
return ret;
ret = dev_set_param(&nv_device, name, value);
if (ret)
return ret;
return 0;
}
ret = globalvar_add_simple(name, value);
if (ret && ret != -EEXIST)
return ret;
p = dev_add_param(&nv_device, name, nv_set, nv_get, 0);
if (IS_ERR(p))
return PTR_ERR(p);
if (value) {
ret = dev_set_param(&global_device, name, value);
if (ret)
return ret;
} else {
value = dev_get_param(&global_device, name);
if (!value)
value = "";
}
p->value = xstrdup(value);
return nv_save(p->name, value);
}
int nvvar_remove(const char *name)
{
struct param_d *p;
char *fname;
p = get_param_by_name(&nv_device, name);
if (!p)
return -ENOENT;
fname = asprintf("/env/nv/%s", p->name);
unlink(fname);
free(fname);
list_del(&p->list);
free(p->name);
free(p);
return 0;
}
int nvvar_load(void)
{
char *val;
int ret;
DIR *dir;
struct dirent *d;
dir = opendir("/env/nv");
if (!dir)
return -ENOENT;
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
val = read_file_line("/env/nv/%s", d->d_name);
pr_debug("%s: Setting \"%s\" to \"%s\"\n",
__func__, d->d_name, val);
ret = nvvar_add(d->d_name, val);
if (ret)
pr_err("failed to create nv variable %s: %s\n",
d->d_name, strerror(-ret));
}
closedir(dir);
return 0;
}
static void device_param_print(struct device_d *dev)
{
struct param_d *param;
list_for_each_entry(param, &dev->parameters, list) {
const char *p = dev_get_param(dev, param->name);
const char *nv = NULL;
if (dev != &nv_device)
nv = dev_get_param(&nv_device, param->name);
printf("%s%s: %s\n", nv ? "* " : " ", param->name, p);
}
}
void nvvar_print(void)
{
device_param_print(&nv_device);
}
void globalvar_print(void)
{
device_param_print(&global_device);
}
/*
* globalvar_get_match
*
@ -87,6 +264,7 @@ int globalvar_add_simple(const char *name, const char *value)
static int globalvar_init(void)
{
register_device(&global_device);
register_device(&nv_device);
globalvar_add_simple("version", UTS_RELEASE);

View File

@ -40,6 +40,7 @@
#include <envfs.h>
#include <asm/sections.h>
#include <uncompress.h>
#include <globalvar.h>
extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
__barebox_initcalls_end[];
@ -78,17 +79,13 @@ void __noreturn start_barebox(void)
pr_debug("initcalls done\n");
if (IS_ENABLED(CONFIG_ENV_HANDLING)) {
int ret;
char *default_environment_path = default_environment_path_get();
ret = envfs_load(default_environment_path, "/env", 0);
if (ret && IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT)) {
pr_err("no valid environment found on %s. "
"Using default environment\n",
default_environment_path);
if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT))
defaultenv_load("/env", 0);
}
envfs_load(default_environment_path, "/env", 0);
nvvar_load();
}
if (IS_ENABLED(CONFIG_COMMAND_SUPPORT)) {

View File

@ -16,9 +16,12 @@ global editcmd
[ -z "${global.hostname}" ] && global.hostname=generic
[ -z "${global.user}" ] && global.user=none
magicvar -a global.user "username (used in network filenames)"
[ -z "${global.autoboot_timeout}" ] && global.autoboot_timeout=3
magicvar -a global.autoboot_timeout "timeout in seconds before automatic booting"
[ -z "${global.boot.default}" ] && global.boot.default=net
[ -z "${global.allow_color}" ] && global.allow_color=true
magicvar -a global.allow_color "Allow color on the console (boolean)"
[ -z "${global.editcmd}" ] && global.editcmd=sedit
[ -e /env/config-board ] && /env/config-board

View File

@ -3,23 +3,5 @@
# change network settings in /env/network/eth0
# change mtd partition settings and automountpoints in /env/init/*
#global.hostname=
# set to false if you do not want to have colors
#global.allow_color=true
# user (used for network filenames)
#global.user=none
# timeout in seconds before the default boot entry is started
#global.autoboot_timeout=3
# list of boot entries. These are executed in order until one
# succeeds. An entry can be:
# - a filename in /env/boot/
# - a full path to a directory. All files in this directory are
# treated as boot files and executed in alphabetical order
#global.boot.default=net
# base bootargs
#global.linux.bootargs.base="console=ttyS0,115200"
# The settings that used to be here are in nv variables now.
# See 'help nv', 'magicvar'

View File

@ -0,0 +1 @@
true

View File

@ -0,0 +1 @@
3

View File

@ -0,0 +1 @@
none

View File

@ -72,6 +72,13 @@ static inline int globalvar_add_simple_ip(const char *name,
return 0;
}
int nvvar_load(void);
void nvvar_print(void);
int nvvar_add(const char *name, const char *value);
int nvvar_remove(const char *name);
void globalvar_print(void);
#else
static inline int globalvar_add_simple(const char *name, const char *value)
{
@ -116,6 +123,12 @@ static inline char *globalvar_get_match(const char *match, const char *separator
}
static inline void globalvar_set_match(const char *match, const char *val) {}
static inline int nvvar_load(void)
{
return 0;
}
#endif
#endif /* __GLOBALVAR_H */

View File

@ -15,6 +15,8 @@ int write_file(const char *filename, void *buf, size_t size);
int copy_file(const char *src, const char *dst, int verbose);
int copy_recursive(const char *src, const char *dst);
int compare_file(const char *f1, const char *f2);
#endif /* __LIBFILE_H */

View File

@ -332,6 +332,46 @@ out:
}
EXPORT_SYMBOL(copy_file);
int copy_recursive(const char *src, const char *dst)
{
struct stat s;
DIR *dir;
struct dirent *d;
int ret;
ret = stat(src, &s);
if (ret)
return ret;
if (!S_ISDIR(s.st_mode))
return copy_file(src, dst, 0);
ret = make_directory(dst);
if (ret)
return ret;
dir = opendir(src);
if (!dir)
return -EIO;
while ((d = readdir(dir))) {
char *from, *to;
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
from = asprintf("%s/%s", src, d->d_name);
to = asprintf("%s/%s", dst, d->d_name);
ret = copy_recursive(from, to);
if (ret)
break;
free(from);
free(to);
}
closedir(dir);
return ret;
}
/**
* compare_file - Compare two files
* @f1: The first file