From f0a21d3d48112d58ac655703ffb6529e3c112b7e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 13 Dec 2015 09:55:52 -0600 Subject: [PATCH] NSH: Add module commands: insmod, rmmod, and lsmod --- ChangeLog.txt | 2 + examples/module/module_main.c | 2 +- nshlib/Kconfig | 5 + nshlib/Makefile | 6 ++ nshlib/README.txt | 87 +++++++++++++++-- nshlib/nsh.h | 8 ++ nshlib/nsh_command.c | 22 ++++- nshlib/nsh_modcmds.c | 176 ++++++++++++++++++++++++++++++++++ 8 files changed, 294 insertions(+), 14 deletions(-) create mode 100644 nshlib/nsh_modcmds.c diff --git a/ChangeLog.txt b/ChangeLog.txt index a98e0a872..d74bd2cb3 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1500,4 +1500,6 @@ sockets (2015-12-11). * examples/module: Add a test harness for verifying NuttX kernel modules (2015-12-12). + * apps/nshlib: Add module commands: insmod, rmmod, and lsmod + (2015-12-13). diff --git a/examples/module/module_main.c b/examples/module/module_main.c index f4c36b745..e35db2585 100644 --- a/examples/module/module_main.c +++ b/examples/module/module_main.c @@ -131,7 +131,7 @@ int module_main(int argc, char *argv[]) /* Set the OS symbol table indirectly through the boardctl() */ - symdesc.symtab = exports; + symdesc.symtab = (FAR struct symtab_s *)exports; symdesc.nsymbols = nexports; ret = boardctl(BOARDIOC_OS_SYMTAB, (uintptr_t)&symdesc); if (ret < 0) diff --git a/nshlib/Kconfig b/nshlib/Kconfig index 4f820e502..5ebd30f3c 100644 --- a/nshlib/Kconfig +++ b/nshlib/Kconfig @@ -311,6 +311,11 @@ config NSH_DISABLE_MH bool "Disable mh" default n +config NSH_DISABLE_MODCMDS + bool "Disable modules commands (insmod, rmmod, lsmod)" + default n + depends on MODULE + config NSH_DISABLE_MOUNT bool "Disable mount" default n diff --git a/nshlib/Makefile b/nshlib/Makefile index 2b25750c3..946a1b0ea 100644 --- a/nshlib/Makefile +++ b/nshlib/Makefile @@ -77,6 +77,12 @@ ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y) CSRCS += nsh_mntcmds.c endif +ifeq ($(CONFIG_MODULE),y) +ifneq ($(CONFIG_NSH_DISABLE_MODCMDS),y) +CSRCS += nsh_modcmds.c +endif +endif + ifeq ($(CONFIG_NSH_CONSOLE),y) CSRCS += nsh_consolemain.c endif diff --git a/nshlib/README.txt b/nshlib/README.txt index d5669dae9..046ef91ae 100644 --- a/nshlib/README.txt +++ b/nshlib/README.txt @@ -517,6 +517,38 @@ o ifup ifup eth0 +o insmod + + Install the loadable OS module at as module + + Example: + + nsh> ls -l /mnt/romfs + /mnt/romfs: + dr-xr-xr-x 0 . + -r-xr-xr-x 9153 chardev + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 console + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + crw-rw-rw- 0 ttyS0 + nsh> insmod /mnt/romfs/chardev mydriver + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 chardev + crw-rw-rw- 0 console + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + crw-rw-rw- 0 ttyS0 + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + mydriver 20404659 20404625 0 20404580 552 204047a8 0 + nsh> rmmod mydriver + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + nsh> + o kill - Send the to the task identified by . @@ -574,6 +606,25 @@ o ls [-lRs] -l Show size and mode information along with the filenames in the listing. +o lsmod + + Show information about the currently installed OS modules. This information includes: + + - The module name assigned to the module when it was installed (NAME). + - The address of the module initialization function (INIT). + - The address of the module un-initialization function (UNINIT). + - An argument that will be passed to the module un-initialization function (ARG). + - The start of the .text memory region (TEXT). + - The size of the .text memory region size (SIZE). + - The start of the .bss/.data memory region (DATA). + - The size of the .bss/.data memory region size (SIZE). + + Example: + + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + mydriver 20404659 20404625 0 20404580 552 204047a8 0 + o md5 [-f] o mb [=][ ] @@ -907,6 +958,21 @@ o rmdir drw-rw-rw- 0 TESTDIR/ nsh> +o rmmod + + Remove the loadable OS module with the . NOTE: An OS module + can only be removed if it is not busy. + + Example: + + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + mydriver 20404659 20404625 0 20404580 552 204047a8 0 + nsh> rmmod mydriver + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + nsh> + o set Set the environment variable to the sting . @@ -1041,9 +1107,11 @@ Command Dependencies on Configuration Settings ifconfig CONFIG_NET && CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_NET ifdown CONFIG_NET && CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_NET ifup CONFIG_NET && CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_NET + insmod CONFIG_MODULE kill !CONFIG_DISABLE_SIGNALS losetup !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_DEV_LOOP ls CONFIG_NFILE_DESCRIPTORS > 0 + lsmod CONFIG_MODULE && CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_MODULE md5 CONFIG_NETUTILS_CODECS && CONFIG_CODECS_HASH_MD5 mb,mh,mw --- mkdir (((!CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_WRITABLE) || !CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_DESCRIPTORS > 0) @@ -1063,6 +1131,7 @@ Command Dependencies on Configuration Settings reboot CONFIG_BOARDCTL_RESET rm (((!CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_WRITABLE) || !CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_DESCRIPTORS > 0) rmdir (((!CONFIG_DISABLE_MOUNTPOINT && CONFIG_FS_WRITABLE) || !CONFIG_DISABLE_PSEUDOFS_OPERATIONS) && CONFIG_NFILE_DESCRIPTORS > 0) + rmmod CONFIG_MODULE set !CONFIG_DISABLE_ENVIRON sh CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !CONFIG_NSH_DISABLESCRIPT shutdown CONFIG_BOARDCTL_POWEROFF || CONFIG_BOARDCTL_RESET @@ -1102,15 +1171,15 @@ also allow it to squeeze into very small memory footprints. CONFIG_NSH_DISABLE_LOSETUP, CONFIG_NSH_DISABLE_LS, CONFIG_NSH_DISABLE_MD5, CONFIG_NSH_DISABLE_MB, CONFIG_NSH_DISABLE_MKDIR, CONFIG_NSH_DISABLE_MKFATFS, CONFIG_NSH_DISABLE_MKFIFO, CONFIG_NSH_DISABLE_MKRD, CONFIG_NSH_DISABLE_MH, - CONFIG_NSH_DISABLE_MOUNT, CONFIG_NSH_DISABLE_MW, CONFIG_NSH_DISABLE_MV, - CONFIG_NSH_DISABLE_NFSMOUNT, CONFIG_NSH_DISABLE_NSLOOKUP, CONFIG_NSH_DISABLE_POWEROFF, - CONFIG_NSH_DISABLE_PS, CONFIG_NSH_DISABLE_PING, CONFIG_NSH_DISABLE_PING6, - CONFIG_NSH_DISABLE_PUT, CONFIG_NSH_DISABLE_PWD, CONFIG_NSH_DISABLE_REBOOT, - CONFIG_NSH_DISABLE_RM, CONFIG_NSH_DISABLE_RMDIR, CONFIG_NSH_DISABLE_SET, - CONFIG_NSH_DISABLE_SH, CONFIG_NSH_DISABLE_SHUTDOWN, CONFIG_NSH_DISABLE_SLEEP, - CONFIG_NSH_DISABLE_TEST, CONFIG_NSH_DISABLE_UMOUNT, CONFIG_NSH_DISABLE_UNSET, - CONFIG_NSH_DISABLE_URLDECODE, CONFIG_NSH_DISABLE_URLENCODE, CONFIG_NSH_DISABLE_USLEEP, - CONFIG_NSH_DISABLE_WGET, CONFIG_NSH_DISABLE_XD + CONFIG_NSH_DISABLE_MODCMDS, CONFIG_NSH_DISABLE_MOUNT, CONFIG_NSH_DISABLE_MW, + CONFIG_NSH_DISABLE_MV, CONFIG_NSH_DISABLE_NFSMOUNT, CONFIG_NSH_DISABLE_NSLOOKUP, + CONFIG_NSH_DISABLE_POWEROFF, CONFIG_NSH_DISABLE_PS, CONFIG_NSH_DISABLE_PING, + CONFIG_NSH_DISABLE_PING6, CONFIG_NSH_DISABLE_PUT, CONFIG_NSH_DISABLE_PWD, + CONFIG_NSH_DISABLE_REBOOT, CONFIG_NSH_DISABLE_RM, CONFIG_NSH_DISABLE_RMDIR, + CONFIG_NSH_DISABLE_SET, CONFIG_NSH_DISABLE_SH, CONFIG_NSH_DISABLE_SHUTDOWN, + CONFIG_NSH_DISABLE_SLEEP, CONFIG_NSH_DISABLE_TEST, CONFIG_NSH_DISABLE_UMOUNT, + CONFIG_NSH_DISABLE_UNSET, CONFIG_NSH_DISABLE_URLDECODE, CONFIG_NSH_DISABLE_URLENCODE, + CONFIG_NSH_DISABLE_USLEEP, CONFIG_NSH_DISABLE_WGET, CONFIG_NSH_DISABLE_XD Verbose help output can be suppressed by defining CONFIG_NSH_HELP_TERSE. In that case, the help command is still available but will be slightly smaller. diff --git a/nshlib/nsh.h b/nshlib/nsh.h index ba246a5e1..0ebd5f9ff 100644 --- a/nshlib/nsh.h +++ b/nshlib/nsh.h @@ -941,6 +941,14 @@ void nsh_usbtrace(void); int cmd_xd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); #endif +#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS) +int cmd_insmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +int cmd_rmmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) +int cmd_lsmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif +#endif + #if !defined(CONFIG_NSH_DISABLESCRIPT) && !defined(CONFIG_NSH_DISABLE_TEST) int cmd_test(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); int cmd_lbracket(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c index b1077b70e..025edb382 100644 --- a/nshlib/nsh_command.c +++ b/nshlib/nsh_command.c @@ -195,7 +195,7 @@ static const struct cmdmap_s g_cmdmap[] = #endif #ifndef CONFIG_NSH_DISABLESCRIPT - { "false", cmd_false, 1, 1, NULL }, + { "false", cmd_false, 1, 1, NULL }, #endif #ifndef CONFIG_NSH_DISABLE_FREE @@ -228,14 +228,18 @@ static const struct cmdmap_s g_cmdmap[] = #ifdef CONFIG_NET # ifndef CONFIG_NSH_DISABLE_IFCONFIG - { "ifconfig", cmd_ifconfig, 1, 11, "[nic_name [|dhcp]] [dr|gw|gateway ] [netmask ] [dns ] [hw ]" }, + { "ifconfig", cmd_ifconfig, 1, 11, "[nic-name [|dhcp]] [dr|gw|gateway ] [netmask ] [dns ] [hw ]" }, # endif # ifndef CONFIG_NSH_DISABLE_IFUPDOWN - { "ifdown", cmd_ifdown, 2, 2, "" }, - { "ifup", cmd_ifup, 2, 2, "" }, + { "ifdown", cmd_ifdown, 2, 2, "" }, + { "ifup", cmd_ifup, 2, 2, "" }, # endif #endif +#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS) + { "insmod", cmd_insmod, 3, 3, " " }, +#endif + #ifndef CONFIG_DISABLE_SIGNALS # ifndef CONFIG_NSH_DISABLE_KILL { "kill", cmd_kill, 3, 3, "- " }, @@ -260,6 +264,12 @@ static const struct cmdmap_s g_cmdmap[] = # endif #endif +#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS) +#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) + { "lsmod", cmd_lsmod, 1, 1, NULL }, +#endif +#endif + #ifndef CONFIG_NSH_DISABLE_MB { "mb", cmd_mb, 2, 3, "[=][ ]" }, #endif @@ -389,6 +399,10 @@ static const struct cmdmap_s g_cmdmap[] = # endif #endif +#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS) + { "rmmod", cmd_rmmod, 2, 2, "" }, +#endif + #ifndef CONFIG_DISABLE_ENVIRON # ifndef CONFIG_NSH_DISABLE_SET { "set", cmd_set, 3, 3, " " }, diff --git a/nshlib/nsh_modcmds.c b/nshlib/nsh_modcmds.c new file mode 100644 index 000000000..4fbfdfe71 --- /dev/null +++ b/nshlib/nsh_modcmds.c @@ -0,0 +1,176 @@ +/**************************************************************************** + * apps/nshlib/nsh_modcmds.c + * + * Copyright (C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "nsh.h" +#include "nsh_console.h" + +#if defined(CONFIG_MODULE) && !defined(CONFIG_NSH_DISABLE_MODCMDS) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cmd_insmod + ****************************************************************************/ + +int cmd_insmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + int ret; + + /* Usage: insmod */ + /* Install the module */ + + ret = insmod(argv[1], argv[2]); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "insmod", NSH_ERRNO); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: cmd_rmmod + ****************************************************************************/ + +int cmd_rmmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + int ret; + + /* Usage: rmmod */ + /* Remove the module */ + + ret = rmmod(argv[1]); + if (ret < 0) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "rmmod", NSH_ERRNO); + return ERROR; + } + + return OK; +} + +/**************************************************************************** + * Name: cmd_lsmod + ****************************************************************************/ + +#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE) +int cmd_lsmod(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + FILE *stream; + + /* Usage: lsmod */ + /* Open /proc/modules */ + + stream = fopen("/proc/modules", "r"); + if (stream == NULL) + { + nsh_output(vtbl, g_fmtcmdfailed, argv[0], "fopen", NSH_ERRNO); + return ERROR; + } + + /* Output a Header */ + + nsh_output(vtbl, "%-16s %9s %9s %9s %9s %8s %9s %8s\n", + "NAME", "INIT", "UNINIT", "ARG", "TEXT", "SIZE", + "DATA", "SIZE"); + + /* Read each line from the procfs "file" */ + + while (fgets(vtbl->iobuffer, IOBUFFERSIZE, stream) != NULL) + { + FAR char *modulename; + FAR char *initializer; + FAR char *uninitializer; + FAR char *arg; + FAR char *text; + FAR char *textsize; + FAR char *data; + FAR char *datasize; + FAR char *lasts; + + /* Form of returned data is: + * + * "%s,%p,%p,%p,%p,%lu,%p,%lu\n" + * + * 1) Module name string + * 2) Initializer address + * 3) Uninitializer address + * 4) Uninitializer argument + * 5) .text address + * 6) Size of .text + * 7) .bss/.data address + * 8) Size of .bss/.data + */ + + modulename = strtok_r(vtbl->iobuffer, ",\n", &lasts); + initializer = strtok_r(NULL, ",\n", &lasts); + uninitializer = strtok_r(NULL, ",\n", &lasts); + arg = strtok_r(NULL, ",\n", &lasts); + text = strtok_r(NULL, ",\n", &lasts); + textsize = strtok_r(NULL, ",\n", &lasts); + data = strtok_r(NULL, ",\n", &lasts); + datasize = strtok_r(NULL, ",\n", &lasts); + + nsh_output(vtbl, "%-16s %9s %9s %9s %9s %8s %9s %8s\n", + modulename, + initializer ? initializer : "", + uninitializer ? uninitializer : "", + arg ? arg : "", + text ? text : "", + textsize ? textsize : "", + data ? data : "", + datasize ? datasize : ""); + } + + (void)fclose(stream); + return OK; +} +#endif /* CONFIG_FS_PROCFS && !CONFIG_FS_PROCFS_EXCLUDE_MODULE */ + +#endif /* CONFIG_MODULE && !CONFIG_NSH_DISABLE_MODCMDS */