summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/ChangeLog.txt3
-rw-r--r--apps/builtin/builtin_list.c79
-rw-r--r--apps/examples/nsh/nsh_main.c38
-rw-r--r--apps/nshlib/Kconfig11
-rw-r--r--apps/nshlib/Makefile4
-rw-r--r--apps/nshlib/nsh.h5
-rw-r--r--apps/nshlib/nsh_builtin.c27
-rw-r--r--apps/nshlib/nsh_fileapps.c298
-rw-r--r--apps/nshlib/nsh_parse.c37
-rw-r--r--nuttx/ChangeLog4
-rw-r--r--nuttx/arch/arm/include/stm32/chip.h38
-rw-r--r--nuttx/binfmt/binfmt_exec.c10
-rw-r--r--nuttx/binfmt/binfmt_loadmodule.c4
-rw-r--r--nuttx/binfmt/binfmt_schedunload.c333
-rw-r--r--nuttx/binfmt/builtin.c4
-rw-r--r--nuttx/binfmt/libbuiltin/libbuiltin_getname.c8
-rw-r--r--nuttx/binfmt/libbuiltin/libbuiltin_isavail.c6
-rw-r--r--nuttx/configs/sim/nsh/defconfig12
-rw-r--r--nuttx/include/nuttx/binfmt/binfmt.h2
-rw-r--r--nuttx/include/nuttx/binfmt/builtin.h30
-rw-r--r--nuttx/libc/spawn/lib_ps.c2
-rw-r--r--nuttx/tools/mkconfig.c2
22 files changed, 927 insertions, 30 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index 14eb78950..ba8dec613 100644
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -485,3 +485,6 @@
argument is now optional. Many files systems do not need
a source and it is really stupid to have to enter a bogus
source parameter.
+ * apps/nshlib/nsh_fileapp.c: Add the ability to execute a file
+ from a file system using posix_spawn().
+ * apps/builtin/: Extensions from Mike Smith.
diff --git a/apps/builtin/builtin_list.c b/apps/builtin/builtin_list.c
new file mode 100644
index 000000000..a5556bf54
--- /dev/null
+++ b/apps/builtin/builtin_list.c
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * apps/builtin/builtin_list.c
+ *
+ * Copyright (C) 2011 Uros Platise. All rights reserved.
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Authors: Uros Platise <uros.platise@isotel.eu>
+ * Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <nuttx/config.h>
+
+#include <nuttx/binfmt/builtin.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#include "builtin_proto.h"
+
+const struct builtin_s g_builtins[] =
+{
+# include "builtin_list.h"
+ { NULL, 0, 0, 0 }
+};
+
+const int g_builtin_count = sizeof(g_builtins) / sizeof(g_builtins[0]);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
diff --git a/apps/examples/nsh/nsh_main.c b/apps/examples/nsh/nsh_main.c
index 97792cb2a..d9bfc2018 100644
--- a/apps/examples/nsh/nsh_main.c
+++ b/apps/examples/nsh/nsh_main.c
@@ -46,6 +46,12 @@
#include <errno.h>
#include <nuttx/arch.h>
+#if defined(CONFIG_FS_BINFS) && (CONFIG_BUILTIN)
+#include <nuttx/binfmt/builtin.h>
+#endif
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+#include <nuttx/binfmt/symtab.h>
+#endif
#include <apps/nsh.h>
@@ -75,6 +81,21 @@
* Public Data
****************************************************************************/
+/* If posix_spawn() is enabled as required for CONFIG_NSH_FILE_APPS, then
+ * a symbol table is needed by the internals of posix_spawn(). The symbol
+ * table is needed to support ELF and NXFLAT binaries to dynamically link to
+ * the base code. However, if only the BINFS file system is supported, then
+ * no Makefile is needed.
+ *
+ * This is a kludge to plug the missing file system in the case where BINFS
+ * is used. REVISIT: This will, of course, be in the way if you want to
+ * support ELF or NXFLAT binaries!
+ */
+
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+const struct symtab_s CONFIG_EXECFUNCS_SYMTAB[1];
+#endif
+
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -98,6 +119,23 @@ int nsh_main(int argc, char *argv[])
up_cxxinitialize();
#endif
+ /* Make sure that we are using our symbol take */
+
+#if defined(CONFIG_LIBC_EXECFUNCS) && defined(CONFIG_EXECFUNCS_SYMTAB)
+ exec_setsymtab(CONFIG_EXECFUNCS_SYMTAB, 0);
+#endif
+
+ /* Register the BINFS file system */
+
+#if defined(CONFIG_FS_BINFS) && (CONFIG_BUILTIN)
+ ret = builtin_initialize();
+ if (ret < 0)
+ {
+ fprintf(stderr, "ERROR: builtin_initialize failed: %d\n", ret);
+ exitval = 1;
+ }
+#endif
+
/* Initialize the NSH library */
nsh_initialize();
diff --git a/apps/nshlib/Kconfig b/apps/nshlib/Kconfig
index e60e9c480..f6a5aa045 100644
--- a/apps/nshlib/Kconfig
+++ b/apps/nshlib/Kconfig
@@ -14,7 +14,7 @@ config NSH_LIBRARY
if NSH_LIBRARY
config NSH_BUILTIN_APPS
bool "Enable built-in applications"
- default y
+ default n
depends on BUILTIN
---help---
Support external registered, "built-in" applications that can be
@@ -22,6 +22,15 @@ config NSH_BUILTIN_APPS
more information). This options requires support for builtin
applications (BUILTIN).
+config NSH_FILE_APPS
+ bool "Enable execution of program files"
+ default n
+ depends on LIBC_EXECFUNCS
+ ---help---
+ Support execution of program files residing within a file
+ system. This options requires support for the posix_spawn()
+ interface (LIBC_EXECFUNCS).
+
menu "Disable Individual commands"
config NSH_DISABLE_BASE64DEC
diff --git a/apps/nshlib/Makefile b/apps/nshlib/Makefile
index 5c5269685..948f43d52 100644
--- a/apps/nshlib/Makefile
+++ b/apps/nshlib/Makefile
@@ -47,6 +47,10 @@ ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
CSRCS += nsh_builtin.c
endif
+ifeq ($(CONFIG_NSH_FILE_APPS),y)
+CSRCS += nsh_fileapps.c
+endif
+
ifeq ($(CONFIG_NSH_ROMFSETC),y)
CSRCS += nsh_romfsetc.c
endif
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
index 253a803f8..64099a8df 100644
--- a/apps/nshlib/nsh.h
+++ b/apps/nshlib/nsh.h
@@ -495,6 +495,11 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
FAR char **argv, FAR const char *redirfile, int oflags);
#endif
+#ifdef CONFIG_NSH_FILE_APPS
+int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags);
+#endif
+
/* Working directory support */
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
diff --git a/apps/nshlib/nsh_builtin.c b/apps/nshlib/nsh_builtin.c
index ba39e8dfe..2d23ca8d8 100644
--- a/apps/nshlib/nsh_builtin.c
+++ b/apps/nshlib/nsh_builtin.c
@@ -51,6 +51,7 @@
#endif
#include <stdbool.h>
+#include <signal.h>
#include <errno.h>
#include <string.h>
@@ -129,20 +130,34 @@ int nsh_builtin(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
ret = exec_builtin(cmd, (FAR const char **)argv, redirfile, oflags);
if (ret >= 0)
{
- /* The application was successfully started (but still blocked because
- * the scheduler is locked). If the application was not backgrounded,
- * then we need to wait here for the application to exit. These really
- * only works works with the following options:
+ /* The application was successfully started with pre-emption disabled.
+ * In the simplest cases, the application will not have run because the
+ * the scheduler is locked. but in the case were I/O redirected, a
+ * proxy task ran and, as result, so may have the application.
+ *
+ * If the application did not run and if the application was not
+ * backgrounded, then we need to wait here for the application to
+ * exit. This only works works with the following options:
*
* - CONFIG_NSH_DISABLEBG - Do not run commands in background
* - CONFIG_SCHED_WAITPID - Required to run external commands in
* foreground
- *
- * These concepts do not apply cleanly to the external applications.
*/
#ifdef CONFIG_SCHED_WAITPID
+ /* Check if the application is still running */
+
+ if (kill(ret, 0) < 0)
+ {
+ /* It is not running. In this case, we have no idea if the
+ * application ran successfully or not. Let's assume that is
+ * did.
+ */
+
+ return 0;
+ }
+
/* CONFIG_SCHED_WAITPID is selected, so we may run the command in
* foreground unless we were specifically requested to run the command
* in background (and running commands in background is enabled).
diff --git a/apps/nshlib/nsh_fileapps.c b/apps/nshlib/nsh_fileapps.c
new file mode 100644
index 000000000..7f9f58e53
--- /dev/null
+++ b/apps/nshlib/nsh_fileapps.c
@@ -0,0 +1,298 @@
+/****************************************************************************
+ * apps/nshlib/nsh_fileapps.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <nuttx/config.h>
+
+#ifdef CONFIG_SCHED_WAITPID
+# include <sys/wait.h>
+#endif
+
+#include <stdbool.h>
+#include <signal.h>
+#include <spawn.h>
+#include <errno.h>
+#include <string.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+#ifdef CONFIG_NSH_FILE_APPS
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nsh_fileapp
+ *
+ * Description:
+ * Attempt to execute the application task whose name is 'cmd'
+ *
+ * Returned Value:
+ * <0 If exec_builtin() fails, then the negated errno value
+ * is returned.
+ * -1 (ERROR) if the application task corresponding to 'cmd' could not
+ * be started (possibly because it doesn not exist).
+ * 0 (OK) if the application task corresponding to 'cmd' was
+ * and successfully started. If CONFIG_SCHED_WAITPID is
+ * defined, this return value also indicates that the
+ * application returned successful status (EXIT_SUCCESS)
+ * 1 If CONFIG_SCHED_WAITPID is defined, then this return value
+ * indicates that the application task was spawned successfully
+ * but returned failure exit status.
+ *
+ ****************************************************************************/
+
+int nsh_fileapp(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
+ FAR char **argv, FAR const char *redirfile, int oflags)
+{
+ posix_spawn_file_actions_t file_actions;
+ posix_spawnattr_t attr;
+ pid_t pid;
+ int ret;
+
+ /* Initialize the attributes file actions structure */
+
+ ret = posix_spawn_file_actions_init(&file_actions);
+ if (ret != 0)
+ {
+ /* posix_spawn_file_actions_init returns a positive errno value on
+ * failure.
+ */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "posix_spawn_file_actions_init",
+ NSH_ERRNO_OF(ret));
+ goto errout;
+ }
+
+ ret = posix_spawnattr_init(&attr);
+ if (ret != 0)
+ {
+ /* posix_spawnattr_init returns a positive errno value on failure. */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "posix_spawnattr_init",
+ NSH_ERRNO);
+ goto errout_with_actions;
+ }
+
+ /* Handle re-direction of output */
+
+ if (redirfile)
+ {
+ ret = posix_spawn_file_actions_addopen(&file_actions, 1, redirfile,
+ oflags, 0644);
+ if (ret != 0)
+ {
+ /* posix_spawn_file_actions_addopen returns a positive errno
+ * value on failure.
+ */
+
+ nsh_output(vtbl, g_fmtcmdfailed, cmd,
+ "posix_spawn_file_actions_addopen",
+ NSH_ERRNO);
+ goto errout_with_attrs;
+ }
+ }
+
+ /* Lock the scheduler to prevent the application from running until the
+ * waitpid() has been called.
+ */
+
+ sched_lock();
+
+ /* Execute the program. posix_spawnp returns a positive errno value on
+ * failure.
+ */
+
+ ret = posix_spawnp(&pid, cmd, &file_actions, &attr, &argv[1], NULL);
+ if (ret == OK)
+ {
+ /* The application was successfully started with pre-emption disabled.
+ * In the simplest cases, the application will not have run because the
+ * the scheduler is locked. but in the case were I/O redirected, a
+ * proxy task ran and, as result, so may have the application.
+ *
+ * If the application did not run and if the application was not
+ * backgrounded, then we need to wait here for the application to
+ * exit. This only works works with the following options:
+ *
+ * - CONFIG_NSH_DISABLEBG - Do not run commands in background
+ * - CONFIG_SCHED_WAITPID - Required to run external commands in
+ * foreground
+ */
+
+#ifdef CONFIG_SCHED_WAITPID
+ /* Check if the application is still running */
+
+ if (kill(ret, 0) < 0)
+ {
+ /* It is not running. In this case, we have no idea if the
+ * application ran successfully or not. Let's assume that is
+ * did.
+ */
+
+ return 0;
+ }
+
+ /* CONFIG_SCHED_WAITPID is selected, so we may run the command in
+ * foreground unless we were specifically requested to run the command
+ * in background (and running commands in background is enabled).
+ */
+
+# ifndef CONFIG_NSH_DISABLEBG
+ if (vtbl->np.np_bg == false)
+# endif /* CONFIG_NSH_DISABLEBG */
+ {
+ int rc = 0;
+
+ /* Wait for the application to exit. Since we have locked the
+ * scheduler above, we know that the application has not yet
+ * started and there is no possibility that it has already exited.
+ * The scheduler will be unlocked while waitpid is waiting and the
+ * application will be able to run.
+ */
+
+ ret = waitpid(pid, &rc, 0);
+ if (ret >= 0)
+ {
+ /* We can't return the exact status (nsh has nowhere to put it)
+ * so just pass back zero/nonzero in a fashion that doesn't look
+ * like an error.
+ */
+
+ ret = (rc == 0) ? OK : 1;
+
+ /* TODO: Set the environment variable '?' to a string corresponding
+ * to WEXITSTATUS(rc) so that $? will expand to the exit status of
+ * the most recently executed task.
+ */
+ }
+ }
+# ifndef CONFIG_NSH_DISABLEBG
+ else
+# endif /* CONFIG_NSH_DISABLEBG */
+#endif /* CONFIG_SCHED_WAITPID */
+
+ /* We get here if either:
+ *
+ * - CONFIG_SCHED_WAITPID is not selected meaning that all commands
+ * have to be run in background, or
+ * - CONFIG_SCHED_WAITPID and CONFIG_NSH_DISABLEBG are both selected, but the
+ * user requested to run the command in background.
+ *
+ * NOTE that the case of a) CONFIG_SCHED_WAITPID is not selected and
+ * b) CONFIG_NSH_DISABLEBG selected cannot be supported. In that event, all
+ * commands will have to run in background. The waitpid() API must be
+ * available to support running the command in foreground.
+ */
+
+#if !defined(CONFIG_SCHED_WAITPID) || !defined(CONFIG_NSH_DISABLEBG)
+ {
+ struct sched_param param;
+ sched_getparam(ret, &param);
+ nsh_output(vtbl, "%s [%d:%d]\n", cmd, ret, param.sched_priority);
+
+ /* Backgrounded commands always 'succeed' as long as we can start
+ * them.
+ */
+
+ ret = OK;
+ }
+#endif /* !CONFIG_SCHED_WAITPID || !CONFIG_NSH_DISABLEBG */
+ }
+
+ sched_unlock();
+
+ /* Free attibutes and file actions. Ignoring return values in the case
+ * of an error.
+ */
+
+errout_with_actions:
+ (void)posix_spawn_file_actions_destroy(&file_actions);
+
+errout_with_attrs:
+ (void)posix_spawnattr_destroy(&attr);
+
+errout:
+ /* Most posix_spawn interfaces return a positive errno value on failure
+ * and do not set the errno variable.
+ */
+
+ if (ret > 0)
+ {
+ /* Set the errno value and return -1 */
+
+ set_errno(ret);
+ ret = ERROR;
+ }
+ else if (ret < 0)
+ {
+ /* Return -1 on failure. errno should have been set. */
+
+ ret = ERROR;
+ }
+
+ return ret;
+}
+
+#endif /* CONFIG_NSH_FILE_APPS */
diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c
index ef4125a63..f679d9b32 100644
--- a/apps/nshlib/nsh_parse.c
+++ b/apps/nshlib/nsh_parse.c
@@ -61,6 +61,7 @@
#ifdef CONFIG_NSH_BUILTIN_APPS
# include <nuttx/binfmt/builtin.h>
#endif
+
#include <apps/nsh.h>
#include "nsh.h"
@@ -1398,6 +1399,40 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
nsh_output(vtbl, g_fmttoomanyargs, cmd);
}
+ /* Does this command correspond to an application filename?
+ * nsh_fileapp() returns:
+ *
+ * -1 (ERROR) if the application task corresponding to 'argv[0]' could not
+ * be started (possibly because it doesn not exist).
+ * 0 (OK) if the application task corresponding to 'argv[0]' was
+ * and successfully started. If CONFIG_SCHED_WAITPID is
+ * defined, this return value also indicates that the
+ * application returned successful status (EXIT_SUCCESS)
+ * 1 If CONFIG_SCHED_WAITPID is defined, then this return value
+ * indicates that the application task was spawned successfully
+ * but returned failure exit status.
+ *
+ * Note the priority if not effected by nice-ness.
+ */
+
+#ifdef CONFIG_NSH_FILE_APPS
+ ret = nsh_fileapp(vtbl, argv[0], argv, redirfile, oflags);
+ if (ret >= 0)
+ {
+ /* nsh_fileapp() returned 0 or 1. This means that the builtin
+ * command was successfully started (although it may not have ran
+ * successfully). So certainly it is not an NSH command.
+ */
+
+ return nsh_saveresult(vtbl, ret != OK);
+ }
+
+ /* No, not a built in command (or, at least, we were unable to start a
+ * builtin command of that name). Treat it like an NSH command.
+ */
+
+#endif
+
/* Does this command correspond to a builtin command?
* nsh_builtin() returns:
*
@@ -1414,7 +1449,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
* Note the priority if not effected by nice-ness.
*/
-#ifdef CONFIG_NSH_BUILTIN_APPS
+#if defined(CONFIG_NSH_BUILTIN_APPS) && (!defined(CONFIG_NSH_FILE_APPS) || !defined(CONFIG_FS_BINFS))
ret = nsh_builtin(vtbl, argv[0], argv, redirfile, oflags);
if (ret >= 0)
{
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 6bc66ec9d..1b0c5338b 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -3967,4 +3967,8 @@
file system.
* configs/sim/nsh: Convert to use kconfig-frontends configuration
tool.
+ * binfmt/binfmt_schedunload.c: Add logic based on SIGCHLD to
+ automatically unload and clean-up after running a task that
+ was loaded into memory.
+ * binfmt/libbuiltin: Extensions from Mike Smith
diff --git a/nuttx/arch/arm/include/stm32/chip.h b/nuttx/arch/arm/include/stm32/chip.h
index d34c2eb4f..b7ec7dbba 100644
--- a/nuttx/arch/arm/include/stm32/chip.h
+++ b/nuttx/arch/arm/include/stm32/chip.h
@@ -183,9 +183,43 @@
# define STM32_NRNG 0 /* No random number generator (RNG) */
# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+/* STM32 F103 Medium Density Family *************************************************/
+/* STM32F103RB is in the Medium-density performance line and is provided in 64 pin
+ * packages with 128K Flash, USB, CAN, 7 timers, 2 ADCs, 9 com. interfaces
+ */
+
+#elif defined(CONFIG_ARCH_CHIP_STM32F103RBT6)
+# define CONFIG_STM32_STM32F10XX 1 /* STM32F10xxx family */
+# undef CONFIG_STM32_LOWDENSITY /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 16/32 Kbytes */
+# define CONFIG_STM32_MEDIUMDENSITY 1 /* STM32F100x, STM32F101x, STM32F102x and STM32F103x w/ 64/128 Kbytes */
+# undef CONFIG_STM32_HIGHDENSITY /* STM32F100x, STM32F101x, and STM32F103x w/ 256/512 Kbytes */
+# undef CONFIG_STM32_VALUELINE /* STM32F100x */
+# undef CONFIG_STM32_CONNECTIVITYLINE /* STM32F105x and STM32F107x */
+# undef CONFIG_STM32_STM32F20XX /* STM32F205x and STM32F207x */
+# undef CONFIG_STM32_STM32F40XX /* STM32F405xx and STM32407xx families */
+# define STM32_NFSMC 0 /* FSMC */
+# define STM32_NATIM 1 /* One advanced timer TIM1 */
+# define STM32_NGTIM 3 /* General timers TIM2,3,4 */
+# define STM32_NBTIM 0 /* Two basic timers TIM6 and TIM7 */
+# define STM32_NDMA 1 /* DMA1 */
+# define STM32_NSPI 2 /* SPI1-2 */
+# define STM32_NI2S 0 /* No I2S (?) */
+# define STM32_NUSART 3 /* USART1-3 */
+# define STM32_NI2C 2 /* I2C1-2 */
+# define STM32_NCAN 1 /* bxCAN1 */
+# define STM32_NSDIO 0 /* No SDIO */
+# define STM32_NUSBOTG 0 /* No USB OTG FS/HS */
+# define STM32_NGPIO 51 /* GPIOA-E */
+# define STM32_NADC 2 /* ADC1-2 */
+# define STM32_NDAC 0 /* No DAC */
+# define STM32_NCRC 1 /* CRC */
+# define STM32_NTHERNET 0 /* No ethernet */
+# define STM32_NRNG 0 /* No random number generator (RNG) */
+# define STM32_NDCMI 0 /* No digital camera interface (DCMI) */
+
/* STM32 F103 High Density Family ***************************************************/
-/* STM32F103RC, STM32F103RD, and STM32F103RE are all provided in 64 pin packages and differ
- * only in the available FLASH and SRAM.
+/* STM32F103RC, STM32F103RD, and STM32F103RE are all provided in 64 pin packages and
+ * differ only in the available FLASH and SRAM.
*/
#elif defined(CONFIG_ARCH_CHIP_STM32F103RET6)
diff --git a/nuttx/binfmt/binfmt_exec.c b/nuttx/binfmt/binfmt_exec.c
index 1cead4384..7f45fb841 100644
--- a/nuttx/binfmt/binfmt_exec.c
+++ b/nuttx/binfmt/binfmt_exec.c
@@ -43,6 +43,7 @@
#include <debug.h>
#include <errno.h>
+#include <nuttx/kmalloc.h>
#include <nuttx/binfmt/binfmt.h>
#include "binfmt_internal.h"
@@ -97,6 +98,7 @@ int exec(FAR const char *filename, FAR const char **argv,
#ifdef CONFIG_SCHED_ONEXIT
FAR struct binary_s *bin;
int errorcode;
+ int pid;
int ret;
/* Allocate the load information */
@@ -131,8 +133,8 @@ int exec(FAR const char *filename, FAR const char **argv,
/* Then start the module */
- ret = exec_module(bin);
- if (ret < 0)
+ pid = exec_module(bin);
+ if (pid < 0)
{
bdbg("ERROR: Failed to execute program '%s'\n", filename);
sched_unlock();
@@ -145,14 +147,14 @@ int exec(FAR const char *filename, FAR const char **argv,
* when the task exists.
*/
- ret = schedul_unload(ret, bin);
+ ret = schedule_unload(pid, bin);
if (ret < 0)
{
bdbg("ERROR: Failed to schedul unload '%s'\n", filename);
}
sched_unlock();
- return ret;
+ return pid;
#else
struct binary_s bin;
int ret;
diff --git a/nuttx/binfmt/binfmt_loadmodule.c b/nuttx/binfmt/binfmt_loadmodule.c
index 4f3dc6952..322ed2c48 100644
--- a/nuttx/binfmt/binfmt_loadmodule.c
+++ b/nuttx/binfmt/binfmt_loadmodule.c
@@ -84,6 +84,7 @@
static int load_default_priority(FAR struct binary_s *bin)
{
struct sched_param param;
+ int ret;
/* Get the priority of this thread */
@@ -97,6 +98,7 @@ static int load_default_priority(FAR struct binary_s *bin)
/* Save that as the priority of child thread */
bin->priority = param.sched_priority;
+ return ret;
}
/****************************************************************************
@@ -180,7 +182,7 @@ int load_module(FAR struct binary_s *bin)
{
/* Set the default priority of the new program. */
- ret = load_default_priority(bin)
+ ret = load_default_priority(bin);
if (ret < 0)
{
/* The errno is already set in this case */
diff --git a/nuttx/binfmt/binfmt_schedunload.c b/nuttx/binfmt/binfmt_schedunload.c
new file mode 100644
index 000000000..972d17963
--- /dev/null
+++ b/nuttx/binfmt/binfmt_schedunload.c
@@ -0,0 +1,333 @@
+/****************************************************************************
+ * binfmt/binfmt_schedunload.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <nuttx/config.h>
+
+#include <sched.h>
+#include <debug.h>
+#include <errno.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/binfmt/binfmt.h>
+
+#include "binfmt_internal.h"
+
+#if !defined(CONFIG_BINFMT_DISABLE) && defined(CONFIG_SCHED_HAVE_PARENT)
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+FAR struct binary_s *g_unloadhead;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: unload_list_add
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined then schedul_unload() will
+ * manage instances of struct binary_s allocated with kmalloc. It
+ * will keep the binary data in a link list and when SIGCHLD is received
+ * (meaning that the task has exit'ed, schedul_unload() will find the
+ * data, unload the module, and free the structure.
+ *
+ * This function will add one structure to the linked list
+ *
+ * Input Parameter:
+ * pid - The task ID of the child task
+ * bin - This structure must have been allocated with kmalloc() and must
+ * persist until the task unloads
+
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void unload_list_add(pid_t pid, FAR struct binary_s *bin)
+{
+ irqstate_t flags;
+
+ /* Save the PID in the structure so that we recover it later */
+
+ bin->pid = pid;
+
+ /* Disable deliver of any signals while we muck with the list. The graceful
+ * way to do this would be block delivery of SIGCHLD would be with
+ * sigprocmask. Here we do it the quick'n'dirty way by just disabling
+ * interrupts.
+ */
+
+ flags = irqsave();
+ bin->flink = g_unloadhead;
+ g_unloadhead = bin;
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: unload_list_remove
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined then schedul_unload() will
+ * manage instances of struct binary_s allocated with kmalloc. It
+ * will keep the binary data in a link list and when SIGCHLD is received
+ * (meaning that the task has exit'ed, schedul_unload() will find the
+ * data, unload the module, and free the structure.
+ *
+ * This function will remove one structure to the linked list
+ *
+ * Input Parameter:
+ * pid - The task ID of the child task
+ *
+ * Returned Value:
+ * On success, the load structure is returned. NULL is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+static FAR struct binary_s *unload_list_remove(pid_t pid)
+{
+ FAR struct binary_s *curr;
+ FAR struct binary_s *prev;
+
+ /* Note the asymmetry. We do not have to disable interrupts here because
+ * the main thread cannot run while we are in the interrupt handler. Here,
+ * it should be sufficient to disable pre-emption so that no other thread
+ * can run.
+ */
+
+ sched_lock();
+
+ /* Find the structure in the unload list with the matching PID */
+
+ for (prev = NULL, curr = g_unloadhead;
+ curr && (curr->pid != pid);
+ prev = curr, curr = curr->flink);
+
+ /* Did we find it? It must be there. Hmmm.. we should probably ASSERT if
+ * we do not!
+ */
+
+ if (curr)
+ {
+ /* Was there another entry before this one? */
+
+ if (prev)
+ {
+ /* Yes.. remove the current entry from after the previous entry */
+
+ prev->flink = curr->flink;
+ }
+ else
+ {
+ /* No.. remove the current entry from the head of the list */
+
+ g_unloadhead = curr->flink;
+ }
+
+ /* Nullify the forward link ... superstitious */
+
+ curr->flink = NULL;
+ }
+
+ sched_unlock();
+ return curr;
+}
+
+/****************************************************************************
+ * Name: unload_callback
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined, this function may be called to
+ * automatically unload the module when task exits. It assumes that
+ * bin was allocated with kmalloc() or friends and will also automatically
+ * free the structure with kfree() when the task exists.
+ *
+ * Input Parameter:
+ * pid - The ID of the task that just exited
+ * arg - A reference to the load structure cast to FAR void *
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void unload_callback(int signo, siginfo_t *info, void *ucontext)
+{
+ FAR struct binary_s *bin;
+ int ret;
+
+ /* Sanity checking */
+
+ if (!info || signo != SIGCHLD)
+ {
+ blldbg("ERROR:Bad signal callback: signo=%d info=%p\n", signo, callback);
+ return;
+ }
+
+ /* Get the load information for this pid */
+
+ bin = unload_list_remove(info->si_pid);
+ if (!bin)
+ {
+ blldbg("ERROR: Could not find load info for PID=%d\n", info->si_pid);
+ return;
+ }
+
+ /* Unload the module */
+
+ ret = unload_module(bin);
+ if (ret < 0)
+ {
+ blldbg("ERROR: unload_module failed: %d\n", get_errno());
+ }
+
+ /* Free the load structure */
+
+ kfree(bin);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: schedule_unload
+ *
+ * Description:
+ * If CONFIG_SCHED_HAVE_PARENT is defined, this function may be called by
+ * the parent of the the newly created task to automatically unload the
+ * module when the task exits. This assumes that (1) the caller is the
+ * parent of the created task, (2) that bin was allocated with kmalloc()
+ * or friends. It will also automatically free the structure with kfree()
+ * after unloading the module.
+ *
+ * Input Parameter:
+ * pid - The task ID of the child task
+ * bin - This structure must have been allocated with kmalloc() and must
+ * persist until the task unloads
+ *
+ * Returned Value:
+ * This is an end-user function, so it follows the normal convention:
+ * It returns 0 (OK) if the callback was successfully scheduled. On
+ * failure, it returns -1 (ERROR) and sets errno appropriately.
+ *
+ * On failures, the 'bin' structure will not be deallocated and the
+ * module not not be unloaded.
+ *
+ ****************************************************************************/
+
+int schedule_unload(pid_t pid, FAR struct binary_s *bin)
+{
+ struct sigaction act;
+ struct sigaction oact;
+ sigset_t sigset;
+ irqstate_t flags;
+ int errorcode;
+ int ret;
+
+ /* Make sure that SIGCHLD is unmasked */
+
+ (void)sigemptyset(&sigset);
+ (void)sigaddset(&sigset, SIGCHLD);
+ ret = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+ if (ret != OK)
+ {
+ /* The errno value will get trashed by the following debug output */
+
+ errorcode = get_errno();
+ bvdbg("ERROR: sigprocmask failed: %d\n", ret);
+ goto errout;
+ }
+
+ /* Add the structure to the list. We want to do this *before* connecting
+ * the signal handler. This does, however, make error recovery more
+ * complex if sigaction() fails below because then we have to remove the
+ * unload structure for the list in an unexpected context.
+ */
+
+ unload_list_add(pid, bin);
+
+ /* Register the SIGCHLD handler */
+
+ act.sa_sigaction = unload_callback;
+ act.sa_flags = SA_SIGINFO;
+
+ (void)sigfillset(&act.sa_mask);
+ (void)sigdelset(&act.sa_mask, SIGCHLD);
+
+ ret = sigaction(SIGCHLD, &act, &oact);
+ if (ret != OK)
+ {
+ /* The errno value will get trashed by the following debug output */
+
+ errorcode = get_errno();
+ bvdbg("ERROR: sigaction failed: %d\n" , ret);
+
+ /* Emergency removal from the list */
+
+ flags = irqsave();
+ if (unload_list_remove(pid) != bin)
+ {
+ blldbg("ERROR: Failed to remove structure\n");
+ }
+
+ goto errout;
+ }
+
+ return OK;
+
+errout:
+ set_errno(errorcode);
+ return ERROR;
+}
+
+#endif /* !CONFIG_BINFMT_DISABLE && CONFIG_SCHED_HAVE_PARENT */
+
diff --git a/nuttx/binfmt/builtin.c b/nuttx/binfmt/builtin.c
index d80d9f5d8..e492f72e5 100644
--- a/nuttx/binfmt/builtin.c
+++ b/nuttx/binfmt/builtin.c
@@ -98,11 +98,11 @@ static int builtin_loadbinary(struct binary_s *binp)
/* Open the binary file for reading (only) */
- fd = open(filename, O_RDONLY);
+ fd = open(binp->filename, O_RDONLY);
if (fd < 0)
{
int errval = errno;
- bdbg("ERROR: Failed to open binary %s: %d\n", filename, errval);
+ bdbg("ERROR: Failed to open binary %s: %d\n", binp->filename, errval);
return -errval;
}
diff --git a/nuttx/binfmt/libbuiltin/libbuiltin_getname.c b/nuttx/binfmt/libbuiltin/libbuiltin_getname.c
index 9da2bac29..d1e3958b3 100644
--- a/nuttx/binfmt/libbuiltin/libbuiltin_getname.c
+++ b/nuttx/binfmt/libbuiltin/libbuiltin_getname.c
@@ -83,13 +83,13 @@
FAR const char *builtin_getname(int index)
{
- struct builtin_s *b;
+ FAR const struct builtin_s *builtin;
- b = builtin_for_index(index);
+ builtin = builtin_for_index(index);
- if (b != NULL)
+ if (builtin != NULL)
{
- return b->name;
+ return builtin->name;
}
return NULL;
diff --git a/nuttx/binfmt/libbuiltin/libbuiltin_isavail.c b/nuttx/binfmt/libbuiltin/libbuiltin_isavail.c
index b1d55ff21..7a480c0f3 100644
--- a/nuttx/binfmt/libbuiltin/libbuiltin_isavail.c
+++ b/nuttx/binfmt/libbuiltin/libbuiltin_isavail.c
@@ -87,12 +87,12 @@
int builtin_isavail(FAR const char *appname)
{
- FAR const char *n;
+ FAR const char *name;
int i;
- for (i = 0; n = builtin_getname(i); i++)
+ for (i = 0; (name = builtin_getname(i)); i++)
{
- if (!strncmp(n, appname, NAME_MAX))
+ if (!strncmp(name, appname, NAME_MAX))
{
return i;
}
diff --git a/nuttx/configs/sim/nsh/defconfig b/nuttx/configs/sim/nsh/defconfig
index c5eadb122..7b72ac303 100644
--- a/nuttx/configs/sim/nsh/defconfig
+++ b/nuttx/configs/sim/nsh/defconfig
@@ -130,7 +130,8 @@ CONFIG_SDCLONE_DISABLE=y
# CONFIG_SCHED_WORKQUEUE is not set
CONFIG_SCHED_WAITPID=y
# CONFIG_SCHED_ATEXIT is not set
-# CONFIG_SCHED_ONEXIT is not set
+CONFIG_SCHED_ONEXIT=y
+CONFIG_SCHED_ONEXIT_MAX=1
CONFIG_USER_ENTRYPOINT="nsh_main"
CONFIG_DISABLE_OS_API=y
# CONFIG_DISABLE_CLOCK is not set
@@ -259,7 +260,8 @@ CONFIG_MM_REGIONS=1
# Binary Formats
#
# CONFIG_BINFMT_DISABLE is not set
-# CONFIG_BINFMT_EXEPATH is not set
+CONFIG_BINFMT_EXEPATH=y
+CONFIG_PATH_INITIAL="/bin"
# CONFIG_NXFLAT is not set
# CONFIG_ELF is not set
CONFIG_BUILTIN=y
@@ -284,7 +286,10 @@ CONFIG_LIB_HOMEDIR="/"
# CONFIG_EOL_IS_LF is not set
# CONFIG_EOL_IS_BOTH_CRLF is not set
CONFIG_EOL_IS_EITHER_CRLF=y
-# CONFIG_LIBC_EXECFUNCS is not set
+CONFIG_LIBC_EXECFUNCS=y
+CONFIG_EXECFUNCS_SYMTAB="g_symtab"
+CONFIG_EXECFUNCS_NSYMBOLS=0
+CONFIG_POSIX_SPAWN_STACKSIZE=1024
# CONFIG_LIBC_STRERROR is not set
# CONFIG_LIBC_PERROR_STDOUT is not set
CONFIG_ARCH_LOWPUTC=y
@@ -410,6 +415,7 @@ CONFIG_EXAMPLES_NSH=y
#
CONFIG_NSH_LIBRARY=y
CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILE_APPS=y
#
# Disable Individual commands
diff --git a/nuttx/include/nuttx/binfmt/binfmt.h b/nuttx/include/nuttx/binfmt/binfmt.h
index 472ba0fc4..590d88402 100644
--- a/nuttx/include/nuttx/binfmt/binfmt.h
+++ b/nuttx/include/nuttx/binfmt/binfmt.h
@@ -265,7 +265,7 @@ int exec_module(FAR const struct binary_s *bin);
****************************************************************************/
#ifdef CONFIG_SCHED_HAVE_PARENT
-int schedule_unload(pid_t pid, FAR const struct binary_s *bin);
+int schedule_unload(pid_t pid, FAR struct binary_s *bin);
#endif
/****************************************************************************
diff --git a/nuttx/include/nuttx/binfmt/builtin.h b/nuttx/include/nuttx/binfmt/builtin.h
index 5921cc518..6ff565395 100644
--- a/nuttx/include/nuttx/binfmt/builtin.h
+++ b/nuttx/include/nuttx/binfmt/builtin.h
@@ -78,6 +78,36 @@ extern "C" {
****************************************************************************/
/****************************************************************************
+ * Name: builtin_initialize
+ *
+ * Description:
+ * Builtin support is built unconditionally. However, it order to
+ * use this binary format, this function must be called during system
+ * format in order to register the builtin binary format.
+ *
+ * Returned Value:
+ * This is a NuttX internal function so it follows the convention that
+ * 0 (OK) is returned on success and a negated errno is returned on
+ * failure.
+ *
+ ****************************************************************************/
+
+int builtin_initialize(void);
+
+/****************************************************************************
+ * Name: builtin_uninitialize
+ *
+ * Description:
+ * Unregister the builtin binary loader
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+void builtin_uninitialize(void);
+
+/****************************************************************************
* Utility Functions Provided to Applications by binfmt/libbuiltin
****************************************************************************/
/****************************************************************************
diff --git a/nuttx/libc/spawn/lib_ps.c b/nuttx/libc/spawn/lib_ps.c
index 638b27f87..000f711a3 100644
--- a/nuttx/libc/spawn/lib_ps.c
+++ b/nuttx/libc/spawn/lib_ps.c
@@ -247,7 +247,7 @@ static int ps_exec(FAR pid_t *pidp, FAR const char *path,
errout:
sched_unlock();
- return OK;
+ return ret;
}
/****************************************************************************
diff --git a/nuttx/tools/mkconfig.c b/nuttx/tools/mkconfig.c
index fe3e00491..d8d09df34 100644
--- a/nuttx/tools/mkconfig.c
+++ b/nuttx/tools/mkconfig.c
@@ -116,7 +116,7 @@ int main(int argc, char **argv, char **envp)
printf(" * configured (at present, NXFLAT is the only supported binary.\n");
printf(" * format).\n");
printf(" */\n\n");
- printf("#if !defined(CONFIG_NXFLAT) && !defined(CONFIG_ELF)\n");
+ printf("#if !defined(CONFIG_NXFLAT) && !defined(CONFIG_ELF) && !defined(CONFIG_BUILTIN)\n");
printf("# undef CONFIG_BINFMT_DISABLE\n");
printf("# define CONFIG_BINFMT_DISABLE 1\n");
printf("#endif\n\n");