fdisk.c revision 37415
18871Srgrimes/* 24Srgrimes * Mach Operating System 34Srgrimes * Copyright (c) 1992 Carnegie Mellon University 44Srgrimes * All Rights Reserved. 58871Srgrimes * 64Srgrimes * Permission to use, copy, modify and distribute this software and its 74Srgrimes * documentation is hereby granted, provided that both the copyright 84Srgrimes * notice and this permission notice appear in all copies of the 94Srgrimes * software, derivative works or modified versions, and any portions 104Srgrimes * thereof, and that both notices appear in supporting documentation. 118871Srgrimes * 124Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 134Srgrimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 144Srgrimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 158871Srgrimes * 164Srgrimes * Carnegie Mellon requests users of this software to return to 178871Srgrimes * 184Srgrimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 194Srgrimes * School of Computer Science 204Srgrimes * Carnegie Mellon University 214Srgrimes * Pittsburgh PA 15213-3890 228871Srgrimes * 234Srgrimes * any improvements or extensions that they make and grant Carnegie Mellon 244Srgrimes * the rights to redistribute these changes. 254Srgrimes */ 264Srgrimes 2737415Scharnier#ifndef lint 2837415Scharnierstatic const char rcsid[] = 2937415Scharnier "$Id$"; 3037415Scharnier#endif /* not lint */ 3137415Scharnier 324Srgrimes#include <sys/disklabel.h> 3337415Scharnier#include <sys/stat.h> 3437415Scharnier#include <ctype.h> 3537415Scharnier#include <fcntl.h> 3637415Scharnier#include <err.h> 3737415Scharnier#include <errno.h> 384Srgrimes#include <stdio.h> 3937415Scharnier#include <stdlib.h> 4016561Salex#include <string.h> 4116561Salex#include <unistd.h> 424Srgrimes 434Srgrimesint iotest; 444Srgrimes 454Srgrimes#define LBUF 100 464Srgrimesstatic char lbuf[LBUF]; 474Srgrimes 484Srgrimes/* 494Srgrimes * 504Srgrimes * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 514Srgrimes * 524Srgrimes * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 534Srgrimes * Copyright (c) 1989 Robert. V. Baron 544Srgrimes * Created. 554Srgrimes */ 564Srgrimes 574Srgrimes#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 584Srgrimes#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp 594Srgrimes#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 604Srgrimes 614Srgrimes#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 624Srgrimes 6320061Ssos#define MAX_SEC_SIZE 2048 /* maximum section size that is supported */ 6420061Ssos#define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 6520061Ssosint secsize = 0; /* the sensed sector size */ 664Srgrimes 6710514Sjoergconst char *disk; 6810514Sjoergconst char *disks[] = 6910514Sjoerg{ 7010514Sjoerg "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0 7110514Sjoerg}; 7210514Sjoerg 734Srgrimesstruct disklabel disklabel; /* disk parameters */ 744Srgrimes 754Srgrimesint cyls, sectors, heads, cylsecs, disksecs; 764Srgrimes 774Srgrimesstruct mboot 784Srgrimes{ 7937415Scharnier unsigned char padding[2]; /* force the longs to be long aligned */ 804Srgrimes unsigned char bootinst[DOSPARTOFF]; 814Srgrimes struct dos_partition parts[4]; 824Srgrimes unsigned short int signature; 8320061Ssos /* room to read in MBRs that are bigger then DEV_BSIZE */ 8420061Ssos unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE]; 854Srgrimes}; 864Srgrimesstruct mboot mboot; 874Srgrimes 884Srgrimes#define ACTIVE 0x80 894Srgrimes#define BOOT_MAGIC 0xAA55 904Srgrimes 914Srgrimesint dos_cyls; 924Srgrimesint dos_heads; 934Srgrimesint dos_sectors; 944Srgrimesint dos_cylsecs; 954Srgrimes 964Srgrimes#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 974Srgrimes#define DOSCYL(c) (c & 0xff) 984Srgrimesstatic int partition = -1; 994Srgrimes 1004Srgrimes 10119459Sjkh#define MAX_ARGS 10 10219459Sjkh 10319459Sjkhstatic int current_line_number; 10419459Sjkh 10519459Sjkhstatic int geom_processed = 0; 10619459Sjkhstatic int part_processed = 0; 10719459Sjkhstatic int active_processed = 0; 10819459Sjkh 10919459Sjkh 11019459Sjkhtypedef struct cmd { 11119459Sjkh char cmd; 11219459Sjkh int n_args; 11319459Sjkh struct arg { 11419459Sjkh char argtype; 11519459Sjkh int arg_val; 11619459Sjkh } args[MAX_ARGS]; 11719459Sjkh} CMD; 11819459Sjkh 11919459Sjkh 1204Srgrimesstatic int a_flag = 0; /* set active partition */ 1214Srgrimesstatic int i_flag = 0; /* replace partition data */ 1224Srgrimesstatic int u_flag = 0; /* update partition data */ 12319459Sjkhstatic int t_flag = 0; /* test only, if f_flag is given */ 12419459Sjkhstatic char *f_flag = NULL; /* Read config info from file */ 12519459Sjkhstatic int v_flag = 0; /* Be verbose */ 1264Srgrimes 1274Srgrimesstatic unsigned char bootcode[] = { 1288871Srgrimes0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf, 1298871Srgrimes0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe, 1308871Srgrimes0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd, 1318871Srgrimes0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74, 1328871Srgrimes0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00, 1338871Srgrimes0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe, 1348871Srgrimes0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00, 1358871Srgrimes0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10, 1364Srgrimes0xeb, 0xf4, 0xfb, 0xeb, 0xfe, 1374Srgrimes'M', 'i', 's', 's', 'i', 'n', 'g', ' ', 1384Srgrimes 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 1398871Srgrimes'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ', 1404Srgrimes 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 1414Srgrimes'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ', 1424Srgrimes 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0, 1434Srgrimes'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ', 1448871Srgrimes 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0, 1454Srgrimes 1468871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1478871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1488871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1498871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1508871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1518871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1528871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1538871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1548871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1558871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1568871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1578871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1588871Srgrimes 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 1594Srgrimes}; 1604Srgrimes 1614Srgrimesstruct part_type 1624Srgrimes{ 1634Srgrimes unsigned char type; 1644Srgrimes char *name; 1654Srgrimes}part_types[] = 1664Srgrimes{ 1678871Srgrimes {0x00, "unused"} 1688871Srgrimes ,{0x01, "Primary DOS with 12 bit FAT"} 1698871Srgrimes ,{0x02, "XENIX / filesystem"} 1708871Srgrimes ,{0x03, "XENIX /usr filesystem"} 17134582Sache ,{0x04, "Primary DOS with 16 bit FAT (<= 32MB)"} 1728871Srgrimes ,{0x05, "Extended DOS"} 1738871Srgrimes ,{0x06, "Primary 'big' DOS (> 32MB)"} 17434952Sobrien ,{0x07, "OS/2 HPFS, NTFS, QNX or Advanced UNIX"} 1758871Srgrimes ,{0x08, "AIX filesystem"} 1768871Srgrimes ,{0x09, "AIX boot partition or Coherent"} 1778871Srgrimes ,{0x0A, "OS/2 Boot Manager or OPUS"} 17834582Sache ,{0x0B, "DOS or Windows 95 with 32 bit FAT"} 17934582Sache ,{0x0C, "DOS or Windows 95 with 32 bit FAT, LBA"} 18034582Sache ,{0x0E, "Primary 'big' DOS (> 32MB, LBA)"} 18134582Sache ,{0x0F, "Extended DOS, LBA"} 1828871Srgrimes ,{0x10, "OPUS"} 1838871Srgrimes ,{0x40, "VENIX 286"} 1848871Srgrimes ,{0x50, "DM"} 1858871Srgrimes ,{0x51, "DM"} 1868871Srgrimes ,{0x52, "CP/M or Microport SysV/AT"} 1878871Srgrimes ,{0x56, "GB"} 1888871Srgrimes ,{0x61, "Speed"} 1898871Srgrimes ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 1908871Srgrimes ,{0x64, "Novell Netware 2.xx"} 1918871Srgrimes ,{0x65, "Novell Netware 3.xx"} 1928871Srgrimes ,{0x75, "PCIX"} 1938871Srgrimes ,{0x80, "Minix 1.1 ... 1.4a"} 1948871Srgrimes ,{0x81, "Minix 1.4b ... 1.5.10"} 1958871Srgrimes ,{0x82, "Linux swap"} 1968871Srgrimes ,{0x83, "Linux filesystem"} 1978871Srgrimes ,{0x93, "Amoeba filesystem"} 1988871Srgrimes ,{0x94, "Amoeba bad block table"} 1998871Srgrimes ,{0xA5, "FreeBSD/NetBSD/386BSD"} 20025378Simp ,{0xA6, "OpenBSD"} 2017902Sgpalmer ,{0xA7, "NEXTSTEP"} 2028871Srgrimes ,{0xB7, "BSDI BSD/386 filesystem"} 2038871Srgrimes ,{0xB8, "BSDI BSD/386 swap"} 2048871Srgrimes ,{0xDB, "Concurrent CPM or C.DOS or CTOS"} 2058871Srgrimes ,{0xE1, "Speed"} 2068871Srgrimes ,{0xE3, "Speed"} 2078871Srgrimes ,{0xE4, "Speed"} 2088871Srgrimes ,{0xF1, "Speed"} 2098871Srgrimes ,{0xF2, "DOS 3.3+ Secondary"} 2108871Srgrimes ,{0xF4, "Speed"} 2118871Srgrimes ,{0xFF, "BBT (Bad Blocks Table)"} 2124Srgrimes}; 2134Srgrimes 21416561Salexstatic void print_s0(int which); 21516561Salexstatic void print_part(int i); 21616561Salexstatic void init_sector0(unsigned long start); 21719459Sjkhstatic void init_boot(void); 21816561Salexstatic void change_part(int i); 21916561Salexstatic void print_params(); 22016561Salexstatic void change_active(int which); 22116561Salexstatic void get_params_to_use(); 22218915Sbdestatic void dos(int sec, int size, unsigned char *c, unsigned char *s, 22318915Sbde unsigned char *h); 22416561Salexstatic int open_disk(int u_flag); 22516561Salexstatic ssize_t read_disk(off_t sector, void *buf); 22616561Salexstatic ssize_t write_disk(off_t sector, void *buf); 22716561Salexstatic int get_params(); 22816561Salexstatic int read_s0(); 22916561Salexstatic int write_s0(); 23016561Salexstatic int ok(char *str); 23116561Salexstatic int decimal(char *str, int *num, int deflt); 23216561Salexstatic char *get_type(int type); 23319459Sjkhstatic int read_config(char *config_file); 23419459Sjkhstatic void reset_boot(void); 23537415Scharnierstatic void usage(void); 23616561Salex#if 0 23716561Salexstatic int hex(char *str, int *num, int deflt); 23816561Salexstatic int string(char *str, char **ans); 23916561Salex#endif 2404Srgrimes 24116561Salex 24216561Salexint 24316561Salexmain(int argc, char *argv[]) 2444Srgrimes{ 24510514Sjoerg int i; 2464Srgrimes 2474Srgrimes for ( argv++ ; --argc ; argv++ ) { register char *token = *argv; 2484Srgrimes if (*token++ != '-' || !*token) 2494Srgrimes break; 2504Srgrimes else { register int flag; 25116561Salex for ( ; (flag = *token++) ; ) { 2524Srgrimes switch (flag) { 2534Srgrimes case '1': 2544Srgrimes partition = 1; 2554Srgrimes break; 2564Srgrimes case '2': 2574Srgrimes partition = 2; 2584Srgrimes break; 2594Srgrimes case '3': 2604Srgrimes partition = 3; 2614Srgrimes break; 26226421Sbrian case '4': 26326421Sbrian partition = 4; 26426421Sbrian break; 2654Srgrimes case 'a': 2664Srgrimes a_flag = 1; 2674Srgrimes break; 26819459Sjkh case 'f': 26919459Sjkh if (*token) 27019459Sjkh { 27119459Sjkh f_flag = token; 27219459Sjkh token = ""; 27319459Sjkh } 27419459Sjkh else 27519459Sjkh { 27619459Sjkh if (argc == 1) 27737415Scharnier usage(); 27819459Sjkh --argc; 27919459Sjkh f_flag = *++argv; 28019459Sjkh } 28119459Sjkh /* 28219459Sjkh * u_flag is needed, because we're 28319459Sjkh * writing to the disk. 28419459Sjkh */ 28519459Sjkh u_flag = 1; 28619459Sjkh break; 2874Srgrimes case 'i': 2884Srgrimes i_flag = 1; 2894Srgrimes case 'u': 2904Srgrimes u_flag = 1; 2914Srgrimes break; 29219459Sjkh case 't': 29319459Sjkh t_flag = 1; 29419459Sjkh case 'v': 29519459Sjkh v_flag = 1; 29619459Sjkh break; 2974Srgrimes default: 29837415Scharnier usage(); 2994Srgrimes } 3004Srgrimes } 3014Srgrimes } 3024Srgrimes } 3034Srgrimes 3044Srgrimes if (argc > 0) 30510514Sjoerg { 30610514Sjoerg static char realname[12]; 3078871Srgrimes 30810514Sjoerg if(strncmp(argv[0], "/dev", 4) == 0) 30910514Sjoerg disk = argv[0]; 31010514Sjoerg else 31110514Sjoerg { 31210514Sjoerg snprintf(realname, 12, "/dev/r%s", argv[0]); 31310514Sjoerg disk = realname; 31410514Sjoerg } 31510514Sjoerg 31610514Sjoerg if (open_disk(u_flag) < 0) 31737415Scharnier err(1, "cannot open disk %s", disk); 31810514Sjoerg } 31910514Sjoerg else 32010514Sjoerg { 32116561Salex int i, rv = 0; 3224Srgrimes 32310514Sjoerg for(i = 0; disks[i]; i++) 32410514Sjoerg { 32510514Sjoerg disk = disks[i]; 32610514Sjoerg rv = open_disk(u_flag); 32710514Sjoerg if(rv != -2) break; 32810514Sjoerg } 32910514Sjoerg if(rv < 0) 33037415Scharnier err(1, "cannot open any disk"); 33110514Sjoerg } 33210514Sjoerg 3334Srgrimes printf("******* Working on device %s *******\n",disk); 33419459Sjkh 33519459Sjkh if (f_flag) 3364Srgrimes { 33719459Sjkh if (read_s0() || i_flag) 33819459Sjkh { 33919459Sjkh reset_boot(); 34019459Sjkh } 34119459Sjkh 34219459Sjkh if (!read_config(f_flag)) 34319459Sjkh { 34419459Sjkh exit(1); 34519459Sjkh } 34619459Sjkh if (v_flag) 34719459Sjkh { 34819459Sjkh print_s0(-1); 34919459Sjkh } 35019459Sjkh if (!t_flag) 35119459Sjkh { 35219459Sjkh write_s0(); 35319459Sjkh } 3544Srgrimes } 3554Srgrimes else 3564Srgrimes { 35719459Sjkh if(u_flag) 35819459Sjkh { 35919459Sjkh get_params_to_use(); 36019459Sjkh } 36119459Sjkh else 36219459Sjkh { 3634Srgrimes print_params(); 36419459Sjkh } 3654Srgrimes 36619459Sjkh if (read_s0()) 3674Srgrimes init_sector0(1); 3684Srgrimes 36920061Ssos printf("Media sector size is %d\n", secsize); 37019459Sjkh printf("Warning: BIOS sector numbering starts with sector 1\n"); 37119459Sjkh printf("Information from DOS bootblock is:\n"); 37219459Sjkh if (partition == -1) 37326421Sbrian for (i = 1; i <= NDOSPART; i++) 37419459Sjkh change_part(i); 37519459Sjkh else 3764Srgrimes change_part(partition); 3774Srgrimes 37819459Sjkh if (u_flag || a_flag) 3794Srgrimes change_active(partition); 3804Srgrimes 38119459Sjkh if (u_flag || a_flag) { 38219459Sjkh if (!t_flag) 38319459Sjkh { 38419459Sjkh printf("\nWe haven't changed the partition table yet. "); 38519459Sjkh printf("This is your last chance.\n"); 38619459Sjkh } 3874Srgrimes print_s0(-1); 38819459Sjkh if (!t_flag) 38919459Sjkh { 39019459Sjkh if (ok("Should we write new partition table?")) 3914Srgrimes write_s0(); 39219459Sjkh } 39319459Sjkh else 39419459Sjkh { 39519459Sjkh printf("\n-t flag specified -- partition table not written.\n"); 39619459Sjkh } 39719459Sjkh } 3984Srgrimes } 3994Srgrimes 4004Srgrimes exit(0); 40137415Scharnier} 4024Srgrimes 40337415Scharnierstatic void 40437415Scharnierusage() 40537415Scharnier{ 40637415Scharnier fprintf(stderr, 40737415Scharnier "usage: fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{1,2,3,4}] [disk]\n"); 40837415Scharnier exit(1); 4094Srgrimes} 4104Srgrimes 41116561Salexstatic void 41216561Salexprint_s0(int which) 4134Srgrimes{ 4144Srgrimesint i; 4154Srgrimes 4164Srgrimes print_params(); 4174Srgrimes printf("Information from DOS bootblock is:\n"); 4184Srgrimes if (which == -1) 41926421Sbrian for (i = 1; i <= NDOSPART; i++) 4204Srgrimes printf("%d: ", i), print_part(i); 4214Srgrimes else 4224Srgrimes print_part(which); 4234Srgrimes} 4244Srgrimes 4254Srgrimesstatic struct dos_partition mtpart = { 0 }; 4264Srgrimes 42716561Salexstatic void 42816561Salexprint_part(int i) 4294Srgrimes{ 43026389Sgibbs struct dos_partition *partp; 43126389Sgibbs u_int64_t part_mb; 4324Srgrimes 43326421Sbrian partp = ((struct dos_partition *) &mboot.parts) + i - 1; 4344Srgrimes 4354Srgrimes if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 4364Srgrimes printf("<UNUSED>\n"); 4374Srgrimes return; 4384Srgrimes } 43926389Sgibbs /* 44026389Sgibbs * Be careful not to overflow. 44126389Sgibbs */ 44226389Sgibbs part_mb = partp->dp_size; 44326389Sgibbs part_mb *= secsize; 44426389Sgibbs part_mb /= (1024 * 1024); 4454Srgrimes printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 44637244Sbde printf(" start %lu, size %lu (%qd Meg), flag %x%s\n", 44737244Sbde (u_long)partp->dp_start, 44837244Sbde (u_long)partp->dp_size, 44926389Sgibbs part_mb, 45034952Sobrien partp->dp_flag, 45134952Sobrien partp->dp_flag == ACTIVE ? " (active)" : ""); 4524Srgrimes printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n" 4534Srgrimes ,DPCYL(partp->dp_scyl, partp->dp_ssect) 4544Srgrimes ,DPSECT(partp->dp_ssect) 4554Srgrimes ,partp->dp_shd 4564Srgrimes ,DPCYL(partp->dp_ecyl, partp->dp_esect) 4574Srgrimes ,DPSECT(partp->dp_esect) 4584Srgrimes ,partp->dp_ehd); 4594Srgrimes} 4604Srgrimes 46119459Sjkh 46216561Salexstatic void 46319459Sjkhinit_boot(void) 46419459Sjkh{ 46519459Sjkh memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 46619459Sjkh mboot.signature = BOOT_MAGIC; 46719459Sjkh} 46819459Sjkh 46919459Sjkh 47019459Sjkhstatic void 47116561Salexinit_sector0(unsigned long start) 4724Srgrimes{ 4734Srgrimesstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 47416561Salexunsigned long size = disksecs - start; 4754Srgrimes 47619459Sjkh init_boot(); 4774Srgrimes 4784Srgrimes partp->dp_typ = DOSPTYP_386BSD; 4794Srgrimes partp->dp_flag = ACTIVE; 4804Srgrimes partp->dp_start = start; 4814Srgrimes partp->dp_size = size; 4824Srgrimes 48318915Sbde dos(partp->dp_start, partp->dp_size, 48418915Sbde &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 48518915Sbde dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 48618915Sbde &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 4874Srgrimes} 4884Srgrimes 48916561Salexstatic void 49016561Salexchange_part(int i) 4914Srgrimes{ 49226421Sbrianstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1; 4934Srgrimes 4944Srgrimes printf("The data for partition %d is:\n", i); 4954Srgrimes print_part(i); 4964Srgrimes 4974Srgrimes if (u_flag && ok("Do you want to change it?")) { 4984Srgrimes int tmp; 4994Srgrimes 5004Srgrimes if (i_flag) { 5014Srgrimes bzero((char *)partp, sizeof (struct dos_partition)); 50226421Sbrian if (i == 4) { 5034Srgrimes init_sector0(1); 50426421Sbrian printf("\nThe static data for the DOS partition 4 has been reinitialized to:\n"); 5054Srgrimes print_part(i); 5064Srgrimes } 5074Srgrimes } 5084Srgrimes 5094Srgrimes do { 51034952Sobrien Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp); 5114Srgrimes Decimal("start", partp->dp_start, tmp); 5124Srgrimes Decimal("size", partp->dp_size, tmp); 5134Srgrimes 51436262Sjraynard if (ok("Explicitly specify beg/end address ?")) 5154Srgrimes { 5164Srgrimes int tsec,tcyl,thd; 5174Srgrimes tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 5184Srgrimes thd = partp->dp_shd; 5194Srgrimes tsec = DPSECT(partp->dp_ssect); 5204Srgrimes Decimal("beginning cylinder", tcyl, tmp); 5214Srgrimes Decimal("beginning head", thd, tmp); 5224Srgrimes Decimal("beginning sector", tsec, tmp); 5234Srgrimes partp->dp_scyl = DOSCYL(tcyl); 5244Srgrimes partp->dp_ssect = DOSSECT(tsec,tcyl); 5254Srgrimes partp->dp_shd = thd; 5264Srgrimes 5274Srgrimes tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 5284Srgrimes thd = partp->dp_ehd; 5294Srgrimes tsec = DPSECT(partp->dp_esect); 5304Srgrimes Decimal("ending cylinder", tcyl, tmp); 5314Srgrimes Decimal("ending head", thd, tmp); 5324Srgrimes Decimal("ending sector", tsec, tmp); 5334Srgrimes partp->dp_ecyl = DOSCYL(tcyl); 5344Srgrimes partp->dp_esect = DOSSECT(tsec,tcyl); 5354Srgrimes partp->dp_ehd = thd; 5364Srgrimes } else { 53718915Sbde dos(partp->dp_start, partp->dp_size, 53818915Sbde &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 53918915Sbde dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 54018915Sbde &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 5414Srgrimes } 5428871Srgrimes 5434Srgrimes print_part(i); 5444Srgrimes } while (!ok("Are we happy with this entry?")); 5454Srgrimes } 5464Srgrimes} 5474Srgrimes 54816561Salexstatic void 5494Srgrimesprint_params() 5504Srgrimes{ 5514Srgrimes printf("parameters extracted from in-core disklabel are:\n"); 5524Srgrimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 5534Srgrimes ,cyls,heads,sectors,cylsecs); 5544Srgrimes if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255)) 55520061Ssos printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 5564Srgrimes printf("parameters to be used for BIOS calculations are:\n"); 5574Srgrimes printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 5584Srgrimes ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 5594Srgrimes} 5604Srgrimes 56116561Salexstatic void 56216561Salexchange_active(int which) 5634Srgrimes{ 5644Srgrimesint i; 56526421Sbrianint active = 4, tmp; 5664Srgrimesstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts); 5674Srgrimes 5684Srgrimes if (a_flag && which != -1) 5694Srgrimes active = which; 5703723Sbde if (!ok("Do you want to change the active partition?")) 5713723Sbde return; 57234952Sobriensetactive: 57334952Sobrien active = 4; 57434952Sobrien do { 5753723Sbde Decimal("active partition", active, tmp); 57634952Sobrien if (active < 1 || 4 < active) { 57734952Sobrien printf("Active partition number must be in range 1-4." 57834952Sobrien " Try again.\n"); 57934952Sobrien goto setactive; 58034952Sobrien } 58134952Sobrien } while (!ok("Are you happy with this choice")); 5824Srgrimes for (i = 0; i < NDOSPART; i++) 5834Srgrimes partp[i].dp_flag = 0; 58426421Sbrian if (active > 0 && active <= NDOSPART) 58526421Sbrian partp[active-1].dp_flag = ACTIVE; 5864Srgrimes} 5874Srgrimes 58816561Salexvoid 5894Srgrimesget_params_to_use() 5904Srgrimes{ 5914Srgrimes int tmp; 5924Srgrimes print_params(); 5934Srgrimes if (ok("Do you want to change our idea of what BIOS thinks ?")) 5944Srgrimes { 5954Srgrimes do 5964Srgrimes { 5974Srgrimes Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 5984Srgrimes Decimal("BIOS's idea of #heads", dos_heads, tmp); 5994Srgrimes Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 6004Srgrimes dos_cylsecs = dos_heads * dos_sectors; 6014Srgrimes print_params(); 6024Srgrimes } 6034Srgrimes while(!ok("Are you happy with this choice")); 6044Srgrimes } 6054Srgrimes} 6064Srgrimes 60719459Sjkh 6084Srgrimes/***********************************************\ 6094Srgrimes* Change real numbers into strange dos numbers * 6104Srgrimes\***********************************************/ 61116561Salexstatic void 61218915Sbdedos(sec, size, c, s, h) 61318915Sbdeint sec, size; 6144Srgrimesunsigned char *c, *s, *h; 6154Srgrimes{ 6164Srgrimesint cy; 6174Srgrimesint hd; 6184Srgrimes 61918915Sbde if (sec == 0 && size == 0) { 6203723Sbde *s = *c = *h = 0; 6213723Sbde return; 6223723Sbde } 6233723Sbde 6244Srgrimes cy = sec / ( dos_cylsecs ); 6254Srgrimes sec = sec - cy * ( dos_cylsecs ); 6264Srgrimes 6274Srgrimes hd = sec / dos_sectors; 6284Srgrimes sec = (sec - hd * dos_sectors) + 1; 6294Srgrimes 6304Srgrimes *h = hd; 6314Srgrimes *c = cy & 0xff; 6324Srgrimes *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 6334Srgrimes} 6344Srgrimes 6354Srgrimesint fd; 6364Srgrimes 6374Srgrimes /* Getting device status */ 6384Srgrimes 63916561Salexstatic int 64016561Salexopen_disk(int u_flag) 6414Srgrimes{ 6424Srgrimesstruct stat st; 6434Srgrimes 6448871Srgrimes if (stat(disk, &st) == -1) { 64537415Scharnier warnx("can't get file status of %s", disk); 6464Srgrimes return -1; 6472810Sbde } 6482810Sbde if ( !(st.st_mode & S_IFCHR) ) 64937415Scharnier warnx("device %s is not character special", disk); 6503723Sbde if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) { 65110514Sjoerg if(errno == ENXIO) 65210514Sjoerg return -2; 65337415Scharnier warnx("can't open device %s", disk); 6544Srgrimes return -1; 6554Srgrimes } 6564Srgrimes if (get_params(0) == -1) { 65737415Scharnier warnx("can't get disk parameters on %s", disk); 6584Srgrimes return -1; 6594Srgrimes } 6604Srgrimes return fd; 6614Srgrimes} 6624Srgrimes 66316561Salexstatic ssize_t 66416561Salexread_disk(off_t sector, void *buf) 6654Srgrimes{ 6664Srgrimes lseek(fd,(sector * 512), 0); 66720061Ssos if( secsize == 0 ) 66820061Ssos for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 ) 66920061Ssos { 67020061Ssos /* try the read */ 67120061Ssos int size = read(fd, buf, secsize); 67220061Ssos if( size == secsize ) 67320061Ssos /* it worked so return */ 67420061Ssos return secsize; 67520061Ssos } 67620061Ssos else 67720061Ssos return read( fd, buf, secsize ); 67820061Ssos 67920061Ssos /* we failed to read at any of the sizes */ 68020061Ssos return -1; 6814Srgrimes} 6824Srgrimes 68316561Salexstatic ssize_t 68416561Salexwrite_disk(off_t sector, void *buf) 6854Srgrimes{ 6864Srgrimes lseek(fd,(sector * 512), 0); 68720061Ssos /* write out in the size that the read_disk found worked */ 68820061Ssos return write(fd, buf, secsize); 6894Srgrimes} 6904Srgrimes 69116561Salexstatic int 69216561Salexget_params() 6934Srgrimes{ 6944Srgrimes 6954Srgrimes if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 69637415Scharnier warnx("can't get disk parameters on %s; supplying dummy ones", disk); 6972810Sbde dos_cyls = cyls = 1; 6982810Sbde dos_heads = heads = 1; 6992810Sbde dos_sectors = sectors = 1; 7002810Sbde dos_cylsecs = cylsecs = heads * sectors; 7012810Sbde disksecs = cyls * heads * sectors; 7022810Sbde return disksecs; 7034Srgrimes } 7044Srgrimes 7054Srgrimes dos_cyls = cyls = disklabel.d_ncylinders; 7064Srgrimes dos_heads = heads = disklabel.d_ntracks; 7074Srgrimes dos_sectors = sectors = disklabel.d_nsectors; 7084Srgrimes dos_cylsecs = cylsecs = heads * sectors; 7094Srgrimes disksecs = cyls * heads * sectors; 7104Srgrimes 7114Srgrimes return (disksecs); 7124Srgrimes} 7134Srgrimes 7144Srgrimes 71516561Salexstatic int 7164Srgrimesread_s0() 7174Srgrimes{ 7188871Srgrimes if (read_disk(0, (char *) mboot.bootinst) == -1) { 71937415Scharnier warnx("can't read fdisk partition table"); 7204Srgrimes return -1; 7214Srgrimes } 7224Srgrimes if (mboot.signature != BOOT_MAGIC) { 72337415Scharnier warnx("invalid fdisk partition table found"); 7244Srgrimes /* So should we initialize things */ 7254Srgrimes return -1; 7264Srgrimes } 7274Srgrimes return 0; 7284Srgrimes} 7294Srgrimes 73016561Salexstatic int 7314Srgrimeswrite_s0() 7324Srgrimes{ 7334Srgrimes int flag; 7344Srgrimes if (iotest) { 7354Srgrimes print_s0(-1); 7364Srgrimes return 0; 7374Srgrimes } 7384Srgrimes /* 7394Srgrimes * write enable label sector before write (if necessary), 7404Srgrimes * disable after writing. 7414Srgrimes * needed if the disklabel protected area also protects 7424Srgrimes * sector 0. (e.g. empty disk) 7434Srgrimes */ 7444Srgrimes flag = 1; 74511143Sjulian#ifdef NOT_NOW 7464Srgrimes if (ioctl(fd, DIOCWLABEL, &flag) < 0) 74737415Scharnier warn("ioctl DIOCWLABEL"); 74811143Sjulian#endif 7498871Srgrimes if (write_disk(0, (char *) mboot.bootinst) == -1) { 75037415Scharnier warnx("can't write fdisk partition table"); 7514Srgrimes return -1; 7524Srgrimes flag = 0; 75311143Sjulian#ifdef NOT_NOW 7544Srgrimes (void) ioctl(fd, DIOCWLABEL, &flag); 75511143Sjulian#endif 7564Srgrimes } 75716561Salex return(0); 7584Srgrimes} 7594Srgrimes 7604Srgrimes 76116561Salexstatic int 7624Srgrimesok(str) 7634Srgrimeschar *str; 7644Srgrimes{ 7654Srgrimes printf("%s [n] ", str); 7664Srgrimes fgets(lbuf, LBUF, stdin); 7674Srgrimes lbuf[strlen(lbuf)-1] = 0; 7684Srgrimes 7694Srgrimes if (*lbuf && 7704Srgrimes (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 7714Srgrimes !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 7724Srgrimes return 1; 7734Srgrimes else 7744Srgrimes return 0; 7754Srgrimes} 7764Srgrimes 77716561Salexstatic int 77816561Salexdecimal(char *str, int *num, int deflt) 7794Srgrimes{ 7804Srgrimesint acc = 0, c; 7814Srgrimeschar *cp; 7824Srgrimes 7834Srgrimes while (1) { 7844Srgrimes printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 7854Srgrimes fgets(lbuf, LBUF, stdin); 7864Srgrimes lbuf[strlen(lbuf)-1] = 0; 7874Srgrimes 7884Srgrimes if (!*lbuf) 7894Srgrimes return 0; 7904Srgrimes 7914Srgrimes cp = lbuf; 7924Srgrimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 7934Srgrimes if (!c) 7944Srgrimes return 0; 79516561Salex while ((c = *cp++)) { 7964Srgrimes if (c <= '9' && c >= '0') 7974Srgrimes acc = acc * 10 + c - '0'; 7984Srgrimes else 7994Srgrimes break; 8004Srgrimes } 8014Srgrimes if (c == ' ' || c == '\t') 8024Srgrimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 8034Srgrimes if (!c) { 8044Srgrimes *num = acc; 8054Srgrimes return 1; 8064Srgrimes } else 80734952Sobrien printf("%s is an invalid decimal number. Try again.\n", 8084Srgrimes lbuf); 8094Srgrimes } 8104Srgrimes 8114Srgrimes} 8124Srgrimes 81316561Salex#if 0 81416561Salexstatic int 81516561Salexhex(char *str, int *num, int deflt) 8164Srgrimes{ 8174Srgrimesint acc = 0, c; 8184Srgrimeschar *cp; 8194Srgrimes 8204Srgrimes while (1) { 8214Srgrimes printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 8224Srgrimes fgets(lbuf, LBUF, stdin); 8234Srgrimes lbuf[strlen(lbuf)-1] = 0; 8244Srgrimes 8254Srgrimes if (!*lbuf) 8264Srgrimes return 0; 8274Srgrimes 8284Srgrimes cp = lbuf; 8294Srgrimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 8304Srgrimes if (!c) 8314Srgrimes return 0; 83216561Salex while ((c = *cp++)) { 8334Srgrimes if (c <= '9' && c >= '0') 8344Srgrimes acc = (acc << 4) + c - '0'; 8354Srgrimes else if (c <= 'f' && c >= 'a') 8364Srgrimes acc = (acc << 4) + c - 'a' + 10; 8374Srgrimes else if (c <= 'F' && c >= 'A') 8384Srgrimes acc = (acc << 4) + c - 'A' + 10; 8394Srgrimes else 8404Srgrimes break; 8414Srgrimes } 8424Srgrimes if (c == ' ' || c == '\t') 8434Srgrimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 8444Srgrimes if (!c) { 8454Srgrimes *num = acc; 8464Srgrimes return 1; 8474Srgrimes } else 84834952Sobrien printf("%s is an invalid hex number. Try again.\n", 8494Srgrimes lbuf); 8504Srgrimes } 8514Srgrimes 8524Srgrimes} 8534Srgrimes 85416561Salexstatic int 85516561Salexstring(char *str, char **ans) 8564Srgrimes{ 8574Srgrimesint c; 8584Srgrimeschar *cp = lbuf; 8594Srgrimes 8604Srgrimes while (1) { 8614Srgrimes printf("Supply a string value for \"%s\" [%s] ", str, *ans); 8624Srgrimes fgets(lbuf, LBUF, stdin); 8634Srgrimes lbuf[strlen(lbuf)-1] = 0; 8644Srgrimes 8654Srgrimes if (!*lbuf) 8664Srgrimes return 0; 8674Srgrimes 8684Srgrimes while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 8694Srgrimes if (c == '"') { 8704Srgrimes c = *++cp; 8714Srgrimes *ans = cp; 8724Srgrimes while ((c = *cp) && c != '"') cp++; 8734Srgrimes } else { 8744Srgrimes *ans = cp; 8754Srgrimes while ((c = *cp) && c != ' ' && c != '\t') cp++; 8764Srgrimes } 8774Srgrimes 8784Srgrimes if (c) 8794Srgrimes *cp = 0; 8804Srgrimes return 1; 8814Srgrimes } 8824Srgrimes} 88316561Salex#endif 8844Srgrimes 88516561Salexstatic char * 88616561Salexget_type(int type) 8874Srgrimes{ 8884Srgrimes int numentries = (sizeof(part_types)/sizeof(struct part_type)); 8894Srgrimes int counter = 0; 8904Srgrimes struct part_type *ptr = part_types; 8914Srgrimes 8928871Srgrimes 8934Srgrimes while(counter < numentries) 8944Srgrimes { 8954Srgrimes if(ptr->type == type) 8964Srgrimes { 8974Srgrimes return(ptr->name); 8984Srgrimes } 8994Srgrimes ptr++; 9004Srgrimes counter++; 9014Srgrimes } 9024Srgrimes return("unknown"); 9034Srgrimes} 90419459Sjkh 90519459Sjkh 90619459Sjkhstatic void 90719459Sjkhparse_config_line(line, command) 90819459Sjkh char *line; 90919459Sjkh CMD *command; 91019459Sjkh{ 91119459Sjkh char *cp, *end; 91219459Sjkh 91319459Sjkh cp = line; 91419459Sjkh while (1) /* dirty trick used to insure one exit point for this 91519459Sjkh function */ 91619459Sjkh { 91719459Sjkh memset(command, 0, sizeof(*command)); 91819459Sjkh 91919459Sjkh while (isspace(*cp)) ++cp; 92019459Sjkh if (*cp == '\0' || *cp == '#') 92119459Sjkh { 92219459Sjkh break; 92319459Sjkh } 92419459Sjkh command->cmd = *cp++; 92519459Sjkh 92619459Sjkh /* 92719459Sjkh * Parse args 92819459Sjkh */ 92919459Sjkh while (1) 93019459Sjkh { 93119459Sjkh while (isspace(*cp)) ++cp; 93219459Sjkh if (*cp == '#') 93319459Sjkh { 93419459Sjkh break; /* found comment */ 93519459Sjkh } 93619459Sjkh if (isalpha(*cp)) 93719459Sjkh { 93819459Sjkh command->args[command->n_args].argtype = *cp++; 93919459Sjkh } 94019459Sjkh if (!isdigit(*cp)) 94119459Sjkh { 94219459Sjkh break; /* assume end of line */ 94319459Sjkh } 94419459Sjkh end = NULL; 94519459Sjkh command->args[command->n_args].arg_val = strtol(cp, &end, 0); 94619459Sjkh if (cp == end) 94719459Sjkh { 94819459Sjkh break; /* couldn't parse number */ 94919459Sjkh } 95019459Sjkh cp = end; 95119459Sjkh command->n_args++; 95219459Sjkh } 95319459Sjkh break; 95419459Sjkh } 95519459Sjkh} 95619459Sjkh 95719459Sjkh 95819459Sjkhstatic int 95919459Sjkhprocess_geometry(command) 96019459Sjkh CMD *command; 96119459Sjkh{ 96219459Sjkh int status = 1, i; 96319459Sjkh 96419459Sjkh while (1) 96519459Sjkh { 96619459Sjkh geom_processed = 1; 96719459Sjkh if (part_processed) 96819459Sjkh { 96937415Scharnier warnx( 97037415Scharnier "ERROR line %d: the geometry specification line must occur before\n\ 97137415Scharnier all partition specifications", 97237415Scharnier current_line_number); 97319459Sjkh status = 0; 97419459Sjkh break; 97519459Sjkh } 97619459Sjkh if (command->n_args != 3) 97719459Sjkh { 97837415Scharnier warnx("ERROR line %d: incorrect number of geometry args", 97937415Scharnier current_line_number); 98019459Sjkh status = 0; 98119459Sjkh break; 98219459Sjkh } 98319459Sjkh dos_cyls = -1; 98419459Sjkh dos_heads = -1; 98519459Sjkh dos_sectors = -1; 98619459Sjkh for (i = 0; i < 3; ++i) 98719459Sjkh { 98819459Sjkh switch (command->args[i].argtype) 98919459Sjkh { 99019459Sjkh case 'c': 99119459Sjkh dos_cyls = command->args[i].arg_val; 99219459Sjkh break; 99319459Sjkh case 'h': 99419459Sjkh dos_heads = command->args[i].arg_val; 99519459Sjkh break; 99619459Sjkh case 's': 99719459Sjkh dos_sectors = command->args[i].arg_val; 99819459Sjkh break; 99919459Sjkh default: 100037415Scharnier warnx( 100137415Scharnier "ERROR line %d: unknown geometry arg type: '%c' (0x%02x)", 100237415Scharnier current_line_number, command->args[i].argtype, 100319459Sjkh command->args[i].argtype); 100419459Sjkh status = 0; 100519459Sjkh break; 100619459Sjkh } 100719459Sjkh } 100819459Sjkh if (status == 0) 100919459Sjkh { 101019459Sjkh break; 101119459Sjkh } 101219459Sjkh 101319459Sjkh dos_cylsecs = dos_heads * dos_sectors; 101419459Sjkh 101519459Sjkh /* 101619459Sjkh * Do sanity checks on parameter values 101719459Sjkh */ 101819459Sjkh if (dos_cyls < 0) 101919459Sjkh { 102037415Scharnier warnx("ERROR line %d: number of cylinders not specified", 102137415Scharnier current_line_number); 102219459Sjkh status = 0; 102319459Sjkh } 102419459Sjkh if (dos_cyls == 0 || dos_cyls > 1024) 102519459Sjkh { 102637415Scharnier warnx( 102737415Scharnier "WARNING line %d: number of cylinders (%d) may be out-of-range\n\ 102819459Sjkh (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\ 102937415Scharnier is dedicated to FreeBSD)", 103037415Scharnier current_line_number, dos_cyls); 103119459Sjkh } 103219459Sjkh 103319459Sjkh if (dos_heads < 0) 103419459Sjkh { 103537415Scharnier warnx("ERROR line %d: number of heads not specified", 103637415Scharnier current_line_number); 103719459Sjkh status = 0; 103819459Sjkh } 103919459Sjkh else if (dos_heads < 1 || dos_heads > 256) 104019459Sjkh { 104137415Scharnier warnx("ERROR line %d: number of heads must be within (1-256)", 104237415Scharnier current_line_number); 104319459Sjkh status = 0; 104419459Sjkh } 104519459Sjkh 104619459Sjkh if (dos_sectors < 0) 104719459Sjkh { 104837415Scharnier warnx("ERROR line %d: number of sectors not specified", 104937415Scharnier current_line_number); 105019459Sjkh status = 0; 105119459Sjkh } 105219459Sjkh else if (dos_sectors < 1 || dos_sectors > 63) 105319459Sjkh { 105437415Scharnier warnx("ERROR line %d: number of sectors must be within (1-63)", 105537415Scharnier current_line_number); 105619459Sjkh status = 0; 105719459Sjkh } 105819459Sjkh 105919459Sjkh break; 106019459Sjkh } 106119459Sjkh return (status); 106219459Sjkh} 106319459Sjkh 106419459Sjkh 106519459Sjkhstatic int 106619459Sjkhprocess_partition(command) 106719459Sjkh CMD *command; 106819459Sjkh{ 106919459Sjkh int status = 0, partition; 107019459Sjkh unsigned long chunks, adj_size, max_end; 107119459Sjkh struct dos_partition *partp; 107219459Sjkh 107319459Sjkh while (1) 107419459Sjkh { 107519459Sjkh part_processed = 1; 107619459Sjkh if (command->n_args != 4) 107719459Sjkh { 107837415Scharnier warnx("ERROR line %d: incorrect number of partition args", 107937415Scharnier current_line_number); 108019459Sjkh break; 108119459Sjkh } 108219459Sjkh partition = command->args[0].arg_val; 108326421Sbrian if (partition < 1 || partition > 4) 108419459Sjkh { 108537415Scharnier warnx("ERROR line %d: invalid partition number %d", 108637415Scharnier current_line_number, partition); 108719459Sjkh break; 108819459Sjkh } 108926421Sbrian partp = ((struct dos_partition *) &mboot.parts) + partition - 1; 109019459Sjkh bzero((char *)partp, sizeof (struct dos_partition)); 109119459Sjkh partp->dp_typ = command->args[1].arg_val; 109219459Sjkh partp->dp_start = command->args[2].arg_val; 109319459Sjkh partp->dp_size = command->args[3].arg_val; 109419459Sjkh max_end = partp->dp_start + partp->dp_size; 109519459Sjkh 109619459Sjkh if (partp->dp_typ == 0) 109719459Sjkh { 109819459Sjkh /* 109919459Sjkh * Get out, the partition is marked as unused. 110019459Sjkh */ 110119459Sjkh /* 110219459Sjkh * Insure that it's unused. 110319459Sjkh */ 110419459Sjkh bzero((char *)partp, sizeof (struct dos_partition)); 110519459Sjkh status = 1; 110619459Sjkh break; 110719459Sjkh } 110819459Sjkh 110919459Sjkh /* 111019459Sjkh * Adjust start upwards, if necessary, to fall on an head boundary. 111119459Sjkh */ 111219459Sjkh if (partp->dp_start % dos_sectors != 0) 111319459Sjkh { 111419459Sjkh adj_size = 111519459Sjkh (partp->dp_start / dos_sectors + 1) * dos_sectors; 111619459Sjkh if (adj_size > max_end) 111719459Sjkh { 111819459Sjkh /* 111919459Sjkh * Can't go past end of partition 112019459Sjkh */ 112137415Scharnier warnx( 112237415Scharnier "ERROR line %d: unable to adjust start of partition %d to fall on\n\ 112337415Scharnier a cylinder boundary", 112437415Scharnier current_line_number, partition); 112519459Sjkh break; 112619459Sjkh } 112737415Scharnier warnx( 112837415Scharnier "WARNING: adjusting start offset of partition '%d' from %lu\n\ 112937415Scharnier to %lu, to round to an head boundary", 113037415Scharnier partition, (u_long)partp->dp_start, adj_size); 113119459Sjkh partp->dp_start = adj_size; 113219459Sjkh } 113319459Sjkh 113419459Sjkh /* 113519459Sjkh * Adjust size downwards, if necessary, to fall on a cylinder 113619459Sjkh * boundary. 113719459Sjkh */ 113819459Sjkh chunks = 113919459Sjkh ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs; 114019459Sjkh adj_size = chunks - partp->dp_start; 114119459Sjkh if (adj_size != partp->dp_size) 114219459Sjkh { 114337415Scharnier warnx( 114437415Scharnier "WARNING: adjusting size of partition '%d' from %lu to %lu,\n\ 114537415Scharnier to round to a cylinder boundary", 114637415Scharnier partition, (u_long)partp->dp_size, adj_size); 114719459Sjkh if (chunks > 0) 114819459Sjkh { 114919459Sjkh partp->dp_size = adj_size; 115019459Sjkh } 115119459Sjkh else 115219459Sjkh { 115319459Sjkh partp->dp_size = 0; 115419459Sjkh } 115519459Sjkh } 115619459Sjkh if (partp->dp_size < 1) 115719459Sjkh { 115837415Scharnier warnx("ERROR line %d: size for partition '%d' is zero", 115937415Scharnier current_line_number, partition); 116019459Sjkh break; 116119459Sjkh } 116219459Sjkh 116319459Sjkh dos(partp->dp_start, partp->dp_size, 116419459Sjkh &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 116519459Sjkh dos(partp->dp_start+partp->dp_size - 1, partp->dp_size, 116619459Sjkh &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 116719459Sjkh status = 1; 116819459Sjkh break; 116919459Sjkh } 117019459Sjkh return (status); 117119459Sjkh} 117219459Sjkh 117319459Sjkh 117419459Sjkhstatic int 117519459Sjkhprocess_active(command) 117619459Sjkh CMD *command; 117719459Sjkh{ 117819459Sjkh int status = 0, partition, i; 117919459Sjkh struct dos_partition *partp; 118019459Sjkh 118119459Sjkh while (1) 118219459Sjkh { 118319459Sjkh active_processed = 1; 118419459Sjkh if (command->n_args != 1) 118519459Sjkh { 118637415Scharnier warnx("ERROR line %d: incorrect number of active args", 118737415Scharnier current_line_number); 118819459Sjkh status = 0; 118919459Sjkh break; 119019459Sjkh } 119119459Sjkh partition = command->args[0].arg_val; 119226421Sbrian if (partition < 1 || partition > 4) 119319459Sjkh { 119437415Scharnier warnx("ERROR line %d: invalid partition number %d", 119537415Scharnier current_line_number, partition); 119619459Sjkh break; 119719459Sjkh } 119819459Sjkh /* 119919459Sjkh * Reset active partition 120019459Sjkh */ 120119459Sjkh partp = ((struct dos_partition *) &mboot.parts); 120219459Sjkh for (i = 0; i < NDOSPART; i++) 120319459Sjkh partp[i].dp_flag = 0; 120426421Sbrian partp[partition-1].dp_flag = ACTIVE; 120519459Sjkh 120619459Sjkh status = 1; 120719459Sjkh break; 120819459Sjkh } 120919459Sjkh return (status); 121019459Sjkh} 121119459Sjkh 121219459Sjkh 121319459Sjkhstatic int 121419459Sjkhprocess_line(line) 121519459Sjkh char *line; 121619459Sjkh{ 121719459Sjkh CMD command; 121819459Sjkh int status = 1; 121919459Sjkh 122019459Sjkh while (1) 122119459Sjkh { 122219459Sjkh parse_config_line(line, &command); 122319459Sjkh switch (command.cmd) 122419459Sjkh { 122519459Sjkh case 0: 122619459Sjkh /* 122719459Sjkh * Comment or blank line 122819459Sjkh */ 122919459Sjkh break; 123019459Sjkh case 'g': 123119459Sjkh /* 123219459Sjkh * Set geometry 123319459Sjkh */ 123419459Sjkh status = process_geometry(&command); 123519459Sjkh break; 123619459Sjkh case 'p': 123719459Sjkh status = process_partition(&command); 123819459Sjkh break; 123919459Sjkh case 'a': 124019459Sjkh status = process_active(&command); 124119459Sjkh break; 124219459Sjkh default: 124319459Sjkh status = 0; 124419459Sjkh break; 124519459Sjkh } 124619459Sjkh break; 124719459Sjkh } 124819459Sjkh return (status); 124919459Sjkh} 125019459Sjkh 125119459Sjkh 125219459Sjkhstatic int 125319459Sjkhread_config(config_file) 125419459Sjkh char *config_file; 125519459Sjkh{ 125619459Sjkh FILE *fp = NULL; 125719459Sjkh int status = 1; 125819459Sjkh char buf[1010]; 125919459Sjkh 126019459Sjkh while (1) /* dirty trick used to insure one exit point for this 126119459Sjkh function */ 126219459Sjkh { 126319459Sjkh if (strcmp(config_file, "-") != 0) 126419459Sjkh { 126519459Sjkh /* 126619459Sjkh * We're not reading from stdin 126719459Sjkh */ 126819459Sjkh if ((fp = fopen(config_file, "r")) == NULL) 126919459Sjkh { 127019459Sjkh status = 0; 127119459Sjkh break; 127219459Sjkh } 127319459Sjkh } 127419459Sjkh else 127519459Sjkh { 127619459Sjkh fp = stdin; 127719459Sjkh } 127819459Sjkh current_line_number = 0; 127919459Sjkh while (!feof(fp)) 128019459Sjkh { 128119459Sjkh if (fgets(buf, sizeof(buf), fp) == NULL) 128219459Sjkh { 128319459Sjkh break; 128419459Sjkh } 128519459Sjkh ++current_line_number; 128619459Sjkh status = process_line(buf); 128719459Sjkh if (status == 0) 128819459Sjkh { 128919459Sjkh break; 129019459Sjkh } 129119459Sjkh } 129219459Sjkh break; 129319459Sjkh } 129419459Sjkh if (fp) 129519459Sjkh { 129619459Sjkh /* 129719459Sjkh * It doesn't matter if we're reading from stdin, as we've reached EOF 129819459Sjkh */ 129919459Sjkh fclose(fp); 130019459Sjkh } 130119459Sjkh return (status); 130219459Sjkh} 130319459Sjkh 130419459Sjkh 130519459Sjkhstatic void 130619459Sjkhreset_boot(void) 130719459Sjkh{ 130819459Sjkh int i; 130919459Sjkh struct dos_partition *partp; 131019459Sjkh 131119459Sjkh init_boot(); 131219459Sjkh for (i = 0; i < 4; ++i) 131319459Sjkh { 131419459Sjkh partp = ((struct dos_partition *) &mboot.parts) + i; 131519459Sjkh bzero((char *)partp, sizeof (struct dos_partition)); 131619459Sjkh } 131719459Sjkh} 1318