15b81b6b3SRodney W. Grimes /* 25b81b6b3SRodney W. Grimes * Mach Operating System 35b81b6b3SRodney W. Grimes * Copyright (c) 1992 Carnegie Mellon University 45b81b6b3SRodney W. Grimes * All Rights Reserved. 55b81b6b3SRodney W. Grimes * 65b81b6b3SRodney W. Grimes * Permission to use, copy, modify and distribute this software and its 75b81b6b3SRodney W. Grimes * documentation is hereby granted, provided that both the copyright 85b81b6b3SRodney W. Grimes * notice and this permission notice appear in all copies of the 95b81b6b3SRodney W. Grimes * software, derivative works or modified versions, and any portions 105b81b6b3SRodney W. Grimes * thereof, and that both notices appear in supporting documentation. 115b81b6b3SRodney W. Grimes * 125b81b6b3SRodney W. Grimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 135b81b6b3SRodney W. Grimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 145b81b6b3SRodney W. Grimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 155b81b6b3SRodney W. Grimes * 165b81b6b3SRodney W. Grimes * Carnegie Mellon requests users of this software to return to 175b81b6b3SRodney W. Grimes * 185b81b6b3SRodney W. Grimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 195b81b6b3SRodney W. Grimes * School of Computer Science 205b81b6b3SRodney W. Grimes * Carnegie Mellon University 215b81b6b3SRodney W. Grimes * Pittsburgh PA 15213-3890 225b81b6b3SRodney W. Grimes * 235b81b6b3SRodney W. Grimes * any improvements or extensions that they make and grant Carnegie Mellon 245b81b6b3SRodney W. Grimes * the rights to redistribute these changes. 255b81b6b3SRodney W. Grimes */ 265b81b6b3SRodney W. Grimes 27c69284caSDavid E. O'Brien #include <sys/cdefs.h> 28c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$"); 29d98b1668SPhilippe Charnier 303f8ba8b5SPoul-Henning Kamp #include <sys/disk.h> 315b81b6b3SRodney W. Grimes #include <sys/disklabel.h> 323bb24c35SPoul-Henning Kamp #include <sys/diskmbr.h> 331a03d6d5SPoul-Henning Kamp #include <sys/endian.h> 34df77f711SJoerg Wunsch #include <sys/param.h> 355b81b6b3SRodney W. Grimes #include <sys/stat.h> 36df77f711SJoerg Wunsch #include <sys/mount.h> 37d98b1668SPhilippe Charnier #include <ctype.h> 385b81b6b3SRodney W. Grimes #include <fcntl.h> 39d98b1668SPhilippe Charnier #include <err.h> 40d98b1668SPhilippe Charnier #include <errno.h> 41de78c288SPoul-Henning Kamp #include <libgeom.h> 42df77f711SJoerg Wunsch #include <paths.h> 43df77f711SJoerg Wunsch #include <regex.h> 44689fee87SBruce Evans #include <stdint.h> 45d98b1668SPhilippe Charnier #include <stdio.h> 46d98b1668SPhilippe Charnier #include <stdlib.h> 47d98b1668SPhilippe Charnier #include <string.h> 484be1e61bSAlexander Langer #include <unistd.h> 495b81b6b3SRodney W. Grimes 505b81b6b3SRodney W. Grimes int iotest; 515b81b6b3SRodney W. Grimes 525b81b6b3SRodney W. Grimes #define LBUF 100 535b81b6b3SRodney W. Grimes static char lbuf[LBUF]; 545b81b6b3SRodney W. Grimes 555b81b6b3SRodney W. Grimes /* 565b81b6b3SRodney W. Grimes * 575b81b6b3SRodney W. Grimes * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 585b81b6b3SRodney W. Grimes * 595b81b6b3SRodney W. Grimes * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 605b81b6b3SRodney W. Grimes * Copyright (c) 1989 Robert. V. Baron 615b81b6b3SRodney W. Grimes * Created. 625b81b6b3SRodney W. Grimes */ 635b81b6b3SRodney W. Grimes 645b81b6b3SRodney W. Grimes #define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 655b81b6b3SRodney W. Grimes 665b81b6b3SRodney W. Grimes #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 675b81b6b3SRodney W. Grimes 687cb29d33SSøren Schmidt #define MAX_SEC_SIZE 2048 /* maximum section size that is supported */ 697cb29d33SSøren Schmidt #define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 70041b8b00SPoul-Henning Kamp static int secsize = 0; /* the sensed sector size */ 715b81b6b3SRodney W. Grimes 72041b8b00SPoul-Henning Kamp static char *disk; 73e3038c6eSJoerg Wunsch 74041b8b00SPoul-Henning Kamp static int cyls, sectors, heads, cylsecs, disksecs; 755b81b6b3SRodney W. Grimes 76041b8b00SPoul-Henning Kamp struct mboot { 7785c2cf30SJohn Baldwin unsigned char *bootinst; /* boot code */ 7885c2cf30SJohn Baldwin off_t bootinst_size; 791a03d6d5SPoul-Henning Kamp struct dos_partition parts[NDOSPART]; 805b81b6b3SRodney W. Grimes }; 81041b8b00SPoul-Henning Kamp 82041b8b00SPoul-Henning Kamp static struct mboot mboot; 83de78c288SPoul-Henning Kamp static int fd; 84f353c761SPoul-Henning Kamp 855b81b6b3SRodney W. Grimes #define ACTIVE 0x80 865b81b6b3SRodney W. Grimes 87041b8b00SPoul-Henning Kamp static uint dos_cyls; 88041b8b00SPoul-Henning Kamp static uint dos_heads; 89041b8b00SPoul-Henning Kamp static uint dos_sectors; 90041b8b00SPoul-Henning Kamp static uint dos_cylsecs; 915b81b6b3SRodney W. Grimes 925b81b6b3SRodney W. Grimes #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 935b81b6b3SRodney W. Grimes #define DOSCYL(c) (c & 0xff) 945b81b6b3SRodney W. Grimes 95f46af505SJordan K. Hubbard #define MAX_ARGS 10 96f46af505SJordan K. Hubbard 97f46af505SJordan K. Hubbard static int current_line_number; 98f46af505SJordan K. Hubbard 99f46af505SJordan K. Hubbard static int geom_processed = 0; 100f46af505SJordan K. Hubbard static int part_processed = 0; 101f46af505SJordan K. Hubbard static int active_processed = 0; 102f46af505SJordan K. Hubbard 103f46af505SJordan K. Hubbard typedef struct cmd { 104f46af505SJordan K. Hubbard char cmd; 105f46af505SJordan K. Hubbard int n_args; 106f46af505SJordan K. Hubbard struct arg { 107f46af505SJordan K. Hubbard char argtype; 108f46af505SJordan K. Hubbard int arg_val; 109f46af505SJordan K. Hubbard } args[MAX_ARGS]; 110f46af505SJordan K. Hubbard } CMD; 111f46af505SJordan K. Hubbard 11226721a89SRobert Nordier static int B_flag = 0; /* replace boot code */ 11310b0ee93SWarner Losh static int I_flag = 0; /* use entire disk for FreeBSD */ 1145b81b6b3SRodney W. Grimes static int a_flag = 0; /* set active partition */ 11526721a89SRobert Nordier static char *b_flag = NULL; /* path to boot code */ 1165b81b6b3SRodney W. Grimes static int i_flag = 0; /* replace partition data */ 117a61d9186SDavid E. O'Brien static int q_flag = 0; /* Be quiet */ 1185b81b6b3SRodney W. Grimes static int u_flag = 0; /* update partition data */ 11910b0ee93SWarner Losh static int s_flag = 0; /* Print a summary and exit */ 12005a213f1STom Rhodes static int t_flag = 0; /* test only */ 121f46af505SJordan K. Hubbard static char *f_flag = NULL; /* Read config info from file */ 122f46af505SJordan K. Hubbard static int v_flag = 0; /* Be verbose */ 1237914c60fSMaxim Konovalov static int print_config_flag = 0; 1245b81b6b3SRodney W. Grimes 12522fccf5cSLuigi Rizzo /* 12622fccf5cSLuigi Rizzo * A list of partition types, probably outdated. 12722fccf5cSLuigi Rizzo */ 12822fccf5cSLuigi Rizzo static const char *const part_types[256] = { 12922fccf5cSLuigi Rizzo [0x00] = "unused", 13022fccf5cSLuigi Rizzo [0x01] = "Primary DOS with 12 bit FAT", 13122fccf5cSLuigi Rizzo [0x02] = "XENIX / file system", 13222fccf5cSLuigi Rizzo [0x03] = "XENIX /usr file system", 13322fccf5cSLuigi Rizzo [0x04] = "Primary DOS with 16 bit FAT (< 32MB)", 13422fccf5cSLuigi Rizzo [0x05] = "Extended DOS", 13522fccf5cSLuigi Rizzo [0x06] = "Primary 'big' DOS (>= 32MB)", 13622fccf5cSLuigi Rizzo [0x07] = "OS/2 HPFS, NTFS, QNX-2 (16 bit) or Advanced UNIX", 13722fccf5cSLuigi Rizzo [0x08] = "AIX file system or SplitDrive", 13822fccf5cSLuigi Rizzo [0x09] = "AIX boot partition or Coherent", 13922fccf5cSLuigi Rizzo [0x0A] = "OS/2 Boot Manager, OPUS or Coherent swap", 14022fccf5cSLuigi Rizzo [0x0B] = "DOS or Windows 95 with 32 bit FAT", 14122fccf5cSLuigi Rizzo [0x0C] = "DOS or Windows 95 with 32 bit FAT (LBA)", 14222fccf5cSLuigi Rizzo [0x0E] = "Primary 'big' DOS (>= 32MB, LBA)", 14322fccf5cSLuigi Rizzo [0x0F] = "Extended DOS (LBA)", 14422fccf5cSLuigi Rizzo [0x10] = "OPUS", 14522fccf5cSLuigi Rizzo [0x11] = "OS/2 BM: hidden DOS with 12-bit FAT", 14622fccf5cSLuigi Rizzo [0x12] = "Compaq diagnostics", 14722fccf5cSLuigi Rizzo [0x14] = "OS/2 BM: hidden DOS with 16-bit FAT (< 32MB)", 14822fccf5cSLuigi Rizzo [0x16] = "OS/2 BM: hidden DOS with 16-bit FAT (>= 32MB)", 14922fccf5cSLuigi Rizzo [0x17] = "OS/2 BM: hidden IFS (e.g. HPFS)", 15022fccf5cSLuigi Rizzo [0x18] = "AST Windows swapfile", 15122fccf5cSLuigi Rizzo [0x24] = "NEC DOS", 15222fccf5cSLuigi Rizzo [0x3C] = "PartitionMagic recovery", 15322fccf5cSLuigi Rizzo [0x39] = "plan9", 15422fccf5cSLuigi Rizzo [0x40] = "VENIX 286", 15522fccf5cSLuigi Rizzo [0x41] = "Linux/MINIX (sharing disk with DRDOS)", 15622fccf5cSLuigi Rizzo [0x42] = "SFS or Linux swap (sharing disk with DRDOS)", 15722fccf5cSLuigi Rizzo [0x43] = "Linux native (sharing disk with DRDOS)", 15822fccf5cSLuigi Rizzo [0x4D] = "QNX 4.2 Primary", 15922fccf5cSLuigi Rizzo [0x4E] = "QNX 4.2 Secondary", 16022fccf5cSLuigi Rizzo [0x4F] = "QNX 4.2 Tertiary", 16122fccf5cSLuigi Rizzo [0x50] = "DM (disk manager)", 16222fccf5cSLuigi Rizzo [0x51] = "DM6 Aux1 (or Novell)", 16322fccf5cSLuigi Rizzo [0x52] = "CP/M or Microport SysV/AT", 16422fccf5cSLuigi Rizzo [0x53] = "DM6 Aux3", 16522fccf5cSLuigi Rizzo [0x54] = "DM6", 16622fccf5cSLuigi Rizzo [0x55] = "EZ-Drive (disk manager)", 16722fccf5cSLuigi Rizzo [0x56] = "Golden Bow (disk manager)", 16822fccf5cSLuigi Rizzo [0x5c] = "Priam Edisk (disk manager)", /* according to S. Widlake */ 16922fccf5cSLuigi Rizzo [0x61] = "SpeedStor", 17022fccf5cSLuigi Rizzo [0x63] = "System V/386 (such as ISC UNIX), GNU HURD or Mach", 17122fccf5cSLuigi Rizzo [0x64] = "Novell Netware/286 2.xx", 17222fccf5cSLuigi Rizzo [0x65] = "Novell Netware/386 3.xx", 17322fccf5cSLuigi Rizzo [0x70] = "DiskSecure Multi-Boot", 17422fccf5cSLuigi Rizzo [0x75] = "PCIX", 17522fccf5cSLuigi Rizzo [0x77] = "QNX4.x", 17622fccf5cSLuigi Rizzo [0x78] = "QNX4.x 2nd part", 17722fccf5cSLuigi Rizzo [0x79] = "QNX4.x 3rd part", 17822fccf5cSLuigi Rizzo [0x80] = "Minix until 1.4a", 17922fccf5cSLuigi Rizzo [0x81] = "Minix since 1.4b, early Linux partition or Mitac disk manager", 18022fccf5cSLuigi Rizzo [0x82] = "Linux swap or Solaris x86", 18122fccf5cSLuigi Rizzo [0x83] = "Linux native", 18222fccf5cSLuigi Rizzo [0x84] = "OS/2 hidden C: drive", 18322fccf5cSLuigi Rizzo [0x85] = "Linux extended", 18422fccf5cSLuigi Rizzo [0x86] = "NTFS volume set??", 18522fccf5cSLuigi Rizzo [0x87] = "NTFS volume set??", 18622fccf5cSLuigi Rizzo [0x93] = "Amoeba file system", 18722fccf5cSLuigi Rizzo [0x94] = "Amoeba bad block table", 18822fccf5cSLuigi Rizzo [0x9F] = "BSD/OS", 18922fccf5cSLuigi Rizzo [0xA0] = "Suspend to Disk", 19022fccf5cSLuigi Rizzo [0xA5] = "FreeBSD/NetBSD/386BSD", 19122fccf5cSLuigi Rizzo [0xA6] = "OpenBSD", 19222fccf5cSLuigi Rizzo [0xA7] = "NeXTSTEP", 19322fccf5cSLuigi Rizzo [0xA9] = "NetBSD", 19422fccf5cSLuigi Rizzo [0xAC] = "IBM JFS", 19522fccf5cSLuigi Rizzo [0xAF] = "HFS+", 19622fccf5cSLuigi Rizzo [0xB7] = "BSDI BSD/386 file system", 19722fccf5cSLuigi Rizzo [0xB8] = "BSDI BSD/386 swap", 19822fccf5cSLuigi Rizzo [0xBE] = "Solaris x86 boot", 19922fccf5cSLuigi Rizzo [0xBF] = "Solaris x86 (new)", 20022fccf5cSLuigi Rizzo [0xC1] = "DRDOS/sec with 12-bit FAT", 20122fccf5cSLuigi Rizzo [0xC4] = "DRDOS/sec with 16-bit FAT (< 32MB)", 20222fccf5cSLuigi Rizzo [0xC6] = "DRDOS/sec with 16-bit FAT (>= 32MB)", 20322fccf5cSLuigi Rizzo [0xC7] = "Syrinx", 20422fccf5cSLuigi Rizzo [0xDB] = "CP/M, Concurrent CP/M, Concurrent DOS or CTOS", 20522fccf5cSLuigi Rizzo [0xE1] = "DOS access or SpeedStor with 12-bit FAT extended partition", 20622fccf5cSLuigi Rizzo [0xE3] = "DOS R/O or SpeedStor", 20722fccf5cSLuigi Rizzo [0xE4] = "SpeedStor with 16-bit FAT extended partition < 1024 cyl.", 20822fccf5cSLuigi Rizzo [0xEB] = "BeOS file system", 20922fccf5cSLuigi Rizzo [0xEE] = "EFI GPT", 21022fccf5cSLuigi Rizzo [0xEF] = "EFI System Partition", 21122fccf5cSLuigi Rizzo [0xF1] = "SpeedStor", 21222fccf5cSLuigi Rizzo [0xF2] = "DOS 3.3+ Secondary", 21322fccf5cSLuigi Rizzo [0xF4] = "SpeedStor large partition", 21422fccf5cSLuigi Rizzo [0xFE] = "SpeedStor >1024 cyl. or LANstep", 21522fccf5cSLuigi Rizzo [0xFF] = "Xenix bad blocks table", 2165b81b6b3SRodney W. Grimes }; 2175b81b6b3SRodney W. Grimes 21822fccf5cSLuigi Rizzo static const char * 21922fccf5cSLuigi Rizzo get_type(int t) 22022fccf5cSLuigi Rizzo { 22122fccf5cSLuigi Rizzo const char *ret; 22222fccf5cSLuigi Rizzo 22322fccf5cSLuigi Rizzo ret = (t >= 0 && t <= 255) ? part_types[t] : NULL; 22422fccf5cSLuigi Rizzo return ret ? ret : "unknown"; 22522fccf5cSLuigi Rizzo } 22622fccf5cSLuigi Rizzo 22722fccf5cSLuigi Rizzo 228fbcb16efSLuigi Rizzo static void print_s0(void); 22940905b6eSLuigi Rizzo static void print_part(const struct dos_partition *); 2304be1e61bSAlexander Langer static void init_sector0(unsigned long start); 231f46af505SJordan K. Hubbard static void init_boot(void); 2324be1e61bSAlexander Langer static void change_part(int i); 233041b8b00SPoul-Henning Kamp static void print_params(void); 2344be1e61bSAlexander Langer static void change_active(int which); 235041b8b00SPoul-Henning Kamp static void change_code(void); 236041b8b00SPoul-Henning Kamp static void get_params_to_use(void); 237df77f711SJoerg Wunsch static char *get_rootdisk(void); 23863692187SIan Dowse static void dos(struct dos_partition *partp); 239041b8b00SPoul-Henning Kamp static int open_disk(int flag); 2404be1e61bSAlexander Langer static ssize_t read_disk(off_t sector, void *buf); 241de78c288SPoul-Henning Kamp static int write_disk(off_t sector, void *buf); 242041b8b00SPoul-Henning Kamp static int get_params(void); 243041b8b00SPoul-Henning Kamp static int read_s0(void); 244041b8b00SPoul-Henning Kamp static int write_s0(void); 245041b8b00SPoul-Henning Kamp static int ok(const char *str); 246041b8b00SPoul-Henning Kamp static int decimal(const char *str, int *num, int deflt); 247f46af505SJordan K. Hubbard static int read_config(char *config_file); 248f46af505SJordan K. Hubbard static void reset_boot(void); 249b594e0feSJohn Baldwin static int sanitize_partition(struct dos_partition *); 250d98b1668SPhilippe Charnier static void usage(void); 2514be1e61bSAlexander Langer 2524be1e61bSAlexander Langer int 2534be1e61bSAlexander Langer main(int argc, char *argv[]) 2545b81b6b3SRodney W. Grimes { 25526721a89SRobert Nordier int c, i; 256041b8b00SPoul-Henning Kamp int partition = -1; 257041b8b00SPoul-Henning Kamp struct dos_partition *partp; 2585b81b6b3SRodney W. Grimes 259a61d9186SDavid E. O'Brien while ((c = getopt(argc, argv, "BIab:f:ipqstuv1234")) != -1) 26026721a89SRobert Nordier switch (c) { 26126721a89SRobert Nordier case 'B': 26226721a89SRobert Nordier B_flag = 1; 2634ddd60b9SBrian Somers break; 26410b0ee93SWarner Losh case 'I': 26510b0ee93SWarner Losh I_flag = 1; 26610b0ee93SWarner Losh break; 2675b81b6b3SRodney W. Grimes case 'a': 2685b81b6b3SRodney W. Grimes a_flag = 1; 2695b81b6b3SRodney W. Grimes break; 27012d910e9SRobert Nordier case 'b': 27126721a89SRobert Nordier b_flag = optarg; 27212d910e9SRobert Nordier break; 273f46af505SJordan K. Hubbard case 'f': 27426721a89SRobert Nordier f_flag = optarg; 275f46af505SJordan K. Hubbard break; 2765b81b6b3SRodney W. Grimes case 'i': 2775b81b6b3SRodney W. Grimes i_flag = 1; 2785b81b6b3SRodney W. Grimes break; 2797914c60fSMaxim Konovalov case 'p': 2807914c60fSMaxim Konovalov print_config_flag = 1; 2817914c60fSMaxim Konovalov break; 282a61d9186SDavid E. O'Brien case 'q': 283a61d9186SDavid E. O'Brien q_flag = 1; 284a61d9186SDavid E. O'Brien break; 28510b0ee93SWarner Losh case 's': 28610b0ee93SWarner Losh s_flag = 1; 28710b0ee93SWarner Losh break; 288f46af505SJordan K. Hubbard case 't': 289f46af505SJordan K. Hubbard t_flag = 1; 29026721a89SRobert Nordier break; 29126721a89SRobert Nordier case 'u': 29226721a89SRobert Nordier u_flag = 1; 29326721a89SRobert Nordier break; 294f46af505SJordan K. Hubbard case 'v': 295f46af505SJordan K. Hubbard v_flag = 1; 296f46af505SJordan K. Hubbard break; 29726721a89SRobert Nordier case '1': 29826721a89SRobert Nordier case '2': 29926721a89SRobert Nordier case '3': 30026721a89SRobert Nordier case '4': 30126721a89SRobert Nordier partition = c - '0'; 30226721a89SRobert Nordier break; 3035b81b6b3SRodney W. Grimes default: 304d98b1668SPhilippe Charnier usage(); 3055b81b6b3SRodney W. Grimes } 30626721a89SRobert Nordier if (f_flag || i_flag) 30726721a89SRobert Nordier u_flag = 1; 30826721a89SRobert Nordier if (t_flag) 30926721a89SRobert Nordier v_flag = 1; 31026721a89SRobert Nordier argc -= optind; 31126721a89SRobert Nordier argv += optind; 3125b81b6b3SRodney W. Grimes 313df77f711SJoerg Wunsch if (argc == 0) { 314df77f711SJoerg Wunsch disk = get_rootdisk(); 315df77f711SJoerg Wunsch } else { 316b31e5ae2SUlf Lilleengen disk = g_device_path(argv[0]); 317041b8b00SPoul-Henning Kamp if (disk == NULL) 318c4898ccbSLuigi Rizzo err(1, "unable to get correct path for %s", argv[0]); 319df77f711SJoerg Wunsch } 3205b81b6b3SRodney W. Grimes if (open_disk(u_flag) < 0) 321d98b1668SPhilippe Charnier err(1, "cannot open disk %s", disk); 32285c2cf30SJohn Baldwin 32385c2cf30SJohn Baldwin /* (abu)use mboot.bootinst to probe for the sector size */ 32485c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(MAX_SEC_SIZE)) == NULL) 32585c2cf30SJohn Baldwin err(1, "cannot allocate buffer to determine disk sector size"); 326aee85526SSimon L. B. Nielsen if (read_disk(0, mboot.bootinst) == -1) 327aee85526SSimon L. B. Nielsen errx(1, "could not detect sector size"); 328a12de062SJohn Baldwin free(mboot.bootinst); 329a12de062SJohn Baldwin mboot.bootinst = NULL; 33085c2cf30SJohn Baldwin 3317914c60fSMaxim Konovalov if (print_config_flag) { 3327914c60fSMaxim Konovalov if (read_s0()) 3337914c60fSMaxim Konovalov err(1, "read_s0"); 3347914c60fSMaxim Konovalov 3357914c60fSMaxim Konovalov printf("# %s\n", disk); 3367914c60fSMaxim Konovalov printf("g c%d h%d s%d\n", dos_cyls, dos_heads, dos_sectors); 3377914c60fSMaxim Konovalov 3387914c60fSMaxim Konovalov for (i = 0; i < NDOSPART; i++) { 339c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 3407914c60fSMaxim Konovalov 3417914c60fSMaxim Konovalov if (partp->dp_start == 0 && partp->dp_size == 0) 3427914c60fSMaxim Konovalov continue; 3437914c60fSMaxim Konovalov 3447914c60fSMaxim Konovalov printf("p %d 0x%02x %lu %lu\n", i + 1, partp->dp_typ, 3457914c60fSMaxim Konovalov (u_long)partp->dp_start, (u_long)partp->dp_size); 3467914c60fSMaxim Konovalov 3477914c60fSMaxim Konovalov /* Fill flags for the partition. */ 3487914c60fSMaxim Konovalov if (partp->dp_flag & 0x80) 3497914c60fSMaxim Konovalov printf("a %d\n", i + 1); 3507914c60fSMaxim Konovalov } 3517914c60fSMaxim Konovalov exit(0); 3527914c60fSMaxim Konovalov } 353041b8b00SPoul-Henning Kamp if (s_flag) { 35410b0ee93SWarner Losh if (read_s0()) 35510b0ee93SWarner Losh err(1, "read_s0"); 35610b0ee93SWarner Losh printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, 35710b0ee93SWarner Losh dos_sectors); 35810b0ee93SWarner Losh printf("Part %11s %11s Type Flags\n", "Start", "Size"); 35910b0ee93SWarner Losh for (i = 0; i < NDOSPART; i++) { 360c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 36110b0ee93SWarner Losh if (partp->dp_start == 0 && partp->dp_size == 0) 36210b0ee93SWarner Losh continue; 36310b0ee93SWarner Losh printf("%4d: %11lu %11lu 0x%02x 0x%02x\n", i + 1, 36410b0ee93SWarner Losh (u_long) partp->dp_start, 36510b0ee93SWarner Losh (u_long) partp->dp_size, partp->dp_typ, 36610b0ee93SWarner Losh partp->dp_flag); 36710b0ee93SWarner Losh } 36810b0ee93SWarner Losh exit(0); 36910b0ee93SWarner Losh } 3705b81b6b3SRodney W. Grimes 3715b81b6b3SRodney W. Grimes printf("******* Working on device %s *******\n",disk); 372f46af505SJordan K. Hubbard 373041b8b00SPoul-Henning Kamp if (I_flag) { 374e6fb3ddeSPoul-Henning Kamp read_s0(); 375e6fb3ddeSPoul-Henning Kamp reset_boot(); 376c4898ccbSLuigi Rizzo partp = &mboot.parts[0]; 377e6fb3ddeSPoul-Henning Kamp partp->dp_typ = DOSPTYP_386BSD; 378e6fb3ddeSPoul-Henning Kamp partp->dp_flag = ACTIVE; 379e6fb3ddeSPoul-Henning Kamp partp->dp_start = dos_sectors; 380b594e0feSJohn Baldwin partp->dp_size = (disksecs / dos_cylsecs) * dos_cylsecs - 381b594e0feSJohn Baldwin dos_sectors; 38263692187SIan Dowse dos(partp); 383e6fb3ddeSPoul-Henning Kamp if (v_flag) 384fbcb16efSLuigi Rizzo print_s0(); 38505a213f1STom Rhodes if (!t_flag) 386e6fb3ddeSPoul-Henning Kamp write_s0(); 387e6fb3ddeSPoul-Henning Kamp exit(0); 388e6fb3ddeSPoul-Henning Kamp } 389041b8b00SPoul-Henning Kamp if (f_flag) { 390f46af505SJordan K. Hubbard if (read_s0() || i_flag) 391f46af505SJordan K. Hubbard reset_boot(); 392f46af505SJordan K. Hubbard if (!read_config(f_flag)) 393f46af505SJordan K. Hubbard exit(1); 394f46af505SJordan K. Hubbard if (v_flag) 395fbcb16efSLuigi Rizzo print_s0(); 396f46af505SJordan K. Hubbard if (!t_flag) 397f46af505SJordan K. Hubbard write_s0(); 398041b8b00SPoul-Henning Kamp } else { 3995b81b6b3SRodney W. Grimes if(u_flag) 4005b81b6b3SRodney W. Grimes get_params_to_use(); 4015b81b6b3SRodney W. Grimes else 4025b81b6b3SRodney W. Grimes print_params(); 4035b81b6b3SRodney W. Grimes 4045b81b6b3SRodney W. Grimes if (read_s0()) 405b594e0feSJohn Baldwin init_sector0(dos_sectors); 4065b81b6b3SRodney W. Grimes 4077cb29d33SSøren Schmidt printf("Media sector size is %d\n", secsize); 4085b81b6b3SRodney W. Grimes printf("Warning: BIOS sector numbering starts with sector 1\n"); 4095b81b6b3SRodney W. Grimes printf("Information from DOS bootblock is:\n"); 4105b81b6b3SRodney W. Grimes if (partition == -1) 4114ddd60b9SBrian Somers for (i = 1; i <= NDOSPART; i++) 4125b81b6b3SRodney W. Grimes change_part(i); 4135b81b6b3SRodney W. Grimes else 4145b81b6b3SRodney W. Grimes change_part(partition); 4155b81b6b3SRodney W. Grimes 4165b81b6b3SRodney W. Grimes if (u_flag || a_flag) 4175b81b6b3SRodney W. Grimes change_active(partition); 4185b81b6b3SRodney W. Grimes 41926721a89SRobert Nordier if (B_flag) 42012d910e9SRobert Nordier change_code(); 42112d910e9SRobert Nordier 42226721a89SRobert Nordier if (u_flag || a_flag || B_flag) { 423041b8b00SPoul-Henning Kamp if (!t_flag) { 4245b81b6b3SRodney W. Grimes printf("\nWe haven't changed the partition table yet. "); 4255b81b6b3SRodney W. Grimes printf("This is your last chance.\n"); 426f46af505SJordan K. Hubbard } 427fbcb16efSLuigi Rizzo print_s0(); 428041b8b00SPoul-Henning Kamp if (!t_flag) { 4295b81b6b3SRodney W. Grimes if (ok("Should we write new partition table?")) 4305b81b6b3SRodney W. Grimes write_s0(); 431041b8b00SPoul-Henning Kamp } else { 432f46af505SJordan K. Hubbard printf("\n-t flag specified -- partition table not written.\n"); 433f46af505SJordan K. Hubbard } 434f46af505SJordan K. Hubbard } 435f46af505SJordan K. Hubbard } 4365b81b6b3SRodney W. Grimes 4375b81b6b3SRodney W. Grimes exit(0); 438d98b1668SPhilippe Charnier } 4395b81b6b3SRodney W. Grimes 440d98b1668SPhilippe Charnier static void 441d98b1668SPhilippe Charnier usage() 442d98b1668SPhilippe Charnier { 44326721a89SRobert Nordier fprintf(stderr, "%s%s", 444a61d9186SDavid E. O'Brien "usage: fdisk [-BIaipqstu] [-b bootcode] [-1234] [disk]\n", 44526721a89SRobert Nordier " fdisk -f configfile [-itv] [disk]\n"); 446d98b1668SPhilippe Charnier exit(1); 4475b81b6b3SRodney W. Grimes } 4485b81b6b3SRodney W. Grimes 4494be1e61bSAlexander Langer static void 450fbcb16efSLuigi Rizzo print_s0(void) 4515b81b6b3SRodney W. Grimes { 4525b81b6b3SRodney W. Grimes int i; 4535b81b6b3SRodney W. Grimes 4545b81b6b3SRodney W. Grimes print_params(); 4555b81b6b3SRodney W. Grimes printf("Information from DOS bootblock is:\n"); 45640905b6eSLuigi Rizzo for (i = 1; i <= NDOSPART; i++) { 45740905b6eSLuigi Rizzo printf("%d: ", i); 45840905b6eSLuigi Rizzo print_part(&mboot.parts[i - 1]); 45940905b6eSLuigi Rizzo } 4605b81b6b3SRodney W. Grimes } 4615b81b6b3SRodney W. Grimes 462041b8b00SPoul-Henning Kamp static struct dos_partition mtpart; 4635b81b6b3SRodney W. Grimes 4644be1e61bSAlexander Langer static void 46540905b6eSLuigi Rizzo print_part(const struct dos_partition *partp) 4665b81b6b3SRodney W. Grimes { 467637fe2f7SJustin T. Gibbs u_int64_t part_mb; 4685b81b6b3SRodney W. Grimes 4695b81b6b3SRodney W. Grimes if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 4705b81b6b3SRodney W. Grimes printf("<UNUSED>\n"); 4715b81b6b3SRodney W. Grimes return; 4725b81b6b3SRodney W. Grimes } 473637fe2f7SJustin T. Gibbs /* 474637fe2f7SJustin T. Gibbs * Be careful not to overflow. 475637fe2f7SJustin T. Gibbs */ 476637fe2f7SJustin T. Gibbs part_mb = partp->dp_size; 477637fe2f7SJustin T. Gibbs part_mb *= secsize; 478637fe2f7SJustin T. Gibbs part_mb /= (1024 * 1024); 479978d3bfeSJosef Karthauser printf("sysid %d (%#04x),(%s)\n", partp->dp_typ, partp->dp_typ, 480978d3bfeSJosef Karthauser get_type(partp->dp_typ)); 481689fee87SBruce Evans printf(" start %lu, size %lu (%ju Meg), flag %x%s\n", 482ba198492SBruce Evans (u_long)partp->dp_start, 483ba198492SBruce Evans (u_long)partp->dp_size, 484689fee87SBruce Evans (uintmax_t)part_mb, 485680426beSDavid E. O'Brien partp->dp_flag, 486680426beSDavid E. O'Brien partp->dp_flag == ACTIVE ? " (active)" : ""); 4876580291bSDavid E. O'Brien printf("\tbeg: cyl %d/ head %d/ sector %d;\n\tend: cyl %d/ head %d/ sector %d\n" 4885b81b6b3SRodney W. Grimes ,DPCYL(partp->dp_scyl, partp->dp_ssect) 4895b81b6b3SRodney W. Grimes ,partp->dp_shd 4906580291bSDavid E. O'Brien ,DPSECT(partp->dp_ssect) 4915b81b6b3SRodney W. Grimes ,DPCYL(partp->dp_ecyl, partp->dp_esect) 4926580291bSDavid E. O'Brien ,partp->dp_ehd 4936580291bSDavid E. O'Brien ,DPSECT(partp->dp_esect)); 4945b81b6b3SRodney W. Grimes } 4955b81b6b3SRodney W. Grimes 496f46af505SJordan K. Hubbard 497f46af505SJordan K. Hubbard static void 498f46af505SJordan K. Hubbard init_boot(void) 499f46af505SJordan K. Hubbard { 50029ea697dSPeter Wemm #ifndef __ia64__ 50126721a89SRobert Nordier const char *fname; 502041b8b00SPoul-Henning Kamp int fdesc, n; 50385c2cf30SJohn Baldwin struct stat sb; 50426721a89SRobert Nordier 50526721a89SRobert Nordier fname = b_flag ? b_flag : "/boot/mbr"; 506041b8b00SPoul-Henning Kamp if ((fdesc = open(fname, O_RDONLY)) == -1 || 507041b8b00SPoul-Henning Kamp fstat(fdesc, &sb) == -1) 50885c2cf30SJohn Baldwin err(1, "%s", fname); 50985c2cf30SJohn Baldwin if ((mboot.bootinst_size = sb.st_size) % secsize != 0) 51085c2cf30SJohn Baldwin errx(1, "%s: length must be a multiple of sector size", fname); 5112b5ce8a9SAndrey A. Chernov if (mboot.bootinst != NULL) 5122b5ce8a9SAndrey A. Chernov free(mboot.bootinst); 51385c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(mboot.bootinst_size = sb.st_size)) == NULL) 51485c2cf30SJohn Baldwin errx(1, "%s: unable to allocate read buffer", fname); 515041b8b00SPoul-Henning Kamp if ((n = read(fdesc, mboot.bootinst, mboot.bootinst_size)) == -1 || 516041b8b00SPoul-Henning Kamp close(fdesc)) 51726721a89SRobert Nordier err(1, "%s", fname); 51885c2cf30SJohn Baldwin if (n != mboot.bootinst_size) 51985c2cf30SJohn Baldwin errx(1, "%s: short read", fname); 52029ea697dSPeter Wemm #else 52129ea697dSPeter Wemm if (mboot.bootinst != NULL) 52229ea697dSPeter Wemm free(mboot.bootinst); 52329ea697dSPeter Wemm mboot.bootinst_size = secsize; 52429ea697dSPeter Wemm if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) 52529ea697dSPeter Wemm errx(1, "unable to allocate boot block buffer"); 52629ea697dSPeter Wemm memset(mboot.bootinst, 0, mboot.bootinst_size); 5271a03d6d5SPoul-Henning Kamp le16enc(&mboot.bootinst[DOSMAGICOFFSET], DOSMAGIC); 52829ea697dSPeter Wemm #endif 529f46af505SJordan K. Hubbard } 530f46af505SJordan K. Hubbard 531f46af505SJordan K. Hubbard 5324be1e61bSAlexander Langer static void 5334be1e61bSAlexander Langer init_sector0(unsigned long start) 5345b81b6b3SRodney W. Grimes { 535c4898ccbSLuigi Rizzo struct dos_partition *partp = &mboot.parts[0]; 5365b81b6b3SRodney W. Grimes 537f46af505SJordan K. Hubbard init_boot(); 5385b81b6b3SRodney W. Grimes 5395b81b6b3SRodney W. Grimes partp->dp_typ = DOSPTYP_386BSD; 5405b81b6b3SRodney W. Grimes partp->dp_flag = ACTIVE; 541b594e0feSJohn Baldwin start = ((start + dos_sectors - 1) / dos_sectors) * dos_sectors; 54285c2cf30SJohn Baldwin if(start == 0) 54385c2cf30SJohn Baldwin start = dos_sectors; 5445b81b6b3SRodney W. Grimes partp->dp_start = start; 545b594e0feSJohn Baldwin partp->dp_size = (disksecs / dos_cylsecs) * dos_cylsecs - start; 5465b81b6b3SRodney W. Grimes 54763692187SIan Dowse dos(partp); 5485b81b6b3SRodney W. Grimes } 5495b81b6b3SRodney W. Grimes 5504be1e61bSAlexander Langer static void 5514be1e61bSAlexander Langer change_part(int i) 5525b81b6b3SRodney W. Grimes { 553c4898ccbSLuigi Rizzo struct dos_partition *partp = &mboot.parts[i - 1]; 5545b81b6b3SRodney W. Grimes 5555b81b6b3SRodney W. Grimes printf("The data for partition %d is:\n", i); 55640905b6eSLuigi Rizzo print_part(partp); 5575b81b6b3SRodney W. Grimes 5585b81b6b3SRodney W. Grimes if (u_flag && ok("Do you want to change it?")) { 5595b81b6b3SRodney W. Grimes int tmp; 5605b81b6b3SRodney W. Grimes 5615b81b6b3SRodney W. Grimes if (i_flag) { 562c4898ccbSLuigi Rizzo bzero(partp, sizeof (*partp)); 563a67ed623SPoul-Henning Kamp if (i == 1) { 5645b81b6b3SRodney W. Grimes init_sector0(1); 565a67ed623SPoul-Henning Kamp printf("\nThe static data for the slice 1 has been reinitialized to:\n"); 56640905b6eSLuigi Rizzo print_part(partp); 5675b81b6b3SRodney W. Grimes } 5685b81b6b3SRodney W. Grimes } 5695b81b6b3SRodney W. Grimes 5705b81b6b3SRodney W. Grimes do { 571680426beSDavid E. O'Brien Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp); 5725b81b6b3SRodney W. Grimes Decimal("start", partp->dp_start, tmp); 5735b81b6b3SRodney W. Grimes Decimal("size", partp->dp_size, tmp); 57463692187SIan Dowse if (!sanitize_partition(partp)) { 57563692187SIan Dowse warnx("ERROR: failed to adjust; setting sysid to 0"); 57663692187SIan Dowse partp->dp_typ = 0; 57763692187SIan Dowse } 5785b81b6b3SRodney W. Grimes 5794b3b45a7SJames Raynard if (ok("Explicitly specify beg/end address ?")) 5805b81b6b3SRodney W. Grimes { 5815b81b6b3SRodney W. Grimes int tsec,tcyl,thd; 5825b81b6b3SRodney W. Grimes tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 5835b81b6b3SRodney W. Grimes thd = partp->dp_shd; 5845b81b6b3SRodney W. Grimes tsec = DPSECT(partp->dp_ssect); 5855b81b6b3SRodney W. Grimes Decimal("beginning cylinder", tcyl, tmp); 5860469c254SDavid E. O'Brien Decimal("beginning head", thd, tmp); 5876580291bSDavid E. O'Brien Decimal("beginning sector", tsec, tmp); 5885b81b6b3SRodney W. Grimes partp->dp_scyl = DOSCYL(tcyl); 5895b81b6b3SRodney W. Grimes partp->dp_ssect = DOSSECT(tsec,tcyl); 5905b81b6b3SRodney W. Grimes partp->dp_shd = thd; 5915b81b6b3SRodney W. Grimes 5925b81b6b3SRodney W. Grimes tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 5935b81b6b3SRodney W. Grimes thd = partp->dp_ehd; 5945b81b6b3SRodney W. Grimes tsec = DPSECT(partp->dp_esect); 5955b81b6b3SRodney W. Grimes Decimal("ending cylinder", tcyl, tmp); 5960469c254SDavid E. O'Brien Decimal("ending head", thd, tmp); 5976580291bSDavid E. O'Brien Decimal("ending sector", tsec, tmp); 5985b81b6b3SRodney W. Grimes partp->dp_ecyl = DOSCYL(tcyl); 5995b81b6b3SRodney W. Grimes partp->dp_esect = DOSSECT(tsec,tcyl); 6005b81b6b3SRodney W. Grimes partp->dp_ehd = thd; 60163692187SIan Dowse } else 60263692187SIan Dowse dos(partp); 6035b81b6b3SRodney W. Grimes 60440905b6eSLuigi Rizzo print_part(partp); 6055b81b6b3SRodney W. Grimes } while (!ok("Are we happy with this entry?")); 6065b81b6b3SRodney W. Grimes } 6075b81b6b3SRodney W. Grimes } 6085b81b6b3SRodney W. Grimes 6094be1e61bSAlexander Langer static void 6105b81b6b3SRodney W. Grimes print_params() 6115b81b6b3SRodney W. Grimes { 6125b81b6b3SRodney W. Grimes printf("parameters extracted from in-core disklabel are:\n"); 6135b81b6b3SRodney W. Grimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 6145b81b6b3SRodney W. Grimes ,cyls,heads,sectors,cylsecs); 6157fa181d4SYoshihiro Takahashi if (dos_cyls > 1023 || dos_heads > 255 || dos_sectors > 63) 6165b81b6b3SRodney W. Grimes printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 6175b81b6b3SRodney W. Grimes printf("parameters to be used for BIOS calculations are:\n"); 6185b81b6b3SRodney W. Grimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 6195b81b6b3SRodney W. Grimes ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 6205b81b6b3SRodney W. Grimes } 6215b81b6b3SRodney W. Grimes 6224be1e61bSAlexander Langer static void 6234be1e61bSAlexander Langer change_active(int which) 6245b81b6b3SRodney W. Grimes { 62563692187SIan Dowse struct dos_partition *partp = &mboot.parts[0]; 62663692187SIan Dowse int active, i, new, tmp; 6275b81b6b3SRodney W. Grimes 62863692187SIan Dowse active = -1; 62963692187SIan Dowse for (i = 0; i < NDOSPART; i++) { 63063692187SIan Dowse if ((partp[i].dp_flag & ACTIVE) == 0) 63163692187SIan Dowse continue; 63263692187SIan Dowse printf("Partition %d is marked active\n", i + 1); 63363692187SIan Dowse if (active == -1) 63463692187SIan Dowse active = i + 1; 63563692187SIan Dowse } 6365b81b6b3SRodney W. Grimes if (a_flag && which != -1) 6375b81b6b3SRodney W. Grimes active = which; 63863692187SIan Dowse else if (active == -1) 63963692187SIan Dowse active = 1; 64063692187SIan Dowse 6410b461cd7SBruce Evans if (!ok("Do you want to change the active partition?")) 6420b461cd7SBruce Evans return; 643680426beSDavid E. O'Brien setactive: 644680426beSDavid E. O'Brien do { 64563692187SIan Dowse new = active; 64663692187SIan Dowse Decimal("active partition", new, tmp); 64763692187SIan Dowse if (new < 1 || new > 4) { 648680426beSDavid E. O'Brien printf("Active partition number must be in range 1-4." 649680426beSDavid E. O'Brien " Try again.\n"); 650680426beSDavid E. O'Brien goto setactive; 651680426beSDavid E. O'Brien } 65263692187SIan Dowse active = new; 653680426beSDavid E. O'Brien } while (!ok("Are you happy with this choice")); 6545b81b6b3SRodney W. Grimes for (i = 0; i < NDOSPART; i++) 6555b81b6b3SRodney W. Grimes partp[i].dp_flag = 0; 6564ddd60b9SBrian Somers if (active > 0 && active <= NDOSPART) 6574ddd60b9SBrian Somers partp[active-1].dp_flag = ACTIVE; 6585b81b6b3SRodney W. Grimes } 6595b81b6b3SRodney W. Grimes 66012d910e9SRobert Nordier static void 66112d910e9SRobert Nordier change_code() 66212d910e9SRobert Nordier { 66312d910e9SRobert Nordier if (ok("Do you want to change the boot code?")) 66412d910e9SRobert Nordier init_boot(); 66512d910e9SRobert Nordier } 66612d910e9SRobert Nordier 6674be1e61bSAlexander Langer void 6685b81b6b3SRodney W. Grimes get_params_to_use() 6695b81b6b3SRodney W. Grimes { 6705b81b6b3SRodney W. Grimes int tmp; 6715b81b6b3SRodney W. Grimes print_params(); 6725b81b6b3SRodney W. Grimes if (ok("Do you want to change our idea of what BIOS thinks ?")) 6735b81b6b3SRodney W. Grimes { 6745b81b6b3SRodney W. Grimes do 6755b81b6b3SRodney W. Grimes { 6765b81b6b3SRodney W. Grimes Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 6775b81b6b3SRodney W. Grimes Decimal("BIOS's idea of #heads", dos_heads, tmp); 6785b81b6b3SRodney W. Grimes Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 6795b81b6b3SRodney W. Grimes dos_cylsecs = dos_heads * dos_sectors; 6805b81b6b3SRodney W. Grimes print_params(); 6815b81b6b3SRodney W. Grimes } 6825b81b6b3SRodney W. Grimes while(!ok("Are you happy with this choice")); 6835b81b6b3SRodney W. Grimes } 6845b81b6b3SRodney W. Grimes } 6855b81b6b3SRodney W. Grimes 686f46af505SJordan K. Hubbard 6875b81b6b3SRodney W. Grimes /***********************************************\ 6885b81b6b3SRodney W. Grimes * Change real numbers into strange dos numbers * 6895b81b6b3SRodney W. Grimes \***********************************************/ 6904be1e61bSAlexander Langer static void 691041b8b00SPoul-Henning Kamp dos(struct dos_partition *partp) 6925b81b6b3SRodney W. Grimes { 69363692187SIan Dowse int cy, sec; 69463692187SIan Dowse u_int32_t end; 6955b81b6b3SRodney W. Grimes 696881c9063SIan Dowse if (partp->dp_typ == 0 && partp->dp_start == 0 && partp->dp_size == 0) { 697881c9063SIan Dowse memcpy(partp, &mtpart, sizeof(*partp)); 6980b461cd7SBruce Evans return; 6990b461cd7SBruce Evans } 7000b461cd7SBruce Evans 70163692187SIan Dowse /* Start c/h/s. */ 70263692187SIan Dowse partp->dp_shd = partp->dp_start % dos_cylsecs / dos_sectors; 70363692187SIan Dowse cy = partp->dp_start / dos_cylsecs; 70463692187SIan Dowse sec = partp->dp_start % dos_sectors + 1; 70563692187SIan Dowse partp->dp_scyl = DOSCYL(cy); 70663692187SIan Dowse partp->dp_ssect = DOSSECT(sec, cy); 7075b81b6b3SRodney W. Grimes 70863692187SIan Dowse /* End c/h/s. */ 70963692187SIan Dowse end = partp->dp_start + partp->dp_size - 1; 71063692187SIan Dowse partp->dp_ehd = end % dos_cylsecs / dos_sectors; 71163692187SIan Dowse cy = end / dos_cylsecs; 71263692187SIan Dowse sec = end % dos_sectors + 1; 71363692187SIan Dowse partp->dp_ecyl = DOSCYL(cy); 71463692187SIan Dowse partp->dp_esect = DOSSECT(sec, cy); 7155b81b6b3SRodney W. Grimes } 7165b81b6b3SRodney W. Grimes 7174be1e61bSAlexander Langer static int 718041b8b00SPoul-Henning Kamp open_disk(int flag) 7195b81b6b3SRodney W. Grimes { 720de78c288SPoul-Henning Kamp int rwmode; 7215b81b6b3SRodney W. Grimes 722b31e5ae2SUlf Lilleengen /* Write mode if one of these flags are set. */ 723b31e5ae2SUlf Lilleengen rwmode = (a_flag || I_flag || B_flag || flag); 724b31e5ae2SUlf Lilleengen fd = g_open(disk, rwmode); 725b31e5ae2SUlf Lilleengen /* If the mode fails, try read-only if we didn't. */ 726b31e5ae2SUlf Lilleengen if (fd == -1 && errno == EPERM && rwmode) 727b31e5ae2SUlf Lilleengen fd = g_open(disk, 0); 728f353c761SPoul-Henning Kamp if (fd == -1 && errno == ENXIO) 729e3038c6eSJoerg Wunsch return -2; 730f353c761SPoul-Henning Kamp if (fd == -1) { 731d98b1668SPhilippe Charnier warnx("can't open device %s", disk); 7325b81b6b3SRodney W. Grimes return -1; 7335b81b6b3SRodney W. Grimes } 734041b8b00SPoul-Henning Kamp if (get_params() == -1) { 735d98b1668SPhilippe Charnier warnx("can't get disk parameters on %s", disk); 7365b81b6b3SRodney W. Grimes return -1; 7375b81b6b3SRodney W. Grimes } 7385b81b6b3SRodney W. Grimes return fd; 7395b81b6b3SRodney W. Grimes } 7405b81b6b3SRodney W. Grimes 7414be1e61bSAlexander Langer static ssize_t 7424be1e61bSAlexander Langer read_disk(off_t sector, void *buf) 7435b81b6b3SRodney W. Grimes { 7447fa181d4SYoshihiro Takahashi 7455b81b6b3SRodney W. Grimes lseek(fd, (sector * 512), 0); 7467cb29d33SSøren Schmidt if (secsize == 0) 7477fa181d4SYoshihiro Takahashi for (secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; 7487fa181d4SYoshihiro Takahashi secsize *= 2) { 7497cb29d33SSøren Schmidt /* try the read */ 7507cb29d33SSøren Schmidt int size = read(fd, buf, secsize); 7517cb29d33SSøren Schmidt if (size == secsize) 7527cb29d33SSøren Schmidt /* it worked so return */ 7537cb29d33SSøren Schmidt return secsize; 7547cb29d33SSøren Schmidt } 7557cb29d33SSøren Schmidt else 7567cb29d33SSøren Schmidt return read(fd, buf, secsize); 7577cb29d33SSøren Schmidt 7587cb29d33SSøren Schmidt /* we failed to read at any of the sizes */ 7597cb29d33SSøren Schmidt return -1; 7605b81b6b3SRodney W. Grimes } 7615b81b6b3SRodney W. Grimes 762de78c288SPoul-Henning Kamp static int 7634be1e61bSAlexander Langer write_disk(off_t sector, void *buf) 7645b81b6b3SRodney W. Grimes { 765de78c288SPoul-Henning Kamp int error; 766de78c288SPoul-Henning Kamp struct gctl_req *grq; 767b31e5ae2SUlf Lilleengen const char *errmsg; 768b31e5ae2SUlf Lilleengen char fbuf[BUFSIZ], *pname; 769de78c288SPoul-Henning Kamp int i, fdw; 770f353c761SPoul-Henning Kamp 771de78c288SPoul-Henning Kamp grq = gctl_get_handle(); 772de78c288SPoul-Henning Kamp gctl_ro_param(grq, "verb", -1, "write MBR"); 773de78c288SPoul-Henning Kamp gctl_ro_param(grq, "class", -1, "MBR"); 774b31e5ae2SUlf Lilleengen pname = g_providername(fd); 775b31e5ae2SUlf Lilleengen if (pname == NULL) { 776bd5add58SUlf Lilleengen warn("Error getting providername for %s", disk); 777b31e5ae2SUlf Lilleengen return (-1); 778b31e5ae2SUlf Lilleengen } 779b31e5ae2SUlf Lilleengen gctl_ro_param(grq, "geom", -1, pname); 780de78c288SPoul-Henning Kamp gctl_ro_param(grq, "data", secsize, buf); 781b31e5ae2SUlf Lilleengen errmsg = gctl_issue(grq); 782b31e5ae2SUlf Lilleengen free(pname); 783b31e5ae2SUlf Lilleengen if (errmsg == NULL) { 784d63612b4SCraig Rodrigues gctl_free(grq); 785de78c288SPoul-Henning Kamp return(0); 786d63612b4SCraig Rodrigues } 787a61d9186SDavid E. O'Brien if (!q_flag) /* GEOM errors are benign, not all devices supported */ 788b31e5ae2SUlf Lilleengen warnx("%s", errmsg); 789d63612b4SCraig Rodrigues gctl_free(grq); 790de78c288SPoul-Henning Kamp 791de78c288SPoul-Henning Kamp error = pwrite(fd, buf, secsize, (sector * 512)); 792de78c288SPoul-Henning Kamp if (error == secsize) 793de78c288SPoul-Henning Kamp return (0); 794de78c288SPoul-Henning Kamp 795de78c288SPoul-Henning Kamp for (i = 1; i < 5; i++) { 796de78c288SPoul-Henning Kamp sprintf(fbuf, "%ss%d", disk, i); 797de78c288SPoul-Henning Kamp fdw = open(fbuf, O_RDWR, 0); 798de78c288SPoul-Henning Kamp if (fdw < 0) 799de78c288SPoul-Henning Kamp continue; 800de78c288SPoul-Henning Kamp error = ioctl(fdw, DIOCSMBR, buf); 801de78c288SPoul-Henning Kamp close(fdw); 802de78c288SPoul-Henning Kamp if (error == 0) 803de78c288SPoul-Henning Kamp return (0); 8045b81b6b3SRodney W. Grimes } 805de78c288SPoul-Henning Kamp warnx("Failed to write sector zero"); 806de78c288SPoul-Henning Kamp return(EINVAL); 807f353c761SPoul-Henning Kamp } 8085b81b6b3SRodney W. Grimes 8094be1e61bSAlexander Langer static int 8104be1e61bSAlexander Langer get_params() 8115b81b6b3SRodney W. Grimes { 8123f8ba8b5SPoul-Henning Kamp int error; 8133f8ba8b5SPoul-Henning Kamp u_int u; 8143f8ba8b5SPoul-Henning Kamp off_t o; 8155b81b6b3SRodney W. Grimes 8167963fae6SPoul-Henning Kamp error = ioctl(fd, DIOCGFWSECTORS, &u); 8177963fae6SPoul-Henning Kamp if (error == 0) 8187963fae6SPoul-Henning Kamp sectors = dos_sectors = u; 819c0fdfdbaSPoul-Henning Kamp else 820c0fdfdbaSPoul-Henning Kamp sectors = dos_sectors = 63; 821c0fdfdbaSPoul-Henning Kamp 8227963fae6SPoul-Henning Kamp error = ioctl(fd, DIOCGFWHEADS, &u); 8237963fae6SPoul-Henning Kamp if (error == 0) 8247963fae6SPoul-Henning Kamp heads = dos_heads = u; 825c0fdfdbaSPoul-Henning Kamp else 826c0fdfdbaSPoul-Henning Kamp heads = dos_heads = 255; 8277963fae6SPoul-Henning Kamp 8285b81b6b3SRodney W. Grimes dos_cylsecs = cylsecs = heads * sectors; 8295b81b6b3SRodney W. Grimes disksecs = cyls * heads * sectors; 8305b81b6b3SRodney W. Grimes 831b31e5ae2SUlf Lilleengen u = g_sectorsize(fd); 832b31e5ae2SUlf Lilleengen if (u <= 0) 833b31e5ae2SUlf Lilleengen return (-1); 8347963fae6SPoul-Henning Kamp 835b31e5ae2SUlf Lilleengen o = g_mediasize(fd); 836b31e5ae2SUlf Lilleengen if (o < 0) 837b31e5ae2SUlf Lilleengen return (-1); 8387963fae6SPoul-Henning Kamp disksecs = o / u; 8397963fae6SPoul-Henning Kamp cyls = dos_cyls = o / (u * dos_heads * dos_sectors); 8407963fae6SPoul-Henning Kamp 8415b81b6b3SRodney W. Grimes return (disksecs); 8425b81b6b3SRodney W. Grimes } 8435b81b6b3SRodney W. Grimes 8444be1e61bSAlexander Langer static int 8455b81b6b3SRodney W. Grimes read_s0() 8465b81b6b3SRodney W. Grimes { 8471a03d6d5SPoul-Henning Kamp int i; 8481a03d6d5SPoul-Henning Kamp 84985c2cf30SJohn Baldwin mboot.bootinst_size = secsize; 8502b5ce8a9SAndrey A. Chernov if (mboot.bootinst != NULL) 8512b5ce8a9SAndrey A. Chernov free(mboot.bootinst); 85285c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) { 85385c2cf30SJohn Baldwin warnx("unable to allocate buffer to read fdisk " 85485c2cf30SJohn Baldwin "partition table"); 85585c2cf30SJohn Baldwin return -1; 85685c2cf30SJohn Baldwin } 85785c2cf30SJohn Baldwin if (read_disk(0, mboot.bootinst) == -1) { 858d98b1668SPhilippe Charnier warnx("can't read fdisk partition table"); 8595b81b6b3SRodney W. Grimes return -1; 8605b81b6b3SRodney W. Grimes } 8611a03d6d5SPoul-Henning Kamp if (le16dec(&mboot.bootinst[DOSMAGICOFFSET]) != DOSMAGIC) { 862d98b1668SPhilippe Charnier warnx("invalid fdisk partition table found"); 8635b81b6b3SRodney W. Grimes /* So should we initialize things */ 8645b81b6b3SRodney W. Grimes return -1; 8655b81b6b3SRodney W. Grimes } 8661a03d6d5SPoul-Henning Kamp for (i = 0; i < NDOSPART; i++) 8671a03d6d5SPoul-Henning Kamp dos_partition_dec( 8681a03d6d5SPoul-Henning Kamp &mboot.bootinst[DOSPARTOFF + i * DOSPARTSIZE], 8691a03d6d5SPoul-Henning Kamp &mboot.parts[i]); 8705b81b6b3SRodney W. Grimes return 0; 8715b81b6b3SRodney W. Grimes } 8725b81b6b3SRodney W. Grimes 8734be1e61bSAlexander Langer static int 8745b81b6b3SRodney W. Grimes write_s0() 8755b81b6b3SRodney W. Grimes { 8761a03d6d5SPoul-Henning Kamp int sector, i; 87785c2cf30SJohn Baldwin 8785b81b6b3SRodney W. Grimes if (iotest) { 879fbcb16efSLuigi Rizzo print_s0(); 8805b81b6b3SRodney W. Grimes return 0; 8815b81b6b3SRodney W. Grimes } 8821a03d6d5SPoul-Henning Kamp for(i = 0; i < NDOSPART; i++) 8831a03d6d5SPoul-Henning Kamp dos_partition_enc(&mboot.bootinst[DOSPARTOFF + i * DOSPARTSIZE], 8841a03d6d5SPoul-Henning Kamp &mboot.parts[i]); 8851a03d6d5SPoul-Henning Kamp le16enc(&mboot.bootinst[DOSMAGICOFFSET], DOSMAGIC); 88685c2cf30SJohn Baldwin for(sector = 0; sector < mboot.bootinst_size / secsize; sector++) 88785c2cf30SJohn Baldwin if (write_disk(sector, 88885c2cf30SJohn Baldwin &mboot.bootinst[sector * secsize]) == -1) { 889e6fb3ddeSPoul-Henning Kamp warn("can't write fdisk partition table"); 8905b81b6b3SRodney W. Grimes return -1; 8915b81b6b3SRodney W. Grimes } 8924be1e61bSAlexander Langer return(0); 8935b81b6b3SRodney W. Grimes } 8945b81b6b3SRodney W. Grimes 8955b81b6b3SRodney W. Grimes 8964be1e61bSAlexander Langer static int 897041b8b00SPoul-Henning Kamp ok(const char *str) 8985b81b6b3SRodney W. Grimes { 8995b81b6b3SRodney W. Grimes printf("%s [n] ", str); 90063692187SIan Dowse fflush(stdout); 90163692187SIan Dowse if (fgets(lbuf, LBUF, stdin) == NULL) 90263692187SIan Dowse exit(1); 9035b81b6b3SRodney W. Grimes lbuf[strlen(lbuf)-1] = 0; 9045b81b6b3SRodney W. Grimes 9055b81b6b3SRodney W. Grimes if (*lbuf && 9065b81b6b3SRodney W. Grimes (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 9075b81b6b3SRodney W. Grimes !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 9085b81b6b3SRodney W. Grimes return 1; 9095b81b6b3SRodney W. Grimes else 9105b81b6b3SRodney W. Grimes return 0; 9115b81b6b3SRodney W. Grimes } 9125b81b6b3SRodney W. Grimes 9134be1e61bSAlexander Langer static int 914041b8b00SPoul-Henning Kamp decimal(const char *str, int *num, int deflt) 9155b81b6b3SRodney W. Grimes { 9165b81b6b3SRodney W. Grimes int acc = 0, c; 9175b81b6b3SRodney W. Grimes char *cp; 9185b81b6b3SRodney W. Grimes 9195b81b6b3SRodney W. Grimes while (1) { 9205b81b6b3SRodney W. Grimes printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 92163692187SIan Dowse fflush(stdout); 92263692187SIan Dowse if (fgets(lbuf, LBUF, stdin) == NULL) 92363692187SIan Dowse exit(1); 9245b81b6b3SRodney W. Grimes lbuf[strlen(lbuf)-1] = 0; 9255b81b6b3SRodney W. Grimes 9265b81b6b3SRodney W. Grimes if (!*lbuf) 9275b81b6b3SRodney W. Grimes return 0; 9285b81b6b3SRodney W. Grimes 9295b81b6b3SRodney W. Grimes cp = lbuf; 9305b81b6b3SRodney W. Grimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 9315b81b6b3SRodney W. Grimes if (!c) 9325b81b6b3SRodney W. Grimes return 0; 9334be1e61bSAlexander Langer while ((c = *cp++)) { 9345b81b6b3SRodney W. Grimes if (c <= '9' && c >= '0') 9355b81b6b3SRodney W. Grimes acc = acc * 10 + c - '0'; 9365b81b6b3SRodney W. Grimes else 9375b81b6b3SRodney W. Grimes break; 9385b81b6b3SRodney W. Grimes } 9395b81b6b3SRodney W. Grimes if (c == ' ' || c == '\t') 9405b81b6b3SRodney W. Grimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 9415b81b6b3SRodney W. Grimes if (!c) { 9425b81b6b3SRodney W. Grimes *num = acc; 9435b81b6b3SRodney W. Grimes return 1; 9445b81b6b3SRodney W. Grimes } else 945680426beSDavid E. O'Brien printf("%s is an invalid decimal number. Try again.\n", 9465b81b6b3SRodney W. Grimes lbuf); 9475b81b6b3SRodney W. Grimes } 9485b81b6b3SRodney W. Grimes 9495b81b6b3SRodney W. Grimes } 9505b81b6b3SRodney W. Grimes 951f46af505SJordan K. Hubbard 952f46af505SJordan K. Hubbard static void 953041b8b00SPoul-Henning Kamp parse_config_line(char *line, CMD *command) 954f46af505SJordan K. Hubbard { 955f46af505SJordan K. Hubbard char *cp, *end; 956f46af505SJordan K. Hubbard 957f46af505SJordan K. Hubbard cp = line; 958041b8b00SPoul-Henning Kamp while (1) { 959f46af505SJordan K. Hubbard memset(command, 0, sizeof(*command)); 960f46af505SJordan K. Hubbard 961f46af505SJordan K. Hubbard while (isspace(*cp)) ++cp; 962f46af505SJordan K. Hubbard if (*cp == '\0' || *cp == '#') 963f46af505SJordan K. Hubbard break; 964f46af505SJordan K. Hubbard command->cmd = *cp++; 965f46af505SJordan K. Hubbard 966f46af505SJordan K. Hubbard /* 967f46af505SJordan K. Hubbard * Parse args 968f46af505SJordan K. Hubbard */ 969041b8b00SPoul-Henning Kamp while (1) { 970f46af505SJordan K. Hubbard while (isspace(*cp)) ++cp; 971f46af505SJordan K. Hubbard if (*cp == '#') 972f46af505SJordan K. Hubbard break; /* found comment */ 973f46af505SJordan K. Hubbard if (isalpha(*cp)) 974f46af505SJordan K. Hubbard command->args[command->n_args].argtype = *cp++; 975f46af505SJordan K. Hubbard if (!isdigit(*cp)) 976f46af505SJordan K. Hubbard break; /* assume end of line */ 977f46af505SJordan K. Hubbard end = NULL; 978f46af505SJordan K. Hubbard command->args[command->n_args].arg_val = strtol(cp, &end, 0); 979f46af505SJordan K. Hubbard if (cp == end) 980f46af505SJordan K. Hubbard break; /* couldn't parse number */ 981f46af505SJordan K. Hubbard cp = end; 982f46af505SJordan K. Hubbard command->n_args++; 983f46af505SJordan K. Hubbard } 984f46af505SJordan K. Hubbard break; 985f46af505SJordan K. Hubbard } 986f46af505SJordan K. Hubbard } 987f46af505SJordan K. Hubbard 988f46af505SJordan K. Hubbard 989f46af505SJordan K. Hubbard static int 990041b8b00SPoul-Henning Kamp process_geometry(CMD *command) 991f46af505SJordan K. Hubbard { 992f46af505SJordan K. Hubbard int status = 1, i; 993f46af505SJordan K. Hubbard 994041b8b00SPoul-Henning Kamp while (1) { 995f46af505SJordan K. Hubbard geom_processed = 1; 996041b8b00SPoul-Henning Kamp if (part_processed) { 997d98b1668SPhilippe Charnier warnx( 998d98b1668SPhilippe Charnier "ERROR line %d: the geometry specification line must occur before\n\ 999d98b1668SPhilippe Charnier all partition specifications", 1000d98b1668SPhilippe Charnier current_line_number); 1001f46af505SJordan K. Hubbard status = 0; 1002f46af505SJordan K. Hubbard break; 1003f46af505SJordan K. Hubbard } 1004041b8b00SPoul-Henning Kamp if (command->n_args != 3) { 1005d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of geometry args", 1006d98b1668SPhilippe Charnier current_line_number); 1007f46af505SJordan K. Hubbard status = 0; 1008f46af505SJordan K. Hubbard break; 1009f46af505SJordan K. Hubbard } 1010041b8b00SPoul-Henning Kamp dos_cyls = 0; 1011041b8b00SPoul-Henning Kamp dos_heads = 0; 1012041b8b00SPoul-Henning Kamp dos_sectors = 0; 1013041b8b00SPoul-Henning Kamp for (i = 0; i < 3; ++i) { 1014041b8b00SPoul-Henning Kamp switch (command->args[i].argtype) { 1015f46af505SJordan K. Hubbard case 'c': 1016f46af505SJordan K. Hubbard dos_cyls = command->args[i].arg_val; 1017f46af505SJordan K. Hubbard break; 1018f46af505SJordan K. Hubbard case 'h': 1019f46af505SJordan K. Hubbard dos_heads = command->args[i].arg_val; 1020f46af505SJordan K. Hubbard break; 1021f46af505SJordan K. Hubbard case 's': 1022f46af505SJordan K. Hubbard dos_sectors = command->args[i].arg_val; 1023f46af505SJordan K. Hubbard break; 1024f46af505SJordan K. Hubbard default: 1025d98b1668SPhilippe Charnier warnx( 1026d98b1668SPhilippe Charnier "ERROR line %d: unknown geometry arg type: '%c' (0x%02x)", 1027d98b1668SPhilippe Charnier current_line_number, command->args[i].argtype, 1028f46af505SJordan K. Hubbard command->args[i].argtype); 1029f46af505SJordan K. Hubbard status = 0; 1030f46af505SJordan K. Hubbard break; 1031f46af505SJordan K. Hubbard } 1032f46af505SJordan K. Hubbard } 1033f46af505SJordan K. Hubbard if (status == 0) 1034f46af505SJordan K. Hubbard break; 1035f46af505SJordan K. Hubbard 1036f46af505SJordan K. Hubbard dos_cylsecs = dos_heads * dos_sectors; 1037f46af505SJordan K. Hubbard 1038f46af505SJordan K. Hubbard /* 1039f46af505SJordan K. Hubbard * Do sanity checks on parameter values 1040f46af505SJordan K. Hubbard */ 1041041b8b00SPoul-Henning Kamp if (dos_cyls == 0) { 1042d98b1668SPhilippe Charnier warnx("ERROR line %d: number of cylinders not specified", 1043d98b1668SPhilippe Charnier current_line_number); 1044f46af505SJordan K. Hubbard status = 0; 1045f46af505SJordan K. Hubbard } 1046041b8b00SPoul-Henning Kamp if (dos_cyls > 1024) { 1047d98b1668SPhilippe Charnier warnx( 1048d98b1668SPhilippe Charnier "WARNING line %d: number of cylinders (%d) may be out-of-range\n\ 1049f46af505SJordan K. Hubbard (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\ 1050d98b1668SPhilippe Charnier is dedicated to FreeBSD)", 1051d98b1668SPhilippe Charnier current_line_number, dos_cyls); 1052f46af505SJordan K. Hubbard } 1053f46af505SJordan K. Hubbard 1054041b8b00SPoul-Henning Kamp if (dos_heads == 0) { 1055d98b1668SPhilippe Charnier warnx("ERROR line %d: number of heads not specified", 1056d98b1668SPhilippe Charnier current_line_number); 1057f46af505SJordan K. Hubbard status = 0; 1058041b8b00SPoul-Henning Kamp } else if (dos_heads > 256) { 1059d98b1668SPhilippe Charnier warnx("ERROR line %d: number of heads must be within (1-256)", 1060d98b1668SPhilippe Charnier current_line_number); 1061f46af505SJordan K. Hubbard status = 0; 1062f46af505SJordan K. Hubbard } 1063f46af505SJordan K. Hubbard 1064041b8b00SPoul-Henning Kamp if (dos_sectors == 0) { 1065d98b1668SPhilippe Charnier warnx("ERROR line %d: number of sectors not specified", 1066d98b1668SPhilippe Charnier current_line_number); 1067f46af505SJordan K. Hubbard status = 0; 1068041b8b00SPoul-Henning Kamp } else if (dos_sectors > 63) { 1069d98b1668SPhilippe Charnier warnx("ERROR line %d: number of sectors must be within (1-63)", 1070d98b1668SPhilippe Charnier current_line_number); 1071f46af505SJordan K. Hubbard status = 0; 1072f46af505SJordan K. Hubbard } 1073f46af505SJordan K. Hubbard 1074f46af505SJordan K. Hubbard break; 1075f46af505SJordan K. Hubbard } 1076f46af505SJordan K. Hubbard return (status); 1077f46af505SJordan K. Hubbard } 1078f46af505SJordan K. Hubbard 1079f46af505SJordan K. Hubbard 1080f46af505SJordan K. Hubbard static int 1081041b8b00SPoul-Henning Kamp process_partition(CMD *command) 1082f46af505SJordan K. Hubbard { 1083f46af505SJordan K. Hubbard int status = 0, partition; 1084b594e0feSJohn Baldwin u_int32_t prev_head_boundary, prev_cyl_boundary; 1085b594e0feSJohn Baldwin u_int32_t adj_size, max_end; 1086f46af505SJordan K. Hubbard struct dos_partition *partp; 1087f46af505SJordan K. Hubbard 1088041b8b00SPoul-Henning Kamp while (1) { 1089f46af505SJordan K. Hubbard part_processed = 1; 1090041b8b00SPoul-Henning Kamp if (command->n_args != 4) { 1091d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of partition args", 1092d98b1668SPhilippe Charnier current_line_number); 1093f46af505SJordan K. Hubbard break; 1094f46af505SJordan K. Hubbard } 1095f46af505SJordan K. Hubbard partition = command->args[0].arg_val; 1096041b8b00SPoul-Henning Kamp if (partition < 1 || partition > 4) { 1097d98b1668SPhilippe Charnier warnx("ERROR line %d: invalid partition number %d", 1098d98b1668SPhilippe Charnier current_line_number, partition); 1099f46af505SJordan K. Hubbard break; 1100f46af505SJordan K. Hubbard } 1101c4898ccbSLuigi Rizzo partp = &mboot.parts[partition - 1]; 1102c4898ccbSLuigi Rizzo bzero(partp, sizeof (*partp)); 1103f46af505SJordan K. Hubbard partp->dp_typ = command->args[1].arg_val; 1104f46af505SJordan K. Hubbard partp->dp_start = command->args[2].arg_val; 1105f46af505SJordan K. Hubbard partp->dp_size = command->args[3].arg_val; 1106f46af505SJordan K. Hubbard max_end = partp->dp_start + partp->dp_size; 1107f46af505SJordan K. Hubbard 1108041b8b00SPoul-Henning Kamp if (partp->dp_typ == 0) { 1109f46af505SJordan K. Hubbard /* 1110f46af505SJordan K. Hubbard * Get out, the partition is marked as unused. 1111f46af505SJordan K. Hubbard */ 1112f46af505SJordan K. Hubbard /* 1113f46af505SJordan K. Hubbard * Insure that it's unused. 1114f46af505SJordan K. Hubbard */ 1115c4898ccbSLuigi Rizzo bzero(partp, sizeof(*partp)); 1116f46af505SJordan K. Hubbard status = 1; 1117f46af505SJordan K. Hubbard break; 1118f46af505SJordan K. Hubbard } 1119f46af505SJordan K. Hubbard 1120f46af505SJordan K. Hubbard /* 1121d64ada50SJens Schweikhardt * Adjust start upwards, if necessary, to fall on a head boundary. 1122f46af505SJordan K. Hubbard */ 1123041b8b00SPoul-Henning Kamp if (partp->dp_start % dos_sectors != 0) { 1124b594e0feSJohn Baldwin prev_head_boundary = partp->dp_start / dos_sectors * dos_sectors; 1125b594e0feSJohn Baldwin if (max_end < dos_sectors || 1126041b8b00SPoul-Henning Kamp prev_head_boundary > max_end - dos_sectors) { 1127f46af505SJordan K. Hubbard /* 1128f46af505SJordan K. Hubbard * Can't go past end of partition 1129f46af505SJordan K. Hubbard */ 1130d98b1668SPhilippe Charnier warnx( 1131d98b1668SPhilippe Charnier "ERROR line %d: unable to adjust start of partition %d to fall on\n\ 1132b594e0feSJohn Baldwin a head boundary", 1133d98b1668SPhilippe Charnier current_line_number, partition); 1134f46af505SJordan K. Hubbard break; 1135f46af505SJordan K. Hubbard } 1136d98b1668SPhilippe Charnier warnx( 1137b594e0feSJohn Baldwin "WARNING: adjusting start offset of partition %d\n\ 1138b594e0feSJohn Baldwin from %u to %u, to fall on a head boundary", 1139b594e0feSJohn Baldwin partition, (u_int)partp->dp_start, 1140b594e0feSJohn Baldwin (u_int)(prev_head_boundary + dos_sectors)); 1141b594e0feSJohn Baldwin partp->dp_start = prev_head_boundary + dos_sectors; 1142f46af505SJordan K. Hubbard } 1143f46af505SJordan K. Hubbard 1144f46af505SJordan K. Hubbard /* 1145f46af505SJordan K. Hubbard * Adjust size downwards, if necessary, to fall on a cylinder 1146f46af505SJordan K. Hubbard * boundary. 1147f46af505SJordan K. Hubbard */ 1148b594e0feSJohn Baldwin prev_cyl_boundary = 1149f46af505SJordan K. Hubbard ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs; 1150b594e0feSJohn Baldwin if (prev_cyl_boundary > partp->dp_start) 1151b594e0feSJohn Baldwin adj_size = prev_cyl_boundary - partp->dp_start; 1152041b8b00SPoul-Henning Kamp else { 1153b594e0feSJohn Baldwin warnx( 1154b594e0feSJohn Baldwin "ERROR: could not adjust partition to start on a head boundary\n\ 1155b594e0feSJohn Baldwin and end on a cylinder boundary."); 1156b594e0feSJohn Baldwin return (0); 1157b594e0feSJohn Baldwin } 1158041b8b00SPoul-Henning Kamp if (adj_size != partp->dp_size) { 1159d98b1668SPhilippe Charnier warnx( 1160b594e0feSJohn Baldwin "WARNING: adjusting size of partition %d from %u to %u\n\ 1161b594e0feSJohn Baldwin to end on a cylinder boundary", 1162b594e0feSJohn Baldwin partition, (u_int)partp->dp_size, (u_int)adj_size); 1163f46af505SJordan K. Hubbard partp->dp_size = adj_size; 1164f46af505SJordan K. Hubbard } 1165041b8b00SPoul-Henning Kamp if (partp->dp_size == 0) { 116663692187SIan Dowse warnx("ERROR line %d: size of partition %d is zero", 1167d98b1668SPhilippe Charnier current_line_number, partition); 1168f46af505SJordan K. Hubbard break; 1169f46af505SJordan K. Hubbard } 1170f46af505SJordan K. Hubbard 117163692187SIan Dowse dos(partp); 1172f46af505SJordan K. Hubbard status = 1; 1173f46af505SJordan K. Hubbard break; 1174f46af505SJordan K. Hubbard } 1175f46af505SJordan K. Hubbard return (status); 1176f46af505SJordan K. Hubbard } 1177f46af505SJordan K. Hubbard 1178f46af505SJordan K. Hubbard 1179f46af505SJordan K. Hubbard static int 1180041b8b00SPoul-Henning Kamp process_active(CMD *command) 1181f46af505SJordan K. Hubbard { 1182f46af505SJordan K. Hubbard int status = 0, partition, i; 1183f46af505SJordan K. Hubbard struct dos_partition *partp; 1184f46af505SJordan K. Hubbard 1185041b8b00SPoul-Henning Kamp while (1) { 1186f46af505SJordan K. Hubbard active_processed = 1; 1187041b8b00SPoul-Henning Kamp if (command->n_args != 1) { 1188d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of active args", 1189d98b1668SPhilippe Charnier current_line_number); 1190f46af505SJordan K. Hubbard status = 0; 1191f46af505SJordan K. Hubbard break; 1192f46af505SJordan K. Hubbard } 1193f46af505SJordan K. Hubbard partition = command->args[0].arg_val; 1194041b8b00SPoul-Henning Kamp if (partition < 1 || partition > 4) { 1195d98b1668SPhilippe Charnier warnx("ERROR line %d: invalid partition number %d", 1196d98b1668SPhilippe Charnier current_line_number, partition); 1197f46af505SJordan K. Hubbard break; 1198f46af505SJordan K. Hubbard } 1199f46af505SJordan K. Hubbard /* 1200f46af505SJordan K. Hubbard * Reset active partition 1201f46af505SJordan K. Hubbard */ 1202c4898ccbSLuigi Rizzo partp = mboot.parts; 1203f46af505SJordan K. Hubbard for (i = 0; i < NDOSPART; i++) 1204f46af505SJordan K. Hubbard partp[i].dp_flag = 0; 12054ddd60b9SBrian Somers partp[partition-1].dp_flag = ACTIVE; 1206f46af505SJordan K. Hubbard 1207f46af505SJordan K. Hubbard status = 1; 1208f46af505SJordan K. Hubbard break; 1209f46af505SJordan K. Hubbard } 1210f46af505SJordan K. Hubbard return (status); 1211f46af505SJordan K. Hubbard } 1212f46af505SJordan K. Hubbard 1213f46af505SJordan K. Hubbard 1214f46af505SJordan K. Hubbard static int 1215041b8b00SPoul-Henning Kamp process_line(char *line) 1216f46af505SJordan K. Hubbard { 1217f46af505SJordan K. Hubbard CMD command; 1218f46af505SJordan K. Hubbard int status = 1; 1219f46af505SJordan K. Hubbard 1220041b8b00SPoul-Henning Kamp while (1) { 1221f46af505SJordan K. Hubbard parse_config_line(line, &command); 1222041b8b00SPoul-Henning Kamp switch (command.cmd) { 1223f46af505SJordan K. Hubbard case 0: 1224f46af505SJordan K. Hubbard /* 1225f46af505SJordan K. Hubbard * Comment or blank line 1226f46af505SJordan K. Hubbard */ 1227f46af505SJordan K. Hubbard break; 1228f46af505SJordan K. Hubbard case 'g': 1229f46af505SJordan K. Hubbard /* 1230f46af505SJordan K. Hubbard * Set geometry 1231f46af505SJordan K. Hubbard */ 1232f46af505SJordan K. Hubbard status = process_geometry(&command); 1233f46af505SJordan K. Hubbard break; 1234f46af505SJordan K. Hubbard case 'p': 1235f46af505SJordan K. Hubbard status = process_partition(&command); 1236f46af505SJordan K. Hubbard break; 1237f46af505SJordan K. Hubbard case 'a': 1238f46af505SJordan K. Hubbard status = process_active(&command); 1239f46af505SJordan K. Hubbard break; 1240f46af505SJordan K. Hubbard default: 1241f46af505SJordan K. Hubbard status = 0; 1242f46af505SJordan K. Hubbard break; 1243f46af505SJordan K. Hubbard } 1244f46af505SJordan K. Hubbard break; 1245f46af505SJordan K. Hubbard } 1246f46af505SJordan K. Hubbard return (status); 1247f46af505SJordan K. Hubbard } 1248f46af505SJordan K. Hubbard 1249f46af505SJordan K. Hubbard 1250f46af505SJordan K. Hubbard static int 1251041b8b00SPoul-Henning Kamp read_config(char *config_file) 1252f46af505SJordan K. Hubbard { 1253f46af505SJordan K. Hubbard FILE *fp = NULL; 1254f46af505SJordan K. Hubbard int status = 1; 1255f46af505SJordan K. Hubbard char buf[1010]; 1256f46af505SJordan K. Hubbard 1257041b8b00SPoul-Henning Kamp while (1) { 1258041b8b00SPoul-Henning Kamp if (strcmp(config_file, "-") != 0) { 1259f46af505SJordan K. Hubbard /* 1260f46af505SJordan K. Hubbard * We're not reading from stdin 1261f46af505SJordan K. Hubbard */ 1262041b8b00SPoul-Henning Kamp if ((fp = fopen(config_file, "r")) == NULL) { 1263f46af505SJordan K. Hubbard status = 0; 1264f46af505SJordan K. Hubbard break; 1265f46af505SJordan K. Hubbard } 1266041b8b00SPoul-Henning Kamp } else { 1267f46af505SJordan K. Hubbard fp = stdin; 1268f46af505SJordan K. Hubbard } 1269f46af505SJordan K. Hubbard current_line_number = 0; 1270041b8b00SPoul-Henning Kamp while (!feof(fp)) { 1271f46af505SJordan K. Hubbard if (fgets(buf, sizeof(buf), fp) == NULL) 1272f46af505SJordan K. Hubbard break; 1273f46af505SJordan K. Hubbard ++current_line_number; 1274f46af505SJordan K. Hubbard status = process_line(buf); 1275f46af505SJordan K. Hubbard if (status == 0) 1276f46af505SJordan K. Hubbard break; 1277f46af505SJordan K. Hubbard } 1278f46af505SJordan K. Hubbard break; 1279f46af505SJordan K. Hubbard } 1280041b8b00SPoul-Henning Kamp if (fp) { 1281f46af505SJordan K. Hubbard /* 1282f46af505SJordan K. Hubbard * It doesn't matter if we're reading from stdin, as we've reached EOF 1283f46af505SJordan K. Hubbard */ 1284f46af505SJordan K. Hubbard fclose(fp); 1285f46af505SJordan K. Hubbard } 1286f46af505SJordan K. Hubbard return (status); 1287f46af505SJordan K. Hubbard } 1288f46af505SJordan K. Hubbard 1289f46af505SJordan K. Hubbard 1290f46af505SJordan K. Hubbard static void 1291f46af505SJordan K. Hubbard reset_boot(void) 1292f46af505SJordan K. Hubbard { 1293f46af505SJordan K. Hubbard int i; 1294f46af505SJordan K. Hubbard struct dos_partition *partp; 1295f46af505SJordan K. Hubbard 1296f46af505SJordan K. Hubbard init_boot(); 1297041b8b00SPoul-Henning Kamp for (i = 0; i < 4; ++i) { 1298c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 1299c4898ccbSLuigi Rizzo bzero(partp, sizeof(*partp)); 1300f46af505SJordan K. Hubbard } 1301f46af505SJordan K. Hubbard } 1302b594e0feSJohn Baldwin 1303b594e0feSJohn Baldwin static int 1304041b8b00SPoul-Henning Kamp sanitize_partition(struct dos_partition *partp) 1305b594e0feSJohn Baldwin { 1306b594e0feSJohn Baldwin u_int32_t prev_head_boundary, prev_cyl_boundary; 130763692187SIan Dowse u_int32_t max_end, size, start; 1308b594e0feSJohn Baldwin 130963692187SIan Dowse start = partp->dp_start; 131063692187SIan Dowse size = partp->dp_size; 131163692187SIan Dowse max_end = start + size; 131263692187SIan Dowse /* Only allow a zero size if the partition is being marked unused. */ 131363692187SIan Dowse if (size == 0) { 131463692187SIan Dowse if (start == 0 && partp->dp_typ == 0) 131563692187SIan Dowse return (1); 131663692187SIan Dowse warnx("ERROR: size of partition is zero"); 131763692187SIan Dowse return (0); 131863692187SIan Dowse } 131963692187SIan Dowse /* Return if no adjustment is necessary. */ 132063692187SIan Dowse if (start % dos_sectors == 0 && (start + size) % dos_sectors == 0) 132163692187SIan Dowse return (1); 132263692187SIan Dowse 13237fb7df31SDag-Erling Smørgrav if (start == 0) { 13247fb7df31SDag-Erling Smørgrav warnx("WARNING: partition overlaps with partition table"); 13257fb7df31SDag-Erling Smørgrav if (ok("Correct this automatically?")) 13267fb7df31SDag-Erling Smørgrav start = dos_sectors; 13277fb7df31SDag-Erling Smørgrav } 132863692187SIan Dowse if (start % dos_sectors != 0) 132963692187SIan Dowse warnx("WARNING: partition does not start on a head boundary"); 133063692187SIan Dowse if ((start +size) % dos_sectors != 0) 133163692187SIan Dowse warnx("WARNING: partition does not end on a cylinder boundary"); 133263692187SIan Dowse warnx("WARNING: this may confuse the BIOS or some operating systems"); 133363692187SIan Dowse if (!ok("Correct this automatically?")) 133463692187SIan Dowse return (1); 1335b594e0feSJohn Baldwin 1336b594e0feSJohn Baldwin /* 1337d64ada50SJens Schweikhardt * Adjust start upwards, if necessary, to fall on a head boundary. 1338b594e0feSJohn Baldwin */ 133963692187SIan Dowse if (start % dos_sectors != 0) { 134063692187SIan Dowse prev_head_boundary = start / dos_sectors * dos_sectors; 1341b594e0feSJohn Baldwin if (max_end < dos_sectors || 134263692187SIan Dowse prev_head_boundary >= max_end - dos_sectors) { 1343b594e0feSJohn Baldwin /* 1344b594e0feSJohn Baldwin * Can't go past end of partition 1345b594e0feSJohn Baldwin */ 1346b594e0feSJohn Baldwin warnx( 1347b594e0feSJohn Baldwin "ERROR: unable to adjust start of partition to fall on a head boundary"); 1348b594e0feSJohn Baldwin return (0); 1349b594e0feSJohn Baldwin } 135063692187SIan Dowse start = prev_head_boundary + dos_sectors; 1351b594e0feSJohn Baldwin } 1352b594e0feSJohn Baldwin 1353b594e0feSJohn Baldwin /* 1354b594e0feSJohn Baldwin * Adjust size downwards, if necessary, to fall on a cylinder 1355b594e0feSJohn Baldwin * boundary. 1356b594e0feSJohn Baldwin */ 135763692187SIan Dowse prev_cyl_boundary = ((start + size) / dos_cylsecs) * dos_cylsecs; 135863692187SIan Dowse if (prev_cyl_boundary > start) 135963692187SIan Dowse size = prev_cyl_boundary - start; 136063692187SIan Dowse else { 1361b594e0feSJohn Baldwin warnx("ERROR: could not adjust partition to start on a head boundary\n\ 1362b594e0feSJohn Baldwin and end on a cylinder boundary."); 1363b594e0feSJohn Baldwin return (0); 1364b594e0feSJohn Baldwin } 136563692187SIan Dowse 136663692187SIan Dowse /* Finally, commit any changes to partp and return. */ 136763692187SIan Dowse if (start != partp->dp_start) { 136863692187SIan Dowse warnx("WARNING: adjusting start offset of partition to %u", 136963692187SIan Dowse (u_int)start); 137063692187SIan Dowse partp->dp_start = start; 1371b594e0feSJohn Baldwin } 137263692187SIan Dowse if (size != partp->dp_size) { 137363692187SIan Dowse warnx("WARNING: adjusting size of partition to %u", (u_int)size); 137463692187SIan Dowse partp->dp_size = size; 1375b594e0feSJohn Baldwin } 1376b594e0feSJohn Baldwin 1377b594e0feSJohn Baldwin return (1); 1378b594e0feSJohn Baldwin } 1379df77f711SJoerg Wunsch 1380df77f711SJoerg Wunsch /* 1381df77f711SJoerg Wunsch * Try figuring out the root device's canonical disk name. 1382df77f711SJoerg Wunsch * The following choices are considered: 1383df77f711SJoerg Wunsch * /dev/ad0s1a => /dev/ad0 1384df77f711SJoerg Wunsch * /dev/da0a => /dev/da0 1385df77f711SJoerg Wunsch * /dev/vinum/root => /dev/vinum/root 1386df77f711SJoerg Wunsch */ 1387df77f711SJoerg Wunsch static char * 1388df77f711SJoerg Wunsch get_rootdisk(void) 1389df77f711SJoerg Wunsch { 1390df77f711SJoerg Wunsch struct statfs rootfs; 1391df77f711SJoerg Wunsch regex_t re; 1392df77f711SJoerg Wunsch #define NMATCHES 2 1393df77f711SJoerg Wunsch regmatch_t rm[NMATCHES]; 1394df77f711SJoerg Wunsch char *s; 1395df77f711SJoerg Wunsch int rv; 1396df77f711SJoerg Wunsch 1397df77f711SJoerg Wunsch if (statfs("/", &rootfs) == -1) 1398df77f711SJoerg Wunsch err(1, "statfs(\"/\")"); 1399df77f711SJoerg Wunsch 1400aee85526SSimon L. B. Nielsen if ((rv = regcomp(&re, "^(/dev/[a-z/]+[0-9]+)([sp][0-9]+)?[a-h]?$", 1401df77f711SJoerg Wunsch REG_EXTENDED)) != 0) 1402df77f711SJoerg Wunsch errx(1, "regcomp() failed (%d)", rv); 1403df77f711SJoerg Wunsch if ((rv = regexec(&re, rootfs.f_mntfromname, NMATCHES, rm, 0)) != 0) 1404df77f711SJoerg Wunsch errx(1, 1405df77f711SJoerg Wunsch "mounted root fs resource doesn't match expectations (regexec returned %d)", 1406df77f711SJoerg Wunsch rv); 1407df77f711SJoerg Wunsch if ((s = malloc(rm[1].rm_eo - rm[1].rm_so + 1)) == NULL) 1408df77f711SJoerg Wunsch errx(1, "out of memory"); 1409df77f711SJoerg Wunsch memcpy(s, rootfs.f_mntfromname + rm[1].rm_so, 1410df77f711SJoerg Wunsch rm[1].rm_eo - rm[1].rm_so); 1411df77f711SJoerg Wunsch s[rm[1].rm_eo - rm[1].rm_so] = 0; 1412df77f711SJoerg Wunsch 1413df77f711SJoerg Wunsch return s; 1414df77f711SJoerg Wunsch } 1415