From f97f4b6571d1297973f08b9f921778e0b2e7f064 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 7 Feb 2014 22:28:12 +0100 Subject: mount: support filesystem options passed via -o MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to mount(8) the barebox command mount now supports passing a string to the file system driver via -o. This is used in the next commit to let the user specify port numbers for nfs mounts. Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- common/blspec.c | 2 +- common/startup.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/blspec.c b/common/blspec.c index 2244d5a8a8..df3c9c3c65 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -276,7 +276,7 @@ static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev) if (type == filetype_mbr || type == filetype_gpt) return -EINVAL; - rootpath = cdev_mount_default(cdev); + rootpath = cdev_mount_default(cdev, NULL); if (IS_ERR(rootpath)) return PTR_ERR(rootpath); diff --git a/common/startup.c b/common/startup.c index e8b9ea0216..0b5fe46adb 100644 --- a/common/startup.c +++ b/common/startup.c @@ -89,9 +89,9 @@ device_initcall(register_default_env); #if defined CONFIG_FS_RAMFS && defined CONFIG_FS_DEVFS static int mount_root(void) { - mount("none", "ramfs", "/"); + mount("none", "ramfs", "/", NULL); mkdir("/dev", 0); - mount("none", "devfs", "/dev"); + mount("none", "devfs", "/dev", NULL); return 0; } fs_initcall(mount_root); -- cgit v1.2.3 From 93578fb2333bba3d1c2d0fa41de11ba4f92f9aed Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 27 Feb 2014 12:23:29 +0100 Subject: run_command: remove unused flag parameter Signed-off-by: Sascha Hauer --- commands/boot.c | 2 +- commands/exec.c | 2 +- commands/login.c | 2 +- commands/time.c | 2 +- common/hush.c | 2 +- common/menu.c | 2 +- common/parser.c | 7 +++---- common/startup.c | 4 ++-- fs/fs.c | 2 +- include/common.h | 3 +-- 10 files changed, 13 insertions(+), 15 deletions(-) (limited to 'common') diff --git a/commands/boot.c b/commands/boot.c index c4b49a9035..fea7b54332 100644 --- a/commands/boot.c +++ b/commands/boot.c @@ -47,7 +47,7 @@ static int boot_script(char *path) globalvar_set_match("linux.bootargs.dyn.", ""); globalvar_set_match("bootm.", ""); - ret = run_command(path, 0); + ret = run_command(path); if (ret) { printf("Running %s failed\n", path); goto out; diff --git a/commands/exec.c b/commands/exec.c index bd7d54afd2..8d12b30ec9 100644 --- a/commands/exec.c +++ b/commands/exec.c @@ -39,7 +39,7 @@ static int do_exec(int argc, char *argv[]) if (!script) return 1; - if (run_command (script, 0) == -1) + if (run_command(script) == -1) goto out; free(script); } diff --git a/commands/login.c b/commands/login.c index b616bf15fc..d9297fa370 100644 --- a/commands/login.c +++ b/commands/login.c @@ -68,7 +68,7 @@ static int do_login(int argc, char *argv[]) if (passwd_len < 0) { console_allow_input(false); - run_command(timeout_cmd, 0); + run_command(timeout_cmd); } if (check_passwd(passwd, passwd_len)) diff --git a/commands/time.c b/commands/time.c index 987c25ef73..2cc3292d7b 100644 --- a/commands/time.c +++ b/commands/time.c @@ -27,7 +27,7 @@ static int do_time(int argc, char *argv[]) start = get_time_ns(); - run_command(buf, 0); + run_command(buf); end = get_time_ns(); diff --git a/common/hush.c b/common/hush.c index abe2ceda07..bd534c12f5 100644 --- a/common/hush.c +++ b/common/hush.c @@ -1824,7 +1824,7 @@ static char * make_string(char ** inp) return str; } -int run_command (const char *cmd, int flag) +int run_command(const char *cmd) { struct p_context ctx; int ret; diff --git a/common/menu.c b/common/menu.c index ef56190604..114c36efcc 100644 --- a/common/menu.c +++ b/common/menu.c @@ -468,7 +468,7 @@ static void menu_action_command(struct menu *m, struct menu_entry *me) if (!s) s = e->command; - ret = run_command (s, 0); + ret = run_command(s); if (ret < 0) udelay(1000000); diff --git a/common/parser.c b/common/parser.c index d390fb6afe..4a48210c4d 100644 --- a/common/parser.c +++ b/common/parser.c @@ -176,7 +176,7 @@ static void process_macros (const char *input, char *output) * creates or modifies environment variables (like "bootp" does). */ -int run_command (const char *cmd, int flag) +int run_command(const char *cmd) { char cmdbuf[CONFIG_CBSIZE]; /* working copy of cmd */ char *token; /* start of token in cmdbuf */ @@ -265,18 +265,17 @@ int run_shell(void) static char lastcommand[CONFIG_CBSIZE] = { 0, }; int len; int rc = 1; - int flag; + for (;;) { len = readline (CONFIG_PROMPT, console_buffer, CONFIG_CBSIZE); - flag = 0; /* assume no special flags for now */ if (len > 0) strcpy (lastcommand, console_buffer); if (len == -1) puts ("\n"); else - rc = run_command (lastcommand, flag); + rc = run_command(lastcommand); if (rc <= 0) { /* invalid command or not repeatable, forget it */ diff --git a/common/startup.c b/common/startup.c index 0b5fe46adb..04f8cf06e3 100644 --- a/common/startup.c +++ b/common/startup.c @@ -137,11 +137,11 @@ void __noreturn start_barebox(void) pr_info("running /env/bin/init...\n"); if (!stat("/env/bin/init", &s)) { - run_command("source /env/bin/init", 0); + run_command("source /env/bin/init"); } else { pr_err("/env/bin/init not found\n"); if (IS_ENABLED(CONFIG_CMD_LOGIN)) - while(run_command("login -t 0", 0)); + while(run_command("login -t 0")); } } diff --git a/fs/fs.c b/fs/fs.c index 7a57bc0670..bb849cb3b9 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -434,7 +434,7 @@ static void automount_mount(const char *path, int instat) setenv("automount_path", am->path); export("automount_path"); - ret = run_command(am->cmd, 0); + ret = run_command(am->cmd); setenv("automount_path", NULL); if (ret) diff --git a/include/common.h b/include/common.h index 293f5041af..6987b4f16d 100644 --- a/include/common.h +++ b/include/common.h @@ -92,8 +92,7 @@ void __noreturn panic(const char *fmt, ...); char *size_human_readable(unsigned long long size); -/* common/main.c */ -int run_command (const char *cmd, int flag); +int run_command(const char *cmd); int readline (const char *prompt, char *buf, int len); /* common/memsize.c */ -- cgit v1.2.3 From a162dfe50345d3461010759f8a0e79f7e388c140 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 28 Feb 2014 08:39:27 +0100 Subject: net: Add ifup support The defaultenv-2 has ifup support as a shell script. This patch replaces it with a command which is more robust, can be called from C and now can also bring up all configured interfaces. Signed-off-by: Sascha Hauer --- common/Kconfig | 1 + defaultenv-2/base/bin/ifup | 67 ----------------- include/net.h | 5 ++ net/Kconfig | 11 +++ net/Makefile | 1 + net/ifup.c | 179 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 197 insertions(+), 67 deletions(-) delete mode 100644 defaultenv-2/base/bin/ifup create mode 100644 net/ifup.c (limited to 'common') diff --git a/common/Kconfig b/common/Kconfig index 8af7ec1a8d..2e91cd7a6c 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -582,6 +582,7 @@ config DEFAULT_ENVIRONMENT_GENERIC_NEW select CMD_DIRNAME select FLEXIBLE_BOOTARGS select CMD_BOOT + select NET_CMD_IFUP if NET prompt "Generic environment template" config DEFAULT_ENVIRONMENT_GENERIC diff --git a/defaultenv-2/base/bin/ifup b/defaultenv-2/base/bin/ifup deleted file mode 100644 index 37b986c44b..0000000000 --- a/defaultenv-2/base/bin/ifup +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -mkdir -p /tmp/network - -if [ $# != 1 ]; then - echo "usage: ifup " - exit 1 -fi - -interface="$1" - -if [ -f /tmp/network/$interface ]; then - exit 0 -fi - -cmd=/env/network/$interface - -if [ ! -e $cmd ]; then - echo "$f: no such file" - exit 1 -fi - -ip= -ipaddr= -netmask= -gateway= -serverip= -ethaddr= - -. $cmd - -if [ $? != 0 ]; then - echo "failed to bring up $interface" - exit 1 -fi - -if [ -f /env/network/${interface}-discover ]; then - /env/network/${interface}-discover - if [ $? != 0 ]; then - echo "failed to discover eth0" - exit 1 - fi -fi - -if [ -n "$ethaddr" ]; then - ${interface}.ethaddr=$ethaddr -fi - -if [ "$ip" = static ]; then - ${interface}.ipaddr=$ipaddr - ${interface}.netmask=$netmask - ${interface}.serverip=$serverip - ${interface}.gateway=$gateway - ret=0 -elif [ "$ip" = dhcp ]; then - dhcp - ret=$? - if [ $ret = 0 -a -n "$serverip" ]; then - ${interface}.serverip=$serverip - fi -fi - -if [ $ret = 0 ]; then - echo -o /tmp/network/$interface up -fi - -exit $ret diff --git a/include/net.h b/include/net.h index a680f972ed..3b800b78f0 100644 --- a/include/net.h +++ b/include/net.h @@ -457,4 +457,9 @@ int net_icmp_send(struct net_connection *con, int len); void led_trigger_network(enum led_trigger trigger); +#define IFUP_FLAG_FORCE (1 << 0) + +int ifup(const char *name, unsigned flags); +int ifup_all(unsigned flags); + #endif /* __NET_H__ */ diff --git a/net/Kconfig b/net/Kconfig index c12193db5c..59b64175de 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -26,4 +26,15 @@ config NET_RESOLV bool prompt "dns support" +config NET_IFUP + default y + bool + +config NET_CMD_IFUP + bool + prompt "ifup support" + help + This enables the 'ifup' command which is used to bring up network + interfaces based on config files under /env/network/ + endif diff --git a/net/Makefile b/net/Makefile index 416e30ac35..fabb17e4a8 100644 --- a/net/Makefile +++ b/net/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_NET_NFS) += nfs.o obj-$(CONFIG_NET_PING) += ping.o obj-$(CONFIG_NET_RESOLV)+= dns.o obj-$(CONFIG_NET_NETCONSOLE) += netconsole.o +obj-$(CONFIG_NET_IFUP) += ifup.o diff --git a/net/ifup.c b/net/ifup.c new file mode 100644 index 0000000000..3b89ce1bc2 --- /dev/null +++ b/net/ifup.c @@ -0,0 +1,179 @@ +/* + * ifup.c - bring up network interfaces + * + * Copyright (c) 2014 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 detaiifup. + * + */ +#define pr_fmt(fmt) "ifup: " fmt + +#include +#include +#include +#include +#include +#include +#include + +static char *vars[] = { + "ipaddr", + "netmask", + "gateway", + "serverip", + "ethaddr", +}; + +static int eth_set_param(struct device_d *dev, const char *param) +{ + const char *value = getenv(param); + + if (!value) + return 0; + if (!*value) + return 0; + + return dev_set_param(dev, param, value); +} + +int ifup(const char *name, unsigned flags) +{ + int ret; + char *cmd, *cmd_discover; + const char *ip; + struct stat s; + int i; + struct device_d *dev; + struct eth_device *edev = eth_get_byname(name); + + if (edev && edev->ipaddr && !(flags & IFUP_FLAG_FORCE)) + return 0; + + env_push_context(); + + setenv("ip", ""); + + for (i = 0; i < ARRAY_SIZE(vars); i++) + setenv(vars[i], ""); + + cmd = asprintf("source /env/network/%s", name); + cmd_discover = asprintf("/env/network/%s-discover", name); + + ret = run_command(cmd); + if (ret) + goto out; + + ret = stat(cmd_discover, &s); + if (!ret) { + ret = run_command(cmd_discover); + if (ret) + goto out; + } + + dev = get_device_by_name(name); + if (!dev) { + pr_err("Cannot find device %s\n", name); + goto out; + } + + ret = eth_set_param(dev, "ethaddr"); + if (ret) + goto out; + + ip = getenv("ip"); + if (!strcmp(ip, "dhcp")) { + ret = run_command("dhcp"); + if (ret) + goto out; + } else if (!strcmp(ip, "static")) { + for (i = 0; i < ARRAY_SIZE(vars); i++) { + ret = eth_set_param(dev, vars[i]); + if (ret) + goto out; + } + } else { + pr_err("unknown ip type: %s\n", ip); + ret = -EINVAL; + goto out; + } + + ret = 0; +out: + env_pop_context(); + free(cmd); + free(cmd_discover); + + return ret; +} + +int ifup_all(unsigned flags) +{ + DIR *dir; + struct dirent *d; + + dir = opendir("/env/network"); + if (!dir) + return -ENOENT; + + while ((d = readdir(dir))) { + if (*d->d_name == '.') + continue; + ifup(d->d_name, flags); + } + + closedir(dir); + + return 0; +} + +#if IS_ENABLED(CONFIG_NET_CMD_IFUP) + +static int do_ifup(int argc, char *argv[]) +{ + int opt; + unsigned flags = 0; + int all = 0; + + while ((opt = getopt(argc, argv, "af")) > 0) { + switch (opt) { + case 'f': + flags |= IFUP_FLAG_FORCE; + break; + case 'a': + all = 1; + break; + } + } + + if (all) + return ifup_all(flags); + + if (argc == optind) + return COMMAND_ERROR_USAGE; + + return ifup(argv[optind], flags); +} + +BAREBOX_CMD_HELP_START(ifup) +BAREBOX_CMD_HELP_USAGE("ifup [OPTIONS] \n") +BAREBOX_CMD_HELP_OPT ("-a", "bring up all interfaces\n") +BAREBOX_CMD_HELP_OPT ("-f", "Force. Configure even if ip already set\n") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(ifup) + .cmd = do_ifup, + .usage = "Bring up network interfaces", + BAREBOX_CMD_HELP(cmd_ifup_help) +BAREBOX_CMD_END + +#endif -- cgit v1.2.3 From 86f681abec4f8485d2e95537e0d59a8d9ab6b546 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 13 Feb 2014 10:38:23 +0100 Subject: blspec: Add NFS support With this barebox can start root filesystems containing bootloader spec entries via NFS. It is used as: boot nfs://[: --- common/blspec.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/blspec.c b/common/blspec.c index df3c9c3c65..9b4b096a0a 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -10,6 +10,8 @@ * GNU General Public License for more details. * */ +#define pr_fmt(fmt) "blspec: " fmt + #include #include #include @@ -22,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +133,107 @@ static int blspec_have_entry(struct blspec *blspec, const char *path) return 0; } +/* + * nfs_find_mountpath - Check if a given url is already mounted + */ +static const char *nfs_find_mountpath(const char *nfshostpath) +{ + struct fs_device_d *fsdev; + + for_each_fs_device(fsdev) { + if (fsdev->backingstore && !strcmp(fsdev->backingstore, nfshostpath)) + return fsdev->path; + } + + return NULL; +} + +/* + * parse_nfs_url - check for nfs:// style url + * + * Check if the passed string is a NFS url and if yes, mount the + * NFS and return the path we have mounted to. + */ +static char *parse_nfs_url(const char *url) +{ + char *sep, *str, *host, *port, *path; + char *mountpath = NULL, *hostpath = NULL, *options = NULL; + const char *prevpath; + IPaddr_t ip; + int ret; + + if (!IS_ENABLED(CONFIG_FS_NFS)) + return ERR_PTR(-ENOSYS); + + if (strncmp(url, "nfs://", 6)) + return ERR_PTR(-EINVAL); + + url += 6; + + str = xstrdup(url); + + host = str; + + sep = strchr(str, '/'); + if (!sep) { + ret = -EINVAL; + goto out; + } + + *sep++ = 0; + + path = sep; + + port = strchr(host, ':'); + if (port) + *port++ = 0; + + ret = ifup_all(0); + if (ret) { + pr_err("Failed to bring up networking\n"); + goto out; + } + + ip = resolv(host); + if (ip == 0) + goto out; + + hostpath = asprintf("%s:%s", ip_to_string(ip), path); + + prevpath = nfs_find_mountpath(hostpath); + + if (prevpath) { + mountpath = xstrdup(prevpath); + } else { + mountpath = asprintf("/mnt/nfs-%s-blspec-%08x", host, rand()); + if (port) + options = asprintf("mountport=%s,port=%s", port, port); + + ret = make_directory(mountpath); + if (ret) + goto out; + + pr_debug("host: %s port: %s path: %s\n", host, port, path); + pr_debug("hostpath: %s mountpath: %s options: %s\n", hostpath, mountpath, options); + + ret = mount(hostpath, "nfs", mountpath, options); + if (ret) + goto out; + } + + ret = 0; + +out: + free(str); + free(hostpath); + free(options); + + if (ret) + free(mountpath); + + return ret ? ERR_PTR(ret) : mountpath; +} + /* * blspec_scan_directory - scan over a directory * @@ -145,9 +249,13 @@ int blspec_scan_directory(struct blspec *blspec, const char *root) char *abspath; int ret, found = 0; const char *dirname = "loader/entries"; - char *entry_default = NULL, *entry_once = NULL, *name; + char *entry_default = NULL, *entry_once = NULL, *name, *nfspath = NULL; + + nfspath = parse_nfs_url(root); + if (!IS_ERR(nfspath)) + root = nfspath; - pr_debug("%s: %s %s\n", __func__, root, dirname); + pr_info("%s: %s %s\n", __func__, root, dirname); entry_default = read_file_line("%s/default", root); entry_once = read_file_line("%s/once", root); @@ -239,6 +347,8 @@ int blspec_scan_directory(struct blspec *blspec, const char *root) closedir(dir); err_out: + if (!IS_ERR(nfspath)) + free(nfspath); free(abspath); free(entry_default); free(entry_once); -- cgit v1.2.3