summaryrefslogtreecommitdiff
path: root/nuttx/binfmt/libnxflat
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-06-16 22:08:59 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-06-16 22:08:59 +0000
commit731994d0383c636e43644c3dc91b91b15745b345 (patch)
tree34e83135dc0e7f8f211822a1350250000701c7cb /nuttx/binfmt/libnxflat
parent50b481d7aad72088a44da871bb7df4865e5afeb9 (diff)
downloadpx4-nuttx-731994d0383c636e43644c3dc91b91b15745b345.tar.gz
px4-nuttx-731994d0383c636e43644c3dc91b91b15745b345.tar.bz2
px4-nuttx-731994d0383c636e43644c3dc91b91b15745b345.zip
Added NXFLAT a bit at a time
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1889 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/binfmt/libnxflat')
-rw-r--r--nuttx/binfmt/libnxflat/Make.defs37
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat_load.c513
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat_stack.c224
-rw-r--r--nuttx/binfmt/libnxflat/libnxflat_verify.c116
4 files changed, 890 insertions, 0 deletions
diff --git a/nuttx/binfmt/libnxflat/Make.defs b/nuttx/binfmt/libnxflat/Make.defs
new file mode 100644
index 000000000..96cff471d
--- /dev/null
+++ b/nuttx/binfmt/libnxflat/Make.defs
@@ -0,0 +1,37 @@
+############################################################################
+# nxflat/lib/Make.defs
+#
+# Copyright (C) 2009 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# 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.
+#
+############################################################################
+
+LIBNXFLAT_ASRCS =
+LIBNXFLAT_CSRCS = libnxflat_load.c libnxflat_stack.c libnxflat_verify.c
diff --git a/nuttx/binfmt/libnxflat/libnxflat_load.c b/nuttx/binfmt/libnxflat/libnxflat_load.c
new file mode 100644
index 000000000..d456ae3a1
--- /dev/null
+++ b/nuttx/binfmt/libnxflat/libnxflat_load.c
@@ -0,0 +1,513 @@
+/****************************************************************************
+ * libnxflat/lib/libnxflat_load.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sys/types.h>
+#include <string.h>
+#include <nxflat.h>
+#include <debug.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <nuttx/nxflat.h>
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+#define V_MAP (load_info->vtbl->map)
+#define V_UNMAP (load_info->vtbl->unmap)
+#define V_ALLOC (load_info->vtbl->alloc)
+#define V_FREE (load_info->vtbl->free)
+#define V_OPEN (load_info->vtbl->open)
+#define V_READ (load_info->vtbl->read)
+#define V_CLOSE (load_info->vtbl->close)
+
+#define NXFLAT_HDR_SIZE sizeof(struct nxflat_hdr_s)
+
+#ifndef MAX
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+#endif
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+#ifdef CONFIG_NXFLAT_DEBUG
+static const char text_segment[] = "TEXT";
+static const char data_segment[] = "DATA";
+static const char bss_segment[] = "BSS";
+static const char unknown[] = "UNKNOWN";
+
+static const char *segment[] =
+{
+ text_segment,
+ data_segment,
+ bss_segment,
+ unknown
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxflat_swap32
+ ****************************************************************************/
+
+#ifdef __BIG_ENDIAN
+static inline uint32 nxflat_swap32(uint32 little)
+{
+ uint32 big =
+ ((little >> 24) & 0xff) |
+ (((little >> 16) & 0xff) << 8) |
+ (((little >> 8) & 0xff) << 16) |
+ ((little & 0xff) << 24);
+ return big;
+}
+#endif
+
+/****************************************************************************
+ * Name: nxflat_reloc
+ ****************************************************************************/
+
+static void nxflat_reloc(struct nxflat_loadinfo_s *load_info, uint32 rl)
+{
+ union
+ {
+ uint32 l;
+ struct nxflat_reloc_s s;
+ } reloc;
+ uint32 *ptr;
+ uint32 datastart;
+
+ /* Force the long value into a union so that we can strip off some
+ * bit-encoded values.
+ */
+
+ reloc.l = rl;
+
+ /* We only support relocations in the data sections.
+ * Verify that the the relocation address lies in the data
+ * section of the file image.
+ */
+
+ if (reloc.s.r_offset > load_info->data_size)
+ {
+ dbg("ERROR: Relocation at 0x%08x invalid -- "
+ "does not lie in the data segment, size=0x%08x\n",
+ reloc.s.r_offset, load_info->data_size);
+ dbg(" Relocation not performed!\n");
+ }
+ else if ((reloc.s.r_offset & 0x00000003) != 0)
+ {
+ dbg("ERROR: Relocation at 0x%08x invalid -- "
+ "Improperly aligned\n",
+ reloc.s.r_offset);
+ }
+ else
+ {
+ /* Get a reference to the "real" start of data. It is
+ * offset slightly from the beginning of the allocated
+ * DSpace to hold information needed by ld.so at run time.
+ */
+
+ datastart = load_info->dspace + NXFLAT_DATA_OFFSET;
+
+ /* Get a pointer to the value that needs relocation in
+ * DSpace.
+ */
+
+ ptr = (uint32*)(datastart + reloc.s.r_offset);
+
+ vdbg("Relocation of variable at DATASEG+0x%08x "
+ "(address 0x%p, currently 0x%08x) into segment %s\n",
+ reloc.s.r_offset, ptr, *ptr, segment[reloc.s.r_type]);
+
+ switch (reloc.s.r_type)
+ {
+ /* TEXT is located at an offset of NXFLAT_HDR_SIZE from
+ * the allocated/mapped ISpace region.
+ */
+
+ case NXFLAT_RELOC_TYPE_TEXT:
+ *ptr += load_info->ispace + NXFLAT_HDR_SIZE;
+ break;
+
+ /* DATA and BSS are always contiguous regions. DATA
+ * begins at an offset of NXFLAT_DATA_OFFSET from
+ * the beginning of the allocated data segment.
+ * BSS is positioned after DATA, unrelocated references
+ * to BSS include the data offset.
+ *
+ * In other contexts, is it necessary to add the data_size
+ * to get the BSS offset like:
+ *
+ * *ptr += datastart + load_info->data_size;
+ */
+
+ case NXFLAT_RELOC_TYPE_DATA:
+ case NXFLAT_RELOC_TYPE_BSS:
+ *ptr += datastart;
+ break;
+
+ /* This case happens normally if the symbol is a weak
+ * undefined symbol. We permit these.
+ */
+
+ case NXFLAT_RELOC_TYPE_NONE:
+ dbg("NULL relocation!\n");
+ break;
+
+ default:
+ dbg("ERROR: Unknown relocation type=%d\n", reloc.s.r_type);
+ break;
+ }
+
+ vdbg("Relocation became 0x%08x\n", *ptr);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxflat_init
+ ****************************************************************************/
+
+int nxflat_init(bin_handle_t bin_handle, file_handle_t file_handle,
+ const struct nxflat_hdr_s *header, const struct nxflat_vtbl_s *vtbl,
+ struct nxflat_loadinfo_s *load_info)
+{
+ uint32 datastart;
+ uint32 dataend;
+ uint32 bssstart;
+ uint32 bssend;
+
+ vdbg("bin_handle=0x%p header=0x%p load_info=0x%p\n",
+ bin_handle, header, load_info);
+
+ /* Clear the load info structure */
+
+ memset(load_info, 0, sizeof(struct nxflat_loadinfo_s));
+
+ /* Verify the xFLT header */
+
+ if (nxflat_verifyheader(header) != 0)
+ {
+ /* This is not an error because we will be called
+ * to attempt loading EVERY binary. Returning -ENOEXEC
+ * simply informs the system that the file is not
+ * an xFLT file. Besides, if there is something worth
+ * complaining about, nnxflat_verifyheader() has already
+ * done so.
+ */
+
+ dbg("Bad xFLT header\n");
+ return -ENOEXEC;
+ }
+
+ /* Save all of the input values in the load_info structure */
+
+ load_info->bin_handle = bin_handle;
+ load_info->file_handle = file_handle;
+ load_info->header = header;
+ load_info->vtbl = vtbl;
+
+ /* And extract some additional information from the xflat
+ * header. Note that the information in the xflat header is in
+ * network order.
+ */
+
+ datastart = ntohl(header->h_datastart);
+ dataend = ntohl(header->h_dataend);
+ bssstart = dataend;
+ bssend = ntohl(header->h_bssend);
+
+ /* And put this information into the load_info structure as well.
+ *
+ * Note that:
+ *
+ * ispace_size = the address range from 0 up to datastart.
+ * data_size = the address range from datastart up to dataend
+ * bss_size = the address range from dataend up to bssend.
+ */
+
+ load_info->entry_offset = ntohl(header->h_entry);
+ load_info->ispace_size = datastart;
+
+ load_info->data_size = dataend - datastart;
+ load_info->bss_size = bssend - dataend;
+ load_info->stack_size = ntohl(header->h_stacksize);
+
+ /* This is the initial dspace size. We'll recaculate this later
+ * after the memory has been allocated. So that the caller can feel
+ * free to modify dspace_size values from now until then.
+ */
+
+ load_info->dspace_size = /* Total DSpace Size is: */
+ (NXFLAT_DATA_OFFSET + /* Memory set aside for ldso */
+ bssend - datastart + /* Data and bss segment sizes */
+ load_info->stack_size); /* (Current) stack size */
+
+ /* Get the offset to the start of the relocations (we'll relocate
+ * this later).
+ */
+
+ load_info->reloc_start = ntohl(header->h_relocstart);
+ load_info->reloc_count = ntohl(header->h_reloccount);
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: nxflat_uninit
+ ****************************************************************************/
+
+int nxflat_uninit(struct nxflat_loadinfo_s *load_info)
+{
+ if (load_info->file_handle)
+ {
+ V_CLOSE(load_info->file_handle);
+ }
+ return 0;
+}
+
+/****************************************************************************
+ * Name: nxflat_load
+ ****************************************************************************/
+
+int nxflat_load(struct nxflat_loadinfo_s *load_info)
+{
+ uint32 dspace_read_size;
+ uint32 data_offset;
+ uint32 *reloc_tab;
+ uint32 result;
+ int i;
+
+ /* Calculate the extra space we need to map in. This region
+ * will be the BSS segment and the stack. It will also be used
+ * temporarily to hold relocation information. So the size of this
+ * region will either be the size of the BSS section and the
+ * stack OR, it the size of the relocation entries, whichever
+ * is larger
+ */
+
+ {
+ uint32 extra_alloc;
+ uint32 reloc_size;
+
+ /* This is the amount of memory that we have to have to hold
+ * the relocations.
+ */
+
+ reloc_size = load_info->reloc_count * sizeof(uint32);
+
+ /* In the file, the relocations should lie at the same offset
+ * as BSS. The additional amount that we allocate have to
+ * be either (1) the BSS size + the stack size, or (2) the
+ * size of the relocation records, whicher is larger.
+ */
+
+ extra_alloc = MAX(load_info->bss_size + load_info->stack_size,
+ reloc_size);
+
+ /* Use this addtional amount to adjust the total size of the
+ * dspace region. */
+
+ load_info->dspace_size =
+ NXFLAT_DATA_OFFSET + /* Memory used by ldso */
+ load_info->data_size + /* Initialized data */
+ extra_alloc; /* bss+stack/relocs */
+
+ /* The number of bytes of data that we have to read from the
+ * file is the data size plus the size of the relocation table.
+ */
+
+ dspace_read_size = load_info->data_size + reloc_size;
+ }
+
+ /* We'll need this a few times as well. */
+
+ data_offset = load_info->ispace_size;
+
+ /* We will make two mmap calls create an address space for
+ * the executable. We will attempt to map the file to get
+ * the ISpace address space and to allocate RAM to get the
+ * DSpace address space. If the system does not support
+ * file mapping, the V_MAP() implementation should do the
+ * right thing.
+ */
+
+ /* The following call will give as a pointer to the mapped
+ * file ISpace. This may be in ROM, RAM, Flash, ...
+ * We don't really care where the memory resides as long
+ * as it is fully initialized and ready to execute.
+ * However, the memory should be share-able between processes;
+ * otherwise, we don't really have shared libraries.
+ */
+
+ load_info->ispace = (uint32)V_MAP(load_info->file_handle,
+ load_info->ispace_size);
+
+ if (load_info->ispace >= (uint32) -4096)
+ {
+ dbg("Failed to map xFLT ISpace, error=%d\n", -load_info->ispace);
+ return load_info->ispace;
+ }
+
+ vdbg("Mapped ISpace (%d bytes) at 0x%08x\n",
+ load_info->ispace_size, load_info->ispace);
+
+ /* The following call will give a pointer to the allocated
+ * but uninitialized ISpace memory.
+ */
+
+ load_info->dspace = (uint32)V_ALLOC(load_info->dspace_size);
+
+ if (load_info->dspace >= (uint32) -4096)
+ {
+ dbg("Failed to allocate DSpace, error=%d\n",
+ -load_info->ispace);
+ (void)nxflat_unload(load_info);
+ return load_info->ispace;
+ }
+
+ vdbg("Allocated DSpace (%d bytes) at 0x%08x\n",
+ load_info->dspace_size, load_info->dspace);
+
+ /* Now, read the data into allocated DSpace at an offset into
+ * the allocated DSpace memory. This offset provides a small
+ * amount of BSS for use by the loader.
+ */
+
+ result = V_READ(load_info->bin_handle,
+ load_info->file_handle,
+ (char*)(load_info->dspace + NXFLAT_DATA_OFFSET),
+ dspace_read_size,
+ data_offset);
+
+ if (result >= (uint32) -4096)
+ {
+ dbg("Unable to read DSpace, errno %d\n", -result);
+ (void)nxflat_unload(load_info);
+ return result;
+ }
+
+ /* Save information about the allocation. */
+
+ load_info->alloc_start = load_info->dspace;
+ load_info->alloc_size = load_info->dspace_size;
+
+ vdbg("TEXT=0x%x Entry point offset=0x%08x, datastart is 0x%08x\n",
+ load_info->ispace, load_info->entry_offset, data_offset);
+
+ /* Resolve the address of the relocation table. In the file, the
+ * relocations should lie at the same offset as BSS. The current
+ * value of reloc_start is the offset from the beginning of the file.
+ * The following adjustment will convert it to an address in DSpace.
+ */
+
+ reloc_tab = (uint32*)
+ (load_info->reloc_start /* File offset to reloc records */
+ + load_info->dspace /* + Allocated DSpace memory */
+ + NXFLAT_DATA_OFFSET /* + Offset for ldso usage */
+ - load_info->ispace_size); /* - File offset to DSpace */
+
+ vdbg("Relocation table at 0x%p, reloc_count=%d\n",
+ reloc_tab, load_info->reloc_count);
+
+ /* Now run through the relocation entries. */
+
+ for (i=0; i < load_info->reloc_count; i++)
+ {
+#ifdef __BIG_ENDIAN
+ nxflat_reloc(load_info, nxflat_swap32(reloc_tab[i]));
+#else
+ nxflat_reloc(load_info, reloc_tab[i]);
+#endif
+ }
+
+ /* Zero the BSS, BRK and stack areas, trashing the relocations
+ * that lived in the corresponding space in the file. */
+
+ memset((void*)(load_info->dspace + NXFLAT_DATA_OFFSET + load_info->data_size),
+ 0,
+ (load_info->dspace_size - NXFLAT_DATA_OFFSET -
+ load_info->data_size));
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: nxflat_unload
+ *
+ * Description:
+ * This function unloads the object from memory. This essentially
+ * undoes the actions of nxflat_load.
+ *
+ ****************************************************************************/
+
+int nxflat_unload(struct nxflat_loadinfo_s *load_info)
+{
+ /* Reset the contents of the info structure. */
+
+ /* Nothing is allocated */
+
+ load_info->alloc_start = 0;
+ load_info->alloc_size = 0;
+
+ /* Release the memory segments */
+
+ if (load_info->ispace)
+ {
+ V_UNMAP((void*)load_info->ispace, load_info->ispace_size);
+ load_info->ispace = 0;
+ }
+
+ if (load_info->dspace)
+ {
+ V_FREE((void*)load_info->dspace, load_info->dspace_size);
+ load_info->dspace = 0;
+ }
+
+ return 0;
+}
+
diff --git a/nuttx/binfmt/libnxflat/libnxflat_stack.c b/nuttx/binfmt/libnxflat/libnxflat_stack.c
new file mode 100644
index 000000000..082a2e05e
--- /dev/null
+++ b/nuttx/binfmt/libnxflat/libnxflat_stack.c
@@ -0,0 +1,224 @@
+/****************************************************************************
+ * libnxflat/lib/nxflat_stack.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sys/types.h>
+#include <debug.h>
+#include <errno.h>
+#include <nuttx/nxflat.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxflat_adjuststacksize
+ ****************************************************************************/
+
+void nxflat_adjuststacksize(struct nxflat_loadinfo_s *load_info,
+ int argc, int envc, int system_usage)
+{
+ uint32 total_usage = system_usage;
+
+ /* For argc, we will store the array (argc elements), the argc
+ * value itself, plus a null pointer.
+ */
+
+ total_usage += (argc + 2) * sizeof(uint32);
+
+ /* For envc, we will store the array (envc elements) plus a null
+ * pointer.
+ */
+
+ total_usage += (envc + 1) * sizeof(uint32);
+
+ /* And we will store six additional words described the memory
+ * layout.
+ */
+
+ total_usage += 6 * sizeof(uint32);
+
+ /* Add this to the previously determined stack size */
+
+ load_info->stack_size += total_usage;
+}
+
+/****************************************************************************
+ * Name: nxflat_initstack
+ *
+ * Description:
+ * When we enter the NXFLAT_ loader, it will expect to see a stack frame
+ * like the following. NOTE: This logic assumes a push down stack
+ * (i.e., we decrement the stack pointer to go from the "BOTTOM" to
+ * the "TOP").
+ *
+ *
+ * TOP->argc Argument count (integer)
+ * argv[0...(argc-1)] Program arguments (pointers)
+ * NULL Marks end of arguments
+ * env[0...N] Environment variables (pointers)
+ * NULL Marks end of environment variables
+ * loader ispace Address of loader ISpace (NXFLAT_ header)
+ * loader dspace Address of loader DSpace
+ * loader dspace size Size of the allocated loader DSpace
+ * program ispace Address of program ISpace (NXFLAT_ header)
+ * program dspace Address of program DSpace
+ * BOTTOM->program dspace size Size of the allocated program DSpace
+ *
+ ****************************************************************************/
+
+uint32 nxflat_initstack(struct nxflat_loadinfo_s *prog_load_info,
+ struct nxflat_loadinfo_s *lib_load_info,
+ int argc, int envc, char *p)
+{
+ uint32 *argv;
+ uint32 *envp;
+ uint32 *sp;
+ char dummy;
+
+ /* p points to the beginning of the array of arguments;
+ * sp points to the "bottom" of a push down stack.
+ */
+
+ sp = (uint32*)((-(uint32)sizeof(char*))&(uint32) p);
+
+ /* Place program information on the stack */
+
+ if (prog_load_info)
+ {
+ *sp-- = (uint32)prog_load_info->dspace_size;
+ *sp-- = (uint32)prog_load_info->dspace;
+ *sp-- = (uint32)prog_load_info->ispace;
+ }
+ else
+ {
+ dbg("No program load info provided\n");
+ return -EINVAL;
+ }
+
+ /* Place loader information on the stack */
+
+ if (lib_load_info)
+ {
+ *sp-- = (uint32)lib_load_info->dspace_size;
+ *sp-- = (uint32)lib_load_info->dspace;
+ *sp-- = (uint32)lib_load_info->ispace;
+ }
+ else
+ {
+ *sp-- = (uint32)0;
+ *sp-- = (uint32)0;
+ *sp-- = (uint32)0;
+ }
+
+ /* Allocate space on the stack for the envp array contents
+ * (including space for a null terminator).
+ */
+
+ sp -= envc+1;
+ envp = sp;
+
+ /* Allocate space on the stack for the argv array contents
+ * (including space for a null terminator).
+ */
+
+ sp -= argc+1;
+ argv = sp;
+
+ /* Put argc on the stack. sp now points to the "top" of the
+ * stack as it will be received by the new task.
+ */
+
+ *sp-- = (uint32)argc;
+
+ /* Copy argv pointers into the stack frame (terminated with
+ * a null pointer).
+ */
+
+ prog_load_info->arg_start = (uint32)p;
+ while (argc-->0)
+ {
+ /* Put the address of the beginning of the string */
+
+ *argv++ = (uint32)p;
+
+ /* Search for the end of the string */
+
+ do
+ {
+ dummy = *p++;
+ }
+ while (dummy);
+ }
+ *argv = (uint32)NULL,argv;
+
+ /* Copy envp pointers into the stack frame (terminated with
+ * a null pointer).
+ */
+
+ prog_load_info->env_start = (uint32)p;
+ while (envc-->0)
+ {
+ /* Put the address of the beginning of the string */
+
+ *envp++ = (uint32)p;
+
+ /* Search for the end of the string */
+
+ do
+ {
+ dummy = *p++;
+ }
+ while (dummy);
+ }
+ *envp = (uint32)NULL;
+
+ prog_load_info->env_end = (uint32)p;
+
+ return (uint32)sp;
+}
+
diff --git a/nuttx/binfmt/libnxflat/libnxflat_verify.c b/nuttx/binfmt/libnxflat/libnxflat_verify.c
new file mode 100644
index 000000000..b31994b8b
--- /dev/null
+++ b/nuttx/binfmt/libnxflat/libnxflat_verify.c
@@ -0,0 +1,116 @@
+/****************************************************************************
+ * nxflat/lib/nxflat_stack.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <sys/types.h>
+#include <string.h>
+#include <debug.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <nuttx/nxflat.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define V_MAP (load_info->vtbl->map)
+#define V_UNMAP (load_info->vtbl->unmap)
+#define V_ALLOC (load_info->vtbl->alloc)
+#define V_FREE (load_info->vtbl->free)
+#define V_OPEN (load_info->vtbl->open)
+#define V_READ (load_info->vtbl->read)
+#define V_CLOSE (load_info->vtbl->close)
+
+#define XFLT_HDR_SIZE sizeof(struct nxflat_hdr_s)
+
+#ifndef MAX
+# define MAX(x,y) ((x) > (y) ? (x) : (y))
+#endif
+
+/****************************************************************************
+ * Private Constant Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nxflat_verifyheader
+ ****************************************************************************/
+
+int nxflat_verifyheader(const struct nxflat_hdr_s *header)
+{
+ uint16 revision;
+
+ if (!header)
+ {
+ dbg("NULL NXFLAT header!");
+ return -ENOEXEC;
+ }
+
+ /* Check the FLT header -- magic number and revision.
+ *
+ * If the the magic number does not match. Just return
+ * silently. This is not our binary.
+ */
+
+ if (strncmp(header->h_magic, "NXFLAT", 4) != 0)
+ {
+ dbg("Unrecognized magic=\"%c%c%c%c\"",
+ header->h_magic[0], header->h_magic[1],
+ header->h_magic[2], header->h_magic[3]);
+ return -ENOEXEC;
+ }
+
+ /* Complain a little more if the version does not match. */
+
+ revision = ntohs(header->h_rev);
+ if (revision != NXFLAT_VERSION_CURRENT)
+ {
+ dbg("Unsupported NXFLAT version=%d\n", revision);
+ return -ENOEXEC;
+ }
+ return 0;
+}
+