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> 283f8ba8b5SPoul-Henning Kamp #include <sys/disk.h> 295b81b6b3SRodney W. Grimes #include <sys/disklabel.h> 303bb24c35SPoul-Henning Kamp #include <sys/diskmbr.h> 311a03d6d5SPoul-Henning Kamp #include <sys/endian.h> 32df77f711SJoerg Wunsch #include <sys/param.h> 335b81b6b3SRodney W. Grimes #include <sys/stat.h> 34df77f711SJoerg Wunsch #include <sys/mount.h> 35d98b1668SPhilippe Charnier #include <ctype.h> 365b81b6b3SRodney W. Grimes #include <fcntl.h> 37d98b1668SPhilippe Charnier #include <err.h> 38d98b1668SPhilippe Charnier #include <errno.h> 39de78c288SPoul-Henning Kamp #include <libgeom.h> 40df77f711SJoerg Wunsch #include <paths.h> 41df77f711SJoerg Wunsch #include <regex.h> 42689fee87SBruce Evans #include <stdint.h> 43d98b1668SPhilippe Charnier #include <stdio.h> 44d98b1668SPhilippe Charnier #include <stdlib.h> 45d98b1668SPhilippe Charnier #include <string.h> 464be1e61bSAlexander Langer #include <unistd.h> 475b81b6b3SRodney W. Grimes 48ac8e5d02SConrad Meyer #include "fdisk_mbr_enc.h" 49ac8e5d02SConrad Meyer 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 70554e6a75SRodney W. Grimes #define MAX_SEC_SIZE 65536 /* maximum sector size that is supported */ 717cb29d33SSøren Schmidt #define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 72041b8b00SPoul-Henning Kamp static int secsize = 0; /* the sensed sector size */ 735b81b6b3SRodney W. Grimes 74041b8b00SPoul-Henning Kamp static char *disk; 75e3038c6eSJoerg Wunsch 76c69a7a71SJuli Mallett static int cyls, sectors, heads, cylsecs; 77c69a7a71SJuli Mallett static u_int32_t disksecs; 785b81b6b3SRodney W. Grimes 79041b8b00SPoul-Henning Kamp struct mboot { 8085c2cf30SJohn Baldwin unsigned char *bootinst; /* boot code */ 8185c2cf30SJohn Baldwin off_t bootinst_size; 821a03d6d5SPoul-Henning Kamp struct dos_partition parts[NDOSPART]; 835b81b6b3SRodney W. Grimes }; 84041b8b00SPoul-Henning Kamp 85041b8b00SPoul-Henning Kamp static struct mboot mboot; 86de78c288SPoul-Henning Kamp static int fd; 87f353c761SPoul-Henning Kamp 885b81b6b3SRodney W. Grimes #define ACTIVE 0x80 895b81b6b3SRodney W. Grimes 90041b8b00SPoul-Henning Kamp static uint dos_cyls; 91041b8b00SPoul-Henning Kamp static uint dos_heads; 92041b8b00SPoul-Henning Kamp static uint dos_sectors; 93041b8b00SPoul-Henning Kamp static uint dos_cylsecs; 945b81b6b3SRodney W. Grimes 955b81b6b3SRodney W. Grimes #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 965b81b6b3SRodney W. Grimes #define DOSCYL(c) (c & 0xff) 975b81b6b3SRodney W. Grimes 98f46af505SJordan K. Hubbard #define MAX_ARGS 10 99f46af505SJordan K. Hubbard 100f46af505SJordan K. Hubbard static int current_line_number; 101f46af505SJordan K. Hubbard 102f46af505SJordan K. Hubbard static int geom_processed = 0; 103f46af505SJordan K. Hubbard static int part_processed = 0; 104f46af505SJordan K. Hubbard static int active_processed = 0; 105f46af505SJordan K. Hubbard 106f46af505SJordan K. Hubbard typedef struct cmd { 107f46af505SJordan K. Hubbard char cmd; 108f46af505SJordan K. Hubbard int n_args; 109f46af505SJordan K. Hubbard struct arg { 110f46af505SJordan K. Hubbard char argtype; 111f9373bbdSRyan Stone unsigned long arg_val; 112d1c77156SBrian Somers char * arg_str; 113f46af505SJordan K. Hubbard } args[MAX_ARGS]; 114f46af505SJordan K. Hubbard } CMD; 115f46af505SJordan K. Hubbard 11626721a89SRobert Nordier static int B_flag = 0; /* replace boot code */ 11710b0ee93SWarner Losh static int I_flag = 0; /* use entire disk for FreeBSD */ 1185b81b6b3SRodney W. Grimes static int a_flag = 0; /* set active partition */ 11926721a89SRobert Nordier static char *b_flag = NULL; /* path to boot code */ 1205b81b6b3SRodney W. Grimes static int i_flag = 0; /* replace partition data */ 121a61d9186SDavid E. O'Brien static int q_flag = 0; /* Be quiet */ 1225b81b6b3SRodney W. Grimes static int u_flag = 0; /* update partition data */ 12310b0ee93SWarner Losh static int s_flag = 0; /* Print a summary and exit */ 12405a213f1STom Rhodes static int t_flag = 0; /* test only */ 125f46af505SJordan K. Hubbard static char *f_flag = NULL; /* Read config info from file */ 126f46af505SJordan K. Hubbard static int v_flag = 0; /* Be verbose */ 1277914c60fSMaxim Konovalov static int print_config_flag = 0; 1285b81b6b3SRodney W. Grimes 12922fccf5cSLuigi Rizzo /* 13022fccf5cSLuigi Rizzo * A list of partition types, probably outdated. 13122fccf5cSLuigi Rizzo */ 13222fccf5cSLuigi Rizzo static const char *const part_types[256] = { 13322fccf5cSLuigi Rizzo [0x00] = "unused", 13422fccf5cSLuigi Rizzo [0x01] = "Primary DOS with 12 bit FAT", 13522fccf5cSLuigi Rizzo [0x02] = "XENIX / file system", 13622fccf5cSLuigi Rizzo [0x03] = "XENIX /usr file system", 13722fccf5cSLuigi Rizzo [0x04] = "Primary DOS with 16 bit FAT (< 32MB)", 13822fccf5cSLuigi Rizzo [0x05] = "Extended DOS", 13931fade05SLuigi Rizzo [0x06] = "Primary DOS, 16 bit FAT (>= 32MB)", 14031fade05SLuigi Rizzo [0x07] = "NTFS, OS/2 HPFS, QNX-2 (16 bit) or Advanced UNIX", 14122fccf5cSLuigi Rizzo [0x08] = "AIX file system or SplitDrive", 14222fccf5cSLuigi Rizzo [0x09] = "AIX boot partition or Coherent", 14322fccf5cSLuigi Rizzo [0x0A] = "OS/2 Boot Manager, OPUS or Coherent swap", 14422fccf5cSLuigi Rizzo [0x0B] = "DOS or Windows 95 with 32 bit FAT", 14522fccf5cSLuigi Rizzo [0x0C] = "DOS or Windows 95 with 32 bit FAT (LBA)", 14622fccf5cSLuigi Rizzo [0x0E] = "Primary 'big' DOS (>= 32MB, LBA)", 14722fccf5cSLuigi Rizzo [0x0F] = "Extended DOS (LBA)", 14822fccf5cSLuigi Rizzo [0x10] = "OPUS", 14922fccf5cSLuigi Rizzo [0x11] = "OS/2 BM: hidden DOS with 12-bit FAT", 15022fccf5cSLuigi Rizzo [0x12] = "Compaq diagnostics", 15122fccf5cSLuigi Rizzo [0x14] = "OS/2 BM: hidden DOS with 16-bit FAT (< 32MB)", 15222fccf5cSLuigi Rizzo [0x16] = "OS/2 BM: hidden DOS with 16-bit FAT (>= 32MB)", 15322fccf5cSLuigi Rizzo [0x17] = "OS/2 BM: hidden IFS (e.g. HPFS)", 15422fccf5cSLuigi Rizzo [0x18] = "AST Windows swapfile", 15531fade05SLuigi Rizzo [0x1b] = "ASUS Recovery partition (NTFS)", 15622fccf5cSLuigi Rizzo [0x24] = "NEC DOS", 15722fccf5cSLuigi Rizzo [0x3C] = "PartitionMagic recovery", 15822fccf5cSLuigi Rizzo [0x39] = "plan9", 15922fccf5cSLuigi Rizzo [0x40] = "VENIX 286", 16022fccf5cSLuigi Rizzo [0x41] = "Linux/MINIX (sharing disk with DRDOS)", 16122fccf5cSLuigi Rizzo [0x42] = "SFS or Linux swap (sharing disk with DRDOS)", 16222fccf5cSLuigi Rizzo [0x43] = "Linux native (sharing disk with DRDOS)", 16322fccf5cSLuigi Rizzo [0x4D] = "QNX 4.2 Primary", 16422fccf5cSLuigi Rizzo [0x4E] = "QNX 4.2 Secondary", 16522fccf5cSLuigi Rizzo [0x4F] = "QNX 4.2 Tertiary", 16622fccf5cSLuigi Rizzo [0x50] = "DM (disk manager)", 16722fccf5cSLuigi Rizzo [0x51] = "DM6 Aux1 (or Novell)", 16822fccf5cSLuigi Rizzo [0x52] = "CP/M or Microport SysV/AT", 16922fccf5cSLuigi Rizzo [0x53] = "DM6 Aux3", 17022fccf5cSLuigi Rizzo [0x54] = "DM6", 17122fccf5cSLuigi Rizzo [0x55] = "EZ-Drive (disk manager)", 17222fccf5cSLuigi Rizzo [0x56] = "Golden Bow (disk manager)", 17322fccf5cSLuigi Rizzo [0x5c] = "Priam Edisk (disk manager)", /* according to S. Widlake */ 17422fccf5cSLuigi Rizzo [0x61] = "SpeedStor", 17522fccf5cSLuigi Rizzo [0x63] = "System V/386 (such as ISC UNIX), GNU HURD or Mach", 17622fccf5cSLuigi Rizzo [0x64] = "Novell Netware/286 2.xx", 17722fccf5cSLuigi Rizzo [0x65] = "Novell Netware/386 3.xx", 178276b25f1SConrad Meyer [0x6C] = "DragonFlyBSD", 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", 221f933af5dSDmitry Morozovsky [0xFB] = "VMware VMFS", 22222fccf5cSLuigi Rizzo [0xFE] = "SpeedStor >1024 cyl. or LANstep", 22322fccf5cSLuigi Rizzo [0xFF] = "Xenix bad blocks table", 2245b81b6b3SRodney W. Grimes }; 2255b81b6b3SRodney W. Grimes 22622fccf5cSLuigi Rizzo static const char * 22722fccf5cSLuigi Rizzo get_type(int t) 22822fccf5cSLuigi Rizzo { 22922fccf5cSLuigi Rizzo const char *ret; 23022fccf5cSLuigi Rizzo 23122fccf5cSLuigi Rizzo ret = (t >= 0 && t <= 255) ? part_types[t] : NULL; 23222fccf5cSLuigi Rizzo return ret ? ret : "unknown"; 23322fccf5cSLuigi Rizzo } 23422fccf5cSLuigi Rizzo 23522fccf5cSLuigi Rizzo 236fd1ca22aSAndrey V. Elsukov static int geom_class_available(const char *); 237fbcb16efSLuigi Rizzo static void print_s0(void); 23840905b6eSLuigi Rizzo static void print_part(const struct dos_partition *); 2394be1e61bSAlexander Langer static void init_sector0(unsigned long start); 240f46af505SJordan K. Hubbard static void init_boot(void); 2414be1e61bSAlexander Langer static void change_part(int i); 242041b8b00SPoul-Henning Kamp static void print_params(void); 2434be1e61bSAlexander Langer static void change_active(int which); 244041b8b00SPoul-Henning Kamp static void change_code(void); 245041b8b00SPoul-Henning Kamp static void get_params_to_use(void); 246df77f711SJoerg Wunsch static char *get_rootdisk(void); 24763692187SIan Dowse static void dos(struct dos_partition *partp); 248041b8b00SPoul-Henning Kamp static int open_disk(int flag); 2494be1e61bSAlexander Langer static ssize_t read_disk(off_t sector, void *buf); 250de78c288SPoul-Henning Kamp static int write_disk(off_t sector, void *buf); 251041b8b00SPoul-Henning Kamp static int get_params(void); 252041b8b00SPoul-Henning Kamp static int read_s0(void); 253041b8b00SPoul-Henning Kamp static int write_s0(void); 254041b8b00SPoul-Henning Kamp static int ok(const char *str); 2554be78ce3SMaxim Sobolev static int decimal(const char *str, int *num, int deflt, uint32_t maxval); 256f46af505SJordan K. Hubbard static int read_config(char *config_file); 257f46af505SJordan K. Hubbard static void reset_boot(void); 258b594e0feSJohn Baldwin static int sanitize_partition(struct dos_partition *); 25965f3be91SAlfonso Gregory static void usage(void) __dead2; 2604be1e61bSAlexander Langer 2614be1e61bSAlexander Langer int 2624be1e61bSAlexander Langer main(int argc, char *argv[]) 2635b81b6b3SRodney W. Grimes { 26426721a89SRobert Nordier int c, i; 265041b8b00SPoul-Henning Kamp int partition = -1; 266041b8b00SPoul-Henning Kamp struct dos_partition *partp; 2675b81b6b3SRodney W. Grimes 26886e66321SEd Maste fprintf(stderr, 26986e66321SEd Maste "WARNING: fdisk is deprecated and is not available in FreeBSD 15 or later.\n" 27086e66321SEd Maste "Please use gpart instead.\n\n"); 27186e66321SEd Maste 272a61d9186SDavid E. O'Brien while ((c = getopt(argc, argv, "BIab:f:ipqstuv1234")) != -1) 27326721a89SRobert Nordier switch (c) { 27426721a89SRobert Nordier case 'B': 27526721a89SRobert Nordier B_flag = 1; 2764ddd60b9SBrian Somers break; 27710b0ee93SWarner Losh case 'I': 27810b0ee93SWarner Losh I_flag = 1; 27910b0ee93SWarner Losh break; 2805b81b6b3SRodney W. Grimes case 'a': 2815b81b6b3SRodney W. Grimes a_flag = 1; 2825b81b6b3SRodney W. Grimes break; 28312d910e9SRobert Nordier case 'b': 28426721a89SRobert Nordier b_flag = optarg; 28512d910e9SRobert Nordier break; 286f46af505SJordan K. Hubbard case 'f': 28726721a89SRobert Nordier f_flag = optarg; 288f46af505SJordan K. Hubbard break; 2895b81b6b3SRodney W. Grimes case 'i': 2905b81b6b3SRodney W. Grimes i_flag = 1; 2915b81b6b3SRodney W. Grimes break; 2927914c60fSMaxim Konovalov case 'p': 2937914c60fSMaxim Konovalov print_config_flag = 1; 2947914c60fSMaxim Konovalov break; 295a61d9186SDavid E. O'Brien case 'q': 296a61d9186SDavid E. O'Brien q_flag = 1; 297a61d9186SDavid E. O'Brien break; 29810b0ee93SWarner Losh case 's': 29910b0ee93SWarner Losh s_flag = 1; 30010b0ee93SWarner Losh break; 301f46af505SJordan K. Hubbard case 't': 302f46af505SJordan K. Hubbard t_flag = 1; 30326721a89SRobert Nordier break; 30426721a89SRobert Nordier case 'u': 30526721a89SRobert Nordier u_flag = 1; 30626721a89SRobert Nordier break; 307f46af505SJordan K. Hubbard case 'v': 308f46af505SJordan K. Hubbard v_flag = 1; 309f46af505SJordan K. Hubbard break; 31026721a89SRobert Nordier case '1': 31126721a89SRobert Nordier case '2': 31226721a89SRobert Nordier case '3': 31326721a89SRobert Nordier case '4': 31426721a89SRobert Nordier partition = c - '0'; 31526721a89SRobert Nordier break; 3165b81b6b3SRodney W. Grimes default: 317d98b1668SPhilippe Charnier usage(); 3185b81b6b3SRodney W. Grimes } 31926721a89SRobert Nordier if (f_flag || i_flag) 32026721a89SRobert Nordier u_flag = 1; 32126721a89SRobert Nordier if (t_flag) 32226721a89SRobert Nordier v_flag = 1; 32326721a89SRobert Nordier argc -= optind; 32426721a89SRobert Nordier argv += optind; 3255b81b6b3SRodney W. Grimes 326df77f711SJoerg Wunsch if (argc == 0) { 327df77f711SJoerg Wunsch disk = get_rootdisk(); 328df77f711SJoerg Wunsch } else { 329b31e5ae2SUlf Lilleengen disk = g_device_path(argv[0]); 330041b8b00SPoul-Henning Kamp if (disk == NULL) 331c4898ccbSLuigi Rizzo err(1, "unable to get correct path for %s", argv[0]); 332df77f711SJoerg Wunsch } 3335b81b6b3SRodney W. Grimes if (open_disk(u_flag) < 0) 334d98b1668SPhilippe Charnier err(1, "cannot open disk %s", disk); 33585c2cf30SJohn Baldwin 33685c2cf30SJohn Baldwin /* (abu)use mboot.bootinst to probe for the sector size */ 33785c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(MAX_SEC_SIZE)) == NULL) 33885c2cf30SJohn Baldwin err(1, "cannot allocate buffer to determine disk sector size"); 339aee85526SSimon L. B. Nielsen if (read_disk(0, mboot.bootinst) == -1) 340aee85526SSimon L. B. Nielsen errx(1, "could not detect sector size"); 341a12de062SJohn Baldwin free(mboot.bootinst); 342a12de062SJohn Baldwin mboot.bootinst = NULL; 34385c2cf30SJohn Baldwin 3447914c60fSMaxim Konovalov if (print_config_flag) { 3457914c60fSMaxim Konovalov if (read_s0()) 3467914c60fSMaxim Konovalov err(1, "read_s0"); 3477914c60fSMaxim Konovalov 3487914c60fSMaxim Konovalov printf("# %s\n", disk); 3497914c60fSMaxim Konovalov printf("g c%d h%d s%d\n", dos_cyls, dos_heads, dos_sectors); 3507914c60fSMaxim Konovalov 3517914c60fSMaxim Konovalov for (i = 0; i < NDOSPART; i++) { 352c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 3537914c60fSMaxim Konovalov 3547914c60fSMaxim Konovalov if (partp->dp_start == 0 && partp->dp_size == 0) 3557914c60fSMaxim Konovalov continue; 3567914c60fSMaxim Konovalov 3577914c60fSMaxim Konovalov printf("p %d 0x%02x %lu %lu\n", i + 1, partp->dp_typ, 3587914c60fSMaxim Konovalov (u_long)partp->dp_start, (u_long)partp->dp_size); 3597914c60fSMaxim Konovalov 3607914c60fSMaxim Konovalov /* Fill flags for the partition. */ 3617914c60fSMaxim Konovalov if (partp->dp_flag & 0x80) 3627914c60fSMaxim Konovalov printf("a %d\n", i + 1); 3637914c60fSMaxim Konovalov } 3647914c60fSMaxim Konovalov exit(0); 3657914c60fSMaxim Konovalov } 366041b8b00SPoul-Henning Kamp if (s_flag) { 36710b0ee93SWarner Losh if (read_s0()) 36810b0ee93SWarner Losh err(1, "read_s0"); 36910b0ee93SWarner Losh printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, 37010b0ee93SWarner Losh dos_sectors); 37110b0ee93SWarner Losh printf("Part %11s %11s Type Flags\n", "Start", "Size"); 37210b0ee93SWarner Losh for (i = 0; i < NDOSPART; i++) { 373c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 37410b0ee93SWarner Losh if (partp->dp_start == 0 && partp->dp_size == 0) 37510b0ee93SWarner Losh continue; 37610b0ee93SWarner Losh printf("%4d: %11lu %11lu 0x%02x 0x%02x\n", i + 1, 37710b0ee93SWarner Losh (u_long) partp->dp_start, 37810b0ee93SWarner Losh (u_long) partp->dp_size, partp->dp_typ, 37910b0ee93SWarner Losh partp->dp_flag); 38010b0ee93SWarner Losh } 38110b0ee93SWarner Losh exit(0); 38210b0ee93SWarner Losh } 3835b81b6b3SRodney W. Grimes 3845b81b6b3SRodney W. Grimes printf("******* Working on device %s *******\n",disk); 385f46af505SJordan K. Hubbard 386041b8b00SPoul-Henning Kamp if (I_flag) { 3872af5769eSWarner Losh if (read_s0()) 3882af5769eSWarner Losh warnx("Ignoring bad existing MBR."); 389e6fb3ddeSPoul-Henning Kamp reset_boot(); 390c4898ccbSLuigi Rizzo partp = &mboot.parts[0]; 391e6fb3ddeSPoul-Henning Kamp partp->dp_typ = DOSPTYP_386BSD; 392e6fb3ddeSPoul-Henning Kamp partp->dp_flag = ACTIVE; 393e6fb3ddeSPoul-Henning Kamp partp->dp_start = dos_sectors; 394fbcfcbbcSPedro F. Giffuni partp->dp_size = rounddown(disksecs, dos_cylsecs) - 395b594e0feSJohn Baldwin dos_sectors; 39663692187SIan Dowse dos(partp); 397e6fb3ddeSPoul-Henning Kamp if (v_flag) 398fbcb16efSLuigi Rizzo print_s0(); 39905a213f1STom Rhodes if (!t_flag) 400e6fb3ddeSPoul-Henning Kamp write_s0(); 401e6fb3ddeSPoul-Henning Kamp exit(0); 402e6fb3ddeSPoul-Henning Kamp } 403041b8b00SPoul-Henning Kamp if (f_flag) { 404f46af505SJordan K. Hubbard if (read_s0() || i_flag) 405f46af505SJordan K. Hubbard reset_boot(); 406f46af505SJordan K. Hubbard if (!read_config(f_flag)) 407f46af505SJordan K. Hubbard exit(1); 408f46af505SJordan K. Hubbard if (v_flag) 409fbcb16efSLuigi Rizzo print_s0(); 410f46af505SJordan K. Hubbard if (!t_flag) 411f46af505SJordan K. Hubbard write_s0(); 412041b8b00SPoul-Henning Kamp } else { 4135b81b6b3SRodney W. Grimes if(u_flag) 4145b81b6b3SRodney W. Grimes get_params_to_use(); 4155b81b6b3SRodney W. Grimes else 4165b81b6b3SRodney W. Grimes print_params(); 4175b81b6b3SRodney W. Grimes 4182af5769eSWarner Losh if (read_s0()) { 4192af5769eSWarner Losh printf("Will replace existing bad MBR\n"); 420b594e0feSJohn Baldwin init_sector0(dos_sectors); 4212af5769eSWarner Losh } 4225b81b6b3SRodney W. Grimes 4237cb29d33SSøren Schmidt printf("Media sector size is %d\n", secsize); 4245b81b6b3SRodney W. Grimes printf("Warning: BIOS sector numbering starts with sector 1\n"); 4255b81b6b3SRodney W. Grimes printf("Information from DOS bootblock is:\n"); 4265b81b6b3SRodney W. Grimes if (partition == -1) 4274ddd60b9SBrian Somers for (i = 1; i <= NDOSPART; i++) 4285b81b6b3SRodney W. Grimes change_part(i); 4295b81b6b3SRodney W. Grimes else 4305b81b6b3SRodney W. Grimes change_part(partition); 4315b81b6b3SRodney W. Grimes 4325b81b6b3SRodney W. Grimes if (u_flag || a_flag) 4335b81b6b3SRodney W. Grimes change_active(partition); 4345b81b6b3SRodney W. Grimes 43526721a89SRobert Nordier if (B_flag) 43612d910e9SRobert Nordier change_code(); 43712d910e9SRobert Nordier 43826721a89SRobert Nordier if (u_flag || a_flag || B_flag) { 439041b8b00SPoul-Henning Kamp if (!t_flag) { 4405b81b6b3SRodney W. Grimes printf("\nWe haven't changed the partition table yet. "); 4415b81b6b3SRodney W. Grimes printf("This is your last chance.\n"); 442f46af505SJordan K. Hubbard } 443fbcb16efSLuigi Rizzo print_s0(); 444041b8b00SPoul-Henning Kamp if (!t_flag) { 4455b81b6b3SRodney W. Grimes if (ok("Should we write new partition table?")) 4465b81b6b3SRodney W. Grimes write_s0(); 447041b8b00SPoul-Henning Kamp } else { 448f46af505SJordan K. Hubbard printf("\n-t flag specified -- partition table not written.\n"); 449f46af505SJordan K. Hubbard } 450f46af505SJordan K. Hubbard } 451f46af505SJordan K. Hubbard } 4525b81b6b3SRodney W. Grimes 4535b81b6b3SRodney W. Grimes exit(0); 454d98b1668SPhilippe Charnier } 4555b81b6b3SRodney W. Grimes 456d98b1668SPhilippe Charnier static void 4570a04bb7aSJohn Baldwin usage(void) 458d98b1668SPhilippe Charnier { 45926721a89SRobert Nordier fprintf(stderr, "%s%s", 460a61d9186SDavid E. O'Brien "usage: fdisk [-BIaipqstu] [-b bootcode] [-1234] [disk]\n", 46126721a89SRobert Nordier " fdisk -f configfile [-itv] [disk]\n"); 462d98b1668SPhilippe Charnier exit(1); 4635b81b6b3SRodney W. Grimes } 4645b81b6b3SRodney W. Grimes 4654be1e61bSAlexander Langer static void 466fbcb16efSLuigi Rizzo print_s0(void) 4675b81b6b3SRodney W. Grimes { 4685b81b6b3SRodney W. Grimes int i; 4695b81b6b3SRodney W. Grimes 4705b81b6b3SRodney W. Grimes print_params(); 4715b81b6b3SRodney W. Grimes printf("Information from DOS bootblock is:\n"); 47240905b6eSLuigi Rizzo for (i = 1; i <= NDOSPART; i++) { 47340905b6eSLuigi Rizzo printf("%d: ", i); 47440905b6eSLuigi Rizzo print_part(&mboot.parts[i - 1]); 47540905b6eSLuigi Rizzo } 4765b81b6b3SRodney W. Grimes } 4775b81b6b3SRodney W. Grimes 478041b8b00SPoul-Henning Kamp static struct dos_partition mtpart; 4795b81b6b3SRodney W. Grimes 4804be1e61bSAlexander Langer static void 48140905b6eSLuigi Rizzo print_part(const struct dos_partition *partp) 4825b81b6b3SRodney W. Grimes { 483637fe2f7SJustin T. Gibbs u_int64_t part_mb; 4845b81b6b3SRodney W. Grimes 4855b81b6b3SRodney W. Grimes if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 4865b81b6b3SRodney W. Grimes printf("<UNUSED>\n"); 4875b81b6b3SRodney W. Grimes return; 4885b81b6b3SRodney W. Grimes } 489637fe2f7SJustin T. Gibbs /* 490637fe2f7SJustin T. Gibbs * Be careful not to overflow. 491637fe2f7SJustin T. Gibbs */ 492637fe2f7SJustin T. Gibbs part_mb = partp->dp_size; 493637fe2f7SJustin T. Gibbs part_mb *= secsize; 494637fe2f7SJustin T. Gibbs part_mb /= (1024 * 1024); 495978d3bfeSJosef Karthauser printf("sysid %d (%#04x),(%s)\n", partp->dp_typ, partp->dp_typ, 496978d3bfeSJosef Karthauser get_type(partp->dp_typ)); 497689fee87SBruce Evans printf(" start %lu, size %lu (%ju Meg), flag %x%s\n", 498ba198492SBruce Evans (u_long)partp->dp_start, 499ba198492SBruce Evans (u_long)partp->dp_size, 500689fee87SBruce Evans (uintmax_t)part_mb, 501680426beSDavid E. O'Brien partp->dp_flag, 502680426beSDavid E. O'Brien partp->dp_flag == ACTIVE ? " (active)" : ""); 5036580291bSDavid E. O'Brien printf("\tbeg: cyl %d/ head %d/ sector %d;\n\tend: cyl %d/ head %d/ sector %d\n" 5045b81b6b3SRodney W. Grimes ,DPCYL(partp->dp_scyl, partp->dp_ssect) 5055b81b6b3SRodney W. Grimes ,partp->dp_shd 5066580291bSDavid E. O'Brien ,DPSECT(partp->dp_ssect) 5075b81b6b3SRodney W. Grimes ,DPCYL(partp->dp_ecyl, partp->dp_esect) 5086580291bSDavid E. O'Brien ,partp->dp_ehd 5096580291bSDavid E. O'Brien ,DPSECT(partp->dp_esect)); 5105b81b6b3SRodney W. Grimes } 5115b81b6b3SRodney W. Grimes 512f46af505SJordan K. Hubbard 513f46af505SJordan K. Hubbard static void 514f46af505SJordan K. Hubbard init_boot(void) 515f46af505SJordan K. Hubbard { 51626721a89SRobert Nordier const char *fname; 517041b8b00SPoul-Henning Kamp int fdesc, n; 51885c2cf30SJohn Baldwin struct stat sb; 51926721a89SRobert Nordier 52026721a89SRobert Nordier fname = b_flag ? b_flag : "/boot/mbr"; 521041b8b00SPoul-Henning Kamp if ((fdesc = open(fname, O_RDONLY)) == -1 || 522041b8b00SPoul-Henning Kamp fstat(fdesc, &sb) == -1) 52385c2cf30SJohn Baldwin err(1, "%s", fname); 524469a1218SJohn-Mark Gurney if (sb.st_size == 0) 525469a1218SJohn-Mark Gurney errx(1, "%s is empty, must not be.", fname); 52685c2cf30SJohn Baldwin if ((mboot.bootinst_size = sb.st_size) % secsize != 0) 52785c2cf30SJohn Baldwin errx(1, "%s: length must be a multiple of sector size", fname); 5282b5ce8a9SAndrey A. Chernov if (mboot.bootinst != NULL) 5292b5ce8a9SAndrey A. Chernov free(mboot.bootinst); 53085c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(mboot.bootinst_size = sb.st_size)) == NULL) 53185c2cf30SJohn Baldwin errx(1, "%s: unable to allocate read buffer", fname); 532041b8b00SPoul-Henning Kamp if ((n = read(fdesc, mboot.bootinst, mboot.bootinst_size)) == -1 || 533041b8b00SPoul-Henning Kamp close(fdesc)) 53426721a89SRobert Nordier err(1, "%s", fname); 53585c2cf30SJohn Baldwin if (n != mboot.bootinst_size) 53685c2cf30SJohn Baldwin errx(1, "%s: short read", fname); 537f46af505SJordan K. Hubbard } 538f46af505SJordan K. Hubbard 539f46af505SJordan K. Hubbard 5404be1e61bSAlexander Langer static void 5414be1e61bSAlexander Langer init_sector0(unsigned long start) 5425b81b6b3SRodney W. Grimes { 543c4898ccbSLuigi Rizzo struct dos_partition *partp = &mboot.parts[0]; 5445b81b6b3SRodney W. Grimes 545f46af505SJordan K. Hubbard init_boot(); 5465b81b6b3SRodney W. Grimes 5475b81b6b3SRodney W. Grimes partp->dp_typ = DOSPTYP_386BSD; 5485b81b6b3SRodney W. Grimes partp->dp_flag = ACTIVE; 549fbcfcbbcSPedro F. Giffuni start = roundup(start, dos_sectors); 55085c2cf30SJohn Baldwin if(start == 0) 55185c2cf30SJohn Baldwin start = dos_sectors; 5525b81b6b3SRodney W. Grimes partp->dp_start = start; 553fbcfcbbcSPedro F. Giffuni partp->dp_size = rounddown(disksecs, dos_cylsecs) - start; 5545b81b6b3SRodney W. Grimes 55563692187SIan Dowse dos(partp); 5565b81b6b3SRodney W. Grimes } 5575b81b6b3SRodney W. Grimes 5584be1e61bSAlexander Langer static void 5594be1e61bSAlexander Langer change_part(int i) 5605b81b6b3SRodney W. Grimes { 561c4898ccbSLuigi Rizzo struct dos_partition *partp = &mboot.parts[i - 1]; 5625b81b6b3SRodney W. Grimes 5635b81b6b3SRodney W. Grimes printf("The data for partition %d is:\n", i); 56440905b6eSLuigi Rizzo print_part(partp); 5655b81b6b3SRodney W. Grimes 5665b81b6b3SRodney W. Grimes if (u_flag && ok("Do you want to change it?")) { 5675b81b6b3SRodney W. Grimes int tmp; 5685b81b6b3SRodney W. Grimes 5695b81b6b3SRodney W. Grimes if (i_flag) { 570c4898ccbSLuigi Rizzo bzero(partp, sizeof (*partp)); 571a67ed623SPoul-Henning Kamp if (i == 1) { 5725b81b6b3SRodney W. Grimes init_sector0(1); 573a67ed623SPoul-Henning Kamp printf("\nThe static data for the slice 1 has been reinitialized to:\n"); 57440905b6eSLuigi Rizzo print_part(partp); 5755b81b6b3SRodney W. Grimes } 5765b81b6b3SRodney W. Grimes } 5775b81b6b3SRodney W. Grimes 5785b81b6b3SRodney W. Grimes do { 5794be78ce3SMaxim Sobolev Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp, 255); 5804be78ce3SMaxim Sobolev Decimal("start", partp->dp_start, tmp, NO_DISK_SECTORS); 5814be78ce3SMaxim Sobolev Decimal("size", partp->dp_size, tmp, NO_DISK_SECTORS); 58263692187SIan Dowse if (!sanitize_partition(partp)) { 58363692187SIan Dowse warnx("ERROR: failed to adjust; setting sysid to 0"); 58463692187SIan Dowse partp->dp_typ = 0; 58563692187SIan Dowse } 5865b81b6b3SRodney W. Grimes 5874b3b45a7SJames Raynard if (ok("Explicitly specify beg/end address ?")) 5885b81b6b3SRodney W. Grimes { 5895b81b6b3SRodney W. Grimes int tsec,tcyl,thd; 5905b81b6b3SRodney W. Grimes tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 5915b81b6b3SRodney W. Grimes thd = partp->dp_shd; 5925b81b6b3SRodney W. Grimes tsec = DPSECT(partp->dp_ssect); 5934be78ce3SMaxim Sobolev Decimal("beginning cylinder", tcyl, tmp, NO_TRACK_CYLINDERS); 5944be78ce3SMaxim Sobolev Decimal("beginning head", thd, tmp, NO_TRACK_HEADS); 5954be78ce3SMaxim Sobolev Decimal("beginning sector", tsec, tmp, NO_TRACK_SECTORS); 5965b81b6b3SRodney W. Grimes partp->dp_scyl = DOSCYL(tcyl); 5975b81b6b3SRodney W. Grimes partp->dp_ssect = DOSSECT(tsec,tcyl); 5985b81b6b3SRodney W. Grimes partp->dp_shd = thd; 5995b81b6b3SRodney W. Grimes 6005b81b6b3SRodney W. Grimes tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 6015b81b6b3SRodney W. Grimes thd = partp->dp_ehd; 6025b81b6b3SRodney W. Grimes tsec = DPSECT(partp->dp_esect); 6034be78ce3SMaxim Sobolev Decimal("ending cylinder", tcyl, tmp, NO_TRACK_CYLINDERS); 6044be78ce3SMaxim Sobolev Decimal("ending head", thd, tmp, NO_TRACK_HEADS); 6054be78ce3SMaxim Sobolev Decimal("ending sector", tsec, tmp, NO_TRACK_SECTORS); 6065b81b6b3SRodney W. Grimes partp->dp_ecyl = DOSCYL(tcyl); 6075b81b6b3SRodney W. Grimes partp->dp_esect = DOSSECT(tsec,tcyl); 6085b81b6b3SRodney W. Grimes partp->dp_ehd = thd; 60963692187SIan Dowse } else 61063692187SIan Dowse dos(partp); 6115b81b6b3SRodney W. Grimes 61240905b6eSLuigi Rizzo print_part(partp); 6135b81b6b3SRodney W. Grimes } while (!ok("Are we happy with this entry?")); 6145b81b6b3SRodney W. Grimes } 6155b81b6b3SRodney W. Grimes } 6165b81b6b3SRodney W. Grimes 6174be1e61bSAlexander Langer static void 6180a04bb7aSJohn Baldwin print_params(void) 6195b81b6b3SRodney W. Grimes { 6205b81b6b3SRodney W. Grimes printf("parameters extracted from in-core disklabel are:\n"); 6215b81b6b3SRodney W. Grimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 6225b81b6b3SRodney W. Grimes ,cyls,heads,sectors,cylsecs); 6237fa181d4SYoshihiro Takahashi if (dos_cyls > 1023 || dos_heads > 255 || dos_sectors > 63) 6245b81b6b3SRodney W. Grimes printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 6255b81b6b3SRodney W. Grimes printf("parameters to be used for BIOS calculations are:\n"); 6265b81b6b3SRodney W. Grimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 6275b81b6b3SRodney W. Grimes ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 6285b81b6b3SRodney W. Grimes } 6295b81b6b3SRodney W. Grimes 6304be1e61bSAlexander Langer static void 6314be1e61bSAlexander Langer change_active(int which) 6325b81b6b3SRodney W. Grimes { 63363692187SIan Dowse struct dos_partition *partp = &mboot.parts[0]; 63463692187SIan Dowse int active, i, new, tmp; 6355b81b6b3SRodney W. Grimes 63663692187SIan Dowse active = -1; 63763692187SIan Dowse for (i = 0; i < NDOSPART; i++) { 63863692187SIan Dowse if ((partp[i].dp_flag & ACTIVE) == 0) 63963692187SIan Dowse continue; 64063692187SIan Dowse printf("Partition %d is marked active\n", i + 1); 64163692187SIan Dowse if (active == -1) 64263692187SIan Dowse active = i + 1; 64363692187SIan Dowse } 6445b81b6b3SRodney W. Grimes if (a_flag && which != -1) 6455b81b6b3SRodney W. Grimes active = which; 64663692187SIan Dowse else if (active == -1) 64763692187SIan Dowse active = 1; 64863692187SIan Dowse 6490b461cd7SBruce Evans if (!ok("Do you want to change the active partition?")) 6500b461cd7SBruce Evans return; 651680426beSDavid E. O'Brien setactive: 652680426beSDavid E. O'Brien do { 65363692187SIan Dowse new = active; 65468df7abeSMaxim Sobolev Decimal("active partition", new, tmp, 0); 65563692187SIan Dowse if (new < 1 || new > 4) { 656680426beSDavid E. O'Brien printf("Active partition number must be in range 1-4." 657680426beSDavid E. O'Brien " Try again.\n"); 658680426beSDavid E. O'Brien goto setactive; 659680426beSDavid E. O'Brien } 66063692187SIan Dowse active = new; 661680426beSDavid E. O'Brien } while (!ok("Are you happy with this choice")); 6625b81b6b3SRodney W. Grimes for (i = 0; i < NDOSPART; i++) 6635b81b6b3SRodney W. Grimes partp[i].dp_flag = 0; 6644ddd60b9SBrian Somers if (active > 0 && active <= NDOSPART) 6654ddd60b9SBrian Somers partp[active-1].dp_flag = ACTIVE; 6665b81b6b3SRodney W. Grimes } 6675b81b6b3SRodney W. Grimes 66812d910e9SRobert Nordier static void 6690a04bb7aSJohn Baldwin change_code(void) 67012d910e9SRobert Nordier { 67112d910e9SRobert Nordier if (ok("Do you want to change the boot code?")) 67212d910e9SRobert Nordier init_boot(); 67312d910e9SRobert Nordier } 67412d910e9SRobert Nordier 6754be1e61bSAlexander Langer void 6760a04bb7aSJohn Baldwin get_params_to_use(void) 6775b81b6b3SRodney W. Grimes { 6785b81b6b3SRodney W. Grimes int tmp; 6795b81b6b3SRodney W. Grimes print_params(); 6805b81b6b3SRodney W. Grimes if (ok("Do you want to change our idea of what BIOS thinks ?")) 6815b81b6b3SRodney W. Grimes { 6825b81b6b3SRodney W. Grimes do 6835b81b6b3SRodney W. Grimes { 68468df7abeSMaxim Sobolev Decimal("BIOS's idea of #cylinders", dos_cyls, tmp, 0); 68568df7abeSMaxim Sobolev Decimal("BIOS's idea of #heads", dos_heads, tmp, 0); 68668df7abeSMaxim Sobolev Decimal("BIOS's idea of #sectors", dos_sectors, tmp, 0); 6875b81b6b3SRodney W. Grimes dos_cylsecs = dos_heads * dos_sectors; 6885b81b6b3SRodney W. Grimes print_params(); 6895b81b6b3SRodney W. Grimes } 6905b81b6b3SRodney W. Grimes while(!ok("Are you happy with this choice")); 6915b81b6b3SRodney W. Grimes } 6925b81b6b3SRodney W. Grimes } 6935b81b6b3SRodney W. Grimes 694f46af505SJordan K. Hubbard 6955b81b6b3SRodney W. Grimes /***********************************************\ 6965b81b6b3SRodney W. Grimes * Change real numbers into strange dos numbers * 6975b81b6b3SRodney W. Grimes \***********************************************/ 6984be1e61bSAlexander Langer static void 699041b8b00SPoul-Henning Kamp dos(struct dos_partition *partp) 7005b81b6b3SRodney W. Grimes { 70163692187SIan Dowse int cy, sec; 70263692187SIan Dowse u_int32_t end; 7035b81b6b3SRodney W. Grimes 704881c9063SIan Dowse if (partp->dp_typ == 0 && partp->dp_start == 0 && partp->dp_size == 0) { 705881c9063SIan Dowse memcpy(partp, &mtpart, sizeof(*partp)); 7060b461cd7SBruce Evans return; 7070b461cd7SBruce Evans } 7080b461cd7SBruce Evans 70963692187SIan Dowse /* Start c/h/s. */ 71063692187SIan Dowse partp->dp_shd = partp->dp_start % dos_cylsecs / dos_sectors; 71163692187SIan Dowse cy = partp->dp_start / dos_cylsecs; 71263692187SIan Dowse sec = partp->dp_start % dos_sectors + 1; 71363692187SIan Dowse partp->dp_scyl = DOSCYL(cy); 71463692187SIan Dowse partp->dp_ssect = DOSSECT(sec, cy); 7155b81b6b3SRodney W. Grimes 71663692187SIan Dowse /* End c/h/s. */ 71763692187SIan Dowse end = partp->dp_start + partp->dp_size - 1; 71863692187SIan Dowse partp->dp_ehd = end % dos_cylsecs / dos_sectors; 71963692187SIan Dowse cy = end / dos_cylsecs; 72063692187SIan Dowse sec = end % dos_sectors + 1; 72163692187SIan Dowse partp->dp_ecyl = DOSCYL(cy); 72263692187SIan Dowse partp->dp_esect = DOSSECT(sec, cy); 7235b81b6b3SRodney W. Grimes } 7245b81b6b3SRodney W. Grimes 7254be1e61bSAlexander Langer static int 726041b8b00SPoul-Henning Kamp open_disk(int flag) 7275b81b6b3SRodney W. Grimes { 728de78c288SPoul-Henning Kamp int rwmode; 7295b81b6b3SRodney W. Grimes 730b31e5ae2SUlf Lilleengen /* Write mode if one of these flags are set. */ 731b31e5ae2SUlf Lilleengen rwmode = (a_flag || I_flag || B_flag || flag); 732b31e5ae2SUlf Lilleengen fd = g_open(disk, rwmode); 733b31e5ae2SUlf Lilleengen /* If the mode fails, try read-only if we didn't. */ 734b31e5ae2SUlf Lilleengen if (fd == -1 && errno == EPERM && rwmode) 735b31e5ae2SUlf Lilleengen fd = g_open(disk, 0); 736f353c761SPoul-Henning Kamp if (fd == -1 && errno == ENXIO) 737e3038c6eSJoerg Wunsch return -2; 738f353c761SPoul-Henning Kamp if (fd == -1) { 739d98b1668SPhilippe Charnier warnx("can't open device %s", disk); 7405b81b6b3SRodney W. Grimes return -1; 7415b81b6b3SRodney W. Grimes } 742041b8b00SPoul-Henning Kamp if (get_params() == -1) { 743d98b1668SPhilippe Charnier warnx("can't get disk parameters on %s", disk); 7445b81b6b3SRodney W. Grimes return -1; 7455b81b6b3SRodney W. Grimes } 7465b81b6b3SRodney W. Grimes return fd; 7475b81b6b3SRodney W. Grimes } 7485b81b6b3SRodney W. Grimes 7494be1e61bSAlexander Langer static ssize_t 7504be1e61bSAlexander Langer read_disk(off_t sector, void *buf) 7515b81b6b3SRodney W. Grimes { 7527fa181d4SYoshihiro Takahashi 7535b81b6b3SRodney W. Grimes lseek(fd, (sector * 512), 0); 7547cb29d33SSøren Schmidt if (secsize == 0) 7557fa181d4SYoshihiro Takahashi for (secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; 7567fa181d4SYoshihiro Takahashi secsize *= 2) { 7577cb29d33SSøren Schmidt /* try the read */ 7587cb29d33SSøren Schmidt int size = read(fd, buf, secsize); 7597cb29d33SSøren Schmidt if (size == secsize) 7607cb29d33SSøren Schmidt /* it worked so return */ 7617cb29d33SSøren Schmidt return secsize; 7627cb29d33SSøren Schmidt } 7637cb29d33SSøren Schmidt else 7647cb29d33SSøren Schmidt return read(fd, buf, secsize); 7657cb29d33SSøren Schmidt 7667cb29d33SSøren Schmidt /* we failed to read at any of the sizes */ 7677cb29d33SSøren Schmidt return -1; 7685b81b6b3SRodney W. Grimes } 7695b81b6b3SRodney W. Grimes 770de78c288SPoul-Henning Kamp static int 771fd1ca22aSAndrey V. Elsukov geom_class_available(const char *name) 772fd1ca22aSAndrey V. Elsukov { 773fd1ca22aSAndrey V. Elsukov struct gclass *class; 774fd1ca22aSAndrey V. Elsukov struct gmesh mesh; 775fd1ca22aSAndrey V. Elsukov int error; 776fd1ca22aSAndrey V. Elsukov 777fd1ca22aSAndrey V. Elsukov error = geom_gettree(&mesh); 778fd1ca22aSAndrey V. Elsukov if (error != 0) 779fd1ca22aSAndrey V. Elsukov errc(1, error, "Cannot get GEOM tree"); 780fd1ca22aSAndrey V. Elsukov 781fd1ca22aSAndrey V. Elsukov LIST_FOREACH(class, &mesh.lg_class, lg_class) { 782fd1ca22aSAndrey V. Elsukov if (strcmp(class->lg_name, name) == 0) { 783fd1ca22aSAndrey V. Elsukov geom_deletetree(&mesh); 784fd1ca22aSAndrey V. Elsukov return (1); 785fd1ca22aSAndrey V. Elsukov } 786fd1ca22aSAndrey V. Elsukov } 787fd1ca22aSAndrey V. Elsukov 788fd1ca22aSAndrey V. Elsukov geom_deletetree(&mesh); 789fd1ca22aSAndrey V. Elsukov 790fd1ca22aSAndrey V. Elsukov return (0); 791fd1ca22aSAndrey V. Elsukov } 792fd1ca22aSAndrey V. Elsukov 793fd1ca22aSAndrey V. Elsukov static int 7944be1e61bSAlexander Langer write_disk(off_t sector, void *buf) 7955b81b6b3SRodney W. Grimes { 796ac8e5d02SConrad Meyer ssize_t wr; 797f353c761SPoul-Henning Kamp 79839e9a28fSAndrey V. Elsukov /* 79939e9a28fSAndrey V. Elsukov * Try to write MBR directly. This may help when disk 800fd1ca22aSAndrey V. Elsukov * is not in use. 801fd1ca22aSAndrey V. Elsukov * XXX: hardcoded sectorsize 802fd1ca22aSAndrey V. Elsukov */ 803ac8e5d02SConrad Meyer wr = pwrite(fd, buf, secsize, (sector * 512)); 804ac8e5d02SConrad Meyer if (wr == secsize) 805de78c288SPoul-Henning Kamp return (0); 806fd1ca22aSAndrey V. Elsukov 807fd1ca22aSAndrey V. Elsukov if (geom_class_available("PART") != 0) 808fd1ca22aSAndrey V. Elsukov warnx("Failed to write MBR. Try to use gpart(8)."); 809fd1ca22aSAndrey V. Elsukov else 810de78c288SPoul-Henning Kamp warnx("Failed to write sector zero"); 811de78c288SPoul-Henning Kamp return(EINVAL); 812f353c761SPoul-Henning Kamp } 8135b81b6b3SRodney W. Grimes 8144be1e61bSAlexander Langer static int 8150a04bb7aSJohn Baldwin get_params(void) 8165b81b6b3SRodney W. Grimes { 8173f8ba8b5SPoul-Henning Kamp int error; 8183f8ba8b5SPoul-Henning Kamp u_int u; 8193f8ba8b5SPoul-Henning Kamp off_t o; 8205b81b6b3SRodney W. Grimes 8217963fae6SPoul-Henning Kamp error = ioctl(fd, DIOCGFWSECTORS, &u); 8227963fae6SPoul-Henning Kamp if (error == 0) 8237963fae6SPoul-Henning Kamp sectors = dos_sectors = u; 824c0fdfdbaSPoul-Henning Kamp else 825c0fdfdbaSPoul-Henning Kamp sectors = dos_sectors = 63; 826c0fdfdbaSPoul-Henning Kamp 8277963fae6SPoul-Henning Kamp error = ioctl(fd, DIOCGFWHEADS, &u); 8287963fae6SPoul-Henning Kamp if (error == 0) 8297963fae6SPoul-Henning Kamp heads = dos_heads = u; 830c0fdfdbaSPoul-Henning Kamp else 831c0fdfdbaSPoul-Henning Kamp heads = dos_heads = 255; 8327963fae6SPoul-Henning Kamp 8335b81b6b3SRodney W. Grimes dos_cylsecs = cylsecs = heads * sectors; 8345b81b6b3SRodney W. Grimes disksecs = cyls * heads * sectors; 8355b81b6b3SRodney W. Grimes 836b31e5ae2SUlf Lilleengen u = g_sectorsize(fd); 837b31e5ae2SUlf Lilleengen if (u <= 0) 838b31e5ae2SUlf Lilleengen return (-1); 8397963fae6SPoul-Henning Kamp 840b31e5ae2SUlf Lilleengen o = g_mediasize(fd); 841b31e5ae2SUlf Lilleengen if (o < 0) 842b31e5ae2SUlf Lilleengen return (-1); 843c69a7a71SJuli Mallett if (o / u <= NO_DISK_SECTORS) 8447963fae6SPoul-Henning Kamp disksecs = o / u; 845c69a7a71SJuli Mallett else 846c69a7a71SJuli Mallett disksecs = NO_DISK_SECTORS; 8477963fae6SPoul-Henning Kamp cyls = dos_cyls = o / (u * dos_heads * dos_sectors); 8487963fae6SPoul-Henning Kamp 849c69a7a71SJuli Mallett return (0); 8505b81b6b3SRodney W. Grimes } 8515b81b6b3SRodney W. Grimes 8524be1e61bSAlexander Langer static int 8530a04bb7aSJohn Baldwin read_s0(void) 8545b81b6b3SRodney W. Grimes { 8551a03d6d5SPoul-Henning Kamp int i; 8561a03d6d5SPoul-Henning Kamp 85785c2cf30SJohn Baldwin mboot.bootinst_size = secsize; 8582b5ce8a9SAndrey A. Chernov if (mboot.bootinst != NULL) 8592b5ce8a9SAndrey A. Chernov free(mboot.bootinst); 86085c2cf30SJohn Baldwin if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) { 86185c2cf30SJohn Baldwin warnx("unable to allocate buffer to read fdisk " 86285c2cf30SJohn Baldwin "partition table"); 86385c2cf30SJohn Baldwin return -1; 86485c2cf30SJohn Baldwin } 86585c2cf30SJohn Baldwin if (read_disk(0, mboot.bootinst) == -1) { 866d98b1668SPhilippe Charnier warnx("can't read fdisk partition table"); 8675b81b6b3SRodney W. Grimes return -1; 8685b81b6b3SRodney W. Grimes } 8691a03d6d5SPoul-Henning Kamp if (le16dec(&mboot.bootinst[DOSMAGICOFFSET]) != DOSMAGIC) { 870d98b1668SPhilippe Charnier warnx("invalid fdisk partition table found"); 8715b81b6b3SRodney W. Grimes /* So should we initialize things */ 8725b81b6b3SRodney W. Grimes return -1; 8735b81b6b3SRodney W. Grimes } 8741a03d6d5SPoul-Henning Kamp for (i = 0; i < NDOSPART; i++) 8751a03d6d5SPoul-Henning Kamp dos_partition_dec( 8761a03d6d5SPoul-Henning Kamp &mboot.bootinst[DOSPARTOFF + i * DOSPARTSIZE], 8771a03d6d5SPoul-Henning Kamp &mboot.parts[i]); 8785b81b6b3SRodney W. Grimes return 0; 8795b81b6b3SRodney W. Grimes } 8805b81b6b3SRodney W. Grimes 8814be1e61bSAlexander Langer static int 8820a04bb7aSJohn Baldwin write_s0(void) 8835b81b6b3SRodney W. Grimes { 8841a03d6d5SPoul-Henning Kamp int sector, i; 88585c2cf30SJohn Baldwin 8865b81b6b3SRodney W. Grimes if (iotest) { 887fbcb16efSLuigi Rizzo print_s0(); 8885b81b6b3SRodney W. Grimes return 0; 8895b81b6b3SRodney W. Grimes } 8901a03d6d5SPoul-Henning Kamp for(i = 0; i < NDOSPART; i++) 8911a03d6d5SPoul-Henning Kamp dos_partition_enc(&mboot.bootinst[DOSPARTOFF + i * DOSPARTSIZE], 8921a03d6d5SPoul-Henning Kamp &mboot.parts[i]); 8931a03d6d5SPoul-Henning Kamp le16enc(&mboot.bootinst[DOSMAGICOFFSET], DOSMAGIC); 89485c2cf30SJohn Baldwin for(sector = 0; sector < mboot.bootinst_size / secsize; sector++) 89585c2cf30SJohn Baldwin if (write_disk(sector, 89685c2cf30SJohn Baldwin &mboot.bootinst[sector * secsize]) == -1) { 897e6fb3ddeSPoul-Henning Kamp warn("can't write fdisk partition table"); 8985b81b6b3SRodney W. Grimes return -1; 8995b81b6b3SRodney W. Grimes } 9004be1e61bSAlexander Langer return(0); 9015b81b6b3SRodney W. Grimes } 9025b81b6b3SRodney W. Grimes 9035b81b6b3SRodney W. Grimes 9044be1e61bSAlexander Langer static int 905041b8b00SPoul-Henning Kamp ok(const char *str) 9065b81b6b3SRodney W. Grimes { 9075b81b6b3SRodney W. Grimes printf("%s [n] ", str); 90863692187SIan Dowse fflush(stdout); 90963692187SIan Dowse if (fgets(lbuf, LBUF, stdin) == NULL) 91063692187SIan Dowse exit(1); 9115b81b6b3SRodney W. Grimes lbuf[strlen(lbuf)-1] = 0; 9125b81b6b3SRodney W. Grimes 9135b81b6b3SRodney W. Grimes if (*lbuf && 9145b81b6b3SRodney W. Grimes (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 9155b81b6b3SRodney W. Grimes !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 9165b81b6b3SRodney W. Grimes return 1; 9175b81b6b3SRodney W. Grimes else 9185b81b6b3SRodney W. Grimes return 0; 9195b81b6b3SRodney W. Grimes } 9205b81b6b3SRodney W. Grimes 9214be1e61bSAlexander Langer static int 9224be78ce3SMaxim Sobolev decimal(const char *str, int *num, int deflt, uint32_t maxval) 9235b81b6b3SRodney W. Grimes { 9241b100fd3SAndrey V. Elsukov long long acc; 92568df7abeSMaxim Sobolev int c; 9265b81b6b3SRodney W. Grimes char *cp; 9275b81b6b3SRodney W. Grimes 9285b81b6b3SRodney W. Grimes while (1) { 9291b100fd3SAndrey V. Elsukov acc = 0; 9305b81b6b3SRodney W. Grimes printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 93163692187SIan Dowse fflush(stdout); 93263692187SIan Dowse if (fgets(lbuf, LBUF, stdin) == NULL) 93363692187SIan Dowse exit(1); 9345b81b6b3SRodney W. Grimes lbuf[strlen(lbuf)-1] = 0; 9355b81b6b3SRodney W. Grimes 9365b81b6b3SRodney W. Grimes if (!*lbuf) 9375b81b6b3SRodney W. Grimes return 0; 9385b81b6b3SRodney W. Grimes 9395b81b6b3SRodney W. Grimes cp = lbuf; 9405b81b6b3SRodney W. Grimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 9415b81b6b3SRodney W. Grimes if (!c) 9425b81b6b3SRodney W. Grimes return 0; 9434be1e61bSAlexander Langer while ((c = *cp++)) { 94468df7abeSMaxim Sobolev if (c <= '9' && c >= '0') { 9456bfcd9c3SAndrey V. Elsukov if (acc <= maxval || maxval == 0) 9465b81b6b3SRodney W. Grimes acc = acc * 10 + c - '0'; 94768df7abeSMaxim Sobolev } else 9485b81b6b3SRodney W. Grimes break; 9495b81b6b3SRodney W. Grimes } 9505b81b6b3SRodney W. Grimes if (c == ' ' || c == '\t') 9515b81b6b3SRodney W. Grimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 9525b81b6b3SRodney W. Grimes if (!c) { 9534be78ce3SMaxim Sobolev if (maxval > 0 && acc > maxval) { 9544be78ce3SMaxim Sobolev acc = maxval; 9554be78ce3SMaxim Sobolev printf("%s exceeds maximum value allowed for " 9564be78ce3SMaxim Sobolev "this field. The value has been reduced " 9574be78ce3SMaxim Sobolev "to %lld\n", lbuf, acc); 95868df7abeSMaxim Sobolev } 9595b81b6b3SRodney W. Grimes *num = acc; 9605b81b6b3SRodney W. Grimes return 1; 9615b81b6b3SRodney W. Grimes } else 962680426beSDavid E. O'Brien printf("%s is an invalid decimal number. Try again.\n", 9635b81b6b3SRodney W. Grimes lbuf); 9645b81b6b3SRodney W. Grimes } 9655b81b6b3SRodney W. Grimes } 9665b81b6b3SRodney W. Grimes 967f46af505SJordan K. Hubbard 968f46af505SJordan K. Hubbard static void 969041b8b00SPoul-Henning Kamp parse_config_line(char *line, CMD *command) 970f46af505SJordan K. Hubbard { 971f46af505SJordan K. Hubbard char *cp, *end; 972f46af505SJordan K. Hubbard 973f46af505SJordan K. Hubbard cp = line; 974041b8b00SPoul-Henning Kamp while (1) { 975f46af505SJordan K. Hubbard memset(command, 0, sizeof(*command)); 976f46af505SJordan K. Hubbard 977f46af505SJordan K. Hubbard while (isspace(*cp)) ++cp; 978f46af505SJordan K. Hubbard if (*cp == '\0' || *cp == '#') 979f46af505SJordan K. Hubbard break; 980f46af505SJordan K. Hubbard command->cmd = *cp++; 981f46af505SJordan K. Hubbard 982f46af505SJordan K. Hubbard /* 983f46af505SJordan K. Hubbard * Parse args 984f46af505SJordan K. Hubbard */ 985041b8b00SPoul-Henning Kamp while (1) { 986f46af505SJordan K. Hubbard while (isspace(*cp)) ++cp; 987d1c77156SBrian Somers if (*cp == '\0') 988d1c77156SBrian Somers break; /* eol */ 989f46af505SJordan K. Hubbard if (*cp == '#') 990f46af505SJordan K. Hubbard break; /* found comment */ 991f46af505SJordan K. Hubbard if (isalpha(*cp)) 992f46af505SJordan K. Hubbard command->args[command->n_args].argtype = *cp++; 993f46af505SJordan K. Hubbard end = NULL; 994f9373bbdSRyan Stone command->args[command->n_args].arg_val = strtoul(cp, &end, 0); 995d1c77156SBrian Somers if (cp == end || (!isspace(*end) && *end != '\0')) { 996d1c77156SBrian Somers char ch; 997d1c77156SBrian Somers end = cp; 998d1c77156SBrian Somers while (!isspace(*end) && *end != '\0') ++end; 999d1c77156SBrian Somers ch = *end; *end = '\0'; 1000d1c77156SBrian Somers command->args[command->n_args].arg_str = strdup(cp); 1001d1c77156SBrian Somers *end = ch; 1002d1c77156SBrian Somers } else 1003d1c77156SBrian Somers command->args[command->n_args].arg_str = NULL; 1004f46af505SJordan K. Hubbard cp = end; 1005f46af505SJordan K. Hubbard command->n_args++; 1006f46af505SJordan K. Hubbard } 1007f46af505SJordan K. Hubbard break; 1008f46af505SJordan K. Hubbard } 1009f46af505SJordan K. Hubbard } 1010f46af505SJordan K. Hubbard 1011f46af505SJordan K. Hubbard 1012f46af505SJordan K. Hubbard static int 1013041b8b00SPoul-Henning Kamp process_geometry(CMD *command) 1014f46af505SJordan K. Hubbard { 1015f46af505SJordan K. Hubbard int status = 1, i; 1016f46af505SJordan K. Hubbard 1017041b8b00SPoul-Henning Kamp while (1) { 1018f46af505SJordan K. Hubbard geom_processed = 1; 1019041b8b00SPoul-Henning Kamp if (part_processed) { 1020d98b1668SPhilippe Charnier warnx( 1021d98b1668SPhilippe Charnier "ERROR line %d: the geometry specification line must occur before\n\ 1022d98b1668SPhilippe Charnier all partition specifications", 1023d98b1668SPhilippe Charnier current_line_number); 1024f46af505SJordan K. Hubbard status = 0; 1025f46af505SJordan K. Hubbard break; 1026f46af505SJordan K. Hubbard } 1027041b8b00SPoul-Henning Kamp if (command->n_args != 3) { 1028d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of geometry args", 1029d98b1668SPhilippe Charnier current_line_number); 1030f46af505SJordan K. Hubbard status = 0; 1031f46af505SJordan K. Hubbard break; 1032f46af505SJordan K. Hubbard } 1033041b8b00SPoul-Henning Kamp dos_cyls = 0; 1034041b8b00SPoul-Henning Kamp dos_heads = 0; 1035041b8b00SPoul-Henning Kamp dos_sectors = 0; 1036041b8b00SPoul-Henning Kamp for (i = 0; i < 3; ++i) { 1037041b8b00SPoul-Henning Kamp switch (command->args[i].argtype) { 1038f46af505SJordan K. Hubbard case 'c': 1039f46af505SJordan K. Hubbard dos_cyls = command->args[i].arg_val; 1040f46af505SJordan K. Hubbard break; 1041f46af505SJordan K. Hubbard case 'h': 1042f46af505SJordan K. Hubbard dos_heads = command->args[i].arg_val; 1043f46af505SJordan K. Hubbard break; 1044f46af505SJordan K. Hubbard case 's': 1045f46af505SJordan K. Hubbard dos_sectors = command->args[i].arg_val; 1046f46af505SJordan K. Hubbard break; 1047f46af505SJordan K. Hubbard default: 1048d98b1668SPhilippe Charnier warnx( 1049d98b1668SPhilippe Charnier "ERROR line %d: unknown geometry arg type: '%c' (0x%02x)", 1050d98b1668SPhilippe Charnier current_line_number, command->args[i].argtype, 1051f46af505SJordan K. Hubbard command->args[i].argtype); 1052f46af505SJordan K. Hubbard status = 0; 1053f46af505SJordan K. Hubbard break; 1054f46af505SJordan K. Hubbard } 1055f46af505SJordan K. Hubbard } 1056f46af505SJordan K. Hubbard if (status == 0) 1057f46af505SJordan K. Hubbard break; 1058f46af505SJordan K. Hubbard 1059f46af505SJordan K. Hubbard dos_cylsecs = dos_heads * dos_sectors; 1060f46af505SJordan K. Hubbard 1061f46af505SJordan K. Hubbard /* 1062f46af505SJordan K. Hubbard * Do sanity checks on parameter values 1063f46af505SJordan K. Hubbard */ 1064041b8b00SPoul-Henning Kamp if (dos_cyls == 0) { 1065d98b1668SPhilippe Charnier warnx("ERROR line %d: number of cylinders not specified", 1066d98b1668SPhilippe Charnier current_line_number); 1067f46af505SJordan K. Hubbard status = 0; 1068f46af505SJordan K. Hubbard } 1069041b8b00SPoul-Henning Kamp if (dos_cyls > 1024) { 1070d98b1668SPhilippe Charnier warnx( 1071d98b1668SPhilippe Charnier "WARNING line %d: number of cylinders (%d) may be out-of-range\n\ 1072f46af505SJordan K. Hubbard (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\ 1073d98b1668SPhilippe Charnier is dedicated to FreeBSD)", 1074d98b1668SPhilippe Charnier current_line_number, dos_cyls); 1075f46af505SJordan K. Hubbard } 1076f46af505SJordan K. Hubbard 1077041b8b00SPoul-Henning Kamp if (dos_heads == 0) { 1078d98b1668SPhilippe Charnier warnx("ERROR line %d: number of heads not specified", 1079d98b1668SPhilippe Charnier current_line_number); 1080f46af505SJordan K. Hubbard status = 0; 1081ea32a699SUlf Lilleengen } else if (dos_heads > 256) { 1082ea32a699SUlf Lilleengen warnx("ERROR line %d: number of heads must be within (1-256)", 1083d98b1668SPhilippe Charnier current_line_number); 1084f46af505SJordan K. Hubbard status = 0; 1085f46af505SJordan K. Hubbard } 1086f46af505SJordan K. Hubbard 1087041b8b00SPoul-Henning Kamp if (dos_sectors == 0) { 1088d98b1668SPhilippe Charnier warnx("ERROR line %d: number of sectors not specified", 1089d98b1668SPhilippe Charnier current_line_number); 1090f46af505SJordan K. Hubbard status = 0; 1091041b8b00SPoul-Henning Kamp } else if (dos_sectors > 63) { 1092d98b1668SPhilippe Charnier warnx("ERROR line %d: number of sectors must be within (1-63)", 1093d98b1668SPhilippe Charnier current_line_number); 1094f46af505SJordan K. Hubbard status = 0; 1095f46af505SJordan K. Hubbard } 1096f46af505SJordan K. Hubbard 1097f46af505SJordan K. Hubbard break; 1098f46af505SJordan K. Hubbard } 1099f46af505SJordan K. Hubbard return (status); 1100f46af505SJordan K. Hubbard } 1101f46af505SJordan K. Hubbard 1102d1c77156SBrian Somers static u_int32_t 1103d1c77156SBrian Somers str2sectors(const char *str) 1104d1c77156SBrian Somers { 1105d1c77156SBrian Somers char *end; 1106d1c77156SBrian Somers unsigned long val; 1107d1c77156SBrian Somers 1108d1c77156SBrian Somers val = strtoul(str, &end, 0); 1109d1c77156SBrian Somers if (str == end || *end == '\0') { 1110d1c77156SBrian Somers warnx("ERROR line %d: unexpected size: \'%s\'", 1111d1c77156SBrian Somers current_line_number, str); 11124be78ce3SMaxim Sobolev return NO_DISK_SECTORS; 1113d1c77156SBrian Somers } 1114d1c77156SBrian Somers 1115d1c77156SBrian Somers if (*end == 'K') 1116d1c77156SBrian Somers val *= 1024UL / secsize; 1117d1c77156SBrian Somers else if (*end == 'M') 1118d1c77156SBrian Somers val *= 1024UL * 1024UL / secsize; 1119d1c77156SBrian Somers else if (*end == 'G') 1120d1c77156SBrian Somers val *= 1024UL * 1024UL * 1024UL / secsize; 1121d1c77156SBrian Somers else { 1122d1c77156SBrian Somers warnx("ERROR line %d: unexpected modifier: %c " 1123d1c77156SBrian Somers "(not K/M/G)", current_line_number, *end); 11244be78ce3SMaxim Sobolev return NO_DISK_SECTORS; 1125d1c77156SBrian Somers } 1126d1c77156SBrian Somers 1127d1c77156SBrian Somers return val; 1128d1c77156SBrian Somers } 1129f46af505SJordan K. Hubbard 1130f46af505SJordan K. Hubbard static int 1131041b8b00SPoul-Henning Kamp process_partition(CMD *command) 1132f46af505SJordan K. Hubbard { 1133f46af505SJordan K. Hubbard int status = 0, partition; 1134b594e0feSJohn Baldwin u_int32_t prev_head_boundary, prev_cyl_boundary; 1135b594e0feSJohn Baldwin u_int32_t adj_size, max_end; 1136f46af505SJordan K. Hubbard struct dos_partition *partp; 1137f46af505SJordan K. Hubbard 1138041b8b00SPoul-Henning Kamp while (1) { 1139f46af505SJordan K. Hubbard part_processed = 1; 1140041b8b00SPoul-Henning Kamp if (command->n_args != 4) { 1141d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of partition args", 1142d98b1668SPhilippe Charnier current_line_number); 1143f46af505SJordan K. Hubbard break; 1144f46af505SJordan K. Hubbard } 1145f46af505SJordan K. Hubbard partition = command->args[0].arg_val; 1146041b8b00SPoul-Henning Kamp if (partition < 1 || partition > 4) { 1147d98b1668SPhilippe Charnier warnx("ERROR line %d: invalid partition number %d", 1148d98b1668SPhilippe Charnier current_line_number, partition); 1149f46af505SJordan K. Hubbard break; 1150f46af505SJordan K. Hubbard } 1151c4898ccbSLuigi Rizzo partp = &mboot.parts[partition - 1]; 1152c4898ccbSLuigi Rizzo bzero(partp, sizeof (*partp)); 1153f46af505SJordan K. Hubbard partp->dp_typ = command->args[1].arg_val; 1154d1c77156SBrian Somers if (command->args[2].arg_str != NULL) { 1155d1c77156SBrian Somers if (strcmp(command->args[2].arg_str, "*") == 0) { 1156d1c77156SBrian Somers int i; 1157d1c77156SBrian Somers partp->dp_start = dos_sectors; 1158d1c77156SBrian Somers for (i = 1; i < partition; i++) { 1159d1c77156SBrian Somers struct dos_partition *prev_partp; 1160d1c77156SBrian Somers prev_partp = ((struct dos_partition *) 1161d1c77156SBrian Somers &mboot.parts) + i - 1; 1162d1c77156SBrian Somers if (prev_partp->dp_typ != 0) 1163d1c77156SBrian Somers partp->dp_start = prev_partp->dp_start + 1164d1c77156SBrian Somers prev_partp->dp_size; 1165d1c77156SBrian Somers } 1166d1c77156SBrian Somers if (partp->dp_start % dos_sectors != 0) { 1167fbcfcbbcSPedro F. Giffuni prev_head_boundary = rounddown(partp->dp_start, 1168fbcfcbbcSPedro F. Giffuni dos_sectors); 1169d1c77156SBrian Somers partp->dp_start = prev_head_boundary + 1170d1c77156SBrian Somers dos_sectors; 1171d1c77156SBrian Somers } 1172d1c77156SBrian Somers } else { 1173d1c77156SBrian Somers partp->dp_start = str2sectors(command->args[2].arg_str); 11744be78ce3SMaxim Sobolev if (partp->dp_start == NO_DISK_SECTORS) 1175d1c77156SBrian Somers break; 1176d1c77156SBrian Somers } 1177d1c77156SBrian Somers } else 1178f46af505SJordan K. Hubbard partp->dp_start = command->args[2].arg_val; 1179d1c77156SBrian Somers 1180d1c77156SBrian Somers if (command->args[3].arg_str != NULL) { 1181d1c77156SBrian Somers if (strcmp(command->args[3].arg_str, "*") == 0) 1182fbcfcbbcSPedro F. Giffuni partp->dp_size = rounddown(disksecs, dos_cylsecs) - 1183fbcfcbbcSPedro F. Giffuni partp->dp_start; 1184d1c77156SBrian Somers else { 1185d1c77156SBrian Somers partp->dp_size = str2sectors(command->args[3].arg_str); 11864be78ce3SMaxim Sobolev if (partp->dp_size == NO_DISK_SECTORS) 1187d1c77156SBrian Somers break; 1188d1c77156SBrian Somers } 1189fbcfcbbcSPedro F. Giffuni prev_cyl_boundary = rounddown(partp->dp_start + partp->dp_size, 1190fbcfcbbcSPedro F. Giffuni dos_cylsecs); 1191d1c77156SBrian Somers if (prev_cyl_boundary > partp->dp_start) 1192d1c77156SBrian Somers partp->dp_size = prev_cyl_boundary - partp->dp_start; 1193d1c77156SBrian Somers } else 1194f46af505SJordan K. Hubbard partp->dp_size = command->args[3].arg_val; 1195d1c77156SBrian Somers 1196f46af505SJordan K. Hubbard max_end = partp->dp_start + partp->dp_size; 1197f46af505SJordan K. Hubbard 1198041b8b00SPoul-Henning Kamp if (partp->dp_typ == 0) { 1199f46af505SJordan K. Hubbard /* 1200f46af505SJordan K. Hubbard * Get out, the partition is marked as unused. 1201f46af505SJordan K. Hubbard */ 1202f46af505SJordan K. Hubbard /* 1203f46af505SJordan K. Hubbard * Insure that it's unused. 1204f46af505SJordan K. Hubbard */ 1205c4898ccbSLuigi Rizzo bzero(partp, sizeof(*partp)); 1206f46af505SJordan K. Hubbard status = 1; 1207f46af505SJordan K. Hubbard break; 1208f46af505SJordan K. Hubbard } 1209f46af505SJordan K. Hubbard 1210f46af505SJordan K. Hubbard /* 1211d64ada50SJens Schweikhardt * Adjust start upwards, if necessary, to fall on a head boundary. 1212f46af505SJordan K. Hubbard */ 1213041b8b00SPoul-Henning Kamp if (partp->dp_start % dos_sectors != 0) { 1214fbcfcbbcSPedro F. Giffuni prev_head_boundary = rounddown(partp->dp_start, dos_sectors); 1215b594e0feSJohn Baldwin if (max_end < dos_sectors || 1216041b8b00SPoul-Henning Kamp prev_head_boundary > max_end - dos_sectors) { 1217f46af505SJordan K. Hubbard /* 1218f46af505SJordan K. Hubbard * Can't go past end of partition 1219f46af505SJordan K. Hubbard */ 1220d98b1668SPhilippe Charnier warnx( 1221d98b1668SPhilippe Charnier "ERROR line %d: unable to adjust start of partition %d to fall on\n\ 1222b594e0feSJohn Baldwin a head boundary", 1223d98b1668SPhilippe Charnier current_line_number, partition); 1224f46af505SJordan K. Hubbard break; 1225f46af505SJordan K. Hubbard } 1226d98b1668SPhilippe Charnier warnx( 1227b594e0feSJohn Baldwin "WARNING: adjusting start offset of partition %d\n\ 1228b594e0feSJohn Baldwin from %u to %u, to fall on a head boundary", 1229b594e0feSJohn Baldwin partition, (u_int)partp->dp_start, 1230b594e0feSJohn Baldwin (u_int)(prev_head_boundary + dos_sectors)); 1231b594e0feSJohn Baldwin partp->dp_start = prev_head_boundary + dos_sectors; 1232f46af505SJordan K. Hubbard } 1233f46af505SJordan K. Hubbard 1234f46af505SJordan K. Hubbard /* 1235f46af505SJordan K. Hubbard * Adjust size downwards, if necessary, to fall on a cylinder 1236f46af505SJordan K. Hubbard * boundary. 1237f46af505SJordan K. Hubbard */ 1238fbcfcbbcSPedro F. Giffuni prev_cyl_boundary = rounddown(partp->dp_start + partp->dp_size, 1239fbcfcbbcSPedro F. Giffuni dos_cylsecs); 1240b594e0feSJohn Baldwin if (prev_cyl_boundary > partp->dp_start) 1241b594e0feSJohn Baldwin adj_size = prev_cyl_boundary - partp->dp_start; 1242041b8b00SPoul-Henning Kamp else { 1243b594e0feSJohn Baldwin warnx( 1244b594e0feSJohn Baldwin "ERROR: could not adjust partition to start on a head boundary\n\ 1245b594e0feSJohn Baldwin and end on a cylinder boundary."); 1246b594e0feSJohn Baldwin return (0); 1247b594e0feSJohn Baldwin } 1248041b8b00SPoul-Henning Kamp if (adj_size != partp->dp_size) { 1249d98b1668SPhilippe Charnier warnx( 1250b594e0feSJohn Baldwin "WARNING: adjusting size of partition %d from %u to %u\n\ 1251b594e0feSJohn Baldwin to end on a cylinder boundary", 1252b594e0feSJohn Baldwin partition, (u_int)partp->dp_size, (u_int)adj_size); 1253f46af505SJordan K. Hubbard partp->dp_size = adj_size; 1254f46af505SJordan K. Hubbard } 1255041b8b00SPoul-Henning Kamp if (partp->dp_size == 0) { 125663692187SIan Dowse warnx("ERROR line %d: size of partition %d is zero", 1257d98b1668SPhilippe Charnier current_line_number, partition); 1258f46af505SJordan K. Hubbard break; 1259f46af505SJordan K. Hubbard } 1260f46af505SJordan K. Hubbard 126163692187SIan Dowse dos(partp); 1262f46af505SJordan K. Hubbard status = 1; 1263f46af505SJordan K. Hubbard break; 1264f46af505SJordan K. Hubbard } 1265f46af505SJordan K. Hubbard return (status); 1266f46af505SJordan K. Hubbard } 1267f46af505SJordan K. Hubbard 1268f46af505SJordan K. Hubbard 1269f46af505SJordan K. Hubbard static int 1270041b8b00SPoul-Henning Kamp process_active(CMD *command) 1271f46af505SJordan K. Hubbard { 1272f46af505SJordan K. Hubbard int status = 0, partition, i; 1273f46af505SJordan K. Hubbard struct dos_partition *partp; 1274f46af505SJordan K. Hubbard 1275041b8b00SPoul-Henning Kamp while (1) { 1276f46af505SJordan K. Hubbard active_processed = 1; 1277041b8b00SPoul-Henning Kamp if (command->n_args != 1) { 1278d98b1668SPhilippe Charnier warnx("ERROR line %d: incorrect number of active args", 1279d98b1668SPhilippe Charnier current_line_number); 1280f46af505SJordan K. Hubbard status = 0; 1281f46af505SJordan K. Hubbard break; 1282f46af505SJordan K. Hubbard } 1283f46af505SJordan K. Hubbard partition = command->args[0].arg_val; 1284041b8b00SPoul-Henning Kamp if (partition < 1 || partition > 4) { 1285d98b1668SPhilippe Charnier warnx("ERROR line %d: invalid partition number %d", 1286d98b1668SPhilippe Charnier current_line_number, partition); 1287f46af505SJordan K. Hubbard break; 1288f46af505SJordan K. Hubbard } 1289f46af505SJordan K. Hubbard /* 1290f46af505SJordan K. Hubbard * Reset active partition 1291f46af505SJordan K. Hubbard */ 1292c4898ccbSLuigi Rizzo partp = mboot.parts; 1293f46af505SJordan K. Hubbard for (i = 0; i < NDOSPART; i++) 1294f46af505SJordan K. Hubbard partp[i].dp_flag = 0; 12954ddd60b9SBrian Somers partp[partition-1].dp_flag = ACTIVE; 1296f46af505SJordan K. Hubbard 1297f46af505SJordan K. Hubbard status = 1; 1298f46af505SJordan K. Hubbard break; 1299f46af505SJordan K. Hubbard } 1300f46af505SJordan K. Hubbard return (status); 1301f46af505SJordan K. Hubbard } 1302f46af505SJordan K. Hubbard 1303f46af505SJordan K. Hubbard 1304f46af505SJordan K. Hubbard static int 1305041b8b00SPoul-Henning Kamp process_line(char *line) 1306f46af505SJordan K. Hubbard { 1307f46af505SJordan K. Hubbard CMD command; 1308f46af505SJordan K. Hubbard int status = 1; 1309f46af505SJordan K. Hubbard 1310041b8b00SPoul-Henning Kamp while (1) { 1311f46af505SJordan K. Hubbard parse_config_line(line, &command); 1312041b8b00SPoul-Henning Kamp switch (command.cmd) { 1313f46af505SJordan K. Hubbard case 0: 1314f46af505SJordan K. Hubbard /* 1315f46af505SJordan K. Hubbard * Comment or blank line 1316f46af505SJordan K. Hubbard */ 1317f46af505SJordan K. Hubbard break; 1318f46af505SJordan K. Hubbard case 'g': 1319f46af505SJordan K. Hubbard /* 1320f46af505SJordan K. Hubbard * Set geometry 1321f46af505SJordan K. Hubbard */ 1322f46af505SJordan K. Hubbard status = process_geometry(&command); 1323f46af505SJordan K. Hubbard break; 1324f46af505SJordan K. Hubbard case 'p': 1325f46af505SJordan K. Hubbard status = process_partition(&command); 1326f46af505SJordan K. Hubbard break; 1327f46af505SJordan K. Hubbard case 'a': 1328f46af505SJordan K. Hubbard status = process_active(&command); 1329f46af505SJordan K. Hubbard break; 1330f46af505SJordan K. Hubbard default: 1331f46af505SJordan K. Hubbard status = 0; 1332f46af505SJordan K. Hubbard break; 1333f46af505SJordan K. Hubbard } 1334f46af505SJordan K. Hubbard break; 1335f46af505SJordan K. Hubbard } 1336f46af505SJordan K. Hubbard return (status); 1337f46af505SJordan K. Hubbard } 1338f46af505SJordan K. Hubbard 1339f46af505SJordan K. Hubbard 1340f46af505SJordan K. Hubbard static int 1341041b8b00SPoul-Henning Kamp read_config(char *config_file) 1342f46af505SJordan K. Hubbard { 1343f46af505SJordan K. Hubbard FILE *fp = NULL; 1344f46af505SJordan K. Hubbard int status = 1; 1345f46af505SJordan K. Hubbard char buf[1010]; 1346f46af505SJordan K. Hubbard 1347041b8b00SPoul-Henning Kamp while (1) { 1348041b8b00SPoul-Henning Kamp if (strcmp(config_file, "-") != 0) { 1349f46af505SJordan K. Hubbard /* 1350f46af505SJordan K. Hubbard * We're not reading from stdin 1351f46af505SJordan K. Hubbard */ 1352041b8b00SPoul-Henning Kamp if ((fp = fopen(config_file, "r")) == NULL) { 1353f46af505SJordan K. Hubbard status = 0; 1354f46af505SJordan K. Hubbard break; 1355f46af505SJordan K. Hubbard } 1356041b8b00SPoul-Henning Kamp } else { 1357f46af505SJordan K. Hubbard fp = stdin; 1358f46af505SJordan K. Hubbard } 1359f46af505SJordan K. Hubbard current_line_number = 0; 1360041b8b00SPoul-Henning Kamp while (!feof(fp)) { 1361f46af505SJordan K. Hubbard if (fgets(buf, sizeof(buf), fp) == NULL) 1362f46af505SJordan K. Hubbard break; 1363f46af505SJordan K. Hubbard ++current_line_number; 1364f46af505SJordan K. Hubbard status = process_line(buf); 1365f46af505SJordan K. Hubbard if (status == 0) 1366f46af505SJordan K. Hubbard break; 1367f46af505SJordan K. Hubbard } 1368f46af505SJordan K. Hubbard break; 1369f46af505SJordan K. Hubbard } 1370041b8b00SPoul-Henning Kamp if (fp) { 1371f46af505SJordan K. Hubbard /* 1372f46af505SJordan K. Hubbard * It doesn't matter if we're reading from stdin, as we've reached EOF 1373f46af505SJordan K. Hubbard */ 1374f46af505SJordan K. Hubbard fclose(fp); 1375f46af505SJordan K. Hubbard } 1376f46af505SJordan K. Hubbard return (status); 1377f46af505SJordan K. Hubbard } 1378f46af505SJordan K. Hubbard 1379f46af505SJordan K. Hubbard 1380f46af505SJordan K. Hubbard static void 1381f46af505SJordan K. Hubbard reset_boot(void) 1382f46af505SJordan K. Hubbard { 1383f46af505SJordan K. Hubbard int i; 1384f46af505SJordan K. Hubbard struct dos_partition *partp; 1385f46af505SJordan K. Hubbard 1386f46af505SJordan K. Hubbard init_boot(); 1387041b8b00SPoul-Henning Kamp for (i = 0; i < 4; ++i) { 1388c4898ccbSLuigi Rizzo partp = &mboot.parts[i]; 1389c4898ccbSLuigi Rizzo bzero(partp, sizeof(*partp)); 1390f46af505SJordan K. Hubbard } 1391f46af505SJordan K. Hubbard } 1392b594e0feSJohn Baldwin 1393b594e0feSJohn Baldwin static int 1394041b8b00SPoul-Henning Kamp sanitize_partition(struct dos_partition *partp) 1395b594e0feSJohn Baldwin { 1396b594e0feSJohn Baldwin u_int32_t prev_head_boundary, prev_cyl_boundary; 139763692187SIan Dowse u_int32_t max_end, size, start; 1398b594e0feSJohn Baldwin 139963692187SIan Dowse start = partp->dp_start; 140063692187SIan Dowse size = partp->dp_size; 140163692187SIan Dowse max_end = start + size; 140263692187SIan Dowse /* Only allow a zero size if the partition is being marked unused. */ 140363692187SIan Dowse if (size == 0) { 140463692187SIan Dowse if (start == 0 && partp->dp_typ == 0) 140563692187SIan Dowse return (1); 140663692187SIan Dowse warnx("ERROR: size of partition is zero"); 140763692187SIan Dowse return (0); 140863692187SIan Dowse } 140963692187SIan Dowse /* Return if no adjustment is necessary. */ 141063692187SIan Dowse if (start % dos_sectors == 0 && (start + size) % dos_sectors == 0) 141163692187SIan Dowse return (1); 141263692187SIan Dowse 14137fb7df31SDag-Erling Smørgrav if (start == 0) { 14147fb7df31SDag-Erling Smørgrav warnx("WARNING: partition overlaps with partition table"); 14157fb7df31SDag-Erling Smørgrav if (ok("Correct this automatically?")) 14167fb7df31SDag-Erling Smørgrav start = dos_sectors; 14177fb7df31SDag-Erling Smørgrav } 141863692187SIan Dowse if (start % dos_sectors != 0) 141963692187SIan Dowse warnx("WARNING: partition does not start on a head boundary"); 142063692187SIan Dowse if ((start +size) % dos_sectors != 0) 142163692187SIan Dowse warnx("WARNING: partition does not end on a cylinder boundary"); 142263692187SIan Dowse warnx("WARNING: this may confuse the BIOS or some operating systems"); 142363692187SIan Dowse if (!ok("Correct this automatically?")) 142463692187SIan Dowse return (1); 1425b594e0feSJohn Baldwin 1426b594e0feSJohn Baldwin /* 1427d64ada50SJens Schweikhardt * Adjust start upwards, if necessary, to fall on a head boundary. 1428b594e0feSJohn Baldwin */ 142963692187SIan Dowse if (start % dos_sectors != 0) { 1430fbcfcbbcSPedro F. Giffuni prev_head_boundary = rounddown(start, dos_sectors); 1431b594e0feSJohn Baldwin if (max_end < dos_sectors || 143263692187SIan Dowse prev_head_boundary >= max_end - dos_sectors) { 1433b594e0feSJohn Baldwin /* 1434b594e0feSJohn Baldwin * Can't go past end of partition 1435b594e0feSJohn Baldwin */ 1436b594e0feSJohn Baldwin warnx( 1437b594e0feSJohn Baldwin "ERROR: unable to adjust start of partition to fall on a head boundary"); 1438b594e0feSJohn Baldwin return (0); 1439b594e0feSJohn Baldwin } 144063692187SIan Dowse start = prev_head_boundary + dos_sectors; 1441b594e0feSJohn Baldwin } 1442b594e0feSJohn Baldwin 1443b594e0feSJohn Baldwin /* 1444b594e0feSJohn Baldwin * Adjust size downwards, if necessary, to fall on a cylinder 1445b594e0feSJohn Baldwin * boundary. 1446b594e0feSJohn Baldwin */ 1447fbcfcbbcSPedro F. Giffuni prev_cyl_boundary = rounddown(start + size, dos_cylsecs); 144863692187SIan Dowse if (prev_cyl_boundary > start) 144963692187SIan Dowse size = prev_cyl_boundary - start; 145063692187SIan Dowse else { 1451b594e0feSJohn Baldwin warnx("ERROR: could not adjust partition to start on a head boundary\n\ 1452b594e0feSJohn Baldwin and end on a cylinder boundary."); 1453b594e0feSJohn Baldwin return (0); 1454b594e0feSJohn Baldwin } 145563692187SIan Dowse 145663692187SIan Dowse /* Finally, commit any changes to partp and return. */ 145763692187SIan Dowse if (start != partp->dp_start) { 145863692187SIan Dowse warnx("WARNING: adjusting start offset of partition to %u", 145963692187SIan Dowse (u_int)start); 146063692187SIan Dowse partp->dp_start = start; 1461b594e0feSJohn Baldwin } 146263692187SIan Dowse if (size != partp->dp_size) { 146363692187SIan Dowse warnx("WARNING: adjusting size of partition to %u", (u_int)size); 146463692187SIan Dowse partp->dp_size = size; 1465b594e0feSJohn Baldwin } 1466b594e0feSJohn Baldwin 1467b594e0feSJohn Baldwin return (1); 1468b594e0feSJohn Baldwin } 1469df77f711SJoerg Wunsch 1470df77f711SJoerg Wunsch /* 1471df77f711SJoerg Wunsch * Try figuring out the root device's canonical disk name. 1472df77f711SJoerg Wunsch * The following choices are considered: 1473df77f711SJoerg Wunsch * /dev/ad0s1a => /dev/ad0 1474df77f711SJoerg Wunsch * /dev/da0a => /dev/da0 14751dc7e010SBrian Somers * A ".eli" part is removed if it exists (see geli(8)). 14766a5ffa06SBrian Somers * A ".journal" ending is removed if it exists (see gjournal(8)). 1477df77f711SJoerg Wunsch */ 1478df77f711SJoerg Wunsch static char * 1479df77f711SJoerg Wunsch get_rootdisk(void) 1480df77f711SJoerg Wunsch { 1481df77f711SJoerg Wunsch struct statfs rootfs; 1482df77f711SJoerg Wunsch regex_t re; 1483df77f711SJoerg Wunsch #define NMATCHES 2 1484df77f711SJoerg Wunsch regmatch_t rm[NMATCHES]; 14851dc7e010SBrian Somers char dev[PATH_MAX], *s; 1486df77f711SJoerg Wunsch int rv; 1487df77f711SJoerg Wunsch 1488df77f711SJoerg Wunsch if (statfs("/", &rootfs) == -1) 1489df77f711SJoerg Wunsch err(1, "statfs(\"/\")"); 1490df77f711SJoerg Wunsch 1491*2b12e667SJohn Baldwin if ((rv = regcomp(&re, "^(/dev/[a-z/]+[0-9]+)([sp][0-9]+)?[a-h]?(\\.journal)?$", 1492df77f711SJoerg Wunsch REG_EXTENDED)) != 0) 1493df77f711SJoerg Wunsch errx(1, "regcomp() failed (%d)", rv); 14941dc7e010SBrian Somers strlcpy(dev, rootfs.f_mntfromname, sizeof (dev)); 14951dc7e010SBrian Somers if ((s = strstr(dev, ".eli")) != NULL) 14961dc7e010SBrian Somers memmove(s, s+4, strlen(s + 4) + 1); 14971dc7e010SBrian Somers 14981dc7e010SBrian Somers if ((rv = regexec(&re, dev, NMATCHES, rm, 0)) != 0) 1499df77f711SJoerg Wunsch errx(1, 1500df77f711SJoerg Wunsch "mounted root fs resource doesn't match expectations (regexec returned %d)", 1501df77f711SJoerg Wunsch rv); 1502df77f711SJoerg Wunsch if ((s = malloc(rm[1].rm_eo - rm[1].rm_so + 1)) == NULL) 1503df77f711SJoerg Wunsch errx(1, "out of memory"); 1504df77f711SJoerg Wunsch memcpy(s, rootfs.f_mntfromname + rm[1].rm_so, 1505df77f711SJoerg Wunsch rm[1].rm_eo - rm[1].rm_so); 1506df77f711SJoerg Wunsch s[rm[1].rm_eo - rm[1].rm_so] = 0; 1507df77f711SJoerg Wunsch 1508df77f711SJoerg Wunsch return s; 1509df77f711SJoerg Wunsch } 1510