xref: /illumos-gate/usr/src/cmd/fs.d/pcfs/mkfs/mkfs.c (revision 5b5a71c4)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52d700530Sartem  * Common Development and Distribution License (the "License").
62d700530Sartem  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22db92b35aSGary Mills  * Copyright (c) 2011 Gary Mills
23db92b35aSGary Mills  *
2465908c77Syu, larry liu - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25c719c59aSjkennedy  * Use is subject to license terms.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <ctype.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate #include <errno.h>
357c478bd9Sstevel@tonic-gate #include <fcntl.h>
367c478bd9Sstevel@tonic-gate #include <libintl.h>
377c478bd9Sstevel@tonic-gate #include <locale.h>
387c478bd9Sstevel@tonic-gate #include <sys/fdio.h>
397c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
407c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
41*5b5a71c4SToomas Soome #include <sys/vtoc.h>
42*5b5a71c4SToomas Soome #include <sys/efi_partition.h>
437c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
447c478bd9Sstevel@tonic-gate #include "mkfs_pcfs.h"
457c478bd9Sstevel@tonic-gate #include <sys/fs/pc_fs.h>
467c478bd9Sstevel@tonic-gate #include <sys/fs/pc_dir.h>
477c478bd9Sstevel@tonic-gate #include <sys/fs/pc_label.h>
487c478bd9Sstevel@tonic-gate #include <macros.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  *	mkfs (for pcfs)
527c478bd9Sstevel@tonic-gate  *
537c478bd9Sstevel@tonic-gate  *	Install a boot block, FAT, and (if desired) the first resident
547c478bd9Sstevel@tonic-gate  *	of the new fs.
557c478bd9Sstevel@tonic-gate  *
567c478bd9Sstevel@tonic-gate  *	XXX -- floppy opens need O_NDELAY?
577c478bd9Sstevel@tonic-gate  */
58db92b35aSGary Mills #define	IN_RANGE(n, x, y) (((n) >= (x)) && ((n) <= (y)))
597c478bd9Sstevel@tonic-gate #define	DEFAULT_LABEL "NONAME"
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static char	*BootBlkFn = NULL;
627c478bd9Sstevel@tonic-gate static char	*DiskName = NULL;
637c478bd9Sstevel@tonic-gate static char	*FirstFn = NULL;
647c478bd9Sstevel@tonic-gate static char	*Label = NULL;
657c478bd9Sstevel@tonic-gate static char	Firstfileattr = 0x20;
667c478bd9Sstevel@tonic-gate static int	Outputtofile = 0;
677c478bd9Sstevel@tonic-gate static int	SunBPBfields = 0;
687c478bd9Sstevel@tonic-gate static int	GetFsParams = 0;
697c478bd9Sstevel@tonic-gate static int	Fatentsize = 0;
707c478bd9Sstevel@tonic-gate static int	Imagesize = 3;
717c478bd9Sstevel@tonic-gate static int	Notreally = 0;
727c478bd9Sstevel@tonic-gate static int	Verbose = 0;
737c478bd9Sstevel@tonic-gate static int	MakeFAT32 = 0;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * If there is an FDISK entry for the device where we're about to
777c478bd9Sstevel@tonic-gate  * make the file system, we ought to make a file system that has the
787c478bd9Sstevel@tonic-gate  * same size FAT as the FDISK table claims.  We track the size FDISK
797c478bd9Sstevel@tonic-gate  * thinks in this variable.
807c478bd9Sstevel@tonic-gate  */
817c478bd9Sstevel@tonic-gate static int	FdiskFATsize = 0;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate static int	GetSize = 1;	/* Unless we're given as arg, must look it up */
847c478bd9Sstevel@tonic-gate static ulong_t	TotSize;	/* Total size of FS in # of sectors */
857c478bd9Sstevel@tonic-gate static int	GetSPC = 1;	/* Unless we're given as arg, must calculate */
867c478bd9Sstevel@tonic-gate static ulong_t	SecPerClust;	/* # of sectors per cluster */
877c478bd9Sstevel@tonic-gate static int	GetOffset = 1;	/* Unless we're given as arg, must look it up */
887c478bd9Sstevel@tonic-gate static ulong_t	RelOffset;	/* Relative start sector (hidden sectors) */
897c478bd9Sstevel@tonic-gate static int	GetSPT = 1;	/* Unless we're given as arg, must look it up */
907c478bd9Sstevel@tonic-gate static ushort_t	SecPerTrk;	/* # of sectors per track */
917c478bd9Sstevel@tonic-gate static int	GetTPC = 1;	/* Unless we're given as arg, must look it up */
927c478bd9Sstevel@tonic-gate static ushort_t	TrkPerCyl;	/* # of tracks per cylinder */
937c478bd9Sstevel@tonic-gate static int	GetResrvd = 1;	/* Unless we're given as arg, must calculate */
94c719c59aSjkennedy static int	Resrvd;		/* Number of reserved sectors */
957c478bd9Sstevel@tonic-gate static int	GetBPF = 1;	/* Unless we're given as arg, must calculate */
967c478bd9Sstevel@tonic-gate static int	BitsPerFAT;	/* Total size of FS in # of sectors */
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate static ulong_t	TotalClusters;	/* Computed total number of clusters */
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate  * Unless we are told otherwise, we should use fdisk table for non-diskettes.
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate static int	DontUseFdisk = 0;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * Function prototypes
1077c478bd9Sstevel@tonic-gate  */
1087c478bd9Sstevel@tonic-gate #ifndef i386
1097c478bd9Sstevel@tonic-gate static void swap_pack_grabsebpb(bpb_t *wbpb, struct _boot_sector *bsp);
1107c478bd9Sstevel@tonic-gate static void swap_pack_bpb32cpy(struct _boot_sector32 *bsp, bpb_t *wbpb);
1117c478bd9Sstevel@tonic-gate static void swap_pack_sebpbcpy(struct _boot_sector *bsp, bpb_t *wbpb);
1127c478bd9Sstevel@tonic-gate static void swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp);
1137c478bd9Sstevel@tonic-gate static void swap_pack_bpbcpy(struct _boot_sector *bsp, bpb_t *wbpb);
1147c478bd9Sstevel@tonic-gate #endif
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate static uchar_t *build_rootdir(bpb_t *wbpb, char *ffn, int fffd,
1177c478bd9Sstevel@tonic-gate 	ulong_t ffsize, pc_cluster32_t ffstart, ulong_t *rdirsize);
118f127cb91Sfrankho static uchar_t *build_fat(bpb_t *wbpb, struct fat_od_fsi *fsinfop,
1197c478bd9Sstevel@tonic-gate 	ulong_t bootblksize, ulong_t *fatsize, char *ffn, int *fffd,
1207c478bd9Sstevel@tonic-gate 	ulong_t *ffsize, pc_cluster32_t *ffstartclust);
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate static char *stat_actual_disk(char *diskname, struct stat *info, char **suffix);
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate static void compare_existing_with_computed(int fd, char *suffix,
1257c478bd9Sstevel@tonic-gate 	bpb_t *wbpb, int *prtsize, int *prtspc, int *prtbpf, int *prtnsect,
1267c478bd9Sstevel@tonic-gate 	int *prtntrk, int *prtfdisk, int *prthidden, int *prtrsrvd,
1277c478bd9Sstevel@tonic-gate 	int *dashos);
1287c478bd9Sstevel@tonic-gate static void print_reproducing_command(int fd, char *actualdisk, char *suffix,
1297c478bd9Sstevel@tonic-gate 	bpb_t *wbpb);
1307c478bd9Sstevel@tonic-gate static void compute_file_area_size(bpb_t *wbpb);
1317c478bd9Sstevel@tonic-gate static void write_fat32_bootstuff(int fd, boot_sector_t *bsp,
132f127cb91Sfrankho 	struct fat_od_fsi *fsinfop, off64_t seekto);
1337c478bd9Sstevel@tonic-gate static void sanity_check_options(int argc, int optind);
1347c478bd9Sstevel@tonic-gate static void compute_cluster_size(bpb_t *wbpb);
1357c478bd9Sstevel@tonic-gate static void find_fixed_details(int fd, bpb_t *wbpb);
1367c478bd9Sstevel@tonic-gate static void dirent_fname_fill(struct pcdir *dep, char *fn);
1377c478bd9Sstevel@tonic-gate static void floppy_bpb_fillin(bpb_t *wbpb,
1387c478bd9Sstevel@tonic-gate 	int diam, int hds, int spt);
1397c478bd9Sstevel@tonic-gate static void read_existing_bpb(int fd, bpb_t *wbpb);
1407c478bd9Sstevel@tonic-gate static void warn_funky_fatsize(void);
1417c478bd9Sstevel@tonic-gate static void warn_funky_floppy(void);
1427c478bd9Sstevel@tonic-gate static void dirent_time_fill(struct pcdir *dep);
1437c478bd9Sstevel@tonic-gate static void parse_suboptions(char *optsstr);
1447c478bd9Sstevel@tonic-gate static void header_for_dump(void);
1457c478bd9Sstevel@tonic-gate static void write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb,
146f127cb91Sfrankho 	struct fat_od_fsi *fsinfop, off64_t seekto);
1477c478bd9Sstevel@tonic-gate static void fill_bpb_sizes(bpb_t *wbpb, struct ipart part[],
1487c478bd9Sstevel@tonic-gate 	int partno, off64_t offset);
1497c478bd9Sstevel@tonic-gate static void set_fat_string(bpb_t *wbpb, int fatsize);
1507c478bd9Sstevel@tonic-gate static void partn_lecture(char *dn);
1517c478bd9Sstevel@tonic-gate static void store_16_bits(uchar_t **bp, uint32_t v);
1527c478bd9Sstevel@tonic-gate static void store_32_bits(uchar_t **bp, uint32_t v);
1537c478bd9Sstevel@tonic-gate static void lookup_floppy(struct fd_char *fdchar, bpb_t *wbpb);
1547c478bd9Sstevel@tonic-gate static void label_volume(char *lbl, bpb_t *wbpb);
1557c478bd9Sstevel@tonic-gate static void mark_cluster(uchar_t *fatp, pc_cluster32_t clustnum,
1567c478bd9Sstevel@tonic-gate 	uint32_t value);
1577c478bd9Sstevel@tonic-gate static void missing_arg(char *option);
1587c478bd9Sstevel@tonic-gate static void dashm_bail(int fd);
1597c478bd9Sstevel@tonic-gate static void dump_bytes(uchar_t *, int);
1607c478bd9Sstevel@tonic-gate static void write_rest(bpb_t *wbpb, char *efn,
1617c478bd9Sstevel@tonic-gate 	int dfd, int sfd, int remaining);
1627c478bd9Sstevel@tonic-gate static void write_fat(int fd, off64_t seekto, char *fn, char *lbl,
1637c478bd9Sstevel@tonic-gate 	char *ffn, bpb_t *wbpb);
1647c478bd9Sstevel@tonic-gate static void bad_arg(char *option);
1657c478bd9Sstevel@tonic-gate static void usage(void);
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate static int prepare_image_file(char *fn, bpb_t *wbpb);
1687c478bd9Sstevel@tonic-gate static int verify_bootblkfile(char *fn, boot_sector_t *bs,
1697c478bd9Sstevel@tonic-gate 	ulong_t *blkfilesize);
1707c478bd9Sstevel@tonic-gate static int open_and_examine(char *dn, bpb_t *wbpb);
1717c478bd9Sstevel@tonic-gate static int verify_firstfile(char *fn, ulong_t *filesize);
1727c478bd9Sstevel@tonic-gate static int lookup_FAT_size(uchar_t partid);
1737c478bd9Sstevel@tonic-gate static int open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto);
1747c478bd9Sstevel@tonic-gate static int warn_mismatch(char *desc, char *src, int expect, int assigned);
1757c478bd9Sstevel@tonic-gate static int copy_bootblk(char *fn, boot_sector_t *bootsect,
1767c478bd9Sstevel@tonic-gate 	ulong_t *bootblksize);
1777c478bd9Sstevel@tonic-gate static int parse_drvnum(char *pn);
1787c478bd9Sstevel@tonic-gate static int seek_nofdisk(int fd, bpb_t *wbpb, off64_t *seekto);
1797c478bd9Sstevel@tonic-gate static int ask_nicely(char *special);
1807c478bd9Sstevel@tonic-gate static int seek_partn(int fd, char *pn, bpb_t *wbpb, off64_t *seekto);
1817c478bd9Sstevel@tonic-gate static int yes(void);
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  *  usage
1857c478bd9Sstevel@tonic-gate  *
1867c478bd9Sstevel@tonic-gate  *	Display usage message and exit.
1877c478bd9Sstevel@tonic-gate  */
1887c478bd9Sstevel@tonic-gate static
1897c478bd9Sstevel@tonic-gate void
usage(void)1907c478bd9Sstevel@tonic-gate usage(void)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
1937c478bd9Sstevel@tonic-gate 	    gettext("pcfs usage: mkfs [-F FSType] [-V] [-m] "
194f127cb91Sfrankho 	    "[-o specific_options] special\n"));
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
1977c478bd9Sstevel@tonic-gate 	    gettext(" -V: print this command line and return\n"
198f127cb91Sfrankho 	    " -m: dump command line used to create a FAT on this media\n"
199f127cb91Sfrankho 	    "\t(other options are ignored if this option is chosen).\n"
200f127cb91Sfrankho 	    " -o: pcfs_specific_options:\n"
201f127cb91Sfrankho 	    "\t'pcfs_specific_options' is a comma separated list\n"
202f127cb91Sfrankho 	    "\tincluding one or more of the following options:\n"
203f127cb91Sfrankho 	    "\t    N,v,r,h,s,b=label,B=filename,i=filename,\n"
204f127cb91Sfrankho 	    "\t    spc=n,fat=n,nsect=n,ntrack=n,nofdisk,size=n,\n"
205f127cb91Sfrankho 	    "\t    reserve=n,hidden=n\n\n"));
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
2087c478bd9Sstevel@tonic-gate 	    gettext("'Special' should specify a raw diskette "
209f127cb91Sfrankho 	    "or raw fixed disk device.  \"Fixed\"\n"
210f127cb91Sfrankho 	    "disks (which include high-capacity removable "
211f127cb91Sfrankho 	    "media such as Zip disks)\n"
212f127cb91Sfrankho 	    "may be further qualified with a logical "
213f127cb91Sfrankho 	    "drive specifier.\n"
214f127cb91Sfrankho 	    "Examples are: /dev/rdiskette and "
215f127cb91Sfrankho 	    "/dev/rdsk/c0t0d0p0:c\n"));
2167c478bd9Sstevel@tonic-gate 	exit(1);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate static
2207c478bd9Sstevel@tonic-gate int
yes(void)2217c478bd9Sstevel@tonic-gate yes(void)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate 	char *affirmative = gettext("yY");
2247c478bd9Sstevel@tonic-gate 	char *a = affirmative;
2257c478bd9Sstevel@tonic-gate 	int b;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	b = getchar();
2287c478bd9Sstevel@tonic-gate 	while (b == '\n' && b != '\0' && b != EOF)
2297c478bd9Sstevel@tonic-gate 		b = getchar();
2307c478bd9Sstevel@tonic-gate 	while (*a) {
2317c478bd9Sstevel@tonic-gate 		if (b == (int)*a)
2327c478bd9Sstevel@tonic-gate 			break;
2337c478bd9Sstevel@tonic-gate 		a++;
2347c478bd9Sstevel@tonic-gate 	}
2357c478bd9Sstevel@tonic-gate 	return (*a);
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate static
2397c478bd9Sstevel@tonic-gate int
ask_nicely(char * special)2407c478bd9Sstevel@tonic-gate ask_nicely(char *special)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 	/*
2437c478bd9Sstevel@tonic-gate 	 * 4228473 - No way to non-interactively make a pcfs filesystem
2447c478bd9Sstevel@tonic-gate 	 *
2457c478bd9Sstevel@tonic-gate 	 *	If we don't have an input TTY, or we aren't really doing
2467c478bd9Sstevel@tonic-gate 	 *	anything, then don't ask questions.  Assume a yes answer
2477c478bd9Sstevel@tonic-gate 	 *	to any questions we would ask.
2487c478bd9Sstevel@tonic-gate 	 */
2497c478bd9Sstevel@tonic-gate 	if (Notreally || !isatty(fileno(stdin)))
2507c478bd9Sstevel@tonic-gate 		return (1);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	(void) printf(
2537c478bd9Sstevel@tonic-gate 	    gettext("Construct a new FAT file system on %s: (y/n)? "), special);
2547c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
2557c478bd9Sstevel@tonic-gate 	return (yes());
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate  * store_16_bits
2607c478bd9Sstevel@tonic-gate  *	Save the lower 16 bits of a 32 bit value (v) into the provided
2617c478bd9Sstevel@tonic-gate  *	buffer (pointed at by *bp), and increment the buffer pointer
2627c478bd9Sstevel@tonic-gate  *	as well.  This way the routine can be called multiple times in
2637c478bd9Sstevel@tonic-gate  *	succession to fill buffers.  The value is stored in little-endian
2647c478bd9Sstevel@tonic-gate  *	order.
2657c478bd9Sstevel@tonic-gate  */
2667c478bd9Sstevel@tonic-gate static
2677c478bd9Sstevel@tonic-gate void
store_16_bits(uchar_t ** bp,uint32_t v)2687c478bd9Sstevel@tonic-gate store_16_bits(uchar_t **bp, uint32_t v)
2697c478bd9Sstevel@tonic-gate {
2707c478bd9Sstevel@tonic-gate 	uchar_t *l = *bp;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	*l++ = v & 0xff;
2737c478bd9Sstevel@tonic-gate 	*l = (v >> 8) & 0xff;
2747c478bd9Sstevel@tonic-gate 	*bp += 2;
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate  * store_32_bits
2797c478bd9Sstevel@tonic-gate  * 	Save the 32 bit value (v) into the provided buffer (pointed
2807c478bd9Sstevel@tonic-gate  *	at by *bp), and increment the buffer pointer as well.  This way
2817c478bd9Sstevel@tonic-gate  *	the routine can be called multiple times in succession to fill
2827c478bd9Sstevel@tonic-gate  *	buffers.  The value is stored in little-endian order.
2837c478bd9Sstevel@tonic-gate  */
2847c478bd9Sstevel@tonic-gate static
2857c478bd9Sstevel@tonic-gate void
store_32_bits(uchar_t ** bp,uint32_t v)2867c478bd9Sstevel@tonic-gate store_32_bits(uchar_t **bp, uint32_t v)
2877c478bd9Sstevel@tonic-gate {
2887c478bd9Sstevel@tonic-gate 	uchar_t *l = *bp;
2897c478bd9Sstevel@tonic-gate 	int b;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	for (b = 0; b < 4; b++) {
2927c478bd9Sstevel@tonic-gate 		*l++ = v & 0xff;
2937c478bd9Sstevel@tonic-gate 		v = v >> 8;
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 	*bp += 4;
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate  *  dump_bytes  -- display bytes as hex numbers.
3007c478bd9Sstevel@tonic-gate  *		   b is the pointer to the byte buffer
3017c478bd9Sstevel@tonic-gate  *		   n is the number of bytes in the buffer
3027c478bd9Sstevel@tonic-gate  */
3037c478bd9Sstevel@tonic-gate /* Note: BPL = bytes to display per line */
3047c478bd9Sstevel@tonic-gate #define	BPL 16
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate static
3077c478bd9Sstevel@tonic-gate void
dump_bytes(uchar_t * b,int n)3087c478bd9Sstevel@tonic-gate dump_bytes(uchar_t *b, int n)
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate 	int cd = n;
3117c478bd9Sstevel@tonic-gate 	int cu = 0;
3127c478bd9Sstevel@tonic-gate 	int o = 0;
3137c478bd9Sstevel@tonic-gate 	int bl;
3147c478bd9Sstevel@tonic-gate 	int ac;
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	/* Display offset, 16 bytes per line, and printable ascii version */
3177c478bd9Sstevel@tonic-gate 	while (cd > 0) {
3187c478bd9Sstevel@tonic-gate 		ac = 0;
3197c478bd9Sstevel@tonic-gate 		(void) printf("\n%06x: ", o);
3207c478bd9Sstevel@tonic-gate 		for (bl = 0; bl < BPL; bl++) {
3217c478bd9Sstevel@tonic-gate 			if (cu+bl < n) {
3227c478bd9Sstevel@tonic-gate 				(void) printf("%02x ", (b[cu+bl] & 0xff));
3237c478bd9Sstevel@tonic-gate 				ac++;
3247c478bd9Sstevel@tonic-gate 			}
3257c478bd9Sstevel@tonic-gate 			else
3267c478bd9Sstevel@tonic-gate 				(void) printf("   ");
3277c478bd9Sstevel@tonic-gate 		}
3287c478bd9Sstevel@tonic-gate 		for (bl = 0; bl < BPL; bl++) {
3297c478bd9Sstevel@tonic-gate 			if ((cu+bl < n) &&
330f127cb91Sfrankho 			    ((b[cu+bl] >= ' ') && (b[cu+bl] <= '~')))
331f127cb91Sfrankho 				(void) printf("%c", b[cu+bl]);
3327c478bd9Sstevel@tonic-gate 			else
3337c478bd9Sstevel@tonic-gate 				(void) printf(".");
3347c478bd9Sstevel@tonic-gate 		}
3357c478bd9Sstevel@tonic-gate 		cu += ac; o += ac; cd -= ac;
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 	(void) printf("\n\n");
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate /*
3417c478bd9Sstevel@tonic-gate  *  header_for_dump  --  display simple header over what will be output.
3427c478bd9Sstevel@tonic-gate  */
3437c478bd9Sstevel@tonic-gate static
3447c478bd9Sstevel@tonic-gate void
header_for_dump(void)3457c478bd9Sstevel@tonic-gate header_for_dump(void)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate 	int bl;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	(void) printf("\n        ");
3507c478bd9Sstevel@tonic-gate 	for (bl = 0; bl < BPL; bl++)
3517c478bd9Sstevel@tonic-gate 		(void) printf("%02x ", bl);
3527c478bd9Sstevel@tonic-gate 	(void) printf("\n       ");
3537c478bd9Sstevel@tonic-gate 	bl = 3*BPL;
3547c478bd9Sstevel@tonic-gate 	while (bl-- > 0)
3557c478bd9Sstevel@tonic-gate 		(void) printf("-");
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate /*
3597c478bd9Sstevel@tonic-gate  *  parse_drvnum
3607c478bd9Sstevel@tonic-gate  *	Convert a partition name into a drive number.
3617c478bd9Sstevel@tonic-gate  */
3627c478bd9Sstevel@tonic-gate static
3637c478bd9Sstevel@tonic-gate int
parse_drvnum(char * pn)3647c478bd9Sstevel@tonic-gate parse_drvnum(char *pn)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate 	int drvnum;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	/*
3697c478bd9Sstevel@tonic-gate 	 * Determine logical drive to seek after.
3707c478bd9Sstevel@tonic-gate 	 */
3717c478bd9Sstevel@tonic-gate 	if (strlen(pn) == 1 && *pn >= 'c' && *pn <= 'z') {
3727c478bd9Sstevel@tonic-gate 		drvnum = *pn - 'c' + 1;
3737c478bd9Sstevel@tonic-gate 	} else if (*pn >= '0' && *pn <= '9') {
3747c478bd9Sstevel@tonic-gate 		char *d;
3757c478bd9Sstevel@tonic-gate 		int v, m, c;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 		v = 0;
3787c478bd9Sstevel@tonic-gate 		d = pn;
3797c478bd9Sstevel@tonic-gate 		while (*d && *d >= '0' && *d <= '9') {
3807c478bd9Sstevel@tonic-gate 			c = strlen(d);
3817c478bd9Sstevel@tonic-gate 			m = 1;
3827c478bd9Sstevel@tonic-gate 			while (--c)
3837c478bd9Sstevel@tonic-gate 				m *= 10;
3847c478bd9Sstevel@tonic-gate 			v += m * (*d - '0');
3857c478bd9Sstevel@tonic-gate 			d++;
3867c478bd9Sstevel@tonic-gate 		}
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 		if (*d || v > 24) {
3897c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
3907c478bd9Sstevel@tonic-gate 			    gettext("%s: bogus logical drive specification.\n"),
3917c478bd9Sstevel@tonic-gate 			    pn);
3927c478bd9Sstevel@tonic-gate 			return (-1);
3937c478bd9Sstevel@tonic-gate 		}
3947c478bd9Sstevel@tonic-gate 		drvnum = v;
3957c478bd9Sstevel@tonic-gate 	} else if (strcmp(pn, "boot") == 0) {
3967c478bd9Sstevel@tonic-gate 		drvnum = 99;
3977c478bd9Sstevel@tonic-gate 	} else {
3987c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3997c478bd9Sstevel@tonic-gate 		    gettext("%s: bogus logical drive specification.\n"), pn);
4007c478bd9Sstevel@tonic-gate 		return (-1);
4017c478bd9Sstevel@tonic-gate 	}
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	return (drvnum);
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate  *  Define some special logical drives we use.
4087c478bd9Sstevel@tonic-gate  */
4097c478bd9Sstevel@tonic-gate #define	BOOT_PARTITION_DRIVE	99
4107c478bd9Sstevel@tonic-gate #define	PRIMARY_DOS_DRIVE	1
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate  * isDosDrive()
4147c478bd9Sstevel@tonic-gate  *	Boolean function.  Give it the systid field for an fdisk partition
4157c478bd9Sstevel@tonic-gate  *	and it decides if that's a systid that describes a DOS drive.  We
4167c478bd9Sstevel@tonic-gate  *	use systid values defined in sys/dktp/fdisk.h.
4177c478bd9Sstevel@tonic-gate  */
4187c478bd9Sstevel@tonic-gate static int
isDosDrive(uchar_t checkMe)4197c478bd9Sstevel@tonic-gate isDosDrive(uchar_t checkMe)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 	return ((checkMe == DOSOS12) || (checkMe == DOSOS16) ||
4227c478bd9Sstevel@tonic-gate 	    (checkMe == DOSHUGE) || (checkMe == FDISK_WINDOWS) ||
4237c478bd9Sstevel@tonic-gate 	    (checkMe == FDISK_EXT_WIN) || (checkMe == FDISK_FAT95) ||
4247c478bd9Sstevel@tonic-gate 	    (checkMe == DIAGPART));
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate /*
4287c478bd9Sstevel@tonic-gate  * isDosExtended()
4297c478bd9Sstevel@tonic-gate  *	Boolean function.  Give it the systid field for an fdisk partition
4307c478bd9Sstevel@tonic-gate  *	and it decides if that's a systid that describes an extended DOS
4317c478bd9Sstevel@tonic-gate  *	partition.
4327c478bd9Sstevel@tonic-gate  */
4337c478bd9Sstevel@tonic-gate static int
isDosExtended(uchar_t checkMe)4347c478bd9Sstevel@tonic-gate isDosExtended(uchar_t checkMe)
4357c478bd9Sstevel@tonic-gate {
4367c478bd9Sstevel@tonic-gate 	return ((checkMe == EXTDOS) || (checkMe == FDISK_EXTLBA));
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate  * isBootPart()
4417c478bd9Sstevel@tonic-gate  *	Boolean function.  Give it the systid field for an fdisk partition
4427c478bd9Sstevel@tonic-gate  *	and it decides if that's a systid that describes a Solaris boot
4437c478bd9Sstevel@tonic-gate  *	partition.
4447c478bd9Sstevel@tonic-gate  */
4457c478bd9Sstevel@tonic-gate static int
isBootPart(uchar_t checkMe)4467c478bd9Sstevel@tonic-gate isBootPart(uchar_t checkMe)
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate 	return (checkMe == X86BOOT);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate static
4527c478bd9Sstevel@tonic-gate int
warn_mismatch(char * desc,char * src,int expect,int assigned)4537c478bd9Sstevel@tonic-gate warn_mismatch(char *desc, char *src, int expect, int assigned)
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate 	if (expect == assigned)
4567c478bd9Sstevel@tonic-gate 		return (assigned);
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	/*
4597c478bd9Sstevel@tonic-gate 	 * 4228473 - No way to non-interactively make a pcfs filesystem
4607c478bd9Sstevel@tonic-gate 	 *
4617c478bd9Sstevel@tonic-gate 	 *	If we don't have an input TTY, or we aren't really doing
4627c478bd9Sstevel@tonic-gate 	 *	anything, then don't ask questions.  Assume a yes answer
4637c478bd9Sstevel@tonic-gate 	 *	to any questions we would ask.
4647c478bd9Sstevel@tonic-gate 	 */
4657c478bd9Sstevel@tonic-gate 	if (Notreally || !isatty(fileno(stdin))) {
4667c478bd9Sstevel@tonic-gate 		(void) printf(gettext("WARNING: User supplied %s is %d,"
467f127cb91Sfrankho 		    "\nbut value obtained from the %s is %d.\n"
468f127cb91Sfrankho 		    "Using user supplied value.\n"),
469f127cb91Sfrankho 		    desc, assigned, src, expect);
4707c478bd9Sstevel@tonic-gate 		return (assigned);
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	(void) printf(gettext("User supplied %s is %d."
474f127cb91Sfrankho 	    "\nThe value obtained from the %s is %d.\n"),
475f127cb91Sfrankho 	    desc, assigned, src, expect);
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	(void) printf(
4787c478bd9Sstevel@tonic-gate 	    gettext("Continue with value given on command line (y/n)? "));
4797c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
4807c478bd9Sstevel@tonic-gate 	if (yes())
4817c478bd9Sstevel@tonic-gate 		return (assigned);
4827c478bd9Sstevel@tonic-gate 	else
4837c478bd9Sstevel@tonic-gate 		exit(2);
4847c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate static
4887c478bd9Sstevel@tonic-gate void
fill_fat32_bpb(bpb_t * wbpb)4897c478bd9Sstevel@tonic-gate fill_fat32_bpb(bpb_t *wbpb)
4907c478bd9Sstevel@tonic-gate {
4917c478bd9Sstevel@tonic-gate 	/*
4927c478bd9Sstevel@tonic-gate 	 * ExtFlags means (according to MSDN BPB (FAT32) document)
4937c478bd9Sstevel@tonic-gate 	 *
4947c478bd9Sstevel@tonic-gate 	 * Bit 8 indicates info written to the active FAT is written
4957c478bd9Sstevel@tonic-gate 	 * to all copies of the FAT.  (I think they mean bit 7, with
4967c478bd9Sstevel@tonic-gate 	 * numbering starting at 0)
4977c478bd9Sstevel@tonic-gate 	 *
4987c478bd9Sstevel@tonic-gate 	 * Lowest 4 bits of field are the 0 based FAT number of the
4997c478bd9Sstevel@tonic-gate 	 * Active FAT.  (only meaningful if bit 8 is set)
5007c478bd9Sstevel@tonic-gate 	 *
5017c478bd9Sstevel@tonic-gate 	 * Field contains combination of these values:
5027c478bd9Sstevel@tonic-gate 	 *
5037c478bd9Sstevel@tonic-gate 	 *	VALUE				DESCRIPTION
5047c478bd9Sstevel@tonic-gate 	 * BGBPB_F_ActiveFATMsk		Mask for low four bits
5057c478bd9Sstevel@tonic-gate 	 * (0x000F)
5067c478bd9Sstevel@tonic-gate 	 * BGBPB_F_NoFATMirror		If set FAT mirroring disabled.
5077c478bd9Sstevel@tonic-gate 	 * (0x0080)			If clear, FAT mirroring enabled.
5087c478bd9Sstevel@tonic-gate 	 *
5097c478bd9Sstevel@tonic-gate 	 * We set the value based on what I've seen on all the FAT32 drives
5107c478bd9Sstevel@tonic-gate 	 * I've seen created by Windows.
5117c478bd9Sstevel@tonic-gate 	 *
5127c478bd9Sstevel@tonic-gate 	 */
5137c478bd9Sstevel@tonic-gate 	wbpb->bpb32.ext_flags = 0x0;
5147c478bd9Sstevel@tonic-gate 	/*
5157c478bd9Sstevel@tonic-gate 	 * No real explanation of the fs_vers file in the BPB doc.  The
5167c478bd9Sstevel@tonic-gate 	 * high byte is supposed to be the major version and the low the
5177c478bd9Sstevel@tonic-gate 	 * minor version.  Again I set according to what I've seen on Windows.
5187c478bd9Sstevel@tonic-gate 	 */
5197c478bd9Sstevel@tonic-gate 	wbpb->bpb32.fs_vers_lo = '\0';
5207c478bd9Sstevel@tonic-gate 	wbpb->bpb32.fs_vers_hi = '\0';
5217c478bd9Sstevel@tonic-gate 	/*
5227c478bd9Sstevel@tonic-gate 	 * The convention appears to be to place the fs info sector
5237c478bd9Sstevel@tonic-gate 	 * immediately after the boot sector, and that the backup boot
5247c478bd9Sstevel@tonic-gate 	 * sector should be at sector 6. (based on what I see with
5257c478bd9Sstevel@tonic-gate 	 * Windows)
5267c478bd9Sstevel@tonic-gate 	 */
5277c478bd9Sstevel@tonic-gate 	wbpb->bpb32.fsinfosec = 1;
5287c478bd9Sstevel@tonic-gate 	wbpb->bpb32.backupboot = 6;
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate static
5327c478bd9Sstevel@tonic-gate void
fill_bpb_sizes(bpb_t * wbpb,struct ipart part[],int partno,off64_t offset)5337c478bd9Sstevel@tonic-gate fill_bpb_sizes(bpb_t *wbpb, struct ipart part[], int partno, off64_t offset)
5347c478bd9Sstevel@tonic-gate {
5357c478bd9Sstevel@tonic-gate 	ulong_t usesize;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if (GetFsParams || GetSize) {
5387c478bd9Sstevel@tonic-gate 		usesize = ltohi(part[partno].numsect);
5397c478bd9Sstevel@tonic-gate 		if (Verbose) {
540f127cb91Sfrankho 			(void) printf(
541f127cb91Sfrankho 			    gettext("Partition size (from FDISK table) "
5427c478bd9Sstevel@tonic-gate 			    "= %d sectors.\n"), usesize);
5437c478bd9Sstevel@tonic-gate 		}
5447c478bd9Sstevel@tonic-gate 	} else {
5457c478bd9Sstevel@tonic-gate 		usesize = warn_mismatch(
5467c478bd9Sstevel@tonic-gate 		    gettext("length of partition (in sectors)"),
5477c478bd9Sstevel@tonic-gate 		    gettext("FDISK table"),
5487c478bd9Sstevel@tonic-gate 		    ltohi(part[partno].numsect), TotSize);
5497c478bd9Sstevel@tonic-gate 	}
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	if (GetFsParams) {
5527c478bd9Sstevel@tonic-gate 		TotSize = usesize;
5537c478bd9Sstevel@tonic-gate 	} else {
5547c478bd9Sstevel@tonic-gate 		if (usesize > 0xffff)
5557c478bd9Sstevel@tonic-gate 			wbpb->bpb.sectors_in_volume = 0;
5567c478bd9Sstevel@tonic-gate 		else
5577c478bd9Sstevel@tonic-gate 			wbpb->bpb.sectors_in_volume = usesize;
5587c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_in_logical_volume = usesize;
5597c478bd9Sstevel@tonic-gate 	}
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	wbpb->bpb.hidden_sectors = offset;
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	if (GetFsParams) {
5647c478bd9Sstevel@tonic-gate 		RelOffset = offset;
5657c478bd9Sstevel@tonic-gate 	} else {
5667c478bd9Sstevel@tonic-gate 		wbpb->sunbpb.bs_offset_high = offset >> 16;
5677c478bd9Sstevel@tonic-gate 		wbpb->sunbpb.bs_offset_low = offset & 0xFFFF;
5687c478bd9Sstevel@tonic-gate 	}
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate /*
5727c478bd9Sstevel@tonic-gate  *  lookup_FAT_size
5737c478bd9Sstevel@tonic-gate  *
5747c478bd9Sstevel@tonic-gate  *	Given the FDISK partition file system identifier, return the
5757c478bd9Sstevel@tonic-gate  *	expected FAT size for the partition.
5767c478bd9Sstevel@tonic-gate  */
5777c478bd9Sstevel@tonic-gate static
5787c478bd9Sstevel@tonic-gate int
lookup_FAT_size(uchar_t partid)5797c478bd9Sstevel@tonic-gate lookup_FAT_size(uchar_t partid)
5807c478bd9Sstevel@tonic-gate {
5817c478bd9Sstevel@tonic-gate 	int rval;
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	switch (partid) {
5847c478bd9Sstevel@tonic-gate 	case DOSOS12:
5857c478bd9Sstevel@tonic-gate 		rval = 12;
5867c478bd9Sstevel@tonic-gate 		break;
5877c478bd9Sstevel@tonic-gate 	case DOSOS16:
5887c478bd9Sstevel@tonic-gate 	case DOSHUGE:
5897c478bd9Sstevel@tonic-gate 	case FDISK_FAT95:
5907c478bd9Sstevel@tonic-gate 	case X86BOOT:
5917c478bd9Sstevel@tonic-gate 		rval = 16;
5927c478bd9Sstevel@tonic-gate 		break;
5937c478bd9Sstevel@tonic-gate 	case FDISK_WINDOWS:
5947c478bd9Sstevel@tonic-gate 	case FDISK_EXT_WIN:
5957c478bd9Sstevel@tonic-gate 		rval = 32;
5967c478bd9Sstevel@tonic-gate 		break;
5977c478bd9Sstevel@tonic-gate 	case EXTDOS:
5987c478bd9Sstevel@tonic-gate 	case FDISK_EXTLBA:
5997c478bd9Sstevel@tonic-gate 	default:
6007c478bd9Sstevel@tonic-gate 		rval = -1;
6017c478bd9Sstevel@tonic-gate 		break;
6027c478bd9Sstevel@tonic-gate 	}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	return (rval);
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate /*
6087c478bd9Sstevel@tonic-gate  *  seek_partn
6097c478bd9Sstevel@tonic-gate  *
6107c478bd9Sstevel@tonic-gate  *	Seek to the beginning of the partition where we need to install
6117c478bd9Sstevel@tonic-gate  *	the new FAT.  Zero return for any error, but print error
6127c478bd9Sstevel@tonic-gate  *	messages here.
6137c478bd9Sstevel@tonic-gate  */
6147c478bd9Sstevel@tonic-gate static
6157c478bd9Sstevel@tonic-gate int
seek_partn(int fd,char * pn,bpb_t * wbpb,off64_t * seekto)6167c478bd9Sstevel@tonic-gate seek_partn(int fd, char *pn, bpb_t *wbpb, off64_t *seekto)
6177c478bd9Sstevel@tonic-gate {
6187c478bd9Sstevel@tonic-gate 	struct ipart part[FD_NUMPART];
6197c478bd9Sstevel@tonic-gate 	struct mboot extmboot;
6207c478bd9Sstevel@tonic-gate 	struct mboot mb;
621342440ecSPrasad Singamsetty 	diskaddr_t xstartsect;
6227c478bd9Sstevel@tonic-gate 	off64_t nextseek = 0;
6237c478bd9Sstevel@tonic-gate 	off64_t lastseek = 0;
6247c478bd9Sstevel@tonic-gate 	int logicalDriveCount = 0;
6257c478bd9Sstevel@tonic-gate 	int extendedPart = -1;
6267c478bd9Sstevel@tonic-gate 	int primaryPart = -1;
6277c478bd9Sstevel@tonic-gate 	int bootPart = -1;
628342440ecSPrasad Singamsetty 	uint32_t xnumsect = 0;
6297c478bd9Sstevel@tonic-gate 	int drvnum;
6307c478bd9Sstevel@tonic-gate 	int driveIndex;
6317c478bd9Sstevel@tonic-gate 	int i;
6327c478bd9Sstevel@tonic-gate 	/*
6337c478bd9Sstevel@tonic-gate 	 * Count of drives in the current extended partition's
6347c478bd9Sstevel@tonic-gate 	 * FDISK table, and indexes of the drives themselves.
6357c478bd9Sstevel@tonic-gate 	 */
6367c478bd9Sstevel@tonic-gate 	int extndDrives[FD_NUMPART];
6377c478bd9Sstevel@tonic-gate 	int numDrives = 0;
6387c478bd9Sstevel@tonic-gate 	/*
6397c478bd9Sstevel@tonic-gate 	 * Count of drives (beyond primary) in master boot record's
6407c478bd9Sstevel@tonic-gate 	 * FDISK table, and indexes of the drives themselves.
6417c478bd9Sstevel@tonic-gate 	 */
6427c478bd9Sstevel@tonic-gate 	int extraDrives[FD_NUMPART];
6437c478bd9Sstevel@tonic-gate 	int numExtraDrives = 0;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	if ((drvnum = parse_drvnum(pn)) < 0)
6467c478bd9Sstevel@tonic-gate 		return (PART_NOT_FOUND);
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	if (read(fd, &mb, sizeof (mb)) != sizeof (mb)) {
6497c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6507c478bd9Sstevel@tonic-gate 		    gettext("Couldn't read a Master Boot Record?!\n"));
6517c478bd9Sstevel@tonic-gate 		return (PART_NOT_FOUND);
6527c478bd9Sstevel@tonic-gate 	}
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	if (ltohs(mb.signature) != BOOTSECSIG) {
6557c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
6567c478bd9Sstevel@tonic-gate 		    gettext("Bad Sig on master boot record!\n"));
6577c478bd9Sstevel@tonic-gate 		return (PART_NOT_FOUND);
6587c478bd9Sstevel@tonic-gate 	}
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	*seekto = 0;
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	/*
6637c478bd9Sstevel@tonic-gate 	 * Copy partition table into memory
6647c478bd9Sstevel@tonic-gate 	 */
6657c478bd9Sstevel@tonic-gate 	(void) memcpy(part, mb.parts, sizeof (part));
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	/*
6687c478bd9Sstevel@tonic-gate 	 * Get a summary of what is in the Master FDISK table.
6697c478bd9Sstevel@tonic-gate 	 * Normally we expect to find one partition marked as a DOS drive.
6707c478bd9Sstevel@tonic-gate 	 * This partition is the one Windows calls the primary dos partition.
6717c478bd9Sstevel@tonic-gate 	 * If the machine has any logical drives then we also expect
6727c478bd9Sstevel@tonic-gate 	 * to find a partition marked as an extended DOS partition.
6737c478bd9Sstevel@tonic-gate 	 *
6747c478bd9Sstevel@tonic-gate 	 * Sometimes we'll find multiple partitions marked as DOS drives.
6757c478bd9Sstevel@tonic-gate 	 * The Solaris fdisk program allows these partitions
6767c478bd9Sstevel@tonic-gate 	 * to be created, but Windows fdisk no longer does.  We still need
6777c478bd9Sstevel@tonic-gate 	 * to support these, though, since Windows does.  We also need to fix
6787c478bd9Sstevel@tonic-gate 	 * our fdisk to behave like the Windows version.
6797c478bd9Sstevel@tonic-gate 	 *
6807c478bd9Sstevel@tonic-gate 	 * It turns out that some off-the-shelf media have *only* an
6817c478bd9Sstevel@tonic-gate 	 * Extended partition, so we need to deal with that case as
6827c478bd9Sstevel@tonic-gate 	 * well.
6837c478bd9Sstevel@tonic-gate 	 *
6847c478bd9Sstevel@tonic-gate 	 * Only a single (the first) Extended or Boot Partition will
6857c478bd9Sstevel@tonic-gate 	 * be recognized.  Any others will be ignored.
6867c478bd9Sstevel@tonic-gate 	 */
6877c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
6887c478bd9Sstevel@tonic-gate 		if (isDosDrive(part[i].systid)) {
6897c478bd9Sstevel@tonic-gate 			if (primaryPart < 0) {
6907c478bd9Sstevel@tonic-gate 				logicalDriveCount++;
6917c478bd9Sstevel@tonic-gate 				primaryPart = i;
6927c478bd9Sstevel@tonic-gate 			} else {
6937c478bd9Sstevel@tonic-gate 				extraDrives[numExtraDrives++] = i;
6947c478bd9Sstevel@tonic-gate 			}
6957c478bd9Sstevel@tonic-gate 			continue;
6967c478bd9Sstevel@tonic-gate 		}
6977c478bd9Sstevel@tonic-gate 		if ((extendedPart < 0) && isDosExtended(part[i].systid)) {
6987c478bd9Sstevel@tonic-gate 			extendedPart = i;
6997c478bd9Sstevel@tonic-gate 			continue;
7007c478bd9Sstevel@tonic-gate 		}
7017c478bd9Sstevel@tonic-gate 		if ((bootPart < 0) && isBootPart(part[i].systid)) {
7027c478bd9Sstevel@tonic-gate 			bootPart = i;
7037c478bd9Sstevel@tonic-gate 			continue;
7047c478bd9Sstevel@tonic-gate 		}
7057c478bd9Sstevel@tonic-gate 	}
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	if (drvnum == BOOT_PARTITION_DRIVE) {
7087c478bd9Sstevel@tonic-gate 		if (bootPart < 0) {
7097c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
7107c478bd9Sstevel@tonic-gate 			    gettext("No boot partition found on drive\n"));
7117c478bd9Sstevel@tonic-gate 			return (PART_NOT_FOUND);
7127c478bd9Sstevel@tonic-gate 		}
7137c478bd9Sstevel@tonic-gate 		if ((*seekto = ltohi(part[bootPart].relsect)) == 0) {
7147c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Bogus FDISK entry? "
7157c478bd9Sstevel@tonic-gate 			    "A boot partition starting\nat sector 0 would "
7167c478bd9Sstevel@tonic-gate 			    "collide with the FDISK table!\n"));
7177c478bd9Sstevel@tonic-gate 			return (PART_NOT_FOUND);
7187c478bd9Sstevel@tonic-gate 		}
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 		fill_bpb_sizes(wbpb, part, bootPart, *seekto);
7217c478bd9Sstevel@tonic-gate 		*seekto *= BPSEC;
7227c478bd9Sstevel@tonic-gate 		FdiskFATsize = lookup_FAT_size(part[bootPart].systid);
7237c478bd9Sstevel@tonic-gate 		if (Verbose)
7247c478bd9Sstevel@tonic-gate 			(void) printf(gettext("Boot partition's offset: "
7257c478bd9Sstevel@tonic-gate 			    "Sector %x.\n"), *seekto/BPSEC);
7267c478bd9Sstevel@tonic-gate 		if (lseek64(fd, *seekto, SEEK_SET) < 0) {
7277c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Partition %s: "), pn);
7287c478bd9Sstevel@tonic-gate 			perror("");
7297c478bd9Sstevel@tonic-gate 			return (PART_NOT_FOUND);
7307c478bd9Sstevel@tonic-gate 		}
7317c478bd9Sstevel@tonic-gate 		return (PART_FOUND);
7327c478bd9Sstevel@tonic-gate 	}
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 	if (drvnum == PRIMARY_DOS_DRIVE && primaryPart >= 0) {
7357c478bd9Sstevel@tonic-gate 		if ((*seekto = ltohi(part[primaryPart].relsect)) == 0) {
7367c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Bogus FDISK entry? "
7377c478bd9Sstevel@tonic-gate 			    "A partition starting\nat sector 0 would "
7387c478bd9Sstevel@tonic-gate 			    "collide with the FDISK table!\n"));
7397c478bd9Sstevel@tonic-gate 			return (PART_NOT_FOUND);
7407c478bd9Sstevel@tonic-gate 		}
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 		fill_bpb_sizes(wbpb, part, primaryPart, *seekto);
7437c478bd9Sstevel@tonic-gate 		*seekto *= BPSEC;
7447c478bd9Sstevel@tonic-gate 		FdiskFATsize = lookup_FAT_size(part[primaryPart].systid);
7457c478bd9Sstevel@tonic-gate 		if (Verbose)
7467c478bd9Sstevel@tonic-gate 			(void) printf(gettext("Partition's offset: "
7477c478bd9Sstevel@tonic-gate 			    "Sector %x.\n"), *seekto/BPSEC);
7487c478bd9Sstevel@tonic-gate 		if (lseek64(fd, *seekto, SEEK_SET) < 0) {
7497c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Partition %s: "), pn);
7507c478bd9Sstevel@tonic-gate 			perror("");
7517c478bd9Sstevel@tonic-gate 			return (PART_NOT_FOUND);
7527c478bd9Sstevel@tonic-gate 		}
7537c478bd9Sstevel@tonic-gate 		return (PART_FOUND);
7547c478bd9Sstevel@tonic-gate 	}
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 	/*
7577c478bd9Sstevel@tonic-gate 	 * We are not looking for the C: drive (or there was no primary
7587c478bd9Sstevel@tonic-gate 	 * drive found), so we had better have an extended partition or
7597c478bd9Sstevel@tonic-gate 	 * extra drives in the Master FDISK table.
7607c478bd9Sstevel@tonic-gate 	 */
7617c478bd9Sstevel@tonic-gate 	if ((extendedPart < 0) && (numExtraDrives == 0)) {
7627c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
7637c478bd9Sstevel@tonic-gate 		    gettext("No such logical drive "
7647c478bd9Sstevel@tonic-gate 		    "(missing extended partition entry)\n"));
7657c478bd9Sstevel@tonic-gate 		return (PART_NOT_FOUND);
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	if (extendedPart >= 0) {
7697c478bd9Sstevel@tonic-gate 		nextseek = xstartsect = ltohi(part[extendedPart].relsect);
7707c478bd9Sstevel@tonic-gate 		xnumsect = ltohi(part[extendedPart].numsect);
7717c478bd9Sstevel@tonic-gate 		do {
7727c478bd9Sstevel@tonic-gate 			/*
7737c478bd9Sstevel@tonic-gate 			 *  If the seek would not cause us to change
7747c478bd9Sstevel@tonic-gate 			 *  position on the drive, then we're out of
7757c478bd9Sstevel@tonic-gate 			 *  extended partitions to examine.
7767c478bd9Sstevel@tonic-gate 			 */
7777c478bd9Sstevel@tonic-gate 			if (nextseek == lastseek)
7787c478bd9Sstevel@tonic-gate 				break;
7797c478bd9Sstevel@tonic-gate 			logicalDriveCount += numDrives;
7807c478bd9Sstevel@tonic-gate 			/*
7817c478bd9Sstevel@tonic-gate 			 *  Seek the next extended partition, and find
7827c478bd9Sstevel@tonic-gate 			 *  logical drives within it.
7837c478bd9Sstevel@tonic-gate 			 */
7847c478bd9Sstevel@tonic-gate 			if (lseek64(fd, nextseek * BPSEC, SEEK_SET) < 0 ||
7857c478bd9Sstevel@tonic-gate 			    read(fd, &extmboot, sizeof (extmboot)) !=
786f127cb91Sfrankho 			    sizeof (extmboot)) {
7877c478bd9Sstevel@tonic-gate 				perror(gettext("Unable to read extended "
788f127cb91Sfrankho 				    "partition record"));
7897c478bd9Sstevel@tonic-gate 				return (PART_NOT_FOUND);
7907c478bd9Sstevel@tonic-gate 			}
7917c478bd9Sstevel@tonic-gate 			(void) memcpy(part, extmboot.parts, sizeof (part));
7927c478bd9Sstevel@tonic-gate 			lastseek = nextseek;
7937c478bd9Sstevel@tonic-gate 			if (ltohs(extmboot.signature) != MBB_MAGIC) {
7947c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
7957c478bd9Sstevel@tonic-gate 				    gettext("Bad signature on "
7967c478bd9Sstevel@tonic-gate 				    "extended partition\n"));
7977c478bd9Sstevel@tonic-gate 				return (PART_NOT_FOUND);
7987c478bd9Sstevel@tonic-gate 			}
7997c478bd9Sstevel@tonic-gate 			/*
8007c478bd9Sstevel@tonic-gate 			 *  Count up drives, and track where the next
8017c478bd9Sstevel@tonic-gate 			 *  extended partition is in case we need it.  We
8027c478bd9Sstevel@tonic-gate 			 *  are expecting only one extended partition.  If
8037c478bd9Sstevel@tonic-gate 			 *  there is more than one we'll only go to the
8047c478bd9Sstevel@tonic-gate 			 *  first one we see, but warn about ignoring.
8057c478bd9Sstevel@tonic-gate 			 */
8067c478bd9Sstevel@tonic-gate 			numDrives = 0;
8077c478bd9Sstevel@tonic-gate 			for (i = 0; i < FD_NUMPART; i++) {
8087c478bd9Sstevel@tonic-gate 				if (isDosDrive(part[i].systid)) {
8097c478bd9Sstevel@tonic-gate 					extndDrives[numDrives++] = i;
8107c478bd9Sstevel@tonic-gate 					continue;
8117c478bd9Sstevel@tonic-gate 				} else if (isDosExtended(part[i].systid)) {
8127c478bd9Sstevel@tonic-gate 					if (nextseek != lastseek) {
8137c478bd9Sstevel@tonic-gate 						/*
8147c478bd9Sstevel@tonic-gate 						 * Already found an extended
8157c478bd9Sstevel@tonic-gate 						 * partition in this table.
8167c478bd9Sstevel@tonic-gate 						 */
8177c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
8187c478bd9Sstevel@tonic-gate 						    gettext("WARNING: "
8197c478bd9Sstevel@tonic-gate 						    "Ignoring unexpected "
8207c478bd9Sstevel@tonic-gate 						    "additional extended "
8217c478bd9Sstevel@tonic-gate 						    "partition"));
8227c478bd9Sstevel@tonic-gate 						continue;
8237c478bd9Sstevel@tonic-gate 					}
8247c478bd9Sstevel@tonic-gate 					nextseek = xstartsect +
8257c478bd9Sstevel@tonic-gate 					    ltohi(part[i].relsect);
8267c478bd9Sstevel@tonic-gate 					continue;
8277c478bd9Sstevel@tonic-gate 				}
8287c478bd9Sstevel@tonic-gate 			}
8297c478bd9Sstevel@tonic-gate 		} while (drvnum > logicalDriveCount + numDrives);
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 		if (drvnum <= logicalDriveCount + numDrives) {
8327c478bd9Sstevel@tonic-gate 			/*
8337c478bd9Sstevel@tonic-gate 			 * The number of logical drives we've found thus
8347c478bd9Sstevel@tonic-gate 			 * far is enough to get us to the one we were
8357c478bd9Sstevel@tonic-gate 			 * searching for.
8367c478bd9Sstevel@tonic-gate 			 */
8377c478bd9Sstevel@tonic-gate 			driveIndex = logicalDriveCount + numDrives - drvnum;
8387c478bd9Sstevel@tonic-gate 			*seekto =
8397c478bd9Sstevel@tonic-gate 			    ltohi(part[extndDrives[driveIndex]].relsect) +
8407c478bd9Sstevel@tonic-gate 			    lastseek;
8417c478bd9Sstevel@tonic-gate 			if (*seekto == lastseek) {
8427c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
8437c478bd9Sstevel@tonic-gate 				    gettext("Bogus FDISK entry?  A logical "
8447c478bd9Sstevel@tonic-gate 				    "drive starting at\nsector 0x%llx would "
8457c478bd9Sstevel@tonic-gate 				    "collide with the\nFDISK information in "
8467c478bd9Sstevel@tonic-gate 				    "that sector.\n"), *seekto);
8477c478bd9Sstevel@tonic-gate 				return (PART_NOT_FOUND);
8487c478bd9Sstevel@tonic-gate 			} else if (*seekto <= xstartsect ||
8497c478bd9Sstevel@tonic-gate 			    *seekto >= (xstartsect + xnumsect)) {
8507c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
8517c478bd9Sstevel@tonic-gate 				    gettext("Bogus FDISK entry?  "
8527c478bd9Sstevel@tonic-gate 				    "Logical drive start sector (0x%llx)\n"
8537c478bd9Sstevel@tonic-gate 				    "not within extended partition! "
8547c478bd9Sstevel@tonic-gate 				    "(Expected in range 0x%x - 0x%x)\n"),
8557c478bd9Sstevel@tonic-gate 				    *seekto, xstartsect + 1,
8567c478bd9Sstevel@tonic-gate 				    xstartsect + xnumsect - 1);
8577c478bd9Sstevel@tonic-gate 				return (PART_NOT_FOUND);
8587c478bd9Sstevel@tonic-gate 			}
8597c478bd9Sstevel@tonic-gate 			fill_bpb_sizes(wbpb, part, extndDrives[driveIndex],
8607c478bd9Sstevel@tonic-gate 			    *seekto);
8617c478bd9Sstevel@tonic-gate 			*seekto *= BPSEC;
8627c478bd9Sstevel@tonic-gate 			FdiskFATsize = lookup_FAT_size(
8637c478bd9Sstevel@tonic-gate 			    part[extndDrives[driveIndex]].systid);
8647c478bd9Sstevel@tonic-gate 			if (Verbose)
8657c478bd9Sstevel@tonic-gate 				(void) printf(gettext("Partition's offset: "
8667c478bd9Sstevel@tonic-gate 				    "Sector 0x%x.\n"), *seekto/BPSEC);
8677c478bd9Sstevel@tonic-gate 			if (lseek64(fd, *seekto, SEEK_SET) < 0) {
8687c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
8697c478bd9Sstevel@tonic-gate 				    gettext("Partition %s: "), pn);
8707c478bd9Sstevel@tonic-gate 				perror("");
8717c478bd9Sstevel@tonic-gate 				return (PART_NOT_FOUND);
8727c478bd9Sstevel@tonic-gate 			}
8737c478bd9Sstevel@tonic-gate 			return (PART_FOUND);
8747c478bd9Sstevel@tonic-gate 		} else {
8757c478bd9Sstevel@tonic-gate 			/*
8767c478bd9Sstevel@tonic-gate 			 * We ran out of extended dos partition
8777c478bd9Sstevel@tonic-gate 			 * drives.  The only hope now is to go
8787c478bd9Sstevel@tonic-gate 			 * back to extra drives defined in the master
8797c478bd9Sstevel@tonic-gate 			 * fdisk table.  But we overwrote that table
8807c478bd9Sstevel@tonic-gate 			 * already, so we must load it in again.
8817c478bd9Sstevel@tonic-gate 			 */
8827c478bd9Sstevel@tonic-gate 			logicalDriveCount += numDrives;
8837c478bd9Sstevel@tonic-gate 			(void) memcpy(part, mb.parts, sizeof (part));
8847c478bd9Sstevel@tonic-gate 		}
8857c478bd9Sstevel@tonic-gate 	}
8867c478bd9Sstevel@tonic-gate 	/*
8877c478bd9Sstevel@tonic-gate 	 *  Still haven't found the drive, is it an extra
8887c478bd9Sstevel@tonic-gate 	 *  drive defined in the main FDISK table?
8897c478bd9Sstevel@tonic-gate 	 */
8907c478bd9Sstevel@tonic-gate 	if (drvnum <= logicalDriveCount + numExtraDrives) {
8917c478bd9Sstevel@tonic-gate 		driveIndex = logicalDriveCount + numExtraDrives - drvnum;
8927c478bd9Sstevel@tonic-gate 		*seekto = ltohi(part[extraDrives[driveIndex]].relsect);
8937c478bd9Sstevel@tonic-gate 		if (*seekto == 0) {
8947c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext("Bogus FDISK entry? "
8957c478bd9Sstevel@tonic-gate 			    "A partition starting\nat sector 0 would "
8967c478bd9Sstevel@tonic-gate 			    "collide with the FDISK table!\n"));
8977c478bd9Sstevel@tonic-gate 			return (PART_NOT_FOUND);
8987c478bd9Sstevel@tonic-gate 		}
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 		fill_bpb_sizes(wbpb, part, extraDrives[driveIndex], *seekto);
9017c478bd9Sstevel@tonic-gate 		*seekto *= BPSEC;
9027c478bd9Sstevel@tonic-gate 		FdiskFATsize =
903f127cb91Sfrankho 		    lookup_FAT_size(part[extraDrives[driveIndex]].systid);
9047c478bd9Sstevel@tonic-gate 		if (Verbose)
9057c478bd9Sstevel@tonic-gate 			(void) printf(gettext("Partition's offset: "
9067c478bd9Sstevel@tonic-gate 			    "Sector %x.\n"), *seekto/BPSEC);
9077c478bd9Sstevel@tonic-gate 		if (lseek64(fd, *seekto, SEEK_SET) < 0) {
9087c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
9097c478bd9Sstevel@tonic-gate 			    gettext("Partition %s: "), pn);
9107c478bd9Sstevel@tonic-gate 			perror("");
9117c478bd9Sstevel@tonic-gate 			return (PART_NOT_FOUND);
9127c478bd9Sstevel@tonic-gate 		}
9137c478bd9Sstevel@tonic-gate 		return (PART_FOUND);
9147c478bd9Sstevel@tonic-gate 	}
9157c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, gettext("No such logical drive\n"));
9167c478bd9Sstevel@tonic-gate 	return (PART_NOT_FOUND);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate /*
9207c478bd9Sstevel@tonic-gate  *  seek_nofdisk
9217c478bd9Sstevel@tonic-gate  *
9227c478bd9Sstevel@tonic-gate  *	User is asking us to trust them that they know best.
9237c478bd9Sstevel@tonic-gate  *	We basically won't do much seeking here, the only seeking we'll do
9247c478bd9Sstevel@tonic-gate  *	is if the 'hidden' parameter was given.
9257c478bd9Sstevel@tonic-gate  */
9267c478bd9Sstevel@tonic-gate static
9277c478bd9Sstevel@tonic-gate int
seek_nofdisk(int fd,bpb_t * wbpb,off64_t * seekto)9287c478bd9Sstevel@tonic-gate seek_nofdisk(int fd, bpb_t *wbpb, off64_t *seekto)
9297c478bd9Sstevel@tonic-gate {
9307c478bd9Sstevel@tonic-gate 	if (TotSize > 0xffff)
9317c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_in_volume = 0;
9327c478bd9Sstevel@tonic-gate 	else
9337c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_in_volume = (short)TotSize;
9347c478bd9Sstevel@tonic-gate 	wbpb->bpb.sectors_in_logical_volume = TotSize;
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	*seekto = RelOffset * BPSEC;
9377c478bd9Sstevel@tonic-gate 	wbpb->bpb.hidden_sectors = RelOffset;
9387c478bd9Sstevel@tonic-gate 	wbpb->sunbpb.bs_offset_high = RelOffset >> 16;
9397c478bd9Sstevel@tonic-gate 	wbpb->sunbpb.bs_offset_low = RelOffset & 0xFFFF;
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	if (Verbose)
9427c478bd9Sstevel@tonic-gate 		(void) printf(gettext("Requested offset: Sector %x.\n"),
9437c478bd9Sstevel@tonic-gate 		    *seekto/BPSEC);
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	if (lseek64(fd, *seekto, SEEK_SET) < 0) {
9467c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
9477c478bd9Sstevel@tonic-gate 		    gettext("User specified start sector %d"), RelOffset);
9487c478bd9Sstevel@tonic-gate 		perror("");
9497c478bd9Sstevel@tonic-gate 		return (PART_NOT_FOUND);
9507c478bd9Sstevel@tonic-gate 	}
9517c478bd9Sstevel@tonic-gate 	return (PART_FOUND);
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate /*
9557c478bd9Sstevel@tonic-gate  * set_fat_string
9567c478bd9Sstevel@tonic-gate  *
9577c478bd9Sstevel@tonic-gate  *	Fill in the type string of the FAT
9587c478bd9Sstevel@tonic-gate  */
9597c478bd9Sstevel@tonic-gate static
9607c478bd9Sstevel@tonic-gate void
set_fat_string(bpb_t * wbpb,int fatsize)9617c478bd9Sstevel@tonic-gate set_fat_string(bpb_t *wbpb, int fatsize)
9627c478bd9Sstevel@tonic-gate {
9637c478bd9Sstevel@tonic-gate 	if (fatsize == 12) {
9647c478bd9Sstevel@tonic-gate 		(void) strncpy((char *)wbpb->ebpb.type, FAT12_TYPE_STRING,
965f127cb91Sfrankho 		    strlen(FAT12_TYPE_STRING));
9667c478bd9Sstevel@tonic-gate 	} else if (fatsize == 16) {
9677c478bd9Sstevel@tonic-gate 		(void) strncpy((char *)wbpb->ebpb.type, FAT16_TYPE_STRING,
968f127cb91Sfrankho 		    strlen(FAT16_TYPE_STRING));
9697c478bd9Sstevel@tonic-gate 	} else {
9707c478bd9Sstevel@tonic-gate 		(void) strncpy((char *)wbpb->ebpb.type, FAT32_TYPE_STRING,
971f127cb91Sfrankho 		    strlen(FAT32_TYPE_STRING));
9727c478bd9Sstevel@tonic-gate 	}
9737c478bd9Sstevel@tonic-gate }
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate /*
9767c478bd9Sstevel@tonic-gate  *  prepare_image_file
9777c478bd9Sstevel@tonic-gate  *
9787c478bd9Sstevel@tonic-gate  *	Open the file that will hold the image (as opposed to the image
9797c478bd9Sstevel@tonic-gate  *	being written to the boot sector of an actual disk).
9807c478bd9Sstevel@tonic-gate  */
9817c478bd9Sstevel@tonic-gate static
9827c478bd9Sstevel@tonic-gate int
prepare_image_file(char * fn,bpb_t * wbpb)9837c478bd9Sstevel@tonic-gate prepare_image_file(char *fn, bpb_t *wbpb)
9847c478bd9Sstevel@tonic-gate {
9857c478bd9Sstevel@tonic-gate 	int fd;
9867c478bd9Sstevel@tonic-gate 	char zerobyte = '\0';
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate 	if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) {
9897c478bd9Sstevel@tonic-gate 		perror(fn);
9907c478bd9Sstevel@tonic-gate 		exit(2);
9917c478bd9Sstevel@tonic-gate 	}
9927c478bd9Sstevel@tonic-gate 
9937c478bd9Sstevel@tonic-gate 	if (Imagesize == 5) {
9947c478bd9Sstevel@tonic-gate 		/* Disk image of a 1.2M floppy */
9957c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_in_volume = 2 * 80 * 15;
9967c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_in_logical_volume = 2 * 80 * 15;
9977c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_per_track = 15;
9987c478bd9Sstevel@tonic-gate 		wbpb->bpb.heads = 2;
9997c478bd9Sstevel@tonic-gate 		wbpb->bpb.media = 0xF9;
10007c478bd9Sstevel@tonic-gate 		wbpb->bpb.num_root_entries = 224;
10017c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_per_cluster = 1;
10027c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_per_fat = 7;
10037c478bd9Sstevel@tonic-gate 	} else {
10047c478bd9Sstevel@tonic-gate 		/* Disk image of a 1.44M floppy */
10057c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_in_volume = 2 * 80 * 18;
10067c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_in_logical_volume = 2 * 80 * 18;
10077c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_per_track = 18;
10087c478bd9Sstevel@tonic-gate 		wbpb->bpb.heads = 2;
10097c478bd9Sstevel@tonic-gate 		wbpb->bpb.media = 0xF0;
10107c478bd9Sstevel@tonic-gate 		wbpb->bpb.num_root_entries = 224;
10117c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_per_cluster = 1;
10127c478bd9Sstevel@tonic-gate 		wbpb->bpb.sectors_per_fat = 9;
10137c478bd9Sstevel@tonic-gate 	}
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 	/*
10167c478bd9Sstevel@tonic-gate 	 * Make a holey file, with length the exact
10177c478bd9Sstevel@tonic-gate 	 * size of the floppy image.
10187c478bd9Sstevel@tonic-gate 	 */
10197c478bd9Sstevel@tonic-gate 	if (lseek(fd, (wbpb->bpb.sectors_in_volume * BPSEC)-1, SEEK_SET) < 0) {
10207c478bd9Sstevel@tonic-gate 		(void) close(fd);
10217c478bd9Sstevel@tonic-gate 		perror(fn);
10227c478bd9Sstevel@tonic-gate 		exit(2);
10237c478bd9Sstevel@tonic-gate 	}
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	if (write(fd, &zerobyte, 1) != 1) {
10267c478bd9Sstevel@tonic-gate 		(void) close(fd);
10277c478bd9Sstevel@tonic-gate 		perror(fn);
10287c478bd9Sstevel@tonic-gate 		exit(2);
10297c478bd9Sstevel@tonic-gate 	}
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	if (lseek(fd, 0, SEEK_SET) < 0) {
10327c478bd9Sstevel@tonic-gate 		(void) close(fd);
10337c478bd9Sstevel@tonic-gate 		perror(fn);
10347c478bd9Sstevel@tonic-gate 		exit(2);
10357c478bd9Sstevel@tonic-gate 	}
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	Fatentsize = 12;  /* Size of fat entry in bits */
10387c478bd9Sstevel@tonic-gate 	set_fat_string(wbpb, Fatentsize);
10397c478bd9Sstevel@tonic-gate 
10407c478bd9Sstevel@tonic-gate 	wbpb->ebpb.phys_drive_num = 0;
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	wbpb->sunbpb.bs_offset_high = 0;
10437c478bd9Sstevel@tonic-gate 	wbpb->sunbpb.bs_offset_low = 0;
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	return (fd);
10467c478bd9Sstevel@tonic-gate }
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate /*
10497c478bd9Sstevel@tonic-gate  *  partn_lecture
10507c478bd9Sstevel@tonic-gate  *
10517c478bd9Sstevel@tonic-gate  *	Give a brief sermon on dev_name user should pass to
10527c478bd9Sstevel@tonic-gate  *	the program from the command line.
10537c478bd9Sstevel@tonic-gate  *
10547c478bd9Sstevel@tonic-gate  */
10557c478bd9Sstevel@tonic-gate static
10567c478bd9Sstevel@tonic-gate void
partn_lecture(char * dn)10577c478bd9Sstevel@tonic-gate partn_lecture(char *dn)
10587c478bd9Sstevel@tonic-gate {
10597c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
1060f127cb91Sfrankho 	    gettext("\nDevice %s was assumed to be a diskette.\n"
1061f127cb91Sfrankho 	    "A diskette specific operation failed on this device.\n"
1062f127cb91Sfrankho 	    "If the device is a hard disk, provide the name of "
1063f127cb91Sfrankho 	    "the full physical disk,\n"
1064f127cb91Sfrankho 	    "and qualify that name with a logical drive specifier.\n\n"
1065f127cb91Sfrankho 	    "Hint: the device is usually something similar to\n\n"
1066f127cb91Sfrankho 	    "/dev/rdsk/c0d0p0 or /dev/rdsk/c0t0d0p0 (x86)\n"
1067f127cb91Sfrankho 	    "/dev/rdsk/c0t5d0s2 (sparc)\n\n"
1068f127cb91Sfrankho 	    "The drive specifier is appended to the device name."
1069f127cb91Sfrankho 	    " For example:\n\n"
1070f127cb91Sfrankho 	    "/dev/rdsk/c0t5d0s2:c or /dev/rdsk/c0d0p0:boot\n\n"), dn);
10717c478bd9Sstevel@tonic-gate }
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate static
10747c478bd9Sstevel@tonic-gate void
warn_funky_floppy(void)10757c478bd9Sstevel@tonic-gate warn_funky_floppy(void)
10767c478bd9Sstevel@tonic-gate {
10777c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
10787c478bd9Sstevel@tonic-gate 	    gettext("Use the 'nofdisk' option to create file systems\n"
1079f127cb91Sfrankho 	    "on non-standard floppies.\n\n"));
10807c478bd9