From 378b22ec07cade90a150c948b40a402c578bacbb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 30 Jun 2016 11:25:59 -0600 Subject: [PATCH] binfmt: Remove PCODE dependency on apps/pcode.h --- binfmt/Kconfig | 14 ++-- binfmt/libpcode/Kconfig | 39 +++++----- binfmt/libpcode/Make.defs | 14 +++- binfmt/libpcode/README.txt | 35 ++++----- binfmt/pcode.c | 150 ++++++++++++++++++++++++++++--------- 5 files changed, 170 insertions(+), 82 deletions(-) diff --git a/binfmt/Kconfig b/binfmt/Kconfig index fc2b457f89..bd563bc0c8 100644 --- a/binfmt/Kconfig +++ b/binfmt/Kconfig @@ -69,10 +69,10 @@ if BUILTIN source binfmt/libbuiltin/Kconfig endif -config PCODE +config BINFMT_PCODE bool "Support P-Code Applications" default n - depends on INTERPRETERS_PCODE && SYSTEM_PRUN && ((!BUILD_PROTECTED && !BUILD_KERNEL) || EXPERIMENTAL) + depends on INTERPRETERS_PCODE && ((!BUILD_PROTECTED && !BUILD_KERNEL) || EXPERIMENTAL) ---help--- Enable support for interpreted P-Code binaries. P-Code binaries are generated by the NuttX Pascal compiler. @@ -84,12 +84,12 @@ config PCODE Pascal package directory for more details. The correct installation directory is: apps/interpreters. - ISSUES: This feature is highly coupled with logic in the apps/subdirectory - and, as a consequence, cannot be used in environments that do not - include the standard NuttX apps/ nor in build configurations using - UILD_PROTECTED or BUILD_KERNEL.. + ISSUES: This feature is highly coupled with logic in the apps/ + directory and, as a consequence, cannot be used in environments that + do not include the standard NuttX apps/ directory nor in build + configurations using BUILD_PROTECTED or BUILD_KERNEL. -if PCODE +if BINFMT_PCODE source binfmt/libpcode/Kconfig endif diff --git a/binfmt/libpcode/Kconfig b/binfmt/libpcode/Kconfig index 046dc71c55..12bc6665c0 100644 --- a/binfmt/libpcode/Kconfig +++ b/binfmt/libpcode/Kconfig @@ -3,65 +3,68 @@ # see the file kconfig-language.txt in the NuttX tools repository. # -config PCODE_STACKSIZE +config BINFMT_PCODE_STACKSIZE int "P-code interpreter stack size" default 2048 ---help--- This is the stack size that will be used when starting P-code interpreter. -config PCODE_PRIORITY +config BINFMT_PCODE_PRIORITY int "P-code interpreter priority" default 100 ---help--- This is the task_priority that will be used when starting P-code interpreter. -config PCODE_VARSTACKSIZE +config BINFMT_PCODE_VARSTACKSIZE int "P-code variable stack size" default 1024 ---help--- This size of the P-Code variable storage area to be allocated by the P-Code runtime. -config PCODE_STRSTACKSIZE +config BINFMT_PCODE_STRSTACKSIZE int "P-code string stack size" default 128 ---help--- This size of the P-Code string stack area to be allocated by the P-Code runtime. -config PCODE_TEST_FS +config BINFMT_PCODE_TEST_FS bool "Mount a test file system" depends on FS_ROMFS && !DISABLE_MOUNTPOINT ---help--- - Mount a test file system. This test file system was used to verify the P-Code binary format. + Mount a test file system. This test file system was used to verify + the P-Code binary format. -if PCODE_TEST_FS +if BINFMT_PCODE_TEST_FS -config PCODE_TEST_DEVMINOR +config BINFMT_PCODE_TEST_DEVMINOR int "Test file system minor device number" default 0 ---help--- - The minor device number of the ROMFS block. For example, the N in /dev/ramN. - Used for registering the RAM block driver that will hold the ROMFS file system - containing the P-code files to be tested. Default: 0 + The minor device number of the ROMFS block. For example, the N in + /dev/ramN. Used for registering the RAM block driver that will hold + the ROMFS file system containing the P-code files to be tested. + Default: 0 -config PCODE_TEST_DEVPATH +config BINFMT_PCODE_TEST_DEVPATH string "Test file system device Path" default "/dev/ram0" ---help--- - The path to the ROMFS block driver device. This must match PCODE_TEST_DEVMINOR. - Used for registering the RAM block driver that will hold the ROMFS file system - containing the P-code files to be tested. Default: "/dev/ram0" + The path to the ROMFS block driver device. This must match + BINFMT_PCODE_TEST_DEVMINOR. Used for registering the RAM block + driver that will hold the ROMFS file system containing the P-code + files to be tested. Default: "/dev/ram0" -config PCODE_TEST_MOUNTPOINT +config BINFMT_PCODE_TEST_MOUNTPOINT string "Test file system mount point" default "/bin" ---help--- Location where the test file system will be mounted -endif # PCODE_TEST_FS +endif # BINFMT_PCODE_TEST_FS -config PCODE_DUMPBUFFER +config BINFMT_PCODE_DUMPBUFFER bool "Dump P-code buffers" default n depends on DEBUG_INFO diff --git a/binfmt/libpcode/Make.defs b/binfmt/libpcode/Make.defs index e84d0d3257..5b0107c39a 100644 --- a/binfmt/libpcode/Make.defs +++ b/binfmt/libpcode/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # binfmt/libpcode/Make.defs # -# Copyright (C) 2014 Gregory Nutt. All rights reserved. +# Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -33,7 +33,7 @@ # ############################################################################ -ifeq ($(CONFIG_PCODE),y) +ifeq ($(CONFIG_BINFMT_PCODE),y) # P-code application interfaces @@ -46,7 +46,15 @@ BINFMT_CSRCS += pcode.c # Add an include path so that P-Code related header files may reside in # the libpcode sub-directory -CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" "$(TOPDIR)$(DELIM)binfmt$(DELIM)libpcode"} +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \ + "$(TOPDIR)$(DELIM)binfmt$(DELIM)libpcode"} + +# FIXME: This also depends upon header files installed at +# apps/interpreters/pcode + +PCODE_DIR = $(TOPDIR)$(DELIM)$(CONFIG_APPS_DIR)$(DELIM)interpreters$(DELIM)pcode +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \ + "$(PCODE_DIR)$(DELIM)include" "$(PCODE_DIR)$(DELIM)insn$(DELIM)include"} # Hook the libpcode subdirectory into the build diff --git a/binfmt/libpcode/README.txt b/binfmt/libpcode/README.txt index d6cb606af7..4e0724ee07 100644 --- a/binfmt/libpcode/README.txt +++ b/binfmt/libpcode/README.txt @@ -14,7 +14,7 @@ Other required configuration settings: CONFIG_NFILE_DESCRIPTORS > 3 CONFIG_BINFMT_DISABLE=n - CONFIG_PCODE=y + CONFIG_BINFMT_PCODE=y Directory Contents ------------------ @@ -83,16 +83,16 @@ Here is a simple test configuration using the NuttX simulator: This enables building the PCODE binary format - CONFIG_PCODE=y - CONFIG_PCODE_PRIORITY=100 - CONFIG_PCODE_STACKSIZE=2048 + CONFIG_BINFMT_PCODE=y + CONFIG_BINFMT_PCODE_PRIORITY=100 + CONFIG_BINFMT_PCODE_STACKSIZE=2048 This enables building and mount a test filesystem: - CONFIG_PCODE_TEST_FS=y - CONFIG_PCODE_TEST_DEVMINOR=3 - CONFIG_PCODE_TEST_DEVPATH="/dev/ram3" - CONFIG_PCODE_TEST_MOUNTPOINT="/bin" + CONFIG_BINFMT_PCODE_TEST_FS=y + CONFIG_BINFMT_PCODE_TEST_DEVMINOR=3 + CONFIG_BINFMT_PCODE_TEST_DEVPATH="/dev/ram3" + CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT="/bin" Debug options can also be enabled with: @@ -127,23 +127,24 @@ Here is a simple test configuration using the NuttX simulator: Issues ------ -1. As implemented now, there is a tight coupling between the nuttx/directory - and the apps/ directory. That should not be the case; the nuttx/ logic - should be completely independent of apps/ logic (but not vice versa). +1. As implemented now, there is a tight coupling between the nuttx/binfmt + directory and the apps/interpreters/pcode directory. That should not + be the case; the nuttx/ logic should be completely independent of apps/ + logic (but not vice versa). 2. The current implementation will not work in the CONFIG_BUILD_PROTECTED or CONFIG_BUILD_KERNEL configurations. That is because of the little proxy - logic (function pcode_proxy() in the file pcode.c). (a) That logic would - attempt to link with P-code logic that resides in user space. That will - not work. And (2) that proxy would be started in user mode but in the - kernel address space which will certainly crash immediately. + logic (function pcode_proxy() and prun() in the file pcode.c). (a) That + logic would attempt to link with P-code logic that resides in user space. + That will not work. And (2) that proxy would be started in user mode but + in the kernel address space which will certainly crash immediately. The general idea to fix both of these problems is as follows: 1. Eliminate the pcode_proxy. Instead start a P-Code execution program that resides in the file system. That P-Code execution program already - exists. It is in apps/system/prun. This program should be built as, - say, an ELF binary and installed in a file system. + exists. This program should be built as, say, an ELF binary and + installed in a file system. 2. Add a configuration setting that gives the full path to where the pexec program is stored in the filesystem. diff --git a/binfmt/pcode.c b/binfmt/pcode.c index 8e52b75aab..f295e1291c 100644 --- a/binfmt/pcode.c +++ b/binfmt/pcode.c @@ -1,7 +1,7 @@ /**************************************************************************** * binfmt/pcode.c * - * Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2014-2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -47,15 +47,16 @@ #include #include -#include - #include #include #include #include #include -#ifdef CONFIG_PCODE +#include "pexec.h" +#include "pedefs.h" + +#ifdef CONFIG_BINFMT_PCODE /**************************************************************************** * Pre-processor Definitions @@ -72,23 +73,19 @@ # error The binary loader is disabled (CONFIG_BINFMT_DISABLE)! #endif -#ifndef CONFIG_PCODE -# error You must select CONFIG_PCODE in your configuration file -#endif - #ifndef CONFIG_SCHED_ONEXIT # error CONFIG_SCHED_ONEXIT is required #endif -#ifndef CONFIG_PCODE_VARSTACKSIZE -# define CONFIG_PCODE_VARSTACKSIZE 1024 +#ifndef CONFIG_BINFMT_PCODE_VARSTACKSIZE +# define CONFIG_BINFMT_PCODE_VARSTACKSIZE 1024 #endif -#ifndef CONFIG_PCODE_STRSTACKSIZE -# define CONFIG_PCODE_STRSTACKSIZE 128 +#ifndef CONFIG_BINFMT_PCODE_STRSTACKSIZE +# define CONFIG_BINFMT_PCODE_STRSTACKSIZE 128 #endif -#ifdef CONFIG_PCODE_TEST_FS +#ifdef CONFIG_BINFMT_PCODE_TEST_FS # ifndef CONFIG_FS_ROMFS # error You must select CONFIG_FS_ROMFS in your configuration file # endif @@ -97,16 +94,16 @@ # error You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file # endif -# ifndef CONFIG_PCODE_TEST_DEVMINOR -# define CONFIG_PCODE_TEST_DEVMINOR 0 +# ifndef CONFIG_BINFMT_PCODE_TEST_DEVMINOR +# define CONFIG_BINFMT_PCODE_TEST_DEVMINOR 0 # endif -# ifndef CONFIG_PCODE_TEST_DEVPATH -# define CONFIG_PCODE_TEST_DEVPATH "/dev/ram0" +# ifndef CONFIG_BINFMT_PCODE_TEST_DEVPATH +# define CONFIG_BINFMT_PCODE_TEST_DEVPATH "/dev/ram0" # endif -# ifndef CONFIG_PCODE_TEST_MOUNTPOINT -# define CONFIG_PCODE_TEST_MOUNTPOINT "/bin" +# ifndef CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT +# define CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT "/bin" # endif #endif @@ -130,6 +127,16 @@ struct binfmt_handoff_s * Private Function Prototypes ****************************************************************************/ +static int pcode_run(FAR char *exepath, size_t varsize, size_t strsize); +#ifdef CONFIG_BINFMT_PCODE_TEST_FS +static int pcode_mount_testfs(void); +#endif +#if !defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_BUILD_KERNEL) +static void pcode_onexit(int exitcode, FAR void *arg); +#endif +#if !defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_BUILD_KERNEL) +static int pcode_proxy(int argc, char **argv); +#endif static int pcode_load(FAR struct binary_s *binp); static int pcode_unload(FAR struct binary_s *binp); @@ -146,7 +153,7 @@ static struct binfmt_s g_pcode_binfmt = struct binfmt_handoff_s g_pcode_handoff; -#ifdef CONFIG_PCODE_TEST_FS +#ifdef CONFIG_BINFMT_PCODE_TEST_FS # include "romfs.h" #endif @@ -154,6 +161,69 @@ struct binfmt_handoff_s g_pcode_handoff; * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: pcode_run + * + * Description: + * Execute/interpret a P-Code file. This function does not return until + * the P-code program terminates or until a fatal error occurs. + * + * Input Parameters: + * exepath - The full path to the P-Code binary. + * varsize - Size of the P-Code variable stack + * strsize - the size of the P-Code string stack. + * + * Returned Value: + * OK if the P-Code program successfully terminated; A negated errno value + * is returned on the event of any failure. + * + ****************************************************************************/ + +static int pcode_run(FAR char *exepath, size_t varsize, size_t strsize) +{ + FAR struct pexec_s *st; + int errcode; + int ret = OK; + + /* Load the POFF file into memory */ + + st = pload(exepath, varsize, varsize); + if (!st) + { + berr("ERROR: Could not load %s\n", exepath); + return -ENOEXEC; + } + + binfo("Loaded %s\n", exepath); + + /* Execute the P-Code program until a stopping condition occurs */ + + for (;;) + { + /* Execute the instruction; Check for exceptional conditions */ + + errcode = pexec(st); + if (errcode != eNOERROR) + { + break; + } + } + + if (errcode != eEXIT) + { + /* REVISIT: Select a more appropriated return errocode */ + + berr("ERROR: Runtime error 0x%02x -- Execution Stopped\n", errcode); + ret = -ENOEXEC; + } + + /* Clean up resources used by the interpreter */ + + binfo("Execution terminated\n"); + pexec_release(st); + return ret; +} + /**************************************************************************** * Name: pcode_mount_testfs * @@ -162,15 +232,15 @@ struct binfmt_handoff_s g_pcode_handoff; * ****************************************************************************/ -#ifdef CONFIG_PCODE_TEST_FS +#ifdef CONFIG_BINFMT_PCODE_TEST_FS static int pcode_mount_testfs(void) { int ret; /* Create a ROM disk for the ROMFS filesystem */ - binfo("Registering romdisk at /dev/ram%d\n", CONFIG_PCODE_TEST_DEVMINOR); - ret = romdisk_register(CONFIG_PCODE_TEST_DEVMINOR, (FAR uint8_t *)romfs_img, + binfo("Registering romdisk at /dev/ram%d\n", CONFIG_BINFMT_PCODE_TEST_DEVMINOR); + ret = romdisk_register(CONFIG_BINFMT_PCODE_TEST_DEVMINOR, (FAR uint8_t *)romfs_img, NSECTORS(ROMFS_IMG_LEN), SECTORSIZE); if (ret < 0) { @@ -181,9 +251,11 @@ static int pcode_mount_testfs(void) /* Mount the test file system */ binfo("Mounting ROMFS filesystem at target=%s with source=%s\n", - CONFIG_PCODE_TEST_MOUNTPOINT, CONFIG_PCODE_TEST_DEVPATH); + CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT, + CONFIG_BINFMT_PCODE_TEST_DEVPATH); - ret = mount(CONFIG_PCODE_TEST_DEVPATH, CONFIG_PCODE_TEST_MOUNTPOINT, + ret = mount(CONFIG_BINFMT_PCODE_TEST_DEVPATH, + CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT, "romfs", MS_RDONLY, NULL); if (ret < 0) { @@ -191,7 +263,9 @@ static int pcode_mount_testfs(void) DEBUGASSERT(errval > 0); berr("ERROR: mount(%s,%s,romfs) failed: %d\n", - CONFIG_PCODE_TEST_DEVPATH, CONFIG_PCODE_TEST_MOUNTPOINT, errval); + CONFIG_BINFMT_PCODE_TEST_DEVPATH, + CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT, errval); + return -errval; } @@ -201,7 +275,7 @@ static int pcode_mount_testfs(void) */ #if defined(CONFIG_BINFMT_EXEPATH) && !defined(CONFIG_PATH_INITIAL) - (void)setenv("PATH", CONFIG_PCODE_TEST_MOUNTPOINT, 1); + (void)setenv("PATH", CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT, 1); #endif return OK; @@ -273,7 +347,8 @@ static int pcode_proxy(int argc, char **argv) /* Load the P-code file and execute it */ - ret = prun(fullpath, CONFIG_PCODE_VARSTACKSIZE, CONFIG_PCODE_STRSTACKSIZE); + ret = pcode_run(fullpath, CONFIG_BINFMT_PCODE_VARSTACKSIZE, + CONFIG_BINFMT_PCODE_STRSTACKSIZE); /* We no longer need the fullpath */ @@ -324,8 +399,8 @@ static int pcode_load(struct binary_s *binp) /* Read the POFF file header */ - for (remaining = sizeof(struct poff_fileheader_s), ptr = (FAR uint8_t *)&hdr; - remaining > 0; ) + for (remaining = sizeof(struct poff_fileheader_s), + ptr = (FAR uint8_t *)&hdr; remaining > 0; ) { /* Read the next GULP */ @@ -358,7 +433,7 @@ static int pcode_load(struct binary_s *binp) } } -#ifdef CONFIG_PCODE_DUMPBUFFER +#ifdef CONFIG_BINFMT_PCODE_DUMPBUFFER lib_dumpbuffer("POFF File Header", &hdr, sizeof(poff_fileheader_s)); #endif @@ -377,8 +452,8 @@ static int pcode_load(struct binary_s *binp) */ binp->entrypt = pcode_proxy; - binp->stacksize = CONFIG_PCODE_STACKSIZE; - binp->priority = CONFIG_PCODE_PRIORITY; + binp->stacksize = CONFIG_BINFMT_PCODE_STACKSIZE; + binp->priority = CONFIG_BINFMT_PCODE_PRIORITY; /* Get exclusive access to the p-code handoff structure */ @@ -517,14 +592,15 @@ void pcode_uninitialize(void) UNUSED(errval); } -#ifdef CONFIG_PCODE_TEST_FS - ret = umount(CONFIG_PCODE_TEST_MOUNTPOINT); +#ifdef CONFIG_BINFMT_PCODE_TEST_FS + ret = umount(CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT); if (ret < 0) { int errval = get_errno(); DEBUGASSERT(errval > 0); - berr("ERROR: umount(%s) failed: %d\n", CONFIG_PCODE_TEST_MOUNTPOINT, errval); + berr("ERROR: umount(%s) failed: %d\n", + CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT, errval); UNUSED(errval); } #endif @@ -534,4 +610,4 @@ void pcode_uninitialize(void) sem_destroy(&g_pcode_handoff.exclsem); } -#endif /* CONFIG_PCODE */ +#endif /* CONFIG_BINFMT_PCODE */