|
|
1.1 root 1: /*
2: *
3: * <xcoff_load.c>
4: *
5: * XCOFF file loader
6: *
7: * Copyright (C) 2009 Laurent Vivier ([email protected])
8: *
9: * from original XCOFF loader by Steven Noonan <[email protected]>
10: *
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
14: *
15: */
16:
17: #include "config.h"
18: #include "libopenbios/bindings.h"
19: #include "libopenbios/xcoff_load.h"
20:
21: #include "arch/common/xcoff.h"
22:
23: #ifdef CONFIG_PPC
24: extern void flush_icache_range( char *start, char *stop );
25: #endif
26:
27: //#define DEBUG_XCOFF
28:
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
36:
37: int
38: is_xcoff(COFF_filehdr_t *fhdr)
39: {
40: return (fhdr->f_magic == U802WRMAGIC
41: || fhdr->f_magic == U802ROMAGIC
42: || fhdr->f_magic == U802TOCMAGIC
43: || fhdr->f_magic == U802TOMAGIC);
44: }
45:
46: int
47: xcoff_load(struct sys_info *info, const char *filename)
48: {
49: // Currently not implemented
50: return LOADER_NOT_SUPPORT;
51: }
52:
53: void
54: xcoff_init_program(void)
55: {
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;
63:
64: feval("0 state-valid !");
65:
66: feval("load-base");
67: base = (char*)cell2pointer(POP());
68:
69: fhdr = (COFF_filehdr_t*)base;
70:
71: /* Is it an XCOFF file ? */
72: if (!is_xcoff(fhdr)) {
73: DPRINTF("Not a XCOFF file %02x\n", fhdr->f_magic);
74: return;
75: }
76:
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;
82: }
83:
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;
88: }
89:
90: ahdr = (COFF_aouthdr_t*)(base + sizeof(COFF_filehdr_t));
91:
92: /* check a.out magic number */
93: if (ahdr->magic != AOUT_MAGIC) {
94: DPRINTF("Invalid AOUT optional header\n");
95: return;
96: }
97:
98: offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t);
99:
100: DPRINTF("XCOFF file with %d sections\n", fhdr->f_nscns);
101:
102: for (i = 0; i < fhdr->f_nscns; i++) {
103:
104: DPRINTF("Read header at offset %0x\n", offset);
105:
106: shdr = (COFF_scnhdr_t*)(base + offset);
107:
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);
111:
112: if (strcmp(shdr->s_name, ".text") == 0) {
113:
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) {
122:
123: memcpy((char*)(uintptr_t)shdr->s_vaddr, base + shdr->s_scnptr,
124: shdr->s_size);
125: total_size += shdr->s_size;
126:
127: } else if (strcmp(shdr->s_name, ".bss") == 0) {
128:
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);
133: }
134: offset += sizeof(COFF_scnhdr_t);
135: }
136:
137: DPRINTF("XCOFF entry point: %x\n", *(uint32_t*)ahdr->entry);
138:
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 !");
145:
146: feval("-1 state-valid !");
147: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.