1*eb4cb19dSkjell /* $OpenBSD: part.c,v 1.22 2001/06/23 01:54:38 kjell Exp $ */ 2a1705421Sweingart 3a1705421Sweingart /* 4a1705421Sweingart * Copyright (c) 1997 Tobias Weingartner 5a1705421Sweingart * All rights reserved. 6a1705421Sweingart * 7a1705421Sweingart * Redistribution and use in source and binary forms, with or without 8a1705421Sweingart * modification, are permitted provided that the following conditions 9a1705421Sweingart * are met: 10a1705421Sweingart * 1. Redistributions of source code must retain the above copyright 11a1705421Sweingart * notice, this list of conditions and the following disclaimer. 12a1705421Sweingart * 2. Redistributions in binary form must reproduce the above copyright 13a1705421Sweingart * notice, this list of conditions and the following disclaimer in the 14a1705421Sweingart * documentation and/or other materials provided with the distribution. 15a1705421Sweingart * 3. All advertising materials mentioning features or use of this software 16a1705421Sweingart * must display the following acknowledgement: 17a1705421Sweingart * This product includes software developed by Tobias Weingartner. 18a1705421Sweingart * 4. The name of the author may not be used to endorse or promote products 19a1705421Sweingart * derived from this software without specific prior written permission. 20a1705421Sweingart * 21a1705421Sweingart * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22a1705421Sweingart * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23a1705421Sweingart * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24a1705421Sweingart * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25a1705421Sweingart * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26a1705421Sweingart * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27a1705421Sweingart * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28a1705421Sweingart * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29a1705421Sweingart * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30a1705421Sweingart * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31a1705421Sweingart */ 32a1705421Sweingart 33a1705421Sweingart #include <err.h> 34a1705421Sweingart #include <util.h> 35a1705421Sweingart #include <stdio.h> 36a1705421Sweingart #include <unistd.h> 37a1705421Sweingart #include <sys/fcntl.h> 38a1705421Sweingart #include <sys/types.h> 39a1705421Sweingart #include <sys/stat.h> 40a1705421Sweingart #include <sys/disklabel.h> 41a1705421Sweingart #include <machine/param.h> 42a1705421Sweingart #include "disk.h" 43a1705421Sweingart #include "misc.h" 44a1705421Sweingart #include "mbr.h" 45a1705421Sweingart 46a1705421Sweingart 476c2b1c19Smickey static const struct part_type { 48a1705421Sweingart int type; 496c2b1c19Smickey char sname[14]; 504b464610Sderaadt char *lname; 51a1705421Sweingart } part_types[] = { 524b464610Sderaadt { 0x00, "unused ", "unused"}, 534b464610Sderaadt { 0x01, "DOS FAT-12 ", "Primary DOS with 12 bit FAT"}, 544b464610Sderaadt { 0x02, "XENIX / ", "XENIX / filesystem"}, 554b464610Sderaadt { 0x03, "XENIX /usr ", "XENIX /usr filesystem"}, 564b464610Sderaadt { 0x04, "DOS FAT-16 ", "Primary DOS with 16 bit FAT"}, 574b464610Sderaadt { 0x05, "Extended DOS", "Extended DOS"}, 584b464610Sderaadt { 0x06, "DOS > 32MB ", "Primary 'big' DOS (> 32MB)"}, 59f3f2107eSderaadt { 0x07, "HPFS/QNX/AUX", "OS/2 HPFS, QNX-2 or Advanced UNIX"}, 604b464610Sderaadt { 0x08, "AIX fs ", "AIX filesystem"}, 614b464610Sderaadt { 0x09, "AIX/Coherent", "AIX boot partition or Coherent"}, 624b464610Sderaadt { 0x0A, "OS/2 Bootmgr", "OS/2 Boot Manager or OPUS"}, 634b464610Sderaadt { 0x0B, "Win95 FAT-32", "Primary Win95 w/ 32-bit FAT"}, 64c3e3230dSderaadt { 0x0C, "Win95 FAT32L", "Primary Win95 w/ 32-bit FAT LBA-mapped"}, 654b464610Sderaadt { 0x0E, "DOS FAT-16 ", "Primary DOS w/ 16-bit FAT, CHS-mapped"}, 66c3e3230dSderaadt { 0x0F, "Extended LBA", "Extended DOS LBA-mapped"}, 674b464610Sderaadt { 0x10, "OPUS ", "OPUS"}, 684b464610Sderaadt { 0x12, "Compaq Diag.", "Compaq Diagnostics"}, 69a34f1fa7Smarkus { 0x39, "Plan 9 ", "Plan 9"}, 704b464610Sderaadt { 0x40, "VENIX 286 ", "VENIX 286"}, 71f3f2107eSderaadt { 0x4d, "QNX 4.2 Pri ", "QNX 4.2 Primary"}, 72f3f2107eSderaadt { 0x4e, "QNX 4.2 Sec ", "QNX 4.2 Secondary"}, 73f3f2107eSderaadt { 0x4f, "QNX 4.2 Ter ", "QNX 4.2 Tertiary"}, 744b464610Sderaadt { 0x50, "DM ", "DM"}, 754b464610Sderaadt { 0x51, "DM ", "DM"}, 764b464610Sderaadt { 0x52, "CP/M or SysV", "CP/M or Microport SysV/AT"}, 774b464610Sderaadt { 0x54, "Ontrack ", "Ontrack"}, 784b464610Sderaadt { 0x56, "GB ", "GB"}, 794b464610Sderaadt { 0x61, "Speed ", "Speed"}, 804b464610Sderaadt { 0x63, "ISC, HURD, *", "ISC, System V/386, GNU HURD or Mach"}, 814b464610Sderaadt { 0x64, "Netware 2.xx", "Novell Netware 2.xx"}, 824b464610Sderaadt { 0x65, "Netware 3.xx", "Novell Netware 3.xx"}, 834b464610Sderaadt { 0x75, "PCIX ", "PCIX"}, 844b464610Sderaadt { 0x80, "Minix (old) ", "Minix 1.1 ... 1.4a"}, 854b464610Sderaadt { 0x81, "Minix (new) ", "Minix 1.4b ... 1.5.10"}, 864b464610Sderaadt { 0x82, "Linux swap ", "Linux swap"}, 874b464610Sderaadt { 0x83, "Linux files*", "Linux filesystem"}, 884b464610Sderaadt { 0x93, "Amoeba file*", "Amoeba filesystem"}, 894b464610Sderaadt { 0x94, "Amoeba BBT ", "Amoeba bad block table"}, 90bdb6a33cSmarkus { 0x9f, "BSDI ", "BSDI BSD/OS"}, 913addffc7Sian { 0xA0, "NotebookSave", "Phoenix NoteBIOS save-to-disk"}, 9258fe3b3aSderaadt { 0xA5, "FreeBSD ", "FreeBSD"}, 934b464610Sderaadt { 0xA6, "OpenBSD ", "OpenBSD"}, 944b464610Sderaadt { 0xA7, "NEXTSTEP ", "NEXTSTEP"}, 9558fe3b3aSderaadt { 0xA9, "NetBSD ", "NetBSD"}, 964b464610Sderaadt { 0xB7, "BSDI filesy*", "BSDI BSD/386 filesystem"}, 974b464610Sderaadt { 0xB8, "BSDI swap ", "BSDI BSD/386 swap"}, 984b464610Sderaadt { 0xDB, "CPM/C.DOS/C*", "Concurrent CPM or C.DOS or CTOS"}, 994b464610Sderaadt { 0xE1, "Speed ", "Speed"}, 1004b464610Sderaadt { 0xE3, "Speed ", "Speed"}, 1014b464610Sderaadt { 0xE4, "Speed ", "Speed"}, 102092b495fSderaadt { 0xEB, "BeOS/i386 ", "BeOS for Intel"}, 1034b464610Sderaadt { 0xF1, "Speed ", "Speed"}, 1044b464610Sderaadt { 0xF2, "DOS 3.3+ Sec", "DOS 3.3+ Secondary"}, 1054b464610Sderaadt { 0xF4, "Speed ", "Speed"}, 1064b464610Sderaadt { 0xFF, "BBT ", "BBT (Bad Blocks Table)"}, 107a1705421Sweingart }; 108a1705421Sweingart 1094b464610Sderaadt void 1104b464610Sderaadt PRT_printall() 1114b464610Sderaadt { 112d20bdfc6Skrw int i, idrows; 113d20bdfc6Skrw 114d20bdfc6Skrw idrows = ((sizeof(part_types)/sizeof(struct part_type))+3)/4; 1154b464610Sderaadt 116c2ad5584Sderaadt printf("Choose from the following Partition id values:\n"); 117d20bdfc6Skrw for (i = 0; i < idrows; i++) { 118d20bdfc6Skrw printf("%02X %s %02X %s %02X %s" 119d20bdfc6Skrw , part_types[i ].type, part_types[i ].sname 120d20bdfc6Skrw , part_types[i+idrows ].type, part_types[i+idrows ].sname 121d20bdfc6Skrw , part_types[i+idrows*2].type, part_types[i+idrows*2].sname 122d20bdfc6Skrw ); 123d20bdfc6Skrw if ((i+idrows*3) < (sizeof(part_types)/sizeof(struct part_type))) { 124d20bdfc6Skrw printf(" %02X %s\n" 125d20bdfc6Skrw , part_types[i+idrows*3].type, part_types[i+idrows*3].sname ); 1264b464610Sderaadt } 127d20bdfc6Skrw else 1284b464610Sderaadt printf( "\n" ); 1294b464610Sderaadt } 130d20bdfc6Skrw } 131a1705421Sweingart 1326c2b1c19Smickey const char * 133a1705421Sweingart PRT_ascii_id(id) 134a1705421Sweingart int id; 135a1705421Sweingart { 136a1705421Sweingart static char unknown[] = "<Unknown ID>"; 137a1705421Sweingart int i; 138a1705421Sweingart 139a1705421Sweingart for (i = 0; i < sizeof(part_types)/sizeof(struct part_type); i++) { 140a1705421Sweingart if (part_types[i].type == id) 1414b464610Sderaadt return (part_types[i].sname); 142a1705421Sweingart } 143a1705421Sweingart 144a1705421Sweingart return (unknown); 145a1705421Sweingart } 146a1705421Sweingart 147a1705421Sweingart void 1480d5049c6Smickey PRT_parse(disk, prt, offset, reloff, partn, pn) 1494ed7cd7eSrahnds disk_t *disk; 150a1705421Sweingart void *prt; 151ca2e86e1Sprovos off_t offset; 152ca2e86e1Sprovos off_t reloff; 153a1705421Sweingart prt_t *partn; 1540d5049c6Smickey int pn; 155a1705421Sweingart { 156a1705421Sweingart unsigned char *p = prt; 157ca2e86e1Sprovos off_t off; 158a1705421Sweingart 159a1705421Sweingart partn->flag = *p++; 160a1705421Sweingart partn->shead = *p++; 161ca2e86e1Sprovos 162a1705421Sweingart partn->ssect = (*p) & 0x3F; 163a1705421Sweingart partn->scyl = ((*p << 2) & 0xFF00) | (*(p+1)); 164a1705421Sweingart p += 2; 165a1705421Sweingart 166a1705421Sweingart partn->id = *p++; 167a1705421Sweingart partn->ehead = *p++; 168a1705421Sweingart partn->esect = (*p) & 0x3F; 169a1705421Sweingart partn->ecyl = ((*p << 2) & 0xFF00) | (*(p+1)); 170a1705421Sweingart p += 2; 171a1705421Sweingart 172c3e3230dSderaadt if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL)) 173c3e3230dSderaadt off = reloff; 174c3e3230dSderaadt else 175c3e3230dSderaadt off = offset; 176ca2e86e1Sprovos 177ca2e86e1Sprovos partn->bs = getlong(p) + off; 178a1705421Sweingart partn->ns = getlong(p+4); 1794ed7cd7eSrahnds 1800d5049c6Smickey PRT_fix_CHS(disk, partn, pn); 1814ed7cd7eSrahnds } 182a1705421Sweingart 1834ed7cd7eSrahnds int 1844ed7cd7eSrahnds PRT_check_chs(partn) 1854ed7cd7eSrahnds prt_t *partn; 1864ed7cd7eSrahnds { 1874ed7cd7eSrahnds if ( (partn->shead > 255) || 1884ed7cd7eSrahnds (partn->ssect >63) || 1894ed7cd7eSrahnds (partn->scyl > 1023) || 1904ed7cd7eSrahnds (partn->ehead >255) || 1914ed7cd7eSrahnds (partn->esect >63) || 1924ed7cd7eSrahnds (partn->ecyl > 1023) ) 1934ed7cd7eSrahnds { 1944ed7cd7eSrahnds return 0; 1954ed7cd7eSrahnds } 1964ed7cd7eSrahnds return 1; 1974ed7cd7eSrahnds } 198a1705421Sweingart void 199ca2e86e1Sprovos PRT_make(partn, offset, reloff, prt) 200a1705421Sweingart prt_t *partn; 201ca2e86e1Sprovos off_t offset; 202ca2e86e1Sprovos off_t reloff; 203a1705421Sweingart void *prt; 204a1705421Sweingart { 205a1705421Sweingart unsigned char *p = prt; 206c3e3230dSderaadt prt_t tmp; 207c3e3230dSderaadt off_t off; 208c3e3230dSderaadt 209c3e3230dSderaadt tmp.shead = partn->shead; 210c3e3230dSderaadt tmp.ssect = partn->ssect; 211*eb4cb19dSkjell tmp.scyl = (partn->scyl > 1023)? 1023: partn->scyl; 212c3e3230dSderaadt tmp.ehead = partn->ehead; 213c3e3230dSderaadt tmp.esect = partn->ssect; 214*eb4cb19dSkjell tmp.ecyl = (partn->ecyl > 1023)? 1023: partn->ecyl; 215c3e3230dSderaadt if (!PRT_check_chs(partn) && PRT_check_chs(&tmp)) { 216c3e3230dSderaadt partn->shead = tmp.shead; 217c3e3230dSderaadt partn->ssect = tmp.ssect; 218c3e3230dSderaadt partn->scyl = tmp.scyl; 219c3e3230dSderaadt partn->ehead = tmp.ehead; 220c3e3230dSderaadt partn->esect = tmp.esect; 221c3e3230dSderaadt partn->ecyl = tmp.ecyl; 222c3e3230dSderaadt printf("Cylinder values are modified to fit in CHS.\n"); 223c3e3230dSderaadt } 224c3e3230dSderaadt if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL)) 225c3e3230dSderaadt off = reloff; 226c3e3230dSderaadt else 227c3e3230dSderaadt off = offset; 228a1705421Sweingart 2294ed7cd7eSrahnds if (PRT_check_chs(partn)) { 230a1705421Sweingart *p++ = partn->flag & 0xFF; 2314ed7cd7eSrahnds 232a1705421Sweingart *p++ = partn->shead & 0xFF; 233a1705421Sweingart *p++ = (partn->ssect & 0x3F) | ((partn->scyl & 0x300) >> 2); 234a1705421Sweingart *p++ = partn->scyl & 0xFF; 235a1705421Sweingart 236a1705421Sweingart *p++ = partn->id & 0xFF; 237a1705421Sweingart 238a1705421Sweingart *p++ = partn->ehead & 0xFF; 239a1705421Sweingart *p++ = (partn->esect & 0x3F) | ((partn->ecyl & 0x300) >> 2); 240a1705421Sweingart *p++ = partn->ecyl & 0xFF; 2414ed7cd7eSrahnds } else { 2424ed7cd7eSrahnds /* should this really keep flag, id and set others to 0xff? */ 2434ed7cd7eSrahnds *p++ = partn->flag & 0xFF; 2444ed7cd7eSrahnds *p++ = 0xFF; 2454ed7cd7eSrahnds *p++ = 0xFF; 2464ed7cd7eSrahnds *p++ = 0xFF; 2474ed7cd7eSrahnds *p++ = partn->id & 0xFF; 2484ed7cd7eSrahnds *p++ = 0xFF; 2494ed7cd7eSrahnds *p++ = 0xFF; 2504ed7cd7eSrahnds *p++ = 0xFF; 2514ed7cd7eSrahnds printf("Warning CHS values out of bounds only saving LBA values\n"); 2524ed7cd7eSrahnds } 253a1705421Sweingart 254ca2e86e1Sprovos putlong(p, partn->bs - off); 255a1705421Sweingart putlong(p+4, partn->ns); 256a1705421Sweingart } 257a1705421Sweingart 258a1705421Sweingart void 259a1705421Sweingart PRT_print(num, partn) 260a1705421Sweingart int num; 261a1705421Sweingart prt_t *partn; 262a1705421Sweingart { 263a1705421Sweingart 264a1705421Sweingart if (partn == NULL) { 265a1705421Sweingart printf(" Starting Ending\n"); 266a1705421Sweingart printf(" #: id cyl hd sec - cyl hd sec [ start - size]\n"); 2676c2b1c19Smickey printf("------------------------------------------------------------------------\n"); 268a1705421Sweingart } else { 2696c2b1c19Smickey printf("%c%1d: %.2X %4d %3d %3d - %4d %3d %3d [%10d - %10d] %s\n", 270a1705421Sweingart (partn->flag == 0x80)?'*':' ', 271a1705421Sweingart num, partn->id, 272a1705421Sweingart partn->scyl, partn->shead, partn->ssect, 273a1705421Sweingart partn->ecyl, partn->ehead, partn->esect, 274a1705421Sweingart partn->bs, partn->ns, 275a1705421Sweingart PRT_ascii_id(partn->id)); 276a1705421Sweingart } 277a1705421Sweingart } 278a1705421Sweingart 279a1705421Sweingart void 2800d5049c6Smickey PRT_fix_BN(disk, part, pn) 281a1705421Sweingart disk_t *disk; 282a1705421Sweingart prt_t *part; 2830d5049c6Smickey int pn; 284a1705421Sweingart { 285a1705421Sweingart int spt, tpc, spc; 286a1705421Sweingart int start = 0; 287a1705421Sweingart int end = 0; 288a1705421Sweingart 289*eb4cb19dSkjell /* Zero out entry if not used */ 290*eb4cb19dSkjell if (part->id == DOSPTYP_UNUSED ) { 291*eb4cb19dSkjell memset(part, 0, sizeof(*part)); 292*eb4cb19dSkjell return; 293*eb4cb19dSkjell } 294*eb4cb19dSkjell 295a1705421Sweingart /* Disk metrics */ 2964b464610Sderaadt spt = disk->real->sectors; 2974b464610Sderaadt tpc = disk->real->heads; 298a1705421Sweingart spc = spt * tpc; 299a1705421Sweingart 300a1705421Sweingart start += part->scyl * spc; 301a1705421Sweingart start += part->shead * spt; 302a1705421Sweingart start += part->ssect - 1; 303a1705421Sweingart 304a1705421Sweingart end += part->ecyl * spc; 305a1705421Sweingart end += part->ehead * spt; 306a1705421Sweingart end += part->esect - 1; 307a1705421Sweingart 308a1705421Sweingart /* XXX - Should handle this... */ 309a1705421Sweingart if (start > end) 3100d5049c6Smickey warn("Start of partition #%d after end!", pn); 311a1705421Sweingart 312a1705421Sweingart part->bs = start; 313a1705421Sweingart part->ns = (end - start) + 1; 314a1705421Sweingart } 315a1705421Sweingart 316a1705421Sweingart void 3170d5049c6Smickey PRT_fix_CHS(disk, part, pn) 318a1705421Sweingart disk_t *disk; 319a1705421Sweingart prt_t *part; 3200d5049c6Smickey int pn; 321a1705421Sweingart { 322a1705421Sweingart int spt, tpc, spc; 323a1705421Sweingart int start, end, size; 324a1705421Sweingart int cyl, head, sect; 325a1705421Sweingart 326*eb4cb19dSkjell /* Zero out entry if not used */ 327*eb4cb19dSkjell if (part->id == DOSPTYP_UNUSED ) { 328*eb4cb19dSkjell memset(part, 0, sizeof(*part)); 329*eb4cb19dSkjell return; 330*eb4cb19dSkjell } 331*eb4cb19dSkjell 332a1705421Sweingart /* Disk metrics */ 3334b464610Sderaadt spt = disk->real->sectors; 3344b464610Sderaadt tpc = disk->real->heads; 335a1705421Sweingart spc = spt * tpc; 336a1705421Sweingart 337a1705421Sweingart start = part->bs; 338a1705421Sweingart size = part->ns; 339a1705421Sweingart end = (start + size) - 1; 340a1705421Sweingart 341a1705421Sweingart /* Figure out starting CHS values */ 342a1705421Sweingart cyl = (start / spc); start -= (cyl * spc); 343a1705421Sweingart head = (start / spt); start -= (head * spt); 344a1705421Sweingart sect = (start + 1); 345a1705421Sweingart 346c3e3230dSderaadt if (cyl > 1023) { 347c3e3230dSderaadt cyl = 1023; 3480d5049c6Smickey printf("Only LBA values are valid in starting cylinder for partition #%d.\n", pn); 349c3e3230dSderaadt } 350a1705421Sweingart part->scyl = cyl; 351a1705421Sweingart part->shead = head; 352a1705421Sweingart part->ssect = sect; 353a1705421Sweingart 354a1705421Sweingart /* Figure out ending CHS values */ 355a1705421Sweingart cyl = (end / spc); end -= (cyl * spc); 356a1705421Sweingart head = (end / spt); end -= (head * spt); 357a1705421Sweingart sect = (end + 1); 358a1705421Sweingart 359c3e3230dSderaadt if (cyl > 1023) { 360c3e3230dSderaadt cyl = 1023; 3610d5049c6Smickey printf("Only LBA values are valid in ending cylinder for partition #%d.\n", pn); 362c3e3230dSderaadt } 363a1705421Sweingart part->ecyl = cyl; 364a1705421Sweingart part->ehead = head; 365a1705421Sweingart part->esect = sect; 366a1705421Sweingart } 367a1705421Sweingart 368