summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openhackware/src/libexec/chrp.c
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/openhackware/src/libexec/chrp.c
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (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/chrp.c')
-rw-r--r--qemu/roms/openhackware/src/libexec/chrp.c404
1 files changed, 404 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;
+}