[OpenBIOS] [PATCHv2 23/25] xcoff: implement load/init-program as per IEEE-1275 specification

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Thu Sep 8 09:01:02 CEST 2016


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 at ilande.co.uk>
---
 include/libopenbios/xcoff_load.h |    2 +-
 libopenbios/load.c               |   11 ++++
 libopenbios/xcoff_load.c         |  105 +++++++++++++++++++++++++++++++++++---
 3 files changed, 110 insertions(+), 8 deletions(-)

diff --git a/include/libopenbios/xcoff_load.h b/include/libopenbios/xcoff_load.h
index 2ec693d..854d3ba 100644
--- a/include/libopenbios/xcoff_load.h
+++ b/include/libopenbios/xcoff_load.h
@@ -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 */
diff --git a/libopenbios/load.c b/libopenbios/load.c
index 048f459..174d221 100644
--- a/libopenbios/load.c
+++ b/libopenbios/load.c
@@ -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) {
diff --git a/libopenbios/xcoff_load.c b/libopenbios/xcoff_load.c
index bd14343..11c67d9 100644
--- a/libopenbios/xcoff_load.c
+++ b/libopenbios/xcoff_load.c
@@ -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,101 @@ 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) {
+		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 retval;
+	}
+
+	/* Optional header is a.out ? */
+	if (fhdr.f_opthdr != sizeof(COFF_aouthdr_t)) {
+		DPRINTF("AOUT optional error size mismatch in XCOFF file\n");
+		return retval;
+	}
+	
+	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 retval;
+	}
+
+	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 +154,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 +230,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 !");
 }
-- 
1.7.10.4




More information about the OpenBIOS mailing list