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.
