4 * Open Hack'Ware BIOS Classic MacOS executable file loader
6 * Copyright (c) 2004-2005 Jocelyn Mayer
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License V2
10 * as published by the Free Software Foundation
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 /* PEF (old MacOS executable format) */
28 typedef struct PEF_container_t PEF_container_t;
29 struct PEF_container_t {
35 uint32_t oldDefVersion;
36 uint32_t oldImpVersion;
37 uint32_t currentVersion;
39 uint16_t nb_inst_sections;
41 } __attribute__ (( packed ));
43 typedef struct PEF_section_t PEF_section_t;
44 struct PEF_section_t {
48 uint32_t unpacked_size;
50 uint32_t container_offset;
55 } __attribute__ (( packed ));
57 typedef struct PEF_loader_t PEF_loader_t;
65 uint32_t nb_import_libs;
66 uint32_t nb_import_symbols;
67 uint32_t nb_reloc_sections;
68 uint32_t reloc_instr_offset;
69 uint32_t loader_strings_offset;
70 uint32_t export_hash_offset;
71 uint32_t export_hashtable_power;
72 uint32_t nb_export_symbols;
73 } __attribute__ (( packed ));
77 PEF_SECTION_UNPDATA = 1,
78 PEF_SECTION_INIDATA = 2,
79 PEF_SECTION_CONSTANT = 3,
80 PEF_SECTION_LOADER = 4,
81 PEF_SECTION_DEBUG = 5,
84 PEF_SECTION_TRACE = 8,
88 PEF_SHARE_PROCESS = 1,
90 PEF_SHARE_PROTECTED = 5,
93 int exec_load_pef (inode_t *file, void **dest, void **entry, void **end,
96 PEF_container_t container;
97 PEF_section_t section;
99 void *first, *last, *addr, **sections;
100 uint32_t pos, padsize, size, lpos, main_offset;
102 int nb_sections, nb_inst_sections, main_section, i, n;
104 file_seek(file, loffset);
105 if (fs_read(file, &container, sizeof(PEF_container_t)) < 0) {
106 ERROR("Cannot load container header\n");
109 pos = sizeof(PEF_container_t);
110 /* Check tags and architecture */
111 if (memcmp(&container.tag1, "Joy!", 4) != 0) {
112 DPRINTF("No joy, no PEF\n");
115 if (memcmp(&container.tag2, "peff", 4) != 0) {
116 DPRINTF("No PEFF file\n");
119 if (memcmp(&container.arch, "pwpc", 4) != 0) {
120 DPRINTF("PEFF file not for PPC\n");
123 if (get_be32(&container.version) != 1) {
124 DPRINTF("Unknown PEFF container version\n");
127 nb_sections = get_be32(&container.nb_sections);
128 sections = malloc(nb_sections * sizeof(void *));
129 if (sections == NULL) {
130 ERROR("Cannot allocate sections\n");
133 nb_inst_sections = get_be32(&container.nb_inst_sections);
134 first = (void *)0xFFFFFFFF;
138 for (i = 0, n = 0; i < nb_sections; i++) {
139 file_seek(file, loffset + pos);
140 if (fs_read(file, §ion, sizeof(PEF_section_t)) < 0) {
141 ERROR("Cannot read section %d\n", i);
144 pos += sizeof(PEF_section_t);
145 addr = (void *)get_be32(§ion.address);
149 size = get_be32(§ion.total_size);
150 lpos = get_be32(§ion.container_offset);
151 file_seek(file, loffset + lpos);
152 switch (section.section_kind) {
153 case PEF_SECTION_CODE:
154 case PEF_SECTION_UNPDATA:
155 /* Load as raw data */
156 padsize = get_be32(§ion.unpacked_size) - size;
157 file_seek(file, loffset + lpos);
158 if (fs_read(file, addr, size) < 0) {
159 ERROR("Cannot load section %d\n", i);
162 addr = (char *)addr + size;
163 memset(addr, 0, padsize);
164 addr = (char *)addr + padsize;
166 case PEF_SECTION_INIDATA:
167 case PEF_SECTION_CONSTANT:
168 case PEF_SECTION_EXEC:
169 /* Load as compressed data */
173 uint8_t bsize, csize, count, j;
175 if (fs_read(file, &opcode, 1) < 0) {
176 ERROR("Cannot get opcode\n");
179 bsize = opcode & 0x1F;
180 switch (opcode >> 5) {
182 /* Initialize size bytes to zero */
183 memset(addr, 0, bsize);
184 addr = (char *)addr + bsize;
189 if (fs_read(file, addr, bsize) < 0) {
190 ERROR("Cannot copy bloc\n");
193 addr = (char *)addr + bsize;
198 if (fs_read(file, &count, 1) < 0) {
199 ERROR("Cannot read bloc size\n");
206 if (fs_read(file, addr, bsize) < 0) {
207 ERROR("Cannot read repeat bloc\n");
211 addr = (char *)addr + bsize;
212 for (j = 1; j < count; j++) {
213 memcpy(addr, ref, bsize);
215 addr = (char *)addr + bsize;
219 /* Interleave repeat bloc with bloc copy */
220 if (fs_read(file, &csize, 1) < 0 ||
221 fs_read(file, &count, 1) < 0) {
222 ERROR("Cannot read repeat params\n");
226 if (fs_read(file, addr, bsize) < 0) {
227 ERROR("Cannot read common data\n");
230 addr = (char *)addr + bsize;
232 for (j = 0; j < count; j++) {
233 if (fs_read(file, addr, csize) < 0) {
234 ERROR("Cannot read custom data\n");
237 addr = (char *)addr + csize;
238 memcpy(addr, ref, bsize);
239 addr = (char *)addr + bsize;
240 total += csize + bsize;
244 /* Interleave repeat bloc with zero */
245 if (fs_read(file, &csize, 1) < 0 ||
246 fs_read(file, &count, 1) < 0) {
247 ERROR("Cannot read repeat params\n");
251 for (j = 0; j < count; j++) {
252 memset(addr, 0, bsize);
253 addr = (char *)addr + bsize;
254 if (fs_read(file, addr, csize) < 0) {
255 ERROR("Cannot read repeat data\n");
258 addr = (char *)addr + csize;
259 total += csize + bsize;
261 memset(addr, 0, bsize);
262 addr = (char *)addr + bsize;
266 ERROR("Unknown opcode\n");
276 case PEF_SECTION_LOADER:
277 /* find entry point */
278 if (fs_read(file, &loader, sizeof(PEF_loader_t)) < 0) {
279 ERROR("Cannot read loader header\n");
282 main_section = get_be32(&loader.main_section);
283 main_offset = get_be32(&loader.main_offset);
284 if (main_section >= nb_sections) {
285 ERROR("Invalid main section\n");
289 case PEF_SECTION_DEBUG:
290 case PEF_SECTION_EXCP:
291 case PEF_SECTION_TRACE:
299 if (main_section == -1) {
302 *entry = (char *)sections[main_section] + main_offset;