📄 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 and A.OUT are supported. This requires that
* TFS_EBIN_COFF, TFS_EBIN_ELF or TFS_EBIN_AOUT, respectively, be set in
* the monitor's config.h file.
*
* 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.
*
* Author: Ed Sutter
* email: esutter@lucent.com (home: lesutter@worldnet.att.net)
* phone: 908-582-2351 (home: 908-889-5161)
*/
#include "config.h"
#include "stddefs.h"
#include "genlib.h"
#include "tfs.h"
#include "coff.h"
#include "elf.h"
#include "aout.h"
#if INCLUDE_TFS
#if TFS_EBIN_AOUT
/* tfsloadaout():
* The file pointed to by fp has been determined to be an A.OUT
* 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
tfsloadebin(TFILE *fp,int verbose,long *entrypoint,int verifyonly)
{
uchar *tfrom, *dfrom;
struct exec *ehdr;
/* 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)
printf("%-10s: ","text");
if (tfsmemcpy((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)
printf("%-10s: ","data");
if (tfsmemcpy((char *)(ehdr->a_entry+ehdr->a_text),(char *)dfrom,
ehdr->a_data,verbose,verifyonly) != 0)
return(TFSERR_MEMFAIL);
/* Clear out bss space: */
if (verbose)
printf("%-10s: ","bss");
if (tfsmemset((char *)(ehdr->a_entry+ehdr->a_text+ehdr->a_data),
0,ehdr->a_bss,verbose,verifyonly) != 0)
return(TFSERR_MEMFAIL);
if (verbose & !verifyonly)
printf("entrypoint: 0x%lx\n",ehdr->a_entry);
/* Store entry point: */
if (entrypoint)
*entrypoint = (long)(ehdr->a_entry);
return(TFS_OKAY);
}
#elif TFS_EBIN_COFF
/* tfsloadcoff():
* The file pointed to by fp has been determined 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
tfsloadebin(TFILE *fp,int verbose,long *entrypoint,int verifyonly)
{
int i, err;
FILHDR *fhdr;
AOUTHDR *ahdr;
SCNHDR *shdr;
/* 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 (verbose)
printf("%-10s: ",shdr->s_name);
if (ISLOADABLE(shdr->s_flags)) {
if (TFS_ISCPRS(fp)) {
extern int decompress(char *,int, char *);
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 {
if (tfsmemcpy((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 (tfsmemset((char *)(shdr->s_paddr),0,shdr->s_size,
verbose,verifyonly) != 0)
err++;
}
else if (verbose)
printf("???\n");
shdr++;
}
if (verbose & !verifyonly)
printf("entrypoint: 0x%lx\n",ahdr->entry);
if (err)
return(TFSERR_MEMFAIL);
/* Store entry point: */
if (entrypoint)
*entrypoint = (long)(ahdr->entry);
return(TFS_OKAY);
}
#elif TFS_EBIN_ELF
/* tfsloadelf():
* The file pointed to by fp has been determined 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
tfsloadebin(TFILE *fp,int verbose,long *entrypoint,int verifyonly)
{
Elf32_Word size, notproctot;
int i, err;
char *shname_strings;
ELFFHDR *ehdr;
ELFSHDR *shdr;
/* 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;
if ((verbose) && (ehdr->e_shstrndx != SHN_UNDEF))
printf("%-10s: ", shname_strings + shdr->sh_name);
if (!(shdr->sh_flags & SHF_ALLOC)) {
notproctot += size;
if (verbose)
printf(" %7ld bytes not processed (tot=%ld)\n",
size,notproctot);
continue;
}
if (shdr->sh_type == SHT_NOBITS) {
if (tfsmemset((char *)(shdr->sh_addr),0,size,
verbose,verifyonly) != 0)
err++;
}
else {
if (TFS_ISCPRS(fp)) {
extern int decompress(char *,int, char *);
int outsize;
outsize = decompress((char *)(ehdr)+shdr->sh_offset,size,
(char *)shdr->sh_addr);
if (outsize == -1) {
err++;
continue;
}
if (verbose)
printf("dcmp %7d bytes from 0x%08lx to 0x%08lx\n",outsize,
(ulong)(ehdr)+shdr->sh_offset,shdr->sh_addr);
}
else {
if (tfsmemcpy((char *)(shdr->sh_addr),
(char *)((int)ehdr+shdr->sh_offset),
size,verbose,verifyonly) != 0)
err++;
}
/* Flush caches for each loadable section... */
flushDcache((char *)shdr->sh_addr,size);
invalidateIcache((char *)shdr->sh_addr,size);
}
}
if (err)
return(TFSERR_MEMFAIL);
if (verbose & !verifyonly)
printf("entrypoint: 0x%lx\n",ehdr->e_entry);
/* Store entry point: */
if (entrypoint)
*entrypoint = (long)(ehdr->e_entry);
return(TFS_OKAY);
}
#endif /* TFS_EBIN_XXXX */
#endif /* INCLUDE_TFS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -