fdisk.c revision 20061
1145479Smp/* 259243Sobrien * Mach Operating System 359243Sobrien * Copyright (c) 1992 Carnegie Mellon University 459243Sobrien * All Rights Reserved. 559243Sobrien * 659243Sobrien * Permission to use, copy, modify and distribute this software and its 759243Sobrien * documentation is hereby granted, provided that both the copyright 859243Sobrien * notice and this permission notice appear in all copies of the 959243Sobrien * software, derivative works or modified versions, and any portions 1059243Sobrien * thereof, and that both notices appear in supporting documentation. 1159243Sobrien * 1259243Sobrien * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 1359243Sobrien * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 1459243Sobrien * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 1559243Sobrien * 1659243Sobrien * Carnegie Mellon requests users of this software to return to 17100616Smp * 1859243Sobrien * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 1959243Sobrien * School of Computer Science 2059243Sobrien * Carnegie Mellon University 2159243Sobrien * Pittsburgh PA 15213-3890 2259243Sobrien * 2359243Sobrien * any improvements or extensions that they make and grant Carnegie Mellon 2459243Sobrien * the rights to redistribute these changes. 2559243Sobrien */ 2659243Sobrien 2759243Sobrien#include <sys/types.h> 2859243Sobrien#include <sys/disklabel.h> 2959243Sobrien#include <stdio.h> 3059243Sobrien#include <string.h> 3159243Sobrien#include <errno.h> 3259243Sobrien#include <sys/stat.h> 3359243Sobrien#include <sys/ioctl.h> 3459243Sobrien#include <fcntl.h> 35145479Smp#include <unistd.h> 3659243Sobrien 3759243Sobrienint iotest; 3859243Sobrien 3959243Sobrien#define LBUF 100 40145479Smpstatic char lbuf[LBUF]; 41145479Smp 42145479Smp/* 43145479Smp * 44145479Smp * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 45131962Smp * 4659243Sobrien * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 4759243Sobrien * Copyright (c) 1989 Robert. V. Baron 4859243Sobrien * Created. 4959243Sobrien */ 5059243Sobrien 5159243Sobrien#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 5259243Sobrien#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp 5359243Sobrien#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 5459243Sobrien 5559243Sobrien#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 5659243Sobrien 5759243Sobrien#define MAX_SEC_SIZE 2048 /* maximum section size that is supported */ 5859243Sobrien#define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 5959243Sobrienint secsize = 0; /* the sensed sector size */ 6059243Sobrien 6159243Sobrienconst char *disk; 6259243Sobrienconst char *disks[] = 6359243Sobrien{ 6459243Sobrien "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0 6559243Sobrien}; 6659243Sobrien 6759243Sobrienchar *name; 6859243Sobrien 6959243Sobrienstruct disklabel disklabel; /* disk parameters */ 7059243Sobrien 7159243Sobrienint cyls, sectors, heads, cylsecs, disksecs; 72145479Smp 7359243Sobrienstruct mboot 7459243Sobrien{ 7559243Sobrien unsigned char padding[2]; /* force the longs to be long alligned */ 7659243Sobrien unsigned char bootinst[DOSPARTOFF]; 7759243Sobrien struct dos_partition parts[4]; 78145479Smp unsigned short int signature; 7959243Sobrien /* room to read in MBRs that are bigger then DEV_BSIZE */ 8059243Sobrien unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE]; 8159243Sobrien}; 8259243Sobrienstruct mboot mboot; 8359243Sobrien 8459243Sobrien#define ACTIVE 0x80 8559243Sobrien#define BOOT_MAGIC 0xAA55 8659243Sobrien 8759243Sobrienint dos_cyls; 8859243Sobrienint dos_heads; 8959243Sobrienint dos_sectors; 9059243Sobrienint dos_cylsecs; 9159243Sobrien 9259243Sobrien#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 9359243Sobrien#define DOSCYL(c) (c & 0xff) 9459243Sobrienstatic int partition = -1; 9559243Sobrien 9659243Sobrien 9759243Sobrien#define MAX_ARGS 10 9859243Sobrien 9959243Sobrienstatic int current_line_number; 100145479Smp 10159243Sobrienstatic int geom_processed = 0; 10259243Sobrienstatic int part_processed = 0; 10359243Sobrienstatic int active_processed = 0; 10459243Sobrien 10559243Sobrien 10659243Sobrientypedef struct cmd { 10759243Sobrien char cmd; 10859243Sobrien int n_args; 10959243Sobrien struct arg { 11059243Sobrien char argtype; 11159243Sobrien int arg_val; 11259243Sobrien } args[MAX_ARGS]; 11359243Sobrien} CMD; 11459243Sobrien 11559243Sobrien 11659243Sobrienstatic int a_flag = 0; /* set active partition */ 11759243Sobrienstatic int i_flag = 0; /* replace partition data */ 11859243Sobrienstatic int u_flag = 0; /* update partition data */ 11959243Sobrienstatic int t_flag = 0; /* test only, if f_flag is given */ 12059243Sobrienstatic char *f_flag = NULL; /* Read config info from file */ 12159243Sobrienstatic int v_flag = 0; /* Be verbose */ 12259243Sobrien 12359243Sobrienstatic unsigned char bootcode[] = { 12459243Sobrien0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf, 12559243Sobrien0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe, 12659243Sobrien0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd, 12759243Sobrien0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74, 12859243Sobrien0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00, 129131962Smp0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe, 13059243Sobrien0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00, 13159243Sobrien0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10, 13259243Sobrien0xeb, 0xf4, 0xfb, 0xeb, 0xfe, 13359243Sobrien'M', 'i', 's', 's', 'i', 'n', 'g', ' ', 13459243Sobrien 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 13559243Sobrien'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ', 13659243Sobrien 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0, 13759243Sobrien'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ', 13859243Sobrien 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0, 13959243Sobrien'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ', 14059243Sobrien 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0, 14159243Sobrien 14259243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14359243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14459243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14559243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14659243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14759243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14859243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14959243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15059243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15159243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15259243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15359243Sobrien 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154131962Smp 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 155131962Smp}; 156131962Smp 157131962Smpstruct part_type 158131962Smp{ 159131962Smp unsigned char type; 160131962Smp char *name; 161131962Smp}part_types[] = 162131962Smp{ 163131962Smp {0x00, "unused"} 164131962Smp ,{0x01, "Primary DOS with 12 bit FAT"} 165131962Smp ,{0x02, "XENIX / filesystem"} 16659243Sobrien ,{0x03, "XENIX /usr filesystem"} 16759243Sobrien ,{0x04, "Primary DOS with 16 bit FAT"} 16859243Sobrien ,{0x05, "Extended DOS"} 16959243Sobrien ,{0x06, "Primary 'big' DOS (> 32MB)"} 17059243Sobrien ,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"} 17159243Sobrien ,{0x08, "AIX filesystem"} 17259243Sobrien ,{0x09, "AIX boot partition or Coherent"} 17359243Sobrien ,{0x0A, "OS/2 Boot Manager or OPUS"} 17459243Sobrien ,{0x10, "OPUS"} 17583098Smp ,{0x40, "VENIX 286"} 17683098Smp ,{0x50, "DM"} 17783098Smp ,{0x51, "DM"} 17859243Sobrien ,{0x52, "CP/M or Microport SysV/AT"} 17959243Sobrien ,{0x56, "GB"} 18059243Sobrien ,{0x61, "Speed"} 18159243Sobrien ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 18259243Sobrien ,{0x64, "Novell Netware 2.xx"} 18359243Sobrien ,{0x65, "Novell Netware 3.xx"} 18459243Sobrien ,{0x75, "PCIX"} 18559243Sobrien ,{0x80, "Minix 1.1 ... 1.4a"} 18659243Sobrien ,{0x81, "Minix 1.4b ... 1.5.10"} 18759243Sobrien ,{0x82, "Linux swap"} 18859243Sobrien ,{0x83, "Linux filesystem"} 18959243Sobrien ,{0x93, "Amoeba filesystem"} 19059243Sobrien ,{0x94, "Amoeba bad block table"} 19159243Sobrien ,{0xA5, "FreeBSD/NetBSD/386BSD"} 19259243Sobrien ,{0xA7, "NEXTSTEP"} 19359243Sobrien ,{0xB7, "BSDI BSD/386 filesystem"} 19459243Sobrien ,{0xB8, "BSDI BSD/386 swap"} 19559243Sobrien ,{0xDB, "Concurrent CPM or C.DOS or CTOS"} 19669408Sache ,{0xE1, "Speed"} 19769408Sache ,{0xE3, "Speed"} 198145479Smp ,{0xE4, "Speed"} 19969408Sache ,{0xF1, "Speed"} 20069408Sache ,{0xF2, "DOS 3.3+ Secondary"} 201100616Smp ,{0xF4, "Speed"} 202100616Smp ,{0xFF, "BBT (Bad Blocks Table)"} 203100616Smp}; 204100616Smp 20569408Sachestatic void print_s0(int which); 20659243Sobrienstatic void print_part(int i); 20759243Sobrienstatic void init_sector0(unsigned long start); 20859243Sobrienstatic void init_boot(void); 20959243Sobrienstatic void change_part(int i); 21059243Sobrienstatic void print_params(); 21159243Sobrienstatic void change_active(int which); 212145479Smpstatic void get_params_to_use(); 21359243Sobrienstatic void dos(int sec, int size, unsigned char *c, unsigned char *s, 21459243Sobrien unsigned char *h); 215145479Smpstatic int open_disk(int u_flag); 21659243Sobrienstatic ssize_t read_disk(off_t sector, void *buf); 21759243Sobrienstatic ssize_t write_disk(off_t sector, void *buf); 218145479Smpstatic int get_params(); 21959243Sobrienstatic int read_s0(); 22059243Sobrienstatic int write_s0(); 221145479Smpstatic int ok(char *str); 222145479Smpstatic int decimal(char *str, int *num, int deflt); 223145479Smpstatic char *get_type(int type); 22459243Sobrienstatic int read_config(char *config_file); 22559243Sobrienstatic void reset_boot(void); 22659243Sobrien#if 0 22759243Sobrienstatic int hex(char *str, int *num, int deflt); 22859243Sobrienstatic int string(char *str, char **ans); 22959243Sobrien#endif 23059243Sobrien 23159243Sobrien 23259243Sobrienint 23359243Sobrienmain(int argc, char *argv[]) 23459243Sobrien{ 23559243Sobrien int i; 23659243Sobrien 23759243Sobrien name = *argv; 23859243Sobrien {register char *cp = name; 23959243Sobrien while (*cp) if (*cp++ == '/') name = cp; 24059243Sobrien } 24159243Sobrien 24259243Sobrien for ( argv++ ; --argc ; argv++ ) { register char *token = *argv; 24359243Sobrien if (*token++ != '-' || !*token) 24459243Sobrien break; 24559243Sobrien else { register int flag; 24659243Sobrien for ( ; (flag = *token++) ; ) { 24759243Sobrien switch (flag) { 24859243Sobrien case '0': 24959243Sobrien partition = 0; 25059243Sobrien break; 25159243Sobrien case '1': 25259243Sobrien partition = 1; 25359243Sobrien break; 25459243Sobrien case '2': 25559243Sobrien partition = 2; 25659243Sobrien break; 25759243Sobrien case '3': 25859243Sobrien partition = 3; 25959243Sobrien break; 26059243Sobrien case 'a': 26159243Sobrien a_flag = 1; 26259243Sobrien break; 26359243Sobrien case 'f': 26459243Sobrien if (*token) 26559243Sobrien { 26659243Sobrien f_flag = token; 26759243Sobrien token = ""; 26859243Sobrien } 26959243Sobrien else 27059243Sobrien { 27159243Sobrien if (argc == 1) 27259243Sobrien { 27359243Sobrien goto usage; 27459243Sobrien } 27559243Sobrien --argc; 27659243Sobrien f_flag = *++argv; 27759243Sobrien } 27859243Sobrien /* 27959243Sobrien * u_flag is needed, because we're 28059243Sobrien * writing to the disk. 28159243Sobrien */ 282145479Smp u_flag = 1; 28359243Sobrien break; 28459243Sobrien case 'i': 28559243Sobrien i_flag = 1; 28659243Sobrien case 'u': 28759243Sobrien u_flag = 1; 28859243Sobrien break; 28959243Sobrien case 't': 29059243Sobrien t_flag = 1; 29159243Sobrien case 'v': 29259243Sobrien v_flag = 1; 29359243Sobrien break; 29459243Sobrien default: 29559243Sobrien goto usage; 29659243Sobrien } 29759243Sobrien } 29859243Sobrien } 29959243Sobrien } 30059243Sobrien 30159243Sobrien if (argc > 0) 30259243Sobrien { 30359243Sobrien static char realname[12]; 30459243Sobrien 30559243Sobrien if(strncmp(argv[0], "/dev", 4) == 0) 30659243Sobrien disk = argv[0]; 30759243Sobrien else 30859243Sobrien { 30959243Sobrien snprintf(realname, 12, "/dev/r%s", argv[0]); 31059243Sobrien disk = realname; 31159243Sobrien } 31259243Sobrien 31359243Sobrien if (open_disk(u_flag) < 0) 31459243Sobrien { 315145479Smp fprintf(stderr, "Cannot open disk %s (%s)\n", 316145479Smp disk, sys_errlist[errno]); 31759243Sobrien exit(1); 31859243Sobrien } 31959243Sobrien } 32059243Sobrien else 32159243Sobrien { 32259243Sobrien int i, rv = 0; 32359243Sobrien 32459243Sobrien for(i = 0; disks[i]; i++) 32559243Sobrien { 32659243Sobrien disk = disks[i]; 32759243Sobrien rv = open_disk(u_flag); 32859243Sobrien if(rv != -2) break; 32959243Sobrien } 33059243Sobrien if(rv < 0) 33159243Sobrien { 33259243Sobrien fprintf(stderr, "Cannot open any disk (%s)\n", 333145479Smp sys_errlist[errno]); 33459243Sobrien exit(1); 33559243Sobrien } 33659243Sobrien } 33759243Sobrien 33859243Sobrien printf("******* Working on device %s *******\n",disk); 33959243Sobrien 34059243Sobrien if (f_flag) 34159243Sobrien { 34259243Sobrien if (read_s0() || i_flag) 34359243Sobrien { 34459243Sobrien reset_boot(); 34559243Sobrien } 346145479Smp 34759243Sobrien if (!read_config(f_flag)) 34859243Sobrien { 34959243Sobrien exit(1); 35059243Sobrien } 35159243Sobrien if (v_flag) 35259243Sobrien { 35359243Sobrien print_s0(-1); 35459243Sobrien } 35559243Sobrien if (!t_flag) 35659243Sobrien { 35759243Sobrien write_s0(); 35859243Sobrien } 35959243Sobrien } 36059243Sobrien else 361145479Smp { 36259243Sobrien if(u_flag) 363145479Smp { 36459243Sobrien get_params_to_use(); 36559243Sobrien } 36659243Sobrien else 36759243Sobrien { 36859243Sobrien print_params(); 36959243Sobrien } 37059243Sobrien 37159243Sobrien if (read_s0()) 37259243Sobrien init_sector0(1); 37359243Sobrien 37459243Sobrien printf("Media sector size is %d\n", secsize); 37559243Sobrien printf("Warning: BIOS sector numbering starts with sector 1\n"); 37659243Sobrien printf("Information from DOS bootblock is:\n"); 37759243Sobrien if (partition == -1) 37859243Sobrien for (i = 0; i < NDOSPART; i++) 37959243Sobrien change_part(i); 38059243Sobrien else 38159243Sobrien change_part(partition); 38259243Sobrien 38359243Sobrien if (u_flag || a_flag) 38459243Sobrien change_active(partition); 38559243Sobrien 38659243Sobrien if (u_flag || a_flag) { 38759243Sobrien if (!t_flag) 38859243Sobrien { 38959243Sobrien printf("\nWe haven't changed the partition table yet. "); 39059243Sobrien printf("This is your last chance.\n"); 39159243Sobrien } 39259243Sobrien print_s0(-1); 39359243Sobrien if (!t_flag) 39459243Sobrien { 39559243Sobrien if (ok("Should we write new partition table?")) 39659243Sobrien write_s0(); 39759243Sobrien } 39859243Sobrien else 39959243Sobrien { 40059243Sobrien printf("\n-t flag specified -- partition table not written.\n"); 40159243Sobrien } 40259243Sobrien } 40359243Sobrien } 40459243Sobrien 40559243Sobrien exit(0); 40659243Sobrien 40759243Sobrienusage: 40859243Sobrien printf("fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{0,1,2,3}] [disk]\n"); 40959243Sobrien return(1); 41059243Sobrien} 41159243Sobrien 41259243Sobrienstatic void 41359243Sobrienprint_s0(int which) 41459243Sobrien{ 41559243Sobrienint i; 41659243Sobrien 41759243Sobrien print_params(); 41859243Sobrien printf("Information from DOS bootblock is:\n"); 41959243Sobrien if (which == -1) 42059243Sobrien for (i = 0; i < NDOSPART; i++) 42159243Sobrien printf("%d: ", i), print_part(i); 42259243Sobrien else 42359243Sobrien print_part(which); 42459243Sobrien} 42559243Sobrien 42659243Sobrienstatic struct dos_partition mtpart = { 0 }; 42759243Sobrien 42859243Sobrienstatic void 42959243Sobrienprint_part(int i) 43059243Sobrien{ 43159243Sobrienstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 43259243Sobrien 43359243Sobrien 43459243Sobrien if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 43559243Sobrien printf("<UNUSED>\n"); 43659243Sobrien return; 43759243Sobrien } 43859243Sobrien printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 43959243Sobrien printf(" start %ld, size %ld (%ld Meg), flag %x\n", 44059243Sobrien partp->dp_start, 44159243Sobrien partp->dp_size, partp->dp_size * secsize / (1024 * 1024), 44259243Sobrien partp->dp_flag); 44359243Sobrien printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n" 44459243Sobrien ,DPCYL(partp->dp_scyl, partp->dp_ssect) 44559243Sobrien ,DPSECT(partp->dp_ssect) 44659243Sobrien ,partp->dp_shd 44759243Sobrien ,DPCYL(partp->dp_ecyl, partp->dp_esect) 44859243Sobrien ,DPSECT(partp->dp_esect) 449145479Smp ,partp->dp_ehd); 45059243Sobrien} 45159243Sobrien 45259243Sobrien 45359243Sobrienstatic void 45459243Sobrieninit_boot(void) 45559243Sobrien{ 45659243Sobrien memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 45759243Sobrien mboot.signature = BOOT_MAGIC; 45859243Sobrien} 45959243Sobrien 46059243Sobrien 46159243Sobrienstatic void 46259243Sobrieninit_sector0(unsigned long start) 46359243Sobrien{ 46459243Sobrienstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 46559243Sobrienunsigned long size = disksecs - start; 46659243Sobrien 467145479Smp init_boot(); 46859243Sobrien 469145479Smp partp->dp_typ = DOSPTYP_386BSD; 47059243Sobrien partp->dp_flag = ACTIVE; 47159243Sobrien partp->dp_start = start; 47259243Sobrien partp->dp_size = size; 47359243Sobrien 47459243Sobrien dos(partp->dp_start, partp->dp_size, 47559243Sobrien &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 47659243Sobrien dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 47759243Sobrien &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 47859243Sobrien} 47959243Sobrien 48059243Sobrienstatic void 48159243Sobrienchange_part(int i) 48259243Sobrien{ 48359243Sobrienstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i; 48459243Sobrien 48559243Sobrien printf("The data for partition %d is:\n", i); 48659243Sobrien print_part(i); 48759243Sobrien 48859243Sobrien if (u_flag && ok("Do you want to change it?")) { 48959243Sobrien int tmp; 49059243Sobrien 49159243Sobrien if (i_flag) { 492145479Smp bzero((char *)partp, sizeof (struct dos_partition)); 49359243Sobrien if (i == 3) { 49459243Sobrien init_sector0(1); 49559243Sobrien printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n"); 49659243Sobrien print_part(i); 49759243Sobrien } 49859243Sobrien } 49959243Sobrien 50059243Sobrien do { 50159243Sobrien Decimal("sysid", partp->dp_typ, tmp); 50259243Sobrien Decimal("start", partp->dp_start, tmp); 50359243Sobrien Decimal("size", partp->dp_size, tmp); 50459243Sobrien 50559243Sobrien if (ok("Explicitly specifiy beg/end address ?")) 50659243Sobrien { 50759243Sobrien int tsec,tcyl,thd; 50859243Sobrien tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 50959243Sobrien thd = partp->dp_shd; 51059243Sobrien tsec = DPSECT(partp->dp_ssect); 51159243Sobrien Decimal("beginning cylinder", tcyl, tmp); 51259243Sobrien Decimal("beginning head", thd, tmp); 51359243Sobrien Decimal("beginning sector", tsec, tmp); 51459243Sobrien partp->dp_scyl = DOSCYL(tcyl); 51559243Sobrien partp->dp_ssect = DOSSECT(tsec,tcyl); 51659243Sobrien partp->dp_shd = thd; 51759243Sobrien 51859243Sobrien tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 51959243Sobrien thd = partp->dp_ehd; 52059243Sobrien tsec = DPSECT(partp->dp_esect); 52159243Sobrien Decimal("ending cylinder", tcyl, tmp); 52259243Sobrien Decimal("ending head", thd, tmp); 52359243Sobrien Decimal("ending sector", tsec, tmp); 524145479Smp partp->dp_ecyl = DOSCYL(tcyl); 52559243Sobrien partp->dp_esect = DOSSECT(tsec,tcyl); 52659243Sobrien partp->dp_ehd = thd; 52759243Sobrien } else { 52859243Sobrien dos(partp->dp_start, partp->dp_size, 52959243Sobrien &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 53059243Sobrien dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 53159243Sobrien &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 53259243Sobrien } 533145479Smp 53459243Sobrien print_part(i); 535145479Smp } while (!ok("Are we happy with this entry?")); 53659243Sobrien } 53759243Sobrien} 53859243Sobrien 53959243Sobrienstatic void 54059243Sobrienprint_params() 54159243Sobrien{ 54259243Sobrien printf("parameters extracted from in-core disklabel are:\n"); 54359243Sobrien printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 54459243Sobrien ,cyls,heads,sectors,cylsecs); 54559243Sobrien if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255)) 54659243Sobrien printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 54759243Sobrien printf("parameters to be used for BIOS calculations are:\n"); 54859243Sobrien printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 54959243Sobrien ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 55059243Sobrien} 55159243Sobrien 55259243Sobrienstatic void 55359243Sobrienchange_active(int which) 55459243Sobrien{ 55559243Sobrienint i; 55659243Sobrienint active = 3, tmp; 55759243Sobrienstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts); 55859243Sobrien 55959243Sobrien if (a_flag && which != -1) 56059243Sobrien active = which; 56159243Sobrien if (!ok("Do you want to change the active partition?")) 56259243Sobrien return; 563145479Smp do 56459243Sobrien Decimal("active partition", active, tmp); 56559243Sobrien while (!ok("Are you happy with this choice")); 56659243Sobrien for (i = 0; i < NDOSPART; i++) 56759243Sobrien partp[i].dp_flag = 0; 56859243Sobrien if (active >= 0 && active < NDOSPART) 569100616Smp partp[active].dp_flag = ACTIVE; 570100616Smp} 57159243Sobrien 57259243Sobrienvoid 57359243Sobrienget_params_to_use() 57459243Sobrien{ 57559243Sobrien int tmp; 576145479Smp print_params(); 57759243Sobrien if (ok("Do you want to change our idea of what BIOS thinks ?")) 578145479Smp { 57959243Sobrien do 58059243Sobrien { 58159243Sobrien Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 58259243Sobrien Decimal("BIOS's idea of #heads", dos_heads, tmp); 58359243Sobrien Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 58459243Sobrien dos_cylsecs = dos_heads * dos_sectors; 58559243Sobrien print_params(); 58659243Sobrien } 58759243Sobrien while(!ok("Are you happy with this choice")); 58859243Sobrien } 58959243Sobrien} 59059243Sobrien 591145479Smp 592145479Smp/***********************************************\ 59359243Sobrien* Change real numbers into strange dos numbers * 59459243Sobrien\***********************************************/ 59559243Sobrienstatic void 59659243Sobriendos(sec, size, c, s, h) 59759243Sobrienint sec, size; 59859243Sobrienunsigned char *c, *s, *h; 59959243Sobrien{ 60059243Sobrienint cy; 60159243Sobrienint hd; 60259243Sobrien 60359243Sobrien if (sec == 0 && size == 0) { 60459243Sobrien *s = *c = *h = 0; 60559243Sobrien return; 60659243Sobrien } 60759243Sobrien 60859243Sobrien cy = sec / ( dos_cylsecs ); 60959243Sobrien sec = sec - cy * ( dos_cylsecs ); 61059243Sobrien 61159243Sobrien hd = sec / dos_sectors; 61259243Sobrien sec = (sec - hd * dos_sectors) + 1; 61359243Sobrien 614145479Smp *h = hd; 61559243Sobrien *c = cy & 0xff; 61659243Sobrien *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 61759243Sobrien} 61859243Sobrien 61959243Sobrienint fd; 62059243Sobrien 62159243Sobrien /* Getting device status */ 62259243Sobrien 62359243Sobrienstatic int 62459243Sobrienopen_disk(int u_flag) 62559243Sobrien{ 62659243Sobrienstruct stat st; 627145479Smp 62859243Sobrien if (stat(disk, &st) == -1) { 62959243Sobrien fprintf(stderr, "%s: Can't get file status of %s\n", 63059243Sobrien name, disk); 63159243Sobrien return -1; 63259243Sobrien } 63359243Sobrien if ( !(st.st_mode & S_IFCHR) ) 63459243Sobrien fprintf(stderr,"%s: Device %s is not character special\n", 63559243Sobrien name, disk); 63659243Sobrien if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) { 63759243Sobrien if(errno == ENXIO) 63859243Sobrien return -2; 63959243Sobrien fprintf(stderr,"%s: Can't open device %s\n", name, disk); 64059243Sobrien return -1; 64159243Sobrien } 64259243Sobrien if (get_params(0) == -1) { 64359243Sobrien fprintf(stderr, "%s: Can't get disk parameters on %s\n", 64459243Sobrien name, disk); 64559243Sobrien return -1; 64659243Sobrien } 64759243Sobrien return fd; 64859243Sobrien} 64959243Sobrien 65059243Sobrienstatic ssize_t 65159243Sobrienread_disk(off_t sector, void *buf) 65259243Sobrien{ 65359243Sobrien lseek(fd,(sector * 512), 0); 65459243Sobrien if( secsize == 0 ) 65559243Sobrien for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 ) 65659243Sobrien { 65759243Sobrien /* try the read */ 65859243Sobrien int size = read(fd, buf, secsize); 65959243Sobrien if( size == secsize ) 66059243Sobrien /* it worked so return */ 66159243Sobrien return secsize; 66259243Sobrien } 66359243Sobrien else 66459243Sobrien return read( fd, buf, secsize ); 66559243Sobrien 66659243Sobrien /* we failed to read at any of the sizes */ 66759243Sobrien return -1; 66859243Sobrien} 66959243Sobrien 67059243Sobrienstatic ssize_t 67159243Sobrienwrite_disk(off_t sector, void *buf) 67259243Sobrien{ 67359243Sobrien lseek(fd,(sector * 512), 0); 67459243Sobrien /* write out in the size that the read_disk found worked */ 67559243Sobrien return write(fd, buf, secsize); 67659243Sobrien} 67759243Sobrien 67859243Sobrienstatic int 67959243Sobrienget_params() 68059243Sobrien{ 68159243Sobrien 68259243Sobrien if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 68359243Sobrien fprintf(stderr, 68459243Sobrien "%s: Can't get disk parameters on %s; supplying dummy ones\n", 68559243Sobrien name, disk); 68659243Sobrien dos_cyls = cyls = 1; 68759243Sobrien dos_heads = heads = 1; 68859243Sobrien dos_sectors = sectors = 1; 68959243Sobrien dos_cylsecs = cylsecs = heads * sectors; 69059243Sobrien disksecs = cyls * heads * sectors; 69159243Sobrien return disksecs; 69259243Sobrien } 69359243Sobrien 69459243Sobrien dos_cyls = cyls = disklabel.d_ncylinders; 69559243Sobrien dos_heads = heads = disklabel.d_ntracks; 69659243Sobrien dos_sectors = sectors = disklabel.d_nsectors; 69759243Sobrien dos_cylsecs = cylsecs = heads * sectors; 69859243Sobrien disksecs = cyls * heads * sectors; 699145479Smp 70059243Sobrien return (disksecs); 70159243Sobrien} 702145479Smp 703145479Smp 70459243Sobrienstatic int 70559243Sobrienread_s0() 70659243Sobrien{ 70759243Sobrien if (read_disk(0, (char *) mboot.bootinst) == -1) { 70859243Sobrien fprintf(stderr, "%s: Can't read fdisk partition table\n", name); 70959243Sobrien return -1; 71059243Sobrien } 71159243Sobrien if (mboot.signature != BOOT_MAGIC) { 71259243Sobrien fprintf(stderr, "%s: Invalid fdisk partition table found\n", 71359243Sobrien name); 71459243Sobrien /* So should we initialize things */ 71559243Sobrien return -1; 71659243Sobrien } 71759243Sobrien return 0; 71859243Sobrien} 71959243Sobrien 72059243Sobrienstatic int 72159243Sobrienwrite_s0() 72259243Sobrien{ 72359243Sobrien int flag; 72459243Sobrien if (iotest) { 72559243Sobrien print_s0(-1); 72659243Sobrien return 0; 72759243Sobrien } 72859243Sobrien /* 72959243Sobrien * write enable label sector before write (if necessary), 73059243Sobrien * disable after writing. 73159243Sobrien * needed if the disklabel protected area also protects 73259243Sobrien * sector 0. (e.g. empty disk) 73359243Sobrien */ 73459243Sobrien flag = 1; 735145479Smp#ifdef NOT_NOW 73659243Sobrien if (ioctl(fd, DIOCWLABEL, &flag) < 0) 73759243Sobrien perror("ioctl DIOCWLABEL"); 73859243Sobrien#endif 73959243Sobrien if (write_disk(0, (char *) mboot.bootinst) == -1) { 74059243Sobrien fprintf(stderr, "%s: Can't write fdisk partition table\n", 741100616Smp name); 742100616Smp return -1; 743100616Smp flag = 0; 744100616Smp#ifdef NOT_NOW 745100616Smp (void) ioctl(fd, DIOCWLABEL, &flag); 746100616Smp#endif 74759243Sobrien } 74859243Sobrien return(0); 74959243Sobrien} 75059243Sobrien 751131962Smp 752131962Smpstatic int 75359243Sobrienok(str) 75459243Sobrienchar *str; 75559243Sobrien{ 75659243Sobrien printf("%s [n] ", str); 75759243Sobrien fgets(lbuf, LBUF, stdin); 75859243Sobrien lbuf[strlen(lbuf)-1] = 0; 75959243Sobrien 76059243Sobrien if (*lbuf && 76159243Sobrien (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 76259243Sobrien !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 76359243Sobrien return 1; 76459243Sobrien else 76559243Sobrien return 0; 76659243Sobrien} 76759243Sobrien 76859243Sobrienstatic int 76959243Sobriendecimal(char *str, int *num, int deflt) 77059243Sobrien{ 77183098Smpint acc = 0, c; 77283098Smpchar *cp; 77359243Sobrien 77459243Sobrien while (1) { 77559243Sobrien printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 77659243Sobrien fgets(lbuf, LBUF, stdin); 77759243Sobrien lbuf[strlen(lbuf)-1] = 0; 77859243Sobrien 77959243Sobrien if (!*lbuf) 78059243Sobrien return 0; 78159243Sobrien 78259243Sobrien cp = lbuf; 78359243Sobrien while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 78469408Sache if (!c) 785145479Smp return 0; 78669408Sache while ((c = *cp++)) { 78769408Sache if (c <= '9' && c >= '0') 78859243Sobrien acc = acc * 10 + c - '0'; 78959243Sobrien else 79059243Sobrien break; 79159243Sobrien } 792145479Smp if (c == ' ' || c == '\t') 79359243Sobrien while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 79459243Sobrien if (!c) { 795145479Smp *num = acc; 796145479Smp return 1; 79759243Sobrien } else 79859243Sobrien printf("%s is an invalid decimal number. Try again\n", 79959243Sobrien lbuf); 80059243Sobrien } 80159243Sobrien 80259243Sobrien} 80359243Sobrien 80459243Sobrien#if 0 80559243Sobrienstatic int 80659243Sobrienhex(char *str, int *num, int deflt) 80759243Sobrien{ 80859243Sobrienint acc = 0, c; 80959243Sobrienchar *cp; 81059243Sobrien 81159243Sobrien while (1) { 81259243Sobrien printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 81359243Sobrien fgets(lbuf, LBUF, stdin); 814145479Smp lbuf[strlen(lbuf)-1] = 0; 81559243Sobrien 81659243Sobrien if (!*lbuf) 81759243Sobrien return 0; 81859243Sobrien 81959243Sobrien cp = lbuf; 82059243Sobrien while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 82159243Sobrien if (!c) 82259243Sobrien return 0; 823145479Smp while ((c = *cp++)) { 82459243Sobrien if (c <= '9' && c >= '0') 825145479Smp acc = (acc << 4) + c - '0'; 826145479Smp else if (c <= 'f' && c >= 'a') 82759243Sobrien acc = (acc << 4) + c - 'a' + 10; 82859243Sobrien else if (c <= 'F' && c >= 'A') 82959243Sobrien acc = (acc << 4) + c - 'A' + 10; 83059243Sobrien else 83159243Sobrien break; 83259243Sobrien } 83359243Sobrien if (c == ' ' || c == '\t') 83459243Sobrien while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 83559243Sobrien if (!c) { 83659243Sobrien *num = acc; 83759243Sobrien return 1; 83859243Sobrien } else 83959243Sobrien printf("%s is an invalid hex number. Try again\n", 84059243Sobrien lbuf); 84159243Sobrien } 84259243Sobrien 84359243Sobrien} 84459243Sobrien 84559243Sobrienstatic int 84659243Sobrienstring(char *str, char **ans) 84759243Sobrien{ 84859243Sobrienint c; 84959243Sobrienchar *cp = lbuf; 85059243Sobrien 85159243Sobrien while (1) { 85259243Sobrien printf("Supply a string value for \"%s\" [%s] ", str, *ans); 85359243Sobrien fgets(lbuf, LBUF, stdin); 85459243Sobrien lbuf[strlen(lbuf)-1] = 0; 85559243Sobrien 85659243Sobrien if (!*lbuf) 85759243Sobrien return 0; 85859243Sobrien 85959243Sobrien while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 86059243Sobrien if (c == '"') { 86159243Sobrien c = *++cp; 86259243Sobrien *ans = cp; 86359243Sobrien while ((c = *cp) && c != '"') cp++; 86459243Sobrien } else { 86559243Sobrien *ans = cp; 86659243Sobrien while ((c = *cp) && c != ' ' && c != '\t') cp++; 86759243Sobrien } 86859243Sobrien 86959243Sobrien if (c) 87059243Sobrien *cp = 0; 87159243Sobrien return 1; 87259243Sobrien } 87359243Sobrien} 87459243Sobrien#endif 87559243Sobrien 876145479Smpstatic char * 87759243Sobrienget_type(int type) 87859243Sobrien{ 879145479Smp int numentries = (sizeof(part_types)/sizeof(struct part_type)); 880145479Smp int counter = 0; 88159243Sobrien struct part_type *ptr = part_types; 88259243Sobrien 88359243Sobrien 88459243Sobrien while(counter < numentries) 88559243Sobrien { 88659243Sobrien if(ptr->type == type) 88759243Sobrien { 88859243Sobrien return(ptr->name); 88959243Sobrien } 890100616Smp ptr++; 89159243Sobrien counter++; 89259243Sobrien } 89359243Sobrien return("unknown"); 89459243Sobrien} 89559243Sobrien 89659243Sobrien 89759243Sobrienstatic void 89859243Sobrienparse_config_line(line, command) 89959243Sobrien char *line; 90059243Sobrien CMD *command; 90159243Sobrien{ 90259243Sobrien char *cp, *end; 90359243Sobrien 90459243Sobrien cp = line; 90559243Sobrien while (1) /* dirty trick used to insure one exit point for this 90659243Sobrien function */ 90759243Sobrien { 90859243Sobrien memset(command, 0, sizeof(*command)); 90959243Sobrien 91059243Sobrien while (isspace(*cp)) ++cp; 91159243Sobrien if (*cp == '\0' || *cp == '#') 91259243Sobrien { 91359243Sobrien break; 91459243Sobrien } 91559243Sobrien command->cmd = *cp++; 91659243Sobrien 91759243Sobrien /* 91859243Sobrien * Parse args 91959243Sobrien */ 92059243Sobrien while (1) 92159243Sobrien { 92259243Sobrien while (isspace(*cp)) ++cp; 92359243Sobrien if (*cp == '#') 92459243Sobrien { 92559243Sobrien break; /* found comment */ 92659243Sobrien } 92759243Sobrien if (isalpha(*cp)) 92859243Sobrien { 92959243Sobrien command->args[command->n_args].argtype = *cp++; 93059243Sobrien } 93159243Sobrien if (!isdigit(*cp)) 93259243Sobrien { 93359243Sobrien break; /* assume end of line */ 93459243Sobrien } 93559243Sobrien end = NULL; 93659243Sobrien command->args[command->n_args].arg_val = strtol(cp, &end, 0); 93759243Sobrien if (cp == end) 93859243Sobrien { 93959243Sobrien break; /* couldn't parse number */ 94059243Sobrien } 94159243Sobrien cp = end; 94259243Sobrien command->n_args++; 94359243Sobrien } 94459243Sobrien break; 94559243Sobrien } 94659243Sobrien} 94759243Sobrien 94859243Sobrien 94959243Sobrienstatic int 95059243Sobrienprocess_geometry(command) 95159243Sobrien CMD *command; 95259243Sobrien{ 95359243Sobrien int status = 1, i; 95459243Sobrien 95559243Sobrien while (1) 95659243Sobrien { 95759243Sobrien geom_processed = 1; 95859243Sobrien if (part_processed) 95959243Sobrien { 96059243Sobrien fprintf(stderr, 96159243Sobrien "%s: ERROR line %d: the geometry specification line must occur before\n\ 96259243Sobrien all partition specifications.\n", 96359243Sobrien name, current_line_number); 96459243Sobrien status = 0; 96559243Sobrien break; 96659243Sobrien } 96759243Sobrien if (command->n_args != 3) 96859243Sobrien { 96959243Sobrien fprintf(stderr, 97059243Sobrien "%s: ERROR line %d: incorrect number of geometry args\n", 97159243Sobrien name, current_line_number); 972145479Smp status = 0; 973145479Smp break; 97459243Sobrien } 975145479Smp dos_cyls = -1; 97659243Sobrien dos_heads = -1; 97759243Sobrien dos_sectors = -1; 978145479Smp for (i = 0; i < 3; ++i) 97959243Sobrien { 980145479Smp switch (command->args[i].argtype) 98159243Sobrien { 98259243Sobrien case 'c': 98359243Sobrien dos_cyls = command->args[i].arg_val; 98459243Sobrien break; 98559243Sobrien case 'h': 98659243Sobrien dos_heads = command->args[i].arg_val; 98759243Sobrien break; 98859243Sobrien case 's': 98959243Sobrien dos_sectors = command->args[i].arg_val; 99059243Sobrien break; 99159243Sobrien default: 99259243Sobrien fprintf(stderr, 99359243Sobrien "%s: ERROR line %d: unknown geometry arg type: '%c' (0x%02x)\n", 99459243Sobrien name, current_line_number, command->args[i].argtype, 99559243Sobrien command->args[i].argtype); 99659243Sobrien status = 0; 99759243Sobrien break; 99859243Sobrien } 99959243Sobrien } 100059243Sobrien if (status == 0) 100159243Sobrien { 100259243Sobrien break; 100359243Sobrien } 100459243Sobrien 100559243Sobrien dos_cylsecs = dos_heads * dos_sectors; 100659243Sobrien 100759243Sobrien /* 100859243Sobrien * Do sanity checks on parameter values 100959243Sobrien */ 101059243Sobrien if (dos_cyls < 0) 101159243Sobrien { 101259243Sobrien fprintf(stderr, 101359243Sobrien "%s: ERROR line %d: number of cylinders not specified\n", 101459243Sobrien name, current_line_number); 101559243Sobrien status = 0; 101659243Sobrien } 101759243Sobrien if (dos_cyls == 0 || dos_cyls > 1024) 101859243Sobrien { 101959243Sobrien fprintf(stderr, 102059243Sobrien "%s: WARNING line %d: number of cylinders (%d) may be out-of-range\n\ 102159243Sobrien (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\ 102259243Sobrien is dedicated to FreeBSD).\n", 102359243Sobrien name, current_line_number, dos_cyls); 102459243Sobrien } 102559243Sobrien 102659243Sobrien if (dos_heads < 0) 102759243Sobrien { 102859243Sobrien fprintf(stderr, 102959243Sobrien "%s: ERROR line %d: number of heads not specified\n", 103059243Sobrien name, current_line_number); 103159243Sobrien status = 0; 103259243Sobrien } 103359243Sobrien else if (dos_heads < 1 || dos_heads > 256) 103459243Sobrien { 103559243Sobrien fprintf(stderr, 103659243Sobrien "%s: ERROR line %d: number of heads must be within (1-256)\n", 103759243Sobrien name, current_line_number); 103859243Sobrien status = 0; 103959243Sobrien } 104059243Sobrien 104159243Sobrien if (dos_sectors < 0) 104259243Sobrien { 104359243Sobrien fprintf(stderr, "%s: ERROR line %d: number of sectors not specified\n", 104459243Sobrien name, current_line_number); 104559243Sobrien status = 0; 104659243Sobrien } 104759243Sobrien else if (dos_sectors < 1 || dos_sectors > 63) 104859243Sobrien { 104959243Sobrien fprintf(stderr, 105059243Sobrien "%s: ERROR line %d: number of sectors must be within (1-63)\n", 105159243Sobrien name, current_line_number); 105259243Sobrien status = 0; 105359243Sobrien } 105459243Sobrien 105559243Sobrien break; 105659243Sobrien } 105759243Sobrien return (status); 105859243Sobrien} 105959243Sobrien 106059243Sobrien 106159243Sobrienstatic int 106259243Sobrienprocess_partition(command) 106359243Sobrien CMD *command; 106459243Sobrien{ 106559243Sobrien int status = 0, partition; 106659243Sobrien unsigned long chunks, adj_size, max_end; 106759243Sobrien struct dos_partition *partp; 106859243Sobrien 106959243Sobrien while (1) 107059243Sobrien { 107159243Sobrien part_processed = 1; 107259243Sobrien if (command->n_args != 4) 107359243Sobrien { 107459243Sobrien fprintf(stderr, 107559243Sobrien "%s: ERROR line %d: incorrect number of partition args\n", 107659243Sobrien name, current_line_number); 1077145479Smp break; 107859243Sobrien } 107959243Sobrien partition = command->args[0].arg_val; 1080145479Smp if (partition < 0 || partition > 3) 1081145479Smp { 108259243Sobrien fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n", 108359243Sobrien name, current_line_number, partition); 108459243Sobrien break; 108559243Sobrien } 108659243Sobrien partp = ((struct dos_partition *) &mboot.parts) + partition; 108759243Sobrien bzero((char *)partp, sizeof (struct dos_partition)); 108859243Sobrien partp->dp_typ = command->args[1].arg_val; 108959243Sobrien partp->dp_start = command->args[2].arg_val; 109059243Sobrien partp->dp_size = command->args[3].arg_val; 109159243Sobrien max_end = partp->dp_start + partp->dp_size; 109259243Sobrien 109359243Sobrien if (partp->dp_typ == 0) 109459243Sobrien { 109559243Sobrien /* 109659243Sobrien * Get out, the partition is marked as unused. 109759243Sobrien */ 109859243Sobrien /* 109959243Sobrien * Insure that it's unused. 110059243Sobrien */ 110159243Sobrien bzero((char *)partp, sizeof (struct dos_partition)); 110259243Sobrien status = 1; 110359243Sobrien break; 110459243Sobrien } 110559243Sobrien 110659243Sobrien /* 110759243Sobrien * Adjust start upwards, if necessary, to fall on an head boundary. 110859243Sobrien */ 110959243Sobrien if (partp->dp_start % dos_sectors != 0) 111059243Sobrien { 111159243Sobrien adj_size = 111259243Sobrien (partp->dp_start / dos_sectors + 1) * dos_sectors; 111359243Sobrien if (adj_size > max_end) 111459243Sobrien { 111559243Sobrien /* 111659243Sobrien * Can't go past end of partition 111759243Sobrien */ 111859243Sobrien fprintf(stderr, 1119145479Smp "%s: ERROR line %d: unable to adjust start of partition %d to fall on\n\ 112059243Sobrien a cylinder boundary.\n", 112159243Sobrien name, current_line_number, partition); 112259243Sobrien break; 112359243Sobrien } 112459243Sobrien fprintf(stderr, 112559243Sobrien "%s: WARNING: adjusting start offset of partition '%d' from %d\n\ 112659243Sobrien to %d, to round to an head boundary.\n", 112759243Sobrien name, partition, partp->dp_start, adj_size); 112859243Sobrien partp->dp_start = adj_size; 112959243Sobrien } 113059243Sobrien 113159243Sobrien /* 1132145479Smp * Adjust size downwards, if necessary, to fall on a cylinder 113359243Sobrien * boundary. 1134145479Smp */ 113559243Sobrien chunks = 1136145479Smp ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs; 113783098Smp adj_size = chunks - partp->dp_start; 1138145479Smp if (adj_size != partp->dp_size) 1139100616Smp { 114059243Sobrien fprintf(stderr, 114159243Sobrien "%s: WARNING: adjusting size of partition '%d' from %d to %d,\n\ 114259243Sobrien to round to a cylinder boundary.\n", 114359243Sobrien name, partition, partp->dp_size, adj_size); 114459243Sobrien if (chunks > 0) 114559243Sobrien { 114659243Sobrien partp->dp_size = adj_size; 114759243Sobrien } 114859243Sobrien else 114959243Sobrien { 115059243Sobrien partp->dp_size = 0; 115159243Sobrien } 115259243Sobrien } 115359243Sobrien if (partp->dp_size < 1) 115459243Sobrien { 115559243Sobrien fprintf(stderr, 115659243Sobrien "%s: ERROR line %d: size for partition '%d' is zero.\n", 115759243Sobrien name, current_line_number, partition); 115859243Sobrien break; 115959243Sobrien } 116059243Sobrien 116159243Sobrien dos(partp->dp_start, partp->dp_size, 116259243Sobrien &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 116359243Sobrien dos(partp->dp_start+partp->dp_size - 1, partp->dp_size, 116483098Smp &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 116583098Smp status = 1; 116683098Smp break; 116783098Smp } 116883098Smp return (status); 1169100616Smp} 1170100616Smp 1171100616Smp 1172100616Smpstatic int 1173100616Smpprocess_active(command) 117459243Sobrien CMD *command; 117559243Sobrien{ 117659243Sobrien int status = 0, partition, i; 117759243Sobrien struct dos_partition *partp; 117859243Sobrien 117959243Sobrien while (1) 118059243Sobrien { 118159243Sobrien active_processed = 1; 118259243Sobrien if (command->n_args != 1) 118359243Sobrien { 118459243Sobrien fprintf(stderr, 118559243Sobrien "%s: ERROR line %d: incorrect number of active args\n", 118659243Sobrien name, current_line_number); 118759243Sobrien status = 0; 118859243Sobrien break; 118959243Sobrien } 119059243Sobrien partition = command->args[0].arg_val; 119159243Sobrien if (partition < 0 || partition > 3) 119259243Sobrien { 119359243Sobrien fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n", 119459243Sobrien name, current_line_number, partition); 119559243Sobrien break; 119659243Sobrien } 119759243Sobrien /* 119859243Sobrien * Reset active partition 119959243Sobrien */ 120059243Sobrien partp = ((struct dos_partition *) &mboot.parts); 120159243Sobrien for (i = 0; i < NDOSPART; i++) 120259243Sobrien partp[i].dp_flag = 0; 120359243Sobrien partp[partition].dp_flag = ACTIVE; 120459243Sobrien 120559243Sobrien status = 1; 120659243Sobrien break; 120759243Sobrien } 120859243Sobrien return (status); 120959243Sobrien} 121059243Sobrien 121159243Sobrien 121259243Sobrienstatic int 121359243Sobrienprocess_line(line) 121459243Sobrien char *line; 121559243Sobrien{ 121659243Sobrien CMD command; 121759243Sobrien int status = 1; 121859243Sobrien 121959243Sobrien while (1) 122059243Sobrien { 122159243Sobrien parse_config_line(line, &command); 122259243Sobrien switch (command.cmd) 122359243Sobrien { 122459243Sobrien case 0: 122559243Sobrien /* 122659243Sobrien * Comment or blank line 122759243Sobrien */ 122859243Sobrien break; 122959243Sobrien case 'g': 123059243Sobrien /* 123159243Sobrien * Set geometry 123259243Sobrien */ 123359243Sobrien status = process_geometry(&command); 123459243Sobrien break; 123559243Sobrien case 'p': 123659243Sobrien status = process_partition(&command); 123759243Sobrien break; 123859243Sobrien case 'a': 123959243Sobrien status = process_active(&command); 124059243Sobrien break; 124159243Sobrien default: 124259243Sobrien status = 0; 124359243Sobrien break; 124459243Sobrien } 1245145479Smp break; 1246145479Smp } 1247145479Smp return (status); 1248145479Smp} 1249145479Smp 1250145479Smp 1251131962Smpstatic int 1252145479Smpread_config(config_file) 1253131962Smp char *config_file; 1254145479Smp{ 1255145479Smp FILE *fp = NULL; 1256145479Smp int status = 1; 1257145479Smp char buf[1010]; 125859243Sobrien 125959243Sobrien while (1) /* dirty trick used to insure one exit point for this 1260145479Smp function */ 1261145479Smp { 1262145479Smp if (strcmp(config_file, "-") != 0) 1263145479Smp { 1264145479Smp /* 1265145479Smp * We're not reading from stdin 1266145479Smp */ 1267145479Smp if ((fp = fopen(config_file, "r")) == NULL) 1268145479Smp { 126959243Sobrien status = 0; 1270145479Smp break; 1271145479Smp } 1272145479Smp } 1273145479Smp else 1274145479Smp { 1275145479Smp fp = stdin; 1276145479Smp } 1277145479Smp current_line_number = 0; 1278145479Smp while (!feof(fp)) 1279145479Smp { 1280145479Smp if (fgets(buf, sizeof(buf), fp) == NULL) 1281145479Smp { 1282145479Smp break; 128359243Sobrien } 128459243Sobrien ++current_line_number; 128559243Sobrien status = process_line(buf); 128659243Sobrien if (status == 0) 1287131962Smp { 1288145479Smp break; 128959243Sobrien } 129059243Sobrien } 129159243Sobrien break; 129259243Sobrien } 129359243Sobrien if (fp) 129459243Sobrien { 129559243Sobrien /* 1296 * It doesn't matter if we're reading from stdin, as we've reached EOF 1297 */ 1298 fclose(fp); 1299 } 1300 return (status); 1301} 1302 1303 1304static void 1305reset_boot(void) 1306{ 1307 int i; 1308 struct dos_partition *partp; 1309 1310 init_boot(); 1311 for (i = 0; i < 4; ++i) 1312 { 1313 partp = ((struct dos_partition *) &mboot.parts) + i; 1314 bzero((char *)partp, sizeof (struct dos_partition)); 1315 } 1316} 1317