libnxflat_load.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /****************************************************************************
  2. * binfmt/libnxflat/libnxflat_load.c
  3. *
  4. * Copyright (C) 2009 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/types.h>
  40. #include <sys/mman.h>
  41. #include <stdint.h>
  42. #include <stdlib.h>
  43. #include <nxflat.h>
  44. #include <debug.h>
  45. #include <errno.h>
  46. #include <arpa/inet.h>
  47. #include <nuttx/binfmt/nxflat.h>
  48. #include "libnxflat.h"
  49. /****************************************************************************
  50. * Pre-processor Definitions
  51. ****************************************************************************/
  52. #ifndef MAX
  53. #define MAX(x,y) ((x) > (y) ? (x) : (y))
  54. #endif
  55. /****************************************************************************
  56. * Private Constant Data
  57. ****************************************************************************/
  58. /****************************************************************************
  59. * Private Functions
  60. ****************************************************************************/
  61. /****************************************************************************
  62. * Public Functions
  63. ****************************************************************************/
  64. /****************************************************************************
  65. * Name: nxflat_load
  66. *
  67. * Description:
  68. * Loads the binary specified by nxflat_init into memory, mapping
  69. * the I-space executable regions, allocating the D-Space region,
  70. * and initializing the data segment (relocation information is
  71. * temporarily loaded into the BSS region. BSS will be cleared
  72. * by nxflat_bind() after the relocation data has been processed).
  73. *
  74. * Returned Value:
  75. * 0 (OK) is returned on success and a negated errno is returned on
  76. * failure.
  77. *
  78. ****************************************************************************/
  79. int nxflat_load(struct nxflat_loadinfo_s *loadinfo)
  80. {
  81. off_t doffset; /* Offset to .data in the NXFLAT file */
  82. uint32_t dreadsize; /* Total number of bytes of .data to be read */
  83. uint32_t relocsize; /* Memory needed to hold relocations */
  84. uint32_t extrasize; /* MAX(BSS size, relocsize) */
  85. int ret = OK;
  86. /* Calculate the extra space we need to allocate. This extra space will be
  87. * the size of the BSS section. This extra space will also be used
  88. * temporarily to hold relocation information. So the allocated size of this
  89. * region will either be the size of .data + size of.bss section OR, the
  90. * size of .data + the relocation entries, whichever is larger
  91. *
  92. * This is the amount of memory that we have to have to hold the
  93. * relocations.
  94. */
  95. relocsize = loadinfo->reloccount * sizeof(struct nxflat_reloc_s);
  96. /* In the file, the relocations should lie at the same offset as BSS.
  97. * The additional amount that we allocate have to be either (1) the
  98. * BSS size, or (2) the size of the relocation records, whicher is
  99. * larger.
  100. */
  101. extrasize = MAX(loadinfo->bsssize, relocsize);
  102. /* Use this additional amount to adjust the total size of the dspace
  103. * region.
  104. */
  105. loadinfo->dsize = loadinfo->datasize + extrasize;
  106. /* The number of bytes of data that we have to read from the file is
  107. * the data size plus the size of the relocation table.
  108. */
  109. dreadsize = loadinfo->datasize + relocsize;
  110. /* We'll need this a few times. */
  111. doffset = loadinfo->isize;
  112. /* We will make two mmap calls create an address space for the executable.
  113. * We will attempt to map the file to get the ISpace address space and
  114. * to allocate RAM to get the DSpace address space. If the filesystem does
  115. * not support file mapping, the map() implementation should do the
  116. * right thing.
  117. */
  118. /* The following call will give as a pointer to the mapped file ISpace.
  119. * This may be in ROM, RAM, Flash, ... We don't really care where the memory
  120. * resides as long as it is fully initialized and ready to execute.
  121. */
  122. loadinfo->ispace = (uint32_t)mmap(NULL, loadinfo->isize, PROT_READ,
  123. MAP_SHARED | MAP_FILE, loadinfo->filfd, 0);
  124. if (loadinfo->ispace == (uint32_t)MAP_FAILED)
  125. {
  126. berr("Failed to map NXFLAT ISpace: %d\n", errno);
  127. return -errno;
  128. }
  129. binfo("Mapped ISpace (%d bytes) at %08x\n", loadinfo->isize, loadinfo->ispace);
  130. /* The following call allocate D-Space memory and will provide a pointer
  131. * to the allocated (but still uninitialized) D-Space memory.
  132. */
  133. ret = nxflat_addrenv_alloc(loadinfo, loadinfo->dsize);
  134. if (ret < 0)
  135. {
  136. berr("ERROR: nxflat_addrenv_alloc() failed: %d\n", ret);
  137. return ret;
  138. }
  139. binfo("Allocated DSpace (%d bytes) at %p\n",
  140. loadinfo->dsize, loadinfo->dspace->region);
  141. /* If CONFIG_ARCH_ADDRENV=y, then the D-Space allocation lies in an address
  142. * environment that may not be in place. So, in that case, we must call
  143. * nxflat_addrenv_select to temporarily instantiate that address space
  144. * it can be initialized.
  145. */
  146. #ifdef CONFIG_ARCH_ADDRENV
  147. ret = nxflat_addrenv_select(loadinfo);
  148. if (ret < 0)
  149. {
  150. berr("ERROR: nxflat_addrenv_select() failed: %d\n", ret);
  151. return ret;
  152. }
  153. #endif
  154. /* Now, read the data into allocated DSpace at doffset into the allocated
  155. * DSpace memory.
  156. */
  157. ret = nxflat_read(loadinfo, (FAR char *)loadinfo->dspace->region,
  158. dreadsize, doffset);
  159. if (ret < 0)
  160. {
  161. berr("Failed to read .data section: %d\n", ret);
  162. goto errout;
  163. }
  164. binfo("TEXT: %08x Entry point offset: %08x Data offset: %08x\n",
  165. loadinfo->ispace, loadinfo->entryoffs, doffset);
  166. /* Restore the original address environment */
  167. #ifdef CONFIG_ARCH_ADDRENV
  168. ret = nxflat_addrenv_restore(loadinfo);
  169. if (ret < 0)
  170. {
  171. berr("ERROR: nxflat_addrenv_restore() failed: %d\n", ret);
  172. return ret;
  173. }
  174. #endif
  175. return OK;
  176. errout:
  177. #ifdef CONFIG_ARCH_ADDRENV
  178. (void)nxflat_addrenv_restore(loadinfo);
  179. #endif
  180. (void)nxflat_unload(loadinfo);
  181. return ret;
  182. }