diff options
Diffstat (limited to 'qemu/roms/openhackware/src/libpart')
-rw-r--r-- | qemu/roms/openhackware/src/libpart/apple.c | 314 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libpart/core.c | 288 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libpart/isofs.c | 257 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libpart/libpart.h | 67 | ||||
-rw-r--r-- | qemu/roms/openhackware/src/libpart/prep.c | 216 |
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; +} |