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 27145748Snyan#include <sys/cdefs.h> 28145748Snyan__FBSDID("$FreeBSD: releng/10.3/sbin/fdisk_pc98/fdisk.c 254015 2013-08-07 00:00:48Z marcel $"); 2958234Skato 30106047Snyan#include <sys/disk.h> 3158234Skato#include <sys/disklabel.h> 32104459Snyan#include <sys/diskpc98.h> 33106047Snyan#include <sys/param.h> 3458234Skato#include <sys/stat.h> 35106047Snyan#include <sys/mount.h> 3658234Skato#include <ctype.h> 3758234Skato#include <fcntl.h> 3858234Skato#include <err.h> 3958234Skato#include <errno.h> 40148062Snyan#include <libgeom.h> 4169793Sobrien#include <paths.h> 42106047Snyan#include <regex.h> 43106047Snyan#include <stdint.h> 4458234Skato#include <stdio.h> 4558234Skato#include <stdlib.h> 4658234Skato#include <string.h> 4758234Skato#include <unistd.h> 4858234Skato 4958234Skatoint iotest; 5058234Skato 5158234Skato#define LBUF 100 5258234Skatostatic char lbuf[LBUF]; 5358234Skato 5458234Skato/* 5558234Skato * 5658234Skato * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 5758234Skato * 5858234Skato * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 5958234Skato * Copyright (c) 1989 Robert. V. Baron 6058234Skato * Created. 6158234Skato */ 6258234Skato 6358234Skato#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp 6458234Skato#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); } 6558234Skato 6658234Skato#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs) 6758234Skato 6858234Skato#define MAX_SEC_SIZE 2048 /* maximum section size that is supported */ 6958234Skato#define MIN_SEC_SIZE 512 /* the sector size to start sensing at */ 70106047Snyanstatic int secsize = 0; /* the sensed sector size */ 7158234Skato 72106047Snyanstatic char *disk; 7358234Skato 74106047Snyanstatic int cyls, sectors, heads, cylsecs, disksecs; 7558234Skato 76106047Snyanstruct mboot { 7758234Skato unsigned char padding[2]; /* force the longs to be long aligned */ 7858234Skato unsigned char bootinst[510]; 7958234Skato unsigned short int signature; 80108650Snyan struct pc98_partition parts[8]; 8158234Skato unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE]; 8258234Skato}; 8358234Skato 84106047Snyanstatic struct mboot mboot; 85148062Snyanstatic int fd; 86106047Snyan 87106047Snyanstatic uint dos_cyls; 88106047Snyanstatic uint dos_heads; 89106047Snyanstatic uint dos_sectors; 90106047Snyanstatic uint dos_cylsecs; 9158234Skato 9258234Skato#define MAX_ARGS 10 9358234Skato 9458234Skatotypedef struct cmd { 9558234Skato char cmd; 9658234Skato int n_args; 9758234Skato struct arg { 9858234Skato char argtype; 9958234Skato int arg_val; 10058234Skato } args[MAX_ARGS]; 10158234Skato} CMD; 10258234Skato 10358234Skatostatic int B_flag = 0; /* replace boot code */ 104156020Simpstatic int I_flag = 0; /* Inizialize disk to defaults */ 10558234Skatostatic int a_flag = 0; /* set active partition */ 10658234Skatostatic int i_flag = 0; /* replace partition data */ 10758234Skatostatic int u_flag = 0; /* update partition data */ 10858234Skatostatic int s_flag = 0; /* Print a summary and exit */ 109106047Snyanstatic int t_flag = 0; /* test only */ 11058234Skatostatic char *f_flag = NULL; /* Read config info from file */ 11158234Skatostatic int v_flag = 0; /* Be verbose */ 11258234Skato 113106047Snyanstatic struct part_type 11458234Skato{ 115106047Snyan unsigned char type; 116106047Snyan const char *name; 117106047Snyan} part_types[] = { 11858234Skato {0x00, "unused"} 11958234Skato ,{0x01, "Primary DOS with 12 bit FAT"} 12058234Skato ,{0x11, "MSDOS"} 12158234Skato ,{0x20, "MSDOS"} 12258234Skato ,{0x21, "MSDOS"} 12358234Skato ,{0x22, "MSDOS"} 12458234Skato ,{0x23, "MSDOS"} 125102231Strhodes ,{0x02, "XENIX / file system"} 126102231Strhodes ,{0x03, "XENIX /usr file system"} 12758234Skato ,{0x04, "PC-UX"} 12858234Skato ,{0x05, "Extended DOS"} 12958234Skato ,{0x06, "Primary 'big' DOS (> 32MB)"} 13058234Skato ,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"} 131102231Strhodes ,{0x08, "AIX file system"} 13258234Skato ,{0x09, "AIX boot partition or Coherent"} 13358234Skato ,{0x0A, "OS/2 Boot Manager or OPUS"} 13458234Skato ,{0x10, "OPUS"} 13558234Skato ,{0x14, "FreeBSD/NetBSD/386BSD"} 13658234Skato ,{0x94, "FreeBSD/NetBSD/386BSD"} 13758234Skato ,{0x40, "VENIX 286"} 13858234Skato ,{0x50, "DM"} 13958234Skato ,{0x51, "DM"} 14058234Skato ,{0x52, "CP/M or Microport SysV/AT"} 14158234Skato ,{0x56, "GB"} 14258234Skato ,{0x61, "Speed"} 14358234Skato ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"} 14458234Skato ,{0x64, "Novell Netware 2.xx"} 14558234Skato ,{0x65, "Novell Netware 3.xx"} 14658234Skato ,{0x75, "PCIX"} 14758234Skato ,{0x40, "Minix"} 14858234Skato}; 14958234Skato 15058234Skatostatic void print_s0(int which); 15158234Skatostatic void print_part(int i); 15258234Skatostatic void init_sector0(unsigned long start); 15358234Skatostatic void init_boot(void); 154168934Simpstatic void change_part(int i, int force); 155106047Snyanstatic void print_params(void); 15658234Skatostatic void change_active(int which); 157106047Snyanstatic void change_code(void); 158106047Snyanstatic void get_params_to_use(void); 159106047Snyanstatic char *get_rootdisk(void); 160145765Snyanstatic void dos(u_int32_t start, u_int32_t size, struct pc98_partition *partp); 161106047Snyanstatic int open_disk(int flag); 16258234Skatostatic ssize_t read_disk(off_t sector, void *buf); 163148062Snyanstatic int write_disk(off_t sector, void *buf); 164106047Snyanstatic int get_params(void); 165106047Snyanstatic int read_s0(void); 166106047Snyanstatic int write_s0(void); 167106047Snyanstatic int ok(const char *str); 168106047Snyanstatic int decimal(const char *str, int *num, int deflt); 169106047Snyanstatic const char *get_type(int type); 17058234Skatostatic void usage(void); 171145765Snyanstatic int string(const char *str, char **ans); 172156020Simpstatic void reset_boot(void); 17358234Skato 17458234Skatoint 17558234Skatomain(int argc, char *argv[]) 17658234Skato{ 177106047Snyan struct stat sb; 17858234Skato int c, i; 179106047Snyan int partition = -1; 180108650Snyan struct pc98_partition *partp; 18158234Skato 182156020Simp while ((c = getopt(argc, argv, "BIa:f:istuv12345678")) != -1) 18358234Skato switch (c) { 18458234Skato case 'B': 18558234Skato B_flag = 1; 18658234Skato break; 187156020Simp case 'I': 188156020Simp I_flag = 1; 189156020Simp break; 19058234Skato case 'a': 19158234Skato a_flag = 1; 19258234Skato break; 19358234Skato case 'f': 19458234Skato f_flag = optarg; 19558234Skato break; 19658234Skato case 'i': 19758234Skato i_flag = 1; 19858234Skato break; 19958234Skato case 's': 20058234Skato s_flag = 1; 20158234Skato break; 20258234Skato case 't': 20358234Skato t_flag = 1; 20458234Skato break; 20558234Skato case 'u': 20658234Skato u_flag = 1; 20758234Skato break; 20858234Skato case 'v': 20958234Skato v_flag = 1; 21058234Skato break; 21158234Skato case '1': 21258234Skato case '2': 21358234Skato case '3': 21458234Skato case '4': 21558234Skato case '5': 21658234Skato case '6': 21758234Skato case '7': 21858234Skato case '8': 21958234Skato partition = c - '0'; 22058234Skato break; 22158234Skato default: 22258234Skato usage(); 22358234Skato } 22458234Skato if (f_flag || i_flag) 22558234Skato u_flag = 1; 22658234Skato if (t_flag) 22758234Skato v_flag = 1; 22858234Skato argc -= optind; 22958234Skato argv += optind; 23058234Skato 231106047Snyan if (argc == 0) { 232106047Snyan disk = get_rootdisk(); 233106047Snyan } else { 234106047Snyan if (stat(argv[0], &sb) == 0) { 235106047Snyan /* OK, full pathname given */ 23658234Skato disk = argv[0]; 237136887Snyan } else if (errno == ENOENT && argv[0][0] != '/') { 238106047Snyan /* Try prepending "/dev" */ 239106047Snyan asprintf(&disk, "%s%s", _PATH_DEV, argv[0]); 240106047Snyan if (disk == NULL) 241106047Snyan errx(1, "out of memory"); 242106047Snyan } else { 243106047Snyan /* other stat error, let it fail below */ 244106047Snyan disk = argv[0]; 24558234Skato } 24658234Skato } 247106047Snyan if (open_disk(u_flag) < 0) 248106047Snyan err(1, "cannot open disk %s", disk); 24958234Skato 250106047Snyan if (s_flag) { 25158234Skato if (read_s0()) 25258234Skato err(1, "read_s0"); 25358234Skato printf("%s: %d cyl %d hd %d sec\n", disk, dos_cyls, dos_heads, 25458234Skato dos_sectors); 255168934Simp printf("Part %11s %11s %4s %4s %-16s\n", "Start", "Size", "MID", 256168934Simp "SID", "Name"); 257254015Smarcel for (i = 0; i < PC98_NPARTS; i++) { 258108650Snyan partp = ((struct pc98_partition *) &mboot.parts) + i; 25958234Skato if (partp->dp_sid == 0) 26058234Skato continue; 261168934Simp printf("%4d: %11u %11u 0x%02x 0x%02x %-16.16s\n", i + 1, 26258234Skato partp->dp_scyl * cylsecs, 26358234Skato (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs, 264168934Simp partp->dp_mid, partp->dp_sid, partp->dp_name); 26558234Skato } 26658234Skato exit(0); 26758234Skato } 26858234Skato 26958234Skato printf("******* Working on device %s *******\n",disk); 27058234Skato 271156020Simp if (I_flag) { 272156020Simp read_s0(); 273156020Simp reset_boot(); 274156020Simp partp = (struct pc98_partition *) (&mboot.parts[0]); 275156020Simp partp->dp_mid = DOSMID_386BSD; 276156020Simp partp->dp_sid = DOSSID_386BSD; 277168934Simp strncpy(partp->dp_name, "FreeBSD", sizeof(partp->dp_name)); 278156020Simp /* Start c/h/s. */ 279156020Simp partp->dp_scyl = partp->dp_ipl_cyl = 1; 280156020Simp partp->dp_shd = partp->dp_ipl_head = 1; 281156020Simp partp->dp_ssect = partp->dp_ipl_sct = 0; 282156020Simp 283156020Simp /* End c/h/s. */ 284156020Simp partp->dp_ecyl = dos_cyls - 1; 285156020Simp partp->dp_ehd = dos_cylsecs / dos_sectors; 286156020Simp partp->dp_esect = dos_sectors; 287156020Simp 288156020Simp if (v_flag) 289156020Simp print_s0(-1); 290156020Simp if (!t_flag) 291156020Simp write_s0(); 292156020Simp exit(0); 293156020Simp } 294156020Simp 295106047Snyan if (f_flag) { 29658234Skato if (v_flag) 29758234Skato print_s0(-1); 29858234Skato if (!t_flag) 29958234Skato write_s0(); 300106047Snyan } else { 30158234Skato if(u_flag) 30258234Skato get_params_to_use(); 30358234Skato else 30458234Skato print_params(); 30558234Skato 30658234Skato if (read_s0()) 307106047Snyan init_sector0(dos_sectors); 30858234Skato 30958234Skato printf("Media sector size is %d\n", secsize); 31058234Skato printf("Warning: BIOS sector numbering starts with sector 1\n"); 31158234Skato printf("Information from DOS bootblock is:\n"); 31258234Skato if (partition == -1) 313254015Smarcel for (i = 1; i <= PC98_NPARTS; i++) 314168934Simp change_part(i, v_flag); 31558234Skato else 316168934Simp change_part(partition, 1); 31758234Skato 31858234Skato if (u_flag || a_flag) 31958234Skato change_active(partition); 32058234Skato 32158234Skato if (B_flag) 32258234Skato change_code(); 32358234Skato 32458234Skato if (u_flag || a_flag || B_flag) { 325106047Snyan if (!t_flag) { 32658234Skato printf("\nWe haven't changed the partition table yet. "); 32758234Skato printf("This is your last chance.\n"); 32858234Skato } 32958234Skato print_s0(-1); 330106047Snyan if (!t_flag) { 33158234Skato if (ok("Should we write new partition table?")) 33258234Skato write_s0(); 333106047Snyan } else { 33458234Skato printf("\n-t flag specified -- partition table not written.\n"); 33558234Skato } 33658234Skato } 33758234Skato } 33858234Skato 33958234Skato exit(0); 34058234Skato} 34158234Skato 34258234Skatostatic void 34358234Skatousage() 34458234Skato{ 34558234Skato fprintf(stderr, "%s%s", 346156020Simp "usage: fdisk [-BIaistu] [-12345678] [disk]\n", 34758234Skato " fdisk -f configfile [-itv] [disk]\n"); 34858234Skato exit(1); 34958234Skato} 35058234Skato 351168934Simpstatic struct pc98_partition mtpart; 352168934Simp 353168934Simpstatic int 354168934Simppart_unused(int i) 355168934Simp{ 356168934Simp struct pc98_partition *partp; 357168934Simp 358168934Simp partp = ((struct pc98_partition *) &mboot.parts) + i - 1; 359168934Simp return (bcmp(partp, &mtpart, sizeof (struct pc98_partition)) == 0); 360168934Simp} 361168934Simp 36258234Skatostatic void 36358234Skatoprint_s0(int which) 36458234Skato{ 365106047Snyan int i; 36658234Skato 36758234Skato print_params(); 36858234Skato printf("Information from DOS bootblock is:\n"); 369168934Simp if (which == -1) { 370254015Smarcel for (i = 1; i <= PC98_NPARTS; i++) 371168934Simp if (v_flag || !part_unused(i)) { 372168934Simp printf("%d: ", i); 373168934Simp print_part(i); 374168934Simp } 375168934Simp } 37658234Skato else 37758234Skato print_part(which); 37858234Skato} 37958234Skato 38058234Skatostatic void 38158234Skatoprint_part(int i) 38258234Skato{ 383108650Snyan struct pc98_partition *partp; 384106047Snyan u_int64_t part_sz, part_mb; 38558234Skato 386168934Simp if (part_unused(i)) { 38758234Skato printf("<UNUSED>\n"); 38858234Skato return; 38958234Skato } 39058234Skato /* 39158234Skato * Be careful not to overflow. 39258234Skato */ 393168934Simp partp = ((struct pc98_partition *) &mboot.parts) + i - 1; 394106047Snyan part_sz = (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs; 395106047Snyan part_mb = part_sz * secsize; 396106047Snyan part_mb /= (1024 * 1024); 397106047Snyan printf("sysmid %d (%#04x),(%s)\n", partp->dp_mid, partp->dp_mid, 398106047Snyan get_type(partp->dp_mid)); 399106047Snyan printf(" start %lu, size %lu (%ju Meg), sid %d\n", 400106047Snyan (u_long)(partp->dp_scyl * cylsecs), (u_long)part_sz, 401106047Snyan (uintmax_t)part_mb, partp->dp_sid); 402106047Snyan printf("\tbeg: cyl %d/ head %d/ sector %d;\n\tend: cyl %d/ head %d/ sector %d\n" 403104617Snyan ,partp->dp_scyl 404106047Snyan ,partp->dp_shd 405104617Snyan ,partp->dp_ssect 406104617Snyan ,partp->dp_ecyl 407106047Snyan ,partp->dp_ehd 408106047Snyan ,partp->dp_esect); 409145765Snyan printf ("\tsystem Name %.16s\n", partp->dp_name); 41058234Skato} 41158234Skato 41258234Skato 41358234Skatostatic void 41458234Skatoinit_boot(void) 41558234Skato{ 41658234Skato 417254015Smarcel mboot.signature = PC98_MAGIC; 41858234Skato} 41958234Skato 42058234Skato 42158234Skatostatic void 42258234Skatoinit_sector0(unsigned long start) 42358234Skato{ 424108650Snyan struct pc98_partition *partp = 425145765Snyan (struct pc98_partition *)(&mboot.parts[0]); 42658234Skato 42758234Skato init_boot(); 42858234Skato 42958234Skato partp->dp_mid = DOSMID_386BSD; 43058234Skato partp->dp_sid = DOSSID_386BSD; 43158234Skato 432145765Snyan dos(start, disksecs - start, partp); 43358234Skato} 43458234Skato 43558234Skatostatic void 436168934Simpchange_part(int i, int force) 43758234Skato{ 438108650Snyan struct pc98_partition *partp = 439108650Snyan ((struct pc98_partition *) &mboot.parts) + i - 1; 44058234Skato 441168934Simp if (!force && part_unused(i)) 442168934Simp return; 44358234Skato 444168934Simp printf("The data for partition %d is:\n", i); 445168934Simp print_part(i); 44658234Skato 447168934Simp if (u_flag && ok("Do you want to change it?")) { 448168934Simp int tmp; 449168934Simp 450168934Simp if (i_flag) { 451168934Simp bzero((char *)partp, sizeof (struct pc98_partition)); 452168934Simp if (i == 1) { 453168934Simp init_sector0(1); 454168934Simp printf("\nThe static data for the slice 1 has been reinitialized to:\n"); 455168934Simp print_part(i); 456168934Simp } 45758234Skato } 458168934Simp do { 459168934Simp int x_start = partp->dp_scyl * cylsecs ; 460168934Simp int x_size = (partp->dp_ecyl - partp->dp_scyl + 1) * cylsecs; 461168934Simp Decimal("sysmid", partp->dp_mid, tmp); 462168934Simp Decimal("syssid", partp->dp_sid, tmp); 463168934Simp String ("system name", partp->dp_name, 16); 464168934Simp Decimal("start", x_start, tmp); 465168934Simp Decimal("size", x_size, tmp); 46658234Skato 467168934Simp if (ok("Explicitly specify beg/end address ?")) 468168934Simp { 469168934Simp int tsec,tcyl,thd; 470168934Simp tcyl = partp->dp_scyl; 471168934Simp thd = partp->dp_shd; 472168934Simp tsec = partp->dp_ssect; 473168934Simp Decimal("beginning cylinder", tcyl, tmp); 474168934Simp Decimal("beginning head", thd, tmp); 475168934Simp Decimal("beginning sector", tsec, tmp); 476168934Simp partp->dp_scyl = tcyl; 477168934Simp partp->dp_ssect = tsec; 478168934Simp partp->dp_shd = thd; 479168934Simp partp->dp_ipl_cyl = partp->dp_scyl; 480168934Simp partp->dp_ipl_sct = partp->dp_ssect; 481168934Simp partp->dp_ipl_head = partp->dp_shd; 482106047Snyan 483168934Simp tcyl = partp->dp_ecyl; 484168934Simp thd = partp->dp_ehd; 485168934Simp tsec = partp->dp_esect; 486168934Simp Decimal("ending cylinder", tcyl, tmp); 487168934Simp Decimal("ending head", thd, tmp); 488168934Simp Decimal("ending sector", tsec, tmp); 489168934Simp partp->dp_ecyl = tcyl; 490168934Simp partp->dp_esect = tsec; 491168934Simp partp->dp_ehd = thd; 492168934Simp } else 493168934Simp dos(x_start, x_size, partp); 49458234Skato 495168934Simp print_part(i); 496168934Simp } while (!ok("Are we happy with this entry?")); 497168934Simp } 49858234Skato} 49958234Skato 50058234Skatostatic void 50158234Skatoprint_params() 50258234Skato{ 50358234Skato printf("parameters extracted from in-core disklabel are:\n"); 50458234Skato printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 50558234Skato ,cyls,heads,sectors,cylsecs); 506145765Snyan if (dos_cyls > 65535 || dos_heads > 255 || dos_sectors > 255) 50758234Skato printf("Figures below won't work with BIOS for partitions not in cyl 1\n"); 50858234Skato printf("parameters to be used for BIOS calculations are:\n"); 50958234Skato printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n" 51058234Skato ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs); 51158234Skato} 51258234Skato 51358234Skatostatic void 51458234Skatochange_active(int which) 51558234Skato{ 516145765Snyan struct pc98_partition *partp = &mboot.parts[0]; 517106047Snyan int active, i, new, tmp; 518106047Snyan 519106047Snyan active = -1; 520254015Smarcel for (i = 0; i < PC98_NPARTS; i++) { 521190027Snyan if ((partp[i].dp_sid & PC98_SID_ACTIVE) == 0) 522106047Snyan continue; 523106047Snyan printf("Partition %d is marked active\n", i + 1); 524106047Snyan if (active == -1) 525106047Snyan active = i + 1; 526106047Snyan } 52758234Skato if (a_flag && which != -1) 52858234Skato active = which; 529106047Snyan else if (active == -1) 530106047Snyan active = 1; 531106047Snyan 53258234Skato if (!ok("Do you want to change the active partition?")) 53358234Skato return; 53458234Skatosetactive: 53558234Skato do { 536106047Snyan new = active; 537106047Snyan Decimal("active partition", new, tmp); 538145765Snyan if (new < 1 || new > 8) { 539145765Snyan printf("Active partition number must be in range 1-8." 54058234Skato " Try again.\n"); 54158234Skato goto setactive; 54258234Skato } 543106047Snyan active = new; 54458234Skato } while (!ok("Are you happy with this choice")); 545145765Snyan if (active > 0 && active <= 8) 546190027Snyan partp[active-1].dp_sid |= PC98_SID_ACTIVE; 54758234Skato} 54858234Skato 54958234Skatostatic void 55058234Skatochange_code() 55158234Skato{ 55258234Skato if (ok("Do you want to change the boot code?")) 55358234Skato init_boot(); 55458234Skato} 55558234Skato 55658234Skatovoid 55758234Skatoget_params_to_use() 55858234Skato{ 55958234Skato int tmp; 56058234Skato print_params(); 56158234Skato if (ok("Do you want to change our idea of what BIOS thinks ?")) 56258234Skato { 56358234Skato do 56458234Skato { 56558234Skato Decimal("BIOS's idea of #cylinders", dos_cyls, tmp); 56658234Skato Decimal("BIOS's idea of #heads", dos_heads, tmp); 56758234Skato Decimal("BIOS's idea of #sectors", dos_sectors, tmp); 56858234Skato dos_cylsecs = dos_heads * dos_sectors; 56958234Skato print_params(); 57058234Skato } 57158234Skato while(!ok("Are you happy with this choice")); 57258234Skato } 57358234Skato} 57458234Skato 57558234Skato 57658234Skato/***********************************************\ 57758234Skato* Change real numbers into strange dos numbers * 57858234Skato\***********************************************/ 57958234Skatostatic void 580145765Snyandos(u_int32_t start, u_int32_t size, struct pc98_partition *partp) 58158234Skato{ 582106047Snyan u_int32_t end; 58358234Skato 584145765Snyan if (partp->dp_mid == 0 && partp->dp_sid == 0 && 585145765Snyan start == 0 && size == 0) { 586106047Snyan memcpy(partp, &mtpart, sizeof(*partp)); 587106047Snyan return; 588106047Snyan } 58958234Skato 590106047Snyan /* Start c/h/s. */ 591145765Snyan partp->dp_scyl = partp->dp_ipl_cyl = start / dos_cylsecs; 592145765Snyan partp->dp_shd = partp->dp_ipl_head = start % dos_cylsecs / dos_sectors; 593145765Snyan partp->dp_ssect = partp->dp_ipl_sct = start % dos_sectors; 59458234Skato 595106047Snyan /* End c/h/s. */ 596145765Snyan end = start + size - cylsecs; 597145765Snyan partp->dp_ecyl = end / dos_cylsecs; 598106047Snyan partp->dp_ehd = end % dos_cylsecs / dos_sectors; 599145765Snyan partp->dp_esect = end % dos_sectors; 600106047Snyan} 60158234Skato 60258234Skatostatic int 603106047Snyanopen_disk(int flag) 60458234Skato{ 605106047Snyan struct stat st; 606148062Snyan int rwmode; 60758234Skato 60858234Skato if (stat(disk, &st) == -1) { 609106047Snyan if (errno == ENOENT) 610106047Snyan return -2; 61158234Skato warnx("can't get file status of %s", disk); 61258234Skato return -1; 61358234Skato } 61458234Skato if ( !(st.st_mode & S_IFCHR) ) 61558234Skato warnx("device %s is not character special", disk); 616156020Simp rwmode = I_flag || a_flag || B_flag || flag ? O_RDWR : O_RDONLY; 617110679Snyan fd = open(disk, rwmode); 618148062Snyan if (fd == -1 && errno == EPERM && rwmode == O_RDWR) 619148062Snyan fd = open(disk, O_RDONLY); 620110679Snyan if (fd == -1 && errno == ENXIO) 621110679Snyan return -2; 622110679Snyan if (fd == -1) { 623106047Snyan warnx("can't open device %s", disk); 624106047Snyan return -1; 625106047Snyan } 626106047Snyan if (get_params() == -1) { 62758234Skato warnx("can't get disk parameters on %s", disk); 62858234Skato return -1; 62958234Skato } 63058234Skato return fd; 63158234Skato} 63258234Skato 63358234Skatostatic ssize_t 63458234Skatoread_disk(off_t sector, void *buf) 63558234Skato{ 636145765Snyan 637145765Snyan lseek(fd, (sector * 512), 0); 638106047Snyan return read(fd, buf, 639106047Snyan secsize > MIN_SEC_SIZE ? secsize : MIN_SEC_SIZE * 2); 64058234Skato} 64158234Skato 642148062Snyanstatic int 64358234Skatowrite_disk(off_t sector, void *buf) 64458234Skato{ 645148062Snyan int error; 646148062Snyan struct gctl_req *grq; 647148062Snyan const char *q; 648148062Snyan char fbuf[BUFSIZ]; 649156020Simp int i, fdw, sz; 650110679Snyan 651156020Simp sz = secsize > MIN_SEC_SIZE ? secsize : MIN_SEC_SIZE * 2; 652148062Snyan grq = gctl_get_handle(); 653148062Snyan gctl_ro_param(grq, "verb", -1, "write PC98"); 654148062Snyan gctl_ro_param(grq, "class", -1, "PC98"); 655148062Snyan q = strrchr(disk, '/'); 656148062Snyan if (q == NULL) 657148062Snyan q = disk; 658148062Snyan else 659148062Snyan q++; 660148062Snyan gctl_ro_param(grq, "geom", -1, q); 661156020Simp gctl_ro_param(grq, "data", sz, buf); 662148062Snyan q = gctl_issue(grq); 663150268Snyan if (q == NULL) { 664150268Snyan gctl_free(grq); 665148062Snyan return(0); 666150268Snyan } 667156020Simp warnx("Geom problem: %s", q); 668150268Snyan gctl_free(grq); 669148062Snyan 670156020Simp warnx("Warning: Partitioning via geom failed, trying raw write"); 671156020Simp error = pwrite(fd, buf, sz, sector * 512); 672156020Simp if (error == sz) 673148062Snyan return (0); 674148062Snyan 675254015Smarcel for (i = 0; i < PC98_NPARTS; i++) { 676148062Snyan sprintf(fbuf, "%ss%d", disk, i + 1); 677148062Snyan fdw = open(fbuf, O_RDWR, 0); 678148062Snyan if (fdw < 0) 679148062Snyan continue; 680148062Snyan error = ioctl(fdw, DIOCSPC98, buf); 681148062Snyan close(fdw); 682148062Snyan if (error == 0) 683148062Snyan return (0); 684110679Snyan } 685148062Snyan warnx("Failed to write sector zero"); 686148062Snyan return(EINVAL); 68758234Skato} 68858234Skato 68958234Skatostatic int 69058234Skatoget_params() 69158234Skato{ 692106047Snyan int error; 693106047Snyan u_int u; 694106047Snyan off_t o; 69558234Skato 696106047Snyan error = ioctl(fd, DIOCGFWSECTORS, &u); 697106047Snyan if (error == 0) 698106047Snyan sectors = dos_sectors = u; 699114413Snyan else 700145765Snyan sectors = dos_sectors = 17; 701114413Snyan 702106047Snyan error = ioctl(fd, DIOCGFWHEADS, &u); 703106047Snyan if (error == 0) 704106047Snyan heads = dos_heads = u; 705114413Snyan else 706145765Snyan heads = dos_heads = 8; 707106047Snyan 70858234Skato dos_cylsecs = cylsecs = heads * sectors; 70958234Skato disksecs = cyls * heads * sectors; 710106047Snyan 711106047Snyan error = ioctl(fd, DIOCGSECTORSIZE, &u); 712114413Snyan if (error != 0 || u == 0) 713106047Snyan u = 512; 714106047Snyan secsize = u; 71558234Skato 716106047Snyan error = ioctl(fd, DIOCGMEDIASIZE, &o); 717106047Snyan if (error == 0) { 718106047Snyan disksecs = o / u; 719106047Snyan cyls = dos_cyls = o / (u * dos_heads * dos_sectors); 720106047Snyan } 721106047Snyan 722106047Snyan return (disksecs); 72358234Skato} 72458234Skato 72558234Skato 72658234Skatostatic int 72758234Skatoread_s0() 72858234Skato{ 729145765Snyan 73058234Skato if (read_disk(0, (char *) mboot.bootinst) == -1) { 73158234Skato warnx("can't read fdisk partition table"); 73258234Skato return -1; 73358234Skato } 734254015Smarcel if (mboot.signature != PC98_MAGIC) { 73558234Skato warnx("invalid fdisk partition table found"); 73658234Skato /* So should we initialize things */ 73758234Skato return -1; 73858234Skato } 739145765Snyan 74058234Skato return 0; 74158234Skato} 74258234Skato 74358234Skatostatic int 74458234Skatowrite_s0() 74558234Skato{ 746106047Snyan 74758234Skato if (iotest) { 74858234Skato print_s0(-1); 74958234Skato return 0; 75058234Skato } 751145765Snyan 75258234Skato /* 75358234Skato * write enable label sector before write (if necessary), 75458234Skato * disable after writing. 75558234Skato * needed if the disklabel protected area also protects 75658234Skato * sector 0. (e.g. empty disk) 75758234Skato */ 75858234Skato if (write_disk(0, (char *) mboot.bootinst) == -1) { 75958234Skato warn("can't write fdisk partition table"); 76058234Skato return -1; 761106047Snyan } 762145765Snyan 76358234Skato return(0); 76458234Skato} 76558234Skato 76658234Skato 76758234Skatostatic int 768106047Snyanok(const char *str) 76958234Skato{ 77058234Skato printf("%s [n] ", str); 771106047Snyan fflush(stdout); 772106047Snyan if (fgets(lbuf, LBUF, stdin) == NULL) 773106047Snyan exit(1); 77458234Skato lbuf[strlen(lbuf)-1] = 0; 77558234Skato 77658234Skato if (*lbuf && 77758234Skato (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") || 77858234Skato !strcmp(lbuf, "y") || !strcmp(lbuf, "Y"))) 77958234Skato return 1; 78058234Skato else 78158234Skato return 0; 78258234Skato} 78358234Skato 78458234Skatostatic int 785106047Snyandecimal(const char *str, int *num, int deflt) 78658234Skato{ 787106047Snyan int acc = 0, c; 788106047Snyan char *cp; 78958234Skato 79058234Skato while (1) { 79158234Skato printf("Supply a decimal value for \"%s\" [%d] ", str, deflt); 792106047Snyan fflush(stdout); 793106047Snyan if (fgets(lbuf, LBUF, stdin) == NULL) 794106047Snyan exit(1); 79558234Skato lbuf[strlen(lbuf)-1] = 0; 79658234Skato 79758234Skato if (!*lbuf) 79858234Skato return 0; 79958234Skato 80058234Skato cp = lbuf; 80158234Skato while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 80258234Skato if (!c) 80358234Skato return 0; 80458234Skato while ((c = *cp++)) { 80558234Skato if (c <= '9' && c >= '0') 80658234Skato acc = acc * 10 + c - '0'; 80758234Skato else 80858234Skato break; 80958234Skato } 81058234Skato if (c == ' ' || c == '\t') 81158234Skato while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 81258234Skato if (!c) { 81358234Skato *num = acc; 81458234Skato return 1; 81558234Skato } else 81658234Skato printf("%s is an invalid decimal number. Try again.\n", 81758234Skato lbuf); 81858234Skato } 81958234Skato 82058234Skato} 82158234Skato 82258234Skatostatic int 823145765Snyanstring(const char *str, char **ans) 82458234Skato{ 825106047Snyan int i, c; 826106047Snyan char *cp = lbuf; 82758234Skato 82858234Skato while (1) { 82958234Skato printf("Supply a string value for \"%s\" [%s] ", str, *ans); 83058234Skato fgets(lbuf, LBUF, stdin); 83158234Skato lbuf[strlen(lbuf)-1] = 0; 83258234Skato 83358234Skato if (!*lbuf) 83458234Skato return 0; 83558234Skato 83658234Skato while ((c = *cp) && (c == ' ' || c == '\t')) cp++; 83758234Skato if (c == '"') { 83858234Skato c = *++cp; 83958234Skato *ans = cp; 84058234Skato while ((c = *cp) && c != '"') cp++; 84158234Skato } else { 84258234Skato *ans = cp; 84358234Skato while ((c = *cp) && c != ' ' && c != '\t') cp++; 84458234Skato } 84558234Skato 84658234Skato for (i = strlen(*ans); i < 16; i++) 84758234Skato (*ans)[i] = ' '; 84858234Skato (*ans)[16] = 0; 849106047Snyan 85058234Skato return 1; 85158234Skato } 85258234Skato} 85358234Skato 854106047Snyanstatic const char * 85558234Skatoget_type(int type) 85658234Skato{ 85758234Skato int numentries = (sizeof(part_types)/sizeof(struct part_type)); 85858234Skato int counter = 0; 85958234Skato struct part_type *ptr = part_types; 86058234Skato 86158234Skato 862106047Snyan while(counter < numentries) { 86358234Skato if(ptr->type == (type & 0x7f)) 864106047Snyan return(ptr->name); 86558234Skato ptr++; 86658234Skato counter++; 86758234Skato } 86858234Skato return("unknown"); 86958234Skato} 87058234Skato 871106047Snyan/* 872106047Snyan * Try figuring out the root device's canonical disk name. 873106047Snyan * The following choices are considered: 874106047Snyan * /dev/ad0s1a => /dev/ad0 875106047Snyan * /dev/da0a => /dev/da0 876106047Snyan * /dev/vinum/root => /dev/vinum/root 877106047Snyan */ 878106047Snyanstatic char * 879106047Snyanget_rootdisk(void) 88058234Skato{ 881106047Snyan struct statfs rootfs; 882106047Snyan regex_t re; 883106047Snyan#define NMATCHES 2 884106047Snyan regmatch_t rm[NMATCHES]; 885106047Snyan char *s; 886106047Snyan int rv; 88758234Skato 888106047Snyan if (statfs("/", &rootfs) == -1) 889106047Snyan err(1, "statfs(\"/\")"); 89058234Skato 891106047Snyan if ((rv = regcomp(&re, "^(/dev/[a-z]+[0-9]+)([sp][0-9]+)?[a-h]?$", 892106047Snyan REG_EXTENDED)) != 0) 893106047Snyan errx(1, "regcomp() failed (%d)", rv); 894106047Snyan if ((rv = regexec(&re, rootfs.f_mntfromname, NMATCHES, rm, 0)) != 0) 895106047Snyan errx(1, 896106047Snyan"mounted root fs resource doesn't match expectations (regexec returned %d)", 897106047Snyan rv); 898106047Snyan if ((s = malloc(rm[1].rm_eo - rm[1].rm_so + 1)) == NULL) 899106047Snyan errx(1, "out of memory"); 900106047Snyan memcpy(s, rootfs.f_mntfromname + rm[1].rm_so, 901106047Snyan rm[1].rm_eo - rm[1].rm_so); 902106047Snyan s[rm[1].rm_eo - rm[1].rm_so] = 0; 90358234Skato 904106047Snyan return s; 90558234Skato} 906156020Simp 907156020Simpstatic void 908156020Simpreset_boot(void) 909156020Simp{ 910156020Simp int i; 911156020Simp struct pc98_partition *partp; 912156020Simp 913156020Simp init_boot(); 914254015Smarcel for (i = 1; i <= PC98_NPARTS; i++) { 915156020Simp partp = ((struct pc98_partition *) &mboot.parts) + i - 1; 916156020Simp bzero((char *)partp, sizeof (struct pc98_partition)); 917156020Simp } 918156020Simp} 919