fdisk.c revision 104459
158234Skato/* 258234Skato * Mach Operating System 358234Skato * Copyright (c) 1992 Carnegie Mellon University 458234Skato * All Rights Reserved. 558234Skato * 658234Skato * Permission to use, copy, modify and distribute this software and its 758234Skato * documentation is hereby granted, provided that both the copyright 858234Skato * notice and this permission notice appear in all copies of the 958234Skato * software, derivative works or modified versions, and any portions 1058234Skato * thereof, and that both notices appear in supporting documentation. 1158234Skato * 1258234Skato * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 1358234Skato * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 1458234Skato * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 1558234Skato * 1658234Skato * Carnegie Mellon requests users of this software to return to 1758234Skato * 1858234Skato * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 1958234Skato * School of Computer Science 2058234Skato * Carnegie Mellon University 2158234Skato * Pittsburgh PA 15213-3890 2258234Skato * 2358234Skato * any improvements or extensions that they make and grant Carnegie Mellon 2458234Skato * the rights to redistribute these changes. 2558234Skato */ 2658234Skato 2758234Skato#ifndef lint 2858234Skatostatic const char rcsid[] = 2958234Skato "$FreeBSD: head/sbin/fdisk_pc98/fdisk.c 104459 2002-10-04 14:05:00Z nyan $"; 3058234Skato#endif /* not lint */ 3158234Skato 3258234Skato#include <sys/disklabel.h> 33104459Snyan#include <sys/diskpc98.h> 3458234Skato#include <sys/stat.h> 3558234Skato#include <ctype.h> 3658234Skato#include <fcntl.h> 3758234Skato#include <err.h> 3858234Skato#include <errno.h> 3969793Sobrien#include <paths.h> 4058234Skato#include <stdio.h> 4158234Skato#include <stdlib.h> 4258234Skato#include <string.h> 4358234Skato#include <unistd.h> 4458234Skato 4558234Skatoint iotest; 4658234Skato 4758234Skato#define LBUF 100 4858234Skatostatic char lbuf[LBUF]; 4958234Skato 5058234Skato/* 5158234Skato * 5258234Skato * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 5358234Skato * 5458234Skato * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 5558234Skato * Copyright (c) 1989 Robert. V. Baron 5658234Skato * Created. 5758234Skato */ 5858234Skato 5958234Skato#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 6058234Skato#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp 6158234Skato#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 6258234Skato 6358234Skato#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 6458234Skato 6558234Skato#define MAX_SEC_SIZE 2048 /* maximum section size that is supported */ 6658234Skato#define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 6758234Skatoint secsize = 0; /* the sensed sector size */ 6858234Skato 6958234Skatoconst char *disk; 7058234Skatoconst char *disks[] = 7158234Skato{ 7261278Snyan "/dev/ad0", "/dev/wd0", "/dev/da0", "/dev/od0", 0 7358234Skato}; 7458234Skato 7558234Skatostruct disklabel disklabel; /* disk parameters */ 7658234Skato 7758234Skatoint cyls, sectors, heads, cylsecs, disksecs; 7858234Skato 7958234Skatostruct mboot 8058234Skato{ 8158234Skato unsigned char padding[2]; /* force the longs to be long aligned */ 8258234Skato#ifdef PC98 8358234Skato unsigned char bootinst[510]; 8458234Skato#else 8558234Skato unsigned char bootinst[DOSPARTOFF]; 8658234Skato struct dos_partition parts[4]; 8758234Skato#endif 8858234Skato unsigned short int signature; 8958234Skato 9058234Skato#ifdef PC98 9158234Skato struct dos_partition parts[8]; 9258234Skato#endif 9358234Skato /* room to read in MBRs that are bigger then DEV_BSIZE */ 9458234Skato unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE]; 9558234Skato}; 9658234Skatostruct mboot mboot; 9758234Skato 9858234Skato#define ACTIVE 0x80 9958234Skato#define BOOT_MAGIC 0xAA55 10058234Skato 10158234Skatoint dos_cyls; 10258234Skatoint dos_heads; 10358234Skatoint dos_sectors; 10458234Skatoint dos_cylsecs; 10558234Skato 10658234Skato#ifdef PC98 10758234Skato#define DOSSECT(s,c) (s) 10858234Skato#define DOSCYL(c) (c) 10958234Skato#else 11058234Skato#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0)) 11158234Skato#define DOSCYL(c) (c & 0xff) 11258234Skato#endif 11358234Skatostatic int partition = -1; 11458234Skato 11558234Skato 11658234Skato#define MAX_ARGS 10 11758234Skato 11858234Skatostatic int current_line_number; 11958234Skato 12058234Skatostatic int geom_processed = 0; 12158234Skatostatic int part_processed = 0; 12258234Skatostatic int active_processed = 0; 12358234Skato 12458234Skato 12558234Skatotypedef struct cmd { 12658234Skato char cmd; 12758234Skato int n_args; 12858234Skato struct arg { 12958234Skato char argtype; 13058234Skato int arg_val; 13158234Skato } args[MAX_ARGS]; 13258234Skato} CMD; 13358234Skato 13458234Skato 13558234Skatostatic int B_flag = 0; /* replace boot code */ 13658234Skatostatic int I_flag = 0; /* use entire disk for FreeBSD */ 13758234Skatostatic int a_flag = 0; /* set active partition */ 13858234Skatostatic char *b_flag = NULL; /* path to boot code */ 13958234Skatostatic int i_flag = 0; /* replace partition data */ 14058234Skatostatic int u_flag = 0; /* update partition data */ 14158234Skatostatic int s_flag = 0; /* Print a summary and exit */ 14258234Skatostatic int t_flag = 0; /* test only, if f_flag is given */ 14358234Skatostatic char *f_flag = NULL; /* Read config info from file */ 14458234Skatostatic int v_flag = 0; /* Be verbose */ 14558234Skato 14658234Skatostruct part_type 14758234Skato{ 14858234Skato unsigned char type; 14958234Skato char *name; 15058234Skato}part_types[] = 15158234Skato{ 15258234Skato {0x00, "unused"} 15358234Skato ,{0x01, "Primary DOS with 12 bit FAT"} 15458234Skato#ifdef PC98 15558234Skato ,{0x11, "MSDOS"} 15658234Skato ,{0x20, "MSDOS"} 15758234Skato ,{0x21, "MSDOS"} 15858234Skato ,{0x22, "MSDOS"} 15958234Skato ,{0x23, "MSDOS"} 160102231Strhodes ,{0x02, "XENIX / file system"} 161102231Strhodes ,{0x03, "XENIX /usr file system"} 16258234Skato ,{0x04, "PC-UX"} 16358234Skato ,{0x05, "Extended DOS"} 16458234Skato ,{0x06, "Primary 'big' DOS (> 32MB)"} 16558234Skato ,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"} 166102231Strhodes ,{0x08, "AIX file system"} 16758234Skato ,{0x09, "AIX boot partition or Coherent"} 16858234Skato ,{0x0A, "OS/2 Boot Manager or OPUS"} 16958234Skato ,{0x10, "OPUS"} 17058234Skato ,{0x14, "FreeBSD/NetBSD/386BSD"} 17158234Skato ,{0x94, "FreeBSD/NetBSD/386BSD"} 17258234Skato ,{0x40, "VENIX 286"} 17358234Skato ,{0x50, "DM"} 17458234Skato ,{0x51, "DM"} 17558234Skato ,{0x52, "CP/M or Microport SysV/AT"} 17658234Skato ,{0x56, "GB"} 17758234Skato ,{0x61, "Speed"} 17858234Skato ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 17958234Skato ,{0x64, "Novell Netware 2.xx"} 18058234Skato ,{0x65, "Novell Netware 3.xx"} 18158234Skato ,{0x75, "PCIX"} 18258234Skato ,{0x40, "Minix"} 18358234Skato#else 184102231Strhodes ,{0x02, "XENIX / file system"} 185102231Strhodes ,{0x03, "XENIX /usr file system"} 18658234Skato ,{0x04, "Primary DOS with 16 bit FAT (<= 32MB)"} 18758234Skato ,{0x05, "Extended DOS"} 18858234Skato ,{0x06, "Primary 'big' DOS (> 32MB)"} 18958234Skato ,{0x07, "OS/2 HPFS, NTFS, QNX or Advanced UNIX"} 190102231Strhodes ,{0x08, "AIX file system"} 19158234Skato ,{0x09, "AIX boot partition or Coherent"} 19258234Skato ,{0x0A, "OS/2 Boot Manager or OPUS"} 19358234Skato ,{0x0B, "DOS or Windows 95 with 32 bit FAT"} 19458234Skato ,{0x0C, "DOS or Windows 95 with 32 bit FAT, LBA"} 19558234Skato ,{0x0E, "Primary 'big' DOS (> 32MB, LBA)"} 19658234Skato ,{0x0F, "Extended DOS, LBA"} 19758234Skato ,{0x10, "OPUS"} 19858234Skato ,{0x40, "VENIX 286"} 19958234Skato ,{0x50, "DM"} 20058234Skato ,{0x51, "DM"} 20158234Skato ,{0x52, "CP/M or Microport SysV/AT"} 20258234Skato ,{0x56, "GB"} 20358234Skato ,{0x61, "Speed"} 20458234Skato ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 20558234Skato ,{0x64, "Novell Netware 2.xx"} 20658234Skato ,{0x65, "Novell Netware 3.xx"} 20758234Skato ,{0x75, "PCIX"} 20858234Skato ,{0x80, "Minix 1.1 ... 1.4a"} 20958234Skato ,{0x81, "Minix 1.4b ... 1.5.10"} 21058234Skato ,{0x82, "Linux swap or Solaris x86"} 211102231Strhodes ,{0x83, "Linux file system"} 212102231Strhodes ,{0x93, "Amoeba file system"} 21358234Skato ,{0x94, "Amoeba bad block table"} 21458234Skato ,{0x9F, "BSD/OS"} 21558234Skato ,{0xA5, "FreeBSD/NetBSD/386BSD"} 21658234Skato ,{0xA6, "OpenBSD"} 21758234Skato ,{0xA7, "NEXTSTEP"} 21858234Skato ,{0xA9, "NetBSD"} 219102231Strhodes ,{0xB7, "BSDI BSD/386 file system"} 22058234Skato ,{0xB8, "BSDI BSD/386 swap"} 22158234Skato ,{0xDB, "Concurrent CPM or C.DOS or CTOS"} 22258234Skato ,{0xE1, "Speed"} 22358234Skato ,{0xE3, "Speed"} 22458234Skato ,{0xE4, "Speed"} 22558234Skato ,{0xF1, "Speed"} 22658234Skato ,{0xF2, "DOS 3.3+ Secondary"} 22758234Skato ,{0xF4, "Speed"} 22858234Skato ,{0xFF, "BBT (Bad Blocks Table)"} 22958234Skato#endif 23058234Skato}; 23158234Skato 23258234Skatostatic void print_s0(int which); 23358234Skatostatic void print_part(int i); 23458234Skatostatic void init_sector0(unsigned long start); 23558234Skatostatic void init_boot(void); 23658234Skatostatic void change_part(int i); 23758234Skatostatic void print_params(); 23858234Skatostatic void change_active(int which); 23958234Skatostatic void change_code(); 24058234Skatostatic void get_params_to_use(); 24158234Skato#ifdef PC98 24258234Skatostatic void dos(int sec, int size, unsigned short *c, unsigned char *s, 24358234Skato unsigned char *h); 24458234Skato#else 24558234Skatostatic void dos(int sec, int size, unsigned char *c, unsigned char *s, 24658234Skato unsigned char *h); 24758234Skato#endif 24858234Skatostatic int open_disk(int u_flag); 24958234Skatostatic ssize_t read_disk(off_t sector, void *buf); 25058234Skatostatic ssize_t write_disk(off_t sector, void *buf); 25158234Skatostatic int get_params(); 25258234Skatostatic int read_s0(); 25358234Skatostatic int write_s0(); 25458234Skatostatic int ok(char *str); 25558234Skatostatic int decimal(char *str, int *num, int deflt); 25658234Skatostatic char *get_type(int type); 25758234Skatostatic int read_config(char *config_file); 25858234Skatostatic void reset_boot(void); 25958234Skatostatic void usage(void); 26058234Skato#if 0 26158234Skatostatic int hex(char *str, int *num, int deflt); 26258234Skato#endif 26358234Skato#ifdef PC98 26458234Skatostatic int string(char *str, char **ans); 26558234Skato#endif 26658234Skato 26758234Skato 26858234Skato 26958234Skatoint 27058234Skatomain(int argc, char *argv[]) 27158234Skato{ 27258234Skato int c, i; 27358234Skato 27458234Skato#ifdef PC98 27558234Skato while ((c = getopt(argc, argv, "Bab:f:istuv12345678")) != -1) 27658234Skato#else 27758234Skato while ((c = getopt(argc, argv, "BIab:f:istuv1234")) != -1) 27858234Skato#endif 27958234Skato switch (c) { 28058234Skato case 'B': 28158234Skato B_flag = 1; 28258234Skato break; 28358234Skato case 'I': 28458234Skato I_flag = 1; 28558234Skato break; 28658234Skato case 'a': 28758234Skato a_flag = 1; 28858234Skato break; 28958234Skato case 'b': 29058234Skato b_flag = optarg; 29158234Skato break; 29258234Skato case 'f': 29358234Skato f_flag = optarg; 29458234Skato break; 29558234Skato case 'i': 29658234Skato i_flag = 1; 29758234Skato break; 29858234Skato case 's': 29958234Skato s_flag = 1; 30058234Skato break; 30158234Skato case 't': 30258234Skato t_flag = 1; 30358234Skato break; 30458234Skato case 'u': 30558234Skato u_flag = 1; 30658234Skato break; 30758234Skato case 'v': 30858234Skato v_flag = 1; 30958234Skato break; 31058234Skato case '1': 31158234Skato case '2': 31258234Skato case '3': 31358234Skato case '4': 31458234Skato#ifdef PC98 31558234Skato case '5': 31658234Skato case '6': 31758234Skato case '7': 31858234Skato case '8': 31958234Skato#endif 32058234Skato partition = c - '0'; 32158234Skato break; 32258234Skato default: 32358234Skato usage(); 32458234Skato } 32558234Skato if (f_flag || i_flag) 32658234Skato u_flag = 1; 32758234Skato if (t_flag) 32858234Skato v_flag = 1; 32958234Skato argc -= optind; 33058234Skato argv += optind; 33158234Skato 33258234Skato if (argc > 0) 33358234Skato { 33458234Skato static char realname[12]; 33558234Skato 33669793Sobrien if(strncmp(argv[0], _PATH_DEV, sizeof _PATH_DEV - 2) == 0) 33758234Skato disk = argv[0]; 33858234Skato else 33958234Skato { 34069793Sobrien snprintf(realname, 12, "%s%s", _PATH_DEV, argv[0]); 34158234Skato disk = realname; 34258234Skato } 34358234Skato 34458234Skato if (open_disk(u_flag) < 0) 34558234Skato err(1, "cannot open disk %s", disk); 34658234Skato } 34758234Skato else 34858234Skato { 34958234Skato int rv = 0; 35058234Skato 35158234Skato for(i = 0; disks[i]; i++) 35258234Skato { 35358234Skato disk = disks[i]; 35458234Skato rv = open_disk(u_flag); 35558234Skato if(rv != -2) break; 35658234Skato } 35758234Skato if(rv < 0) 35858234Skato err(1, "cannot open any disk"); 35958234Skato } 36058234Skato if (s_flag) 36158234Skato { 36258234Skato int i; 36358234Skato struct dos_partition *partp; 36458234Skato 36558234Skato if (read_s0()) 36658234Skato err(1, "read_s0"); 36758234Skato printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, 36858234Skato dos_sectors); 36958234Skato#ifdef PC98 37058234Skato printf("Part %11s %11s SID\n", "Start", "Size"); 37158234Skato#else 37258234Skato printf("Part %11s %11s Type Flags\n", "Start", "Size"); 37358234Skato#endif 37458234Skato for (i = 0; i < NDOSPART; i++) { 37558234Skato partp = ((struct dos_partition *) &mboot.parts) + i; 37658234Skato#ifdef PC98 37758234Skato if (partp->dp_sid == 0) 37858234Skato#else 37958234Skato if (partp->dp_start == 0 && partp->dp_size == 0) 38058234Skato#endif 38158234Skato continue; 38293266Simp printf("%4d: %11lu %11lu 0x%02x\n", i + 1, 38358234Skato#ifdef PC98 38458234Skato partp->dp_scyl * cylsecs, 38558234Skato (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs, 38658234Skato partp->dp_sid); 38758234Skato#else 38858234Skato (u_long) partp->dp_start, 38958234Skato (u_long) partp->dp_size, partp->dp_typ, 39058234Skato partp->dp_flag); 39158234Skato#endif 39258234Skato } 39358234Skato exit(0); 39458234Skato } 39558234Skato 39658234Skato printf("******* Working on device %s *******\n",disk); 39758234Skato 39858234Skato#ifndef PC98 39958234Skato if (I_flag) 40058234Skato { 40158234Skato struct dos_partition *partp; 40258234Skato 40358234Skato read_s0(); 40458234Skato reset_boot(); 40558234Skato partp = (struct dos_partition *) (&mboot.parts[0]); 40658234Skato partp->dp_typ = DOSPTYP_386BSD; 40758234Skato partp->dp_flag = ACTIVE; 40858234Skato partp->dp_start = dos_sectors; 40958234Skato partp->dp_size = disksecs - dos_sectors; 41058234Skato 41158234Skato dos(partp->dp_start, partp->dp_size, 41258234Skato &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 41358234Skato dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 41458234Skato &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 41558234Skato if (v_flag) 41658234Skato print_s0(-1); 41758234Skato write_s0(); 41858234Skato exit(0); 41958234Skato } 42058234Skato#endif 42158234Skato if (f_flag) 42258234Skato { 42358234Skato#ifndef PC98 42458234Skato if (read_s0() || i_flag) 42558234Skato { 42658234Skato reset_boot(); 42758234Skato } 42858234Skato 42958234Skato if (!read_config(f_flag)) 43058234Skato { 43158234Skato exit(1); 43258234Skato } 43358234Skato#endif 43458234Skato if (v_flag) 43558234Skato { 43658234Skato print_s0(-1); 43758234Skato } 43858234Skato if (!t_flag) 43958234Skato { 44058234Skato write_s0(); 44158234Skato } 44258234Skato } 44358234Skato else 44458234Skato { 44558234Skato if(u_flag) 44658234Skato { 44758234Skato get_params_to_use(); 44858234Skato } 44958234Skato else 45058234Skato { 45158234Skato print_params(); 45258234Skato } 45358234Skato 45458234Skato if (read_s0()) 45558234Skato init_sector0(1); 45658234Skato 45758234Skato printf("Media sector size is %d\n", secsize); 45858234Skato printf("Warning: BIOS sector numbering starts with sector 1\n"); 45958234Skato printf("Information from DOS bootblock is:\n"); 46058234Skato if (partition == -1) 46158234Skato for (i = 1; i <= NDOSPART; i++) 46258234Skato change_part(i); 46358234Skato else 46458234Skato change_part(partition); 46558234Skato 46658234Skato if (u_flag || a_flag) 46758234Skato change_active(partition); 46858234Skato 46958234Skato if (B_flag) 47058234Skato change_code(); 47158234Skato 47258234Skato if (u_flag || a_flag || B_flag) { 47358234Skato if (!t_flag) 47458234Skato { 47558234Skato printf("\nWe haven't changed the partition table yet. "); 47658234Skato printf("This is your last chance.\n"); 47758234Skato } 47858234Skato print_s0(-1); 47958234Skato if (!t_flag) 48058234Skato { 48158234Skato if (ok("Should we write new partition table?")) 48258234Skato write_s0(); 48358234Skato } 48458234Skato else 48558234Skato { 48658234Skato printf("\n-t flag specified -- partition table not written.\n"); 48758234Skato } 48858234Skato } 48958234Skato } 49058234Skato 49158234Skato exit(0); 49258234Skato} 49358234Skato 49458234Skatostatic void 49558234Skatousage() 49658234Skato{ 49758234Skato fprintf(stderr, "%s%s", 49858234Skato "usage: fdisk [-Batu] [-b bootcode] [-12345678] [disk]\n", 49958234Skato " fdisk -f configfile [-itv] [disk]\n"); 50058234Skato exit(1); 50158234Skato} 50258234Skato 50358234Skatostatic void 50458234Skatoprint_s0(int which) 50558234Skato{ 50658234Skatoint i; 50758234Skato 50858234Skato print_params(); 50958234Skato printf("Information from DOS bootblock is:\n"); 51058234Skato if (which == -1) 51158234Skato for (i = 1; i <= NDOSPART; i++) 51258234Skato printf("%d: ", i), print_part(i); 51358234Skato else 51458234Skato print_part(which); 51558234Skato} 51658234Skato 51758234Skatostatic struct dos_partition mtpart = { 0 }; 51858234Skato 51958234Skatostatic void 52058234Skatoprint_part(int i) 52158234Skato{ 52258234Skato struct dos_partition *partp; 52358234Skato u_int64_t part_mb; 52458234Skato 52558234Skato partp = ((struct dos_partition *) &mboot.parts) + i - 1; 52658234Skato 52758234Skato if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) { 52858234Skato printf("<UNUSED>\n"); 52958234Skato return; 53058234Skato } 53158234Skato /* 53258234Skato * Be careful not to overflow. 53358234Skato */ 53458234Skato#ifdef PC98 53558234Skato printf("sysmid %d,(%s)\n", partp->dp_mid, get_type(partp->dp_mid)); 53658234Skato printf(" start %d, size %d (%d Meg), sid %d\n", 53758234Skato partp->dp_scyl * cylsecs , 53858234Skato (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs, 53958234Skato (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs * 512 / (1024 * 1024), 54058234Skato partp->dp_sid); 54158234Skato#else 54258234Skato part_mb = partp->dp_size; 54358234Skato part_mb *= secsize; 54458234Skato part_mb /= (1024 * 1024); 54558234Skato printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ)); 54658234Skato printf(" start %lu, size %lu (%qd Meg), flag %x%s\n", 54758234Skato (u_long)partp->dp_start, 54858234Skato (u_long)partp->dp_size, 54958234Skato part_mb, 55058234Skato partp->dp_flag, 55158234Skato partp->dp_flag == ACTIVE ? " (active)" : ""); 55258234Skato#endif 55358234Skato printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n" 55458234Skato ,DPCYL(partp->dp_scyl, partp->dp_ssect) 55558234Skato ,DPSECT(partp->dp_ssect) 55658234Skato ,partp->dp_shd 55758234Skato ,DPCYL(partp->dp_ecyl, partp->dp_esect) 55858234Skato ,DPSECT(partp->dp_esect) 55958234Skato ,partp->dp_ehd); 56058234Skato#ifdef PC98 56158234Skato printf ("\tsystem Name %.16s\n",partp->dp_name); 56258234Skato#endif 56358234Skato} 56458234Skato 56558234Skato 56658234Skatostatic void 56758234Skatoinit_boot(void) 56858234Skato{ 56958234Skato#ifndef PC98 57058234Skato const char *fname; 57158234Skato int fd; 57258234Skato 57358234Skato fname = b_flag ? b_flag : "/boot/mbr"; 57458234Skato if ((fd = open(fname, O_RDONLY)) == -1 || 57558234Skato read(fd, mboot.bootinst, DOSPARTOFF) == -1 || 57658234Skato close(fd)) 57758234Skato err(1, "%s", fname); 57858234Skato#endif 57958234Skato mboot.signature = BOOT_MAGIC; 58058234Skato} 58158234Skato 58258234Skato 58358234Skatostatic void 58458234Skatoinit_sector0(unsigned long start) 58558234Skato{ 58658234Skatostruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); 58758234Skatounsigned long size = disksecs - start; 58858234Skato 58958234Skato init_boot(); 59058234Skato 59158234Skato#ifdef PC98 59258234Skato partp->dp_mid = DOSMID_386BSD; 59358234Skato partp->dp_sid = DOSSID_386BSD; 59458234Skato 59558234Skato dos(start, size, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 59658234Skato partp->dp_ipl_cyl = partp->dp_scyl; 59758234Skato partp->dp_ipl_sct = partp->dp_ssect; 59858234Skato partp->dp_ipl_head = partp->dp_shd; 59958234Skato dos(start+size-cylsecs, size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 60058234Skato#else 60158234Skato partp->dp_typ = DOSPTYP_386BSD; 60258234Skato partp->dp_flag = ACTIVE; 60358234Skato partp->dp_start = start; 60458234Skato partp->dp_size = size; 60558234Skato 60658234Skato dos(partp->dp_start, partp->dp_size, 60758234Skato &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 60858234Skato dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 60958234Skato &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 61058234Skato#endif 61158234Skato} 61258234Skato 61358234Skatostatic void 61458234Skatochange_part(int i) 61558234Skato{ 61658234Skatostruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1; 61758234Skato 61858234Skato printf("The data for partition %d is:\n", i); 61958234Skato print_part(i); 62058234Skato 62158234Skato if (u_flag && ok("Do you want to change it?")) { 62258234Skato int tmp; 62358234Skato 62458234Skato if (i_flag) { 62558234Skato bzero((char *)partp, sizeof (struct dos_partition)); 62658234Skato if (i == 4) { 62758234Skato init_sector0(1); 62858234Skato printf("\nThe static data for the DOS partition 4 has been reinitialized to:\n"); 62958234Skato print_part(i); 63058234Skato } 63158234Skato } 63258234Skato 63358234Skato do { 63458234Skato#ifdef PC98 63558234Skato int x_start = partp->dp_scyl * cylsecs ; 63658234Skato int x_size = (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs; 63758234Skato Decimal("sysmid", partp->dp_mid, tmp); 63858234Skato Decimal("syssid", partp->dp_sid, tmp); 63958234Skato String ("system name", partp->dp_name, 16); 64058234Skato Decimal("start", x_start, tmp); 64158234Skato Decimal("size", x_size, tmp); 64258234Skato#else 64358234Skato Decimal("sysid (165=FreeBSD)", partp->dp_typ, tmp); 64458234Skato Decimal("start", partp->dp_start, tmp); 64558234Skato Decimal("size", partp->dp_size, tmp); 64658234Skato#endif 64758234Skato if (ok("Explicitly specify beg/end address ?")) 64858234Skato { 64958234Skato int tsec,tcyl,thd; 65058234Skato tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect); 65158234Skato thd = partp->dp_shd; 65258234Skato tsec = DPSECT(partp->dp_ssect); 65358234Skato Decimal("beginning cylinder", tcyl, tmp); 65458234Skato Decimal("beginning head", thd, tmp); 65558234Skato Decimal("beginning sector", tsec, tmp); 65658234Skato partp->dp_scyl = DOSCYL(tcyl); 65758234Skato partp->dp_ssect = DOSSECT(tsec,tcyl); 65858234Skato partp->dp_shd = thd; 65958234Skato#ifdef PC98 66058234Skato partp->dp_ipl_cyl = partp->dp_scyl; 66158234Skato partp->dp_ipl_sct = partp->dp_ssect; 66258234Skato partp->dp_ipl_head = partp->dp_shd; 66358234Skato#endif 66458234Skato 66558234Skato tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect); 66658234Skato thd = partp->dp_ehd; 66758234Skato tsec = DPSECT(partp->dp_esect); 66858234Skato Decimal("ending cylinder", tcyl, tmp); 66958234Skato Decimal("ending head", thd, tmp); 67058234Skato Decimal("ending sector", tsec, tmp); 67158234Skato partp->dp_ecyl = DOSCYL(tcyl); 67258234Skato partp->dp_esect = DOSSECT(tsec,tcyl); 67358234Skato partp->dp_ehd = thd; 67458234Skato } else { 67558234Skato#ifdef PC98 67658234Skato dos(x_start, x_size, &partp->dp_scyl, 67758234Skato &partp->dp_ssect, &partp->dp_shd); 67858234Skato partp->dp_ipl_cyl = partp->dp_scyl; 67958234Skato partp->dp_ipl_sct = partp->dp_ssect; 68058234Skato partp->dp_ipl_head = partp->dp_shd; 68158234Skato dos(x_start+x_size - cylsecs, x_size, &partp->dp_ecyl, 68258234Skato &partp->dp_esect, &partp->dp_ehd); 68358234Skato#else 68458234Skato dos(partp->dp_start, partp->dp_size, 68558234Skato &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 68658234Skato dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, 68758234Skato &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 68858234Skato#endif 68958234Skato } 69058234Skato 69158234Skato print_part(i); 69258234Skato } while (!ok("Are we happy with this entry?")); 69358234Skato } 69458234Skato} 69558234Skato 69658234Skatostatic void 69758234Skatoprint_params() 69858234Skato{ 69958234Skato printf("parameters extracted from in-core disklabel are:\n"); 70058234Skato printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 70158234Skato ,cyls,heads,sectors,cylsecs); 70258234Skato#ifndef PC98 70358234Skato if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255)) 70458234Skato printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 70558234Skato#endif 70658234Skato printf("parameters to be used for BIOS calculations are:\n"); 70758234Skato printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 70858234Skato ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 70958234Skato} 71058234Skato 71158234Skatostatic void 71258234Skatochange_active(int which) 71358234Skato{ 71458234Skatoint i; 71558234Skato#ifdef PC98 71658234Skatoint active = 8, tmp; 71758234Skato#else 71858234Skatoint active = 4, tmp; 71958234Skato#endif 72058234Skato 72158234Skatostruct dos_partition *partp = ((struct dos_partition *) &mboot.parts); 72258234Skato 72358234Skato if (a_flag && which != -1) 72458234Skato active = which; 72558234Skato if (!ok("Do you want to change the active partition?")) 72658234Skato return; 72758234Skatosetactive: 72858234Skato#ifdef PC98 72958234Skato active = 4; 73058234Skato#else 73158234Skato active = 4; 73258234Skato#endif 73358234Skato do { 73458234Skato Decimal("active partition", active, tmp); 73558234Skato#ifdef PC98 73658234Skato if (active < 1 || 8 < active) { 73758234Skato printf("Active partition number must be in range 1-8." 73858234Skato " Try again.\n"); 73958234Skato goto setactive; 74058234Skato } 74158234Skato#else 74258234Skato if (active < 1 || 4 < active) { 74358234Skato printf("Active partition number must be in range 1-4." 74458234Skato " Try again.\n"); 74558234Skato goto setactive; 74658234Skato } 74758234Skato#endif 74858234Skato } while (!ok("Are you happy with this choice")); 74958234Skato#ifdef PC98 75058234Skato partp[active].dp_sid |= ACTIVE; 75158234Skato#else 75258234Skato for (i = 0; i < NDOSPART; i++) 75358234Skato partp[i].dp_flag = 0; 75458234Skato if (active > 0 && active <= NDOSPART) 75558234Skato partp[active-1].dp_flag = ACTIVE; 75658234Skato#endif 75758234Skato} 75858234Skato 75958234Skatostatic void 76058234Skatochange_code() 76158234Skato{ 76258234Skato if (ok("Do you want to change the boot code?")) 76358234Skato init_boot(); 76458234Skato 76558234Skato} 76658234Skato 76758234Skatovoid 76858234Skatoget_params_to_use() 76958234Skato{ 77058234Skato int tmp; 77158234Skato print_params(); 77258234Skato if (ok("Do you want to change our idea of what BIOS thinks ?")) 77358234Skato { 77458234Skato do 77558234Skato { 77658234Skato Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 77758234Skato Decimal("BIOS's idea of #heads", dos_heads, tmp); 77858234Skato Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 77958234Skato dos_cylsecs = dos_heads * dos_sectors; 78058234Skato print_params(); 78158234Skato } 78258234Skato while(!ok("Are you happy with this choice")); 78358234Skato } 78458234Skato} 78558234Skato 78658234Skato 78758234Skato/***********************************************\ 78858234Skato* Change real numbers into strange dos numbers * 78958234Skato\***********************************************/ 79058234Skatostatic void 79158234Skatodos(sec, size, c, s, h) 79258234Skatoint sec, size; 79358234Skato#ifdef PC98 79458234Skatounsigned short *c; 79558234Skatounsigned char *s, *h; 79658234Skato#else 79758234Skatounsigned char *c, *s, *h; 79858234Skato#endif 79958234Skato{ 80058234Skatoint cy; 80158234Skatoint hd; 80258234Skato 80358234Skato if (sec == 0 && size == 0) { 80458234Skato *s = *c = *h = 0; 80558234Skato return; 80658234Skato } 80758234Skato 80858234Skato cy = sec / ( dos_cylsecs ); 80958234Skato sec = sec - cy * ( dos_cylsecs ); 81058234Skato 81158234Skato hd = sec / dos_sectors; 81258234Skato#ifdef PC98 81358234Skato sec = (sec - hd * dos_sectors); 81458234Skato 81558234Skato *h = hd; 81658234Skato *c = cy; 81758234Skato *s = sec; 81858234Skato#else 81958234Skato sec = (sec - hd * dos_sectors) + 1; 82058234Skato 82158234Skato *h = hd; 82258234Skato *c = cy & 0xff; 82358234Skato *s = (sec & 0x3f) | ( (cy & 0x300) >> 2); 82458234Skato#endif 82558234Skato} 82658234Skato 82758234Skatoint fd; 82858234Skato 82958234Skato /* Getting device status */ 83058234Skato 83158234Skatostatic int 83258234Skatoopen_disk(int u_flag) 83358234Skato{ 83458234Skatostruct stat st; 83558234Skato 83658234Skato if (stat(disk, &st) == -1) { 83758234Skato warnx("can't get file status of %s", disk); 83858234Skato return -1; 83958234Skato } 84058234Skato if ( !(st.st_mode & S_IFCHR) ) 84158234Skato warnx("device %s is not character special", disk); 84258234Skato if ((fd = open(disk, 84358234Skato a_flag || I_flag || B_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) { 84458234Skato if(errno == ENXIO) 84558234Skato return -2; 84658234Skato warnx("can't open device %s", disk); 84758234Skato return -1; 84858234Skato } 84958234Skato if (get_params(0) == -1) { 85058234Skato warnx("can't get disk parameters on %s", disk); 85158234Skato return -1; 85258234Skato } 85358234Skato return fd; 85458234Skato} 85558234Skato 85658234Skatostatic ssize_t 85758234Skatoread_disk(off_t sector, void *buf) 85858234Skato{ 85958234Skato lseek(fd,(sector * 512), 0); 86058234Skato#ifdef PC98 86158234Skato return read(fd, buf, secsize > MIN_SEC_SIZE ? secsize : MIN_SEC_SIZE * 2); 86258234Skato#else 86358234Skato if( secsize == 0 ) 86458234Skato for( secsize = MIN_SEC_SIZE; secsize <= MAX_SEC_SIZE; secsize *= 2 ) 86558234Skato { 86658234Skato /* try the read */ 86758234Skato int size = read(fd, buf, secsize); 86858234Skato if( size == secsize ) 86958234Skato /* it worked so return */ 87058234Skato return secsize; 87158234Skato } 87258234Skato else 87358234Skato return read( fd, buf, secsize ); 87458234Skato 87558234Skato /* we failed to read at any of the sizes */ 87658234Skato return -1; 87758234Skato#endif 87858234Skato} 87958234Skato 88058234Skatostatic ssize_t 88158234Skatowrite_disk(off_t sector, void *buf) 88258234Skato{ 88358234Skato lseek(fd,(sector * 512), 0); 88458234Skato /* write out in the size that the read_disk found worked */ 88558234Skato#ifdef PC98 88658234Skato return write(fd, buf, secsize > MIN_SEC_SIZE ? secsize : MIN_SEC_SIZE * 2); 88758234Skato#else 88858234Skato return write(fd, buf, secsize); 88958234Skato#endif 89058234Skato} 89158234Skato 89258234Skatostatic int 89358234Skatoget_params() 89458234Skato{ 89558234Skato 89658234Skato if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 89758234Skato warnx("can't get disk parameters on %s; supplying dummy ones", disk); 89858234Skato dos_cyls = cyls = 1; 89958234Skato dos_heads = heads = 1; 90058234Skato dos_sectors = sectors = 1; 90158234Skato dos_cylsecs = cylsecs = heads * sectors; 90258234Skato disksecs = cyls * heads * sectors; 90358234Skato#ifdef PC98 90458234Skato secsize = disklabel.d_secsize; 90558234Skato#endif 90658234Skato return disksecs; 90758234Skato } 90858234Skato 90958234Skato dos_cyls = cyls = disklabel.d_ncylinders; 91058234Skato dos_heads = heads = disklabel.d_ntracks; 91158234Skato dos_sectors = sectors = disklabel.d_nsectors; 91258234Skato dos_cylsecs = cylsecs = heads * sectors; 91358234Skato disksecs = cyls * heads * sectors; 91458234Skato#ifdef PC98 91558234Skato secsize = disklabel.d_secsize; 91658234Skato#endif 91758234Skato return (disksecs); 91858234Skato} 91958234Skato 92058234Skato 92158234Skatostatic int 92258234Skatoread_s0() 92358234Skato{ 92458234Skato if (read_disk(0, (char *) mboot.bootinst) == -1) { 92558234Skato warnx("can't read fdisk partition table"); 92658234Skato return -1; 92758234Skato } 92858234Skato if (mboot.signature != BOOT_MAGIC) { 92958234Skato warnx("invalid fdisk partition table found"); 93058234Skato /* So should we initialize things */ 93158234Skato return -1; 93258234Skato } 93358234Skato return 0; 93458234Skato} 93558234Skato 93658234Skatostatic int 93758234Skatowrite_s0() 93858234Skato{ 93958234Skato#ifdef NOT_NOW 94058234Skato int flag; 94158234Skato#endif 94258234Skato if (iotest) { 94358234Skato print_s0(-1); 94458234Skato return 0; 94558234Skato } 94658234Skato /* 94758234Skato * write enable label sector before write (if necessary), 94858234Skato * disable after writing. 94958234Skato * needed if the disklabel protected area also protects 95058234Skato * sector 0. (e.g. empty disk) 95158234Skato */ 95258234Skato#ifdef NOT_NOW 95358234Skato flag = 1; 95458234Skato if (ioctl(fd, DIOCWLABEL, &flag) < 0) 95558234Skato warn("ioctl DIOCWLABEL"); 95658234Skato#endif 95758234Skato if (write_disk(0, (char *) mboot.bootinst) == -1) { 95858234Skato warn("can't write fdisk partition table"); 95958234Skato return -1; 96058234Skato#ifdef NOT_NOW 96158234Skato flag = 0; 96258234Skato (void) ioctl(fd, DIOCWLABEL, &flag); 96358234Skato#endif 96458234Skato } 96558234Skato return(0); 96658234Skato} 96758234Skato 96858234Skato 96958234Skatostatic int 97058234Skatook(str) 97158234Skatochar *str; 97258234Skato{ 97358234Skato printf("%s [n] ", str); 97458234Skato fgets(lbuf, LBUF, stdin); 97558234Skato lbuf[strlen(lbuf)-1] = 0; 97658234Skato 97758234Skato if (*lbuf && 97858234Skato (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 97958234Skato !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 98058234Skato return 1; 98158234Skato else 98258234Skato return 0; 98358234Skato} 98458234Skato 98558234Skatostatic int 98658234Skatodecimal(char *str, int *num, int deflt) 98758234Skato{ 98858234Skatoint acc = 0, c; 98958234Skatochar *cp; 99058234Skato 99158234Skato while (1) { 99258234Skato printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 99358234Skato fgets(lbuf, LBUF, stdin); 99458234Skato lbuf[strlen(lbuf)-1] = 0; 99558234Skato 99658234Skato if (!*lbuf) 99758234Skato return 0; 99858234Skato 99958234Skato cp = lbuf; 100058234Skato while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 100158234Skato if (!c) 100258234Skato return 0; 100358234Skato while ((c = *cp++)) { 100458234Skato if (c <= '9' && c >= '0') 100558234Skato acc = acc * 10 + c - '0'; 100658234Skato else 100758234Skato break; 100858234Skato } 100958234Skato if (c == ' ' || c == '\t') 101058234Skato while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 101158234Skato if (!c) { 101258234Skato *num = acc; 101358234Skato return 1; 101458234Skato } else 101558234Skato printf("%s is an invalid decimal number. Try again.\n", 101658234Skato lbuf); 101758234Skato } 101858234Skato 101958234Skato} 102058234Skato 102158234Skato#if 0 102258234Skatostatic int 102358234Skatohex(char *str, int *num, int deflt) 102458234Skato{ 102558234Skatoint acc = 0, c; 102658234Skatochar *cp; 102758234Skato 102858234Skato while (1) { 102958234Skato printf("Supply a hex value for \"%s\" [%x] ", str, deflt); 103058234Skato fgets(lbuf, LBUF, stdin); 103158234Skato lbuf[strlen(lbuf)-1] = 0; 103258234Skato 103358234Skato if (!*lbuf) 103458234Skato return 0; 103558234Skato 103658234Skato cp = lbuf; 103758234Skato while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 103858234Skato if (!c) 103958234Skato return 0; 104058234Skato while ((c = *cp++)) { 104158234Skato if (c <= '9' && c >= '0') 104258234Skato acc = (acc << 4) + c - '0'; 104358234Skato else if (c <= 'f' && c >= 'a') 104458234Skato acc = (acc << 4) + c - 'a' + 10; 104558234Skato else if (c <= 'F' && c >= 'A') 104658234Skato acc = (acc << 4) + c - 'A' + 10; 104758234Skato else 104858234Skato break; 104958234Skato } 105058234Skato if (c == ' ' || c == '\t') 105158234Skato while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 105258234Skato if (!c) { 105358234Skato *num = acc; 105458234Skato return 1; 105558234Skato } else 105658234Skato printf("%s is an invalid hex number. Try again.\n", 105758234Skato lbuf); 105858234Skato } 105958234Skato 106058234Skato} 106158234Skato#endif 106258234Skato 106358234Skato#ifdef PC98 106458234Skatostatic int 106558234Skatostring(char *str, char **ans) 106658234Skato{ 106758234Skato#ifdef PC98 106858234Skatoint i; 106958234Skato#endif 107058234Skatoint c; 107158234Skatochar *cp = lbuf; 107258234Skato 107358234Skato while (1) { 107458234Skato printf("Supply a string value for \"%s\" [%s] ", str, *ans); 107558234Skato fgets(lbuf, LBUF, stdin); 107658234Skato lbuf[strlen(lbuf)-1] = 0; 107758234Skato 107858234Skato if (!*lbuf) 107958234Skato return 0; 108058234Skato 108158234Skato while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 108258234Skato if (c == '"') { 108358234Skato c = *++cp; 108458234Skato *ans = cp; 108558234Skato while ((c = *cp) && c != '"') cp++; 108658234Skato } else { 108758234Skato *ans = cp; 108858234Skato while ((c = *cp) && c != ' ' && c != '\t') cp++; 108958234Skato } 109058234Skato 109158234Skato#ifdef PC98 109258234Skato for (i = strlen(*ans); i < 16; i++) 109358234Skato (*ans)[i] = ' '; 109458234Skato (*ans)[16] = 0; 109558234Skato#else 109658234Skato if (c) 109758234Skato *cp = 0; 109858234Skato#endif 109958234Skato return 1; 110058234Skato } 110158234Skato} 110258234Skato#endif 110358234Skato 110458234Skatostatic char * 110558234Skatoget_type(int type) 110658234Skato{ 110758234Skato int numentries = (sizeof(part_types)/sizeof(struct part_type)); 110858234Skato int counter = 0; 110958234Skato struct part_type *ptr = part_types; 111058234Skato 111158234Skato 111258234Skato while(counter < numentries) 111358234Skato { 111458234Skato#ifdef PC98 111558234Skato if(ptr->type == (type & 0x7f)) 111658234Skato#else 111758234Skato if(ptr->type == type) 111858234Skato#endif 111958234Skato { 112058234Skato return(ptr->name); 112158234Skato } 112258234Skato ptr++; 112358234Skato counter++; 112458234Skato } 112558234Skato return("unknown"); 112658234Skato} 112758234Skato 112858234Skato#ifndef PC98 112958234Skatostatic void 113058234Skatoparse_config_line(line, command) 113158234Skato char *line; 113258234Skato CMD *command; 113358234Skato{ 113458234Skato char *cp, *end; 113558234Skato 113658234Skato cp = line; 113758234Skato while (1) /* dirty trick used to insure one exit point for this 113858234Skato function */ 113958234Skato { 114058234Skato memset(command, 0, sizeof(*command)); 114158234Skato 114258234Skato while (isspace(*cp)) ++cp; 114358234Skato if (*cp == '\0' || *cp == '#') 114458234Skato { 114558234Skato break; 114658234Skato } 114758234Skato command->cmd = *cp++; 114858234Skato 114958234Skato /* 115058234Skato * Parse args 115158234Skato */ 115258234Skato while (1) 115358234Skato { 115458234Skato while (isspace(*cp)) ++cp; 115558234Skato if (*cp == '#') 115658234Skato { 115758234Skato break; /* found comment */ 115858234Skato } 115958234Skato if (isalpha(*cp)) 116058234Skato { 116158234Skato command->args[command->n_args].argtype = *cp++; 116258234Skato } 116358234Skato if (!isdigit(*cp)) 116458234Skato { 116558234Skato break; /* assume end of line */ 116658234Skato } 116758234Skato end = NULL; 116858234Skato command->args[command->n_args].arg_val = strtol(cp, &end, 0); 116958234Skato if (cp == end) 117058234Skato { 117158234Skato break; /* couldn't parse number */ 117258234Skato } 117358234Skato cp = end; 117458234Skato command->n_args++; 117558234Skato } 117658234Skato break; 117758234Skato } 117858234Skato} 117958234Skato 118058234Skato 118158234Skatostatic int 118258234Skatoprocess_geometry(command) 118358234Skato CMD *command; 118458234Skato{ 118558234Skato int status = 1, i; 118658234Skato 118758234Skato while (1) 118858234Skato { 118958234Skato geom_processed = 1; 119058234Skato if (part_processed) 119158234Skato { 119258234Skato warnx( 119358234Skato "ERROR line %d: the geometry specification line must occur before\n\ 119458234Skato all partition specifications", 119558234Skato current_line_number); 119658234Skato status = 0; 119758234Skato break; 119858234Skato } 119958234Skato if (command->n_args != 3) 120058234Skato { 120158234Skato warnx("ERROR line %d: incorrect number of geometry args", 120258234Skato current_line_number); 120358234Skato status = 0; 120458234Skato break; 120558234Skato } 120658234Skato dos_cyls = -1; 120758234Skato dos_heads = -1; 120858234Skato dos_sectors = -1; 120958234Skato for (i = 0; i < 3; ++i) 121058234Skato { 121158234Skato switch (command->args[i].argtype) 121258234Skato { 121358234Skato case 'c': 121458234Skato dos_cyls = command->args[i].arg_val; 121558234Skato break; 121658234Skato case 'h': 121758234Skato dos_heads = command->args[i].arg_val; 121858234Skato break; 121958234Skato case 's': 122058234Skato dos_sectors = command->args[i].arg_val; 122158234Skato break; 122258234Skato default: 122358234Skato warnx( 122458234Skato "ERROR line %d: unknown geometry arg type: '%c' (0x%02x)", 122558234Skato current_line_number, command->args[i].argtype, 122658234Skato command->args[i].argtype); 122758234Skato status = 0; 122858234Skato break; 122958234Skato } 123058234Skato } 123158234Skato if (status == 0) 123258234Skato { 123358234Skato break; 123458234Skato } 123558234Skato 123658234Skato dos_cylsecs = dos_heads * dos_sectors; 123758234Skato 123858234Skato /* 123958234Skato * Do sanity checks on parameter values 124058234Skato */ 124158234Skato if (dos_cyls < 0) 124258234Skato { 124358234Skato warnx("ERROR line %d: number of cylinders not specified", 124458234Skato current_line_number); 124558234Skato status = 0; 124658234Skato } 124758234Skato if (dos_cyls == 0 || dos_cyls > 1024) 124858234Skato { 124958234Skato warnx( 125058234Skato "WARNING line %d: number of cylinders (%d) may be out-of-range\n\ 125158234Skato (must be within 1-1024 for normal BIOS operation, unless the entire disk\n\ 125258234Skato is dedicated to FreeBSD)", 125358234Skato current_line_number, dos_cyls); 125458234Skato } 125558234Skato 125658234Skato if (dos_heads < 0) 125758234Skato { 125858234Skato warnx("ERROR line %d: number of heads not specified", 125958234Skato current_line_number); 126058234Skato status = 0; 126158234Skato } 126258234Skato else if (dos_heads < 1 || dos_heads > 256) 126358234Skato { 126458234Skato warnx("ERROR line %d: number of heads must be within (1-256)", 126558234Skato current_line_number); 126658234Skato status = 0; 126758234Skato } 126858234Skato 126958234Skato if (dos_sectors < 0) 127058234Skato { 127158234Skato warnx("ERROR line %d: number of sectors not specified", 127258234Skato current_line_number); 127358234Skato status = 0; 127458234Skato } 127558234Skato else if (dos_sectors < 1 || dos_sectors > 63) 127658234Skato { 127758234Skato warnx("ERROR line %d: number of sectors must be within (1-63)", 127858234Skato current_line_number); 127958234Skato status = 0; 128058234Skato } 128158234Skato 128258234Skato break; 128358234Skato } 128458234Skato return (status); 128558234Skato} 128658234Skato 128758234Skato 128858234Skatostatic int 128958234Skatoprocess_partition(command) 129058234Skato CMD *command; 129158234Skato{ 129258234Skato int status = 0, partition; 129358234Skato unsigned long chunks, adj_size, max_end; 129458234Skato struct dos_partition *partp; 129558234Skato 129658234Skato while (1) 129758234Skato { 129858234Skato part_processed = 1; 129958234Skato if (command->n_args != 4) 130058234Skato { 130158234Skato warnx("ERROR line %d: incorrect number of partition args", 130258234Skato current_line_number); 130358234Skato break; 130458234Skato } 130558234Skato partition = command->args[0].arg_val; 130658234Skato if (partition < 1 || partition > 4) 130758234Skato { 130858234Skato warnx("ERROR line %d: invalid partition number %d", 130958234Skato current_line_number, partition); 131058234Skato break; 131158234Skato } 131258234Skato partp = ((struct dos_partition *) &mboot.parts) + partition - 1; 131358234Skato bzero((char *)partp, sizeof (struct dos_partition)); 131458234Skato partp->dp_typ = command->args[1].arg_val; 131558234Skato partp->dp_start = command->args[2].arg_val; 131658234Skato partp->dp_size = command->args[3].arg_val; 131758234Skato max_end = partp->dp_start + partp->dp_size; 131858234Skato 131958234Skato if (partp->dp_typ == 0) 132058234Skato { 132158234Skato /* 132258234Skato * Get out, the partition is marked as unused. 132358234Skato */ 132458234Skato /* 132558234Skato * Insure that it's unused. 132658234Skato */ 132758234Skato bzero((char *)partp, sizeof (struct dos_partition)); 132858234Skato status = 1; 132958234Skato break; 133058234Skato } 133158234Skato 133258234Skato /* 133358234Skato * Adjust start upwards, if necessary, to fall on an head boundary. 133458234Skato */ 133558234Skato if (partp->dp_start % dos_sectors != 0) 133658234Skato { 133758234Skato adj_size = 133858234Skato (partp->dp_start / dos_sectors + 1) * dos_sectors; 133958234Skato if (adj_size > max_end) 134058234Skato { 134158234Skato /* 134258234Skato * Can't go past end of partition 134358234Skato */ 134458234Skato warnx( 134558234Skato "ERROR line %d: unable to adjust start of partition %d to fall on\n\ 134658234Skato a cylinder boundary", 134758234Skato current_line_number, partition); 134858234Skato break; 134958234Skato } 135058234Skato warnx( 135158234Skato "WARNING: adjusting start offset of partition '%d' from %lu\n\ 135258234Skato to %lu, to round to an head boundary", 135358234Skato partition, (u_long)partp->dp_start, adj_size); 135458234Skato partp->dp_start = adj_size; 135558234Skato } 135658234Skato 135758234Skato /* 135858234Skato * Adjust size downwards, if necessary, to fall on a cylinder 135958234Skato * boundary. 136058234Skato */ 136158234Skato chunks = 136258234Skato ((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs; 136358234Skato adj_size = chunks - partp->dp_start; 136458234Skato if (adj_size != partp->dp_size) 136558234Skato { 136658234Skato warnx( 136758234Skato "WARNING: adjusting size of partition '%d' from %lu to %lu,\n\ 136858234Skato to round to a cylinder boundary", 136958234Skato partition, (u_long)partp->dp_size, adj_size); 137058234Skato if (chunks > 0) 137158234Skato { 137258234Skato partp->dp_size = adj_size; 137358234Skato } 137458234Skato else 137558234Skato { 137658234Skato partp->dp_size = 0; 137758234Skato } 137858234Skato } 137958234Skato if (partp->dp_size < 1) 138058234Skato { 138158234Skato warnx("ERROR line %d: size for partition '%d' is zero", 138258234Skato current_line_number, partition); 138358234Skato break; 138458234Skato } 138558234Skato 138658234Skato dos(partp->dp_start, partp->dp_size, 138758234Skato &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); 138858234Skato dos(partp->dp_start+partp->dp_size - 1, partp->dp_size, 138958234Skato &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd); 139058234Skato status = 1; 139158234Skato break; 139258234Skato } 139358234Skato return (status); 139458234Skato} 139558234Skato 139658234Skato 139758234Skatostatic int 139858234Skatoprocess_active(command) 139958234Skato CMD *command; 140058234Skato{ 140158234Skato int status = 0, partition, i; 140258234Skato struct dos_partition *partp; 140358234Skato 140458234Skato while (1) 140558234Skato { 140658234Skato active_processed = 1; 140758234Skato if (command->n_args != 1) 140858234Skato { 140958234Skato warnx("ERROR line %d: incorrect number of active args", 141058234Skato current_line_number); 141158234Skato status = 0; 141258234Skato break; 141358234Skato } 141458234Skato partition = command->args[0].arg_val; 141558234Skato if (partition < 1 || partition > 4) 141658234Skato { 141758234Skato warnx("ERROR line %d: invalid partition number %d", 141858234Skato current_line_number, partition); 141958234Skato break; 142058234Skato } 142158234Skato /* 142258234Skato * Reset active partition 142358234Skato */ 142458234Skato partp = ((struct dos_partition *) &mboot.parts); 142558234Skato for (i = 0; i < NDOSPART; i++) 142658234Skato partp[i].dp_flag = 0; 142758234Skato partp[partition-1].dp_flag = ACTIVE; 142858234Skato 142958234Skato status = 1; 143058234Skato break; 143158234Skato } 143258234Skato return (status); 143358234Skato} 143458234Skato 143558234Skato 143658234Skatostatic int 143758234Skatoprocess_line(line) 143858234Skato char *line; 143958234Skato{ 144058234Skato CMD command; 144158234Skato int status = 1; 144258234Skato 144358234Skato while (1) 144458234Skato { 144558234Skato parse_config_line(line, &command); 144658234Skato switch (command.cmd) 144758234Skato { 144858234Skato case 0: 144958234Skato /* 145058234Skato * Comment or blank line 145158234Skato */ 145258234Skato break; 145358234Skato case 'g': 145458234Skato /* 145558234Skato * Set geometry 145658234Skato */ 145758234Skato status = process_geometry(&command); 145858234Skato break; 145958234Skato case 'p': 146058234Skato status = process_partition(&command); 146158234Skato break; 146258234Skato case 'a': 146358234Skato status = process_active(&command); 146458234Skato break; 146558234Skato default: 146658234Skato status = 0; 146758234Skato break; 146858234Skato } 146958234Skato break; 147058234Skato } 147158234Skato return (status); 147258234Skato} 147358234Skato 147458234Skato 147558234Skatostatic int 147658234Skatoread_config(config_file) 147758234Skato char *config_file; 147858234Skato{ 147958234Skato FILE *fp = NULL; 148058234Skato int status = 1; 148158234Skato char buf[1010]; 148258234Skato 148358234Skato while (1) /* dirty trick used to insure one exit point for this 148458234Skato function */ 148558234Skato { 148658234Skato if (strcmp(config_file, "-") != 0) 148758234Skato { 148858234Skato /* 148958234Skato * We're not reading from stdin 149058234Skato */ 149158234Skato if ((fp = fopen(config_file, "r")) == NULL) 149258234Skato { 149358234Skato status = 0; 149458234Skato break; 149558234Skato } 149658234Skato } 149758234Skato else 149858234Skato { 149958234Skato fp = stdin; 150058234Skato } 150158234Skato current_line_number = 0; 150258234Skato while (!feof(fp)) 150358234Skato { 150458234Skato if (fgets(buf, sizeof(buf), fp) == NULL) 150558234Skato { 150658234Skato break; 150758234Skato } 150858234Skato ++current_line_number; 150958234Skato status = process_line(buf); 151058234Skato if (status == 0) 151158234Skato { 151258234Skato break; 151358234Skato } 151458234Skato } 151558234Skato break; 151658234Skato } 151758234Skato if (fp) 151858234Skato { 151958234Skato /* 152058234Skato * It doesn't matter if we're reading from stdin, as we've reached EOF 152158234Skato */ 152258234Skato fclose(fp); 152358234Skato } 152458234Skato return (status); 152558234Skato} 152658234Skato 152758234Skato 152858234Skatostatic void 152958234Skatoreset_boot(void) 153058234Skato{ 153158234Skato int i; 153258234Skato struct dos_partition *partp; 153358234Skato 153458234Skato init_boot(); 153558234Skato for (i = 0; i < 4; ++i) 153658234Skato { 153758234Skato partp = ((struct dos_partition *) &mboot.parts) + i; 153858234Skato bzero((char *)partp, sizeof (struct dos_partition)); 153958234Skato } 154058234Skato} 154158234Skato#endif 1542