Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openhackware / src / libpart / apple.c
diff --git a/qemu/roms/openhackware/src/libpart/apple.c b/qemu/roms/openhackware/src/libpart/apple.c
new file mode 100644 (file)
index 0000000..1d72f67
--- /dev/null
@@ -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;
+
+}