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 501efe3c6bSEd Schouten static int iotest; 515b81b6b3SRodney W. Grimes 524be78ce3SMaxim Sobolev #define NO_DISK_SECTORS ((u_int32_t)-1) 534be78ce3SMaxim Sobolev #define NO_TRACK_CYLINDERS 1023 544be78ce3SMaxim Sobolev #define NO_TRACK_HEADS 255 554be78ce3SMaxim Sobolev #define NO_TRACK_SECTORS 63 565b81b6b3SRodney W. Grimes #define LBUF 100 575b81b6b3SRodney W. Grimes static char lbuf[LBUF]; 585b81b6b3SRodney W. Grimes 595b81b6b3SRodney W. Grimes /* 605b81b6b3SRodney W. Grimes * 615b81b6b3SRodney W. Grimes * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 625b81b6b3SRodney W. Grimes * 635b81b6b3SRodney W. Grimes * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 645b81b6b3SRodney W. Grimes * Copyright (c) 1989 Robert. V. Baron 655b81b6b3SRodney W. Grimes * Created. 665b81b6b3SRodney W. Grimes */ 675b81b6b3SRodney W. Grimes 684be78ce3SMaxim Sobolev #define Decimal(str, ans, tmp, maxval) if (decimal(str, &tmp, ans, maxval)) ans = tmp 695b81b6b3SRodney W. Grimes 705b81b6b3SRodney W. Grimes #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 715b81b6b3SRodney W. Grimes 727cb29d33SSøren Schmidt #define MAX_SEC_SIZE 2048 /* maximum section size that is supported */ 737cb29d33SSøren Schmidt #define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 74041b8b00SPoul-Henning Kamp static int secsize = 0; /* the sensed sector size */ 755b81b6b3SRodney W. Grimes 76041b8b00SPoul-Henning Kamp static char *disk; 77e3038c6eSJoerg Wunsch 78041b8b00SPoul-Henning Kamp static int cyls, sectors, heads, cylsecs, disksecs; 795b81b6b3SRodney W. Grimes 80041b8b00SPoul-Henning Kamp struct mboot { 8185c2cf30SJohn Baldwin unsigned char *bootinst; /* boot code */ 8285c2cf30SJohn Baldwin off_t bootinst_size; 831a03d6d5SPoul-Henning Kamp struct dos_partition parts[NDOSPART]; 845b81b6b3SRodney W. Grimes }; 85041b8b00SPoul-Henning Kamp 86041b8b00SPoul-Henning Kamp static struct mboot mboot; 87de78c288SPoul-Henning Kamp static int fd; 88f353c761SPoul-Henning Kamp 895b81b6b3SRodney W. Grimes #define ACTIVE 0x80 905b81b6b3SRodney W. Grimes 91041b8b00SPoul-Henning Kamp static uint dos_cyls; 92041b8b00SPoul-Henning Kamp static uint dos_heads; 93041b8b00SPoul-Henning Kamp static uint dos_sectors; 94041b8b00SPoul-Henning Kamp static uint dos_cylsecs; 955b81b6b3SRodney W. Grimes 965b81b6b3SRodney W. Grimes #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 975b81b6b3SRodney W. Grimes #define DOSCYL(c) (c & 0xff) 985b81b6b3SRodney W. Grimes 99f46af505SJordan K. Hubbard #define MAX_ARGS 10 100f46af505SJordan K. Hubbard 101f46af505SJordan K. Hubbard static int current_line_number; 102f46af505SJordan K. Hubbard 103f46af505SJordan K. Hubbard static int geom_processed = 0; 104f46af505SJordan K. Hubbard static int part_processed = 0; 105f46af505SJordan K. Hubbard static int active_processed = 0; 106f46af505SJordan K. Hubbard 107f46af505SJordan K. Hubbard typedef struct cmd { 108f46af505SJordan K. Hubbard char cmd; 109f46af505SJordan K. Hubbard int n_args; 110f46af505SJordan K. Hubbard struct arg { 111f46af505SJordan K. Hubbard char argtype; 112f9373bbdSRyan Stone unsigned long arg_val; 113d1c77156SBrian Somers char * arg_str; 114f46af505SJordan K. Hubbard } args[MAX_ARGS]; 115f46af505SJordan K. Hubbard } CMD; 116f46af505SJordan K. Hubbard 11726721a89SRobert Nordier static int B_flag = 0; /* replace boot code */ 11810b0ee93SWarner Losh static int I_flag = 0; /* use entire disk for FreeBSD */ 1195b81b6b3SRodney W. Grimes static int a_flag = 0; /* set active partition */ 12026721a89SRobert Nordier static char *b_flag = NULL; /* path to boot code */ 1215b81b6b3SRodney W. Grimes static int i_flag = 0; /* replace partition data */ 122a61d9186SDavid E. O'Brien static int q_flag = 0; /* Be quiet */ 1235b81b6b3SRodney W. Grimes static int u_flag = 0; /* update partition data */ 12410b0ee93SWarner Losh static int s_flag = 0; /* Print a summary and exit */ 12505a213f1STom Rhodes static int t_flag = 0; /* test only */ 126f46af505SJordan K. Hubbard static char *f_flag = NULL; /* Read config info from file */ 127f46af505SJordan K. Hubbard static int v_flag = 0; /* Be verbose */ 1287914c60fSMaxim Konovalov static int print_config_flag = 0; 1295b81b6b3SRodney W. Grimes 13022fccf5cSLuigi Rizzo /* 13122fccf5cSLuigi Rizzo * A list of partition types, probably outdated. 13222fccf5cSLuigi Rizzo */ 13322fccf5cSLuigi Rizzo static const char *const part_types[256] = { 13422fccf5cSLuigi Rizzo [0x00] = "unused", 13522fccf5cSLuigi Rizzo [0x01] = "Primary DOS with 12 bit FAT", 13622fccf5cSLuigi Rizzo [0x02] = "XENIX / file system", 13722fccf5cSLuigi Rizzo [0x03] = "XENIX /usr file system", 13822fccf5cSLuigi Rizzo [0x04] = "Primary DOS with 16 bit FAT (< 32MB)", 13922fccf5cSLuigi Rizzo [0x05] = "Extended DOS", 14031fade05SLuigi Rizzo [0x06] = "Primary DOS, 16 bit FAT (>= 32MB)", 14131fade05SLuigi Rizzo [0x07] = "NTFS, OS/2 HPFS, QNX-2 (16 bit) or Advanced UNIX", 14222fccf5cSLuigi Rizzo [0x08] = "AIX file system or SplitDrive", 14322fccf5cSLuigi Rizzo [0x09] = "AIX boot partition or Coherent", 14422fccf5cSLuigi Rizzo [0x0A] = "OS/2 Boot Manager, OPUS or Coherent swap", 14522fccf5cSLuigi Rizzo [0x0B] = "DOS or Windows 95 with 32 bit FAT", 14622fccf5cSLuigi Rizzo [0x0C] = "DOS or Windows 95 with 32 bit FAT (LBA)", 14722fccf5cSLuigi Rizzo [0x0E] = "Primary 'big' DOS (>= 32MB, LBA)", 14822fccf5cSLuigi Rizzo [0x0F] = "Extended DOS (LBA)", 14922fccf5cSLuigi Rizzo [0x10] = "OPUS", 15022fccf5cSLuigi Rizzo [0x11] = "OS/2 BM: hidden DOS with 12-bit FAT", 15122fccf5cSLuigi Rizzo [0x12] = "Compaq diagnostics", 15222fccf5cSLuigi Rizzo [0x14] = "OS/2 BM: hidden DOS with 16-bit FAT (< 32MB)", 15322fccf5cSLuigi Rizzo [0x16] = "OS/2 BM: hidden DOS with 16-bit FAT (>= 32MB)", 15422fccf5cSLuigi Rizzo [0x17] = "OS/2 BM: hidden IFS (e.g. HPFS)", 15522fccf5cSLuigi Rizzo [0x18] = "AST Windows swapfile", 15631fade05SLuigi Rizzo [0x1b] = "ASUS Recovery partition (NTFS)", 15722fccf5cSLuigi Rizzo [0x24] = "NEC DOS", 15822fccf5cSLuigi Rizzo [0x3C] = "PartitionMagic recovery", 15922fccf5cSLuigi Rizzo [0x39] = "plan9", 16022fccf5cSLuigi Rizzo [0x40] = "VENIX 286", 16122fccf5cSLuigi Rizzo [0x41] = "Linux/MINIX (sharing disk with DRDOS)", 16222fccf5cSLuigi Rizzo [0x42] = "SFS or Linux swap (sharing disk with DRDOS)", 16322fccf5cSLuigi Rizzo [0x43] = "Linux native (sharing disk with DRDOS)", 16422fccf5cSLuigi Rizzo [0x4D] = "QNX 4.2 Primary", 16522fccf5cSLuigi Rizzo [0x4E] = "QNX 4.2 Secondary", 16622fccf5cSLuigi Rizzo [0x4F] = "QNX 4.2 Tertiary", 16722fccf5cSLuigi Rizzo [0x50] = "DM (disk manager)", 16822fccf5cSLuigi Rizzo [0x51] = "DM6 Aux1 (or Novell)", 16922fccf5cSLuigi Rizzo [0x52] = "CP/M or Microport SysV/AT", 17022fccf5cSLuigi Rizzo [0x53] = "DM6 Aux3", 17122fccf5cSLuigi Rizzo [0x54] = "DM6", 17222fccf5cSLuigi Rizzo [0x55] = "EZ-Drive (disk manager)", 17322fccf5cSLuigi Rizzo [0x56] = "Golden Bow (disk manager)", 17422fccf5cSLuigi Rizzo [0x5c] = "Priam Edisk (disk manager)", /* according to S. Widlake */ 17522fccf5cSLuigi Rizzo [0x61] = "SpeedStor", 17622fccf5cSLuigi Rizzo [0x63] = "System V/386 (such as ISC UNIX), GNU HURD or Mach", 17722fccf5cSLuigi Rizzo [0x64] = "Novell Netware/286 2.xx", 17822fccf5cSLuigi Rizzo [0x65] = "Novell Netware/386 3.xx", 17922fccf5cSLuigi Rizzo [0x70] = "DiskSecure Multi-Boot", 18022fccf5cSLuigi Rizzo [0x75] = "PCIX", 18122fccf5cSLuigi Rizzo [0x77] = "QNX4.x", 18222fccf5cSLuigi Rizzo [0x78] = "QNX4.x 2nd part", 18322fccf5cSLuigi Rizzo [0x79] = "QNX4.x 3rd part", 18422fccf5cSLuigi Rizzo [0x80] = "Minix until 1.4a", 18522fccf5cSLuigi Rizzo [0x81] = "Minix since 1.4b, early Linux partition or Mitac disk manager", 18622fccf5cSLuigi Rizzo [0x82] = "Linux swap or Solaris x86", 18722fccf5cSLuigi Rizzo [0x83] = "Linux native", 18822fccf5cSLuigi Rizzo [0x84] = "OS/2 hidden C: drive", 18922fccf5cSLuigi Rizzo [0x85] = "Linux extended", 19022fccf5cSLuigi Rizzo [0x86] = "NTFS volume set??", 19122fccf5cSLuigi Rizzo [0x87] = "NTFS volume set??", 19222fccf5cSLuigi Rizzo [0x93] = "Amoeba file system", 19322fccf5cSLuigi Rizzo [0x94] = "Amoeba bad block table", 19422fccf5cSLuigi Rizzo [0x9F] = "BSD/OS", 19522fccf5cSLuigi Rizzo [0xA0] = "Suspend to Disk", 19622fccf5cSLuigi Rizzo [0xA5] = "FreeBSD/NetBSD/386BSD", 19722fccf5cSLuigi Rizzo [0xA6] = "OpenBSD", 19822fccf5cSLuigi Rizzo [0xA7] = "NeXTSTEP", 19922fccf5cSLuigi Rizzo [0xA9] = "NetBSD", 20022fccf5cSLuigi Rizzo [0xAC] = "IBM JFS", 20122fccf5cSLuigi Rizzo [0xAF] = "HFS+", 20222fccf5cSLuigi Rizzo [0xB7] = "BSDI BSD/386 file system", 20322fccf5cSLuigi Rizzo [0xB8] = "BSDI BSD/386 swap", 20422fccf5cSLuigi Rizzo [0xBE] = "Solaris x86 boot", 20522fccf5cSLuigi Rizzo [0xBF] = "Solaris x86 (new)", 20622fccf5cSLuigi Rizzo [0xC1] = "DRDOS/sec with 12-bit FAT", 20722fccf5cSLuigi Rizzo [0xC4] = "DRDOS/sec with 16-bit FAT (< 32MB)", 20822fccf5cSLuigi Rizzo [0xC6] = "DRDOS/sec with 16-bit FAT (>= 32MB)", 20922fccf5cSLuigi Rizzo [0xC7] = "Syrinx", 21022fccf5cSLuigi Rizzo [0xDB] = "CP/M, Concurrent CP/M, Concurrent DOS or CTOS", 21131fade05SLuigi Rizzo [0xDE] = "DELL Utilities - FAT filesystem", 21222fccf5cSLuigi Rizzo [0xE1] = "DOS access or SpeedStor with 12-bit FAT extended partition", 21322fccf5cSLuigi Rizzo [0xE3] = "DOS R/O or SpeedStor", 21422fccf5cSLuigi Rizzo [0xE4] = "SpeedStor with 16-bit FAT extended partition < 1024 cyl.", 21522fccf5cSLuigi Rizzo [0xEB] = "BeOS file system", 21622fccf5cSLuigi Rizzo [0xEE] = "EFI GPT", 21722fccf5cSLuigi Rizzo [0xEF] = "EFI System Partition", 21822fccf5cSLuigi Rizzo [0xF1] = "SpeedStor", 21922fccf5cSLuigi Rizzo [0xF2] = "DOS 3.3+ Secondary", 22022fccf5cSLuigi Rizzo [0xF4] = "SpeedStor large partition", 22122fccf5cSLuigi Rizzo [0xFE] = "SpeedStor >1024 cyl. or LANstep", 22222fccf5cSLuigi Rizzo [0xFF] = "Xenix bad blocks table", 2235b81b6b3SRodney W. Grimes }; 2245b81b6b3SRodney W. Grimes 22522fccf5cSLuigi Rizzo static const char * 22622fccf5cSLuigi Rizzo get_type(int t) 22722fccf5cSLuigi Rizzo { 22822fccf5cSLuigi Rizzo const char *ret; 22922fccf5cSLuigi Rizzo 23022fccf5cSLuigi Rizzo ret = (t >= 0 && t <= 255) ? part_types[t] : NULL; 23122fccf5cSLuigi Rizzo return ret ? ret : "unknown"; 23222fccf5cSLuigi Rizzo } 23322fccf5cSLuigi Rizzo 23422fccf5cSLuigi Rizzo 235fbcb16efSLuigi Rizzo static void print_s0(void); 23640905b6eSLuigi Rizzo static void print_part(const struct dos_partition *); 2374be1e61bSAlexander Langer static void init_sector0(unsigned long start); 238f46af505SJordan K. Hubbard static void init_boot(void); 2394be1e61bSAlexander Langer static void change_part(int i); 240041b8b00SPoul-Henning Kamp static void print_params(void); 2414be1e61bSAlexander Langer static void change_active(int which); 242041b8b00SPoul-Henning Kamp static void change_code(void); 243041b8b00SPoul-Henning Kamp static void get_params_to_use(void); 244df77f711SJoerg Wunsch static char *get_rootdisk(void); 24563692187SIan Dowse static void dos(struct dos_partition *partp); 246041b8b00SPoul-Henning Kamp static int open_disk(int flag); 2474be1e61bSAlexander Langer static ssize_t read_disk(off_t sector, void *buf); 248de78c288SPoul-Henning Kamp static int write_disk(off_t sector, void *buf); 249041b8b00SPoul-Henning Kamp static int get_params(void); 250041b8b00SPoul-Henning Kamp static int read_s0(void); 251041b8b00SPoul-Henning Kamp static int write_s0(void); 252041b8b00SPoul-Henning Kamp static int ok(const char *str); 2534be78ce3SMaxim Sobolev static int decimal(const char *str, int *num, int deflt, uint32_t maxval); 254f46af505SJordan K. Hubbard static int read_config(char *config_file); 255f46af505SJordan K. Hubbard static void reset_boot(void); 256b594e0feSJohn Baldwin static int sanitize_partition(struct dos_partition *); 257d98b1668SPhilippe Charnier static void usage(void); 2584be1e61bSAlexander Langer 2594be1e61bSAlexander Langer int 2604be1e61bSAlexander Langer main(int argc, char *argv[]) 2615b81b6b3SRodney W. Grimes { 26226721a89SRobert Nordier int c, i; 263041b8b00SPoul-Henning Kamp int partition = -1; 264041b8b00SPoul-Henning Kamp struct dos_partition *partp; 2655b81b6b3SRodney W. Grimes 266a61d9186SDavid E. O'Brien while ((c = getopt(argc, argv, "BIab:f:ipqstuv1234")) != -1) 26726721a89SRobert Nordier switch (c) { 26826721a89SRobert Nordier case 'B': 26926721a89SRobert Nordier B_flag = 1; 2704ddd60b9SBrian Somers break; 27110b0ee93SWarner Losh case 'I': 27210b0ee93SWarner Losh I_flag = 1; 27310b0ee93SWarner Losh break; 2745b81b6b3SRodney W. Grimes case 'a': 2755b81b6b3SRodney W. Grimes a_flag = 1; 2765b81b6b3SRodney W. Grimes break; 27712d910e9SRobert Nordier case 'b': 27826721a89SRobert Nordier b_flag = optarg; 27912d910e9SRobert Nordier break; 280f46af505SJordan K. Hubbard case 'f': 28126721a89SRobert Nordier f_flag = optarg; 282f46af505SJordan K. Hubbard break; 2835b81b6b3SRodney W. Grimes case 'i': 2845b81b6b3SRodney W. Grimes i_flag = 1; 2855b81b6b3SRodney W. Grimes break; 2867914c60fSMaxim Konovalov case 'p': 2877914c60fSMaxim Konovalov print_config_flag = 1; 2887914c60fSMaxim Konovalov break; 289a61d9186SDavid E. O'Brien case 'q': 290a61d9186SDavid E. O'Brien q_flag = 1; 291a61d9186SDavid E. O'Brien break; 29210b0ee93SWarner Losh case 's': 29310b0ee93SWarner Losh s_flag = 1; 29410b0ee93SWarner Losh break; 295f46af505SJordan K. Hubbard case 't': 296f46af505SJordan K. Hubbard t_flag = 1; 29726721a89SRobert Nordier break; 29826721a89SRobert Nordier case 'u': 29926721a89SRobert Nordier u_flag = 1; 30026721a89SRobert Nordier break; 301f46af505SJordan K. Hubbard case 'v': 302f46af505SJordan K. Hubbard v_flag = 1; 303f46af505SJordan K. Hubbard break; 30426721a89SRobert Nordier case '1': 30526721a89SRobert Nordier case '2': 30626721a89SRobert Nordier case '3': 30726721a89SRobert Nordier case '4': 30826721a89SRobert Nordier partition = c - '0'; 30926721a89SRobert Nordier break; 3105b81b6b3SRodney W. Grimes default: 311d98b1668SPhilippe Charnier usage(); 3125b81b6b3SRodney W. Grimes } 31326721a89SRobert Nordier if (f_flag || i_flag) 31426721a89SRobert Nordier u_flag = 1; 31526721a89SRobert Nordier if (t_flag) 31626721a89SRobert Nordier v_flag = 1; 31726721a89SRobert Nordier argc -= optind; 31826721a89SRobert Nordier argv += optind; 3195b81b6b3SRodney W. Grimes 320df77f711SJoerg Wunsch if (argc == 0) { 321df77f711SJoerg Wunsch disk = get_rootdisk(); 322df77f711SJoerg Wunsch } else { 323b31e5ae2SUlf Lilleengen disk = g_device_path(argv[0]); 324041b8b00SPoul-Henning Kamp if (disk == NULL) 325c4898ccbSLuigi Rizzo err(1, "unable to get correct path for %s", argv[0]); 326df77f711SJoerg Wunsch } 3275b81b6b3SRodney W. Grimes if (open_disk(u_flag) < 0) 328d98b1668SPhilippe Charnier err(1, "cannot open disk %s", disk); 32985c2cf30SJohn Baldwin 33085c2cf30SJohn Baldwin /* (abu)use mboot.bootinst to probe for the sector size */ 33185c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(MAX_SEC_SIZE)) == NULL) 33285c2cf30SJohn Baldwin err(1, "cannot allocate buffer to determine disk sector size"); 333aee85526SSimon L. B. Nielsen if (read_disk(0, mboot.bootinst) == -1) 334aee85526SSimon L. B. Nielsen errx(1, "could not detect sector size"); 335a12de062SJohn Baldwin free(mboot.bootinst); 336a12de062SJohn Baldwin mboot.bootinst = NULL; 33785c2cf30SJohn Baldwin 3387914c60fSMaxim Konovalov if (print_config_flag) { 3397914c60fSMaxim Konovalov if (read_s0()) 3407914c60fSMaxim Konovalov err(1, "read_s0"); 3417914c60fSMaxim Konovalov 3427914c60fSMaxim Konovalov printf("# %s\n", disk); 3437914c60fSMaxim Konovalov printf("g c%d h%d s%d\n", dos_cyls, dos_heads, dos_sectors); 3447914c60fSMaxim Konovalov 3457914c60fSMaxim Konovalov for (i = 0; i < NDOSPART; i++) { 346c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 3477914c60fSMaxim Konovalov 3487914c60fSMaxim Konovalov if (partp->dp_start == 0 && partp->dp_size == 0) 3497914c60fSMaxim Konovalov continue; 3507914c60fSMaxim Konovalov 3517914c60fSMaxim Konovalov printf("p %d 0x%02x %lu %lu\n", i + 1, partp->dp_typ, 3527914c60fSMaxim Konovalov (u_long)partp->dp_start, (u_long)partp->dp_size); 3537914c60fSMaxim Konovalov 3547914c60fSMaxim Konovalov /* Fill flags for the partition. */ 3557914c60fSMaxim Konovalov if (partp->dp_flag & 0x80) 3567914c60fSMaxim Konovalov printf("a %d\n", i + 1); 3577914c60fSMaxim Konovalov } 3587914c60fSMaxim Konovalov exit(0); 3597914c60fSMaxim Konovalov } 360041b8b00SPoul-Henning Kamp if (s_flag) { 36110b0ee93SWarner Losh if (read_s0()) 36210b0ee93SWarner Losh err(1, "read_s0"); 36310b0ee93SWarner Losh printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, 36410b0ee93SWarner Losh dos_sectors); 36510b0ee93SWarner Losh printf("Part %11s %11s Type Flags\n", "Start", "Size"); 36610b0ee93SWarner Losh for (i = 0; i < NDOSPART; i++) { 367c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 36810b0ee93SWarner Losh if (partp->dp_start == 0 && partp->dp_size == 0) 36910b0ee93SWarner Losh continue; 37010b0ee93SWarner Losh printf("%4d: %11lu %11lu 0x%02x 0x%02x\n", i + 1, 37110b0ee93SWarner Losh (u_long) partp->dp_start, 37210b0ee93SWarner Losh (u_long) partp->dp_size, partp->dp_typ, 37310b0ee93SWarner Losh partp->dp_flag); 37410b0ee93SWarner Losh } 37510b0ee93SWarner Losh exit(0); 37610b0ee93SWarner Losh } 3775b81b6b3SRodney W. Grimes 3785b81b6b3SRodney W. Grimes printf("******* Working on device %s *******\n",disk); 379f46af505SJordan K. Hubbard 380041b8b00SPoul-Henning Kamp if (I_flag) { 381e6fb3ddeSPoul-Henning Kamp read_s0(); 382e6fb3ddeSPoul-Henning Kamp reset_boot(); 383c4898ccbSLuigi Rizzo partp = &mboot.parts[0]; 384e6fb3ddeSPoul-Henning Kamp partp->dp_typ = DOSPTYP_386BSD; 385e6fb3ddeSPoul-Henning Kamp partp->dp_flag = ACTIVE; 386e6fb3ddeSPoul-Henning Kamp partp->dp_start = dos_sectors; 387b594e0feSJohn Baldwin partp->dp_size = (disksecs / dos_cylsecs) * dos_cylsecs - 388b594e0feSJohn Baldwin dos_sectors; 38963692187SIan Dowse dos(partp); 390e6fb3ddeSPoul-Henning Kamp if (v_flag) 391fbcb16efSLuigi Rizzo print_s0(); 39205a213f1STom Rhodes if (!t_flag) 393e6fb3ddeSPoul-Henning Kamp write_s0(); 394e6fb3ddeSPoul-Henning Kamp exit(0); 395e6fb3ddeSPoul-Henning Kamp } 396041b8b00SPoul-Henning Kamp if (f_flag) { 397f46af505SJordan K. Hubbard if (read_s0() || i_flag) 398f46af505SJordan K. Hubbard reset_boot(); 399f46af505SJordan K. Hubbard if (!read_config(f_flag)) 400f46af505SJordan K. Hubbard exit(1); 401f46af505SJordan K. Hubbard if (v_flag) 402fbcb16efSLuigi Rizzo print_s0(); 403f46af505SJordan K. Hubbard if (!t_flag) 404f46af505SJordan K. Hubbard write_s0(); 405041b8b00SPoul-Henning Kamp } else { 4065b81b6b3SRodney W. Grimes if(u_flag) 4075b81b6b3SRodney W. Grimes get_params_to_use(); 4085b81b6b3SRodney W. Grimes else 4095b81b6b3SRodney W. Grimes print_params(); 4105b81b6b3SRodney W. Grimes 4115b81b6b3SRodney W. Grimes if (read_s0()) 412b594e0feSJohn Baldwin init_sector0(dos_sectors); 4135b81b6b3SRodney W. Grimes 4147cb29d33SSøren Schmidt printf("Media sector size is %d\n", secsize); 4155b81b6b3SRodney W. Grimes printf("Warning: BIOS sector numbering starts with sector 1\n"); 4165b81b6b3SRodney W. Grimes printf("Information from DOS bootblock is:\n"); 4175b81b6b3SRodney W. Grimes if (partition == -1) 4184ddd60b9SBrian Somers for (i = 1; i <= NDOSPART; i++) 4195b81b6b3SRodney W. Grimes change_part(i); 4205b81b6b3SRodney W. Grimes else 4215b81b6b3SRodney W. Grimes change_part(partition); 4225b81b6b3SRodney W. Grimes 4235b81b6b3SRodney W. Grimes if (u_flag || a_flag) 4245b81b6b3SRodney W. Grimes change_active(partition); 4255b81b6b3SRodney W. Grimes 42626721a89SRobert Nordier if (B_flag) 42712d910e9SRobert Nordier change_code(); 42812d910e9SRobert Nordier 42926721a89SRobert Nordier if (u_flag || a_flag || B_flag) { 430041b8b00SPoul-Henning Kamp if (!t_flag) { 4315b81b6b3SRodney W. Grimes printf("\nWe haven't changed the partition table yet. "); 4325b81b6b3SRodney W. Grimes printf("This is your last chance.\n"); 433f46af505SJordan K. Hubbard } 434fbcb16efSLuigi Rizzo print_s0(); 435041b8b00SPoul-Henning Kamp if (!t_flag) { 4365b81b6b3SRodney W. Grimes if (ok("Should we write new partition table?")) 4375b81b6b3SRodney W. Grimes write_s0(); 438041b8b00SPoul-Henning Kamp } else { 439f46af505SJordan K. Hubbard printf("\n-t flag specified -- partition table not written.\n"); 440f46af505SJordan K. Hubbard } 441f46af505SJordan K. Hubbard } 442f46af505SJordan K. Hubbard } 4435b81b6b3SRodney W. Grimes 4445b81b6b3SRodney W. Grimes exit(0); 445d98b1668SPhilippe Charnier } 4465b81b6b3SRodney W. Grimes 447d98b1668SPhilippe Charnier static void 448d98b1668SPhilippe Charnier usage() 449d98b1668SPhilippe Charnier { 45026721a89SRobert Nordier fprintf(stderr, "%s%s", 451a61d9186SDavid E. O'Brien "usage: fdisk [-BIaipqstu] [-b bootcode] [-1234] [disk]\n", 45226721a89SRobert Nordier " fdisk -f configfile [-itv] [disk]\n"); 453d98b1668SPhilippe Charnier exit(1); 4545b81b6b3SRodney W. Grimes } 4555b81b6b3SRodney W. Grimes 4564be1e61bSAlexander Langer static void 457fbcb16efSLuigi Rizzo print_s0(void) 4585b81b6b3SRodney W. Grimes { 4595b81b6b3SRodney W. Grimes int i; 4605b81b6b3SRodney W. Grimes 4615b81b6b3SRodney W. Grimes print_params(); 4625b81b6b3SRodney W. Grimes printf("Information from DOS bootblock is:\n"); 46340905b6eSLuigi Rizzo for (i = 1; i <= NDOSPART; i++) { 46440905b6eSLuigi Rizzo printf("%d: ", i); 46540905b6eSLuigi Rizzo print_part(&mboot.parts[i - 1]); 46640905b6eSLuigi Rizzo } 4675b81b6b3SRodney W. Grimes } 4685b81b6b3SRodney W. Grimes 469041b8b00SPoul-Henning Kamp static struct dos_partition mtpart; 4705b81b6b3SRodney W. Grimes 4714be1e61bSAlexander Langer static void 47240905b6eSLuigi Rizzo print_part(const struct dos_partition *partp) 4735b81b6b3SRodney W. Grimes { 474637fe2f7SJustin T. Gibbs u_int64_t part_mb; 4755b81b6b3SRodney W. Grimes 4765b81b6b3SRodney W. Grimes if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 4775b81b6b3SRodney W. Grimes printf("<UNUSED>\n"); 4785b81b6b3SRodney W. Grimes return; 4795b81b6b3SRodney W. Grimes } 480637fe2f7SJustin T. Gibbs /* 481637fe2f7SJustin T. Gibbs * Be careful not to overflow. 482637fe2f7SJustin T. Gibbs */ 483637fe2f7SJustin T. Gibbs part_mb = partp->dp_size; 484637fe2f7SJustin T. Gibbs part_mb *= secsize; 485637fe2f7SJustin T. Gibbs part_mb /= (1024 * 1024); 486978d3bfeSJosef Karthauser printf("sysid %d (%#04x),(%s)\n", partp->dp_typ, partp->dp_typ, 487978d3bfeSJosef Karthauser get_type(partp->dp_typ)); 488689fee87SBruce Evans printf(" start %lu, size %lu (%ju Meg), flag %x%s\n", 489ba198492SBruce Evans (u_long)partp->dp_start, 490ba198492SBruce Evans (u_long)partp->dp_size, 491689fee87SBruce Evans (uintmax_t)part_mb, 492680426beSDavid E. O'Brien partp->dp_flag, 493680426beSDavid E. O'Brien partp->dp_flag == ACTIVE ? " (active)" : ""); 4946580291bSDavid E. O'Brien printf("\tbeg: cyl %d/ head %d/ sector %d;\n\tend: cyl %d/ head %d/ sector %d\n" 4955b81b6b3SRodney W. Grimes ,DPCYL(partp->dp_scyl, partp->dp_ssect) 4965b81b6b3SRodney W. Grimes ,partp->dp_shd 4976580291bSDavid E. O'Brien ,DPSECT(partp->dp_ssect) 4985b81b6b3SRodney W. Grimes ,DPCYL(partp->dp_ecyl, partp->dp_esect) 4996580291bSDavid E. O'Brien ,partp->dp_ehd 5006580291bSDavid E. O'Brien ,DPSECT(partp->dp_esect)); 5015b81b6b3SRodney W. Grimes } 5025b81b6b3SRodney W. Grimes 503f46af505SJordan K. Hubbard 504f46af505SJordan K. Hubbard static void 505f46af505SJordan K. Hubbard init_boot(void) 506f46af505SJordan K. Hubbard { 50729ea697dSPeter Wemm #ifndef __ia64__ 50826721a89SRobert Nordier const char *fname; 509041b8b00SPoul-Henning Kamp int fdesc, n; 51085c2cf30SJohn Baldwin struct stat sb; 51126721a89SRobert Nordier 51226721a89SRobert Nordier fname = b_flag ? b_flag : "/boot/mbr"; 513041b8b00SPoul-Henning Kamp if ((fdesc = open(fname, O_RDONLY)) == -1 || 514041b8b00SPoul-Henning Kamp fstat(fdesc, &sb) == -1) 51585c2cf30SJohn Baldwin err(1, "%s", fname); 516469a1218SJohn-Mark Gurney if (sb.st_size == 0) 517469a1218SJohn-Mark Gurney errx(1, "%s is empty, must not be.", fname); 51885c2cf30SJohn Baldwin if ((mboot.bootinst_size = sb.st_size) % secsize != 0) 51985c2cf30SJohn Baldwin errx(1, "%s: length must be a multiple of sector size", fname); 5202b5ce8a9SAndrey A. Chernov if (mboot.bootinst != NULL) 5212b5ce8a9SAndrey A. Chernov free(mboot.bootinst); 52285c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(mboot.bootinst_size = sb.st_size)) == NULL) 52385c2cf30SJohn Baldwin errx(1, "%s: unable to allocate read buffer", fname); 524041b8b00SPoul-Henning Kamp if ((n = read(fdesc, mboot.bootinst, mboot.bootinst_size)) == -1 || 525041b8b00SPoul-Henning Kamp close(fdesc)) 52626721a89SRobert Nordier err(1, "%s", fname); 52785c2cf30SJohn Baldwin if (n != mboot.bootinst_size) 52885c2cf30SJohn Baldwin errx(1, "%s: short read", fname); 52929ea697dSPeter Wemm #else 53029ea697dSPeter Wemm if (mboot.bootinst != NULL) 53129ea697dSPeter Wemm free(mboot.bootinst); 53229ea697dSPeter Wemm mboot.bootinst_size = secsize; 53329ea697dSPeter Wemm if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) 53429ea697dSPeter Wemm errx(1, "unable to allocate boot block buffer"); 53529ea697dSPeter Wemm memset(mboot.bootinst, 0, mboot.bootinst_size); 5361a03d6d5SPoul-Henning Kamp le16enc(&mboot.bootinst[DOSMAGICOFFSET], DOSMAGIC); 53729ea697dSPeter Wemm #endif 538f46af505SJordan K. Hubbard } 539f46af505SJordan K. Hubbard 540f46af505SJordan K. Hubbard 5414be1e61bSAlexander Langer static void 5424be1e61bSAlexander Langer init_sector0(unsigned long start) 5435b81b6b3SRodney W. Grimes { 544c4898ccbSLuigi Rizzo struct dos_partition *partp = &mboot.parts[0]; 5455b81b6b3SRodney W. Grimes 546f46af505SJordan K. Hubbard init_boot(); 5475b81b6b3SRodney W. Grimes 5485b81b6b3SRodney W. Grimes partp->dp_typ = DOSPTYP_386BSD; 5495b81b6b3SRodney W. Grimes partp->dp_flag = ACTIVE; 550b594e0feSJohn Baldwin start = ((start + dos_sectors - 1) / dos_sectors) * dos_sectors; 55185c2cf30SJohn Baldwin if(start == 0) 55285c2cf30SJohn Baldwin start = dos_sectors; 5535b81b6b3SRodney W. Grimes partp->dp_start = start; 554b594e0feSJohn Baldwin partp->dp_size = (disksecs / dos_cylsecs) * dos_cylsecs - start; 5555b81b6b3SRodney W. Grimes 55663692187SIan Dowse dos(partp); 5575b81b6b3SRodney W. Grimes } 5585b81b6b3SRodney W. Grimes 5594be1e61bSAlexander Langer static void 5604be1e61bSAlexander Langer change_part(int i) 5615b81b6b3SRodney W. Grimes { 562c4898ccbSLuigi Rizzo struct dos_partition *partp = &mboot.parts[i - 1]; 5635b81b6b3SRodney W. Grimes 5645b81b6b3SRodney W. Grimes printf("The data for partition %d is:\n", i); 56540905b6eSLuigi Rizzo print_part(partp); 5665b81b6b3SRodney W. Grimes 5675b81b6b3SRodney W. Grimes if (u_flag && ok("Do you want to change it?")) { 5685b81b6b3SRodney W. Grimes int tmp; 5695b81b6b3SRodney W. Grimes 5705b81b6b3SRodney W. Grimes if (i_flag) { 571c4898ccbSLuigi Rizzo bzero(partp, sizeof (*partp)); 572a67ed623SPoul-Henning Kamp if (i == 1) { 5735b81b6b3SRodney W. Grimes init_sector0(1); 574a67ed623SPoul-Henning Kamp printf("\nThe static data for the slice 1 has been reinitialized to:\n"); 57540905b6eSLuigi Rizzo print_part(partp); 5765b81b6b3SRodney W. Grimes } 5775b81b6b3SRodney W. Grimes } 5785b81b6b3SRodney W. Grimes 5795b81b6b3SRodney W. Grimes do { 5804be78ce3SMaxim Sobolev Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp, 255); 5814be78ce3SMaxim Sobolev Decimal("start", partp->dp_start, tmp, NO_DISK_SECTORS); 5824be78ce3SMaxim Sobolev Decimal("size", partp->dp_size, tmp, NO_DISK_SECTORS); 58363692187SIan Dowse if (!sanitize_partition(partp)) { 58463692187SIan Dowse warnx("ERROR: failed to adjust; setting sysid to 0"); 58563692187SIan Dowse partp->dp_typ = 0; 58663692187SIan Dowse } 5875b81b6b3SRodney W. Grimes 5884b3b45a7SJames Raynard if (ok("Explicitly specify beg/end address ?")) 5895b81b6b3SRodney W. Grimes { 5905b81b6b3SRodney W. Grimes int tsec,tcyl,thd; 5915b81b6b3SRodney W. Grimes tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 5925b81b6b3SRodney W. Grimes thd = partp->dp_shd; 5935b81b6b3SRodney W. Grimes tsec = DPSECT(partp->dp_ssect); 5944be78ce3SMaxim Sobolev Decimal("beginning cylinder", tcyl, tmp, NO_TRACK_CYLINDERS); 5954be78ce3SMaxim Sobolev Decimal("beginning head", thd, tmp, NO_TRACK_HEADS); 5964be78ce3SMaxim Sobolev Decimal("beginning sector", tsec, tmp, NO_TRACK_SECTORS); 5975b81b6b3SRodney W. Grimes partp->dp_scyl = DOSCYL(tcyl); 5985b81b6b3SRodney W. Grimes partp->dp_ssect = DOSSECT(tsec,tcyl); 5995b81b6b3SRodney W. Grimes partp->dp_shd = thd; 6005b81b6b3SRodney W. Grimes 6015b81b6b3SRodney W. Grimes tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 6025b81b6b3SRodney W. Grimes thd = partp->dp_ehd; 6035b81b6b3SRodney W. Grimes tsec = DPSECT(partp->dp_esect); 6044be78ce3SMaxim Sobolev Decimal("ending cylinder", tcyl, tmp, NO_TRACK_CYLINDERS); 6054be78ce3SMaxim Sobolev Decimal("ending head", thd, tmp, NO_TRACK_HEADS); 6064be78ce3SMaxim Sobolev Decimal("ending sector", tsec, tmp, NO_TRACK_SECTORS); 6075b81b6b3SRodney W. Grimes partp->dp_ecyl = DOSCYL(tcyl); 6085b81b6b3SRodney W. Grimes partp->dp_esect = DOSSECT(tsec,tcyl); 6095b81b6b3SRodney W. Grimes partp->dp_ehd = thd; 61063692187SIan Dowse } else 61163692187SIan Dowse dos(partp); 6125b81b6b3SRodney W. Grimes 61340905b6eSLuigi Rizzo print_part(partp); 6145b81b6b3SRodney W. Grimes } while (!ok("Are we happy with this entry?")); 6155b81b6b3SRodney W. Grimes } 6165b81b6b3SRodney W. Grimes } 6175b81b6b3SRodney W. Grimes 6184be1e61bSAlexander Langer static void 6195b81b6b3SRodney W. Grimes print_params() 6205b81b6b3SRodney W. Grimes { 6215b81b6b3SRodney W. Grimes printf("parameters extracted from in-core disklabel are:\n"); 6225b81b6b3SRodney W. Grimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 6235b81b6b3SRodney W. Grimes ,cyls,heads,sectors,cylsecs); 6247fa181d4SYoshihiro Takahashi if (dos_cyls > 1023 || dos_heads > 255 || dos_sectors > 63) 6255b81b6b3SRodney W. Grimes printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 6265b81b6b3SRodney W. Grimes printf("parameters to be used for BIOS calculations are:\n"); 6275b81b6b3SRodney W. Grimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 6285b81b6b3SRodney W. Grimes ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 6295b81b6b3SRodney W. Grimes } 6305b81b6b3SRodney W. Grimes 6314be1e61bSAlexander Langer static void 6324be1e61bSAlexander Langer change_active(int which) 6335b81b6b3SRodney W. Grimes { 63463692187SIan Dowse struct dos_partition *partp = &mboot.parts[0]; 63563692187SIan Dowse int active, i, new, tmp; 6365b81b6b3SRodney W. Grimes 63763692187SIan Dowse active = -1; 63863692187SIan Dowse for (i = 0; i < NDOSPART; i++) { 63963692187SIan Dowse if ((partp[i].dp_flag & ACTIVE) == 0) 64063692187SIan Dowse continue; 64163692187SIan Dowse printf("Partition %d is marked active\n", i + 1); 64263692187SIan Dowse if (active == -1) 64363692187SIan Dowse active = i + 1; 64463692187SIan Dowse } 6455b81b6b3SRodney W. Grimes if (a_flag && which != -1) 6465b81b6b3SRodney W. Grimes active = which; 64763692187SIan Dowse else if (active == -1) 64863692187SIan Dowse active = 1; 64963692187SIan Dowse 6500b461cd7SBruce Evans if (!ok("Do you want to change the active partition?")) 6510b461cd7SBruce Evans return; 652680426beSDavid E. O'Brien setactive: 653680426beSDavid E. O'Brien do { 65463692187SIan Dowse new = active; 65568df7abeSMaxim Sobolev Decimal("active partition", new, tmp, 0); 65663692187SIan Dowse if (new < 1 || new > 4) { 657680426beSDavid E. O'Brien printf("Active partition number must be in range 1-4." 658680426beSDavid E. O'Brien " Try again.\n"); 659680426beSDavid E. O'Brien goto setactive; 660680426beSDavid E. O'Brien } 66163692187SIan Dowse active = new; 662680426beSDavid E. O'Brien } while (!ok("Are you happy with this choice")); 6635b81b6b3SRodney W. Grimes for (i = 0; i < NDOSPART; i++) 6645b81b6b3SRodney W. Grimes partp[i].dp_flag = 0; 6654ddd60b9SBrian Somers if (active > 0 && active <= NDOSPART) 6664ddd60b9SBrian Somers partp[active-1].dp_flag = ACTIVE; 6675b81b6b3SRodney W. Grimes } 6685b81b6b3SRodney W. Grimes 66912d910e9SRobert Nordier static void 67012d910e9SRobert Nordier change_code() 67112d910e9SRobert Nordier { 67212d910e9SRobert Nordier if (ok("Do you want to change the boot code?")) 67312d910e9SRobert Nordier init_boot(); 67412d910e9SRobert Nordier } 67512d910e9SRobert Nordier 6764be1e61bSAlexander Langer void 6775b81b6b3SRodney W. Grimes get_params_to_use() 6785b81b6b3SRodney W. Grimes { 6795b81b6b3SRodney W. Grimes int tmp; 6805b81b6b3SRodney W. Grimes print_params(); 6815b81b6b3SRodney W. Grimes if (ok("Do you want to change our idea of what BIOS thinks ?")) 6825b81b6b3SRodney W. Grimes { 6835b81b6b3SRodney W. Grimes do 6845b81b6b3SRodney W. Grimes { 68568df7abeSMaxim Sobolev Decimal("BIOS's idea of #cylinders", dos_cyls, tmp, 0); 68668df7abeSMaxim Sobolev Decimal("BIOS's idea of #heads", dos_heads, tmp, 0); 68768df7abeSMaxim Sobolev Decimal("BIOS's idea of #sectors", dos_sectors, tmp, 0); 6885b81b6b3SRodney W. Grimes dos_cylsecs = dos_heads * dos_sectors; 6895b81b6b3SRodney W. Grimes print_params(); 6905b81b6b3SRodney W. Grimes } 6915b81b6b3SRodney W. Grimes while(!ok("Are you happy with this choice")); 6925b81b6b3SRodney W. Grimes } 6935b81b6b3SRodney W. Grimes } 6945b81b6b3SRodney W. Grimes 695f46af505SJordan K. Hubbard 6965b81b6b3SRodney W. Grimes /***********************************************\ 6975b81b6b3SRodney W. Grimes * Change real numbers into strange dos numbers * 6985b81b6b3SRodney W. Grimes \***********************************************/ 6994be1e61bSAlexander Langer static void 700041b8b00SPoul-Henning Kamp dos(struct dos_partition *partp) 7015b81b6b3SRodney W. Grimes { 70263692187SIan Dowse int cy, sec; 70363692187SIan Dowse u_int32_t end; 7045b81b6b3SRodney W. Grimes 705881c9063SIan Dowse if (partp->dp_typ == 0 && partp->dp_start == 0 && partp->dp_size == 0) { 706881c9063SIan Dowse memcpy(partp, &mtpart, sizeof(*partp)); 7070b461cd7SBruce Evans return; 7080b461cd7SBruce Evans } 7090b461cd7SBruce Evans 71063692187SIan Dowse /* Start c/h/s. */ 71163692187SIan Dowse partp->dp_shd = partp->dp_start % dos_cylsecs / dos_sectors; 71263692187SIan Dowse cy = partp->dp_start / dos_cylsecs; 71363692187SIan Dowse sec = partp->dp_start % dos_sectors + 1; 71463692187SIan Dowse partp->dp_scyl = DOSCYL(cy); 71563692187SIan Dowse partp->dp_ssect = DOSSECT(sec, cy); 7165b81b6b3SRodney W. Grimes 71763692187SIan Dowse /* End c/h/s. */ 71863692187SIan Dowse end = partp->dp_start + partp->dp_size - 1; 71963692187SIan Dowse partp->dp_ehd = end % dos_cylsecs / dos_sectors; 72063692187SIan Dowse cy = end / dos_cylsecs; 72163692187SIan Dowse sec = end % dos_sectors + 1; 72263692187SIan Dowse partp->dp_ecyl = DOSCYL(cy); 72363692187SIan Dowse partp->dp_esect = DOSSECT(sec, cy); 7245b81b6b3SRodney W. Grimes } 7255b81b6b3SRodney W. Grimes 7264be1e61bSAlexander Langer static int 727041b8b00SPoul-Henning Kamp open_disk(int flag) 7285b81b6b3SRodney W. Grimes { 729de78c288SPoul-Henning Kamp int rwmode; 7305b81b6b3SRodney W. Grimes 731b31e5ae2SUlf Lilleengen /* Write mode if one of these flags are set. */ 732b31e5ae2SUlf Lilleengen rwmode = (a_flag || I_flag || B_flag || flag); 733b31e5ae2SUlf Lilleengen fd = g_open(disk, rwmode); 734b31e5ae2SUlf Lilleengen /* If the mode fails, try read-only if we didn't. */ 735b31e5ae2SUlf Lilleengen if (fd == -1 && errno == EPERM && rwmode) 736b31e5ae2SUlf Lilleengen fd = g_open(disk, 0); 737f353c761SPoul-Henning Kamp if (fd == -1 && errno == ENXIO) 738e3038c6eSJoerg Wunsch return -2; 739f353c761SPoul-Henning Kamp if (fd == -1) { 740d98b1668SPhilippe Charnier warnx("can't open device %s", disk); 7415b81b6b3SRodney W. Grimes return -1; 7425b81b6b3SRodney W. Grimes } 743041b8b00SPoul-Henning Kamp if (get_params() == -1) { 744d98b1668SPhilippe Charnier warnx("can't get disk parameters on %s", disk); 7455b81b6b3SRodney W. Grimes return -1; 7465b81b6b3SRodney W. Grimes } 7475b81b6b3SRodney W. Grimes return fd; 7485b81b6b3SRodney W. Grimes } 7495b81b6b3SRodney W. Grimes 7504be1e61bSAlexander Langer static ssize_t 7514be1e61bSAlexander Langer read_disk(off_t sector, void *buf) 7525b81b6b3SRodney W. Grimes { 7537fa181d4SYoshihiro Takahashi 7545b81b6b3SRodney W. Grimes lseek(fd, (sector * 512), 0); 7557cb29d33SSøren Schmidt if (secsize == 0) 7567fa181d4SYoshihiro Takahashi for (secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; 7577fa181d4SYoshihiro Takahashi secsize *= 2) { 7587cb29d33SSøren Schmidt /* try the read */ 7597cb29d33SSøren Schmidt int size = read(fd, buf, secsize); 7607cb29d33SSøren Schmidt if (size == secsize) 7617cb29d33SSøren Schmidt /* it worked so return */ 7627cb29d33SSøren Schmidt return secsize; 7637cb29d33SSøren Schmidt } 7647cb29d33SSøren Schmidt else 7657cb29d33SSøren Schmidt return read(fd, buf, secsize); 7667cb29d33SSøren Schmidt 7677cb29d33SSøren Schmidt /* we failed to read at any of the sizes */ 7687cb29d33SSøren Schmidt return -1; 7695b81b6b3SRodney W. Grimes } 7705b81b6b3SRodney W. Grimes 771de78c288SPoul-Henning Kamp static int 7724be1e61bSAlexander Langer write_disk(off_t sector, void *buf) 7735b81b6b3SRodney W. Grimes { 774de78c288SPoul-Henning Kamp int error; 775de78c288SPoul-Henning Kamp struct gctl_req *grq; 776b31e5ae2SUlf Lilleengen const char *errmsg; 777b31e5ae2SUlf Lilleengen char fbuf[BUFSIZ], *pname; 778de78c288SPoul-Henning Kamp int i, fdw; 779f353c761SPoul-Henning Kamp 780de78c288SPoul-Henning Kamp grq = gctl_get_handle(); 781de78c288SPoul-Henning Kamp gctl_ro_param(grq, "verb", -1, "write MBR"); 782de78c288SPoul-Henning Kamp gctl_ro_param(grq, "class", -1, "MBR"); 783b31e5ae2SUlf Lilleengen pname = g_providername(fd); 784b31e5ae2SUlf Lilleengen if (pname == NULL) { 785bd5add58SUlf Lilleengen warn("Error getting providername for %s", disk); 786b31e5ae2SUlf Lilleengen return (-1); 787b31e5ae2SUlf Lilleengen } 788b31e5ae2SUlf Lilleengen gctl_ro_param(grq, "geom", -1, pname); 789de78c288SPoul-Henning Kamp gctl_ro_param(grq, "data", secsize, buf); 790b31e5ae2SUlf Lilleengen errmsg = gctl_issue(grq); 791b31e5ae2SUlf Lilleengen free(pname); 792b31e5ae2SUlf Lilleengen if (errmsg == NULL) { 793d63612b4SCraig Rodrigues gctl_free(grq); 794de78c288SPoul-Henning Kamp return(0); 795d63612b4SCraig Rodrigues } 796a61d9186SDavid E. O'Brien if (!q_flag) /* GEOM errors are benign, not all devices supported */ 797b31e5ae2SUlf Lilleengen warnx("%s", errmsg); 798d63612b4SCraig Rodrigues gctl_free(grq); 799de78c288SPoul-Henning Kamp 800de78c288SPoul-Henning Kamp error = pwrite(fd, buf, secsize, (sector * 512)); 801de78c288SPoul-Henning Kamp if (error == secsize) 802de78c288SPoul-Henning Kamp return (0); 803de78c288SPoul-Henning Kamp 804de78c288SPoul-Henning Kamp for (i = 1; i < 5; i++) { 805de78c288SPoul-Henning Kamp sprintf(fbuf, "%ss%d", disk, i); 806de78c288SPoul-Henning Kamp fdw = open(fbuf, O_RDWR, 0); 807de78c288SPoul-Henning Kamp if (fdw < 0) 808de78c288SPoul-Henning Kamp continue; 809de78c288SPoul-Henning Kamp error = ioctl(fdw, DIOCSMBR, buf); 810de78c288SPoul-Henning Kamp close(fdw); 811de78c288SPoul-Henning Kamp if (error == 0) 812de78c288SPoul-Henning Kamp return (0); 8135b81b6b3SRodney W. Grimes } 814de78c288SPoul-Henning Kamp warnx("Failed to write sector zero"); 815de78c288SPoul-Henning Kamp return(EINVAL); 816f353c761SPoul-Henning Kamp } 8175b81b6b3SRodney W. Grimes 8184be1e61bSAlexander Langer static int 8194be1e61bSAlexander Langer get_params() 8205b81b6b3SRodney W. Grimes { 8213f8ba8b5SPoul-Henning Kamp int error; 8223f8ba8b5SPoul-Henning Kamp u_int u; 8233f8ba8b5SPoul-Henning Kamp off_t o; 8245b81b6b3SRodney W. Grimes 8257963fae6SPoul-Henning Kamp error = ioctl(fd, DIOCGFWSECTORS, &u); 8267963fae6SPoul-Henning Kamp if (error == 0) 8277963fae6SPoul-Henning Kamp sectors = dos_sectors = u; 828c0fdfdbaSPoul-Henning Kamp else 829c0fdfdbaSPoul-Henning Kamp sectors = dos_sectors = 63; 830c0fdfdbaSPoul-Henning Kamp 8317963fae6SPoul-Henning Kamp error = ioctl(fd, DIOCGFWHEADS, &u); 8327963fae6SPoul-Henning Kamp if (error == 0) 8337963fae6SPoul-Henning Kamp heads = dos_heads = u; 834c0fdfdbaSPoul-Henning Kamp else 835c0fdfdbaSPoul-Henning Kamp heads = dos_heads = 255; 8367963fae6SPoul-Henning Kamp 8375b81b6b3SRodney W. Grimes dos_cylsecs = cylsecs = heads * sectors; 8385b81b6b3SRodney W. Grimes disksecs = cyls * heads * sectors; 8395b81b6b3SRodney W. Grimes 840b31e5ae2SUlf Lilleengen u = g_sectorsize(fd); 841b31e5ae2SUlf Lilleengen if (u <= 0) 842b31e5ae2SUlf Lilleengen return (-1); 8437963fae6SPoul-Henning Kamp 844b31e5ae2SUlf Lilleengen o = g_mediasize(fd); 845b31e5ae2SUlf Lilleengen if (o < 0) 846b31e5ae2SUlf Lilleengen return (-1); 8477963fae6SPoul-Henning Kamp disksecs = o / u; 8487963fae6SPoul-Henning Kamp cyls = dos_cyls = o / (u * dos_heads * dos_sectors); 8497963fae6SPoul-Henning Kamp 8505b81b6b3SRodney W. Grimes return (disksecs); 8515b81b6b3SRodney W. Grimes } 8525b81b6b3SRodney W. Grimes 8534be1e61bSAlexander Langer static int 8545b81b6b3SRodney W. Grimes read_s0() 8555b81b6b3SRodney W. Grimes { 8561a03d6d5SPoul-Henning Kamp int i; 8571a03d6d5SPoul-Henning Kamp 85885c2cf30SJohn Baldwin mboot.bootinst_size = secsize; 8592b5ce8a9SAndrey A. Chernov if (mboot.bootinst != NULL) 8602b5ce8a9SAndrey A. Chernov free(mboot.bootinst); 86185c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) { 86285c2cf30SJohn Baldwin warnx("unable to allocate buffer to read fdisk " 86385c2cf30SJohn Baldwin "partition table"); 86485c2cf30SJohn Baldwin return -1; 86585c2cf30SJohn Baldwin } 86685c2cf30SJohn Baldwin if (read_disk(0, mboot.bootinst) == -1) { 867d98b1668SPhilippe Charnier warnx("can't read fdisk partition table"); 8685b81b6b3SRodney W. Grimes return -1; 8695b81b6b3SRodney W. Grimes } 8701a03d6d5SPoul-Henning Kamp if (le16dec(&mboot.bootinst[DOSMAGICOFFSET]) != DOSMAGIC) { 871d98b1668SPhilippe Charnier warnx("invalid fdisk partition table found"); 8725b81b6b3SRodney W. Grimes /* So should we initialize things */ 8735b81b6b3SRodney W. Grimes return -1; 8745b81b6b3SRodney W. Grimes } 8751a03d6d5SPoul-Henning Kamp for (i = 0; i < NDOSPART; i++) 8761a03d6d5SPoul-Henning Kamp dos_partition_dec( 8771a03d6d5SPoul-Henning Kamp &mboot.bootinst[DOSPARTOFF + i * DOSPARTSIZE], 8781a03d6d5SPoul-Henning Kamp &mboot.parts[i]); 8795b81b6b3SRodney W. Grimes return 0; 8805b81b6b3SRodney W. Grimes } 8815b81b6b3SRodney W. Grimes 8824be1e61bSAlexander Langer static int 8835b81b6b3SRodney W. Grimes write_s0() 8845b81b6b3SRodney W. Grimes { 8851a03d6d5SPoul-Henning Kamp int sector, i; 88685c2cf30SJohn Baldwin 8875b81b6b3SRodney W. Grimes if (iotest) { 888fbcb16efSLuigi Rizzo print_s0(); 8895b81b6b3SRodney W. Grimes return 0; 8905b81b6b3SRodney W. Grimes } 8911a03d6d5SPoul-Henning Kamp for(i = 0; i < NDOSPART; i++) 8921a03d6d5SPoul-Henning Kamp dos_partition_enc(&mboot.bootinst[DOSPARTOFF + i * DOSPARTSIZE], 8931a03d6d5SPoul-Henning Kamp &mboot.parts[i]); 8941a03d6d5SPoul-Henning Kamp le16enc(&mboot.bootinst[DOSMAGICOFFSET], DOSMAGIC); 89585c2cf30SJohn Baldwin for(sector = 0; sector < mboot.bootinst_size / secsize; sector++) 89685c2cf30SJohn Baldwin if (write_disk(sector, 89785c2cf30SJohn Baldwin &mboot.bootinst[sector * secsize]) == -1) { 898e6fb3ddeSPoul-Henning Kamp warn("can't write fdisk partition table"); 8995b81b6b3SRodney W. Grimes return -1; 9005b81b6b3SRodney W. Grimes } 9014be1e61bSAlexander Langer return(0); 9025b81b6b3SRodney W. Grimes } 9035b81b6b3SRodney W. Grimes 9045b81b6b3SRodney W. Grimes 9054be1e61bSAlexander Langer static int 906041b8b00SPoul-Henning Kamp ok(const char *str) 9075b81b6b3SRodney W. Grimes { 9085b81b6b3SRodney W. Grimes printf("%s [n] ", str); 90963692187SIan Dowse fflush(stdout); 91063692187SIan Dowse if (fgets(lbuf, LBUF, stdin) == NULL) 91163692187SIan Dowse exit(1); 9125b81b6b3SRodney W. Grimes lbuf[strlen(lbuf)-1] = 0; 9135b81b6b3SRodney W. Grimes 9145b81b6b3SRodney W. Grimes if (*lbuf && 9155b81b6b3SRodney W. Grimes (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 9165b81b6b3SRodney W. Grimes !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 9175b81b6b3SRodney W. Grimes return 1; 9185b81b6b3SRodney W. Grimes else 9195b81b6b3SRodney W. Grimes return 0; 9205b81b6b3SRodney W. Grimes } 9215b81b6b3SRodney W. Grimes 9224be1e61bSAlexander Langer static int 9234be78ce3SMaxim Sobolev decimal(const char *str, int *num, int deflt, uint32_t maxval) 9245b81b6b3SRodney W. Grimes { 925*1b100fd3SAndrey V. Elsukov long long acc; 92668df7abeSMaxim Sobolev int c; 9275b81b6b3SRodney W. Grimes char *cp; 9285b81b6b3SRodney W. Grimes 9295b81b6b3SRodney W. Grimes while (1) { 930*1b100fd3SAndrey V. Elsukov acc = 0; 9315b81b6b3SRodney W. Grimes printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 93263692187SIan Dowse fflush(stdout); 93363692187SIan Dowse if (fgets(lbuf, LBUF, stdin) == NULL) 93463692187SIan Dowse exit(1); 9355b81b6b3SRodney W. Grimes lbuf[strlen(lbuf)-1] = 0; 9365b81b6b3SRodney W. Grimes 9375b81b6b3SRodney W. Grimes if (!*lbuf) 9385b81b6b3SRodney W. Grimes return 0; 9395b81b6b3SRodney W. Grimes 9405b81b6b3SRodney W. Grimes cp = lbuf; 9415b81b6b3SRodney W. Grimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 9425b81b6b3SRodney W. Grimes if (!c) 9435b81b6b3SRodney W. Grimes return 0; 9444be1e61bSAlexander Langer while ((c = *cp++)) { 94568df7abeSMaxim Sobolev if (c <= '9' && c >= '0') { 9466bfcd9c3SAndrey V. Elsukov if (acc <= maxval || maxval == 0) 9475b81b6b3SRodney W. Grimes acc = acc * 10 + c - '0'; 94868df7abeSMaxim Sobolev } else 9495b81b6b3SRodney W. Grimes break; 9505b81b6b3SRodney W. Grimes } 9515b81b6b3SRodney W. Grimes if (c == ' ' || c == '\t') 9525b81b6b3SRodney W. Grimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 9535b81b6b3SRodney W. Grimes if (!c) { 9544be78ce3SMaxim Sobolev if (maxval > 0 && acc > maxval) { 9554be78ce3SMaxim Sobolev acc = maxval; 9564be78ce3SMaxim Sobolev printf("%s exceeds maximum value allowed for " 9574be78ce3SMaxim Sobolev "this field. The value has been reduced " 9584be78ce3SMaxim Sobolev "to %lld\n", lbuf, acc); 95968df7abeSMaxim Sobolev } 9605b81b6b3SRodney W. Grimes *num = acc; 9615b81b6b3SRodney W. Grimes return 1; 9625b81b6b3SRodney W. Grimes } else 963680426beSDavid E. O'Brien printf("%s is an invalid decimal number. Try again.\n", 9645b81b6b3SRodney W. Grimes lbuf); 9655b81b6b3SRodney W. Grimes } 9665b81b6b3SRodney W. Grimes } 9675b81b6b3SRodney W. Grimes 968f46af505SJordan K. Hubbard 969f46af505SJordan K. Hubbard static void 970041b8b00SPoul-Henning Kamp parse_config_line(char *line, CMD *command) 971f46af505SJordan K. Hubbard { 972f46af505SJordan K. Hubbard char *cp, *end; 973f46af505SJordan K. Hubbard 974f46af505SJordan K. Hubbard cp = line; 975041b8b00SPoul-Henning Kamp while (1) { 976f46af505SJordan K. Hubbard memset(command, 0, sizeof(*command)); 977f46af505SJordan K. Hubbard 978f46af505SJordan K. Hubbard while (isspace(*cp)) ++cp; 979f46af505SJordan K. Hubbard if (*cp == '\0' || *cp == '#') 980f46af505SJordan K. Hubbard break; 981f46af505SJordan K. Hubbard command->cmd = *cp++; 982f46af505SJordan K. Hubbard 983f46af505SJordan K. Hubbard /* 984f46af505SJordan K. Hubbard * Parse args 985f46af505SJordan K. Hubbard */ 986041b8b00SPoul-Henning Kamp while (1) { 987f46af505SJordan K. Hubbard while (isspace(*cp)) ++cp; 988d1c77156SBrian Somers if (*cp == '\0') 989d1c77156SBrian Somers break; /* eol */ 990f46af505SJordan K. Hubbard if (*cp == '#') 991f46af505SJordan K. Hubbard break; /* found comment */ 992f46af505SJordan K. Hubbard if (isalpha(*cp)) 993f46af505SJordan K. Hubbard command->args[command->n_args].argtype = *cp++; 994f46af505SJordan K. Hubbard end = NULL; 995f9373bbdSRyan Stone command->args[command->n_args].arg_val = strtoul(cp, &end, 0); 996d1c77156SBrian Somers if (cp == end || (!isspace(*end) && *end != '\0')) { 997d1c77156SBrian Somers char ch; 998d1c77156SBrian Somers end = cp; 999d1c77156SBrian Somers while (!isspace(*end) && *end != '\0') ++end; 1000d1c77156SBrian Somers ch = *end; *end = '\0'; 1001d1c77156SBrian Somers command->args[command->n_args].arg_str = strdup(cp); 1002d1c77156SBrian Somers *end = ch; 1003d1c77156SBrian Somers } else 1004d1c77156SBrian Somers command->args[command->n_args].arg_str = NULL; 1005f46af505SJordan K. Hubbard cp = end; 1006f46af505SJordan K. Hubbard command->n_args++; 1007f46af505SJordan K. Hubbard } 1008f46af505SJordan K. Hubbard break; 1009f46af505SJordan K. Hubbard } 1010f46af505SJordan K. Hubbard } 1011f46af505SJordan K. Hubbard 1012f46af505SJordan K. Hubbard 1013f46af505SJordan K. Hubbard static int 1014041b8b00SPoul-Henning Kamp process_geometry(CMD *command) 1015f46af505SJordan K. Hubbard { 1016f46af505SJordan K. Hubbard int status = 1, i; 1017f46af505SJordan K. Hubbard 1018041b8b00SPoul-Henning Kamp while (1) { 1019f46af505SJordan K. Hubbard geom_processed = 1; 1020041b8b00SPoul-Henning Kamp if (part_processed) { 1021d98b1668SPhilippe Charnier warnx( 1022d98b1668SPhilippe Charnier "ERROR line %d: the geometry specification line must occur before\n\ 1023d98b1668SPhilippe Charnier all partition specifications", 1024d98b1668SPhilippe Charnier current_line_number); 1025f46af505SJordan K. Hubbard status = 0; 1026f46af505SJordan K. Hubbard break; 1027f46af505SJordan K. Hubbard } 1028041b8b00SPoul-Henning Kamp if (command->n_args != 3) { 1029d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of geometry args", 1030d98b1668SPhilippe Charnier current_line_number); 1031f46af505SJordan K. Hubbard status = 0; 1032f46af505SJordan K. Hubbard break; 1033f46af505SJordan K. Hubbard } 1034041b8b00SPoul-Henning Kamp dos_cyls = 0; 1035041b8b00SPoul-Henning Kamp dos_heads = 0; 1036041b8b00SPoul-Henning Kamp dos_sectors = 0; 1037041b8b00SPoul-Henning Kamp for (i = 0; i < 3; ++i) { 1038041b8b00SPoul-Henning Kamp switch (command->args[i].argtype) { 1039f46af505SJordan K. Hubbard case 'c': 1040f46af505SJordan K. Hubbard dos_cyls = command->args[i].arg_val; 1041f46af505SJordan K. Hubbard break; 1042f46af505SJordan K. Hubbard case 'h': 1043f46af505SJordan K. Hubbard dos_heads = command->args[i].arg_val; 1044f46af505SJordan K. Hubbard break; 1045f46af505SJordan K. Hubbard case 's': 1046f46af505SJordan K. Hubbard dos_sectors = command->args[i].arg_val; 1047f46af505SJordan K. Hubbard break; 1048f46af505SJordan K. Hubbard default: 1049d98b1668SPhilippe Charnier warnx( 1050d98b1668SPhilippe Charnier "ERROR line %d: unknown geometry arg type: '%c' (0x%02x)", 1051d98b1668SPhilippe Charnier current_line_number, command->args[i].argtype, 1052f46af505SJordan K. Hubbard command->args[i].argtype); 1053f46af505SJordan K. Hubbard status = 0; 1054f46af505SJordan K. Hubbard break; 1055f46af505SJordan K. Hubbard } 1056f46af505SJordan K. Hubbard } 1057f46af505SJordan K. Hubbard if (status == 0) 1058f46af505SJordan K. Hubbard break; 1059f46af505SJordan K. Hubbard 1060f46af505SJordan K. Hubbard dos_cylsecs = dos_heads * dos_sectors; 1061f46af505SJordan K. Hubbard 1062f46af505SJordan K. Hubbard /* 1063f46af505SJordan K. Hubbard * Do sanity checks on parameter values 1064f46af505SJordan K. Hubbard */ 1065041b8b00SPoul-Henning Kamp if (dos_cyls == 0) { 1066d98b1668SPhilippe Charnier warnx("ERROR line %d: number of cylinders not specified", 1067d98b1668SPhilippe Charnier current_line_number); 1068f46af505SJordan K. Hubbard status = 0; 1069f46af505SJordan K. Hubbard } 1070041b8b00SPoul-Henning Kamp if (dos_cyls > 1024) { 1071d98b1668SPhilippe Charnier warnx( 1072d98b1668SPhilippe Charnier "WARNING line %d: number of cylinders (%d) may be out-of-range\n\ 1073f46af505SJordan K. Hubbard (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\ 1074d98b1668SPhilippe Charnier is dedicated to FreeBSD)", 1075d98b1668SPhilippe Charnier current_line_number, dos_cyls); 1076f46af505SJordan K. Hubbard } 1077f46af505SJordan K. Hubbard 1078041b8b00SPoul-Henning Kamp if (dos_heads == 0) { 1079d98b1668SPhilippe Charnier warnx("ERROR line %d: number of heads not specified", 1080d98b1668SPhilippe Charnier current_line_number); 1081f46af505SJordan K. Hubbard status = 0; 1082ea32a699SUlf Lilleengen } else if (dos_heads > 256) { 1083ea32a699SUlf Lilleengen warnx("ERROR line %d: number of heads must be within (1-256)", 1084d98b1668SPhilippe Charnier current_line_number); 1085f46af505SJordan K. Hubbard status = 0; 1086f46af505SJordan K. Hubbard } 1087f46af505SJordan K. Hubbard 1088041b8b00SPoul-Henning Kamp if (dos_sectors == 0) { 1089d98b1668SPhilippe Charnier warnx("ERROR line %d: number of sectors not specified", 1090d98b1668SPhilippe Charnier current_line_number); 1091f46af505SJordan K. Hubbard status = 0; 1092041b8b00SPoul-Henning Kamp } else if (dos_sectors > 63) { 1093d98b1668SPhilippe Charnier warnx("ERROR line %d: number of sectors must be within (1-63)", 1094d98b1668SPhilippe Charnier current_line_number); 1095f46af505SJordan K. Hubbard status = 0; 1096f46af505SJordan K. Hubbard } 1097f46af505SJordan K. Hubbard 1098f46af505SJordan K. Hubbard break; 1099f46af505SJordan K. Hubbard } 1100f46af505SJordan K. Hubbard return (status); 1101f46af505SJordan K. Hubbard } 1102f46af505SJordan K. Hubbard 1103d1c77156SBrian Somers static u_int32_t 1104d1c77156SBrian Somers str2sectors(const char *str) 1105d1c77156SBrian Somers { 1106d1c77156SBrian Somers char *end; 1107d1c77156SBrian Somers unsigned long val; 1108d1c77156SBrian Somers 1109d1c77156SBrian Somers val = strtoul(str, &end, 0); 1110d1c77156SBrian Somers if (str == end || *end == '\0') { 1111d1c77156SBrian Somers warnx("ERROR line %d: unexpected size: \'%s\'", 1112d1c77156SBrian Somers current_line_number, str); 11134be78ce3SMaxim Sobolev return NO_DISK_SECTORS; 1114d1c77156SBrian Somers } 1115d1c77156SBrian Somers 1116d1c77156SBrian Somers if (*end == 'K') 1117d1c77156SBrian Somers val *= 1024UL / secsize; 1118d1c77156SBrian Somers else if (*end == 'M') 1119d1c77156SBrian Somers val *= 1024UL * 1024UL / secsize; 1120d1c77156SBrian Somers else if (*end == 'G') 1121d1c77156SBrian Somers val *= 1024UL * 1024UL * 1024UL / secsize; 1122d1c77156SBrian Somers else { 1123d1c77156SBrian Somers warnx("ERROR line %d: unexpected modifier: %c " 1124d1c77156SBrian Somers "(not K/M/G)", current_line_number, *end); 11254be78ce3SMaxim Sobolev return NO_DISK_SECTORS; 1126d1c77156SBrian Somers } 1127d1c77156SBrian Somers 1128d1c77156SBrian Somers return val; 1129d1c77156SBrian Somers } 1130f46af505SJordan K. Hubbard 1131f46af505SJordan K. Hubbard static int 1132041b8b00SPoul-Henning Kamp process_partition(CMD *command) 1133f46af505SJordan K. Hubbard { 1134f46af505SJordan K. Hubbard int status = 0, partition; 1135b594e0feSJohn Baldwin u_int32_t prev_head_boundary, prev_cyl_boundary; 1136b594e0feSJohn Baldwin u_int32_t adj_size, max_end; 1137f46af505SJordan K. Hubbard struct dos_partition *partp; 1138f46af505SJordan K. Hubbard 1139041b8b00SPoul-Henning Kamp while (1) { 1140f46af505SJordan K. Hubbard part_processed = 1; 1141041b8b00SPoul-Henning Kamp if (command->n_args != 4) { 1142d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of partition args", 1143d98b1668SPhilippe Charnier current_line_number); 1144f46af505SJordan K. Hubbard break; 1145f46af505SJordan K. Hubbard } 1146f46af505SJordan K. Hubbard partition = command->args[0].arg_val; 1147041b8b00SPoul-Henning Kamp if (partition < 1 || partition > 4) { 1148d98b1668SPhilippe Charnier warnx("ERROR line %d: invalid partition number %d", 1149d98b1668SPhilippe Charnier current_line_number, partition); 1150f46af505SJordan K. Hubbard break; 1151f46af505SJordan K. Hubbard } 1152c4898ccbSLuigi Rizzo partp = &mboot.parts[partition - 1]; 1153c4898ccbSLuigi Rizzo bzero(partp, sizeof (*partp)); 1154f46af505SJordan K. Hubbard partp->dp_typ = command->args[1].arg_val; 1155d1c77156SBrian Somers if (command->args[2].arg_str != NULL) { 1156d1c77156SBrian Somers if (strcmp(command->args[2].arg_str, "*") == 0) { 1157d1c77156SBrian Somers int i; 1158d1c77156SBrian Somers partp->dp_start = dos_sectors; 1159d1c77156SBrian Somers for (i = 1; i < partition; i++) { 1160d1c77156SBrian Somers struct dos_partition *prev_partp; 1161d1c77156SBrian Somers prev_partp = ((struct dos_partition *) 1162d1c77156SBrian Somers &mboot.parts) + i - 1; 1163d1c77156SBrian Somers if (prev_partp->dp_typ != 0) 1164d1c77156SBrian Somers partp->dp_start = prev_partp->dp_start + 1165d1c77156SBrian Somers prev_partp->dp_size; 1166d1c77156SBrian Somers } 1167d1c77156SBrian Somers if (partp->dp_start % dos_sectors != 0) { 1168d1c77156SBrian Somers prev_head_boundary = partp->dp_start / 1169d1c77156SBrian Somers dos_sectors * dos_sectors; 1170d1c77156SBrian Somers partp->dp_start = prev_head_boundary + 1171d1c77156SBrian Somers dos_sectors; 1172d1c77156SBrian Somers } 1173d1c77156SBrian Somers } else { 1174d1c77156SBrian Somers partp->dp_start = str2sectors(command->args[2].arg_str); 11754be78ce3SMaxim Sobolev if (partp->dp_start == NO_DISK_SECTORS) 1176d1c77156SBrian Somers break; 1177d1c77156SBrian Somers } 1178d1c77156SBrian Somers } else 1179f46af505SJordan K. Hubbard partp->dp_start = command->args[2].arg_val; 1180d1c77156SBrian Somers 1181d1c77156SBrian Somers if (command->args[3].arg_str != NULL) { 1182d1c77156SBrian Somers if (strcmp(command->args[3].arg_str, "*") == 0) 1183d1c77156SBrian Somers partp->dp_size = ((disksecs / dos_cylsecs) * 1184d1c77156SBrian Somers dos_cylsecs) - partp->dp_start; 1185d1c77156SBrian Somers else { 1186d1c77156SBrian Somers partp->dp_size = str2sectors(command->args[3].arg_str); 11874be78ce3SMaxim Sobolev if (partp->dp_size == NO_DISK_SECTORS) 1188d1c77156SBrian Somers break; 1189d1c77156SBrian Somers } 1190d1c77156SBrian Somers prev_cyl_boundary = ((partp->dp_start + partp->dp_size) / 1191d1c77156SBrian Somers dos_cylsecs) * dos_cylsecs; 1192d1c77156SBrian Somers if (prev_cyl_boundary > partp->dp_start) 1193d1c77156SBrian Somers partp->dp_size = prev_cyl_boundary - partp->dp_start; 1194d1c77156SBrian Somers } else 1195f46af505SJordan K. Hubbard partp->dp_size = command->args[3].arg_val; 1196d1c77156SBrian Somers 1197f46af505SJordan K. Hubbard max_end = partp->dp_start + partp->dp_size; 1198f46af505SJordan K. Hubbard 1199041b8b00SPoul-Henning Kamp if (partp->dp_typ == 0) { 1200f46af505SJordan K. Hubbard /* 1201f46af505SJordan K. Hubbard * Get out, the partition is marked as unused. 1202f46af505SJordan K. Hubbard */ 1203f46af505SJordan K. Hubbard /* 1204f46af505SJordan K. Hubbard * Insure that it's unused. 1205f46af505SJordan K. Hubbard */ 1206c4898ccbSLuigi Rizzo bzero(partp, sizeof(*partp)); 1207f46af505SJordan K. Hubbard status = 1; 1208f46af505SJordan K. Hubbard break; 1209f46af505SJordan K. Hubbard } 1210f46af505SJordan K. Hubbard 1211f46af505SJordan K. Hubbard /* 1212d64ada50SJens Schweikhardt * Adjust start upwards, if necessary, to fall on a head boundary. 1213f46af505SJordan K. Hubbard */ 1214041b8b00SPoul-Henning Kamp if (partp->dp_start % dos_sectors != 0) { 1215b594e0feSJohn Baldwin prev_head_boundary = partp->dp_start / dos_sectors * dos_sectors; 1216b594e0feSJohn Baldwin if (max_end < dos_sectors || 1217041b8b00SPoul-Henning Kamp prev_head_boundary > max_end - dos_sectors) { 1218f46af505SJordan K. Hubbard /* 1219f46af505SJordan K. Hubbard * Can't go past end of partition 1220f46af505SJordan K. Hubbard */ 1221d98b1668SPhilippe Charnier warnx( 1222d98b1668SPhilippe Charnier "ERROR line %d: unable to adjust start of partition %d to fall on\n\ 1223b594e0feSJohn Baldwin a head boundary", 1224d98b1668SPhilippe Charnier current_line_number, partition); 1225f46af505SJordan K. Hubbard break; 1226f46af505SJordan K. Hubbard } 1227d98b1668SPhilippe Charnier warnx( 1228b594e0feSJohn Baldwin "WARNING: adjusting start offset of partition %d\n\ 1229b594e0feSJohn Baldwin from %u to %u, to fall on a head boundary", 1230b594e0feSJohn Baldwin partition, (u_int)partp->dp_start, 1231b594e0feSJohn Baldwin (u_int)(prev_head_boundary + dos_sectors)); 1232b594e0feSJohn Baldwin partp->dp_start = prev_head_boundary + dos_sectors; 1233f46af505SJordan K. Hubbard } 1234f46af505SJordan K. Hubbard 1235f46af505SJordan K. Hubbard /* 1236f46af505SJordan K. Hubbard * Adjust size downwards, if necessary, to fall on a cylinder 1237f46af505SJordan K. Hubbard * boundary. 1238f46af505SJordan K. Hubbard */ 1239b594e0feSJohn Baldwin prev_cyl_boundary = 1240f46af505SJordan K. Hubbard ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs; 1241b594e0feSJohn Baldwin if (prev_cyl_boundary > partp->dp_start) 1242b594e0feSJohn Baldwin adj_size = prev_cyl_boundary - partp->dp_start; 1243041b8b00SPoul-Henning Kamp else { 1244b594e0feSJohn Baldwin warnx( 1245b594e0feSJohn Baldwin "ERROR: could not adjust partition to start on a head boundary\n\ 1246b594e0feSJohn Baldwin and end on a cylinder boundary."); 1247b594e0feSJohn Baldwin return (0); 1248b594e0feSJohn Baldwin } 1249041b8b00SPoul-Henning Kamp if (adj_size != partp->dp_size) { 1250d98b1668SPhilippe Charnier warnx( 1251b594e0feSJohn Baldwin "WARNING: adjusting size of partition %d from %u to %u\n\ 1252b594e0feSJohn Baldwin to end on a cylinder boundary", 1253b594e0feSJohn Baldwin partition, (u_int)partp->dp_size, (u_int)adj_size); 1254f46af505SJordan K. Hubbard partp->dp_size = adj_size; 1255f46af505SJordan K. Hubbard } 1256041b8b00SPoul-Henning Kamp if (partp->dp_size == 0) { 125763692187SIan Dowse warnx("ERROR line %d: size of partition %d is zero", 1258d98b1668SPhilippe Charnier current_line_number, partition); 1259f46af505SJordan K. Hubbard break; 1260f46af505SJordan K. Hubbard } 1261f46af505SJordan K. Hubbard 126263692187SIan Dowse dos(partp); 1263f46af505SJordan K. Hubbard status = 1; 1264f46af505SJordan K. Hubbard break; 1265f46af505SJordan K. Hubbard } 1266f46af505SJordan K. Hubbard return (status); 1267f46af505SJordan K. Hubbard } 1268f46af505SJordan K. Hubbard 1269f46af505SJordan K. Hubbard 1270f46af505SJordan K. Hubbard static int 1271041b8b00SPoul-Henning Kamp process_active(CMD *command) 1272f46af505SJordan K. Hubbard { 1273f46af505SJordan K. Hubbard int status = 0, partition, i; 1274f46af505SJordan K. Hubbard struct dos_partition *partp; 1275f46af505SJordan K. Hubbard 1276041b8b00SPoul-Henning Kamp while (1) { 1277f46af505SJordan K. Hubbard active_processed = 1; 1278041b8b00SPoul-Henning Kamp if (command->n_args != 1) { 1279d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of active args", 1280d98b1668SPhilippe Charnier current_line_number); 1281f46af505SJordan K. Hubbard status = 0; 1282f46af505SJordan K. Hubbard break; 1283f46af505SJordan K. Hubbard } 1284f46af505SJordan K. Hubbard partition = command->args[0].arg_val; 1285041b8b00SPoul-Henning Kamp if (partition < 1 || partition > 4) { 1286d98b1668SPhilippe Charnier warnx("ERROR line %d: invalid partition number %d", 1287d98b1668SPhilippe Charnier current_line_number, partition); 1288f46af505SJordan K. Hubbard break; 1289f46af505SJordan K. Hubbard } 1290f46af505SJordan K. Hubbard /* 1291f46af505SJordan K. Hubbard * Reset active partition 1292f46af505SJordan K. Hubbard */ 1293c4898ccbSLuigi Rizzo partp = mboot.parts; 1294f46af505SJordan K. Hubbard for (i = 0; i < NDOSPART; i++) 1295f46af505SJordan K. Hubbard partp[i].dp_flag = 0; 12964ddd60b9SBrian Somers partp[partition-1].dp_flag = ACTIVE; 1297f46af505SJordan K. Hubbard 1298f46af505SJordan K. Hubbard status = 1; 1299f46af505SJordan K. Hubbard break; 1300f46af505SJordan K. Hubbard } 1301f46af505SJordan K. Hubbard return (status); 1302f46af505SJordan K. Hubbard } 1303f46af505SJordan K. Hubbard 1304f46af505SJordan K. Hubbard 1305f46af505SJordan K. Hubbard static int 1306041b8b00SPoul-Henning Kamp process_line(char *line) 1307f46af505SJordan K. Hubbard { 1308f46af505SJordan K. Hubbard CMD command; 1309f46af505SJordan K. Hubbard int status = 1; 1310f46af505SJordan K. Hubbard 1311041b8b00SPoul-Henning Kamp while (1) { 1312f46af505SJordan K. Hubbard parse_config_line(line, &command); 1313041b8b00SPoul-Henning Kamp switch (command.cmd) { 1314f46af505SJordan K. Hubbard case 0: 1315f46af505SJordan K. Hubbard /* 1316f46af505SJordan K. Hubbard * Comment or blank line 1317f46af505SJordan K. Hubbard */ 1318f46af505SJordan K. Hubbard break; 1319f46af505SJordan K. Hubbard case 'g': 1320f46af505SJordan K. Hubbard /* 1321f46af505SJordan K. Hubbard * Set geometry 1322f46af505SJordan K. Hubbard */ 1323f46af505SJordan K. Hubbard status = process_geometry(&command); 1324f46af505SJordan K. Hubbard break; 1325f46af505SJordan K. Hubbard case 'p': 1326f46af505SJordan K. Hubbard status = process_partition(&command); 1327f46af505SJordan K. Hubbard break; 1328f46af505SJordan K. Hubbard case 'a': 1329f46af505SJordan K. Hubbard status = process_active(&command); 1330f46af505SJordan K. Hubbard break; 1331f46af505SJordan K. Hubbard default: 1332f46af505SJordan K. Hubbard status = 0; 1333f46af505SJordan K. Hubbard break; 1334f46af505SJordan K. Hubbard } 1335f46af505SJordan K. Hubbard break; 1336f46af505SJordan K. Hubbard } 1337f46af505SJordan K. Hubbard return (status); 1338f46af505SJordan K. Hubbard } 1339f46af505SJordan K. Hubbard 1340f46af505SJordan K. Hubbard 1341f46af505SJordan K. Hubbard static int 1342041b8b00SPoul-Henning Kamp read_config(char *config_file) 1343f46af505SJordan K. Hubbard { 1344f46af505SJordan K. Hubbard FILE *fp = NULL; 1345f46af505SJordan K. Hubbard int status = 1; 1346f46af505SJordan K. Hubbard char buf[1010]; 1347f46af505SJordan K. Hubbard 1348041b8b00SPoul-Henning Kamp while (1) { 1349041b8b00SPoul-Henning Kamp if (strcmp(config_file, "-") != 0) { 1350f46af505SJordan K. Hubbard /* 1351f46af505SJordan K. Hubbard * We're not reading from stdin 1352f46af505SJordan K. Hubbard */ 1353041b8b00SPoul-Henning Kamp if ((fp = fopen(config_file, "r")) == NULL) { 1354f46af505SJordan K. Hubbard status = 0; 1355f46af505SJordan K. Hubbard break; 1356f46af505SJordan K. Hubbard } 1357041b8b00SPoul-Henning Kamp } else { 1358f46af505SJordan K. Hubbard fp = stdin; 1359f46af505SJordan K. Hubbard } 1360f46af505SJordan K. Hubbard current_line_number = 0; 1361041b8b00SPoul-Henning Kamp while (!feof(fp)) { 1362f46af505SJordan K. Hubbard if (fgets(buf, sizeof(buf), fp) == NULL) 1363f46af505SJordan K. Hubbard break; 1364f46af505SJordan K. Hubbard ++current_line_number; 1365f46af505SJordan K. Hubbard status = process_line(buf); 1366f46af505SJordan K. Hubbard if (status == 0) 1367f46af505SJordan K. Hubbard break; 1368f46af505SJordan K. Hubbard } 1369f46af505SJordan K. Hubbard break; 1370f46af505SJordan K. Hubbard } 1371041b8b00SPoul-Henning Kamp if (fp) { 1372f46af505SJordan K. Hubbard /* 1373f46af505SJordan K. Hubbard * It doesn't matter if we're reading from stdin, as we've reached EOF 1374f46af505SJordan K. Hubbard */ 1375f46af505SJordan K. Hubbard fclose(fp); 1376f46af505SJordan K. Hubbard } 1377f46af505SJordan K. Hubbard return (status); 1378f46af505SJordan K. Hubbard } 1379f46af505SJordan K. Hubbard 1380f46af505SJordan K. Hubbard 1381f46af505SJordan K. Hubbard static void 1382f46af505SJordan K. Hubbard reset_boot(void) 1383f46af505SJordan K. Hubbard { 1384f46af505SJordan K. Hubbard int i; 1385f46af505SJordan K. Hubbard struct dos_partition *partp; 1386f46af505SJordan K. Hubbard 1387f46af505SJordan K. Hubbard init_boot(); 1388041b8b00SPoul-Henning Kamp for (i = 0; i < 4; ++i) { 1389c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 1390c4898ccbSLuigi Rizzo bzero(partp, sizeof(*partp)); 1391f46af505SJordan K. Hubbard } 1392f46af505SJordan K. Hubbard } 1393b594e0feSJohn Baldwin 1394b594e0feSJohn Baldwin static int 1395041b8b00SPoul-Henning Kamp sanitize_partition(struct dos_partition *partp) 1396b594e0feSJohn Baldwin { 1397b594e0feSJohn Baldwin u_int32_t prev_head_boundary, prev_cyl_boundary; 139863692187SIan Dowse u_int32_t max_end, size, start; 1399b594e0feSJohn Baldwin 140063692187SIan Dowse start = partp->dp_start; 140163692187SIan Dowse size = partp->dp_size; 140263692187SIan Dowse max_end = start + size; 140363692187SIan Dowse /* Only allow a zero size if the partition is being marked unused. */ 140463692187SIan Dowse if (size == 0) { 140563692187SIan Dowse if (start == 0 && partp->dp_typ == 0) 140663692187SIan Dowse return (1); 140763692187SIan Dowse warnx("ERROR: size of partition is zero"); 140863692187SIan Dowse return (0); 140963692187SIan Dowse } 141063692187SIan Dowse /* Return if no adjustment is necessary. */ 141163692187SIan Dowse if (start % dos_sectors == 0 && (start + size) % dos_sectors == 0) 141263692187SIan Dowse return (1); 141363692187SIan Dowse 14147fb7df31SDag-Erling Smørgrav if (start == 0) { 14157fb7df31SDag-Erling Smørgrav warnx("WARNING: partition overlaps with partition table"); 14167fb7df31SDag-Erling Smørgrav if (ok("Correct this automatically?")) 14177fb7df31SDag-Erling Smørgrav start = dos_sectors; 14187fb7df31SDag-Erling Smørgrav } 141963692187SIan Dowse if (start % dos_sectors != 0) 142063692187SIan Dowse warnx("WARNING: partition does not start on a head boundary"); 142163692187SIan Dowse if ((start +size) % dos_sectors != 0) 142263692187SIan Dowse warnx("WARNING: partition does not end on a cylinder boundary"); 142363692187SIan Dowse warnx("WARNING: this may confuse the BIOS or some operating systems"); 142463692187SIan Dowse if (!ok("Correct this automatically?")) 142563692187SIan Dowse return (1); 1426b594e0feSJohn Baldwin 1427b594e0feSJohn Baldwin /* 1428d64ada50SJens Schweikhardt * Adjust start upwards, if necessary, to fall on a head boundary. 1429b594e0feSJohn Baldwin */ 143063692187SIan Dowse if (start % dos_sectors != 0) { 143163692187SIan Dowse prev_head_boundary = start / dos_sectors * dos_sectors; 1432b594e0feSJohn Baldwin if (max_end < dos_sectors || 143363692187SIan Dowse prev_head_boundary >= max_end - dos_sectors) { 1434b594e0feSJohn Baldwin /* 1435b594e0feSJohn Baldwin * Can't go past end of partition 1436b594e0feSJohn Baldwin */ 1437b594e0feSJohn Baldwin warnx( 1438b594e0feSJohn Baldwin "ERROR: unable to adjust start of partition to fall on a head boundary"); 1439b594e0feSJohn Baldwin return (0); 1440b594e0feSJohn Baldwin } 144163692187SIan Dowse start = prev_head_boundary + dos_sectors; 1442b594e0feSJohn Baldwin } 1443b594e0feSJohn Baldwin 1444b594e0feSJohn Baldwin /* 1445b594e0feSJohn Baldwin * Adjust size downwards, if necessary, to fall on a cylinder 1446b594e0feSJohn Baldwin * boundary. 1447b594e0feSJohn Baldwin */ 144863692187SIan Dowse prev_cyl_boundary = ((start + size) / dos_cylsecs) * dos_cylsecs; 144963692187SIan Dowse if (prev_cyl_boundary > start) 145063692187SIan Dowse size = prev_cyl_boundary - start; 145163692187SIan Dowse else { 1452b594e0feSJohn Baldwin warnx("ERROR: could not adjust partition to start on a head boundary\n\ 1453b594e0feSJohn Baldwin and end on a cylinder boundary."); 1454b594e0feSJohn Baldwin return (0); 1455b594e0feSJohn Baldwin } 145663692187SIan Dowse 145763692187SIan Dowse /* Finally, commit any changes to partp and return. */ 145863692187SIan Dowse if (start != partp->dp_start) { 145963692187SIan Dowse warnx("WARNING: adjusting start offset of partition to %u", 146063692187SIan Dowse (u_int)start); 146163692187SIan Dowse partp->dp_start = start; 1462b594e0feSJohn Baldwin } 146363692187SIan Dowse if (size != partp->dp_size) { 146463692187SIan Dowse warnx("WARNING: adjusting size of partition to %u", (u_int)size); 146563692187SIan Dowse partp->dp_size = size; 1466b594e0feSJohn Baldwin } 1467b594e0feSJohn Baldwin 1468b594e0feSJohn Baldwin return (1); 1469b594e0feSJohn Baldwin } 1470df77f711SJoerg Wunsch 1471df77f711SJoerg Wunsch /* 1472df77f711SJoerg Wunsch * Try figuring out the root device's canonical disk name. 1473df77f711SJoerg Wunsch * The following choices are considered: 1474df77f711SJoerg Wunsch * /dev/ad0s1a => /dev/ad0 1475df77f711SJoerg Wunsch * /dev/da0a => /dev/da0 1476df77f711SJoerg Wunsch * /dev/vinum/root => /dev/vinum/root 14771dc7e010SBrian Somers * A ".eli" part is removed if it exists (see geli(8)). 14786a5ffa06SBrian Somers * A ".journal" ending is removed if it exists (see gjournal(8)). 1479df77f711SJoerg Wunsch */ 1480df77f711SJoerg Wunsch static char * 1481df77f711SJoerg Wunsch get_rootdisk(void) 1482df77f711SJoerg Wunsch { 1483df77f711SJoerg Wunsch struct statfs rootfs; 1484df77f711SJoerg Wunsch regex_t re; 1485df77f711SJoerg Wunsch #define NMATCHES 2 1486df77f711SJoerg Wunsch regmatch_t rm[NMATCHES]; 14871dc7e010SBrian Somers char dev[PATH_MAX], *s; 1488df77f711SJoerg Wunsch int rv; 1489df77f711SJoerg Wunsch 1490df77f711SJoerg Wunsch if (statfs("/", &rootfs) == -1) 1491df77f711SJoerg Wunsch err(1, "statfs(\"/\")"); 1492df77f711SJoerg Wunsch 14936a5ffa06SBrian Somers if ((rv = regcomp(&re, "^(/dev/[a-z/]+[0-9]*)([sp][0-9]+)?[a-h]?(\\.journal)?$", 1494df77f711SJoerg Wunsch REG_EXTENDED)) != 0) 1495df77f711SJoerg Wunsch errx(1, "regcomp() failed (%d)", rv); 14961dc7e010SBrian Somers strlcpy(dev, rootfs.f_mntfromname, sizeof (dev)); 14971dc7e010SBrian Somers if ((s = strstr(dev, ".eli")) != NULL) 14981dc7e010SBrian Somers memmove(s, s+4, strlen(s + 4) + 1); 14991dc7e010SBrian Somers 15001dc7e010SBrian Somers if ((rv = regexec(&re, dev, NMATCHES, rm, 0)) != 0) 1501df77f711SJoerg Wunsch errx(1, 1502df77f711SJoerg Wunsch "mounted root fs resource doesn't match expectations (regexec returned %d)", 1503df77f711SJoerg Wunsch rv); 1504df77f711SJoerg Wunsch if ((s = malloc(rm[1].rm_eo - rm[1].rm_so + 1)) == NULL) 1505df77f711SJoerg Wunsch errx(1, "out of memory"); 1506df77f711SJoerg Wunsch memcpy(s, rootfs.f_mntfromname + rm[1].rm_so, 1507df77f711SJoerg Wunsch rm[1].rm_eo - rm[1].rm_so); 1508df77f711SJoerg Wunsch s[rm[1].rm_eo - rm[1].rm_so] = 0; 1509df77f711SJoerg Wunsch 1510df77f711SJoerg Wunsch return s; 1511df77f711SJoerg Wunsch } 1512