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