From 8413d78ab3e3062641dbe3069fcd454858244679 Mon Sep 17 00:00:00 2001 From: Juergen Beisert Date: Fri, 9 Nov 2007 23:19:54 +0100 Subject: [PATCH] separating environment commands, part 2 Signed-off-by: Juergen Beisert --- commands/Kconfig | 10 +- commands/Makefile | 3 +- commands/loadenv.c | 71 ++++++++++ commands/saveenv.c | 119 ++++++++++++++++ common/Kconfig | 3 + common/Makefile | 1 + {commands => common}/environment.c | 220 +++++++---------------------- include/environment.h | 22 ++- scripts/ubootenv.c | 3 +- 9 files changed, 280 insertions(+), 172 deletions(-) create mode 100644 commands/loadenv.c create mode 100644 commands/saveenv.c rename {commands => common}/environment.c (52%) diff --git a/commands/Kconfig b/commands/Kconfig index 133a16ae6..0725ec0c1 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -18,9 +18,15 @@ config CMD_SLEEP tristate prompt "sleep" -config CMD_ENVIRONMENT +config CMD_SAVEENV tristate - prompt "saveenv / loadenv" + select ENV_HANDLING + prompt "saveenv" + +config CMD_LOADENV + tristate + select ENV_HANDLING + prompt "loadenv" config CMD_EXPORT tristate diff --git a/commands/Makefile b/commands/Makefile index 3d0efd017..ba6ffbfea 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_CMD_EXEC) += exec.o obj-$(CONFIG_CMD_SLEEP) += sleep.o obj-$(CONFIG_CMD_RESET) += reset.o obj-$(CONFIG_CMD_GO) += go.o -obj-$(CONFIG_CMD_ENVIRONMENT) += environment.o obj-$(CONFIG_NET) += net.o obj-$(CONFIG_CMD_PARTITION) += partition.o obj-$(CONFIG_CMD_LS) += ls.o @@ -39,3 +38,5 @@ obj-$(CONFIG_CMD_MV) += mv.o obj-$(CONFIG_SIMPLE_PARSER) += setenv.o obj-$(CONFIG_CMD_EXPORT) += export.o obj-$(CONFIG_CMD_PRINTENV) += printenv.o +obj-$(CONFIG_CMD_SAVEENV) += saveenv.o +obj-$(CONFIG_CMD_LOADENV) += loadenv.o diff --git a/commands/loadenv.c b/commands/loadenv.c new file mode 100644 index 000000000..5db132cc3 --- /dev/null +++ b/commands/loadenv.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2007 Sascha Hauer , 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 + */ + +/** + * @file + * @brief loadenv: Restoring a environment + */ + +#include +#include +#include + +static int do_loadenv(cmd_tbl_t *cmdtp, int argc, char *argv[]) +{ + char *filename, *dirname; + + if (argc < 3) + dirname = "/env"; + else + dirname = argv[2]; + if (argc < 2) + filename = "/dev/env0"; + else + filename = argv[1]; + printf("loading environment from %s\n", filename); + return envfs_load(filename, dirname); +} + +static __maybe_unused char cmd_loadenv_help[] = +"Usage: loadenv [ENVFS] [DIRECTORY]\n" +"Load the persistent storage contained in to the directory\n" +".\n" +"If ommitted defaults to /env and defaults to /dev/env0.\n" +"Note that envfs can only handle files. Directories are skipped silently.\n"; + +U_BOOT_CMD_START(loadenv) + .maxargs = 3, + .cmd = do_loadenv, + .usage = "load environment from persistent storage", + U_BOOT_CMD_HELP(cmd_loadenv_help) +U_BOOT_CMD_END + +/** + * @page loadenv_command loadenv + * + * Usage: loadenv [\] [\] + * + * Load the persistent storage contained in \ to the directory \. + * + * If ommitted \ defaults to \c /env and \ defaults to + * \c /dev/env0. + * + * @note envfs can only handle files. Directories are skipped silently. + */ diff --git a/commands/saveenv.c b/commands/saveenv.c new file mode 100644 index 000000000..ef195bc13 --- /dev/null +++ b/commands/saveenv.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2007 Sascha Hauer , 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 + */ + +/** + * @file + * @brief saveenv: Make the environment persistent + */ + +#include +#include +#include +#include +#include +#include + +static int do_saveenv(cmd_tbl_t *cmdtp, int argc, char *argv[]) +{ + int ret, fd; + char *filename, *dirname; + + printf("saving environment\n"); + if (argc < 3) + dirname = "/env"; + else + dirname = argv[2]; + if (argc < 2) + filename = "/dev/env0"; + else + filename = argv[1]; + + fd = open(filename, O_WRONLY | O_CREAT); + if (fd < 0) { + printf("could not open %s: %s", filename, errno_str()); + return 1; + } + + ret = protect(fd, ~0, 0, 0); + + /* ENOSYS is no error here, many devices do not need it */ + if (ret && errno != -ENOSYS) { + printf("could not unprotect %s: %s\n", filename, errno_str()); + close(fd); + return 1; + } + + ret = erase(fd, ~0, 0); + + /* ENOSYS is no error here, many devices do not need it */ + if (ret && errno != -ENOSYS) { + printf("could not erase %s: %s\n", filename, errno_str()); + close(fd); + return 1; + } + + ret = envfs_save(filename, dirname); + if (ret) { + printf("saveenv failed\n"); + goto out; + } + + ret = protect(fd, ~0, 0, 1); + + /* ENOSYS is no error here, many devices do not need it */ + if (ret && errno != -ENOSYS) { + printf("could not protect %s: %s\n", filename, errno_str()); + close(fd); + return 1; + } + + ret = 0; +out: + close(fd); + return ret; +} + +static __maybe_unused char cmd_saveenv_help[] = +"Usage: saveenv [] []\n" +"Save the files in to the persistent storage device .\n" +" is normally a block in flash, but could be any other file.\n" +"If ommitted defaults to /env and defaults to /dev/env0.\n" +"Note that envfs can only handle files. Directories are skipped silently.\n"; + +U_BOOT_CMD_START(saveenv) + .maxargs = 3, + .cmd = do_saveenv, + .usage = "save environment to persistent storage", + U_BOOT_CMD_HELP(cmd_saveenv_help) +U_BOOT_CMD_END + +/** + * @page saveenv_command saveenv + * + * Usage: saveenv [\] [\] + * + * Save the files in \ to the persistent storage device \. + * \ is normally a block in flash, but could be any other file. + * + * If ommitted \ defaults to \c /env and \ defaults to + * \c /dev/env0. + * + * @note envfs can only handle files. Directories are skipped silently. + */ diff --git a/common/Kconfig b/common/Kconfig index 373c45b71..16a9a02a5 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -11,6 +11,9 @@ config HAS_MODULES config CMD_MEMORY bool +config ENV_HANDLING + bool + menu "General Settings " config BOARDINFO diff --git a/common/Makefile b/common/Makefile index 81d04c275..11d4ae516 100644 --- a/common/Makefile +++ b/common/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_OF_FLAT_TREE) += ft_build.o obj-$(CONFIG_MODULE) += module.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_CMD_MEMORY) += mem.o +obj-$(CONFIG_ENV_HANDLING) += environment.o obj-y += dlmalloc.o obj-y += clock.o diff --git a/commands/environment.c b/common/environment.c similarity index 52% rename from commands/environment.c rename to common/environment.c index 01e7cfed9..67ede3834 100644 --- a/commands/environment.c +++ b/common/environment.c @@ -1,6 +1,4 @@ /* - * environment.c - simple archive implementation - * * Copyright (c) 2007 Sascha Hauer , Pengutronix * * See file CREDITS for list of people who contributed to this @@ -22,36 +20,32 @@ /** * @file - * @brief Managing environment and environment variables + * @brief Environment handling support (host and target) + * + * Important: This file will also be used on the host to create + * the default environment when building the U-Boot binary. So + * do not add any new U-Boot related functions here! */ #ifdef __U_BOOT__ #include #include -#include #include #include #include #include -#include #include #include #include #include +#include #else # define errno_str(x) ("void") +#define EXPORT_SYMBOL(x) #endif -struct action_data { - int fd; - const char *base; - void *writep; -}; - -#define PAD4(x) ((x + 3) & ~3) - -static int file_size_action(const char *filename, struct stat *statbuf, - void *userdata, int depth) +int file_size_action(const char *filename, struct stat *statbuf, + void *userdata, int depth) { struct action_data *data = userdata; @@ -61,15 +55,16 @@ static int file_size_action(const char *filename, struct stat *statbuf, return 1; } -static int file_save_action(const char *filename, struct stat *statbuf, - void *userdata, int depth) +int file_save_action(const char *filename, struct stat *statbuf, + void *userdata, int depth) { struct action_data *data = userdata; struct envfs_inode *inode; int fd; int namelen = strlen(filename) + 1 - strlen(data->base); - debug("handling file %s size %ld namelen %d\n", filename + strlen(data->base), statbuf->st_size, namelen); + debug("handling file %s size %ld namelen %d\n", filename + strlen(data->base), + statbuf->st_size, namelen); inode = (struct envfs_inode*)data->writep; inode->magic = ENVFS_INODE_MAGIC; @@ -98,6 +93,15 @@ out: return 1; } +/** + * Make the current environment persistent + * @param[in] filename where to store + * @param[in] dirname what to store (all files in this dir) + * @return 0 on success, anything else in case of failure + * + * Note: This function will also be used on the host! See note in the header + * of this file. + */ int envfs_save(char *filename, char *dirname) { struct envfs_super *super; @@ -110,7 +114,7 @@ int envfs_save(char *filename, char *dirname) /* first pass: calculate size */ recursive_action(dirname, ACTION_RECURSE, file_size_action, - NULL, &data, 0); + NULL, &data, 0); size = (unsigned long)data.writep; @@ -123,7 +127,7 @@ int envfs_save(char *filename, char *dirname) /* second pass: copy files to buffer */ recursive_action(dirname, ACTION_RECURSE, file_save_action, - NULL, &data, 0); + NULL, &data, 0); super->crc = crc32(0, buf + sizeof(struct envfs_super), size); super->sb_crc = crc32(0, buf, sizeof(struct envfs_super) - 4); @@ -131,11 +135,14 @@ int envfs_save(char *filename, char *dirname) envfd = open(filename, O_WRONLY | O_CREAT); if (envfd < 0) { printf("Open %s %s\n", filename, errno_str()); + ret = envfd; goto out1; } - if (write(envfd, buf, size + sizeof(struct envfs_super)) < sizeof(struct envfs_super)) { + if (write(envfd, buf, size + sizeof(struct envfs_super)) < + sizeof(struct envfs_super)) { perror("write"); + ret = -1; /* FIXME */ goto out; } @@ -147,97 +154,17 @@ out1: free(buf); return ret; } - -#ifdef __U_BOOT__ -static int do_saveenv(cmd_tbl_t *cmdtp, int argc, char *argv[]) -{ - int ret, fd; - char *filename, *dirname; - - printf("saving environment\n"); - if (argc < 3) - dirname = "/env"; - else - dirname = argv[2]; - if (argc < 2) - filename = "/dev/env0"; - else - filename = argv[1]; - - fd = open(filename, O_WRONLY | O_CREAT); - if (fd < 0) { - printf("could not open %s: %s", filename, errno_str()); - return 1; - } - - ret = protect(fd, ~0, 0, 0); - - /* ENOSYS is no error here, many devices do not need it */ - if (ret && errno != -ENOSYS) { - printf("could not unprotect %s: %s\n", filename, errno_str()); - close(fd); - return 1; - } - - ret = erase(fd, ~0, 0); - - /* ENOSYS is no error here, many devices do not need it */ - if (ret && errno != -ENOSYS) { - printf("could not erase %s: %s\n", filename, errno_str()); - close(fd); - return 1; - } - - ret = envfs_save(filename, dirname); - if (ret) { - printf("saveenv failed\n"); - goto out; - } - - ret = protect(fd, ~0, 0, 1); - - /* ENOSYS is no error here, many devices do not need it */ - if (ret && errno != -ENOSYS) { - printf("could not protect %s: %s\n", filename, errno_str()); - close(fd); - return 1; - } - - ret = 0; -out: - close(fd); - return ret; -} - -static __maybe_unused char cmd_saveenv_help[] = -"Usage: saveenv [] []\n" -"Save the files in to the persistent storage device .\n" -" is normally a block in flash, but could be any other file.\n" -"If ommitted defaults to /env and defaults to /dev/env0.\n" -"Note that envfs can only handle files. Directories are skipped silently.\n"; - -U_BOOT_CMD_START(saveenv) - .maxargs = 3, - .cmd = do_saveenv, - .usage = "save environment to persistent storage", - U_BOOT_CMD_HELP(cmd_saveenv_help) -U_BOOT_CMD_END -#endif /* __U_BOOT__ */ +EXPORT_SYMBOL(envfs_save); /** - * @page saveenv_command saveenv + * Restore the last environment into the current one + * @param[in] filename from where to restore + * @param[in] dirname where to store the last content + * @return 0 on success, anything else in case of failure * - * Usage: saveenv [\] [\] - * - * Save the files in \ to the persistent storage device \. - * \ is normally a block in flash, but could be any other file. - * - * If ommitted \ defaults to \b /env and \ defaults to - * \b /dev/env0. - * - * @note envfs can only handle files. Directories are skipped silently. + * Note: This function will also be used on the host! See note in the header + * of this file. */ - int envfs_load(char *filename, char *dir) { struct envfs_super super; @@ -269,7 +196,7 @@ int envfs_load(char *filename, char *dir) } if (crc32(0, (unsigned char *)&super, sizeof(struct envfs_super) - 4) - != super.sb_crc) { + != super.sb_crc) { printf("wrong crc on env superblock\n"); goto out; } @@ -283,31 +210,32 @@ int envfs_load(char *filename, char *dir) } if (crc32(0, (unsigned char *)buf, super.size) - != super.crc) { + != super.crc) { printf("wrong crc on env\n"); goto out; } - + size = super.size; - + while (size) { struct envfs_inode *inode; - + inode = (struct envfs_inode *)buf; - + if (inode->magic != ENVFS_INODE_MAGIC) { printf("envfs: wrong magic on %s\n", filename); ret = -EIO; goto out; } - - debug("loading %s size %d namelen %d\n", inode->data, inode->size, inode->namelen); - + + debug("loading %s size %d namelen %d\n", inode->data, + inode->size, inode->namelen); + str = concat_path_file(dir, inode->data); tmp = strdup(str); make_directory(dirname(tmp)); free(tmp); - + fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); free(str); if (fd < 0) { @@ -317,16 +245,19 @@ int envfs_load(char *filename, char *dir) } namelen_full = PAD4(inode->namelen); - ret = write(fd, buf + namelen_full + sizeof(struct envfs_inode), inode->size); + ret = write(fd, buf + namelen_full + sizeof(struct envfs_inode), + inode->size); if (ret < inode->size) { perror("write"); close(fd); goto out; } close(fd); - - buf += PAD4(inode->namelen) + PAD4(inode->size) + sizeof(struct envfs_inode); - size -= PAD4(inode->namelen) + PAD4(inode->size) + sizeof(struct envfs_inode); + + buf += PAD4(inode->namelen) + PAD4(inode->size) + + sizeof(struct envfs_inode); + size -= PAD4(inode->namelen) + PAD4(inode->size) + + sizeof(struct envfs_inode); } ret = 0; @@ -336,48 +267,3 @@ out: free(buf_free); return ret; } - -#ifdef __U_BOOT__ -static int do_loadenv(cmd_tbl_t *cmdtp, int argc, char *argv[]) -{ - char *filename, *dirname; - - if (argc < 3) - dirname = "/env"; - else - dirname = argv[2]; - if (argc < 2) - filename = "/dev/env0"; - else - filename = argv[1]; - printf("loading environment from %s\n", filename); - return envfs_load(filename, dirname); -} - -static __maybe_unused char cmd_loadenv_help[] = -"Usage: loadenv [ENVFS] [DIRECTORY]\n" -"Load the persistent storage contained in to the directory\n" -".\n" -"If ommitted defaults to /env and defaults to /dev/env0.\n" -"Note that envfs can only handle files. Directories are skipped silently.\n"; - -U_BOOT_CMD_START(loadenv) - .maxargs = 3, - .cmd = do_loadenv, - .usage = "load environment from persistent storage", - U_BOOT_CMD_HELP(cmd_loadenv_help) -U_BOOT_CMD_END -#endif /* __U_BOOT__ */ - -/** - * @page loadenv_command loadenv - * - * Usage: loadenv [\] [\] - * - * Load the persistent storage contained in \ to the directory \. - * - * If ommitted \ defaults to /env and \ defaults to - * \b /dev/env0. - * - * @note envfs can only handle files. Directories are skipped silently. - */ diff --git a/include/environment.h b/include/environment.h index 6612134d3..a50fc6857 100644 --- a/include/environment.h +++ b/include/environment.h @@ -24,6 +24,8 @@ #ifndef _ENVIRONMENT_H_ #define _ENVIRONMENT_H_ + +#ifdef __U_BOOT__ /** * Managment of a environment variable */ @@ -53,8 +55,26 @@ int envfs_save(char *filename, char *dirname); int export(const char *); +struct stat; +int file_size_action(const char *, struct stat *, void *, int); +int file_save_action(const char *, struct stat *, void *, int); + +#endif /* __U_BOOT__ */ + +/* This part is used for the host and the target */ +struct action_data { + int fd; + const char *base; + void *writep; +}; +#define PAD4(x) ((x + 3) & ~3) + #endif /* _ENVIRONMENT_H_ */ -/** @file +/** + * @file * @brief Environment handling + * + * Important: This file will also be used on the host to create + * the default environment when building the U-Boot binary. */ diff --git a/scripts/ubootenv.c b/scripts/ubootenv.c index c072c974c..32da113b5 100644 --- a/scripts/ubootenv.c +++ b/scripts/ubootenv.c @@ -119,7 +119,8 @@ char *concat_subpath_file(const char *path, const char *f) #include "../include/envfs.h" #include "../lib/crc32.c" #include "../lib/make_directory.c" -#include "../commands/environment.c" +#include "../include/environment.h" +#include "../common/environment.c" void usage(char *prgname) {