binfmt: Remove PCODE dependency on apps/pcode.h

This commit is contained in:
Gregory Nutt 2016-06-30 11:25:59 -06:00
parent 7f296f9226
commit 378b22ec07
5 changed files with 170 additions and 82 deletions

View File

@ -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

View File

@ -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

View File

@ -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 <gnutt@nuttx.org>
#
# 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

View File

@ -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.

View File

@ -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 <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -47,15 +47,16 @@
#include <errno.h>
#include <debug.h>
#include <apps/prun.h>
#include <nuttx/kmalloc.h>
#include <nuttx/poff.h>
#include <nuttx/fs/ramdisk.h>
#include <nuttx/binfmt/binfmt.h>
#include <nuttx/binfmt/pcode.h>
#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 */