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 235fd1ca22aSAndrey V. Elsukov static int geom_class_available(const char *); 236fbcb16efSLuigi Rizzo static void print_s0(void); 23740905b6eSLuigi Rizzo static void print_part(const struct dos_partition *); 2384be1e61bSAlexander Langer static void init_sector0(unsigned long start); 239f46af505SJordan K. Hubbard static void init_boot(void); 2404be1e61bSAlexander Langer static void change_part(int i); 241041b8b00SPoul-Henning Kamp static void print_params(void); 2424be1e61bSAlexander Langer static void change_active(int which); 243041b8b00SPoul-Henning Kamp static void change_code(void); 244041b8b00SPoul-Henning Kamp static void get_params_to_use(void); 245df77f711SJoerg Wunsch static char *get_rootdisk(void); 24663692187SIan Dowse static void dos(struct dos_partition *partp); 247041b8b00SPoul-Henning Kamp static int open_disk(int flag); 2484be1e61bSAlexander Langer static ssize_t read_disk(off_t sector, void *buf); 249de78c288SPoul-Henning Kamp static int write_disk(off_t sector, void *buf); 250041b8b00SPoul-Henning Kamp static int get_params(void); 251041b8b00SPoul-Henning Kamp static int read_s0(void); 252041b8b00SPoul-Henning Kamp static int write_s0(void); 253041b8b00SPoul-Henning Kamp static int ok(const char *str); 2544be78ce3SMaxim Sobolev static int decimal(const char *str, int *num, int deflt, uint32_t maxval); 255f46af505SJordan K. Hubbard static int read_config(char *config_file); 256f46af505SJordan K. Hubbard static void reset_boot(void); 257b594e0feSJohn Baldwin static int sanitize_partition(struct dos_partition *); 258d98b1668SPhilippe Charnier static void usage(void); 2594be1e61bSAlexander Langer 2604be1e61bSAlexander Langer int 2614be1e61bSAlexander Langer main(int argc, char *argv[]) 2625b81b6b3SRodney W. Grimes { 26326721a89SRobert Nordier int c, i; 264041b8b00SPoul-Henning Kamp int partition = -1; 265041b8b00SPoul-Henning Kamp struct dos_partition *partp; 2665b81b6b3SRodney W. Grimes 267a61d9186SDavid E. O'Brien while ((c = getopt(argc, argv, "BIab:f:ipqstuv1234")) != -1) 26826721a89SRobert Nordier switch (c) { 26926721a89SRobert Nordier case 'B': 27026721a89SRobert Nordier B_flag = 1; 2714ddd60b9SBrian Somers break; 27210b0ee93SWarner Losh case 'I': 27310b0ee93SWarner Losh I_flag = 1; 27410b0ee93SWarner Losh break; 2755b81b6b3SRodney W. Grimes case 'a': 2765b81b6b3SRodney W. Grimes a_flag = 1; 2775b81b6b3SRodney W. Grimes break; 27812d910e9SRobert Nordier case 'b': 27926721a89SRobert Nordier b_flag = optarg; 28012d910e9SRobert Nordier break; 281f46af505SJordan K. Hubbard case 'f': 28226721a89SRobert Nordier f_flag = optarg; 283f46af505SJordan K. Hubbard break; 2845b81b6b3SRodney W. Grimes case 'i': 2855b81b6b3SRodney W. Grimes i_flag = 1; 2865b81b6b3SRodney W. Grimes break; 2877914c60fSMaxim Konovalov case 'p': 2887914c60fSMaxim Konovalov print_config_flag = 1; 2897914c60fSMaxim Konovalov break; 290a61d9186SDavid E. O'Brien case 'q': 291a61d9186SDavid E. O'Brien q_flag = 1; 292a61d9186SDavid E. O'Brien break; 29310b0ee93SWarner Losh case 's': 29410b0ee93SWarner Losh s_flag = 1; 29510b0ee93SWarner Losh break; 296f46af505SJordan K. Hubbard case 't': 297f46af505SJordan K. Hubbard t_flag = 1; 29826721a89SRobert Nordier break; 29926721a89SRobert Nordier case 'u': 30026721a89SRobert Nordier u_flag = 1; 30126721a89SRobert Nordier break; 302f46af505SJordan K. Hubbard case 'v': 303f46af505SJordan K. Hubbard v_flag = 1; 304f46af505SJordan K. Hubbard break; 30526721a89SRobert Nordier case '1': 30626721a89SRobert Nordier case '2': 30726721a89SRobert Nordier case '3': 30826721a89SRobert Nordier case '4': 30926721a89SRobert Nordier partition = c - '0'; 31026721a89SRobert Nordier break; 3115b81b6b3SRodney W. Grimes default: 312d98b1668SPhilippe Charnier usage(); 3135b81b6b3SRodney W. Grimes } 31426721a89SRobert Nordier if (f_flag || i_flag) 31526721a89SRobert Nordier u_flag = 1; 31626721a89SRobert Nordier if (t_flag) 31726721a89SRobert Nordier v_flag = 1; 31826721a89SRobert Nordier argc -= optind; 31926721a89SRobert Nordier argv += optind; 3205b81b6b3SRodney W. Grimes 321df77f711SJoerg Wunsch if (argc == 0) { 322df77f711SJoerg Wunsch disk = get_rootdisk(); 323df77f711SJoerg Wunsch } else { 324b31e5ae2SUlf Lilleengen disk = g_device_path(argv[0]); 325041b8b00SPoul-Henning Kamp if (disk == NULL) 326c4898ccbSLuigi Rizzo err(1, "unable to get correct path for %s", argv[0]); 327df77f711SJoerg Wunsch } 3285b81b6b3SRodney W. Grimes if (open_disk(u_flag) < 0) 329d98b1668SPhilippe Charnier err(1, "cannot open disk %s", disk); 33085c2cf30SJohn Baldwin 33185c2cf30SJohn Baldwin /* (abu)use mboot.bootinst to probe for the sector size */ 33285c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(MAX_SEC_SIZE)) == NULL) 33385c2cf30SJohn Baldwin err(1, "cannot allocate buffer to determine disk sector size"); 334aee85526SSimon L. B. Nielsen if (read_disk(0, mboot.bootinst) == -1) 335aee85526SSimon L. B. Nielsen errx(1, "could not detect sector size"); 336a12de062SJohn Baldwin free(mboot.bootinst); 337a12de062SJohn Baldwin mboot.bootinst = NULL; 33885c2cf30SJohn Baldwin 3397914c60fSMaxim Konovalov if (print_config_flag) { 3407914c60fSMaxim Konovalov if (read_s0()) 3417914c60fSMaxim Konovalov err(1, "read_s0"); 3427914c60fSMaxim Konovalov 3437914c60fSMaxim Konovalov printf("# %s\n", disk); 3447914c60fSMaxim Konovalov printf("g c%d h%d s%d\n", dos_cyls, dos_heads, dos_sectors); 3457914c60fSMaxim Konovalov 3467914c60fSMaxim Konovalov for (i = 0; i < NDOSPART; i++) { 347c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 3487914c60fSMaxim Konovalov 3497914c60fSMaxim Konovalov if (partp->dp_start == 0 && partp->dp_size == 0) 3507914c60fSMaxim Konovalov continue; 3517914c60fSMaxim Konovalov 3527914c60fSMaxim Konovalov printf("p %d 0x%02x %lu %lu\n", i + 1, partp->dp_typ, 3537914c60fSMaxim Konovalov (u_long)partp->dp_start, (u_long)partp->dp_size); 3547914c60fSMaxim Konovalov 3557914c60fSMaxim Konovalov /* Fill flags for the partition. */ 3567914c60fSMaxim Konovalov if (partp->dp_flag & 0x80) 3577914c60fSMaxim Konovalov printf("a %d\n", i + 1); 3587914c60fSMaxim Konovalov } 3597914c60fSMaxim Konovalov exit(0); 3607914c60fSMaxim Konovalov } 361041b8b00SPoul-Henning Kamp if (s_flag) { 36210b0ee93SWarner Losh if (read_s0()) 36310b0ee93SWarner Losh err(1, "read_s0"); 36410b0ee93SWarner Losh printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, 36510b0ee93SWarner Losh dos_sectors); 36610b0ee93SWarner Losh printf("Part %11s %11s Type Flags\n", "Start", "Size"); 36710b0ee93SWarner Losh for (i = 0; i < NDOSPART; i++) { 368c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 36910b0ee93SWarner Losh if (partp->dp_start == 0 && partp->dp_size == 0) 37010b0ee93SWarner Losh continue; 37110b0ee93SWarner Losh printf("%4d: %11lu %11lu 0x%02x 0x%02x\n", i + 1, 37210b0ee93SWarner Losh (u_long) partp->dp_start, 37310b0ee93SWarner Losh (u_long) partp->dp_size, partp->dp_typ, 37410b0ee93SWarner Losh partp->dp_flag); 37510b0ee93SWarner Losh } 37610b0ee93SWarner Losh exit(0); 37710b0ee93SWarner Losh } 3785b81b6b3SRodney W. Grimes 3795b81b6b3SRodney W. Grimes printf("******* Working on device %s *******\n",disk); 380f46af505SJordan K. Hubbard 381041b8b00SPoul-Henning Kamp if (I_flag) { 382e6fb3ddeSPoul-Henning Kamp read_s0(); 383e6fb3ddeSPoul-Henning Kamp reset_boot(); 384c4898ccbSLuigi Rizzo partp = &mboot.parts[0]; 385e6fb3ddeSPoul-Henning Kamp partp->dp_typ = DOSPTYP_386BSD; 386e6fb3ddeSPoul-Henning Kamp partp->dp_flag = ACTIVE; 387e6fb3ddeSPoul-Henning Kamp partp->dp_start = dos_sectors; 388b594e0feSJohn Baldwin partp->dp_size = (disksecs / dos_cylsecs) * dos_cylsecs - 389b594e0feSJohn Baldwin dos_sectors; 39063692187SIan Dowse dos(partp); 391e6fb3ddeSPoul-Henning Kamp if (v_flag) 392fbcb16efSLuigi Rizzo print_s0(); 39305a213f1STom Rhodes if (!t_flag) 394e6fb3ddeSPoul-Henning Kamp write_s0(); 395e6fb3ddeSPoul-Henning Kamp exit(0); 396e6fb3ddeSPoul-Henning Kamp } 397041b8b00SPoul-Henning Kamp if (f_flag) { 398f46af505SJordan K. Hubbard if (read_s0() || i_flag) 399f46af505SJordan K. Hubbard reset_boot(); 400f46af505SJordan K. Hubbard if (!read_config(f_flag)) 401f46af505SJordan K. Hubbard exit(1); 402f46af505SJordan K. Hubbard if (v_flag) 403fbcb16efSLuigi Rizzo print_s0(); 404f46af505SJordan K. Hubbard if (!t_flag) 405f46af505SJordan K. Hubbard write_s0(); 406041b8b00SPoul-Henning Kamp } else { 4075b81b6b3SRodney W. Grimes if(u_flag) 4085b81b6b3SRodney W. Grimes get_params_to_use(); 4095b81b6b3SRodney W. Grimes else 4105b81b6b3SRodney W. Grimes print_params(); 4115b81b6b3SRodney W. Grimes 4125b81b6b3SRodney W. Grimes if (read_s0()) 413b594e0feSJohn Baldwin init_sector0(dos_sectors); 4145b81b6b3SRodney W. Grimes 4157cb29d33SSøren Schmidt printf("Media sector size is %d\n", secsize); 4165b81b6b3SRodney W. Grimes printf("Warning: BIOS sector numbering starts with sector 1\n"); 4175b81b6b3SRodney W. Grimes printf("Information from DOS bootblock is:\n"); 4185b81b6b3SRodney W. Grimes if (partition == -1) 4194ddd60b9SBrian Somers for (i = 1; i <= NDOSPART; i++) 4205b81b6b3SRodney W. Grimes change_part(i); 4215b81b6b3SRodney W. Grimes else 4225b81b6b3SRodney W. Grimes change_part(partition); 4235b81b6b3SRodney W. Grimes 4245b81b6b3SRodney W. Grimes if (u_flag || a_flag) 4255b81b6b3SRodney W. Grimes change_active(partition); 4265b81b6b3SRodney W. Grimes 42726721a89SRobert Nordier if (B_flag) 42812d910e9SRobert Nordier change_code(); 42912d910e9SRobert Nordier 43026721a89SRobert Nordier if (u_flag || a_flag || B_flag) { 431041b8b00SPoul-Henning Kamp if (!t_flag) { 4325b81b6b3SRodney W. Grimes printf("\nWe haven't changed the partition table yet. "); 4335b81b6b3SRodney W. Grimes printf("This is your last chance.\n"); 434f46af505SJordan K. Hubbard } 435fbcb16efSLuigi Rizzo print_s0(); 436041b8b00SPoul-Henning Kamp if (!t_flag) { 4375b81b6b3SRodney W. Grimes if (ok("Should we write new partition table?")) 4385b81b6b3SRodney W. Grimes write_s0(); 439041b8b00SPoul-Henning Kamp } else { 440f46af505SJordan K. Hubbard printf("\n-t flag specified -- partition table not written.\n"); 441f46af505SJordan K. Hubbard } 442f46af505SJordan K. Hubbard } 443f46af505SJordan K. Hubbard } 4445b81b6b3SRodney W. Grimes 4455b81b6b3SRodney W. Grimes exit(0); 446d98b1668SPhilippe Charnier } 4475b81b6b3SRodney W. Grimes 448d98b1668SPhilippe Charnier static void 449d98b1668SPhilippe Charnier usage() 450d98b1668SPhilippe Charnier { 45126721a89SRobert Nordier fprintf(stderr, "%s%s", 452a61d9186SDavid E. O'Brien "usage: fdisk [-BIaipqstu] [-b bootcode] [-1234] [disk]\n", 45326721a89SRobert Nordier " fdisk -f configfile [-itv] [disk]\n"); 454d98b1668SPhilippe Charnier exit(1); 4555b81b6b3SRodney W. Grimes } 4565b81b6b3SRodney W. Grimes 4574be1e61bSAlexander Langer static void 458fbcb16efSLuigi Rizzo print_s0(void) 4595b81b6b3SRodney W. Grimes { 4605b81b6b3SRodney W. Grimes int i; 4615b81b6b3SRodney W. Grimes 4625b81b6b3SRodney W. Grimes print_params(); 4635b81b6b3SRodney W. Grimes printf("Information from DOS bootblock is:\n"); 46440905b6eSLuigi Rizzo for (i = 1; i <= NDOSPART; i++) { 46540905b6eSLuigi Rizzo printf("%d: ", i); 46640905b6eSLuigi Rizzo print_part(&mboot.parts[i - 1]); 46740905b6eSLuigi Rizzo } 4685b81b6b3SRodney W. Grimes } 4695b81b6b3SRodney W. Grimes 470041b8b00SPoul-Henning Kamp static struct dos_partition mtpart; 4715b81b6b3SRodney W. Grimes 4724be1e61bSAlexander Langer static void 47340905b6eSLuigi Rizzo print_part(const struct dos_partition *partp) 4745b81b6b3SRodney W. Grimes { 475637fe2f7SJustin T. Gibbs u_int64_t part_mb; 4765b81b6b3SRodney W. Grimes 4775b81b6b3SRodney W. Grimes if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 4785b81b6b3SRodney W. Grimes printf("<UNUSED>\n"); 4795b81b6b3SRodney W. Grimes return; 4805b81b6b3SRodney W. Grimes } 481637fe2f7SJustin T. Gibbs /* 482637fe2f7SJustin T. Gibbs * Be careful not to overflow. 483637fe2f7SJustin T. Gibbs */ 484637fe2f7SJustin T. Gibbs part_mb = partp->dp_size; 485637fe2f7SJustin T. Gibbs part_mb *= secsize; 486637fe2f7SJustin T. Gibbs part_mb /= (1024 * 1024); 487978d3bfeSJosef Karthauser printf("sysid %d (%#04x),(%s)\n", partp->dp_typ, partp->dp_typ, 488978d3bfeSJosef Karthauser get_type(partp->dp_typ)); 489689fee87SBruce Evans printf(" start %lu, size %lu (%ju Meg), flag %x%s\n", 490ba198492SBruce Evans (u_long)partp->dp_start, 491ba198492SBruce Evans (u_long)partp->dp_size, 492689fee87SBruce Evans (uintmax_t)part_mb, 493680426beSDavid E. O'Brien partp->dp_flag, 494680426beSDavid E. O'Brien partp->dp_flag == ACTIVE ? " (active)" : ""); 4956580291bSDavid E. O'Brien printf("\tbeg: cyl %d/ head %d/ sector %d;\n\tend: cyl %d/ head %d/ sector %d\n" 4965b81b6b3SRodney W. Grimes ,DPCYL(partp->dp_scyl, partp->dp_ssect) 4975b81b6b3SRodney W. Grimes ,partp->dp_shd 4986580291bSDavid E. O'Brien ,DPSECT(partp->dp_ssect) 4995b81b6b3SRodney W. Grimes ,DPCYL(partp->dp_ecyl, partp->dp_esect) 5006580291bSDavid E. O'Brien ,partp->dp_ehd 5016580291bSDavid E. O'Brien ,DPSECT(partp->dp_esect)); 5025b81b6b3SRodney W. Grimes } 5035b81b6b3SRodney W. Grimes 504f46af505SJordan K. Hubbard 505f46af505SJordan K. Hubbard static void 506f46af505SJordan K. Hubbard init_boot(void) 507f46af505SJordan K. Hubbard { 50829ea697dSPeter Wemm #ifndef __ia64__ 50926721a89SRobert Nordier const char *fname; 510041b8b00SPoul-Henning Kamp int fdesc, n; 51185c2cf30SJohn Baldwin struct stat sb; 51226721a89SRobert Nordier 51326721a89SRobert Nordier fname = b_flag ? b_flag : "/boot/mbr"; 514041b8b00SPoul-Henning Kamp if ((fdesc = open(fname, O_RDONLY)) == -1 || 515041b8b00SPoul-Henning Kamp fstat(fdesc, &sb) == -1) 51685c2cf30SJohn Baldwin err(1, "%s", fname); 517469a1218SJohn-Mark Gurney if (sb.st_size == 0) 518469a1218SJohn-Mark Gurney errx(1, "%s is empty, must not be.", fname); 51985c2cf30SJohn Baldwin if ((mboot.bootinst_size = sb.st_size) % secsize != 0) 52085c2cf30SJohn Baldwin errx(1, "%s: length must be a multiple of sector size", fname); 5212b5ce8a9SAndrey A. Chernov if (mboot.bootinst != NULL) 5222b5ce8a9SAndrey A. Chernov free(mboot.bootinst); 52385c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(mboot.bootinst_size = sb.st_size)) == NULL) 52485c2cf30SJohn Baldwin errx(1, "%s: unable to allocate read buffer", fname); 525041b8b00SPoul-Henning Kamp if ((n = read(fdesc, mboot.bootinst, mboot.bootinst_size)) == -1 || 526041b8b00SPoul-Henning Kamp close(fdesc)) 52726721a89SRobert Nordier err(1, "%s", fname); 52885c2cf30SJohn Baldwin if (n != mboot.bootinst_size) 52985c2cf30SJohn Baldwin errx(1, "%s: short read", fname); 53029ea697dSPeter Wemm #else 53129ea697dSPeter Wemm if (mboot.bootinst != NULL) 53229ea697dSPeter Wemm free(mboot.bootinst); 53329ea697dSPeter Wemm mboot.bootinst_size = secsize; 53429ea697dSPeter Wemm if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) 53529ea697dSPeter Wemm errx(1, "unable to allocate boot block buffer"); 53629ea697dSPeter Wemm memset(mboot.bootinst, 0, mboot.bootinst_size); 5371a03d6d5SPoul-Henning Kamp le16enc(&mboot.bootinst[DOSMAGICOFFSET], DOSMAGIC); 53829ea697dSPeter Wemm #endif 539f46af505SJordan K. Hubbard } 540f46af505SJordan K. Hubbard 541f46af505SJordan K. Hubbard 5424be1e61bSAlexander Langer static void 5434be1e61bSAlexander Langer init_sector0(unsigned long start) 5445b81b6b3SRodney W. Grimes { 545c4898ccbSLuigi Rizzo struct dos_partition *partp = &mboot.parts[0]; 5465b81b6b3SRodney W. Grimes 547f46af505SJordan K. Hubbard init_boot(); 5485b81b6b3SRodney W. Grimes 5495b81b6b3SRodney W. Grimes partp->dp_typ = DOSPTYP_386BSD; 5505b81b6b3SRodney W. Grimes partp->dp_flag = ACTIVE; 551b594e0feSJohn Baldwin start = ((start + dos_sectors - 1) / dos_sectors) * dos_sectors; 55285c2cf30SJohn Baldwin if(start == 0) 55385c2cf30SJohn Baldwin start = dos_sectors; 5545b81b6b3SRodney W. Grimes partp->dp_start = start; 555b594e0feSJohn Baldwin partp->dp_size = (disksecs / dos_cylsecs) * dos_cylsecs - start; 5565b81b6b3SRodney W. Grimes 55763692187SIan Dowse dos(partp); 5585b81b6b3SRodney W. Grimes } 5595b81b6b3SRodney W. Grimes 5604be1e61bSAlexander Langer static void 5614be1e61bSAlexander Langer change_part(int i) 5625b81b6b3SRodney W. Grimes { 563c4898ccbSLuigi Rizzo struct dos_partition *partp = &mboot.parts[i - 1]; 5645b81b6b3SRodney W. Grimes 5655b81b6b3SRodney W. Grimes printf("The data for partition %d is:\n", i); 56640905b6eSLuigi Rizzo print_part(partp); 5675b81b6b3SRodney W. Grimes 5685b81b6b3SRodney W. Grimes if (u_flag && ok("Do you want to change it?")) { 5695b81b6b3SRodney W. Grimes int tmp; 5705b81b6b3SRodney W. Grimes 5715b81b6b3SRodney W. Grimes if (i_flag) { 572c4898ccbSLuigi Rizzo bzero(partp, sizeof (*partp)); 573a67ed623SPoul-Henning Kamp if (i == 1) { 5745b81b6b3SRodney W. Grimes init_sector0(1); 575a67ed623SPoul-Henning Kamp printf("\nThe static data for the slice 1 has been reinitialized to:\n"); 57640905b6eSLuigi Rizzo print_part(partp); 5775b81b6b3SRodney W. Grimes } 5785b81b6b3SRodney W. Grimes } 5795b81b6b3SRodney W. Grimes 5805b81b6b3SRodney W. Grimes do { 5814be78ce3SMaxim Sobolev Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp, 255); 5824be78ce3SMaxim Sobolev Decimal("start", partp->dp_start, tmp, NO_DISK_SECTORS); 5834be78ce3SMaxim Sobolev Decimal("size", partp->dp_size, tmp, NO_DISK_SECTORS); 58463692187SIan Dowse if (!sanitize_partition(partp)) { 58563692187SIan Dowse warnx("ERROR: failed to adjust; setting sysid to 0"); 58663692187SIan Dowse partp->dp_typ = 0; 58763692187SIan Dowse } 5885b81b6b3SRodney W. Grimes 5894b3b45a7SJames Raynard if (ok("Explicitly specify beg/end address ?")) 5905b81b6b3SRodney W. Grimes { 5915b81b6b3SRodney W. Grimes int tsec,tcyl,thd; 5925b81b6b3SRodney W. Grimes tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 5935b81b6b3SRodney W. Grimes thd = partp->dp_shd; 5945b81b6b3SRodney W. Grimes tsec = DPSECT(partp->dp_ssect); 5954be78ce3SMaxim Sobolev Decimal("beginning cylinder", tcyl, tmp, NO_TRACK_CYLINDERS); 5964be78ce3SMaxim Sobolev Decimal("beginning head", thd, tmp, NO_TRACK_HEADS); 5974be78ce3SMaxim Sobolev Decimal("beginning sector", tsec, tmp, NO_TRACK_SECTORS); 5985b81b6b3SRodney W. Grimes partp->dp_scyl = DOSCYL(tcyl); 5995b81b6b3SRodney W. Grimes partp->dp_ssect = DOSSECT(tsec,tcyl); 6005b81b6b3SRodney W. Grimes partp->dp_shd = thd; 6015b81b6b3SRodney W. Grimes 6025b81b6b3SRodney W. Grimes tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 6035b81b6b3SRodney W. Grimes thd = partp->dp_ehd; 6045b81b6b3SRodney W. Grimes tsec = DPSECT(partp->dp_esect); 6054be78ce3SMaxim Sobolev Decimal("ending cylinder", tcyl, tmp, NO_TRACK_CYLINDERS); 6064be78ce3SMaxim Sobolev Decimal("ending head", thd, tmp, NO_TRACK_HEADS); 6074be78ce3SMaxim Sobolev Decimal("ending sector", tsec, tmp, NO_TRACK_SECTORS); 6085b81b6b3SRodney W. Grimes partp->dp_ecyl = DOSCYL(tcyl); 6095b81b6b3SRodney W. Grimes partp->dp_esect = DOSSECT(tsec,tcyl); 6105b81b6b3SRodney W. Grimes partp->dp_ehd = thd; 61163692187SIan Dowse } else 61263692187SIan Dowse dos(partp); 6135b81b6b3SRodney W. Grimes 61440905b6eSLuigi Rizzo print_part(partp); 6155b81b6b3SRodney W. Grimes } while (!ok("Are we happy with this entry?")); 6165b81b6b3SRodney W. Grimes } 6175b81b6b3SRodney W. Grimes } 6185b81b6b3SRodney W. Grimes 6194be1e61bSAlexander Langer static void 6205b81b6b3SRodney W. Grimes print_params() 6215b81b6b3SRodney W. Grimes { 6225b81b6b3SRodney W. Grimes printf("parameters extracted from in-core disklabel are:\n"); 6235b81b6b3SRodney W. Grimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 6245b81b6b3SRodney W. Grimes ,cyls,heads,sectors,cylsecs); 6257fa181d4SYoshihiro Takahashi if (dos_cyls > 1023 || dos_heads > 255 || dos_sectors > 63) 6265b81b6b3SRodney W. Grimes printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 6275b81b6b3SRodney W. Grimes printf("parameters to be used for BIOS calculations are:\n"); 6285b81b6b3SRodney W. Grimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 6295b81b6b3SRodney W. Grimes ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 6305b81b6b3SRodney W. Grimes } 6315b81b6b3SRodney W. Grimes 6324be1e61bSAlexander Langer static void 6334be1e61bSAlexander Langer change_active(int which) 6345b81b6b3SRodney W. Grimes { 63563692187SIan Dowse struct dos_partition *partp = &mboot.parts[0]; 63663692187SIan Dowse int active, i, new, tmp; 6375b81b6b3SRodney W. Grimes 63863692187SIan Dowse active = -1; 63963692187SIan Dowse for (i = 0; i < NDOSPART; i++) { 64063692187SIan Dowse if ((partp[i].dp_flag & ACTIVE) == 0) 64163692187SIan Dowse continue; 64263692187SIan Dowse printf("Partition %d is marked active\n", i + 1); 64363692187SIan Dowse if (active == -1) 64463692187SIan Dowse active = i + 1; 64563692187SIan Dowse } 6465b81b6b3SRodney W. Grimes if (a_flag && which != -1) 6475b81b6b3SRodney W. Grimes active = which; 64863692187SIan Dowse else if (active == -1) 64963692187SIan Dowse active = 1; 65063692187SIan Dowse 6510b461cd7SBruce Evans if (!ok("Do you want to change the active partition?")) 6520b461cd7SBruce Evans return; 653680426beSDavid E. O'Brien setactive: 654680426beSDavid E. O'Brien do { 65563692187SIan Dowse new = active; 65668df7abeSMaxim Sobolev Decimal("active partition", new, tmp, 0); 65763692187SIan Dowse if (new < 1 || new > 4) { 658680426beSDavid E. O'Brien printf("Active partition number must be in range 1-4." 659680426beSDavid E. O'Brien " Try again.\n"); 660680426beSDavid E. O'Brien goto setactive; 661680426beSDavid E. O'Brien } 66263692187SIan Dowse active = new; 663680426beSDavid E. O'Brien } while (!ok("Are you happy with this choice")); 6645b81b6b3SRodney W. Grimes for (i = 0; i < NDOSPART; i++) 6655b81b6b3SRodney W. Grimes partp[i].dp_flag = 0; 6664ddd60b9SBrian Somers if (active > 0 && active <= NDOSPART) 6674ddd60b9SBrian Somers partp[active-1].dp_flag = ACTIVE; 6685b81b6b3SRodney W. Grimes } 6695b81b6b3SRodney W. Grimes 67012d910e9SRobert Nordier static void 67112d910e9SRobert Nordier change_code() 67212d910e9SRobert Nordier { 67312d910e9SRobert Nordier if (ok("Do you want to change the boot code?")) 67412d910e9SRobert Nordier init_boot(); 67512d910e9SRobert Nordier } 67612d910e9SRobert Nordier 6774be1e61bSAlexander Langer void 6785b81b6b3SRodney W. Grimes get_params_to_use() 6795b81b6b3SRodney W. Grimes { 6805b81b6b3SRodney W. Grimes int tmp; 6815b81b6b3SRodney W. Grimes print_params(); 6825b81b6b3SRodney W. Grimes if (ok("Do you want to change our idea of what BIOS thinks ?")) 6835b81b6b3SRodney W. Grimes { 6845b81b6b3SRodney W. Grimes do 6855b81b6b3SRodney W. Grimes { 68668df7abeSMaxim Sobolev Decimal("BIOS's idea of #cylinders", dos_cyls, tmp, 0); 68768df7abeSMaxim Sobolev Decimal("BIOS's idea of #heads", dos_heads, tmp, 0); 68868df7abeSMaxim Sobolev Decimal("BIOS's idea of #sectors", dos_sectors, tmp, 0); 6895b81b6b3SRodney W. Grimes dos_cylsecs = dos_heads * dos_sectors; 6905b81b6b3SRodney W. Grimes print_params(); 6915b81b6b3SRodney W. Grimes } 6925b81b6b3SRodney W. Grimes while(!ok("Are you happy with this choice")); 6935b81b6b3SRodney W. Grimes } 6945b81b6b3SRodney W. Grimes } 6955b81b6b3SRodney W. Grimes 696f46af505SJordan K. Hubbard 6975b81b6b3SRodney W. Grimes /***********************************************\ 6985b81b6b3SRodney W. Grimes * Change real numbers into strange dos numbers * 6995b81b6b3SRodney W. Grimes \***********************************************/ 7004be1e61bSAlexander Langer static void 701041b8b00SPoul-Henning Kamp dos(struct dos_partition *partp) 7025b81b6b3SRodney W. Grimes { 70363692187SIan Dowse int cy, sec; 70463692187SIan Dowse u_int32_t end; 7055b81b6b3SRodney W. Grimes 706881c9063SIan Dowse if (partp->dp_typ == 0 && partp->dp_start == 0 && partp->dp_size == 0) { 707881c9063SIan Dowse memcpy(partp, &mtpart, sizeof(*partp)); 7080b461cd7SBruce Evans return; 7090b461cd7SBruce Evans } 7100b461cd7SBruce Evans 71163692187SIan Dowse /* Start c/h/s. */ 71263692187SIan Dowse partp->dp_shd = partp->dp_start % dos_cylsecs / dos_sectors; 71363692187SIan Dowse cy = partp->dp_start / dos_cylsecs; 71463692187SIan Dowse sec = partp->dp_start % dos_sectors + 1; 71563692187SIan Dowse partp->dp_scyl = DOSCYL(cy); 71663692187SIan Dowse partp->dp_ssect = DOSSECT(sec, cy); 7175b81b6b3SRodney W. Grimes 71863692187SIan Dowse /* End c/h/s. */ 71963692187SIan Dowse end = partp->dp_start + partp->dp_size - 1; 72063692187SIan Dowse partp->dp_ehd = end % dos_cylsecs / dos_sectors; 72163692187SIan Dowse cy = end / dos_cylsecs; 72263692187SIan Dowse sec = end % dos_sectors + 1; 72363692187SIan Dowse partp->dp_ecyl = DOSCYL(cy); 72463692187SIan Dowse partp->dp_esect = DOSSECT(sec, cy); 7255b81b6b3SRodney W. Grimes } 7265b81b6b3SRodney W. Grimes 7274be1e61bSAlexander Langer static int 728041b8b00SPoul-Henning Kamp open_disk(int flag) 7295b81b6b3SRodney W. Grimes { 730de78c288SPoul-Henning Kamp int rwmode; 7315b81b6b3SRodney W. Grimes 732b31e5ae2SUlf Lilleengen /* Write mode if one of these flags are set. */ 733b31e5ae2SUlf Lilleengen rwmode = (a_flag || I_flag || B_flag || flag); 734b31e5ae2SUlf Lilleengen fd = g_open(disk, rwmode); 735b31e5ae2SUlf Lilleengen /* If the mode fails, try read-only if we didn't. */ 736b31e5ae2SUlf Lilleengen if (fd == -1 && errno == EPERM && rwmode) 737b31e5ae2SUlf Lilleengen fd = g_open(disk, 0); 738f353c761SPoul-Henning Kamp if (fd == -1 && errno == ENXIO) 739e3038c6eSJoerg Wunsch return -2; 740f353c761SPoul-Henning Kamp if (fd == -1) { 741d98b1668SPhilippe Charnier warnx("can't open device %s", disk); 7425b81b6b3SRodney W. Grimes return -1; 7435b81b6b3SRodney W. Grimes } 744041b8b00SPoul-Henning Kamp if (get_params() == -1) { 745d98b1668SPhilippe Charnier warnx("can't get disk parameters on %s", disk); 7465b81b6b3SRodney W. Grimes return -1; 7475b81b6b3SRodney W. Grimes } 7485b81b6b3SRodney W. Grimes return fd; 7495b81b6b3SRodney W. Grimes } 7505b81b6b3SRodney W. Grimes 7514be1e61bSAlexander Langer static ssize_t 7524be1e61bSAlexander Langer read_disk(off_t sector, void *buf) 7535b81b6b3SRodney W. Grimes { 7547fa181d4SYoshihiro Takahashi 7555b81b6b3SRodney W. Grimes lseek(fd, (sector * 512), 0); 7567cb29d33SSøren Schmidt if (secsize == 0) 7577fa181d4SYoshihiro Takahashi for (secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; 7587fa181d4SYoshihiro Takahashi secsize *= 2) { 7597cb29d33SSøren Schmidt /* try the read */ 7607cb29d33SSøren Schmidt int size = read(fd, buf, secsize); 7617cb29d33SSøren Schmidt if (size == secsize) 7627cb29d33SSøren Schmidt /* it worked so return */ 7637cb29d33SSøren Schmidt return secsize; 7647cb29d33SSøren Schmidt } 7657cb29d33SSøren Schmidt else 7667cb29d33SSøren Schmidt return read(fd, buf, secsize); 7677cb29d33SSøren Schmidt 7687cb29d33SSøren Schmidt /* we failed to read at any of the sizes */ 7697cb29d33SSøren Schmidt return -1; 7705b81b6b3SRodney W. Grimes } 7715b81b6b3SRodney W. Grimes 772de78c288SPoul-Henning Kamp static int 773fd1ca22aSAndrey V. Elsukov geom_class_available(const char *name) 774fd1ca22aSAndrey V. Elsukov { 775fd1ca22aSAndrey V. Elsukov struct gclass *class; 776fd1ca22aSAndrey V. Elsukov struct gmesh mesh; 777fd1ca22aSAndrey V. Elsukov int error; 778fd1ca22aSAndrey V. Elsukov 779fd1ca22aSAndrey V. Elsukov error = geom_gettree(&mesh); 780fd1ca22aSAndrey V. Elsukov if (error != 0) 781fd1ca22aSAndrey V. Elsukov errc(1, error, "Cannot get GEOM tree"); 782fd1ca22aSAndrey V. Elsukov 783fd1ca22aSAndrey V. Elsukov LIST_FOREACH(class, &mesh.lg_class, lg_class) { 784fd1ca22aSAndrey V. Elsukov if (strcmp(class->lg_name, name) == 0) { 785fd1ca22aSAndrey V. Elsukov geom_deletetree(&mesh); 786fd1ca22aSAndrey V. Elsukov return (1); 787fd1ca22aSAndrey V. Elsukov } 788fd1ca22aSAndrey V. Elsukov } 789fd1ca22aSAndrey V. Elsukov 790fd1ca22aSAndrey V. Elsukov geom_deletetree(&mesh); 791fd1ca22aSAndrey V. Elsukov 792fd1ca22aSAndrey V. Elsukov return (0); 793fd1ca22aSAndrey V. Elsukov } 794fd1ca22aSAndrey V. Elsukov 795fd1ca22aSAndrey V. Elsukov static int 7964be1e61bSAlexander Langer write_disk(off_t sector, void *buf) 7975b81b6b3SRodney W. Grimes { 798de78c288SPoul-Henning Kamp struct gctl_req *grq; 799b31e5ae2SUlf Lilleengen const char *errmsg; 800fd1ca22aSAndrey V. Elsukov char *pname; 801fd1ca22aSAndrey V. Elsukov int error; 802f353c761SPoul-Henning Kamp 803fd1ca22aSAndrey V. Elsukov /* Check that GEOM_MBR is available */ 804fd1ca22aSAndrey V. Elsukov if (geom_class_available("MBR") != 0) { 805de78c288SPoul-Henning Kamp grq = gctl_get_handle(); 806de78c288SPoul-Henning Kamp gctl_ro_param(grq, "verb", -1, "write MBR"); 807de78c288SPoul-Henning Kamp gctl_ro_param(grq, "class", -1, "MBR"); 808b31e5ae2SUlf Lilleengen pname = g_providername(fd); 809b31e5ae2SUlf Lilleengen if (pname == NULL) { 810bd5add58SUlf Lilleengen warn("Error getting providername for %s", disk); 811b31e5ae2SUlf Lilleengen return (-1); 812b31e5ae2SUlf Lilleengen } 813b31e5ae2SUlf Lilleengen gctl_ro_param(grq, "geom", -1, pname); 814de78c288SPoul-Henning Kamp gctl_ro_param(grq, "data", secsize, buf); 815b31e5ae2SUlf Lilleengen errmsg = gctl_issue(grq); 816b31e5ae2SUlf Lilleengen free(pname); 817b31e5ae2SUlf Lilleengen if (errmsg == NULL) { 818d63612b4SCraig Rodrigues gctl_free(grq); 819de78c288SPoul-Henning Kamp return(0); 820d63612b4SCraig Rodrigues } 821fd1ca22aSAndrey V. Elsukov if (!q_flag) 822fd1ca22aSAndrey V. Elsukov warnx("GEOM_MBR: %s", errmsg); 823d63612b4SCraig Rodrigues gctl_free(grq); 824fd1ca22aSAndrey V. Elsukov } else { 825*39e9a28fSAndrey V. Elsukov /* 826*39e9a28fSAndrey V. Elsukov * Try to write MBR directly. This may help when disk 827fd1ca22aSAndrey V. Elsukov * is not in use. 828fd1ca22aSAndrey V. Elsukov * XXX: hardcoded sectorsize 829fd1ca22aSAndrey V. Elsukov */ 830de78c288SPoul-Henning Kamp error = pwrite(fd, buf, secsize, (sector * 512)); 831de78c288SPoul-Henning Kamp if (error == secsize) 832de78c288SPoul-Henning Kamp return (0); 8335b81b6b3SRodney W. Grimes } 834fd1ca22aSAndrey V. Elsukov 835*39e9a28fSAndrey V. Elsukov /* 836*39e9a28fSAndrey V. Elsukov * GEOM_MBR is not available or failed to write MBR. 837fd1ca22aSAndrey V. Elsukov * Now check that we have GEOM_PART and recommend to use gpart (8). 838fd1ca22aSAndrey V. Elsukov */ 839fd1ca22aSAndrey V. Elsukov if (geom_class_available("PART") != 0) 840fd1ca22aSAndrey V. Elsukov warnx("Failed to write MBR. Try to use gpart(8)."); 841fd1ca22aSAndrey V. Elsukov else 842de78c288SPoul-Henning Kamp warnx("Failed to write sector zero"); 843de78c288SPoul-Henning Kamp return(EINVAL); 844f353c761SPoul-Henning Kamp } 8455b81b6b3SRodney W. Grimes 8464be1e61bSAlexander Langer static int 8474be1e61bSAlexander Langer get_params() 8485b81b6b3SRodney W. Grimes { 8493f8ba8b5SPoul-Henning Kamp int error; 8503f8ba8b5SPoul-Henning Kamp u_int u; 8513f8ba8b5SPoul-Henning Kamp off_t o; 8525b81b6b3SRodney W. Grimes 8537963fae6SPoul-Henning Kamp error = ioctl(fd, DIOCGFWSECTORS, &u); 8547963fae6SPoul-Henning Kamp if (error == 0) 8557963fae6SPoul-Henning Kamp sectors = dos_sectors = u; 856c0fdfdbaSPoul-Henning Kamp else 857c0fdfdbaSPoul-Henning Kamp sectors = dos_sectors = 63; 858c0fdfdbaSPoul-Henning Kamp 8597963fae6SPoul-Henning Kamp error = ioctl(fd, DIOCGFWHEADS, &u); 8607963fae6SPoul-Henning Kamp if (error == 0) 8617963fae6SPoul-Henning Kamp heads = dos_heads = u; 862c0fdfdbaSPoul-Henning Kamp else 863c0fdfdbaSPoul-Henning Kamp heads = dos_heads = 255; 8647963fae6SPoul-Henning Kamp 8655b81b6b3SRodney W. Grimes dos_cylsecs = cylsecs = heads * sectors; 8665b81b6b3SRodney W. Grimes disksecs = cyls * heads * sectors; 8675b81b6b3SRodney W. Grimes 868b31e5ae2SUlf Lilleengen u = g_sectorsize(fd); 869b31e5ae2SUlf Lilleengen if (u <= 0) 870b31e5ae2SUlf Lilleengen return (-1); 8717963fae6SPoul-Henning Kamp 872b31e5ae2SUlf Lilleengen o = g_mediasize(fd); 873b31e5ae2SUlf Lilleengen if (o < 0) 874b31e5ae2SUlf Lilleengen return (-1); 8757963fae6SPoul-Henning Kamp disksecs = o / u; 8767963fae6SPoul-Henning Kamp cyls = dos_cyls = o / (u * dos_heads * dos_sectors); 8777963fae6SPoul-Henning Kamp 8785b81b6b3SRodney W. Grimes return (disksecs); 8795b81b6b3SRodney W. Grimes } 8805b81b6b3SRodney W. Grimes 8814be1e61bSAlexander Langer static int 8825b81b6b3SRodney W. Grimes read_s0() 8835b81b6b3SRodney W. Grimes { 8841a03d6d5SPoul-Henning Kamp int i; 8851a03d6d5SPoul-Henning Kamp 88685c2cf30SJohn Baldwin mboot.bootinst_size = secsize; 8872b5ce8a9SAndrey A. Chernov if (mboot.bootinst != NULL) 8882b5ce8a9SAndrey A. Chernov free(mboot.bootinst); 88985c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) { 89085c2cf30SJohn Baldwin warnx("unable to allocate buffer to read fdisk " 89185c2cf30SJohn Baldwin "partition table"); 89285c2cf30SJohn Baldwin return -1; 89385c2cf30SJohn Baldwin } 89485c2cf30SJohn Baldwin if (read_disk(0, mboot.bootinst) == -1) { 895d98b1668SPhilippe Charnier warnx("can't read fdisk partition table"); 8965b81b6b3SRodney W. Grimes return -1; 8975b81b6b3SRodney W. Grimes } 8981a03d6d5SPoul-Henning Kamp if (le16dec(&mboot.bootinst[DOSMAGICOFFSET]) != DOSMAGIC) { 899d98b1668SPhilippe Charnier warnx("invalid fdisk partition table found"); 9005b81b6b3SRodney W. Grimes /* So should we initialize things */ 9015b81b6b3SRodney W. Grimes return -1; 9025b81b6b3SRodney W. Grimes } 9031a03d6d5SPoul-Henning Kamp for (i = 0; i < NDOSPART; i++) 9041a03d6d5SPoul-Henning Kamp dos_partition_dec( 9051a03d6d5SPoul-Henning Kamp &mboot.bootinst[DOSPARTOFF + i * DOSPARTSIZE], 9061a03d6d5SPoul-Henning Kamp &mboot.parts[i]); 9075b81b6b3SRodney W. Grimes return 0; 9085b81b6b3SRodney W. Grimes } 9095b81b6b3SRodney W. Grimes 9104be1e61bSAlexander Langer static int 9115b81b6b3SRodney W. Grimes write_s0() 9125b81b6b3SRodney W. Grimes { 9131a03d6d5SPoul-Henning Kamp int sector, i; 91485c2cf30SJohn Baldwin 9155b81b6b3SRodney W. Grimes if (iotest) { 916fbcb16efSLuigi Rizzo print_s0(); 9175b81b6b3SRodney W. Grimes return 0; 9185b81b6b3SRodney W. Grimes } 9191a03d6d5SPoul-Henning Kamp for(i = 0; i < NDOSPART; i++) 9201a03d6d5SPoul-Henning Kamp dos_partition_enc(&mboot.bootinst[DOSPARTOFF + i * DOSPARTSIZE], 9211a03d6d5SPoul-Henning Kamp &mboot.parts[i]); 9221a03d6d5SPoul-Henning Kamp le16enc(&mboot.bootinst[DOSMAGICOFFSET], DOSMAGIC); 92385c2cf30SJohn Baldwin for(sector = 0; sector < mboot.bootinst_size / secsize; sector++) 92485c2cf30SJohn Baldwin if (write_disk(sector, 92585c2cf30SJohn Baldwin &mboot.bootinst[sector * secsize]) == -1) { 926e6fb3ddeSPoul-Henning Kamp warn("can't write fdisk partition table"); 9275b81b6b3SRodney W. Grimes return -1; 9285b81b6b3SRodney W. Grimes } 9294be1e61bSAlexander Langer return(0); 9305b81b6b3SRodney W. Grimes } 9315b81b6b3SRodney W. Grimes 9325b81b6b3SRodney W. Grimes 9334be1e61bSAlexander Langer static int 934041b8b00SPoul-Henning Kamp ok(const char *str) 9355b81b6b3SRodney W. Grimes { 9365b81b6b3SRodney W. Grimes printf("%s [n] ", str); 93763692187SIan Dowse fflush(stdout); 93863692187SIan Dowse if (fgets(lbuf, LBUF, stdin) == NULL) 93963692187SIan Dowse exit(1); 9405b81b6b3SRodney W. Grimes lbuf[strlen(lbuf)-1] = 0; 9415b81b6b3SRodney W. Grimes 9425b81b6b3SRodney W. Grimes if (*lbuf && 9435b81b6b3SRodney W. Grimes (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 9445b81b6b3SRodney W. Grimes !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 9455b81b6b3SRodney W. Grimes return 1; 9465b81b6b3SRodney W. Grimes else 9475b81b6b3SRodney W. Grimes return 0; 9485b81b6b3SRodney W. Grimes } 9495b81b6b3SRodney W. Grimes 9504be1e61bSAlexander Langer static int 9514be78ce3SMaxim Sobolev decimal(const char *str, int *num, int deflt, uint32_t maxval) 9525b81b6b3SRodney W. Grimes { 9531b100fd3SAndrey V. Elsukov long long acc; 95468df7abeSMaxim Sobolev int c; 9555b81b6b3SRodney W. Grimes char *cp; 9565b81b6b3SRodney W. Grimes 9575b81b6b3SRodney W. Grimes while (1) { 9581b100fd3SAndrey V. Elsukov acc = 0; 9595b81b6b3SRodney W. Grimes printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 96063692187SIan Dowse fflush(stdout); 96163692187SIan Dowse if (fgets(lbuf, LBUF, stdin) == NULL) 96263692187SIan Dowse exit(1); 9635b81b6b3SRodney W. Grimes lbuf[strlen(lbuf)-1] = 0; 9645b81b6b3SRodney W. Grimes 9655b81b6b3SRodney W. Grimes if (!*lbuf) 9665b81b6b3SRodney W. Grimes return 0; 9675b81b6b3SRodney W. Grimes 9685b81b6b3SRodney W. Grimes cp = lbuf; 9695b81b6b3SRodney W. Grimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 9705b81b6b3SRodney W. Grimes if (!c) 9715b81b6b3SRodney W. Grimes return 0; 9724be1e61bSAlexander Langer while ((c = *cp++)) { 97368df7abeSMaxim Sobolev if (c <= '9' && c >= '0') { 9746bfcd9c3SAndrey V. Elsukov if (acc <= maxval || maxval == 0) 9755b81b6b3SRodney W. Grimes acc = acc * 10 + c - '0'; 97668df7abeSMaxim Sobolev } else 9775b81b6b3SRodney W. Grimes break; 9785b81b6b3SRodney W. Grimes } 9795b81b6b3SRodney W. Grimes if (c == ' ' || c == '\t') 9805b81b6b3SRodney W. Grimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 9815b81b6b3SRodney W. Grimes if (!c) { 9824be78ce3SMaxim Sobolev if (maxval > 0 && acc > maxval) { 9834be78ce3SMaxim Sobolev acc = maxval; 9844be78ce3SMaxim Sobolev printf("%s exceeds maximum value allowed for " 9854be78ce3SMaxim Sobolev "this field. The value has been reduced " 9864be78ce3SMaxim Sobolev "to %lld\n", lbuf, acc); 98768df7abeSMaxim Sobolev } 9885b81b6b3SRodney W. Grimes *num = acc; 9895b81b6b3SRodney W. Grimes return 1; 9905b81b6b3SRodney W. Grimes } else 991680426beSDavid E. O'Brien printf("%s is an invalid decimal number. Try again.\n", 9925b81b6b3SRodney W. Grimes lbuf); 9935b81b6b3SRodney W. Grimes } 9945b81b6b3SRodney W. Grimes } 9955b81b6b3SRodney W. Grimes 996f46af505SJordan K. Hubbard 997f46af505SJordan K. Hubbard static void 998041b8b00SPoul-Henning Kamp parse_config_line(char *line, CMD *command) 999f46af505SJordan K. Hubbard { 1000f46af505SJordan K. Hubbard char *cp, *end; 1001f46af505SJordan K. Hubbard 1002f46af505SJordan K. Hubbard cp = line; 1003041b8b00SPoul-Henning Kamp while (1) { 1004f46af505SJordan K. Hubbard memset(command, 0, sizeof(*command)); 1005f46af505SJordan K. Hubbard 1006f46af505SJordan K. Hubbard while (isspace(*cp)) ++cp; 1007f46af505SJordan K. Hubbard if (*cp == '\0' || *cp == '#') 1008f46af505SJordan K. Hubbard break; 1009f46af505SJordan K. Hubbard command->cmd = *cp++; 1010f46af505SJordan K. Hubbard 1011f46af505SJordan K. Hubbard /* 1012f46af505SJordan K. Hubbard * Parse args 1013f46af505SJordan K. Hubbard */ 1014041b8b00SPoul-Henning Kamp while (1) { 1015f46af505SJordan K. Hubbard while (isspace(*cp)) ++cp; 1016d1c77156SBrian Somers if (*cp == '\0') 1017d1c77156SBrian Somers break; /* eol */ 1018f46af505SJordan K. Hubbard if (*cp == '#') 1019f46af505SJordan K. Hubbard break; /* found comment */ 1020f46af505SJordan K. Hubbard if (isalpha(*cp)) 1021f46af505SJordan K. Hubbard command->args[command->n_args].argtype = *cp++; 1022f46af505SJordan K. Hubbard end = NULL; 1023f9373bbdSRyan Stone command->args[command->n_args].arg_val = strtoul(cp, &end, 0); 1024d1c77156SBrian Somers if (cp == end || (!isspace(*end) && *end != '\0')) { 1025d1c77156SBrian Somers char ch; 1026d1c77156SBrian Somers end = cp; 1027d1c77156SBrian Somers while (!isspace(*end) && *end != '\0') ++end; 1028d1c77156SBrian Somers ch = *end; *end = '\0'; 1029d1c77156SBrian Somers command->args[command->n_args].arg_str = strdup(cp); 1030d1c77156SBrian Somers *end = ch; 1031d1c77156SBrian Somers } else 1032d1c77156SBrian Somers command->args[command->n_args].arg_str = NULL; 1033f46af505SJordan K. Hubbard cp = end; 1034f46af505SJordan K. Hubbard command->n_args++; 1035f46af505SJordan K. Hubbard } 1036f46af505SJordan K. Hubbard break; 1037f46af505SJordan K. Hubbard } 1038f46af505SJordan K. Hubbard } 1039f46af505SJordan K. Hubbard 1040f46af505SJordan K. Hubbard 1041f46af505SJordan K. Hubbard static int 1042041b8b00SPoul-Henning Kamp process_geometry(CMD *command) 1043f46af505SJordan K. Hubbard { 1044f46af505SJordan K. Hubbard int status = 1, i; 1045f46af505SJordan K. Hubbard 1046041b8b00SPoul-Henning Kamp while (1) { 1047f46af505SJordan K. Hubbard geom_processed = 1; 1048041b8b00SPoul-Henning Kamp if (part_processed) { 1049d98b1668SPhilippe Charnier warnx( 1050d98b1668SPhilippe Charnier "ERROR line %d: the geometry specification line must occur before\n\ 1051d98b1668SPhilippe Charnier all partition specifications", 1052d98b1668SPhilippe Charnier current_line_number); 1053f46af505SJordan K. Hubbard status = 0; 1054f46af505SJordan K. Hubbard break; 1055f46af505SJordan K. Hubbard } 1056041b8b00SPoul-Henning Kamp if (command->n_args != 3) { 1057d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of geometry args", 1058d98b1668SPhilippe Charnier current_line_number); 1059f46af505SJordan K. Hubbard status = 0; 1060f46af505SJordan K. Hubbard break; 1061f46af505SJordan K. Hubbard } 1062041b8b00SPoul-Henning Kamp dos_cyls = 0; 1063041b8b00SPoul-Henning Kamp dos_heads = 0; 1064041b8b00SPoul-Henning Kamp dos_sectors = 0; 1065041b8b00SPoul-Henning Kamp for (i = 0; i < 3; ++i) { 1066041b8b00SPoul-Henning Kamp switch (command->args[i].argtype) { 1067f46af505SJordan K. Hubbard case 'c': 1068f46af505SJordan K. Hubbard dos_cyls = command->args[i].arg_val; 1069f46af505SJordan K. Hubbard break; 1070f46af505SJordan K. Hubbard case 'h': 1071f46af505SJordan K. Hubbard dos_heads = command->args[i].arg_val; 1072f46af505SJordan K. Hubbard break; 1073f46af505SJordan K. Hubbard case 's': 1074f46af505SJordan K. Hubbard dos_sectors = command->args[i].arg_val; 1075f46af505SJordan K. Hubbard break; 1076f46af505SJordan K. Hubbard default: 1077d98b1668SPhilippe Charnier warnx( 1078d98b1668SPhilippe Charnier "ERROR line %d: unknown geometry arg type: '%c' (0x%02x)", 1079d98b1668SPhilippe Charnier current_line_number, command->args[i].argtype, 1080f46af505SJordan K. Hubbard command->args[i].argtype); 1081f46af505SJordan K. Hubbard status = 0; 1082f46af505SJordan K. Hubbard break; 1083f46af505SJordan K. Hubbard } 1084f46af505SJordan K. Hubbard } 1085f46af505SJordan K. Hubbard if (status == 0) 1086f46af505SJordan K. Hubbard break; 1087f46af505SJordan K. Hubbard 1088f46af505SJordan K. Hubbard dos_cylsecs = dos_heads * dos_sectors; 1089f46af505SJordan K. Hubbard 1090f46af505SJordan K. Hubbard /* 1091f46af505SJordan K. Hubbard * Do sanity checks on parameter values 1092f46af505SJordan K. Hubbard */ 1093041b8b00SPoul-Henning Kamp if (dos_cyls == 0) { 1094d98b1668SPhilippe Charnier warnx("ERROR line %d: number of cylinders not specified", 1095d98b1668SPhilippe Charnier current_line_number); 1096f46af505SJordan K. Hubbard status = 0; 1097f46af505SJordan K. Hubbard } 1098041b8b00SPoul-Henning Kamp if (dos_cyls > 1024) { 1099d98b1668SPhilippe Charnier warnx( 1100d98b1668SPhilippe Charnier "WARNING line %d: number of cylinders (%d) may be out-of-range\n\ 1101f46af505SJordan K. Hubbard (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\ 1102d98b1668SPhilippe Charnier is dedicated to FreeBSD)", 1103d98b1668SPhilippe Charnier current_line_number, dos_cyls); 1104f46af505SJordan K. Hubbard } 1105f46af505SJordan K. Hubbard 1106041b8b00SPoul-Henning Kamp if (dos_heads == 0) { 1107d98b1668SPhilippe Charnier warnx("ERROR line %d: number of heads not specified", 1108d98b1668SPhilippe Charnier current_line_number); 1109f46af505SJordan K. Hubbard status = 0; 1110ea32a699SUlf Lilleengen } else if (dos_heads > 256) { 1111ea32a699SUlf Lilleengen warnx("ERROR line %d: number of heads must be within (1-256)", 1112d98b1668SPhilippe Charnier current_line_number); 1113f46af505SJordan K. Hubbard status = 0; 1114f46af505SJordan K. Hubbard } 1115f46af505SJordan K. Hubbard 1116041b8b00SPoul-Henning Kamp if (dos_sectors == 0) { 1117d98b1668SPhilippe Charnier warnx("ERROR line %d: number of sectors not specified", 1118d98b1668SPhilippe Charnier current_line_number); 1119f46af505SJordan K. Hubbard status = 0; 1120041b8b00SPoul-Henning Kamp } else if (dos_sectors > 63) { 1121d98b1668SPhilippe Charnier warnx("ERROR line %d: number of sectors must be within (1-63)", 1122d98b1668SPhilippe Charnier current_line_number); 1123f46af505SJordan K. Hubbard status = 0; 1124f46af505SJordan K. Hubbard } 1125f46af505SJordan K. Hubbard 1126f46af505SJordan K. Hubbard break; 1127f46af505SJordan K. Hubbard } 1128f46af505SJordan K. Hubbard return (status); 1129f46af505SJordan K. Hubbard } 1130f46af505SJordan K. Hubbard 1131d1c77156SBrian Somers static u_int32_t 1132d1c77156SBrian Somers str2sectors(const char *str) 1133d1c77156SBrian Somers { 1134d1c77156SBrian Somers char *end; 1135d1c77156SBrian Somers unsigned long val; 1136d1c77156SBrian Somers 1137d1c77156SBrian Somers val = strtoul(str, &end, 0); 1138d1c77156SBrian Somers if (str == end || *end == '\0') { 1139d1c77156SBrian Somers warnx("ERROR line %d: unexpected size: \'%s\'", 1140d1c77156SBrian Somers current_line_number, str); 11414be78ce3SMaxim Sobolev return NO_DISK_SECTORS; 1142d1c77156SBrian Somers } 1143d1c77156SBrian Somers 1144d1c77156SBrian Somers if (*end == 'K') 1145d1c77156SBrian Somers val *= 1024UL / secsize; 1146d1c77156SBrian Somers else if (*end == 'M') 1147d1c77156SBrian Somers val *= 1024UL * 1024UL / secsize; 1148d1c77156SBrian Somers else if (*end == 'G') 1149d1c77156SBrian Somers val *= 1024UL * 1024UL * 1024UL / secsize; 1150d1c77156SBrian Somers else { 1151d1c77156SBrian Somers warnx("ERROR line %d: unexpected modifier: %c " 1152d1c77156SBrian Somers "(not K/M/G)", current_line_number, *end); 11534be78ce3SMaxim Sobolev return NO_DISK_SECTORS; 1154d1c77156SBrian Somers } 1155d1c77156SBrian Somers 1156d1c77156SBrian Somers return val; 1157d1c77156SBrian Somers } 1158f46af505SJordan K. Hubbard 1159f46af505SJordan K. Hubbard static int 1160041b8b00SPoul-Henning Kamp process_partition(CMD *command) 1161f46af505SJordan K. Hubbard { 1162f46af505SJordan K. Hubbard int status = 0, partition; 1163b594e0feSJohn Baldwin u_int32_t prev_head_boundary, prev_cyl_boundary; 1164b594e0feSJohn Baldwin u_int32_t adj_size, max_end; 1165f46af505SJordan K. Hubbard struct dos_partition *partp; 1166f46af505SJordan K. Hubbard 1167041b8b00SPoul-Henning Kamp while (1) { 1168f46af505SJordan K. Hubbard part_processed = 1; 1169041b8b00SPoul-Henning Kamp if (command->n_args != 4) { 1170d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of partition args", 1171d98b1668SPhilippe Charnier current_line_number); 1172f46af505SJordan K. Hubbard break; 1173f46af505SJordan K. Hubbard } 1174f46af505SJordan K. Hubbard partition = command->args[0].arg_val; 1175041b8b00SPoul-Henning Kamp if (partition < 1 || partition > 4) { 1176d98b1668SPhilippe Charnier warnx("ERROR line %d: invalid partition number %d", 1177d98b1668SPhilippe Charnier current_line_number, partition); 1178f46af505SJordan K. Hubbard break; 1179f46af505SJordan K. Hubbard } 1180c4898ccbSLuigi Rizzo partp = &mboot.parts[partition - 1]; 1181c4898ccbSLuigi Rizzo bzero(partp, sizeof (*partp)); 1182f46af505SJordan K. Hubbard partp->dp_typ = command->args[1].arg_val; 1183d1c77156SBrian Somers if (command->args[2].arg_str != NULL) { 1184d1c77156SBrian Somers if (strcmp(command->args[2].arg_str, "*") == 0) { 1185d1c77156SBrian Somers int i; 1186d1c77156SBrian Somers partp->dp_start = dos_sectors; 1187d1c77156SBrian Somers for (i = 1; i < partition; i++) { 1188d1c77156SBrian Somers struct dos_partition *prev_partp; 1189d1c77156SBrian Somers prev_partp = ((struct dos_partition *) 1190d1c77156SBrian Somers &mboot.parts) + i - 1; 1191d1c77156SBrian Somers if (prev_partp->dp_typ != 0) 1192d1c77156SBrian Somers partp->dp_start = prev_partp->dp_start + 1193d1c77156SBrian Somers prev_partp->dp_size; 1194d1c77156SBrian Somers } 1195d1c77156SBrian Somers if (partp->dp_start % dos_sectors != 0) { 1196d1c77156SBrian Somers prev_head_boundary = partp->dp_start / 1197d1c77156SBrian Somers dos_sectors * dos_sectors; 1198d1c77156SBrian Somers partp->dp_start = prev_head_boundary + 1199d1c77156SBrian Somers dos_sectors; 1200d1c77156SBrian Somers } 1201d1c77156SBrian Somers } else { 1202d1c77156SBrian Somers partp->dp_start = str2sectors(command->args[2].arg_str); 12034be78ce3SMaxim Sobolev if (partp->dp_start == NO_DISK_SECTORS) 1204d1c77156SBrian Somers break; 1205d1c77156SBrian Somers } 1206d1c77156SBrian Somers } else 1207f46af505SJordan K. Hubbard partp->dp_start = command->args[2].arg_val; 1208d1c77156SBrian Somers 1209d1c77156SBrian Somers if (command->args[3].arg_str != NULL) { 1210d1c77156SBrian Somers if (strcmp(command->args[3].arg_str, "*") == 0) 1211d1c77156SBrian Somers partp->dp_size = ((disksecs / dos_cylsecs) * 1212d1c77156SBrian Somers dos_cylsecs) - partp->dp_start; 1213d1c77156SBrian Somers else { 1214d1c77156SBrian Somers partp->dp_size = str2sectors(command->args[3].arg_str); 12154be78ce3SMaxim Sobolev if (partp->dp_size == NO_DISK_SECTORS) 1216d1c77156SBrian Somers break; 1217d1c77156SBrian Somers } 1218d1c77156SBrian Somers prev_cyl_boundary = ((partp->dp_start + partp->dp_size) / 1219d1c77156SBrian Somers dos_cylsecs) * dos_cylsecs; 1220d1c77156SBrian Somers if (prev_cyl_boundary > partp->dp_start) 1221d1c77156SBrian Somers partp->dp_size = prev_cyl_boundary - partp->dp_start; 1222d1c77156SBrian Somers } else 1223f46af505SJordan K. Hubbard partp->dp_size = command->args[3].arg_val; 1224d1c77156SBrian Somers 1225f46af505SJordan K. Hubbard max_end = partp->dp_start + partp->dp_size; 1226f46af505SJordan K. Hubbard 1227041b8b00SPoul-Henning Kamp if (partp->dp_typ == 0) { 1228f46af505SJordan K. Hubbard /* 1229f46af505SJordan K. Hubbard * Get out, the partition is marked as unused. 1230f46af505SJordan K. Hubbard */ 1231f46af505SJordan K. Hubbard /* 1232f46af505SJordan K. Hubbard * Insure that it's unused. 1233f46af505SJordan K. Hubbard */ 1234c4898ccbSLuigi Rizzo bzero(partp, sizeof(*partp)); 1235f46af505SJordan K. Hubbard status = 1; 1236f46af505SJordan K. Hubbard break; 1237f46af505SJordan K. Hubbard } 1238f46af505SJordan K. Hubbard 1239f46af505SJordan K. Hubbard /* 1240d64ada50SJens Schweikhardt * Adjust start upwards, if necessary, to fall on a head boundary. 1241f46af505SJordan K. Hubbard */ 1242041b8b00SPoul-Henning Kamp if (partp->dp_start % dos_sectors != 0) { 1243b594e0feSJohn Baldwin prev_head_boundary = partp->dp_start / dos_sectors * dos_sectors; 1244b594e0feSJohn Baldwin if (max_end < dos_sectors || 1245041b8b00SPoul-Henning Kamp prev_head_boundary > max_end - dos_sectors) { 1246f46af505SJordan K. Hubbard /* 1247f46af505SJordan K. Hubbard * Can't go past end of partition 1248f46af505SJordan K. Hubbard */ 1249d98b1668SPhilippe Charnier warnx( 1250d98b1668SPhilippe Charnier "ERROR line %d: unable to adjust start of partition %d to fall on\n\ 1251b594e0feSJohn Baldwin a head boundary", 1252d98b1668SPhilippe Charnier current_line_number, partition); 1253f46af505SJordan K. Hubbard break; 1254f46af505SJordan K. Hubbard } 1255d98b1668SPhilippe Charnier warnx( 1256b594e0feSJohn Baldwin "WARNING: adjusting start offset of partition %d\n\ 1257b594e0feSJohn Baldwin from %u to %u, to fall on a head boundary", 1258b594e0feSJohn Baldwin partition, (u_int)partp->dp_start, 1259b594e0feSJohn Baldwin (u_int)(prev_head_boundary + dos_sectors)); 1260b594e0feSJohn Baldwin partp->dp_start = prev_head_boundary + dos_sectors; 1261f46af505SJordan K. Hubbard } 1262f46af505SJordan K. Hubbard 1263f46af505SJordan K. Hubbard /* 1264f46af505SJordan K. Hubbard * Adjust size downwards, if necessary, to fall on a cylinder 1265f46af505SJordan K. Hubbard * boundary. 1266f46af505SJordan K. Hubbard */ 1267b594e0feSJohn Baldwin prev_cyl_boundary = 1268f46af505SJordan K. Hubbard ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs; 1269b594e0feSJohn Baldwin if (prev_cyl_boundary > partp->dp_start) 1270b594e0feSJohn Baldwin adj_size = prev_cyl_boundary - partp->dp_start; 1271041b8b00SPoul-Henning Kamp else { 1272b594e0feSJohn Baldwin warnx( 1273b594e0feSJohn Baldwin "ERROR: could not adjust partition to start on a head boundary\n\ 1274b594e0feSJohn Baldwin and end on a cylinder boundary."); 1275b594e0feSJohn Baldwin return (0); 1276b594e0feSJohn Baldwin } 1277041b8b00SPoul-Henning Kamp if (adj_size != partp->dp_size) { 1278d98b1668SPhilippe Charnier warnx( 1279b594e0feSJohn Baldwin "WARNING: adjusting size of partition %d from %u to %u\n\ 1280b594e0feSJohn Baldwin to end on a cylinder boundary", 1281b594e0feSJohn Baldwin partition, (u_int)partp->dp_size, (u_int)adj_size); 1282f46af505SJordan K. Hubbard partp->dp_size = adj_size; 1283f46af505SJordan K. Hubbard } 1284041b8b00SPoul-Henning Kamp if (partp->dp_size == 0) { 128563692187SIan Dowse warnx("ERROR line %d: size of partition %d is zero", 1286d98b1668SPhilippe Charnier current_line_number, partition); 1287f46af505SJordan K. Hubbard break; 1288f46af505SJordan K. Hubbard } 1289f46af505SJordan K. Hubbard 129063692187SIan Dowse dos(partp); 1291f46af505SJordan K. Hubbard status = 1; 1292f46af505SJordan K. Hubbard break; 1293f46af505SJordan K. Hubbard } 1294f46af505SJordan K. Hubbard return (status); 1295f46af505SJordan K. Hubbard } 1296f46af505SJordan K. Hubbard 1297f46af505SJordan K. Hubbard 1298f46af505SJordan K. Hubbard static int 1299041b8b00SPoul-Henning Kamp process_active(CMD *command) 1300f46af505SJordan K. Hubbard { 1301f46af505SJordan K. Hubbard int status = 0, partition, i; 1302f46af505SJordan K. Hubbard struct dos_partition *partp; 1303f46af505SJordan K. Hubbard 1304041b8b00SPoul-Henning Kamp while (1) { 1305f46af505SJordan K. Hubbard active_processed = 1; 1306041b8b00SPoul-Henning Kamp if (command->n_args != 1) { 1307d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of active args", 1308d98b1668SPhilippe Charnier current_line_number); 1309f46af505SJordan K. Hubbard status = 0; 1310f46af505SJordan K. Hubbard break; 1311f46af505SJordan K. Hubbard } 1312f46af505SJordan K. Hubbard partition = command->args[0].arg_val; 1313041b8b00SPoul-Henning Kamp if (partition < 1 || partition > 4) { 1314d98b1668SPhilippe Charnier warnx("ERROR line %d: invalid partition number %d", 1315d98b1668SPhilippe Charnier current_line_number, partition); 1316f46af505SJordan K. Hubbard break; 1317f46af505SJordan K. Hubbard } 1318f46af505SJordan K. Hubbard /* 1319f46af505SJordan K. Hubbard * Reset active partition 1320f46af505SJordan K. Hubbard */ 1321c4898ccbSLuigi Rizzo partp = mboot.parts; 1322f46af505SJordan K. Hubbard for (i = 0; i < NDOSPART; i++) 1323f46af505SJordan K. Hubbard partp[i].dp_flag = 0; 13244ddd60b9SBrian Somers partp[partition-1].dp_flag = ACTIVE; 1325f46af505SJordan K. Hubbard 1326f46af505SJordan K. Hubbard status = 1; 1327f46af505SJordan K. Hubbard break; 1328f46af505SJordan K. Hubbard } 1329f46af505SJordan K. Hubbard return (status); 1330f46af505SJordan K. Hubbard } 1331f46af505SJordan K. Hubbard 1332f46af505SJordan K. Hubbard 1333f46af505SJordan K. Hubbard static int 1334041b8b00SPoul-Henning Kamp process_line(char *line) 1335f46af505SJordan K. Hubbard { 1336f46af505SJordan K. Hubbard CMD command; 1337f46af505SJordan K. Hubbard int status = 1; 1338f46af505SJordan K. Hubbard 1339041b8b00SPoul-Henning Kamp while (1) { 1340f46af505SJordan K. Hubbard parse_config_line(line, &command); 1341041b8b00SPoul-Henning Kamp switch (command.cmd) { 1342f46af505SJordan K. Hubbard case 0: 1343f46af505SJordan K. Hubbard /* 1344f46af505SJordan K. Hubbard * Comment or blank line 1345f46af505SJordan K. Hubbard */ 1346f46af505SJordan K. Hubbard break; 1347f46af505SJordan K. Hubbard case 'g': 1348f46af505SJordan K. Hubbard /* 1349f46af505SJordan K. Hubbard * Set geometry 1350f46af505SJordan K. Hubbard */ 1351f46af505SJordan K. Hubbard status = process_geometry(&command); 1352f46af505SJordan K. Hubbard break; 1353f46af505SJordan K. Hubbard case 'p': 1354f46af505SJordan K. Hubbard status = process_partition(&command); 1355f46af505SJordan K. Hubbard break; 1356f46af505SJordan K. Hubbard case 'a': 1357f46af505SJordan K. Hubbard status = process_active(&command); 1358f46af505SJordan K. Hubbard break; 1359f46af505SJordan K. Hubbard default: 1360f46af505SJordan K. Hubbard status = 0; 1361f46af505SJordan K. Hubbard break; 1362f46af505SJordan K. Hubbard } 1363f46af505SJordan K. Hubbard break; 1364f46af505SJordan K. Hubbard } 1365f46af505SJordan K. Hubbard return (status); 1366f46af505SJordan K. Hubbard } 1367f46af505SJordan K. Hubbard 1368f46af505SJordan K. Hubbard 1369f46af505SJordan K. Hubbard static int 1370041b8b00SPoul-Henning Kamp read_config(char *config_file) 1371f46af505SJordan K. Hubbard { 1372f46af505SJordan K. Hubbard FILE *fp = NULL; 1373f46af505SJordan K. Hubbard int status = 1; 1374f46af505SJordan K. Hubbard char buf[1010]; 1375f46af505SJordan K. Hubbard 1376041b8b00SPoul-Henning Kamp while (1) { 1377041b8b00SPoul-Henning Kamp if (strcmp(config_file, "-") != 0) { 1378f46af505SJordan K. Hubbard /* 1379f46af505SJordan K. Hubbard * We're not reading from stdin 1380f46af505SJordan K. Hubbard */ 1381041b8b00SPoul-Henning Kamp if ((fp = fopen(config_file, "r")) == NULL) { 1382f46af505SJordan K. Hubbard status = 0; 1383f46af505SJordan K. Hubbard break; 1384f46af505SJordan K. Hubbard } 1385041b8b00SPoul-Henning Kamp } else { 1386f46af505SJordan K. Hubbard fp = stdin; 1387f46af505SJordan K. Hubbard } 1388f46af505SJordan K. Hubbard current_line_number = 0; 1389041b8b00SPoul-Henning Kamp while (!feof(fp)) { 1390f46af505SJordan K. Hubbard if (fgets(buf, sizeof(buf), fp) == NULL) 1391f46af505SJordan K. Hubbard break; 1392f46af505SJordan K. Hubbard ++current_line_number; 1393f46af505SJordan K. Hubbard status = process_line(buf); 1394f46af505SJordan K. Hubbard if (status == 0) 1395f46af505SJordan K. Hubbard break; 1396f46af505SJordan K. Hubbard } 1397f46af505SJordan K. Hubbard break; 1398f46af505SJordan K. Hubbard } 1399041b8b00SPoul-Henning Kamp if (fp) { 1400f46af505SJordan K. Hubbard /* 1401f46af505SJordan K. Hubbard * It doesn't matter if we're reading from stdin, as we've reached EOF 1402f46af505SJordan K. Hubbard */ 1403f46af505SJordan K. Hubbard fclose(fp); 1404f46af505SJordan K. Hubbard } 1405f46af505SJordan K. Hubbard return (status); 1406f46af505SJordan K. Hubbard } 1407f46af505SJordan K. Hubbard 1408f46af505SJordan K. Hubbard 1409f46af505SJordan K. Hubbard static void 1410f46af505SJordan K. Hubbard reset_boot(void) 1411f46af505SJordan K. Hubbard { 1412f46af505SJordan K. Hubbard int i; 1413f46af505SJordan K. Hubbard struct dos_partition *partp; 1414f46af505SJordan K. Hubbard 1415f46af505SJordan K. Hubbard init_boot(); 1416041b8b00SPoul-Henning Kamp for (i = 0; i < 4; ++i) { 1417c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 1418c4898ccbSLuigi Rizzo bzero(partp, sizeof(*partp)); 1419f46af505SJordan K. Hubbard } 1420f46af505SJordan K. Hubbard } 1421b594e0feSJohn Baldwin 1422b594e0feSJohn Baldwin static int 1423041b8b00SPoul-Henning Kamp sanitize_partition(struct dos_partition *partp) 1424b594e0feSJohn Baldwin { 1425b594e0feSJohn Baldwin u_int32_t prev_head_boundary, prev_cyl_boundary; 142663692187SIan Dowse u_int32_t max_end, size, start; 1427b594e0feSJohn Baldwin 142863692187SIan Dowse start = partp->dp_start; 142963692187SIan Dowse size = partp->dp_size; 143063692187SIan Dowse max_end = start + size; 143163692187SIan Dowse /* Only allow a zero size if the partition is being marked unused. */ 143263692187SIan Dowse if (size == 0) { 143363692187SIan Dowse if (start == 0 && partp->dp_typ == 0) 143463692187SIan Dowse return (1); 143563692187SIan Dowse warnx("ERROR: size of partition is zero"); 143663692187SIan Dowse return (0); 143763692187SIan Dowse } 143863692187SIan Dowse /* Return if no adjustment is necessary. */ 143963692187SIan Dowse if (start % dos_sectors == 0 && (start + size) % dos_sectors == 0) 144063692187SIan Dowse return (1); 144163692187SIan Dowse 14427fb7df31SDag-Erling Smørgrav if (start == 0) { 14437fb7df31SDag-Erling Smørgrav warnx("WARNING: partition overlaps with partition table"); 14447fb7df31SDag-Erling Smørgrav if (ok("Correct this automatically?")) 14457fb7df31SDag-Erling Smørgrav start = dos_sectors; 14467fb7df31SDag-Erling Smørgrav } 144763692187SIan Dowse if (start % dos_sectors != 0) 144863692187SIan Dowse warnx("WARNING: partition does not start on a head boundary"); 144963692187SIan Dowse if ((start +size) % dos_sectors != 0) 145063692187SIan Dowse warnx("WARNING: partition does not end on a cylinder boundary"); 145163692187SIan Dowse warnx("WARNING: this may confuse the BIOS or some operating systems"); 145263692187SIan Dowse if (!ok("Correct this automatically?")) 145363692187SIan Dowse return (1); 1454b594e0feSJohn Baldwin 1455b594e0feSJohn Baldwin /* 1456d64ada50SJens Schweikhardt * Adjust start upwards, if necessary, to fall on a head boundary. 1457b594e0feSJohn Baldwin */ 145863692187SIan Dowse if (start % dos_sectors != 0) { 145963692187SIan Dowse prev_head_boundary = start / dos_sectors * dos_sectors; 1460b594e0feSJohn Baldwin if (max_end < dos_sectors || 146163692187SIan Dowse prev_head_boundary >= max_end - dos_sectors) { 1462b594e0feSJohn Baldwin /* 1463b594e0feSJohn Baldwin * Can't go past end of partition 1464b594e0feSJohn Baldwin */ 1465b594e0feSJohn Baldwin warnx( 1466b594e0feSJohn Baldwin "ERROR: unable to adjust start of partition to fall on a head boundary"); 1467b594e0feSJohn Baldwin return (0); 1468b594e0feSJohn Baldwin } 146963692187SIan Dowse start = prev_head_boundary + dos_sectors; 1470b594e0feSJohn Baldwin } 1471b594e0feSJohn Baldwin 1472b594e0feSJohn Baldwin /* 1473b594e0feSJohn Baldwin * Adjust size downwards, if necessary, to fall on a cylinder 1474b594e0feSJohn Baldwin * boundary. 1475b594e0feSJohn Baldwin */ 147663692187SIan Dowse prev_cyl_boundary = ((start + size) / dos_cylsecs) * dos_cylsecs; 147763692187SIan Dowse if (prev_cyl_boundary > start) 147863692187SIan Dowse size = prev_cyl_boundary - start; 147963692187SIan Dowse else { 1480b594e0feSJohn Baldwin warnx("ERROR: could not adjust partition to start on a head boundary\n\ 1481b594e0feSJohn Baldwin and end on a cylinder boundary."); 1482b594e0feSJohn Baldwin return (0); 1483b594e0feSJohn Baldwin } 148463692187SIan Dowse 148563692187SIan Dowse /* Finally, commit any changes to partp and return. */ 148663692187SIan Dowse if (start != partp->dp_start) { 148763692187SIan Dowse warnx("WARNING: adjusting start offset of partition to %u", 148863692187SIan Dowse (u_int)start); 148963692187SIan Dowse partp->dp_start = start; 1490b594e0feSJohn Baldwin } 149163692187SIan Dowse if (size != partp->dp_size) { 149263692187SIan Dowse warnx("WARNING: adjusting size of partition to %u", (u_int)size); 149363692187SIan Dowse partp->dp_size = size; 1494b594e0feSJohn Baldwin } 1495b594e0feSJohn Baldwin 1496b594e0feSJohn Baldwin return (1); 1497b594e0feSJohn Baldwin } 1498df77f711SJoerg Wunsch 1499df77f711SJoerg Wunsch /* 1500df77f711SJoerg Wunsch * Try figuring out the root device's canonical disk name. 1501df77f711SJoerg Wunsch * The following choices are considered: 1502df77f711SJoerg Wunsch * /dev/ad0s1a => /dev/ad0 1503df77f711SJoerg Wunsch * /dev/da0a => /dev/da0 1504df77f711SJoerg Wunsch * /dev/vinum/root => /dev/vinum/root 15051dc7e010SBrian Somers * A ".eli" part is removed if it exists (see geli(8)). 15066a5ffa06SBrian Somers * A ".journal" ending is removed if it exists (see gjournal(8)). 1507df77f711SJoerg Wunsch */ 1508df77f711SJoerg Wunsch static char * 1509df77f711SJoerg Wunsch get_rootdisk(void) 1510df77f711SJoerg Wunsch { 1511df77f711SJoerg Wunsch struct statfs rootfs; 1512df77f711SJoerg Wunsch regex_t re; 1513df77f711SJoerg Wunsch #define NMATCHES 2 1514df77f711SJoerg Wunsch regmatch_t rm[NMATCHES]; 15151dc7e010SBrian Somers char dev[PATH_MAX], *s; 1516df77f711SJoerg Wunsch int rv; 1517df77f711SJoerg Wunsch 1518df77f711SJoerg Wunsch if (statfs("/", &rootfs) == -1) 1519df77f711SJoerg Wunsch err(1, "statfs(\"/\")"); 1520df77f711SJoerg Wunsch 15216a5ffa06SBrian Somers if ((rv = regcomp(&re, "^(/dev/[a-z/]+[0-9]*)([sp][0-9]+)?[a-h]?(\\.journal)?$", 1522df77f711SJoerg Wunsch REG_EXTENDED)) != 0) 1523df77f711SJoerg Wunsch errx(1, "regcomp() failed (%d)", rv); 15241dc7e010SBrian Somers strlcpy(dev, rootfs.f_mntfromname, sizeof (dev)); 15251dc7e010SBrian Somers if ((s = strstr(dev, ".eli")) != NULL) 15261dc7e010SBrian Somers memmove(s, s+4, strlen(s + 4) + 1); 15271dc7e010SBrian Somers 15281dc7e010SBrian Somers if ((rv = regexec(&re, dev, NMATCHES, rm, 0)) != 0) 1529df77f711SJoerg Wunsch errx(1, 1530df77f711SJoerg Wunsch "mounted root fs resource doesn't match expectations (regexec returned %d)", 1531df77f711SJoerg Wunsch rv); 1532df77f711SJoerg Wunsch if ((s = malloc(rm[1].rm_eo - rm[1].rm_so + 1)) == NULL) 1533df77f711SJoerg Wunsch errx(1, "out of memory"); 1534df77f711SJoerg Wunsch memcpy(s, rootfs.f_mntfromname + rm[1].rm_so, 1535df77f711SJoerg Wunsch rm[1].rm_eo - rm[1].rm_so); 1536df77f711SJoerg Wunsch s[rm[1].rm_eo - rm[1].rm_so] = 0; 1537df77f711SJoerg Wunsch 1538df77f711SJoerg Wunsch return s; 1539df77f711SJoerg Wunsch } 1540