Switch all SPARC32 devices over from the private map_io() function over to OFMEM...
[openbios.git] / libopenbios / xcoff_load.c
blob0dcb28ca4dd3609fc6e053ddf8c364ba31312d30
1 /*
3 * <xcoff_load.c>
5 * XCOFF file loader
7 * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
9 * from original XCOFF loader by Steven Noonan <steven@uplinklabs.net>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2
17 #include "config.h"
18 #include "libopenbios/bindings.h"
19 #include "libopenbios/xcoff_load.h"
21 #include "arch/common/xcoff.h"
23 #ifdef CONFIG_PPC
24 extern void flush_icache_range( char *start, char *stop );
25 #endif
27 //#define DEBUG_XCOFF
29 #ifdef DEBUG_XCOFF
30 #define DPRINTF(fmt, args...) \
31 do { printk("%s: " fmt, __func__ , ##args); } while (0)
32 #else
33 #define DPRINTF(fmt, args...) \
34 do { } while (0)
35 #endif
37 int
38 is_xcoff(COFF_filehdr_t *fhdr)
40 return (fhdr->f_magic == U802WRMAGIC
41 || fhdr->f_magic == U802ROMAGIC
42 || fhdr->f_magic == U802TOCMAGIC
43 || fhdr->f_magic == U802TOMAGIC);
46 int
47 xcoff_load(struct sys_info *info, const char *filename)
49 // Currently not implemented
50 return LOADER_NOT_SUPPORT;
53 void
54 xcoff_init_program(void)
56 char *base;
57 COFF_filehdr_t *fhdr;
58 COFF_aouthdr_t *ahdr;
59 COFF_scnhdr_t *shdr;
60 uint32_t offset;
61 size_t total_size = 0;
62 int i;
64 feval("0 state-valid !");
66 feval("load-base");
67 base = (char*)cell2pointer(POP());
69 fhdr = (COFF_filehdr_t*)base;
71 /* Is it an XCOFF file ? */
72 if (!is_xcoff(fhdr)) {
73 DPRINTF("Not a XCOFF file %02x\n", fhdr->f_magic);
74 return;
77 /* Is it executable ? */
78 if (fhdr->f_magic != 0x01DF &&
79 (fhdr->f_flags & COFF_F_EXEC) == 0) {
80 DPRINTF("Not an executable XCOFF file %02x\n", fhdr->f_flags);
81 return;
84 /* Optional header is a.out ? */
85 if (fhdr->f_opthdr != sizeof(COFF_aouthdr_t)) {
86 DPRINTF("AOUT optional error size mismatch in XCOFF file\n");
87 return;
90 ahdr = (COFF_aouthdr_t*)(base + sizeof(COFF_filehdr_t));
92 /* check a.out magic number */
93 if (ahdr->magic != AOUT_MAGIC) {
94 DPRINTF("Invalid AOUT optional header\n");
95 return;
98 offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t);
100 DPRINTF("XCOFF file with %d sections\n", fhdr->f_nscns);
102 for (i = 0; i < fhdr->f_nscns; i++) {
104 DPRINTF("Read header at offset %0x\n", offset);
106 shdr = (COFF_scnhdr_t*)(base + offset);
108 DPRINTF("Initializing '%s' section from %0x %0x to %0x (%0x)\n",
109 shdr->s_name, offset, shdr->s_scnptr,
110 shdr->s_vaddr, shdr->s_size);
112 if (strcmp(shdr->s_name, ".text") == 0) {
114 memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
115 shdr->s_size);
116 total_size += shdr->s_size;
117 #ifdef CONFIG_PPC
118 flush_icache_range((char*)(uintptr_t)shdr->s_vaddr,
119 (char*)(uintptr_t)(shdr->s_vaddr + shdr->s_size));
120 #endif
121 } else if (strcmp(shdr->s_name, ".data") == 0) {
123 memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
124 shdr->s_size);
125 total_size += shdr->s_size;
127 } else if (strcmp(shdr->s_name, ".bss") == 0) {
129 memset((void *)(uintptr_t)shdr->s_vaddr, 0, shdr->s_size);
130 total_size += shdr->s_size;
131 } else {
132 DPRINTF(" Skip '%s' section\n", shdr->s_name);
134 offset += sizeof(COFF_scnhdr_t);
137 DPRINTF("XCOFF entry point: %x\n", *(uint32_t*)ahdr->entry);
139 // Initialise saved-program-state
140 PUSH(*(uint32_t*)(uintptr_t)ahdr->entry);
141 feval("saved-program-state >sps.entry !");
142 PUSH(total_size);
143 feval("saved-program-state >sps.file-size !");
144 feval("xcoff saved-program-state >sps.file-type !");
146 feval("-1 state-valid !");