From a1ae46665fd5a8ff9a066db3d41b44527ee2a1e7 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Tue, 7 May 2024 13:44:34 +0200 Subject: [PATCH 1/6] cpu/native: be less verbose on startup --- boards/native/board_init.c | 9 --------- cpu/native/irq_cpu.c | 2 +- cpu/native/periph/pm.c | 2 +- cpu/native/startup.c | 2 +- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/boards/native/board_init.c b/boards/native/board_init.c index 0bb579c7aa35..085f887f209f 100644 --- a/boards/native/board_init.c +++ b/boards/native/board_init.c @@ -72,12 +72,3 @@ VFS_AUTO_MOUNT(native, { .hostpath = FS_NATIVE_DIR }, VFS_DEFAULT_NVM(0), 0); #endif #endif /* MODULE_VFS_DEFAULT */ - -/** - * Nothing to initialize at the moment. - * Turns the red LED on and the green LED off. - */ -void board_init(void) -{ - puts("RIOT native board initialized."); -} diff --git a/cpu/native/irq_cpu.c b/cpu/native/irq_cpu.c index c5e404115ae4..845fd4d84e18 100644 --- a/cpu/native/irq_cpu.c +++ b/cpu/native/irq_cpu.c @@ -555,6 +555,6 @@ void native_interrupt_init(void) err(EXIT_FAILURE, "native_interrupt_init: sigaction"); } - puts("RIOT native interrupts/signals initialized."); + DEBUG_PUTS("RIOT native interrupts/signals initialized."); } /** @} */ diff --git a/cpu/native/periph/pm.c b/cpu/native/periph/pm.c index a1215163effd..0ce3155415c8 100644 --- a/cpu/native/periph/pm.c +++ b/cpu/native/periph/pm.c @@ -66,7 +66,7 @@ void pm_set(unsigned mode) void pm_off(void) { - puts("\nnative: exiting"); + DEBUG_PUTS("\nnative: exiting"); #ifdef MODULE_PERIPH_SPIDEV_LINUX spidev_linux_teardown(); #endif diff --git a/cpu/native/startup.c b/cpu/native/startup.c index 5ee0515ff40e..3deca8f7d34a 100644 --- a/cpu/native/startup.c +++ b/cpu/native/startup.c @@ -729,7 +729,7 @@ __attribute__((constructor)) static void startup(int argc, char **argv, char **e register_interrupt(SIGUSR1, _reset_handler); - puts("RIOT native hardware initialization complete.\n"); + DEBUG_PUTS("RIOT native hardware initialization complete.\n"); irq_enable(); kernel_init(); } From dc5f7e73322bd4cf453a7d69a29223a9ac2a7d74 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Tue, 7 May 2024 13:46:09 +0200 Subject: [PATCH 2/6] cpu/native: allow to pass arguments to the application --- core/lib/init.c | 10 ++++++++-- cpu/native/startup.c | 8 ++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/core/lib/init.c b/core/lib/init.c index e6e4c026a964..a65cfbf6c920 100644 --- a/core/lib/init.c +++ b/core/lib/init.c @@ -43,8 +43,6 @@ RIOT_VERSION ")" #endif -extern int main(void); - static char main_stack[THREAD_STACKSIZE_MAIN]; static char idle_stack[THREAD_STACKSIZE_IDLE]; @@ -60,7 +58,15 @@ static void *main_trampoline(void *arg) LOG_INFO(CONFIG_BOOT_MSG_STRING "\n"); } +#ifdef CPU_NATIVE + extern int _native_argc_main; + extern char **_native_argv_main; + extern int main(int argc, char **argv); + int res = main(_native_argc_main, _native_argv_main); +#else + extern int main(void); int res = main(); +#endif if (IS_USED(MODULE_TEST_UTILS_MAIN_EXIT_CB)) { void test_utils_main_exit_cb(int res); diff --git a/cpu/native/startup.c b/cpu/native/startup.c index 3deca8f7d34a..0fd4843f477f 100644 --- a/cpu/native/startup.c +++ b/cpu/native/startup.c @@ -466,6 +466,10 @@ static void _reset_handler(void) pm_reboot(); } +/* allow to pass arguments to the application */ +int _native_argc_main; +char **_native_argv_main; + __attribute__((constructor)) static void startup(int argc, char **argv, char **envp) { _native_init_syscalls(); @@ -718,8 +722,12 @@ __attribute__((constructor)) static void startup(int argc, char **argv, char **e netdev_tap_params[taps].tap_name = &argv[optind + i]; netdev_tap_params[taps].wired = true; } + optind += taps; #endif + _native_argc_main = argc - optind; + _native_argv_main = &argv[optind]; + #ifdef MODULE_PERIPH_EEPROM eeprom_native_read(); #endif From 8db537238af2445f2e00ab4dfcf6376bfe378d4d Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Tue, 7 May 2024 16:01:27 +0200 Subject: [PATCH 3/6] sys/shell: ncput: allow relative paths for source file --- sys/shell/cmds/nanocoap_vfs.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sys/shell/cmds/nanocoap_vfs.c b/sys/shell/cmds/nanocoap_vfs.c index 592b7b2bd7be..6d1afe75a068 100644 --- a/sys/shell/cmds/nanocoap_vfs.c +++ b/sys/shell/cmds/nanocoap_vfs.c @@ -169,19 +169,34 @@ static int _nanocoap_put_handler(int argc, char **argv) file = argv[1]; url = argv[2]; + /* append filename to remote URL */ if (_is_dir(url)) { const char *basename = strrchr(file, '/'); if (basename == NULL) { - return -EINVAL; + basename = file; + } else { + ++basename; } + if (snprintf(buffer, sizeof(buffer), "%s%s", - url, basename + 1) >= (int)sizeof(buffer)) { + url, basename) >= (int)sizeof(buffer)) { puts("Constructed URI too long"); return -ENOBUFS; } url = buffer; } + /* file path is relative to CONFIG_NCGET_DEFAULT_DATA_DIR */ + if (file[0] != '/') { + if ((unsigned)snprintf(work_buf, sizeof(work_buf), "%s%s", + CONFIG_NCGET_DEFAULT_DATA_DIR, file) >= sizeof(work_buf)) { + puts("Constructed URI too long"); + return -ENOBUFS; + } + file = work_buf; + } + + /* read from 'stdin' / 3rd argument */ if (strcmp(file, "-") == 0) { if (argc < 4) { printf("Usage: %s - \n", argv[0]); From 960e584ec9ab6f8f37362f589c52ff2287589168 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Tue, 7 May 2024 16:07:27 +0200 Subject: [PATCH 4/6] board/native: make mount point configurable --- boards/native/board_init.c | 12 ++++++------ boards/native/include/board.h | 7 +++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/boards/native/board_init.c b/boards/native/board_init.c index 085f887f209f..5f04fe72ad27 100644 --- a/boards/native/board_init.c +++ b/boards/native/board_init.c @@ -48,27 +48,27 @@ MTD_XFA_ADD(mtd0_dev.base, 0); /* littlefs support */ #if defined(MODULE_LITTLEFS) -VFS_AUTO_MOUNT(littlefs, VFS_MTD(mtd0_dev), VFS_DEFAULT_NVM(0), 0); +VFS_AUTO_MOUNT(littlefs, VFS_MTD(mtd0_dev), CONFIG_NATIVE_MOUNTPOINT, 0); /* littlefs2 support */ #elif defined(MODULE_LITTLEFS2) -VFS_AUTO_MOUNT(littlefs2, VFS_MTD(mtd0_dev), VFS_DEFAULT_NVM(0), 0); +VFS_AUTO_MOUNT(littlefs2, VFS_MTD(mtd0_dev), CONFIG_NATIVE_MOUNTPOINT, 0); /* spiffs support */ #elif defined(MODULE_SPIFFS) -VFS_AUTO_MOUNT(spiffs, VFS_MTD(mtd0_dev), VFS_DEFAULT_NVM(0), 0); +VFS_AUTO_MOUNT(spiffs, VFS_MTD(mtd0_dev), CONFIG_NATIVE_MOUNTPOINT, 0); /* FAT support */ #elif defined(MODULE_FATFS_VFS) -VFS_AUTO_MOUNT(fatfs, VFS_MTD(mtd0_dev), VFS_DEFAULT_NVM(0), 0); +VFS_AUTO_MOUNT(fatfs, VFS_MTD(mtd0_dev), CONFIG_NATIVE_MOUNTPOINT, 0); /* ext2/3/4 support */ #elif defined(MODULE_LWEXT4) -VFS_AUTO_MOUNT(lwext4, VFS_MTD(mtd0_dev), VFS_DEFAULT_NVM(0), 0); +VFS_AUTO_MOUNT(lwext4, VFS_MTD(mtd0_dev), CONFIG_NATIVE_MOUNTPOINT, 0); /* host fs pass-through */ #elif defined(MODULE_FS_NATIVE) -VFS_AUTO_MOUNT(native, { .hostpath = FS_NATIVE_DIR }, VFS_DEFAULT_NVM(0), 0); +VFS_AUTO_MOUNT(native, { .hostpath = FS_NATIVE_DIR }, CONFIG_NATIVE_MOUNTPOINT, 0); #endif #endif /* MODULE_VFS_DEFAULT */ diff --git a/boards/native/include/board.h b/boards/native/include/board.h index 426d18c9f099..3d51e190edf4 100644 --- a/boards/native/include/board.h +++ b/boards/native/include/board.h @@ -99,6 +99,13 @@ void _native_LED_RED_TOGGLE(void); #endif /** @} */ +/** + * @brief The mountpoint at which the native fs gets mounted + */ +#ifndef CONFIG_NATIVE_MOUNTPOINT +#define CONFIG_NATIVE_MOUNTPOINT VFS_DEFAULT_NVM(0) +#endif + #if defined(MODULE_SPIFFS) || DOXYGEN /** * @name SPIFFS default configuration From 5bc5bfaf5c906bd0022679d793e2f02278bdb982 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Tue, 7 May 2024 18:04:59 +0200 Subject: [PATCH 5/6] sys/shell: make find_handler() public --- sys/include/shell.h | 13 ++++++++++++- sys/shell/shell.c | 12 +++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/sys/include/shell.h b/sys/include/shell.h index d8f3bfc53b8d..ac2cb693af6b 100644 --- a/sys/include/shell.h +++ b/sys/include/shell.h @@ -91,7 +91,7 @@ extern "C" { * passing stdin (`isrpipe_t stdin_isrpipe`) does not support backpressure * and overflows silently. As a consequence, commands through such terminals * appear to be truncated at @ref STDIO_RX_BUFSIZE bytes (defaulting to 64) - * unless the command is sent in parts (on many terminals, by presing Ctrl-D + * unless the command is sent in parts (on many terminals, by pressing Ctrl-D * half way through the command). * * For example, this affects systems with direct USB stdio (@ref @@ -225,6 +225,17 @@ static inline void shell_run(const shell_command_t *commands, shell_run_forever(commands, line_buf, len); } +/** + * @brief Searches for a handler function associated with a command + * + * @param[in] command_list ptr to array of command structs + * @param[in] command the command name to search for + * + * @returns handler function associated with @p command + * NULL if the command could not be found + */ +shell_command_handler_t shell_find_handler(const shell_command_t *command_list, + const char *command); /** * @brief Parse and run a line of text as a shell command with * arguments. diff --git a/sys/shell/shell.c b/sys/shell/shell.c index 90dcaceb4888..7f0759e360df 100644 --- a/sys/shell/shell.c +++ b/sys/shell/shell.c @@ -90,7 +90,7 @@ static enum parse_state escape_toggle(enum parse_state s) } static shell_command_handler_t search_commands(const shell_command_t *entry, - char *command) + const char *command) { for (; entry->name != NULL; entry++) { if (strcmp(entry->name, command) == 0) { @@ -100,7 +100,7 @@ static shell_command_handler_t search_commands(const shell_command_t *entry, return NULL; } -static shell_command_handler_t search_commands_xfa(char *command) +static shell_command_handler_t search_commands_xfa(const char *command) { unsigned n = XFA_LEN(shell_command_t*, shell_commands_xfa); @@ -113,11 +113,13 @@ static shell_command_handler_t search_commands_xfa(char *command) return NULL; } -static shell_command_handler_t find_handler( - const shell_command_t *command_list, char *command) +shell_command_handler_t shell_find_handler(const shell_command_t *command_list, + const char *command) { shell_command_handler_t handler = NULL; + assert(command); + if (command_list != NULL) { handler = search_commands(command_list, command); } @@ -326,7 +328,7 @@ int shell_handle_input_line(const shell_command_t *command_list, char *line) argv[argc] = NULL; /* then we call the appropriate handler */ - shell_command_handler_t handler = find_handler(command_list, argv[0]); + shell_command_handler_t handler = shell_find_handler(command_list, argv[0]); if (handler != NULL) { if (IS_USED(MODULE_SHELL_HOOKS)) { shell_pre_command_hook(argc, argv); From c0fd8edcfa8875a7a8bff58219e68765ce2254c1 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Tue, 7 May 2024 19:37:26 +0200 Subject: [PATCH 6/6] examples/nanocoap_tool: add RIOT as a CLI tool --- examples/riot_as_cli_tool/Makefile | 47 +++++++++++++++++++++++++++++ examples/riot_as_cli_tool/README.md | 24 +++++++++++++++ examples/riot_as_cli_tool/main.c | 45 +++++++++++++++++++++++++++ examples/riot_as_cli_tool/ncget.sh | 3 ++ examples/riot_as_cli_tool/ncput.sh | 3 ++ examples/riot_as_cli_tool/ping.sh | 3 ++ 6 files changed, 125 insertions(+) create mode 100644 examples/riot_as_cli_tool/Makefile create mode 100644 examples/riot_as_cli_tool/README.md create mode 100644 examples/riot_as_cli_tool/main.c create mode 100755 examples/riot_as_cli_tool/ncget.sh create mode 100755 examples/riot_as_cli_tool/ncput.sh create mode 100755 examples/riot_as_cli_tool/ping.sh diff --git a/examples/riot_as_cli_tool/Makefile b/examples/riot_as_cli_tool/Makefile new file mode 100644 index 000000000000..fde0ec166b2e --- /dev/null +++ b/examples/riot_as_cli_tool/Makefile @@ -0,0 +1,47 @@ +# name of your application +APPLICATION = riot_as_cli_tool + +# If no BOARD is found in the environment, use this default: +BOARD ?= native + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# Include packages that pull up and auto-init the link layer. +USEMODULE += netdev_default +USEMODULE += auto_init_gnrc_netif +# Specify the mandatory networking modules for IPv6 +USEMODULE += gnrc_ipv6_default +# Additional networking modules that can be dropped if not needed +USEMODULE += gnrc_icmpv6_echo + +USEMODULE += auto_init_sock_dns # add fall-back DNS server +USEMODULE += sock_dns # include DNS client +USEMODULE += gnrc_ipv6_nib_dns # include RDNSS option handling + +USEMODULE += nanocoap_sock +USEMODULE += nanocoap_vfs + +USEMODULE += vfs_default + +USEMODULE += shell +USEMODULE += shell_cmds_default + +# export the whole fs to RIOT +CFLAGS += -DFS_NATIVE_DIR=\"/\" +# mount it as '/' in RIOT to match the host +CFLAGS += -DCONFIG_NATIVE_MOUNTPOINT=\"/\" +# use the current working directory as download destination +CFLAGS += -DCONFIG_NCGET_DEFAULT_DATA_DIR=\"/proc/self/cwd/\" + +# terminate RIOT with main() +CFLAGS += -DCONFIG_CORE_EXIT_WITH_MAIN=1 +# don't be verbose +CFLAGS += -DCONFIG_SKIP_BOOT_MSG=1 + +RIOT_TERMINAL = native +BOARD_WHITELIST = native native64 + +DEVELHELP ?= 1 + +include $(RIOTBASE)/Makefile.include diff --git a/examples/riot_as_cli_tool/README.md b/examples/riot_as_cli_tool/README.md new file mode 100644 index 000000000000..9f9dcfef3afe --- /dev/null +++ b/examples/riot_as_cli_tool/README.md @@ -0,0 +1,24 @@ +RIOT as a CLI tool +================== + +This example demonstrates running RIOT as a one-shot CLI tool. +This can be used to easiely integrate RIOT into a CI pipeline for integration tests +with software that is supposed to interact with RIOT. + +This example demonstrates running the nanoCoAP CLI commands from the host system. + +For this the whole host file system is exported to RIOT, we also need to create a +virtual network interface by running + + sudo dist/tools/tapsetup/tapsetup -u eth0 + +where `eth0` is the network interface used for the internet uplink. +If no internet connectivity is needed, this can be left out. + +RIOT commands can be invoked e.g. via + + bin/native/nanocoap_tool.elf tap0 ping riot-os.org + +or via the provided wrapper scripts + + ./ping.sh riot-os.org diff --git a/examples/riot_as_cli_tool/main.c b/examples/riot_as_cli_tool/main.c new file mode 100644 index 000000000000..e88039f6b0cf --- /dev/null +++ b/examples/riot_as_cli_tool/main.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 ML!PA Consulting GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief Example application to access RIOT shell commands from Linux + * + * @author Benjamin Valentin + * + * @} + */ + +#include +#include "shell.h" +#include "ztimer.h" + +int main(int argc, char **argv) +{ + if (argc < 1) { + printf("usage: [args]\n"); + return 0; + } + + /* argv[0] will be the first 'user' argument to native */ + shell_command_handler_t handler = shell_find_handler(NULL, argv[0]); + if (handler == NULL) { + return -EINVAL; + } + + /* wait some time for the network to be ready */ + ztimer_sleep(ZTIMER_MSEC, 1000); + + msg_t msg_queue[8]; + msg_init_queue(msg_queue, ARRAY_SIZE(msg_queue)); + + return handler(argc, argv); +} diff --git a/examples/riot_as_cli_tool/ncget.sh b/examples/riot_as_cli_tool/ncget.sh new file mode 100755 index 000000000000..10a09316a7d8 --- /dev/null +++ b/examples/riot_as_cli_tool/ncget.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +bin/native/nanocoap_tool.elf tap0 ncget -- $* diff --git a/examples/riot_as_cli_tool/ncput.sh b/examples/riot_as_cli_tool/ncput.sh new file mode 100755 index 000000000000..4242d87208f6 --- /dev/null +++ b/examples/riot_as_cli_tool/ncput.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +bin/native/nanocoap_tool.elf tap0 ncput -- $* diff --git a/examples/riot_as_cli_tool/ping.sh b/examples/riot_as_cli_tool/ping.sh new file mode 100755 index 000000000000..8fd0dacdd96f --- /dev/null +++ b/examples/riot_as_cli_tool/ping.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +bin/native/nanocoap_tool.elf tap0 ping -- $*