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