bootElfLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:9k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* bootElfLib.c - ELF module boot loader */
  2. /* Copyright 1984-1996 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01f,11dec01,tlc  Add endianess checking to elfHdrRead routine.  SPR #66152
  8.                  fix.
  9. 01e,09may96,p_m  ifdef'd PPC specific undefined macros to allow other arch build
  10. 01d,31may95,caf  changed EM_ARCH_MACHINE_ALT to EM_ARCH_MACH_ALT.
  11. 01c,25may95,kvk  added EM_ARCH_MACHINE_ALT as valid arch for elfHdrRead
  12. 01b,01nov94,kdl  added default definition of EM_ARCH_MACHINE.
  13. 01a,25oct93,cd   created from bootEcoffLib v01d
  14. */
  15. /*
  16. DESCRIPTION
  17. This library provides an object module boot loading facility for ELF
  18. format files.  Any ELF format file may be boot loaded into memory.
  19. Modules may be boot loaded from any I/O stream.
  20. INCLUDE FILE: bootElfLib.h
  21. SEE ALSO: bootLoadLib
  22. .pG "Basic OS"
  23. */
  24. #include "vxWorks.h"
  25. #include "stdio.h"
  26. #include "bootLoadLib.h"
  27. #include "bootElfLib.h"
  28. #include "loadElfLib.h"
  29. #include "elf.h"
  30. #include "elftypes.h"
  31. #include "ioLib.h"
  32. #include "fioLib.h"
  33. #include "cacheLib.h"
  34. #include "errnoLib.h"
  35. #include "stdlib.h"
  36. #include "string.h"
  37. #ifndef EM_ARCH_MACHINE
  38. #define EM_ARCH_MACHINE -1 /* default */
  39. #endif
  40. #undef DEBUG
  41. #ifdef DEBUG
  42. LOCAL STATUS bootElfDebug = 1;
  43. #define DBG(x) if (bootElfDebug) sysPrintf x
  44. #else
  45. #define DBG(x)
  46. #endif
  47. /*
  48.  * Define this is if FIOWHERE cannot be relied upon to return the current
  49.  * file position.  Note that defining this makes the loader non reentrant.
  50.  */
  51. #define FIOWHEREFAILS
  52. /*
  53.  * Define this if lseek does not work on all possible sources of input.
  54.  * Note that the current implementation of lseek (vxWorks5.1)
  55.  * uses FIOWHERE...
  56.  */
  57. #define LSEEKFAILS
  58. #if defined(LSEEKFAILS)
  59. #define lseek internalLseek
  60. #endif
  61. #if defined(LSEEKFAILS) && defined(FIOWHEREFAILS)
  62. #define read internalRead
  63. #else
  64. #define read fioRead
  65. #endif
  66. /* forward static functions */
  67. LOCAL STATUS elfHdrRead (int fd, Elf32_Ehdr *pHdr);
  68. #if defined(LSEEKFAILS) && defined(FIOWHEREFAILS)
  69. LOCAL int filePosition;
  70. /*****************************************************************************
  71. *
  72. * internalRead - read data from load file
  73. *
  74. * This routine reads a chunk of data from the load file.  It will attempt to
  75. * read <size> bytes by calling fioRead.  Because sockets do not support the
  76. * FIOWHERE ioctl, this routine keeps a local file position variable so that
  77. * internalLSeek can find out where it is.
  78. *
  79. * RETURNS: Number of bytes read.
  80. *
  81. * SEE ALSO: internalLSeek
  82. *
  83. * NOMANUAL
  84. */
  85. LOCAL int internalRead
  86.     (
  87.     int fd, /* file descriptor */
  88.     char *buf, /* data buffer */
  89.     int size /* number of bytes to read */
  90.     )
  91.     {
  92.     int n;
  93.     n = fioRead (fd, buf, size);
  94.     if (n > 0)
  95. filePosition += n;
  96.     DBG(("read(%d)=%dn", size, n));
  97.     return (n);
  98.     }
  99. #endif
  100. #if defined(LSEEKFAILS)
  101. /*****************************************************************************
  102. *
  103. * internalLseek - seek to position in load file
  104. *
  105. * This routine seeks to a given position in the load file.
  106. * The seek is emulated by performing calls to read until the correct
  107. * file position is reached, thus there is an implicit assumption that you will
  108. * only ever want to seek forwards.
  109. * If the FIOWHERE ioctl does not operate correctly on sockets (vxWorks 5.1beta)
  110. * the file position is determined by a local variable that is updated by read.
  111. *
  112. * RETURNS: The new offset from the beginning of the file, or ERROR.
  113. *
  114. * NOMANUAL
  115. */
  116. LOCAL long internalLseek
  117.     (
  118.     int fd, /* file descriptor */
  119.     long offset, /* position to seek to */
  120.     int whence /* relative file position */
  121.     )
  122.     {
  123.     long where, howmany;
  124.     char buf[4096];
  125. #if defined(FIOWHEREFAILS)
  126.     where = filePosition;
  127. #else
  128.     where = ioctl (fd, FIOWHERE, 0);
  129. #endif
  130.     switch (whence) {
  131.       case L_SET:
  132. break;
  133.       case L_INCR:
  134. offset += where;
  135. break;
  136.       case L_XTND:
  137.       default:
  138. return (ERROR);
  139. }
  140.     if (offset < where)
  141. {
  142. DBG(("backward seek where=%d offset=%dn", where, offset));
  143. return (ERROR);
  144. }
  145.     for (howmany = offset - where;
  146.  howmany >= sizeof(buf); howmany -= sizeof(buf))
  147. {
  148. if (read (fd, buf, sizeof(buf)) != sizeof(buf))
  149.     {
  150.     DBG(("lseek read failuren"));
  151.     return (ERROR);
  152.     }
  153. }
  154.     if (howmany > 0 && (read (fd, buf, howmany) != howmany))
  155. {
  156. DBG(("lseek read failuren"));
  157. return (ERROR);
  158. }
  159.     DBG(("lseek returns offsetn"));
  160.     return (offset);
  161.     }
  162. #endif
  163. /*******************************************************************************
  164. *
  165. * bootElfModule - load an object module into memory
  166. *
  167. * This routine loads an object module in ELF format from the specified
  168. * file, and places the code, data, and BSS at the locations specified within
  169. * the file.  The entry point of the module is returned in <pEntry>.  This 
  170. * routine is generally used for bootstrap loading.
  171. *
  172. * RETURNS:
  173. * OK, or
  174. * ERROR if the routine cannot read the file
  175. *
  176. * SEE ALSO: loadModuleAt()
  177. */
  178. LOCAL STATUS bootElfModule 
  179.     (
  180.     int fd,
  181.     FUNCPTR *pEntry  /* entry point of module */
  182.     )
  183.     {
  184.     Elf32_Ehdr ehdr;
  185.     Elf32_Phdr *pPhdr, *pph;
  186.     int i;
  187.     int segment = 0;
  188.     unsigned int nbytes;
  189.     if (elfHdrRead (fd, &ehdr) != OK)
  190. {
  191. errnoSet (S_loadElfLib_HDR_READ);
  192. return (ERROR);
  193. }
  194.     /* check the program header validity */
  195.     if (ehdr.e_phoff == 0 ||
  196. ehdr.e_phnum == 0 || ehdr.e_phentsize != sizeof(Elf32_Phdr))
  197. {
  198. errnoSet (S_loadElfLib_HDR_ERROR);
  199. return (ERROR);
  200. }
  201.     /* read the program header */
  202.     nbytes = ehdr.e_phnum * ehdr.e_phentsize;
  203.     if ((pPhdr = (Elf32_Phdr *) malloc (nbytes)) == NULL)
  204. {
  205. errnoSet (S_loadElfLib_PHDR_MALLOC);
  206. return (ERROR);
  207. }
  208.     if (lseek (fd, ehdr.e_phoff, L_SET) == ERROR ||
  209. read (fd, (char *) pPhdr, nbytes) != nbytes)
  210. {
  211. errnoSet (S_loadElfLib_PHDR_READ);
  212.       fail:
  213. free (pPhdr);
  214. return (ERROR);
  215. }
  216.     /* read each loadable segment */
  217.     for (i = 0, pph = pPhdr; i < ehdr.e_phnum; i++, pph++)
  218. {
  219. if (pph->p_type == PT_LOAD)
  220.     {
  221.     /* This segment is to be loaded, so do it */
  222.     printf ("%s%ld", segment++ == 0 ? "" : " + ", pph->p_memsz);
  223.     /* load the bits that are present in the file */
  224.     if (pph->p_filesz) {
  225. if (lseek (fd, pph->p_offset, L_SET) != pph->p_offset ||
  226.     read (fd, (char *) pph->p_vaddr, pph->p_filesz) != pph->p_filesz)
  227.     {
  228.     errnoSet (S_loadElfLib_READ_SECTIONS);
  229.     goto fail;
  230.     }
  231. }
  232.     /* zap the bits that didn't appear in the file */
  233.     if (pph->p_filesz < pph->p_memsz)
  234. bzero ((char *) (pph->p_vaddr+pph->p_filesz),
  235.        pph->p_memsz - pph->p_filesz);
  236.     /* if we might end up executing this we need to flush the cache */
  237.     if (pph->p_flags & PF_X)
  238. cacheTextUpdate ((char *)pph->p_vaddr, pph->p_memsz);
  239.     }
  240. }
  241.     printf ("n");
  242.     *pEntry = (FUNCPTR) ehdr.e_entry;
  243.     return (OK);
  244.     }
  245.     
  246. /*******************************************************************************
  247. *
  248. * elfHdrRead - read in elf header
  249. *
  250. * This routine read in the elf header from the specified file and verify it.
  251. * Only relocatable and executable files are supported.
  252. *
  253. * RETURNS: OK or ERROR
  254. *
  255. * NOMANUAL
  256. */
  257. LOCAL STATUS elfHdrRead
  258.     (
  259.     int fd, /* file to read in */
  260.     Elf32_Ehdr * pHdr /* elf header */
  261.     )
  262.     {
  263.     int endiannessIsOk;
  264.     
  265. #if defined(LSEEKFAILS) && defined(FIOWHEREFAILS)
  266.     filePosition = 0; /* assume we are at beginning of file */
  267. #endif
  268.     if (read (fd, (char *) pHdr, sizeof (*pHdr)) != sizeof (*pHdr))
  269.         {
  270. printf ("Erroneous header readn");
  271.         return (ERROR);
  272.         }
  273.     /* Is it an ELF file? */
  274.     if (strncmp ((char *) pHdr->e_ident, (char *) ELFMAG, SELFMAG) != 0)
  275.         return (ERROR);
  276.     /* Does the endianess match? */ 
  277.     if (((_BYTE_ORDER == _BIG_ENDIAN) &&
  278.          (pHdr->e_ident[EI_DATA] == ELFDATA2MSB)) ||
  279.         ((_BYTE_ORDER == _LITTLE_ENDIAN) &&
  280.          (pHdr->e_ident[EI_DATA] == ELFDATA2LSB)))
  281.          endiannessIsOk = TRUE;
  282.     else
  283.          endiannessIsOk = FALSE;
  284.     if (!endiannessIsOk)
  285.         {
  286.         printf ("Endianness is incorrectn");
  287.         return ERROR;
  288.         }
  289.     /* Is the size correct? */
  290.     if (pHdr->e_ehsize != sizeof (*pHdr))
  291. {
  292. printf ("Size is incorrectn");
  293. return (ERROR);
  294. }
  295.     /* check machine type */
  296. #if (CPU_FAMILY==PPC)
  297.     if (pHdr->e_machine != EM_ARCH_MACHINE &&
  298. pHdr->e_machine != EM_ARCH_MACH_ALT)
  299.         return (ERROR);
  300. #endif /* (CPU_FAMILY==PPC) */
  301.     /* Relocatable and Excecutable files supported */
  302.     if ((pHdr->e_type == ET_REL) || (pHdr->e_type == ET_EXEC))
  303. {
  304.         return (OK);
  305. }
  306.     else
  307. return (ERROR);
  308.     }
  309. /********************************************************************************
  310. * bootElfInit - initialize the system for elf load modules
  311. *
  312. * This routine initialises VxWorks to use ELF format for
  313. * boot loading modules.
  314. *
  315. * RETURNS:
  316. * OK, or
  317. * ERROR if XXX
  318. *
  319. * SEE ALSO: loadModuleAt()
  320. */
  321. STATUS bootElfInit
  322.     (
  323.     )
  324.     {
  325.     bootLoadRoutine = bootElfModule;
  326.     return (OK);
  327.     }