diff options
author | Yang Zhang <yang.z.zhang@intel.com> | 2015-08-28 09:58:54 +0800 |
---|---|---|
committer | Yang Zhang <yang.z.zhang@intel.com> | 2015-09-01 12:44:00 +0800 |
commit | e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch) | |
tree | 66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/openhackware/src/libexec | |
parent | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff) |
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5
Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/openhackware/src/libexec')
-rw-r--r-- | qemu/roms/openhackware/src/libexec/chrp.c | 404 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libexec/core.c | 151 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libexec/elf.c | 239 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libexec/exec.h | 40 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libexec/macho.c | 517 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libexec/pef.c | 307 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libexec/prep.c | 45 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libexec/xcoff.c | 216 |
8 files changed, 1919 insertions, 0 deletions
diff --git a/qemu/roms/openhackware/src/libexec/chrp.c b/qemu/roms/openhackware/src/libexec/chrp.c new file mode 100644 index 000000000..9a2be2ea8 --- /dev/null +++ b/qemu/roms/openhackware/src/libexec/chrp.c @@ -0,0 +1,404 @@ +/* + * <chrp.c> + * + * Open Hack'Ware BIOS CHRP boot file loader + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include "bios.h" +#include "exec.h" +#include "libfs/libfs.h" + +/* Simple XML parser */ +typedef struct XML_tag_t XML_tag_t; +struct XML_tag_t { + unsigned char *name; + XML_tag_t *up; + int dlen; + void *data; +}; + +enum { + CHRP_TAG_UNKNOWN = 0, + CHRP_TAG_CHRP_BOOT, + CHRP_TAG_COMPATIBLE, + CHRP_TAG_DESCRIPTION, + CHRP_TAG_BOOT_SCRIPT, + CHRP_TAG_OS_BADGE_ICONS, + CHRP_TAG_ICON, + CHRP_TAG_BITMAP, + CHRP_TAG_LICENSE, +}; + +enum { + CHRP_SCRIPT_IGNORE = 0, + CHRP_SCRIPT_LOAD_BOOT, + CHRP_SCRIPT_EMBEDDED, +}; + +enum { + XML_STATE_OUT = 0, + XML_STATE_TAG, + XML_STATE_DATA, +}; + +static int XML_get_type (const unsigned char *name) +{ + int ret; + + if (strcmp(name, "CHRP-BOOT") == 0) + ret = CHRP_TAG_CHRP_BOOT; + else if (strcmp(name, "COMPATIBLE") == 0) + ret = CHRP_TAG_COMPATIBLE; + else if (strcmp(name, "DESCRIPTION") == 0) + ret = CHRP_TAG_DESCRIPTION; + else if (strcmp(name, "BOOT-SCRIPT") == 0) + ret = CHRP_TAG_BOOT_SCRIPT; + else if (strcmp(name, "OS-BADGE-ICONS") == 0) + ret = CHRP_TAG_OS_BADGE_ICONS; + else if (strcmp(name, "ICON") == 0) + ret = CHRP_TAG_ICON; + else if (strcmp(name, "BITMAP") == 0) + ret = CHRP_TAG_BITMAP; + else if (strcmp(name, "LICENSE") == 0) + ret = CHRP_TAG_LICENSE; + else + ret = CHRP_TAG_UNKNOWN; + + return ret; +} + +static unsigned char *strfind (const unsigned char *buf, const unsigned char *str) +{ + const unsigned char *pos; + int len = strlen(str); + + // DPRINTF("Look for '%s' in \n'%s'\n", str, buf); + for (pos = buf; *pos != '\0'; pos++) { + if (memcmp(pos, str, len) == 0) + return (unsigned char *)pos; + } + + return NULL; +} + +int exec_load_chrp (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset) +{ +#define TMPNAME_LEN 512 + unsigned char tmpname[TMPNAME_LEN], *tmpp, *buf, *pos, *endc, c; + XML_tag_t *tag, *tmp, *first; + part_t *part; + inode_t *inode; + int state; + int script_type = CHRP_SCRIPT_IGNORE; + uint32_t crc, offset = 0; + int ret, rel = 0; + + buf = malloc(16384); + /* Check the file head */ + file_seek(file, loffset); + fs_read(file, buf, 11); + if (memcmp(buf, "<CHRP-BOOT>", 11) != 0) { + ERROR("Not an Apple CHRP boot file !\n"); + return -2; + } + /* Re-seek at start of the file and start parsing it */ + file_seek(file, loffset); + pos = buf; + tag = NULL; + first = NULL; + ret = -1; + fs_read(file, &c, 1); + offset++; + for (state = XML_STATE_TAG; state != XML_STATE_OUT;) { + /* Get next char */ + fs_read(file, &c, 1); + offset++; + if ((state == XML_STATE_TAG && c != '>') || + (state == XML_STATE_DATA && c != '<')) { + *pos++ = c; + continue; + } + *pos++ = '\0'; + switch (state) { + case XML_STATE_TAG: + if (*buf == '/') { + if (tag == NULL || strcmp(buf + 1, tag->name) != 0) { + ERROR("XML error: open name: '%s' close name: '%s'\n", + buf + 1, tag->name); + goto out; + } + DPRINTF("Close tag: '%s'\n", tag->name); + switch (XML_get_type(tag->name)) { + case CHRP_TAG_CHRP_BOOT: + /* Nothing to do */ + break; + case CHRP_TAG_COMPATIBLE: + /* Won't check... */ + pos = tag->data; + if (*(char *)tag->data == 0x0d) { + pos++; + } + DPRINTF("Compatible: '%s'\n", pos); + break; + case CHRP_TAG_DESCRIPTION: + pos = tag->data; + if (*(char *)tag->data == 0x0d) { + pos++; + } + DPRINTF("Description: '%s'\n", pos); + break; + case CHRP_TAG_BOOT_SCRIPT: + /* Here is the interresting part... */ + crc = crc32(0, tag->data, tag->dlen); +#if 0 + DPRINTF("Forth script: %08x\n%s\n", + crc, (char *)tag->data); +#endif + switch (crc) { + case 0x5464F92C: + /* Mandrake 9.1 CD1 boot script */ + case 0x4BC74ECF: + /* Mandrake 10.1 & 10.2 CD1 boot script */ + case 0x5B265246: + /* Gentoo 1.2-r1 */ + /* Gentoo 2004.1 minimal install CD */ + /* Gentoo 1.4 live CDROM */ + /* Knopix PPC beta-pre12 */ + case 0x75420D8A: + /* Debian woody */ + /* Debian 3.0r1 */ + script_type = CHRP_SCRIPT_LOAD_BOOT; + goto do_script; + case 0x633e4c9c: + /* Debian Sarge */ + case 0xbe3abf60: + /* Debian Sarge, installed on a hard disk drive */ + script_type = CHRP_SCRIPT_LOAD_BOOT; + goto do_script; + case 0x07b86bfe: + /* Linux Fedora Core 3 */ + script_type = CHRP_SCRIPT_LOAD_BOOT; + goto do_script; + case 0x9ccdf371: + script_type = CHRP_SCRIPT_LOAD_BOOT; + goto do_script; + case 0xEF423926: + /* OpenBSD 3.4 */ + case 0x68e4f265: + /* OpenBSD 3.5 */ + case 0x3b7ea9e1: + /* OpenBSD 3.6 */ + script_type = CHRP_SCRIPT_LOAD_BOOT; + goto do_script; + case 0xB7981DBC: + /* iBook 2 hw test CDROM */ +#if 1 + script_type = CHRP_SCRIPT_LOAD_BOOT; + goto do_script; +#endif + + case 0xEA06C1A7: + /* MacOS 9.2 boot script: + * the XCOFF loader is embedded in the file... + */ + case 0x53A95958: + /* iBook 2 restore CD (MacOS X 10.2) */ + script_type = CHRP_SCRIPT_EMBEDDED; + pos = strfind(tag->data, "elf-offset"); + if (pos != NULL) { + /* Go backward until we get the value */ + for (--pos; *pos < '0' || *pos > '9'; pos--) + continue; + for (; *pos >= '0' && *pos <= '9'; pos--) + continue; + offset = strtol(pos, NULL, 16); + goto do_script; + } + ERROR("Didn't find boot file offset\n"); + goto out; + case 0x8d5acb86: + /* Darwin-7.01 + * The executable file is embedded after the script + */ + script_type = CHRP_SCRIPT_EMBEDDED; + DPRINTF("Boot file embedded at the end of boot script\n"); + break; + default: + ERROR("XML error: unknown Forth script: %08x\n%s\n", + crc, (char *)tag->data); + goto out; + } + break; + + do_script: + switch (script_type) { + case CHRP_SCRIPT_LOAD_BOOT: + pos = strfind(tag->data, "boot"); + if (pos != NULL) { + /* Eat everything until file name */ + for (pos += 4; *pos != ','; pos++) + continue; + /* Eat ',' */ + for (++pos; isspace(*pos) || *pos == '"'; pos++) + continue; + /* Find file name end */ + redo: + for (endc = pos; + *endc != ' ' && *endc != '"' && + *endc != '\n' && *endc != '\r'; + endc++) { + if (*endc == '\\') + *endc = '/'; + } + if (memcmp(pos, "ofwboot", 7) == 0) { + for (pos = endc + 1; *pos == ' '; pos++) + continue; + goto redo; + } + *endc = '\0'; + } + DPRINTF("Real boot file is: '%s'\n", pos); + part = fs_inode_get_part(file); + /* check if it's a path or just a file */ + tmpp = pos; + if ((pos[0] == '/' && pos[1] == '/') || + pos[0] != '/') { + unsigned char *bootdir; + bootdir = fs_get_boot_dirname(part_fs(part)); + if (bootdir == NULL) { + ERROR("Cannot get boot directory name\n"); + bug(); + } + snprintf(tmpname, TMPNAME_LEN, + "%s/%s", bootdir, pos); + tmpname[TMPNAME_LEN - 1] = '\0'; + rel++; + pos = tmpname; + DPRINTF("'%s' => '%s'\n", bootdir, pos); + } + retry: + inode = fs_open(part_fs(part), pos); + if (inode == NULL) { + ERROR("Real boot inode '%s' not found\n", pos); + /* Try in root directory */ + if (rel == 1) { + for (; *tmpp == '/'; tmpp++) + continue; + snprintf(tmpname, TMPNAME_LEN, "/%s", tmpp); + tmpname[TMPNAME_LEN - 1] = '\0'; + rel++; + goto retry; + } + + bug(); + } + ret = _bootfile_load(inode, dest, entry, end, 0, -1); + fs_close(inode); + goto out; + case CHRP_SCRIPT_EMBEDDED: + DPRINTF("Exec offset: %d %08x\n", offset, offset); + ret = 0; + goto out; + case CHRP_SCRIPT_IGNORE: + break; + } + break; + case CHRP_TAG_OS_BADGE_ICONS: + case CHRP_TAG_ICON: + /* Ignore it */ + break; + case CHRP_TAG_BITMAP: + /* Ignore it */ + break; + case CHRP_TAG_LICENSE: + /* Ignore it */ + pos = tag->data; + if (*(char *)tag->data == 0x0d) { + pos++; + } + DPRINTF("License: '%s'\n", pos); + break; + default: + ERROR("XML error: unknown tag: '%s'\n", tag->name); + goto out; + } + tmp = tag->up; + if (tmp == NULL) + state = XML_STATE_OUT; + else + state = XML_STATE_DATA; + free(tag->name); + free(tag->data); + free(tag); + tag = tmp; + } else { + tmp = malloc(sizeof(XML_tag_t)); + if (tmp == NULL) { + ERROR("Cannot allocate new tag\n"); + goto out; + } + tmp->up = tag; + /* Ignore tag attributes */ + pos = strchr(buf, ' '); + if (pos != NULL) + *pos = '\0'; + tmp->name = strdup(buf); + tag = tmp; + if (first == NULL) + first = tag; + DPRINTF("Open tag '%s'\n", tag->name); + state = XML_STATE_DATA; + } + break; + case XML_STATE_DATA: + if (tag->data == NULL) { + tag->dlen = pos - buf; + tag->data = malloc(tag->dlen); + memcpy(tag->data, buf, tag->dlen); + } + state = XML_STATE_TAG; + break; + } + pos = buf; + } + ret = 0; + fs_read(file, &c, 1); + fs_read(file, &c, 1); + offset += 2; + out: +#if 1 + for (; tag != NULL; tag = tmp) { + tmp = tag->up; + free(tag->name); + free(tag->data); + free(tag); + } +#endif + if (ret == 0 && script_type == CHRP_SCRIPT_EMBEDDED) { + DPRINTF("Load embedded file from offset %d (%d => %d)\n", + offset, loffset, loffset + offset); + ret = _bootfile_load(file, dest, entry, end, loffset + offset, -1); + } + DPRINTF("Done\n"); + + return ret; +} diff --git a/qemu/roms/openhackware/src/libexec/core.c b/qemu/roms/openhackware/src/libexec/core.c new file mode 100644 index 000000000..222a29a8c --- /dev/null +++ b/qemu/roms/openhackware/src/libexec/core.c @@ -0,0 +1,151 @@ +/* + * <file.c> + * + * Open Hack'Ware BIOS executable file loader + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include "bios.h" +#include "exec.h" + +/*****************************************************************************/ +uint32_t file_seek (inode_t *file, uint32_t pos) +{ + uint32_t blocsize, bloc, offset; + + if (file == NULL) + return -1; + blocsize = part_blocsize(fs_inode_get_part(file)); + bloc = pos / blocsize; + offset = pos % blocsize; + + return fs_seek(file, bloc, offset); +} + +/*****************************************************************************/ +/* Executable file loaders */ + +enum { + FILE_TYPE_ELF = 0, + FILE_TYPE_XCOFF, + FILE_TYPE_MACHO, + FILE_TYPE_PEF, + FILE_TYPE_CHRP, + FILE_TYPE_PREP, + FILE_TYPE_FLAT, +}; + +uint32_t fs_inode_get_size (inode_t *inode); +unsigned int part_get_entry (part_t *part); +/*****************************************************************************/ +/* Generic boot file loader */ +int _bootfile_load (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset, int type) +{ + int (*do_load)(inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset); + uint32_t size; + int ret; + int i; + + if (type == -1) + i = 0; + else + i = type; + for (;; i++) { + switch (i) { + case FILE_TYPE_ELF: + do_load = &exec_load_elf; + break; + case FILE_TYPE_XCOFF: + do_load = &exec_load_xcoff; + break; + case FILE_TYPE_MACHO: + do_load = &exec_load_macho; + break; + case FILE_TYPE_PEF: + do_load = &exec_load_pef; + break; + case FILE_TYPE_CHRP: + do_load = &exec_load_chrp; + break; + case FILE_TYPE_PREP: + do_load = &exec_load_prep; + break; + default: + if (*dest == NULL) + *dest = (void *)DEFAULT_LOAD_DEST; + if (*entry == NULL) { + if (part_get_entry(fs_inode_get_part(file)) != 0 || 1) { + *entry = (char *)*dest + + part_get_entry(fs_inode_get_part(file)); + dprintf("dest %p entry %08x => %p\n", + *dest, part_get_entry(fs_inode_get_part(file)), + *entry); + } else { + *entry = *dest + 0xC; + } + } + size = fs_inode_get_size(file); + *end = (char *)*dest + size - loffset; + printf("Load raw file into memory at %p %d (%08x) %d (%08x)\n", + *dest, size, size, loffset, loffset); + file_seek(file, loffset); + set_loadinfo(*dest, size); + if ((uint32_t)fs_read(file, *dest, size) != size) { + ERROR("Error loading file...\n"); + ret = -1; + } else { + ret = 0; + } + goto out; + } + DPRINTF("Check file type %d at offset %d %p\n", i, loffset, do_load); + ret = (*do_load)(file, dest, entry, end, loffset); + if (ret >= -1 || type == i) { + if (type == i) + ret = -2; + break; + } + } + out: + + return ret; +} + +int bootfile_load (void **dest, void **entry, void **end, + part_t *part, int type, const unsigned char *fname, + uint32_t loffset) +{ + inode_t *file; + int ret; + + DPRINTF("Load file '%s' %p %p type: %d offset: %0x => %d %p\n", + fname, part, part_fs(part), type, loffset, part_blocsize(part), *dest); + if (fname == NULL) + file = fs_get_bootfile(part_fs(part)); + else + file = fs_open(part_fs(part), fname); + if (file == NULL) + return -1; + ret = _bootfile_load(file, dest, entry, end, loffset, type); + fs_close(file); + + return ret; +} diff --git a/qemu/roms/openhackware/src/libexec/elf.c b/qemu/roms/openhackware/src/libexec/elf.c new file mode 100644 index 000000000..ae9f8e00e --- /dev/null +++ b/qemu/roms/openhackware/src/libexec/elf.c @@ -0,0 +1,239 @@ +/* + * <elf.c> + * + * Open Hack'Ware BIOS ELF executable file loader + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include "bios.h" +#include "exec.h" + +uint32_t fs_inode_get_size (inode_t *inode); + +/* ELF executable loader */ +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Word; +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Addr; + +#define EI_NIDENT 16 + +typedef struct elf32_hdr_t { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr_t; + +typedef struct elf32_phdr_t { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr_t; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* These constants define the various ELF target machines */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Perhaps disused */ +#define EM_860 7 +#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ +#define EM_PARISC 15 /* HPPA */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC64 */ +#define EM_SH 42 /* SuperH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_IA_64 50 /* HP/Intel IA-64 */ +#define EM_X86_64 62 /* AMD x86-64 */ +#define EM_S390 22 /* IBM S/390 */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_V850 87 /* NEC v850 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +/* + * This is an interim value that we will use until the committee comes + * up with a final number. + */ +#define EM_ALPHA 0x9026 +/* Bogus old v850 magic number, used by old tools. */ +#define EM_CYGNUS_V850 0x9080 +/* + * This is the old interim value for S/390 architecture + */ +#define EM_S390_OLD 0xA390 + +int exec_load_elf (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset) +{ + Elf32_Ehdr_t ehdr; + Elf32_Phdr_t phdr; + void *address, *first, *last; + uint32_t offset, fsize, msize; + int i; + + file_seek(file, loffset); + if (fs_read(file, &ehdr, sizeof(Elf32_Ehdr_t)) < 0) { + ERROR("Cannot load first bloc of file...\n"); + return -1; + } + DPRINTF("Check ELF file\n"); + /* Check ident */ + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 || + ehdr.e_ident[EI_MAG1] != ELFMAG1 || + ehdr.e_ident[EI_MAG2] != ELFMAG2 || + ehdr.e_ident[EI_MAG3] != ELFMAG3) { + DPRINTF("Not an ELF file %0x\n", *(uint32_t *)ehdr.e_ident); + return -2; + } + if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) { + ERROR("Not a 32 bits ELF file\n"); + return -2; + } + if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB) { + ERROR("Not a big-endian ELF file\n"); + return -2; + } + if (ehdr.e_ident[EI_VERSION] != EV_CURRENT /*|| + ehdr->e_version != EV_CURRENT*/) { + ERROR("Invalid ELF executable version %d %08x\n", + ehdr.e_ident[EI_VERSION], ehdr.e_version); + return -2; + } + if (ehdr.e_type != ET_EXEC) { + ERROR("Not an executable ELF file\n"); + return -2; + } + if (ehdr.e_machine != EM_PPC) { + ERROR("Not a PPC ELF executable\n"); + return -2; + } + /* All right, seems to be a regular ELF program for PPC */ + *entry = (void *)ehdr.e_entry; + DPRINTF("ELF file found entry = %p\n", *entry); + last = NULL; + first = last - 4; + fsize = msize = 0; + offset = ehdr.e_phoff; + for (i = 0; i < ehdr.e_phnum; i++) { +#if 0 + if (offset > fs_inode_get_size(file)) { + ERROR("ELF program header %d offset > file size %d %d\n", i, + offset, fs_inode_get_size(file)); + return -1; + } +#endif + DPRINTF("Load program header %d from %08x\n", i, offset); + file_seek(file, offset + loffset); + if (fs_read(file, &phdr, sizeof(Elf32_Phdr_t)) < 0) { + ERROR("Cannot load ELF program header %d...\n", i); + return -1; + } + DPRINTF("Load program header %d %08x %08x %08x %08x\n", i, + phdr.p_offset, phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz); +#if 0 + if (phdr.p_offset > fs_inode_get_size(file)) { + ERROR("ELF program %d offset > file size %d %d\n", + i, phdr.p_offset, fs_inode_get_size(file)); + return -1; + } +#endif + /* As we won't remap memory, load it at it's virtual address (!) */ + address = (void *)phdr.p_vaddr; + if (address < first) + first = address; + fsize = phdr.p_filesz; + msize = phdr.p_memsz; + if (address + msize > last) + last = address + msize; + file_seek(file, phdr.p_offset + loffset); + set_loadinfo((void *)first, last - first); + if (fs_read(file, address, fsize) < 0) { + ERROR("Cannot load ELF program %d...\n", i); + return -1; + } + if (msize > fsize) { + memset(address + fsize, 0, msize - fsize); + } + offset += ehdr.e_phentsize; + } + *dest = (void *)first; + *end = (void *)last; + DPRINTF("ELF file loaded at %p => %p fsize %08x msize %08x " + "(%08x %08x)\n", *dest, *entry, fsize, msize, + *(uint32_t *)entry, *((uint32_t *)entry + 1)); + + return 0; +} diff --git a/qemu/roms/openhackware/src/libexec/exec.h b/qemu/roms/openhackware/src/libexec/exec.h new file mode 100644 index 000000000..46f138fdf --- /dev/null +++ b/qemu/roms/openhackware/src/libexec/exec.h @@ -0,0 +1,40 @@ +/* + * <exec.h> + * + * Open Hack'Ware BIOS: executable files loader definitions + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(__OHW_EXEC_H__) +#define __OHW_EXEC_H__ + +int _bootfile_load (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset, int type); +int exec_load_elf (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset); +int exec_load_xcoff (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset); +int exec_load_macho (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset); +int exec_load_pef (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset); +int exec_load_prep (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset); +int exec_load_chrp (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset); + +#endif /* !defined(__OHW_EXEC_H__) */ diff --git a/qemu/roms/openhackware/src/libexec/macho.c b/qemu/roms/openhackware/src/libexec/macho.c new file mode 100644 index 000000000..f07c92144 --- /dev/null +++ b/qemu/roms/openhackware/src/libexec/macho.c @@ -0,0 +1,517 @@ +/* + * <macho.c> + * + * Open Hack'Ware BIOS MACH-O executable file loader + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include "bios.h" +#include "exec.h" + +/* MACH-O executable loader */ +/* FAT definitions */ +/* CPU type definitions */ +typedef enum cpu_type_t { + CPU_TYPE_ANY = -1, + CPU_TYPE_VAX = 1, + CPU_TYPE_MC680x0 = 6, + CPU_TYPE_I386 = 7, + CPU_TYPE_MIPS = 8, + CPU_TYPE_MC98000 = 10, + CPU_TYPE_HPPA = 11, + CPU_TYPE_ARM = 12, + CPU_TYPE_MC88000 = 13, + CPU_TYPE_SPARC = 14, + CPU_TYPE_I860 = 15, + CPU_TYPE_ALPHA = 16, + CPU_TYPE_POWERPC = 18, +} cpu_type_t; + +/* Any CPU */ +typedef enum cpu_subtype_any_t { + CPU_SUBTYPE_MULTIPLE = -1, + CPU_SUBTYPE_LITTLE_ENDIAN = 0, + CPU_SUBTYPE_BIG_ENDIAN = 1, +} cpu_subtype_any_t; + +/* PowerPC */ +typedef enum cpu_subtype_ppc_t { + CPU_SUBTYPE_PPC_ALL = 0, + CPU_SUBTYPE_PPC_601 = 1, + CPU_SUBTYPE_PPC_602 = 2, + CPU_SUBTYPE_PPC_603 = 3, + CPU_SUBTYPE_PPC_603e = 4, + CPU_SUBTYPE_PPC_603ev = 5, + CPU_SUBTYPE_PPC_604 = 6, + CPU_SUBTYPE_PPC_604e = 7, + CPU_SUBTYPE_PPC_620 = 8, + CPU_SUBTYPE_PPC_750 = 9, + CPU_SUBTYPE_PPC_7400 = 10, + CPU_SUBTYPE_PPC_7450 = 11, +} cpu_subtype_ppc_t; + +/* Fat header definition */ +#define FAT_MAGIC 0xCAFEBABE + +typedef struct fat_head_t { + uint32_t magic; + uint32_t nfat_arch; +} fat_head_t; + +typedef struct fat_arch_t { + cpu_type_t cpu_type; + cpu_subtype_ppc_t cpu_subtype; + uint32_t offset; + uint32_t size; + uint32_t align; +} fat_arch_t; + +/* Mach-O binary definitions */ +#define MACH_O_MAGIC 0xFEEDFACE + +typedef enum filetype_t { + MH_OBJECT = 0x1, + MH_EXECUTE = 0x2, + MH_FVMLIB = 0x3, + MH_CORE = 0x4, + MH_PRELOAD = 0x5, + MH_DYLIB = 0x6, + MH_DYLINKER = 0x7, + MH_BUNDLE = 0x8, +} filetype_t; + +enum { + MH_NOUNDEFS = 0x01, + MH_INCRLINK = 0x02, + MH_DYLDLINK = 0x04, + MH_BINDATLOAD = 0x08, + MH_PREBOUND = 0x10, +}; + +typedef struct mach_head_t { + uint32_t magic; + cpu_type_t cpu_type; + cpu_subtype_ppc_t subtype; + filetype_t file_type; + uint32_t nb_cmds; + uint32_t cmds_size; + uint32_t flags; +} mach_head_t; + +typedef enum load_cmd_t { + LC_SEGMENT = 0x01, + LC_SYMTAB = 0x02, + LC_SYMSEG = 0x03, + LC_THREAD = 0x04, + LC_UNIXTHREAD = 0x05, + LC_LOADFVMLIB = 0x06, + LC_IDFVMLIB = 0x07, + LC_IDENT = 0x08, + LC_FVMFILE = 0x09, + LC_PREPAGE = 0x0A, + LC_DYSYMTAB = 0x0B, + LC_LOAD_DYLIB = 0x0C, + LC_ID_DYLIB = 0x0D, + LC_LOAD_DYLINKER = 0x0E, + LC_ID_DYLINKER = 0x0F, + LC_PREBOUND_DYLIB = 0x10, + LC_0x17 = 0x17, +} load_cmd_t; + +typedef struct mach_load_cmd_t { + load_cmd_t cmd; + uint32_t cmd_size; +} mach_load_cmd_t; + +typedef struct mach_string_t { + uint32_t offset; +} mach_string_t; + +enum { + SG_HIGHVM = 0x1, + SG_FVMLIB = 0x2, + SG_NORELOC = 0x4, +}; + +typedef struct mach_segment_t { + unsigned char segname[16]; + uint32_t vmaddr; + uint32_t vmsize; + uint32_t file_offset; + uint32_t file_size; + uint32_t max_prot; + uint32_t init_prot; + uint32_t nsects; + uint32_t flags; +} mach_segment_t; + +enum { + SECTION_TYPE = 0xFF, + S_REGULAR = 0x0, + S_ZEROFILL = 0x1, + S_CSTRING_LITERALS = 0x2, + S_4BYTE_LITERALS = 0x3, + S_8BYTE_LITERALS = 0x4, + S_LITERAL_POINTERS = 0x5, + S_NON_LAZY_SYMBOL_POINTERS = 0x6, + S_LAZY_SYMBOL_POINTERS = 0x7, + S_SYMBOL_STUBS = 0x8, + S_MOD_INIT_FUNC_POINTERS = 0x9, +}; + +enum { + S_ATTR_PURE_INSTRUCTIONS = 0x80000000, + S_ATTR_SOME_INSTRUCTIONS = 0x00000400, + S_ATTR_EXT_RELOC = 0x00000200, + S_ATTR_LOC_RELOC = 0x00000100, +}; + +typedef struct mach_section_t { + unsigned char sectname[16]; + unsigned char segname[16]; + uint32_t vmaddr; + uint32_t size; + uint32_t offset; + uint32_t align; + uint32_t reloc_offset; + uint32_t nreloc; + uint32_t flags; + uint32_t res1; + uint32_t res2; +} mach_section_t; + +typedef struct mach_symtab_t { + uint32_t offset; + uint32_t nsyms; + uint32_t str_offset; + uint32_t str_size; +} mach_symtab_t; + +typedef struct mach_symseg_t { + uint32_t offset; + uint32_t size; +} mach_symseg_t; + +typedef struct mach_unixth_t { + uint32_t flavor; + uint32_t count; + /* This is supposed to be a stack. + * Let's assume it's less than 1kB (arbitrary !) + */ + uint32_t data[256]; +} mach_unixth_t; + +typedef struct mach_fvmlib_t { + uint32_t str_offset; + uint32_t minor_version; + uint32_t header_addr; +} mach_fvmlib_t; + +typedef struct mach_fvmfile_t { + uint32_t str_offset; + uint32_t vmaddr; +} mach_fvmfile_t; + +typedef struct mach_dysymtab_t { + uint32_t ilocal_syms; + uint32_t nlocal_syms; + uint32_t iext_syms; + uint32_t next_syms; + uint32_t iundef_syms; + uint32_t nundef_syms; + uint32_t toc_offset; + uint32_t ntoc; + uint32_t modtab_offset; + uint32_t nmodtab; + uint32_t extsym_offset; + uint32_t nextsym; + uint32_t indirect_offset; + uint32_t nindirect; + uint32_t ext_reloc_offset; + uint32_t next_reloc; + uint32_t local_reloc_offset; + uint32_t nlocal_reloc; +} mach_dysymtab_t; + +typedef struct mach_dylib_t { + uint32_t str_offset; + uint32_t timestamp; + uint32_t cur_version; + uint32_t compat_version; +} mach_dylib_t; + +typedef struct mach_prebound_t { + uint32_t str_offset; + uint32_t nb_modules; + unsigned char linked_modules[256]; +} mach_prebound_t; + +int exec_load_macho (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset) +{ + mach_head_t mhdr; + mach_load_cmd_t lcmd; + fat_head_t fhdr; + fat_arch_t fahdr; + void *address, *first, *last; + uint32_t k, j, best, offset; + int entry_set; + + /* Probe FAT */ + file_seek(file, loffset); + if (fs_read(file, &fhdr, sizeof(fat_head_t)) < 0) { + ERROR("Cannot load fat header...\n"); + return -1; + } + fhdr.magic = get_be32(&fhdr.magic); + if (fhdr.magic != FAT_MAGIC) + goto macho_probe; + fhdr.nfat_arch = get_be32(&fhdr.nfat_arch); + DPRINTF("FAT file: %d archs\n", fhdr.nfat_arch); + /* Find the best architecture */ + best = -1; + offset = 0; + for (k = 0; k < fhdr.nfat_arch; k++) { + if (fs_read(file, &fahdr, sizeof(fat_arch_t)) < 0) { + ERROR("Cannot load fat arch header\n"); + return -1; + } + fahdr.cpu_type = get_be32(&fahdr.cpu_type); + if (fahdr.cpu_type != CPU_TYPE_POWERPC) + continue; + fahdr.cpu_subtype = get_be32(&fahdr.cpu_subtype); + fahdr.offset = get_be32(&fahdr.offset); + fahdr.size = get_be32(&fahdr.size); + fahdr.align = get_be32(&fahdr.align); + switch (fahdr.cpu_subtype) { + case CPU_SUBTYPE_PPC_750: + best = k; + offset = fahdr.offset; + goto fat_cpu_ok; + case CPU_SUBTYPE_PPC_ALL: + if (best == (uint32_t)-1) { + offset = fahdr.offset; + best = k; + } + break; + case CPU_SUBTYPE_PPC_603: + case CPU_SUBTYPE_PPC_603e: + case CPU_SUBTYPE_PPC_603ev: + case CPU_SUBTYPE_PPC_604: + case CPU_SUBTYPE_PPC_604e: + best = k; + offset = fahdr.offset; + break; + default: + break; + } + } + if (best == (uint32_t)-1) { + ERROR("No matching PPC FAT arch\n"); + return -1; + } + DPRINTF("Use FAT arch %d at %08x %08x\n", best, offset, loffset); + fat_cpu_ok: + loffset += offset; + + /* Probe macho */ + macho_probe: + file_seek(file, loffset); + if (fs_read(file, &mhdr, sizeof(mach_head_t)) < 0) { + ERROR("Cannot load MACH-O header...\n"); + return -1; + } + mhdr.magic = get_be32(&mhdr.magic); + if (mhdr.magic != MACH_O_MAGIC) { + ERROR("Not a MACH-O file\n"); + return -2; + } + mhdr.cpu_type = get_be32(&mhdr.cpu_type); + mhdr.subtype = get_be32(&mhdr.subtype); + mhdr.file_type = get_be32(&mhdr.file_type); + mhdr.nb_cmds = get_be32(&mhdr.nb_cmds); + mhdr.cmds_size = get_be32(&mhdr.cmds_size); + mhdr.flags = get_be32(&mhdr.flags); + DPRINTF("MACHO-O file cpu %d %d file type %08x %d cmds size %08x flags " + "%08x\n", mhdr.cpu_type, mhdr.subtype, mhdr.file_type, + mhdr.nb_cmds, mhdr.cmds_size, mhdr.flags); + offset = sizeof(mach_head_t); + first = (void *)-1; + last = NULL; + entry_set = 0; + for (k = 0; k < mhdr.nb_cmds; k++) { + file_seek(file, loffset + offset); + if (fs_read(file, &lcmd, sizeof(mach_load_cmd_t)) < 0) { + ERROR("Unable to load MACH-O cmd %d\n", k); + return -1; + } + lcmd.cmd = get_be32(&lcmd.cmd); + lcmd.cmd_size = get_be32(&lcmd.cmd_size); + DPRINTF("Cmd %d : %08x size %08x (%08x %08x)\n", k, lcmd.cmd, + lcmd.cmd_size, offset, offset + loffset); + switch (lcmd.cmd) { + case LC_SEGMENT: + /* To be loaded for execution */ + { + mach_segment_t segment; + mach_section_t section; + uint32_t pos; + + pos = offset + sizeof(mach_load_cmd_t); + if (fs_read(file, &segment, sizeof(mach_segment_t)) < 0) { + ERROR("Cannot load MACH-O segment\n"); + return -1; + } + pos += sizeof(mach_segment_t); + segment.vmaddr = get_be32(&segment.vmaddr); + segment.vmsize = get_be32(&segment.vmsize); + segment.file_offset = get_be32(&segment.file_offset); + segment.file_size = get_be32(&segment.file_size); + segment.max_prot = get_be32(&segment.max_prot); + segment.init_prot = get_be32(&segment.init_prot); + segment.nsects = get_be32(&segment.nsects); + segment.flags = get_be32(&segment.flags); + DPRINTF("MACH-O segment addr %08x size %08x off %08x fsize " + "%08x ns %d fl %08x\n", segment.vmaddr, segment.vmsize, + segment.file_offset, segment.file_size, + segment.nsects, segment.flags); + for (j = 0; j < segment.nsects; j++) { + file_seek(file, loffset + pos); + if (fs_read(file, §ion, sizeof(mach_section_t)) < 0) { + ERROR("Cannot load MACH-O section\n"); + return -1; + } + pos += sizeof(mach_section_t); + section.vmaddr = get_be32(§ion.vmaddr); + section.size = get_be32(§ion.size); + section.offset = get_be32(§ion.offset); + section.align = get_be32(§ion.align); + section.reloc_offset = get_be32(§ion.reloc_offset); + section.nreloc = get_be32(§ion.nreloc); + section.flags = get_be32(§ion.flags); + section.res1 = get_be32(§ion.res1); + section.res2 = get_be32(§ion.res2); + DPRINTF("MACH-O section vmaddr %08x size %08x off %08x " + "flags %08x\n", section.vmaddr, section.size, + section.offset, section.flags); + switch (section.flags & SECTION_TYPE) { + case S_REGULAR: + case S_CSTRING_LITERALS: + case S_4BYTE_LITERALS: + case S_8BYTE_LITERALS: + case S_LITERAL_POINTERS: + case S_NON_LAZY_SYMBOL_POINTERS: + case S_LAZY_SYMBOL_POINTERS: + case S_SYMBOL_STUBS: + case S_MOD_INIT_FUNC_POINTERS: + DPRINTF("Load section of type %d from %08x to %08x" + " %08x\n", section.flags, section.offset, + section.vmaddr, section.size); + file_seek(file, section.offset + loffset); + address = (void *)section.vmaddr; + if (address < first && address != NULL) + first = address; + if (address + section.size > last) + last = address + section.size; + if (fs_read(file, address, section.size) < 0) { + ERROR("Cannot load MACH-O section %d %d...\n", + k, j); + return -1; + } + break; + case S_ZEROFILL: + DPRINTF("Fill zero section to %08x %08x\n", + section.vmaddr, section.size); + address = (void *)section.vmaddr; + if (address < first && address != NULL) + first = address; + if (address + section.size > last) + last = address + section.size; + memset(address, 0, section.size); + break; + default: + ERROR("Unknown MACH-O section type: %d\n", + section.flags); + return -1; + } + } + } + break; + case LC_SYMTAB: + /* Don't care */ + break; + case LC_SYMSEG: + /* Don't care */ + break; + case LC_UNIXTHREAD: + /* To be loaded for execution */ + { + mach_unixth_t unixth; + + if (fs_read(file, &unixth, sizeof(mach_unixth_t)) < 0) { + ERROR("Cannot load MACH-O UNIX thread\n"); + return -1; + } + DPRINTF("Set entry point to %08x\n", unixth.data[0]); + *entry = (void *)unixth.data[0]; + entry_set = 1; + } + break; + case LC_THREAD: + break; + case LC_LOADFVMLIB: + break; + case LC_IDFVMLIB: + break; + case LC_IDENT: + break; + case LC_FVMFILE: + break; + case LC_PREPAGE: + printf("Prepage command\n"); + break; + case LC_DYSYMTAB: + break; + case LC_LOAD_DYLIB: + break; + case LC_ID_DYLIB: + break; + case LC_LOAD_DYLINKER: + /* To be loaded for execution */ + break; + case LC_ID_DYLINKER: + break; + case LC_PREBOUND_DYLIB: + break; + case LC_0x17: + /* ? */ + break; + default: + printf("unknown MACH-O command (%d %d)\n", k, lcmd.cmd); + return -1; + } + offset += lcmd.cmd_size; + } + *dest = first; + *end = last; + // if (entry_set == 0) + *entry = *dest; + + return 0; +} diff --git a/qemu/roms/openhackware/src/libexec/pef.c b/qemu/roms/openhackware/src/libexec/pef.c new file mode 100644 index 000000000..2c580147e --- /dev/null +++ b/qemu/roms/openhackware/src/libexec/pef.c @@ -0,0 +1,307 @@ +/* + * <pef.c> + * + * Open Hack'Ware BIOS Classic MacOS executable file loader + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include "bios.h" +#include "exec.h" + +/* PEF (old MacOS executable format) */ +typedef struct PEF_container_t PEF_container_t; +struct PEF_container_t { + uint32_t tag1; + uint32_t tag2; + uint32_t arch; + uint32_t version; + uint32_t timestamp; + uint32_t oldDefVersion; + uint32_t oldImpVersion; + uint32_t currentVersion; + uint16_t nb_sections; + uint16_t nb_inst_sections; + uint32_t pad; +} __attribute__ (( packed )); + +typedef struct PEF_section_t PEF_section_t; +struct PEF_section_t { + int32_t name_offset; + uint32_t address; + uint32_t total_size; + uint32_t unpacked_size; + uint32_t packed_size; + uint32_t container_offset; + uint8_t section_kind; + uint8_t share_kind; + uint8_t align; + uint8_t pad; +} __attribute__ (( packed )); + +typedef struct PEF_loader_t PEF_loader_t; +struct PEF_loader_t { + int32_t main_section; + uint32_t main_offset; + int32_t init_section; + uint32_t init_offset; + int32_t term_section; + uint32_t term_offset; + uint32_t nb_import_libs; + uint32_t nb_import_symbols; + uint32_t nb_reloc_sections; + uint32_t reloc_instr_offset; + uint32_t loader_strings_offset; + uint32_t export_hash_offset; + uint32_t export_hashtable_power; + uint32_t nb_export_symbols; +} __attribute__ (( packed )); + +enum { + PEF_SECTION_CODE = 0, + PEF_SECTION_UNPDATA = 1, + PEF_SECTION_INIDATA = 2, + PEF_SECTION_CONSTANT = 3, + PEF_SECTION_LOADER = 4, + PEF_SECTION_DEBUG = 5, + PEF_SECTION_EXEC = 6, + PEF_SECTION_EXCP = 7, + PEF_SECTION_TRACE = 8, +}; + +enum { + PEF_SHARE_PROCESS = 1, + PEF_SHARE_GLOBAL = 4, + PEF_SHARE_PROTECTED = 5, +}; + +int exec_load_pef (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset) +{ + PEF_container_t container; + PEF_section_t section; + PEF_loader_t loader; + void *first, *last, *addr, **sections; + uint32_t pos, padsize, size, lpos, main_offset; + uint8_t opcode; + int nb_sections, nb_inst_sections, main_section, i, n; + + file_seek(file, loffset); + if (fs_read(file, &container, sizeof(PEF_container_t)) < 0) { + ERROR("Cannot load container header\n"); + return -1; + } + pos = sizeof(PEF_container_t); + /* Check tags and architecture */ + if (memcmp(&container.tag1, "Joy!", 4) != 0) { + DPRINTF("No joy, no PEF\n"); + return -2; + } + if (memcmp(&container.tag2, "peff", 4) != 0) { + DPRINTF("No PEFF file\n"); + return -2; + } + if (memcmp(&container.arch, "pwpc", 4) != 0) { + DPRINTF("PEFF file not for PPC\n"); + return -2; + } + if (get_be32(&container.version) != 1) { + DPRINTF("Unknown PEFF container version\n"); + return -2; + } + nb_sections = get_be32(&container.nb_sections); + sections = malloc(nb_sections * sizeof(void *)); + if (sections == NULL) { + ERROR("Cannot allocate sections\n"); + return -1; + } + nb_inst_sections = get_be32(&container.nb_inst_sections); + first = (void *)0xFFFFFFFF; + last = NULL; + main_section = -1; + main_offset = 0; + for (i = 0, n = 0; i < nb_sections; i++) { + file_seek(file, loffset + pos); + if (fs_read(file, §ion, sizeof(PEF_section_t)) < 0) { + ERROR("Cannot read section %d\n", i); + return -1; + } + pos += sizeof(PEF_section_t); + addr = (void *)get_be32(§ion.address); + sections[i] = addr; + if (addr < first) + first = addr; + size = get_be32(§ion.total_size); + lpos = get_be32(§ion.container_offset); + file_seek(file, loffset + lpos); + switch (section.section_kind) { + case PEF_SECTION_CODE: + case PEF_SECTION_UNPDATA: + /* Load as raw data */ + padsize = get_be32(§ion.unpacked_size) - size; + file_seek(file, loffset + lpos); + if (fs_read(file, addr, size) < 0) { + ERROR("Cannot load section %d\n", i); + return -1; + } + addr = (char *)addr + size; + memset(addr, 0, padsize); + addr = (char *)addr + padsize; + break; + case PEF_SECTION_INIDATA: + case PEF_SECTION_CONSTANT: + case PEF_SECTION_EXEC: + /* Load as compressed data */ + for (;;) { + void *ref; + uint32_t total; + uint8_t bsize, csize, count, j; + + if (fs_read(file, &opcode, 1) < 0) { + ERROR("Cannot get opcode\n"); + return -1; + } + bsize = opcode & 0x1F; + switch (opcode >> 5) { + case 0x0: + /* Initialize size bytes to zero */ + memset(addr, 0, bsize); + addr = (char *)addr + bsize; + total = bsize; + break; + case 0x1: + /* Copy bloc */ + if (fs_read(file, addr, bsize) < 0) { + ERROR("Cannot copy bloc\n"); + return -1; + } + addr = (char *)addr + bsize; + total = bsize; + break; + case 0x2: + /* Repeat bloc */ + if (fs_read(file, &count, 1) < 0) { + ERROR("Cannot read bloc size\n"); + return -1; + } + total = 0; + if (count == 0) { + break; + } + if (fs_read(file, addr, bsize) < 0) { + ERROR("Cannot read repeat bloc\n"); + return -1; + } + ref = addr; + addr = (char *)addr + bsize; + for (j = 1; j < count; j++) { + memcpy(addr, ref, bsize); + total += bsize; + addr = (char *)addr + bsize; + } + break; + case 0x3: + /* Interleave repeat bloc with bloc copy */ + if (fs_read(file, &csize, 1) < 0 || + fs_read(file, &count, 1) < 0) { + ERROR("Cannot read repeat params\n"); + return -1; + } + ref = addr; + if (fs_read(file, addr, bsize) < 0) { + ERROR("Cannot read common data\n"); + return -1; + } + addr = (char *)addr + bsize; + total = bsize; + for (j = 0; j < count; j++) { + if (fs_read(file, addr, csize) < 0) { + ERROR("Cannot read custom data\n"); + return -1; + } + addr = (char *)addr + csize; + memcpy(addr, ref, bsize); + addr = (char *)addr + bsize; + total += csize + bsize; + } + break; + case 0x4: + /* Interleave repeat bloc with zero */ + if (fs_read(file, &csize, 1) < 0 || + fs_read(file, &count, 1) < 0) { + ERROR("Cannot read repeat params\n"); + return -1; + } + total = 0; + for (j = 0; j < count; j++) { + memset(addr, 0, bsize); + addr = (char *)addr + bsize; + if (fs_read(file, addr, csize) < 0) { + ERROR("Cannot read repeat data\n"); + return -1; + } + addr = (char *)addr + csize; + total += csize + bsize; + } + memset(addr, 0, bsize); + addr = (char *)addr + bsize; + total += bsize; + break; + default: + ERROR("Unknown opcode\n"); + return -1; + } + if (addr > last) + last = addr; + if (total >= size) + break; + size -= total; + } + break; + case PEF_SECTION_LOADER: + /* find entry point */ + if (fs_read(file, &loader, sizeof(PEF_loader_t)) < 0) { + ERROR("Cannot read loader header\n"); + return -1; + } + main_section = get_be32(&loader.main_section); + main_offset = get_be32(&loader.main_offset); + if (main_section >= nb_sections) { + ERROR("Invalid main section\n"); + return -1; + } + break; + case PEF_SECTION_DEBUG: + case PEF_SECTION_EXCP: + case PEF_SECTION_TRACE: + break; + default: + return -2; + } + } + *dest = first; + *end = last; + if (main_section == -1) { + *entry = first; + } else { + *entry = (char *)sections[main_section] + main_offset; + } + free(sections); + + return 0; +} diff --git a/qemu/roms/openhackware/src/libexec/prep.c b/qemu/roms/openhackware/src/libexec/prep.c new file mode 100644 index 000000000..15b6ea67d --- /dev/null +++ b/qemu/roms/openhackware/src/libexec/prep.c @@ -0,0 +1,45 @@ +/* + * <prep.c> + * + * Open Hack'Ware BIOS PREP executable file loader + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include "bios.h" +#include "exec.h" + +/* PREP boot loader */ +int exec_load_prep (inode_t *file, unused void **dest, + unused void **entry, unused void **end, + unused uint32_t loffset) +{ + unsigned char buffer[512]; + + file_seek(file, loffset); + if (fs_read(file, buffer, 512) < 0) { + ERROR("Cannot load first bloc of file...\n"); + return -2; + } + if (buffer[0x1FE] != 0x55 || buffer[0x1FF] != 0xAA) { + DPRINTF("Not a PREP file\n"); + return -2; + } + + return -2; +} diff --git a/qemu/roms/openhackware/src/libexec/xcoff.c b/qemu/roms/openhackware/src/libexec/xcoff.c new file mode 100644 index 000000000..a9a6da48b --- /dev/null +++ b/qemu/roms/openhackware/src/libexec/xcoff.c @@ -0,0 +1,216 @@ +/* + * <xcoff.c> + * + * Open Hack'Ware BIOS XCOFF executable file loader + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License V2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> +#include "bios.h" +#include "exec.h" + +uint32_t fs_inode_get_size (inode_t *inode); + +/* XCOFF executable loader */ +typedef struct COFF_filehdr_t { + uint16_t f_magic; /* magic number */ + uint16_t f_nscns; /* number of sections */ + uint32_t f_timdat; /* time & date stamp */ + uint32_t f_symptr; /* file pointer to symtab */ + uint32_t f_nsyms; /* number of symtab entries */ + uint16_t f_opthdr; /* sizeof(optional hdr) */ + uint16_t f_flags; /* flags */ +} COFF_filehdr_t; + +/* IBM RS/6000 */ +#define U802WRMAGIC 0730 /* writeable text segments **chh** */ +#define U802ROMAGIC 0735 /* readonly sharable text segments */ +#define U802TOCMAGIC 0737 /* readonly text segments and TOC */ + +/* + * Bits for f_flags: + * + * F_RELFLG relocation info stripped from file + * F_EXEC file is executable (i.e. no unresolved external + * references) + * F_LNNO line numbers stripped from file + * F_LSYMS local symbols stripped from file + * F_MINMAL this is a minimal object file (".m") output of fextract + * F_UPDATE this is a fully bound update file, output of ogen + * F_SWABD this file has had its bytes swabbed (in names) + * F_AR16WR this file has the byte ordering of an AR16WR + * (e.g. 11/70) machine + * F_AR32WR this file has the byte ordering of an AR32WR machine + * (e.g. vax and iNTEL 386) + * F_AR32W this file has the byte ordering of an AR32W machine + * (e.g. 3b,maxi) + * F_PATCH file contains "patch" list in optional header + * F_NODF (minimal file only) no decision functions for + * replaced functions + */ + +#define COFF_F_RELFLG 0000001 +#define COFF_F_EXEC 0000002 +#define COFF_F_LNNO 0000004 +#define COFF_F_LSYMS 0000010 +#define COFF_F_MINMAL 0000020 +#define COFF_F_UPDATE 0000040 +#define COFF_F_SWABD 0000100 +#define COFF_F_AR16WR 0000200 +#define COFF_F_AR32WR 0000400 +#define COFF_F_AR32W 0001000 +#define COFF_F_PATCH 0002000 +#define COFF_F_NODF 0002000 + +typedef struct COFF_aouthdr_t { + uint16_t magic; /* type of file */ + uint16_t vstamp; /* version stamp */ + uint32_t tsize; /* text size in bytes, padded to FW bdry */ + uint32_t dsize; /* initialized data " " */ + uint32_t bsize; /* uninitialized data " " */ + uint32_t entry; /* entry pt. */ + uint32_t text_start; /* base of text used for this file */ + uint32_t data_start; /* base of data used for this file */ + uint32_t o_toc; /* address of TOC */ + uint16_t o_snentry; /* section number of entry point */ + uint16_t o_sntext; /* section number of .text section */ + uint16_t o_sndata; /* section number of .data section */ + uint16_t o_sntoc; /* section number of TOC */ + uint16_t o_snloader; /* section number of .loader section */ + uint16_t o_snbss; /* section number of .bss section */ + uint16_t o_algntext; /* .text alignment */ + uint16_t o_algndata; /* .data alignment */ + uint16_t o_modtype; /* module type (??) */ + uint16_t o_cputype; /* cpu type */ + uint32_t o_maxstack; /* max stack size (??) */ + uint32_t o_maxdata; /* max data size (??) */ + char o_resv2[12]; /* reserved */ +} COFF_aouthdr_t; + +#define AOUT_MAGIC 0x010b + +typedef struct COFF_scnhdr_t { + char s_name[8]; /* section name */ + uint32_t s_paddr; /* physical address, aliased s_nlib */ + uint32_t s_vaddr; /* virtual address */ + uint32_t s_size; /* section size */ + uint32_t s_scnptr; /* file ptr to raw data for section */ + uint32_t s_relptr; /* file ptr to relocation */ + uint32_t s_lnnoptr; /* file ptr to line numbers */ + uint16_t s_nreloc; /* number of relocation entries */ + uint16_t s_nlnno; /* number of line number entries */ + uint32_t s_flags; /* flags */ +} COFF_scnhdr_t; + +int exec_load_xcoff (inode_t *file, void **dest, void **entry, void **end, + uint32_t loffset) +{ + COFF_filehdr_t fhdr; + COFF_aouthdr_t ahdr; + COFF_scnhdr_t shdr; + void *first, *last; + uint32_t offset; + int i; + + file_seek(file, loffset); + if (fs_read(file, &fhdr, sizeof(COFF_filehdr_t)) < 0) { + ERROR("Cannot load first bloc of file...\n"); + return -1; + } + if (fhdr.f_magic != U802WRMAGIC && fhdr.f_magic != U802ROMAGIC && + fhdr.f_magic != U802TOCMAGIC && fhdr.f_magic != 0x01DF) { + DPRINTF("Not a XCOFF file %02x %08x\n", fhdr.f_magic, + *(uint32_t *)&fhdr.f_magic); + return -2; + } + if (fhdr.f_magic != 0x01DF && (fhdr.f_flags & COFF_F_EXEC) == 0) { + ERROR("Not an executable XCOFF file %02x\n", fhdr.f_flags); + return -2; + } + if (fhdr.f_opthdr != sizeof(COFF_aouthdr_t)) { + ERROR("AOUT optional error size missmactch in XCOFF file\n"); + return -2; + } + if (fs_read(file, &ahdr, sizeof(COFF_aouthdr_t)) < 0) { + ERROR("Cannot load XCOFF AOUT header...\n"); + return -1; + } + if (ahdr.magic != AOUT_MAGIC) { + ERROR("Invalid AOUT optional header\n"); + return -2; + } +#if 0 // XXX: buggy: this makes NetBSD fail to boot + if (fhdr.f_magic == 0x01DF) { + /* Load embedded file */ + return _bootfile_load(file, dest, entry, end, loffset + + sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t) + + (fhdr.f_nscns * sizeof(COFF_scnhdr_t)), + -1); + } +#endif + *entry = (void *)ahdr.entry + 0xC; + last = NULL; + first = last - 4; + offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t); + DPRINTF("XCOFF file with %d sections entry:%p\n", fhdr.f_nscns, *entry); + for (i = 0; i < fhdr.f_nscns; i++) { + DPRINTF("Read next header (%0x)\n", offset); + file_seek(file, offset + loffset); + if (fs_read(file, &shdr, sizeof(COFF_scnhdr_t)) < 0) { + ERROR("Cannot load section header %d...\n", i); + return -1; + } + if (strcmp(shdr.s_name, ".text") == 0 || + strcmp(shdr.s_name, ".data") == 0) { + if ((void *)shdr.s_vaddr < first) + first = (void *)shdr.s_vaddr; + if ((void *)shdr.s_vaddr > last) + last = (void *)shdr.s_vaddr; + DPRINTF("Load '%s' section from %0x %0x to %0x (%0x)\n", + shdr.s_name, offset, shdr.s_scnptr, + shdr.s_vaddr, shdr.s_size); +#if 0 + if (shdr.s_scnptr + shdr.s_size > fs_inode_get_size(file)) { + ERROR("Section %d data offset > file size\n", i); + return -1; + } +#endif + file_seek(file, shdr.s_scnptr + loffset); + set_loadinfo((void *)first, last - first); + if (fs_read(file, (void *)shdr.s_vaddr, shdr.s_size) < 0) { + ERROR("Cannot load section %d...\n", i); + return -1; + } + } else if (strcmp(shdr.s_name, ".bss") == 0) { + if ((void *)shdr.s_vaddr < first) + first = (void *)shdr.s_vaddr; + if ((void *)shdr.s_vaddr > last) + last = (void *)shdr.s_vaddr; + DPRINTF("Erase '%s' section at %0x size: %0x\n", + shdr.s_name, shdr.s_vaddr, shdr.s_size); + memset((void *)shdr.s_vaddr, 0, shdr.s_size); + } else { + DPRINTF("Skip '%s' section\n", shdr.s_name); + } + offset += sizeof(COFF_scnhdr_t); + } + *dest = first; + *end = last; + + return 0; +} |