summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openhackware/src/libpart
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openhackware/src/libpart')
-rw-r--r--qemu/roms/openhackware/src/libpart/apple.c314
-rw-r--r--qemu/roms/openhackware/src/libpart/core.c288
-rw-r--r--qemu/roms/openhackware/src/libpart/isofs.c257
-rw-r--r--qemu/roms/openhackware/src/libpart/libpart.h67
-rw-r--r--qemu/roms/openhackware/src/libpart/prep.c216
5 files changed, 1142 insertions, 0 deletions
diff --git a/qemu/roms/openhackware/src/libpart/apple.c b/qemu/roms/openhackware/src/libpart/apple.c
new file mode 100644
index 000000000..1d72f67d3
--- /dev/null
+++ b/qemu/roms/openhackware/src/libpart/apple.c
@@ -0,0 +1,314 @@
+/*
+ * <apple.c>
+ *
+ * Open Hack'Ware BIOS Apple partition type management
+ *
+ * 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 "libpart.h"
+
+/* Apple partitions handler */
+#define HFS_BLOCSIZE (512)
+
+typedef struct Mac_head_t Mac_head_t;
+struct Mac_head_t {
+ /* 0x000 */
+ uint8_t signature[2];
+ uint16_t bloc_size;
+ uint32_t bloc_count;
+ /* 0x008 */
+ uint16_t dev_type;
+ uint16_t dev_ID;
+ uint32_t data;
+ /* 0x010 */
+ uint16_t driver_cnt;
+ uint8_t pad[428];
+ /* 0x01BE */
+ uint8_t part_table[0x40];
+ /* 0x1FE */
+ uint8_t magic[2];
+ /* 0x0200 */
+} __attribute__ ((packed));
+
+typedef struct Mac_driver_entry_t Mac_driver_entry_t;
+struct Mac_driver_entry_t {
+ uint32_t start;
+ uint16_t size;
+ uint16_t type;
+} __attribute__ ((packed));
+
+typedef enum Mac_partflags_t Mac_partflags_t;
+enum Mac_partflags_t {
+ MACPART_SPEC2 = 0x0100,
+ MACPART_SPEC1 = 0x0080,
+ MACPART_PIC = 0x0040,
+ MACPART_WRITABLE = 0x0020,
+ MACPART_READABLE = 0x0010,
+ MACPART_BOOTABLE = 0x0008,
+ MACPART_INUSE = 0x0004,
+ MACPART_ALLOCATED = 0x0002,
+ MACPART_VALID = 0x0001,
+};
+
+#define MAC_BOOTABLE_PART (MACPART_VALID | MACPART_INUSE | MACPART_BOOTABLE)
+
+typedef struct Mac_partmap_t Mac_partmap_t;
+struct Mac_partmap_t {
+ /* 0x000 */
+ uint8_t signature[2];
+ uint8_t res0[2];
+ uint32_t map_cnt;
+ /* 0x008 */
+ uint32_t start_bloc;
+ uint32_t bloc_cnt;
+ /* 0x010 */
+ uint8_t name[32];
+ /* 0x030 */
+ uint8_t type[32];
+ /* 0x050 */
+ uint32_t data_start;
+ uint32_t data_cnt;
+ /* 0x058 */
+ uint32_t flags;
+ uint32_t boot_start;
+ /* 0x060 */
+ uint32_t boot_size;
+ uint32_t boot_load;
+ /* 0x068 */
+ uint32_t boot_load2;
+ uint32_t boot_entry;
+ /* 0x070 */
+ uint32_t boot_entry2;
+ uint32_t boot_csum;
+ /* 0x078 */
+ uint8_t CPU[16];
+ /* 0x088 */
+ uint8_t boot_args[0x80];
+ /* 0x108 */
+ uint8_t pad0[0xC8];
+ /* 0x1D4 */
+ uint16_t ntype;
+ uint8_t ff[2];
+ /* 0x1D8 */
+ uint8_t pad1[0x24];
+ /* 0x1FC */
+ uint8_t mark[4];
+ /* 0x200 */
+} __attribute__ ((packed));
+
+int fs_raw_set_bootfile (part_t *part,
+ uint32_t start_bloc, uint32_t start_offset,
+ uint32_t size_bloc, uint32_t size_offset);
+
+part_t *Apple_probe_partitions (bloc_device_t *bd)
+{
+ unsigned char tmp[33], *name;
+ Mac_head_t *head;
+ Mac_partmap_t *partmap;
+ part_t *part, *boot_part;
+ unsigned char *type;
+ uint8_t *buffer;
+ uint32_t pos, bloc, start, count;
+ uint32_t bloc_size, flags;
+ int map_count, i, n, len;
+
+ part = NULL;
+ boot_part = NULL;
+ n = 1;
+ buffer = malloc(HFS_BLOCSIZE);
+ /* Read first sector */
+ bd_seek(bd, 0, 0);
+ if (bd_read(bd, buffer, HFS_BLOCSIZE) < 0) {
+ ERROR("Unable to read boot sector from boot device. Aborting...\n");
+ goto error;
+ }
+ head = (Mac_head_t *)buffer;
+ if (head->signature[0] != 'E' || head->signature[1] != 'R') {
+ // MSG("\rNo Apple boot bloc signature...\n");
+ goto error;
+ }
+ MSG("\rFound Apple partition map...\n");
+ bloc = 0;
+ bloc_size = bd_seclen(bd);
+ map_count = 1;
+#if 0
+ if (head->magic[0] == 0x55 && head->magic[1] == 0xAA) {
+ /* PREP boot image ! Must parse it as MS-DOS boot bloc */
+ ERROR("%s PREP head magic\n", __func__);
+ goto error;
+ }
+#endif
+ /* Partition table starts in sector 1 */
+ for (i = 1; i < (map_count + 1); i++) {
+ bloc = (i * HFS_BLOCSIZE) / bloc_size;
+ pos = (i * HFS_BLOCSIZE) % bloc_size;
+ DPRINTF("Check part %d of %d (%d %d %d)\n",
+ i, map_count, bloc, pos, bloc_size);
+ bd_seek(bd, bloc, pos);
+ if (bd_read(bd, buffer, HFS_BLOCSIZE) < 0) {
+ ERROR("%s sector_read failed (%d)\n", __func__, i);
+ goto error;
+ }
+ partmap = (Mac_partmap_t *)buffer;
+ if (partmap->signature[0] != 'P' || partmap->signature[1] != 'M' ) {
+ ERROR("%s bad partition signature (%c %c)\n",
+ __func__, partmap->signature[0], partmap->signature[1]);
+ goto error;
+ }
+ /* We found at least one Apple partition map,
+ * so we won't have to try to parse with other partition mappings.
+ */
+ for (type = partmap->type; (type - partmap->type) < 32; type++) {
+ if (*type != '\0')
+ break;
+ }
+ if (partmap->name[0] == '\0') {
+ sprintf(tmp, "part%d", i);
+ name = tmp;
+ } else {
+ name = partmap->name;
+ }
+ /* Regular Apple partition */
+ part = malloc(sizeof(part_t));
+ if (part == NULL) {
+ ERROR("%s: can't allocate partition\n", __func__);
+ return NULL;
+ }
+ memset(part, 0, sizeof(part_t));
+ part->start = partmap->start_bloc;
+ part->size = partmap->bloc_cnt;
+ part_set_blocsize(bd, part, HFS_BLOCSIZE);
+ len = 32 - (type - partmap->type);
+ if (len == 0) {
+ /* Place holder. Skip it */
+ DPRINTF("%s placeholder part\t%d\n", __func__, i);
+ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_Void", type, 32) == 0) {
+ /* Void partition. Skip it */
+ DPRINTF("%s Void part\t%d [%s]\n", __func__, i, type);
+ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_Free", type, 32) == 0) {
+ /* Free space. Skip it */
+ DPRINTF("%s Free part (%d)\n", __func__, i);
+ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_partition_map", type, 32) == 0 ||
+ strncmp("Apple_Partition_Map", type, 32) == 0
+#if 0 // Is this really used or is it just a mistake ?
+ || strncmp("Apple_patition_map", type, 32) == 0
+#endif
+ ) {
+ DPRINTF("%s Partition map\t%d [%s]\n", __func__, i, type);
+ /* We are in the partition map descriptor */
+ if (i == 1) {
+ /* Get the real map blocs count */
+ map_count = partmap->map_cnt;
+ DPRINTF("%s: map_count: %d\n", __func__, map_count);
+ } else {
+ /* Don't about about secondary partition map
+ * Seems to be used, at least on CDROMs, to describe
+ * the same partition map with bloc_size = 2048
+ */
+ }
+ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_Driver", type, 32) == 0 ||
+ strncmp("Apple_Driver43", type, 32) == 0 ||
+ strncmp("Apple_Driver43_CD", type, 32) == 0 ||
+ strncmp("Apple_Driver_ATA", type, 32) == 0 ||
+ strncmp("Apple_Driver_ATAPI", type, 32) == 0 ||
+ strncmp("Apple_FWDriver", type, 32) == 0 ||
+ strncmp("Apple_Driver_IOKit", type, 32) == 0) {
+ /* Drivers. don't care for now */
+ DPRINTF("%s Drivers part\t%d [%s]\n", __func__, i, type);
+ part->flags = PART_TYPE_APPLE | PART_FLAG_DRIVER;
+ part_register(bd, part, name, i);
+ } else if (strncmp("Apple_Patches", type, 32) == 0) {
+ /* Patches: don't care for now */
+ part->flags = PART_TYPE_APPLE | PART_FLAG_PATCH;
+ part_register(bd, part, name, i);
+ DPRINTF("%s Patches part\t%d [%s]\n", __func__, i, type);
+ } else if (strncmp("Apple_HFS", type, 32) == 0 ||
+ strncmp("Apple_MFS", type, 32) == 0 ||
+ strncmp("Apple_UFS", type, 32) == 0 ||
+ strncmp("Apple_PRODOS", type, 32) == 0 ||
+ strncmp("Apple_UNIX_SVR2", type, 32) == 0 ||
+ strncmp("Linux", type, 32) == 0 ||
+ strncmp("NetBSD/macppc", type, 32) == 0 ||
+ strncmp("Apple_boot", type, 32) == 0 ||
+ strncmp("Apple_bootstrap", type, 32) == 0 ||
+ strncmp("Apple_Bootstrap", type, 32) == 0) {
+ DPRINTF("%s Fs part\t%d [%s]\n", __func__, i, type);
+ /* Filesystems / boot partitions */
+ flags = partmap->flags;
+ start = partmap->start_bloc * HFS_BLOCSIZE;
+ count = partmap->bloc_cnt * HFS_BLOCSIZE;
+ if (partmap->boot_size == 0 || partmap->boot_load == 0) {
+ printf("Not a bootable partition %d %d (%p %p)\n",
+ partmap->boot_size, partmap->boot_load,
+ boot_part, part);
+ part->flags = PART_TYPE_APPLE | PART_FLAG_FS;
+ } else {
+ part->boot_start.bloc = partmap->boot_start;
+ part->boot_start.offset = 0;
+ part->boot_size.bloc = partmap->boot_size / HFS_BLOCSIZE;
+#if 0
+ printf("%0x %0x %0x\n", partmap->boot_size, HFS_BLOCSIZE,
+ part->boot_size.bloc);
+#endif
+ part->boot_size.offset = (partmap->boot_size) % HFS_BLOCSIZE;
+ part->boot_load = partmap->boot_load;
+ part->boot_entry = partmap->boot_entry;
+ fs_raw_set_bootfile(part, part->boot_start.bloc,
+ part->boot_start.offset,
+ part->boot_size.bloc,
+ part->boot_size.offset);
+ boot_part = part;
+ part->flags = PART_TYPE_APPLE | PART_FLAG_FS | PART_FLAG_BOOT;
+ }
+ printf("Partition: %d '%s' '%s' st %0x size %0x",
+ i, name, type, partmap->start_bloc, partmap->bloc_cnt);
+#ifndef DEBUG
+ printf("\n");
+#endif
+ DPRINTF(" - %0x %0x %p %p\n",
+ partmap->boot_start, partmap->boot_size, part, part->fs);
+ DPRINTF(" boot %0x %0x load %0x entry %0x\n",
+ part->boot_start.bloc, part->boot_size.bloc,
+ part->boot_load, part->boot_entry);
+ DPRINTF(" load %0x entry %0x %0x\n",
+ partmap->boot_load2, partmap->boot_entry2, HFS_BLOCSIZE);
+ part_register(bd, part, name, i);
+ } else {
+ memcpy(tmp, type, 32);
+ tmp[32] = '\0';
+ ERROR("Unknown partition type [%s]\n", tmp);
+ part->flags = PART_TYPE_APPLE | PART_FLAG_DUMMY;
+ part_register(bd, part, name, i);
+ }
+ }
+ error:
+ free(buffer);
+
+ return boot_part;
+
+}
diff --git a/qemu/roms/openhackware/src/libpart/core.c b/qemu/roms/openhackware/src/libpart/core.c
new file mode 100644
index 000000000..bc2feb0a4
--- /dev/null
+++ b/qemu/roms/openhackware/src/libpart/core.c
@@ -0,0 +1,288 @@
+/*
+ * <part.c>
+ *
+ * Open Hack'Ware BIOS partitions management
+ *
+ * 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 "libpart.h"
+
+/* Bootable partitions detection and management */
+part_t *part_open (bloc_device_t *bd,
+ uint32_t start, uint32_t size, uint32_t spb)
+{
+ part_t *part;
+
+ if (bd_seek(bd, (start + size) * spb, 0) < 0)
+ return NULL;
+ part = malloc(sizeof(part_t));
+ if (part == NULL)
+ return NULL;
+ part->bd = bd;
+ part->start = start;
+ part->size = size;
+ part->spb = spb;
+
+ return part;
+}
+
+int part_seek (part_t *part, uint32_t bloc, uint32_t pos)
+{
+ if (bloc > part->size) {
+ ERROR("bloc: %d part size: %d %p\n", bloc, part->size, part);
+ return -1;
+ }
+ bloc += part->start;
+ if (part->spb != 0) {
+ bloc *= part->spb;
+ pos = pos % part->bloc_size;
+ } else {
+ pos += (bloc % part->bps) * part->bloc_size;
+ bloc /= part->bps;
+ }
+
+ return bd_seek(part->bd, bloc, pos);
+}
+
+int part_read (part_t *part, void *buffer, int len)
+{
+ return bd_read(part->bd, buffer, len);
+}
+
+int part_write (part_t *part, const void *buffer, int len)
+{
+ return bd_write(part->bd, buffer, len);
+}
+
+void part_close (part_t *part)
+{
+ part->size = 0;
+}
+
+uint32_t part_blocsize (part_t *part)
+{
+ return part->bloc_size;
+}
+
+uint32_t part_flags (part_t *part)
+{
+ return part->flags;
+}
+
+uint32_t part_size (part_t *part)
+{
+ return part->size;
+}
+
+fs_t *part_fs (part_t *part)
+{
+ return part->fs;
+}
+
+void part_private_set (part_t *part, void *private)
+{
+ part->private = private;
+}
+
+void *part_private_get (part_t *part)
+{
+ return part->private;
+}
+
+void part_set_blocsize (bloc_device_t *bd, part_t *part, uint32_t blocsize)
+{
+ uint32_t seclen;
+
+ part->bloc_size = blocsize;
+ seclen = bd_seclen(bd);
+ if (blocsize < seclen) {
+ part->spb = 0;
+ part->bps = bd_seclen(bd) / part->bloc_size;
+ DPRINTF("%d part blocs in one sector (%d %d)\n", part->bps,
+ part->bloc_size, bd_seclen(bd));
+ } else {
+ part->spb = part->bloc_size / bd_seclen(bd);
+ part->bps = 0;
+ DPRINTF("%d sectors in one part bloc (%d %d)\n", part->spb,
+ part->bloc_size, bd_seclen(bd));
+ }
+}
+
+int part_register (bloc_device_t *bd, part_t *partition,
+ const unsigned char *name, int partnum)
+{
+ part_t **cur;
+
+ DPRINTF("Register partition '%s'\n", name);
+ partition->bd = bd;
+ partition->next = NULL;
+ partition->name = strdup(name);
+ partition->partnum = partnum;
+ for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next)
+ continue;
+ *cur = partition;
+
+ return 0;
+}
+
+part_t *part_get (bloc_device_t *bd, int partnum)
+{
+ part_t **listp, *cur;
+
+ listp = _bd_parts(bd);
+
+ for (cur = *listp; cur != NULL; cur = cur->next) {
+ if (cur->partnum == partnum)
+ break;
+ }
+
+ return cur;
+}
+
+part_t *part_get_raw (bloc_device_t *bd)
+{
+ part_t *part;
+ uint32_t seclen;
+
+ part = malloc(sizeof(part_t));
+ part->start = 0;
+ seclen = bd_seclen(bd);
+ part->size = bd_maxbloc(bd);
+ if (seclen > 512) {
+ part->size *= seclen / 512;
+ } else {
+ part->size *= 512 / seclen;
+ }
+ part->boot_start.bloc = 0;
+ part->boot_start.offset = 0;
+ part->boot_size.bloc = part->size;
+ part->boot_size.offset = 0;
+ part->boot_load = 0;
+ part->boot_entry = 0;
+ part_set_blocsize(bd, part, 512);
+ part->bd = bd;
+ part->flags = PART_TYPE_RAW | PART_FLAG_BOOT;
+ part_register(bd, part, "Raw", 0);
+
+ return part;
+}
+
+bloc_device_t *part_get_bd (part_t *part)
+{
+ return part->bd;
+}
+
+part_t *part_probe (bloc_device_t *bd, int set_raw)
+{
+ part_t *part0 = NULL, *boot_part, **cur;
+
+ /* Try to find a valid boot partition */
+ boot_part = Apple_probe_partitions(bd);
+ if (boot_part == NULL) {
+ boot_part = isofs_probe_partitions(bd);
+ if (boot_part == NULL && arch == ARCH_PREP)
+ boot_part = PREP_find_partition(bd);
+ if (boot_part == NULL && set_raw != 0) {
+ dprintf("Use bloc device as raw partition\n");
+ }
+ }
+ if (_bd_parts(bd) == NULL) {
+ /* Register the 0 partition: raw partition containing the whole disk */
+ part0 = part_get_raw(bd);
+ }
+ /* Probe filesystem on each found partition */
+ for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next) {
+ const unsigned char *map, *type;
+ switch ((*cur)->flags & 0x0F) {
+ case PART_TYPE_PREP:
+ map = "PREP";
+ break;
+ case PART_TYPE_APPLE:
+ map = "Apple";
+ break;
+ case PART_TYPE_ISO9660:
+ map = "ISO9660";
+ break;
+ default:
+ map = "Raw";
+ break;
+ }
+ switch ((*cur)->flags & 0xF0) {
+ case PART_FLAG_DUMMY:
+ type = "dummy";
+ break;
+ case PART_FLAG_DRIVER:
+ type = "driver";
+ break;
+ case PART_FLAG_PATCH:
+ type = "patches";
+ break;
+ case PART_FLAG_FS:
+ type = "filesystem";
+ break;
+ default:
+ type = "unknown";
+ break;
+ }
+ dprintf("Probe filesystem on %s %s partition '%s' %s %p\n",
+ type, map, (*cur)->name,
+ ((*cur)->flags) & PART_FLAG_BOOT ? "(bootable)" : "", *cur);
+ if (((*cur)->flags) & PART_FLAG_FS) {
+ if (((*cur)->flags) & PART_FLAG_BOOT)
+ (*cur)->fs = fs_probe(*cur, 1);
+ else
+ (*cur)->fs = fs_probe(*cur, 0);
+ } else if (((*cur)->flags) & PART_TYPE_RAW) {
+ (*cur)->fs = fs_probe(*cur, 2);
+ } else {
+ (*cur)->fs = fs_probe(*cur, 2);
+ }
+ fs_get_bootfile((*cur)->fs);
+ if (((*cur)->flags) & PART_FLAG_BOOT) {
+ dprintf("Partition is bootable (%d)\n", (*cur)->partnum);
+ bd_set_boot_part(bd, *cur, (*cur)->partnum);
+ if (boot_part == NULL)
+ boot_part = *cur;
+ }
+ }
+ dprintf("Boot partition: %p %p %p %p\n", boot_part, boot_part->fs,
+ part_fs(boot_part), part0);
+
+ return boot_part;
+}
+
+int part_set_boot_file (part_t *part, uint32_t start, uint32_t offset,
+ uint32_t size)
+{
+ part->boot_start.bloc = start;
+ part->boot_start.offset = offset;
+ part->boot_size.bloc = size;
+ part->boot_size.offset = 0;
+ part->boot_load = 0;
+ part->boot_entry = 0;
+ part->flags |= PART_FLAG_BOOT;
+
+ return 0;
+}
+
+unsigned int part_get_entry (part_t *part)
+{
+ return part->boot_entry;
+}
diff --git a/qemu/roms/openhackware/src/libpart/isofs.c b/qemu/roms/openhackware/src/libpart/isofs.c
new file mode 100644
index 000000000..6e0adae3e
--- /dev/null
+++ b/qemu/roms/openhackware/src/libpart/isofs.c
@@ -0,0 +1,257 @@
+/*
+ * <isofs.c>
+ *
+ * Open Hack'Ware BIOS ISOFS partition type management
+ *
+ * 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 "libpart.h"
+
+/* ISO FS partitions handlers */
+#define ISOFS_BLOCSIZE (2048)
+
+/* Generic ISO fs descriptor */
+typedef struct isofs_desc_t isofs_desc_t;
+struct isofs_desc_t {
+ uint8_t type;
+ uint8_t ID[5];
+ uint8_t version;
+ uint8_t data[2041];
+} __attribute__ ((packed));
+
+typedef struct iso_primary_desc_t iso_primary_desc_t;
+struct iso_primary_desc_t {
+ uint8_t type;
+ uint8_t ID[5];
+ uint8_t version;
+ uint8_t pad0;
+ uint8_t system_id[32];
+ uint8_t volume_id[32];
+ uint8_t pad1[8];
+ uint32_t volume_size;
+} __attribute__ ((packed));
+
+/* The only descriptor we're interrested in here
+ * is El-torito boot descriptor
+ */
+typedef struct isofs_bootdesc_t isofs_bootdesc_t;
+struct isofs_bootdesc_t {
+ uint8_t type;
+ uint8_t ID[5];
+ uint8_t version;
+ uint8_t sys_ID[32];
+ uint8_t pad[32];
+ uint32_t catalog;
+ uint8_t data[1973];
+} __attribute__ ((packed));
+
+#define ISO_BOOTABLE 0x88
+enum {
+ ISOBOOT_IX86 = 0,
+ ISOBOOT_PPC = 1,
+ ISOBOOT_MAC = 2,
+};
+
+enum {
+ ISOMEDIA_NOEMUL = 0,
+ ISOMEDIA_FL12 = 1,
+ ISOMEDIA_FL144 = 2,
+ ISOMEDIA_FL288 = 3,
+ ISOMEDIA_HD = 4,
+};
+
+typedef struct isofs_validdesc_t isofs_validdesc_t;
+struct isofs_validdesc_t {
+ uint8_t ID;
+ uint8_t arch;
+ uint8_t pad[2];
+ uint8_t name[24];
+ uint8_t csum[2];
+ uint16_t key;
+} __attribute__ ((packed));
+
+typedef struct isofs_bootcat_t isofs_bootcat_t;
+struct isofs_bootcat_t {
+ uint8_t bootable;
+ uint8_t media;
+ uint8_t segment[2];
+ uint8_t sys_type;
+ uint8_t pad;
+ uint16_t nsect;
+ uint32_t offset;
+ uint8_t data[20];
+} __attribute__ ((packed));
+
+part_t *isofs_probe_partitions (bloc_device_t *bd)
+{
+ unsigned char name[32];
+ void *buffer;
+ union {
+ isofs_desc_t desc;
+ isofs_bootdesc_t bootdesc;
+ iso_primary_desc_t primdesc;
+ } *desc;
+ isofs_validdesc_t *valid;
+ isofs_bootcat_t *bootcat;
+ part_t *part;
+ uint32_t boot_desc;
+ uint32_t nsect, bloc, offset, length;
+ int i, end_reached;
+
+ part = NULL;
+ buffer = malloc(ISOFS_BLOCSIZE);
+ end_reached = 0;
+ desc = buffer;
+ boot_desc = -1;
+ /* The descriptors start at offset 0x8000 */
+ for (bloc = 0x8000 / ISOFS_BLOCSIZE; end_reached == 0; bloc++) {
+ bd_seek(bd, bloc, 0);
+ if (bd_read(bd, buffer, ISOFS_BLOCSIZE) < 0) {
+ ERROR("%s bloc_read %d failed\n", __func__, bloc);
+ goto error;
+ }
+ if (strncmp("CD001", desc->desc.ID, 5) != 0) {
+ // MSG("\rNo ISO9660 signature\n");
+ goto error;
+ }
+ /* We found at least one valid descriptor */
+ switch (desc->desc.type) {
+ case 0x00:
+ /* El-torito descriptor, great ! */
+ DPRINTF("El-torito descriptor: %08x %d\n", desc->bootdesc.catalog,
+ (char *)&desc->bootdesc.catalog - (char *)desc);
+ boot_desc = get_le32(&desc->bootdesc.catalog);
+ break;
+ case 0x01:
+ /* ISOFS primary descriptor */
+ DPRINTF("ISOFS primary descriptor (%d %d)\n",
+ get_le32(&desc->primdesc.volume_size) * 2048,
+ get_le32(&desc->primdesc.volume_size));
+ break;
+ case 0x02:
+ /* ISOFS suplementary descriptor */
+ DPRINTF("ISOFS suplementary descriptor\n");
+ break;
+ case 0xFF:
+ /* End of descriptor list */
+ DPRINTF("End of descriptor list\n");
+ end_reached = 1;
+ break;
+ }
+ }
+ if (boot_desc != (uint32_t)(-1)) {
+ /* Find the validation descriptor */
+ bd_seek(bd, boot_desc, 0);
+ for (i = 0; i < (ISOFS_BLOCSIZE / 64); i++) {
+ DPRINTF("ISO catalog...\n");
+ bd_read(bd, buffer, 64);
+ valid = buffer;
+#if 1
+ if (valid->ID != 0x01 || get_le16(&valid->key) != 0xAA55) {
+ ERROR("ISO catalog with invalid ID/key: %x %x\n",
+ valid->ID, valid->key);
+ continue;
+ }
+#endif
+#if 0
+#if defined (__i386__)
+ if (valid->arch != ISOBOOT_IX86) {
+ ERROR("ISO catalog not for x86: %d\n", valid->arch);
+ continue;
+ }
+#elif defined (__powerpc__) || defined (_ARCH_PPC)
+ if (valid->arch != ISOBOOT_PPC && valid->arch != ISOBOOT_MAC) {
+ ERROR("ISO catalog not for PPC: %d\n", valid->arch);
+ continue;
+ }
+#else
+ ERROR("Unknown host architecture !\n");
+ continue;
+#endif
+#endif
+ bootcat = (void *)(valid + 1);
+ if (bootcat->bootable != ISO_BOOTABLE) {
+ ERROR("Non bootable ISO catalog\n");
+ continue;
+ }
+ nsect = get_le16(&bootcat->nsect);
+ switch (bootcat->media) {
+ case ISOMEDIA_NOEMUL:
+ length = nsect * ISOFS_BLOCSIZE;
+ dprintf("No emulation\n");
+ break;
+ case ISOMEDIA_FL12:
+ length = 1200 * 1024;
+ dprintf("1.2 MB floppy\n");
+ break;
+ case ISOMEDIA_FL144:
+ length = 1440 * 1024;
+ dprintf("1.44 MB floppy\n");
+ break;
+ case ISOMEDIA_FL288:
+ length = 2880 * 1024;
+ dprintf("2.88 MB floppy\n");
+ break;
+ case ISOMEDIA_HD:
+ length = nsect * ISOFS_BLOCSIZE;
+ dprintf("HD image\n");
+ break;
+ default:
+ ERROR("Unknown media type: %d\n", bootcat->media);
+ continue;
+ }
+ offset = get_le32(&bootcat->offset);
+ /* Register boot disc */
+ part = malloc(sizeof(part_t));
+ part->bd = bd;
+ part_set_blocsize(bd, part, ISOFS_BLOCSIZE);
+ part->start = offset;
+ part->size = (length + ISOFS_BLOCSIZE - 1) / ISOFS_BLOCSIZE;
+ part->boot_start.bloc = 0;
+ part->boot_start.offset = 0;
+ part->boot_size.bloc = length / ISOFS_BLOCSIZE;
+ part->boot_size.offset = length % ISOFS_BLOCSIZE;
+ part->boot_load = 0;
+ part->boot_entry = 0;
+ if (valid->name[0] == '\0') {
+ strcpy(name, "ISOFS");
+ } else {
+ memcpy(name, valid->name, sizeof(valid->name));
+ name[sizeof(valid->name)] = '\0';
+ }
+ printf("Partition '%s': %p st %0x size %0x %d\n",
+ name, part, offset, length, bootcat->media);
+ printf(" boot %0x %0x load %0x entry %0x\n",
+ part->boot_start.bloc, part->boot_size.bloc,
+ part->boot_load, part->boot_entry);
+ part->flags = PART_TYPE_ISO9660 | PART_FLAG_BOOT;
+ part_register(bd, part, name, i + 1);
+ fs_raw_set_bootfile(part, part->boot_start.bloc,
+ part->boot_start.offset,
+ part->boot_size.bloc,
+ part->boot_size.offset);
+ break;
+ }
+ }
+error:
+ free(buffer);
+
+ return part;
+}
diff --git a/qemu/roms/openhackware/src/libpart/libpart.h b/qemu/roms/openhackware/src/libpart/libpart.h
new file mode 100644
index 000000000..a982b8f29
--- /dev/null
+++ b/qemu/roms/openhackware/src/libpart/libpart.h
@@ -0,0 +1,67 @@
+/*
+ * <libpart.h>
+ *
+ * Open Hack'Ware BIOS partitions management 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_LIBPART_H__)
+#define __OHW_LIBPART_H__
+
+/* LBA for IDE is 48 bits long.
+ * For now, I'll use 32 bits to store bloc nr
+ * and 32 bits to store offsets in blocs and will only handle LBA 28.
+ * So, I'll be affected with the well known 128 GB disk barrier bug...
+ */
+
+struct part_t {
+ bloc_device_t *bd;
+ int partnum;
+ uint32_t start; /* Partition first bloc */
+ uint32_t size; /* Partition size, in blocs */
+ uint32_t spb;
+ uint32_t bps;
+ uint32_t flags;
+
+ uint32_t bloc_size; /* Bloc size (may be != bd->seclen) */
+ /* XXX: broken: to be reworked */
+ pos_t boot_start; /* Boot program start bloc & offset */
+ pos_t boot_size; /* Boot program size */
+ uint32_t boot_load; /* Boot program address load */
+ uint32_t boot_entry; /* Boot program entry point */
+
+ unsigned char *name;
+ inode_t *boot_file;
+ fs_t *fs;
+
+ void *private;
+
+ part_t *next;
+ part_t *bnext;
+};
+
+int part_register (bloc_device_t *bd, part_t *partition,
+ const unsigned char *name, int partnum);
+void part_set_blocsize (bloc_device_t *bd, part_t *part, uint32_t blocsize);
+void part_private_set (part_t *part, void *private);
+void *part_private_get (part_t *part);
+
+part_t *PREP_find_partition (bloc_device_t *bd);
+part_t *Apple_probe_partitions (bloc_device_t *bd);
+part_t *isofs_probe_partitions (bloc_device_t *bd);
+
+#endif /* !defined (__OHW_LIBPART_H__) */
diff --git a/qemu/roms/openhackware/src/libpart/prep.c b/qemu/roms/openhackware/src/libpart/prep.c
new file mode 100644
index 000000000..b957bb902
--- /dev/null
+++ b/qemu/roms/openhackware/src/libpart/prep.c
@@ -0,0 +1,216 @@
+/*
+ * <prep.c>
+ *
+ * Open Hack'Ware PREP BIOS partition type management
+ *
+ * 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 "libpart.h"
+
+/* PREP image management */
+typedef struct MSDOS_part_t MSDOS_part_t;
+struct MSDOS_part_t {
+ uint8_t boot_ind;
+ uint8_t start_head;
+ uint8_t start_sect;
+ uint8_t start_cyl;
+ uint8_t sys_ind;
+ uint8_t end_head;
+ uint8_t end_sect;
+ uint8_t end_cyl;
+ uint32_t LBA_start;
+ uint32_t LBA_end;
+} __attribute__ ((packed));
+
+part_t *PREP_find_partition (bloc_device_t *bd)
+{
+ MSDOS_part_t *p;
+ part_t *part;
+ uint8_t *buffer;
+ uint32_t boot_offset, boot_size;
+ int i;
+
+ part = NULL;
+ buffer = malloc(0x200);
+ bd_seek(bd, 0, 0);
+ if (bd_read(bd, buffer, 0x200) < 0) {
+ ERROR("Unable to read boot sector from boot device. Aborting...\n");
+ goto error;
+ }
+ if (buffer[0x1FE] != 0x55 || buffer[0x1FF] != 0xAA) {
+ ERROR("No MSDOS signature (%x %x %x %x)\n",
+ buffer[0x000], buffer[0x001], buffer[0x1FE], buffer[0x1FF]);
+ goto error;
+ }
+ for (i = 0; i < 4; i++) {
+ p = (void *)(&buffer[0x1BE + (0x10 * i)]);
+ DPRINTF("partition %d: %x is %sbootable - ", i, p->boot_ind,
+ (p->boot_ind & 0x80) ? "" : "not ");
+ DPRINTF("start %0x end %0x type %x\n",
+ get_le32(&p->LBA_start), get_le32(&p->LBA_end), p->sys_ind);
+#if 0
+ if (p->boot_ind != 0x80)
+ continue;
+#endif
+ switch (p->sys_ind) {
+ case 0x07: /* HPFS/NTFS */
+ goto register_nonboot;
+ case 0x08: /* AIX */
+ goto register_nonboot;
+ case 0x09: /* AIX bootable */
+ /* Not supported by now */
+ break;
+ case 0x0A: /* OS/2 boot manager */
+ /* Not supported by now */
+ break;
+ case 0x41: /* PREP boot */
+ part = malloc(sizeof(part_t));
+ memset(part, 0, sizeof(part_t));
+ part->bd = bd;
+ part_set_blocsize(bd, part, 0x200);
+ /* Convert start and size into LBA */
+ if ((p->start_head != 0 || p->start_cyl != 0 ||
+ p->start_sect != 0) && p->LBA_start == 0) {
+ DPRINTF("start: use CHS\n");
+ part->start = bd_CHS2sect(bd, p->start_cyl,
+ p->start_head,
+ p->start_sect);
+ } else {
+ DPRINTF("start: use LBA\n");
+ part->start = get_le32(&p->LBA_start);
+ }
+ if ((p->end_head != 0 || p->end_cyl != 0 ||
+ p->end_sect != 0) && p->LBA_end == 0) {
+ DPRINTF("end: use CHS\n");
+ part->size = bd_CHS2sect(bd, p->end_cyl,
+ p->end_head, p->end_sect);
+ } else {
+ DPRINTF("end: use LBA\n");
+ part->size = get_le32(&p->LBA_end);
+ }
+ /* XXX: seems that some (AIX !)
+ * code the size here instead of partition end
+ */
+ if (part->size > part->start)
+ part->size -= part->start;
+ DPRINTF("LBA: start %0x size: %0x\n", part->start, part->size);
+ /* Now, find and check boot record */
+ part_seek(part, 0, 0);
+ if (bd_read(bd, buffer, part->bloc_size) < 0) {
+ ERROR("%s sector_read failed (%d)\n", __func__, i);
+ freep(&part);
+ goto error;
+ }
+#if 0
+ if (buffer[0x1FE] != 0x55 || buffer[0x1FF] != 0xAA) {
+ ERROR("No MSDOS signature on PREP boot record\n");
+ freep(&part);
+ goto error;
+ }
+#endif
+ boot_offset = get_le32(buffer);
+ boot_size = get_le32(buffer + 4);
+ if ((boot_offset & 3) || /*(boot_size & 3) ||*/
+ boot_offset == 0 || boot_size == 0) {
+ DPRINTF("Suspicious PREP boot parameters: %08x %08x %08x %08x\n",
+ part->start, part->start * 0x200, boot_offset, boot_size);
+#if 0
+ freep(&part);
+ goto error;
+#else
+ /* IBM boot blocs respect the norm better than others... */
+ part->start++;
+ part_seek(part, 0, 0);
+ if (bd_read(bd, buffer, part->bloc_size) < 0) {
+ ERROR("%s sector_read failed (%d)\n", __func__, i);
+ freep(&part);
+ goto error;
+ }
+ boot_offset = get_le32(buffer);
+ boot_size = get_le32(buffer + 4);
+#endif
+ }
+ DPRINTF("PREP boot parameters: %08x %08x %08x %08x\n",
+ part->start, part->start * 0x200, boot_offset, boot_size);
+ if (boot_size > (part->size * part->bloc_size)) {
+ ERROR("PREP boot image greater than boot partition: %0x %0x\n",
+ boot_size, part->size * part->bloc_size);
+#if 0
+ freep(&part);
+ goto error;
+#endif
+ }
+ part->boot_start.bloc = 0;
+ part->boot_start.offset = 0;
+ part->boot_size.bloc = boot_size / part->bloc_size;
+ part->boot_size.offset = boot_size % part->bloc_size;
+ part->boot_load = 0;
+ part->boot_entry = boot_offset - part->bloc_size;
+ part->flags = PART_TYPE_PREP | PART_FLAG_BOOT;
+ part_register(bd, part, "PREP boot", i);
+ fs_raw_set_bootfile(part, part->boot_start.bloc,
+ part->boot_start.offset,
+ part->boot_size.bloc,
+ part->boot_size.offset);
+ break;
+ case 0x63: /* GNU Hurd */
+ goto register_nonboot;
+ case 0x83: /* Linux */
+ goto register_nonboot;
+ case 86 ... 87: /* NFTS volume set */
+ /* Not supported by now */
+ break;
+ case 0x8E: /* Linux LVM */
+ /* Not supported by now */
+ break;
+ case 0x96: /* AIX seems to use this to identify ISO 9660 'partitions' */
+ break;
+ case 0xA5: /* FreeBSD */
+ goto register_nonboot;
+ case 0xA6: /* OpenBSD */
+ goto register_nonboot;
+ case 0xA7: /* NeXTSTEP */
+ goto register_nonboot;
+ case 0xA8: /* Darwin UFS */
+ goto register_nonboot;
+ case 0xA9: /* NetBSD */
+ goto register_nonboot;
+ case 0xAB: /* Darwin boot */
+ /* Not supported by now */
+ break;
+ case 0xBE: /* Solaris boot */
+ /* Not supported by now */
+ break;
+ case 0xEB: /* BeOS fs */
+ goto register_nonboot;
+ case 0xFD: /* Linux RAID */
+ /* Not supported by now */
+ break;
+ default:
+ break;
+ register_nonboot:
+ break;
+ }
+ }
+ error:
+ free(buffer);
+
+ return part;
+}