diff options
Diffstat (limited to 'qemu/roms/openhackware/src/libpart/apple.c')
-rw-r--r-- | qemu/roms/openhackware/src/libpart/apple.c | 314 |
1 files changed, 314 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; + +} |