📄 tfsloader.c
字号:
/* tfsloader.c:
* This file contains the code that is specific to each of the file types
* supported by TFS as the binary executable type.
* Currently, COFF, ELF, A.OUT and MSBIN are supported. This requires that
* TFS_EBIN_COFF, TFS_EBIN_ELF, TFS_EBIN_AOUT or TFS_EBIN_MSBIN
* respectively, be set in the monitor's config.h file. Also, defining
* TFS_EBIN_ELFMSBIN will allow TFS to support both ELF and MSBIN.
*
* General notice:
* This code is part of a boot-monitor package developed as a generic base
* platform for embedded system designs. As such, it is likely to be
* distributed to various projects beyond the control of the original
* author. Please notify the author of any enhancements made or bugs found
* so that all may benefit from the changes. In addition, notification back
* to the author will allow the new user to pick up changes that may have
* been made by other users after this version of the code was distributed.
*
* Note1: the majority of this code was edited with 4-space tabs.
* Note2: as more and more contributions are accepted, the term "author"
* is becoming a mis-representation of credit.
*
* Original author: Ed Sutter
* Email: esutter@lucent.com
* Phone: 908-582-2351
*/
#include "config.h"
#include "stddefs.h"
#include "genlib.h"
#include "tfs.h"
#include "tfsprivate.h"
#include "coff.h"
#include "elf.h"
#include "aout.h"
#include "msbin.h"
#if INCLUDE_TFS
/* tfsld_memcpy():
* Front end to all memcpy calls done by the loader.
* This function just does a quick check to make sure that the
* address ranged being copied to is not part of the monitor's
* own .bss space...
*
* How we return here depends on the verbosity level. If verbosity
* is greater than 1, then assume that this pass through tfsld_memcpy()
* is to dump out map information, not to actually do a memcpy().
* This same logic is used within the s_memcpy() routine and must remain
* consistent to work properly.
*/
int
tfsld_memcpy(char *to, char *from, int count, int verbose, int verify)
{
if (verbose <= 1) {
if (inUmonBssSpace(to,to+count))
return(-1);
}
return(s_memcpy(to,from,count,verbose,verify));
}
void
showEntrypoint(unsigned long entrypoint)
{
printf(" entrypoint: 0x%lx\n",entrypoint);
}
void
showSection(char *sname)
{
printf(" %-10s: ",sname);
}
#if TFS_EBIN_AOUT
/* tfsloadaout():
* The file pointed to by fp is assumed to be an AOUT
* formatted file. This function loads the sections of that file into
* the designated locations and returns the address of the entry point.
* Caches are flushed after loading text section.
*/
int
tfsloadaout(TFILE *fp,int verbose,long *entrypoint,char *sname,int verifyonly)
{
uchar *tfrom, *dfrom;
struct exec *ehdr;
if (tfsTrace)
printf("tfsloadaout(%s)\n",TFS_NAME(fp));
/* Establish file header pointer... */
ehdr = (struct exec *)(TFS_BASE(fp));
/* Return error if relocatable... */
if ((ehdr->a_trsize) || (ehdr->a_drsize))
return(TFSERR_BADHDR);
/* Establish locations from which text and data are to be */
/* copied from ... */
tfrom = (uchar *)(ehdr+1);
dfrom = tfrom+ehdr->a_text;
/* Copy/verify text and data sections to RAM: */
if (verbose)
showSection("text");
if (tfsld_memcpy((char *)(ehdr->a_entry),(char *)tfrom,
ehdr->a_text,verbose,verifyonly) != 0)
return(TFSERR_MEMFAIL);
/* Flush caches after writing to space that will be executed from... */
flushDcache((char *)ehdr->a_entry,ehdr->a_text);
invalidateIcache((char *)ehdr->a_entry,ehdr->a_text);
if (verbose)
showSection("data");
if (tfsld_memcpy((char *)(ehdr->a_entry+ehdr->a_text),(char *)dfrom,
ehdr->a_data,verbose,verifyonly) != 0)
return(TFSERR_MEMFAIL);
/* Clear out bss space: */
if (verbose)
showSection("bss");
if (s_memset((char *)(ehdr->a_entry+ehdr->a_text+ehdr->a_data),
0,ehdr->a_bss,verbose,verifyonly) != 0)
return(TFSERR_MEMFAIL);
if (verbose & !verifyonly)
showEntrypoint(ehdr->a_entry);
/* Store entry point: */
if (entrypoint)
*entrypoint = (long)(ehdr->a_entry);
return(TFS_OKAY);
}
#endif
#if TFS_EBIN_COFF
/* tfsloadcoff():
* The file pointed to by fp is assumed to be a COFF file.
* This function loads the sections of that file into the designated
* locations.
* Caches are flushed after loading each loadable section.
*/
int
tfsloadcoff(TFILE *fp,int verbose,long *entrypoint,char *sname,int verifyonly)
{
int i, err;
FILHDR *fhdr;
AOUTHDR *ahdr;
SCNHDR *shdr;
if (tfsTrace)
printf("tfsloadcoff(%s)\n",TFS_NAME(fp));
/* Establish file header pointers... */
fhdr = (FILHDR *)(TFS_BASE(fp));
if ((fhdr->f_opthdr == 0) || ((fhdr->f_flags & F_EXEC) == 0))
return(TFSERR_BADHDR);
err = 0;
ahdr = (AOUTHDR *)(fhdr+1);
shdr = (SCNHDR *)((uchar *)ahdr + fhdr->f_opthdr);
/* For each section header, relocate or clear if necessary... */
for (i=0;!err && i<fhdr->f_nscns;i++) {
if (shdr->s_size == 0) {
shdr++;
continue;
}
/* If incoming section name is specified, then we only load the
* section with that name...
*/
if ((sname != 0) && (strcmp(sname,shdr->s_name) != 0))
continue;
if (verbose)
showSection(shdr->s_name);
if (ISLOADABLE(shdr->s_flags)) {
#if INCLUDE_UNZIP
if (TFS_ISCPRS(fp)) {
int outsize;
outsize = decompress((char *)shdr->s_scnptr+(int)fhdr,
shdr->s_size,(char *)shdr->s_paddr);
if (outsize == -1) {
err++;
shdr++;
continue;
}
if (verbose)
printf("dcmp %7d bytes from 0x%08lx to 0x%08lx\n",outsize,
shdr->s_scnptr+(ulong)fhdr,shdr->s_paddr);
}
else
#endif
{
if (tfsld_memcpy((char *)(shdr->s_paddr),
(char *)(shdr->s_scnptr+(int)fhdr),
shdr->s_size,verbose,verifyonly) != 0)
err++;
}
/* Flush caches for each loadable section... */
flushDcache((char *)shdr->s_paddr,shdr->s_size);
invalidateIcache((char *)shdr->s_paddr,shdr->s_size);
}
else if (ISBSS(shdr->s_flags)) {
if (s_memset((char *)(shdr->s_paddr),0,shdr->s_size,
verbose,verifyonly) != 0)
err++;
}
else if (verbose)
printf("???\n");
shdr++;
}
if (verbose && !verifyonly && !sname)
showEntrypoint(ahdr->entry);
if (err)
return(TFSERR_MEMFAIL);
/* Store entry point: */
if (entrypoint)
*entrypoint = (long)(ahdr->entry);
return(TFS_OKAY);
}
#endif
#if TFS_EBIN_ELF | TFS_EBIN_ELFMSBIN
/* tfsloadelf():
* The file pointed to by fp is assumed to be an ELF file.
* This function loads the sections of that file into the designated
* locations.
* Caches are flushed after loading each loadable section.
*/
int
tfsloadelf(TFILE *fp,int verbose,long *entrypoint,char *sname,int verifyonly)
{
Elf32_Word size, notproctot;
int i, j, err;
char *shname_strings, *name;
Elf32_Addr sh_addr;
ELFFHDR *ehdr;
ELFSHDR *shdr;
ELFPHDR *phdr;
if (tfsTrace)
printf("tfsloadelf(%s)\n",TFS_NAME(fp));
/* Establish file header pointers... */
ehdr = (ELFFHDR *)(TFS_BASE(fp));
shdr = (ELFSHDR *)((int)ehdr + ehdr->e_shoff);
err = 0;
/* Verify basic file sanity... */
if ((ehdr->e_ident[0] != 0x7f) || (ehdr->e_ident[1] != 'E') ||
(ehdr->e_ident[2] != 'L') || (ehdr->e_ident[3] != 'F'))
return(TFSERR_BADHDR);
/* Store the section name string table base: */
shname_strings = (char *)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
notproctot = 0;
/* For each section header, relocate or clear if necessary... */
for (i=0;!err && i<ehdr->e_shnum;i++,shdr++) {
if ((size = shdr->sh_size) == 0)
continue;
name = shname_strings + shdr->sh_name;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -