diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 44 | ||||
-rw-r--r-- | common/Makefile | 2 | ||||
-rw-r--r-- | common/command.c | 20 | ||||
-rw-r--r-- | common/environment.c | 150 | ||||
-rw-r--r-- | common/filetype.c | 20 | ||||
-rw-r--r-- | common/hush.c | 45 | ||||
-rw-r--r-- | common/menu.c | 17 |
7 files changed, 232 insertions, 66 deletions
diff --git a/common/Kconfig b/common/Kconfig index 7eb5b49a8f..b97392cfdb 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -101,6 +101,48 @@ config ENVIRONMENT_VARIABLES menu "memory layout " +config HAVE_PBL_IMAGE + bool + +config HAVE_IMAGE_COMPRESSION + bool + +config PBL_IMAGE + bool "Pre-Bootloader image" + depends on HAVE_PBL_IMAGE + +config PBL_FORCE_PIGGYDATA_COPY + bool + help + In some case we need to copy the PIGGYDATA as the link address + as example we run from SRAM and shutdown the SDRAM/DDR for + reconfiguration but most of the time we just need to copy the + executable code. + +if PBL_IMAGE + +config IMAGE_COMPRESSION + bool + depends on HAVE_IMAGE_COMPRESSION + default y + +if IMAGE_COMPRESSION + +choice + prompt "Compression" + +config IMAGE_COMPRESSION_LZO + bool "lzo" + +config IMAGE_COMPRESSION_GZIP + bool "gzip" + +endchoice + +endif + +endif + config MMU bool "Enable MMU" help @@ -481,6 +523,8 @@ config DEFAULT_ENVIRONMENT config DEFAULT_ENVIRONMENT_COMPRESSED bool depends on DEFAULT_ENVIRONMENT + depends on !IMAGE_COMPRESSION_LZO + depends on !IMAGE_COMPRESSION_GZIP default y if ZLIB default y if BZLIB default y if LZO_DECOMPRESS diff --git a/common/Makefile b/common/Makefile index d74dffb916..df9f301234 100644 --- a/common/Makefile +++ b/common/Makefile @@ -58,7 +58,7 @@ ifneq ($(CONFIG_DEFAULT_ENVIRONMENT_PATH),"") DEFAULT_ENVIRONMENT_PATH += $(CONFIG_DEFAULT_ENVIRONMENT_PATH) endif -ENV_FILES := $(shell cd $(srctree); for i in $(DEFAULT_ENVIRONMENT_PATH); do find $${i} -type f -exec readlink -f '{}' \;; done) +ENV_FILES := $(shell cd $(srctree); for i in $(DEFAULT_ENVIRONMENT_PATH); do find $${i} -type f ; done) endif # ifdef CONFIG_DEFAULT_ENVIRONMENT diff --git a/common/command.c b/common/command.c index c18998c129..2bfc5117e8 100644 --- a/common/command.c +++ b/common/command.c @@ -38,26 +38,6 @@ LIST_HEAD(command_list); EXPORT_SYMBOL(command_list); -#ifdef CONFIG_SHELL_HUSH - -static int do_exit(int argc, char *argv[]) -{ - int r; - - r = 0; - if (argc > 1) - r = simple_strtoul(argv[1], NULL, 0); - - return -r - 2; -} - -BAREBOX_CMD_START(exit) - .cmd = do_exit, - .usage = "exit script", -BAREBOX_CMD_END - -#endif - void barebox_cmd_usage(struct command *cmdtp) { #ifdef CONFIG_LONGHELP diff --git a/common/environment.c b/common/environment.c index 52ce0de1da..ce46f4a0e6 100644 --- a/common/environment.c +++ b/common/environment.c @@ -53,7 +53,21 @@ int file_size_action(const char *filename, struct stat *statbuf, data->writep += sizeof(struct envfs_inode); data->writep += PAD4(strlen(filename) + 1 - strlen(data->base)); - data->writep += PAD4(statbuf->st_size); + data->writep += sizeof(struct envfs_inode_end); + if (S_ISLNK(statbuf->st_mode)) { + char path[PATH_MAX]; + + memset(path, 0, PATH_MAX); + + if (readlink(filename, path, PATH_MAX - 1) < 0) { + perror("read"); + return 0; + } + data->writep += PAD4(strlen(path) + 1); + } else { + data->writep += PAD4(statbuf->st_size); + } + return 1; } @@ -62,34 +76,60 @@ int file_save_action(const char *filename, struct stat *statbuf, { 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); - 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_32(ENVFS_INODE_MAGIC); - inode->namelen = ENVFS_32(namelen); - inode->size = ENVFS_32(statbuf->st_size); + inode->headerlen = ENVFS_32(PAD4(namelen + sizeof(struct envfs_inode_end))); data->writep += sizeof(struct envfs_inode); strcpy(data->writep, filename + strlen(data->base)); data->writep += PAD4(namelen); + inode_end = (struct envfs_inode_end*)data->writep; + data->writep += sizeof(struct envfs_inode_end); + inode_end->magic = ENVFS_32(ENVFS_INODE_END_MAGIC); + inode_end->mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO); - fd = open(filename, O_RDONLY); - if (fd < 0) { - printf("Open %s %s\n", filename, errno_str()); - goto out; - } + if (S_ISLNK(statbuf->st_mode)) { + char path[PATH_MAX]; + int len; - if (read(fd, data->writep, statbuf->st_size) < statbuf->st_size) { - perror("read"); - goto out; - } - close(fd); + memset(path, 0, PATH_MAX); + + if (readlink(filename, path, PATH_MAX - 1) < 0) { + perror("read"); + goto out; + } + len = strlen(path) + 1; + + inode_end->mode |= ENVFS_32(S_IFLNK); + + memcpy(data->writep, path, len); + inode->size = ENVFS_32(len); + data->writep += PAD4(len); + debug("handling symlink %s size %ld namelen %d headerlen %d\n", filename + strlen(data->base), + len, namelen, ENVFS_32(inode->headerlen)); + } else { + debug("handling file %s size %ld namelen %d headerlen %d\n", filename + strlen(data->base), + statbuf->st_size, namelen, ENVFS_32(inode->headerlen)); - data->writep += PAD4(statbuf->st_size); + 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); + } out: return 1; @@ -125,6 +165,8 @@ int envfs_save(char *filename, char *dirname) super = (struct envfs_super *)buf; super->magic = ENVFS_32(ENVFS_MAGIC); + super->major = ENVFS_MAJOR; + super->minor = ENVFS_MINOR; super->size = ENVFS_32(size); /* second pass: copy files to buffer */ @@ -174,8 +216,13 @@ int envfs_load(char *filename, char *dir) int envfd; int fd, ret = 0; char *str, *tmp; - int namelen_full; + int headerlen_full; unsigned long size; + /* for envfs < 1.0 */ + struct envfs_inode_end inode_end_dummy; + + inode_end_dummy.mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO); + inode_end_dummy.magic = ENVFS_32(ENVFS_INODE_END_MAGIC); envfd = open(filename, O_RDONLY); if (envfd < 0) { @@ -221,11 +268,18 @@ int envfs_load(char *filename, char *dir) goto out; } + if (super.major < ENVFS_MAJOR) + printf("envfs version %d.%d loaded into %d.%d\n", + super.major, super.minor, + ENVFS_MAJOR, ENVFS_MINOR); + while (size) { struct envfs_inode *inode; - uint32_t inode_size, inode_namelen; + struct envfs_inode_end *inode_end; + uint32_t inode_size, inode_headerlen, namelen; inode = (struct envfs_inode *)buf; + buf += sizeof(struct envfs_inode); if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) { printf("envfs: wrong magic on %s\n", filename); @@ -233,38 +287,58 @@ int envfs_load(char *filename, char *dir) goto out; } inode_size = ENVFS_32(inode->size); - inode_namelen = ENVFS_32(inode->namelen); + inode_headerlen = ENVFS_32(inode->headerlen); + namelen = strlen(inode->data) + 1; + if (super.major < 1) + inode_end = &inode_end_dummy; + else + inode_end = (struct envfs_inode_end *)(buf + PAD4(namelen)); - debug("loading %s size %d namelen %d\n", inode->data, - inode_size, inode_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); - fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); - free(str); - if (fd < 0) { - printf("Open %s\n", errno_str()); - ret = fd; + headerlen_full = PAD4(inode_headerlen); + buf += headerlen_full; + + if (ENVFS_32(inode_end->magic) != ENVFS_INODE_END_MAGIC) { + printf("envfs: wrong inode_end_magic on %s\n", filename); + ret = -EIO; goto out; } - namelen_full = PAD4(inode_namelen); - ret = write(fd, buf + namelen_full + sizeof(struct envfs_inode), - inode_size); - if (ret < inode_size) { - perror("write"); - ret = -errno; + 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(""); + } + free(str); + } else { + fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); + free(str); + if (fd < 0) { + printf("Open %s\n", errno_str()); + ret = fd; + goto out; + } + + ret = write(fd, buf, inode_size); + if (ret < inode_size) { + perror("write"); + ret = -errno; + close(fd); + goto out; + } close(fd); - goto out; } - close(fd); - buf += PAD4(inode_namelen) + PAD4(inode_size) + - sizeof(struct envfs_inode); - size -= PAD4(inode_namelen) + PAD4(inode_size) + + buf += PAD4(inode_size); + size -= headerlen_full + PAD4(inode_size) + sizeof(struct envfs_inode); } diff --git a/common/filetype.c b/common/filetype.c index 1a5b82da47..e736d43efe 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -22,6 +22,7 @@ #include <common.h> #include <filetype.h> #include <asm/byteorder.h> +#include <asm/unaligned.h> #include <fcntl.h> #include <fs.h> #include <malloc.h> @@ -40,6 +41,7 @@ static const char *filetype_str[] = { [filetype_aimage] = "Android boot image", [filetype_sh] = "Bourne Shell", [filetype_mips_barebox] = "MIPS barebox image", + [filetype_fat] = "FAT filesytem", }; const char *file_type_to_string(enum filetype f) @@ -50,6 +52,22 @@ const char *file_type_to_string(enum filetype f) return NULL; } +static int is_fat(u8 *buf) +{ + if (get_unaligned_le16(&buf[510]) != 0xAA55) + return 0; + + /* FAT */ + if ((get_unaligned_le32(&buf[54]) & 0xFFFFFF) == 0x544146) + return 1; + + /* FAT32 */ + if ((get_unaligned_le32(&buf[82]) & 0xFFFFFF) == 0x544146) + return 1; + + return 0; +} + enum filetype file_detect_type(void *_buf) { u32 *buf = _buf; @@ -81,6 +99,8 @@ enum filetype file_detect_type(void *_buf) return filetype_aimage; if (strncmp(buf8 + 0x10, "barebox", 7) == 0) return filetype_mips_barebox; + if (is_fat(buf8)) + return filetype_fat; return filetype_unknown; } diff --git a/common/hush.c b/common/hush.c index 8200931387..61aac13d1b 100644 --- a/common/hush.c +++ b/common/hush.c @@ -557,6 +557,18 @@ static int builtin_getopt(struct p_context *ctx, struct child_prog *child, } #endif +static int builtin_exit(struct p_context *ctx, struct child_prog *child, + int argc, char *argv[]) +{ + int r; + + r = last_return_code; + if (argc > 1) + r = simple_strtoul(argv[1], NULL, 0); + + return -r - 2; +} + static void remove_quotes_in_str(char *src) { char *trg = src; @@ -773,10 +785,17 @@ static int run_pipe_real(struct p_context *ctx, struct pipe *pi) remove_quotes(globbuf.gl_pathc, globbuf.gl_pathv); - if (!strcmp(globbuf.gl_pathv[0], "getopt")) + if (!strcmp(globbuf.gl_pathv[0], "getopt")) { ret = builtin_getopt(ctx, child, globbuf.gl_pathc, globbuf.gl_pathv); - else + } else if (!strcmp(globbuf.gl_pathv[0], "exit")) { + ret = builtin_exit(ctx, child, globbuf.gl_pathc, globbuf.gl_pathv); + } else { ret = execute_binfmt(globbuf.gl_pathc, globbuf.gl_pathv); + if (ret < 0) { + printf("%s: %s\n", globbuf.gl_pathv[0], strerror(-ret)); + ret = 127; + } + } globfree(&globbuf); @@ -1885,16 +1904,28 @@ BAREBOX_CMD_START(source) BAREBOX_CMD_HELP(cmd_source_help) BAREBOX_CMD_END -#ifdef CONFIG_HUSH_GETOPT -static int do_getopt(int argc, char *argv[]) +static int do_dummy_command(int argc, char *argv[]) { /* - * This function is never reached. The 'getopt' command is - * only here to provide a help text for the getopt builtin. + * This function is never reached. These commands are only here to + * provide help texts for the builtins. */ return 0; } +static const __maybe_unused char cmd_exit_help[] = +"Usage: exit [n]\n" +"\n" +"exit script with a status of n. If n is omitted, the exit status is that\n" +"of the last command executed\n"; + +BAREBOX_CMD_START(exit) + .cmd = do_dummy_command, + .usage = "exit script", + BAREBOX_CMD_HELP(cmd_exit_help) +BAREBOX_CMD_END + +#ifdef CONFIG_HUSH_GETOPT static const __maybe_unused char cmd_getopt_help[] = "Usage: getopt <optstring> <var>\n" "\n" @@ -1905,7 +1936,7 @@ static const __maybe_unused char cmd_getopt_help[] = "can be accessed starting from $1\n"; BAREBOX_CMD_START(getopt) - .cmd = do_getopt, + .cmd = do_dummy_command, .usage = "getopt <optstring> <var>", BAREBOX_CMD_HELP(cmd_getopt_help) BAREBOX_CMD_END diff --git a/common/menu.c b/common/menu.c index 9f536d6aee..97c6b184bd 100644 --- a/common/menu.c +++ b/common/menu.c @@ -314,6 +314,23 @@ int menu_show(struct menu *m) m->auto_select = -1; switch (ch) { + case '0' ... '9': { + struct menu_entry *me; + int num = ch - '0'; + int next_num = m->selected->num + 10; + if (!num) + num = 10; + + if (ch_previous == ch && next_num <= m->nb_entries) + num = next_num; + + me = menu_entry_get_by_num(m, num); + if (me) { + m->selected = me; + repaint = 1; + } + break; + } case KEY_UP: m->selected = list_entry(m->selected->list.prev, struct menu_entry, list); |