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
18 #include "libopenbios/bindings.h"
19 #include "libopenbios/xcoff_load.h"
21 #include "arch/common/xcoff.h"
24 extern void flush_icache_range( char *start
, char *stop
);
30 #define DPRINTF(fmt, args...) \
31 do { printk("%s: " fmt, __func__ , ##args); } while (0)
33 #define DPRINTF(fmt, args...) \
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
);
47 xcoff_load(struct sys_info
*info
, const char *filename
)
49 // Currently not implemented
50 return LOADER_NOT_SUPPORT
;
54 xcoff_init_program(void)
61 size_t total_size
= 0;
64 feval("0 state-valid !");
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
);
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
);
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");
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");
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
,
116 total_size
+= shdr
->s_size
;
118 flush_icache_range((char*)(uintptr_t)shdr
->s_vaddr
,
119 (char*)(uintptr_t)(shdr
->s_vaddr
+ shdr
->s_size
));
121 } else if (strcmp(shdr
->s_name
, ".data") == 0) {
123 memcpy((char*)(uintptr_t)shdr
->s_vaddr
, base
+ shdr
->s_scnptr
,
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
;
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 !");
143 feval("saved-program-state >sps.file-size !");
144 feval("xcoff saved-program-state >sps.file-type !");
146 feval("-1 state-valid !");