xcoff: implement load/init-program as per IEEE-1275 specification
load should place the file at load-base, whilst init-program should parse the memory at load-base and set up the context accordingly. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
This commit is contained in:
parent
d6a5ca977b
commit
610f9f0e21
|
@ -21,7 +21,7 @@
|
|||
#include "libopenbios/sys_info.h"
|
||||
|
||||
extern int is_xcoff(COFF_filehdr_t *fhdr);
|
||||
extern int xcoff_load(struct sys_info *info, const char *filename);
|
||||
extern int xcoff_load(ihandle_t dev);
|
||||
extern void xcoff_init_program(void);
|
||||
|
||||
#endif /* _H_XCOFFLOAD */
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
#include "libopenbios/forth_load.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LOADER_XCOFF
|
||||
#include "libopenbios/xcoff_load.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LOADER_BOOTCODE
|
||||
#include "libopenbios/bootcode_load.h"
|
||||
#endif
|
||||
|
@ -94,6 +98,13 @@ void load(ihandle_t dev)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LOADER_XCOFF
|
||||
if (xcoff_load(dev) != LOADER_NOT_SUPPORT) {
|
||||
feval("load-state >ls.file-size @");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LOADER_BOOTCODE
|
||||
/* Check for a "raw" %BOOT bootcode payload */
|
||||
if (bootcode_load(dev) != LOADER_NOT_SUPPORT) {
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
#include "config.h"
|
||||
#include "libopenbios/bindings.h"
|
||||
#include "libopenbios/initprogram.h"
|
||||
#include "libopenbios/xcoff_load.h"
|
||||
#include "libc/diskio.h"
|
||||
|
||||
#include "arch/common/xcoff.h"
|
||||
|
||||
|
@ -44,10 +46,102 @@ is_xcoff(COFF_filehdr_t *fhdr)
|
|||
}
|
||||
|
||||
int
|
||||
xcoff_load(struct sys_info *info, const char *filename)
|
||||
xcoff_load(ihandle_t dev)
|
||||
{
|
||||
// Currently not implemented
|
||||
return LOADER_NOT_SUPPORT;
|
||||
COFF_filehdr_t fhdr;
|
||||
COFF_aouthdr_t ahdr;
|
||||
COFF_scnhdr_t shdr;
|
||||
uint32_t offset;
|
||||
size_t total_size = 0;
|
||||
int fd, i;
|
||||
int retval = -1;
|
||||
|
||||
/* Mark the saved-program-state as invalid */
|
||||
feval("0 state-valid !");
|
||||
|
||||
fd = open_ih(dev);
|
||||
if (fd == -1) {
|
||||
retval = LOADER_NOT_SUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (offset = 0; offset < 16 * 512; offset += 512) {
|
||||
seek_io(fd, offset);
|
||||
if (read_io(fd, &fhdr, sizeof fhdr) != sizeof fhdr) {
|
||||
DPRINTF("Can't read XCOFF header\n");
|
||||
retval = LOADER_NOT_SUPPORT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (is_xcoff(&fhdr))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Is it executable ? */
|
||||
if (fhdr.f_magic != 0x01DF &&
|
||||
(fhdr.f_flags & COFF_F_EXEC) == 0) {
|
||||
DPRINTF("Not an executable XCOFF file %02x\n", fhdr.f_flags);
|
||||
return LOADER_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
/* Optional header is a.out ? */
|
||||
if (fhdr.f_opthdr != sizeof(COFF_aouthdr_t)) {
|
||||
DPRINTF("AOUT optional error size mismatch in XCOFF file\n");
|
||||
return LOADER_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
seek_io(fd, sizeof(COFF_filehdr_t));
|
||||
read_io(fd, &ahdr, sizeof(COFF_aouthdr_t));
|
||||
|
||||
/* check a.out magic number */
|
||||
if (ahdr.magic != AOUT_MAGIC) {
|
||||
DPRINTF("Invalid AOUT optional header\n");
|
||||
return LOADER_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t);
|
||||
|
||||
DPRINTF("XCOFF file with %d sections\n", fhdr.f_nscns);
|
||||
|
||||
for (i = 0; i < fhdr.f_nscns; i++) {
|
||||
DPRINTF("Read header at offset %0x\n", offset);
|
||||
seek_io(fd, offset);
|
||||
read_io(fd, &shdr, sizeof(COFF_scnhdr_t));
|
||||
|
||||
DPRINTF("Initializing '%s' section from %0x %0x to %0x (%0x)\n",
|
||||
shdr.s_name, offset, shdr.s_scnptr,
|
||||
shdr.s_vaddr, shdr.s_size);
|
||||
|
||||
if (strcmp(shdr.s_name, ".text") == 0) {
|
||||
read_io(fd, (void *)shdr.s_vaddr, shdr.s_size);
|
||||
total_size += shdr.s_size;
|
||||
#ifdef CONFIG_PPC
|
||||
flush_icache_range((char*)(uintptr_t)shdr.s_vaddr,
|
||||
(char*)(uintptr_t)(shdr.s_vaddr + shdr.s_size));
|
||||
#endif
|
||||
} else if (strcmp(shdr.s_name, ".data") == 0) {
|
||||
read_io(fd, (void *)shdr.s_vaddr, shdr.s_size);
|
||||
total_size += shdr.s_size;
|
||||
|
||||
} else if (strcmp(shdr.s_name, ".bss") == 0) {
|
||||
memset((void *)(uintptr_t)shdr.s_vaddr, 0, shdr.s_size);
|
||||
total_size += shdr.s_size;
|
||||
} else {
|
||||
DPRINTF(" Skip '%s' section\n", shdr.s_name);
|
||||
}
|
||||
offset += sizeof(COFF_scnhdr_t);
|
||||
}
|
||||
|
||||
DPRINTF("XCOFF entry point: %x\n", *(uint32_t*)ahdr.entry);
|
||||
|
||||
// Initialise load-state
|
||||
PUSH(total_size);
|
||||
feval("load-state >ls.file-size !");
|
||||
feval("xcoff load-state >ls.file-type !");
|
||||
|
||||
out:
|
||||
close_io(fd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -61,8 +155,6 @@ xcoff_init_program(void)
|
|||
size_t total_size = 0;
|
||||
int i;
|
||||
|
||||
feval("0 state-valid !");
|
||||
|
||||
feval("load-base");
|
||||
base = (char*)cell2pointer(POP());
|
||||
|
||||
|
@ -139,9 +231,9 @@ xcoff_init_program(void)
|
|||
// Initialise load-state
|
||||
PUSH(*(uint32_t*)(uintptr_t)ahdr->entry);
|
||||
feval("load-state >ls.entry !");
|
||||
PUSH(total_size);
|
||||
feval("load-state >ls.file-size !");
|
||||
feval("xcoff load-state >ls.file-type !");
|
||||
|
||||
arch_init_program();
|
||||
|
||||
feval("-1 state-valid !");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue