libpcode README
===============
Configuration Dependencies
--------------------------
In order to use this module, you must first install the P-Code virtual
machine. You can get this from the Pascal package or from the NuttX Pascal
GIT repository. See the README.txt file at the top-level Pascal for
installation instructions. The correct location to install the P-code
virtual machine is at apps/interpreters (assuming that you are using
the NuttX apps/ package and that you have named the directory apps/).
Other required configuration settings:
CONFIG_NFILE_DESCRIPTORS > 3
CONFIG_BINFMT_DISABLE=n
CONFIG_BINFMT_PCODE=y
Directory Contents
------------------
This directory holds support files for the P-Code binary format. For other
binary formats, the library directory contains critical logic for the binary
format. But this is not the case with the P-code binary format; since the
binary file is interpreted, little additional support is necessary. As a
result, this directory includes only a few files needed by the binfmt build
logic and to support unit-level testing of the P-Code binary format.
Files include in this directory include:
1. This README.txt file
2. Build support file:
Kconfig, Make.defs
3. Unit test support files:
hello.pas -- Pascal "Hello, World!" source file
hello.pex -- P-Code POFF format file created by compiling hello.pas
romfs.img -- A ROMFS filsystem image created by:
make image
cp hello.pex image/.
genromfs -f romfs.img -d image -V pofftest
rm -rf image
romfs.h -- a C header file containing the ROMFS file system in an
initialized C structure. This file was created via:
xxd -g 1 -i romfs.img >romfs.h
then cleaned up with an editor to conform with NuttX coding standards.
Also, the data definitions in the romfs.h file should be marked with
'const' qualifier the so that the data will be stored in FLASH.
Test Configuration
------------------
Here is a simple test configuration using the NuttX simulator:
1. Install the sim/nsh configuration:
cd tools
./configure.sh sim/nsh
cd ..
2. Install p-code virtual machine as described above.
3. Modify the configuration using 'make menuconfig'. Change the following
selections:
This enables general BINFMT support:
CONFIG_DEBUG_BINFMT=y
CONFIG_BINFMT_EXEPATH=y
This enables building of the P-Code virtual machine:
CONFIG_INTERPRETERS_PCODE=y
And the P-Code runtime support:
CONFIG_SYSTEM_PRUN=y
This enables building the PCODE binary format
CONFIG_BINFMT_PCODE=y
CONFIG_BINFMT_PCODE_PRIORITY=100
CONFIG_BINFMT_PCODE_STACKSIZE=2048
This enables building and mount a test filesystem:
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:
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_BINFMT=y
CONFIG_DEBUG_INFO=y
4. In lieu of a a real test application, this Quick'n'Dirty patch can be used
to initialize the P-Code binary format:
@@ -115,6 +115,7 @@ const struct symtab_s CONFIG_EXECFUNCS_SYMTAB_ARRAY[1];
/****************************************************************************
* Name: nsh_main
****************************************************************************/
+int pcode_initialize(void);
int nsh_main(int argc, char *argv[])
{
@@ -143,6 +144,7 @@ int nsh_main(int argc, char *argv[])
exitval = 1;
}
#endif
+(void)pcode_initialize();
/* Initialize the NSH library */
5. Then after building nuttx.exe you should be able to run the P-Code hello
world example like:
nsh> hello.pex
Issues
------
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() 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. 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.
3. Modify the logic so that the P-Code execution program runs (instead of
the requested program) an it received the full path the P-Code file
on the command line. This might be accomplished by simply modifying the
argv[] structure in the struct binary_s instance.
The current start-up logic in binfmt_execmodule.c would have modified to
handle this special start-up. Perhaps the struct binfmt_s could be
extended to include an exec() method that provides custom start up logic?
4. Add a task start hook to the program. Here is where we can setup up the
on_exit() function that will clean up after the P-Code program terminates.
There are many other smaller issues to be resolved, but those are the main
ones.
A more complex solution might include a user-space p-code daemon that
receives the P-Code path in a POSIX message and starts a P-Code interpreter
thread wholly in user space.