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"));
10807c478bd9Sstevel@tonic-gate exit(4);
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate
10837c478bd9Sstevel@tonic-gate static
10847c478bd9Sstevel@tonic-gate void
warn_funky_fatsize(void)10857c478bd9Sstevel@tonic-gate warn_funky_fatsize(void)
10867c478bd9Sstevel@tonic-gate {
10877c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
10887c478bd9Sstevel@tonic-gate gettext("Non-standard FAT size requested for floppy.\n"
1089f127cb91Sfrankho "The 'nofdisk' option must be used to\n"
1090f127cb91Sfrankho "override the 12 bit floppy default.\n\n"));
10917c478bd9Sstevel@tonic-gate exit(4);
10927c478bd9Sstevel@tonic-gate }
10937c478bd9Sstevel@tonic-gate
10947c478bd9Sstevel@tonic-gate static
10957c478bd9Sstevel@tonic-gate void
floppy_bpb_fillin(bpb_t * wbpb,int diam,int hds,int spt)10967c478bd9Sstevel@tonic-gate floppy_bpb_fillin(bpb_t *wbpb, int diam, int hds, int spt)
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate switch (diam) {
10997c478bd9Sstevel@tonic-gate case 3:
11007c478bd9Sstevel@tonic-gate switch (hds) {
11017c478bd9Sstevel@tonic-gate case 2:
11027c478bd9Sstevel@tonic-gate switch (spt) {
11037c478bd9Sstevel@tonic-gate case 9:
11047c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF9;
11057c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112;
11067c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2;
11077c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 3;
11087c478bd9Sstevel@tonic-gate break;
11097c478bd9Sstevel@tonic-gate case 18:
11107c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF0;
11117c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224;
11127c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11137c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9;
11147c478bd9Sstevel@tonic-gate break;
11157c478bd9Sstevel@tonic-gate case 36:
11167c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF0;
11177c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 240;
11187c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2;
11197c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9;
11207c478bd9Sstevel@tonic-gate break;
11217c478bd9Sstevel@tonic-gate default:
11227c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
11237c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! "
1124f127cb91Sfrankho "3.5'' diskette with %d heads "
1125f127cb91Sfrankho "and %d sectors/track.\n"), hds, spt);
11267c478bd9Sstevel@tonic-gate warn_funky_floppy();
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate break;
11297c478bd9Sstevel@tonic-gate case 1:
11307c478bd9Sstevel@tonic-gate default:
11317c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
11327c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! "
1133f127cb91Sfrankho "3.5'' diskette with %d heads "), hds);
11347c478bd9Sstevel@tonic-gate warn_funky_floppy();
11357c478bd9Sstevel@tonic-gate }
11367c478bd9Sstevel@tonic-gate break;
11377c478bd9Sstevel@tonic-gate case 5:
11387c478bd9Sstevel@tonic-gate switch (hds) {
11397c478bd9Sstevel@tonic-gate case 2:
11407c478bd9Sstevel@tonic-gate switch (spt) {
11417c478bd9Sstevel@tonic-gate case 15:
11427c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF9;
11437c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224;
11447c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11457c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 7;
11467c478bd9Sstevel@tonic-gate break;
11477c478bd9Sstevel@tonic-gate case 9:
11487c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xFD;
11497c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112;
11507c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2;
11517c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2;
11527c478bd9Sstevel@tonic-gate break;
11537c478bd9Sstevel@tonic-gate case 8:
11547c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xFF;
11557c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112;
11567c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11577c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2;
11587c478bd9Sstevel@tonic-gate break;
11597c478bd9Sstevel@tonic-gate default:
11607c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
11617c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! "
1162f127cb91Sfrankho "5.25'' diskette with %d heads "
1163f127cb91Sfrankho "and %d sectors/track.\n"), hds, spt);
11647c478bd9Sstevel@tonic-gate warn_funky_floppy();
11657c478bd9Sstevel@tonic-gate }
11667c478bd9Sstevel@tonic-gate break;
11677c478bd9Sstevel@tonic-gate case 1:
11687c478bd9Sstevel@tonic-gate switch (spt) {
11697c478bd9Sstevel@tonic-gate case 9:
11707c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xFC;
11717c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 64;
11727c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11737c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2;
11747c478bd9Sstevel@tonic-gate break;
11757c478bd9Sstevel@tonic-gate case 8:
11767c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xFE;
11777c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 64;
11787c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1;
11797c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 1;
11807c478bd9Sstevel@tonic-gate break;
11817c478bd9Sstevel@tonic-gate default:
11827c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
11837c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! "
1184f127cb91Sfrankho "5.25'' diskette with %d heads "
1185f127cb91Sfrankho "and %d sectors/track.\n"), hds, spt);
11867c478bd9Sstevel@tonic-gate warn_funky_floppy();
11877c478bd9Sstevel@tonic-gate }
11887c478bd9Sstevel@tonic-gate break;
11897c478bd9Sstevel@tonic-gate default:
11907c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
11917c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! "
1192f127cb91Sfrankho "5.25'' diskette with %d heads."), hds);
11937c478bd9Sstevel@tonic-gate warn_funky_floppy();
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate break;
11967c478bd9Sstevel@tonic-gate default:
11977c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
11987c478bd9Sstevel@tonic-gate gettext("\nUnknown diskette type. Only know about "
1199f127cb91Sfrankho "5.25'' and 3.5'' diskettes.\n"));
12007c478bd9Sstevel@tonic-gate warn_funky_floppy();
12017c478bd9Sstevel@tonic-gate }
12027c478bd9Sstevel@tonic-gate }
12037c478bd9Sstevel@tonic-gate
12047c478bd9Sstevel@tonic-gate /*
12057c478bd9Sstevel@tonic-gate * lookup_floppy
12067c478bd9Sstevel@tonic-gate *
12077c478bd9Sstevel@tonic-gate * Look up a media descriptor byte and other crucial BPB values
12087c478bd9Sstevel@tonic-gate * based on floppy characteristics.
12097c478bd9Sstevel@tonic-gate */
12107c478bd9Sstevel@tonic-gate static
12117c478bd9Sstevel@tonic-gate void
lookup_floppy(struct fd_char * fdchar,bpb_t * wbpb)12127c478bd9Sstevel@tonic-gate lookup_floppy(struct fd_char *fdchar, bpb_t *wbpb)
12137c478bd9Sstevel@tonic-gate {
12147c478bd9Sstevel@tonic-gate ulong_t tsize;
12157c478bd9Sstevel@tonic-gate ulong_t cyls, spt, hds, diam;
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate cyls = fdchar->fdc_ncyl;
12187c478bd9Sstevel@tonic-gate diam = fdchar->fdc_medium;
12197c478bd9Sstevel@tonic-gate spt = fdchar->fdc_secptrack;
12207c478bd9Sstevel@tonic-gate hds = fdchar->fdc_nhead;
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate tsize = cyls * hds * spt;
12237c478bd9Sstevel@tonic-gate
12247c478bd9Sstevel@tonic-gate if (GetFsParams)
12257c478bd9Sstevel@tonic-gate TotSize = tsize;
12267c478bd9Sstevel@tonic-gate
12277c478bd9Sstevel@tonic-gate if (GetSize) {
12287c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = tsize;
12297c478bd9Sstevel@tonic-gate } else {
12307c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume =
1231f127cb91Sfrankho warn_mismatch(
1232f127cb91Sfrankho gettext("length of partition (in sectors)"),
1233f127cb91Sfrankho gettext("FDIOGCHAR call"), tsize, TotSize);
12347c478bd9Sstevel@tonic-gate }
12357c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume =
1236f127cb91Sfrankho (short)wbpb->bpb.sectors_in_logical_volume;
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate if (GetSPT) {
12397c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track = spt;
12407c478bd9Sstevel@tonic-gate } else {
12417c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track =
1242f127cb91Sfrankho warn_mismatch(
1243f127cb91Sfrankho gettext("sectors per track"),
1244f127cb91Sfrankho gettext("FDIOGCHAR call"), spt, SecPerTrk);
12457c478bd9Sstevel@tonic-gate spt = wbpb->bpb.sectors_per_track;
12467c478bd9Sstevel@tonic-gate }
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate if (GetTPC) {
12497c478bd9Sstevel@tonic-gate wbpb->bpb.heads = hds;
12507c478bd9Sstevel@tonic-gate } else {
12517c478bd9Sstevel@tonic-gate wbpb->bpb.heads =
1252f127cb91Sfrankho warn_mismatch(
1253f127cb91Sfrankho gettext("number of heads"),
1254f127cb91Sfrankho gettext("FDIOGCHAR call"), hds, TrkPerCyl);
12557c478bd9Sstevel@tonic-gate hds = wbpb->bpb.heads;
12567c478bd9Sstevel@tonic-gate }
12577c478bd9Sstevel@tonic-gate
12587c478bd9Sstevel@tonic-gate Fatentsize = 12; /* Size of fat entry in bits */
12597c478bd9Sstevel@tonic-gate if (!GetBPF && BitsPerFAT != Fatentsize) {
12607c478bd9Sstevel@tonic-gate warn_funky_fatsize();
12617c478bd9Sstevel@tonic-gate }
12627c478bd9Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize);
12637c478bd9Sstevel@tonic-gate
12647c478bd9Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0;
12657c478bd9Sstevel@tonic-gate
12667c478bd9Sstevel@tonic-gate wbpb->bpb.hidden_sectors = 0;
12677c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = 0;
12687c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = 0;
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate floppy_bpb_fillin(wbpb, diam, hds, spt);
12717c478bd9Sstevel@tonic-gate }
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate /*
12747c478bd9Sstevel@tonic-gate * compute_cluster_size
12757c478bd9Sstevel@tonic-gate *
12767c478bd9Sstevel@tonic-gate * Compute an acceptable sectors/cluster value.
12777c478bd9Sstevel@tonic-gate *
1278849ee7a1Swyllys * Based on values from the Hardware White Paper
1279849ee7a1Swyllys * from Microsoft.
1280849ee7a1Swyllys * "Microsoft Extensible Firmware Initiative
1281849ee7a1Swyllys * FAT32 File System Specification
1282849ee7a1Swyllys * FAT: General Overview of On-Disk Format"
1283849ee7a1Swyllys *
1284849ee7a1Swyllys * Version 1.03, December 6, 2000
12857c478bd9Sstevel@tonic-gate *
12867c478bd9Sstevel@tonic-gate */
12877c478bd9Sstevel@tonic-gate static
12887c478bd9Sstevel@tonic-gate void
compute_cluster_size(bpb_t * wbpb)12897c478bd9Sstevel@tonic-gate compute_cluster_size(bpb_t *wbpb)
12907c478bd9Sstevel@tonic-gate {
129157e22c6cSwyllys ulong_t volsize;
129257e22c6cSwyllys ulong_t spc;
12930576819eSwyllys ulong_t rds, tmpval1, tmpval2;
12940576819eSwyllys ulong_t fatsz;
1295849ee7a1Swyllys int newfat = 16;
1296849ee7a1Swyllys
1297849ee7a1Swyllys #define FAT12_MAX_CLUSTERS 0x0FF4
1298849ee7a1Swyllys #define FAT16_MAX_CLUSTERS 0xFFF4
1299849ee7a1Swyllys #define FAT32_MAX_CLUSTERS 0x0FFFFFF0
1300849ee7a1Swyllys #define FAT32_SUGGESTED_NCLUST 0x400000
1301849ee7a1Swyllys
1302849ee7a1Swyllys /* compute volume size in sectors. */
13037c478bd9Sstevel@tonic-gate volsize = wbpb->bpb.sectors_in_volume ? wbpb->bpb.sectors_in_volume :
1304f127cb91Sfrankho wbpb->bpb.sectors_in_logical_volume;
13057c478bd9Sstevel@tonic-gate volsize -= wbpb->bpb.resv_sectors;
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate if (GetSPC) {
1308849ee7a1Swyllys /*
1309849ee7a1Swyllys * User indicated what sort of FAT to create,
1310849ee7a1Swyllys * make sure it is valid with the given size
1311849ee7a1Swyllys * and compute an SPC value.
1312849ee7a1Swyllys */
1313849ee7a1Swyllys if (!MakeFAT32) { /* FAT16 */
1314849ee7a1Swyllys /* volsize is in sectors */
1315849ee7a1Swyllys if (volsize < FAT12_MAX_CLUSTERS) {
1316849ee7a1Swyllys (void) fprintf(stderr,
1317f127cb91Sfrankho gettext("Requested size is too "
1318f127cb91Sfrankho "small for FAT16.\n"));
1319849ee7a1Swyllys exit(4);
13207c478bd9Sstevel@tonic-gate }
1321849ee7a1Swyllys /* SPC must be a power of 2 */
1322849ee7a1Swyllys for (spc = 1; spc <= 64; spc = spc * 2) {
1323849ee7a1Swyllys if (volsize < spc * FAT16_MAX_CLUSTERS)
1324849ee7a1Swyllys break;
1325849ee7a1Swyllys }
1326849ee7a1Swyllys if (volsize > (spc * FAT16_MAX_CLUSTERS)) {
1327849ee7a1Swyllys (void) fprintf(stderr,
1328f127cb91Sfrankho gettext("Requested size is too "
1329f127cb91Sfrankho "large for FAT16.\n"));
1330849ee7a1Swyllys exit(4);
1331849ee7a1Swyllys }
1332849ee7a1Swyllys } else { /* FAT32 */
1333849ee7a1Swyllys /* volsize is in sectors */
1334849ee7a1Swyllys if (volsize < FAT16_MAX_CLUSTERS) {
1335849ee7a1Swyllys (void) fprintf(stderr,
1336f127cb91Sfrankho gettext("Requested size is too "
1337f127cb91Sfrankho "small for FAT32.\n"));
1338849ee7a1Swyllys exit(4);
1339849ee7a1Swyllys }
1340849ee7a1Swyllys /* SPC must be a power of 2 */
1341849ee7a1Swyllys for (spc = 1; spc <= 64; spc = spc * 2) {
1342849ee7a1Swyllys if (volsize < (spc * FAT32_SUGGESTED_NCLUST))
1343849ee7a1Swyllys break;
1344849ee7a1Swyllys }
1345849ee7a1Swyllys if (volsize > (spc * FAT32_MAX_CLUSTERS)) {
1346849ee7a1Swyllys (void) fprintf(stderr,
1347f127cb91Sfrankho gettext("Requested size is too "
1348f127cb91Sfrankho "large for FAT32.\n"));
13497c478bd9Sstevel@tonic-gate exit(4);
13507c478bd9Sstevel@tonic-gate }
13517c478bd9Sstevel@tonic-gate }
13527c478bd9Sstevel@tonic-gate } else {
1353849ee7a1Swyllys /*
1354849ee7a1Swyllys * User gave the SPC as an explicit option,
1355849ee7a1Swyllys * make sure it will work with the requested
1356849ee7a1Swyllys * volume size.
1357849ee7a1Swyllys */
1358849ee7a1Swyllys int nclust;
1359849ee7a1Swyllys
13607c478bd9Sstevel@tonic-gate spc = SecPerClust;
1361849ee7a1Swyllys nclust = volsize / spc;
1362849ee7a1Swyllys
1363849ee7a1Swyllys if (nclust <= FAT16_MAX_CLUSTERS && MakeFAT32) {
1364f127cb91Sfrankho (void) fprintf(stderr, gettext("Requested size is too "
1365f127cb91Sfrankho "small for FAT32.\n"));
1366849ee7a1Swyllys exit(4);
1367849ee7a1Swyllys }
1368849ee7a1Swyllys if (!MakeFAT32) {
1369849ee7a1Swyllys /* Determine if FAT12 or FAT16 */
1370849ee7a1Swyllys if (nclust < FAT12_MAX_CLUSTERS)
1371849ee7a1Swyllys newfat = 12;
1372849ee7a1Swyllys else if (nclust < FAT16_MAX_CLUSTERS)
1373849ee7a1Swyllys newfat = 16;
1374849ee7a1Swyllys else {
1375849ee7a1Swyllys (void) fprintf(stderr,
1376f127cb91Sfrankho gettext("Requested size is too "
1377f127cb91Sfrankho "small for FAT32.\n"));
1378849ee7a1Swyllys exit(4);
1379849ee7a1Swyllys }
1380849ee7a1Swyllys }
13817c478bd9Sstevel@tonic-gate }
13827c478bd9Sstevel@tonic-gate
13830576819eSwyllys /*
13840576819eSwyllys * RootDirSectors = ((BPB_RootEntCnt * 32) +
13850576819eSwyllys * (BPB_BytsPerSec 1)) / BPB_BytsPerSec;
13860576819eSwyllys */
13870576819eSwyllys rds = ((wbpb->bpb.num_root_entries * 32) +
1388f127cb91Sfrankho (wbpb->bpb.bytes_sector - 1)) / wbpb->bpb.bytes_sector;
13890576819eSwyllys
13907c478bd9Sstevel@tonic-gate if (GetBPF) {
13917c478bd9Sstevel@tonic-gate if (MakeFAT32)
13927c478bd9Sstevel@tonic-gate Fatentsize = 32;
13937c478bd9Sstevel@tonic-gate else
1394849ee7a1Swyllys Fatentsize = newfat;
13957c478bd9Sstevel@tonic-gate } else {
13967c478bd9Sstevel@tonic-gate Fatentsize = BitsPerFAT;
13970576819eSwyllys
13980576819eSwyllys if (Fatentsize == 12 &&
1399f127cb91Sfrankho (volsize - rds) >= DOS_F12MAXC * spc) {
14007c478bd9Sstevel@tonic-gate /*
1401849ee7a1Swyllys * If we don't have an input TTY, or we aren't
1402849ee7a1Swyllys * really doing anything, then don't ask
1403849ee7a1Swyllys * questions. Assume a yes answer to any
1404849ee7a1Swyllys * questions we would ask.
14057c478bd9Sstevel@tonic-gate */
14067c478bd9Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) {
1407f127cb91Sfrankho (void) printf(
14087c478bd9Sstevel@tonic-gate gettext("Volume too large for 12 bit FAT,"
1409f127cb91Sfrankho " increasing to 16 bit FAT size.\n"));
1410f127cb91Sfrankho (void) fflush(stdout);
1411f127cb91Sfrankho Fatentsize = 16;
14127c478bd9Sstevel@tonic-gate } else {
1413f127cb91Sfrankho (void) printf(
14147c478bd9Sstevel@tonic-gate gettext("Volume too large for a 12 bit FAT.\n"
1415f127cb91Sfrankho "Increase to 16 bit FAT "
1416f127cb91Sfrankho "and continue (y/n)? "));
1417f127cb91Sfrankho (void) fflush(stdout);
1418f127cb91Sfrankho if (yes())
1419f127cb91Sfrankho Fatentsize = 16;
1420f127cb91Sfrankho else
1421f127cb91Sfrankho exit(5);
14227c478bd9Sstevel@tonic-gate }
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate }
14257c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = spc;
14267c478bd9Sstevel@tonic-gate
14277c478bd9Sstevel@tonic-gate if (!GetFsParams && FdiskFATsize < 0) {
14287c478bd9Sstevel@tonic-gate (void) printf(
14297c478bd9Sstevel@tonic-gate gettext("Cannot verify chosen/computed FAT "
1430f127cb91Sfrankho "entry size (%d bits) with FDISK table.\n"
1431f127cb91Sfrankho "FDISK table has an unknown file system "
1432f127cb91Sfrankho "type for this device. Giving up...\n"),
1433f127cb91Sfrankho Fatentsize, Fatentsize);
14347c478bd9Sstevel@tonic-gate exit(6);
14357c478bd9Sstevel@tonic-gate } else if (!GetFsParams && FdiskFATsize && FdiskFATsize != Fatentsize) {
14367c478bd9Sstevel@tonic-gate (void) printf(
14377c478bd9Sstevel@tonic-gate gettext("Chosen/computed FAT entry size (%d bits) "
1438f127cb91Sfrankho "does not match FDISK table (%d bits).\n"),
1439f127cb91Sfrankho Fatentsize, FdiskFATsize);
14407c478bd9Sstevel@tonic-gate (void) printf(
14417c478bd9Sstevel@tonic-gate gettext("Use -o fat=%d to build a FAT "
1442f127cb91Sfrankho "that matches the FDISK entry.\n"), FdiskFATsize);
14437c478bd9Sstevel@tonic-gate exit(6);
14447c478bd9Sstevel@tonic-gate }
14457c478bd9Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize);
14460576819eSwyllys /*
14470576819eSwyllys * Compure the FAT sizes according to algorithm from Microsoft:
14480576819eSwyllys *
14490576819eSwyllys * RootDirSectors = ((BPB_RootEntCnt * 32) +
14500576819eSwyllys * (BPB_BytsPerSec 1)) / BPB_BytsPerSec;
14510576819eSwyllys * TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
14520576819eSwyllys * TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
14530576819eSwyllys * If (FATType == FAT32)
14540576819eSwyllys * TmpVal2 = TmpVal2 / 2;
14550576819eSwyllys * FATSz = (TMPVal1 + (TmpVal2 1)) / TmpVal2;
14560576819eSwyllys * If (FATType == FAT32) {
14570576819eSwyllys * BPB_FATSz16 = 0;
14580576819eSwyllys * BPB_FATSz32 = FATSz;
14590576819eSwyllys * } else {
14600576819eSwyllys * BPB_FATSz16 = LOWORD(FATSz);
14610576819eSwyllys * // there is no BPB_FATSz32 in a FAT16 BPB
14620576819eSwyllys * }
14630576819eSwyllys */
14640576819eSwyllys tmpval1 = volsize - (wbpb->bpb.resv_sectors + rds);
14650576819eSwyllys
1466f127cb91Sfrankho tmpval2 = (256 * wbpb->bpb.sectors_per_cluster) + wbpb->bpb.num_fats;
14670576819eSwyllys
14680576819eSwyllys if (Fatentsize == 32)
14690576819eSwyllys tmpval2 = tmpval2 / 2;
14700576819eSwyllys
14710576819eSwyllys fatsz = (tmpval1 + (tmpval2 - 1)) / tmpval2;
14727c478bd9Sstevel@tonic-gate
14737c478bd9Sstevel@tonic-gate /* Compute a sector/fat figure */
14747c478bd9Sstevel@tonic-gate switch (Fatentsize) {
14757c478bd9Sstevel@tonic-gate case 32:
14767c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 0;
14770576819eSwyllys wbpb->bpb32.big_sectors_per_fat = fatsz;
14780576819eSwyllys if (Verbose)
1479f127cb91Sfrankho (void) printf("compute_cluster_size: Sectors per "
1480f127cb91Sfrankho "FAT32 = %d\n", wbpb->bpb32.big_sectors_per_fat);
14817c478bd9Sstevel@tonic-gate break;
14827c478bd9Sstevel@tonic-gate case 12:
14837c478bd9Sstevel@tonic-gate default: /* 16 bit FAT */
14840576819eSwyllys wbpb->bpb.sectors_per_fat = (ushort_t)(fatsz & 0x0000FFFF);
14850576819eSwyllys if (Verbose)
1486f127cb91Sfrankho (void) printf("compute_cluster_size: Sectors per "
1487f127cb91Sfrankho "FAT16 = %d\n", wbpb->bpb.sectors_per_fat);
14887c478bd9Sstevel@tonic-gate break;
14897c478bd9Sstevel@tonic-gate }
14907c478bd9Sstevel@tonic-gate }
14917c478bd9Sstevel@tonic-gate
14927c478bd9Sstevel@tonic-gate static
14937c478bd9Sstevel@tonic-gate void
find_fixed_details(int fd,bpb_t * wbpb)14947c478bd9Sstevel@tonic-gate find_fixed_details(int fd, bpb_t *wbpb)
14957c478bd9Sstevel@tonic-gate {
14967c478bd9Sstevel@tonic-gate struct dk_geom dginfo;
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate /*
14997c478bd9Sstevel@tonic-gate * Look up the last remaining bits of info we need
15007c478bd9Sstevel@tonic-gate * that is specific to the hard drive using a disk ioctl.
15017c478bd9Sstevel@tonic-gate */
15027c478bd9Sstevel@tonic-gate if (GetSPT || GetTPC) {
1503f127cb91Sfrankho if (ioctl(fd, DKIOCG_VIRTGEOM, &dginfo) == -1 &&
1504f127cb91Sfrankho ioctl(fd, DKIOCG_PHYGEOM, &dginfo) == -1 &&
1505f127cb91Sfrankho ioctl(fd, DKIOCGGEOM, &dginfo) == -1) {
1506f127cb91Sfrankho (void) close(fd);
1507f127cb91Sfrankho perror(
1508f127cb91Sfrankho gettext("Drive geometry lookup (need "
1509f127cb91Sfrankho "tracks/cylinder and/or sectors/track"));
1510f127cb91Sfrankho exit(2);
15117c478bd9Sstevel@tonic-gate }
15127c478bd9Sstevel@tonic-gate }
15137c478bd9Sstevel@tonic-gate
15147c478bd9Sstevel@tonic-gate wbpb->bpb.heads = (GetTPC ? dginfo.dkg_nhead : TrkPerCyl);
15157c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track = (GetSPT ? dginfo.dkg_nsect : SecPerTrk);
15167c478bd9Sstevel@tonic-gate
15177c478bd9Sstevel@tonic-gate if (Verbose) {
15187c478bd9Sstevel@tonic-gate if (GetTPC) {
1519f127cb91Sfrankho (void) printf(
1520f127cb91Sfrankho gettext("DKIOCG determined number of heads = %d\n"),
1521f127cb91Sfrankho dginfo.dkg_nhead);
15227c478bd9Sstevel@tonic-gate }
15237c478bd9Sstevel@tonic-gate if (GetSPT) {
1524f127cb91Sfrankho (void) printf(
1525f127cb91Sfrankho gettext("DKIOCG determined sectors per track"
1526f127cb91Sfrankho " = %d\n"), dginfo.dkg_nsect);
15277c478bd9Sstevel@tonic-gate }
15287c478bd9Sstevel@tonic-gate }
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate /*
15317c478bd9Sstevel@tonic-gate * XXX - MAY need an additional flag (or flags) to set media
15327c478bd9Sstevel@tonic-gate * and physical drive number fields. That in the case of weird
15337c478bd9Sstevel@tonic-gate * floppies that have to go through 'nofdisk' route for formatting.
15347c478bd9Sstevel@tonic-gate */
15357c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF8;
15367c478bd9Sstevel@tonic-gate if (MakeFAT32)
15377c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 0;
15387c478bd9Sstevel@tonic-gate else
15397c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 512;
15407c478bd9Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0x80;
15417c478bd9Sstevel@tonic-gate compute_cluster_size(wbpb);
15427c478bd9Sstevel@tonic-gate }
15437c478bd9Sstevel@tonic-gate
15447c478bd9Sstevel@tonic-gate static
15457c478bd9Sstevel@tonic-gate char *
stat_actual_disk(char * diskname,struct stat * info,char ** suffix)15467c478bd9Sstevel@tonic-gate stat_actual_disk(char *diskname, struct stat *info, char **suffix)
15477c478bd9Sstevel@tonic-gate {
15487c478bd9Sstevel@tonic-gate char *actualdisk;
15497c478bd9Sstevel@tonic-gate
15507c478bd9Sstevel@tonic-gate if (stat(diskname, info)) {
15517c478bd9Sstevel@tonic-gate /*
15527c478bd9Sstevel@tonic-gate * Device named on command line doesn't exist. That
15537c478bd9Sstevel@tonic-gate * probably means there is a partition-specifying
15547c478bd9Sstevel@tonic-gate * suffix attached to the actual disk name.
15557c478bd9Sstevel@tonic-gate */
15567c478bd9Sstevel@tonic-gate actualdisk = strtok(strdup(diskname), ":");
15577c478bd9Sstevel@tonic-gate if (*suffix = strchr(diskname, ':'))
15587c478bd9Sstevel@tonic-gate (*suffix)++;
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate if (stat(actualdisk, info)) {
15617c478bd9Sstevel@tonic-gate perror(actualdisk);
15627c478bd9Sstevel@tonic-gate exit(2);
15637c478bd9Sstevel@tonic-gate }
15647c478bd9Sstevel@tonic-gate } else {
15657c478bd9Sstevel@tonic-gate actualdisk = strdup(diskname);
15667c478bd9Sstevel@tonic-gate }
15677c478bd9Sstevel@tonic-gate
15687c478bd9Sstevel@tonic-gate return (actualdisk);
15697c478bd9Sstevel@tonic-gate }
15707c478bd9Sstevel@tonic-gate
15717c478bd9Sstevel@tonic-gate static
15727c478bd9Sstevel@tonic-gate void
compute_file_area_size(bpb_t * wbpb)15737c478bd9Sstevel@tonic-gate compute_file_area_size(bpb_t *wbpb)
15747c478bd9Sstevel@tonic-gate {
15750576819eSwyllys int FATSz;
15760576819eSwyllys int TotSec;
15770576819eSwyllys int DataSec;
1578f127cb91Sfrankho int RootDirSectors =
1579f127cb91Sfrankho ((wbpb->bpb.num_root_entries * 32) + (wbpb->bpb.bytes_sector - 1)) /
1580f127cb91Sfrankho wbpb->bpb.bytes_sector;
15817c478bd9Sstevel@tonic-gate
15827c478bd9Sstevel@tonic-gate if (wbpb->bpb.sectors_per_fat) {
15837c478bd9Sstevel@tonic-gate /*
15847c478bd9Sstevel@tonic-gate * Good old FAT12 or FAT16
15857c478bd9Sstevel@tonic-gate */
15860576819eSwyllys FATSz = wbpb->bpb.sectors_per_fat;
15870576819eSwyllys TotSec = wbpb->bpb.sectors_in_volume;
15887c478bd9Sstevel@tonic-gate } else {
15897c478bd9Sstevel@tonic-gate /*
15907c478bd9Sstevel@tonic-gate * FAT32
15917c478bd9Sstevel@tonic-gate */
15920576819eSwyllys FATSz = wbpb->bpb32.big_sectors_per_fat;
15930576819eSwyllys TotSec = wbpb->bpb.sectors_in_logical_volume;
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate
1596f127cb91Sfrankho DataSec = TotSec -
1597f127cb91Sfrankho (wbpb->bpb.resv_sectors + (wbpb->bpb.num_fats * FATSz) +
1598f127cb91Sfrankho RootDirSectors);
15990576819eSwyllys
16000576819eSwyllys
16017c478bd9Sstevel@tonic-gate /*
16027c478bd9Sstevel@tonic-gate * Now change sectors to clusters
16037c478bd9Sstevel@tonic-gate */
16040576819eSwyllys TotalClusters = DataSec / wbpb->bpb.sectors_per_cluster;
16057c478bd9Sstevel@tonic-gate
16067c478bd9Sstevel@tonic-gate if (Verbose)
16077c478bd9Sstevel@tonic-gate (void) printf(gettext("Disk has a file area of %d "
16087c478bd9Sstevel@tonic-gate "allocation units,\neach with %d sectors = %d "
16097c478bd9Sstevel@tonic-gate "bytes.\n"), TotalClusters, wbpb->bpb.sectors_per_cluster,
16107c478bd9Sstevel@tonic-gate TotalClusters * wbpb->bpb.sectors_per_cluster * BPSEC);
16117c478bd9Sstevel@tonic-gate }
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate #ifndef i386
16147c478bd9Sstevel@tonic-gate /*
16157c478bd9Sstevel@tonic-gate * swap_pack_{bpb,bpb32,sebpb}cpy
16167c478bd9Sstevel@tonic-gate *
16177c478bd9Sstevel@tonic-gate * If not on an x86 we assume the structures making up the bpb
16187c478bd9Sstevel@tonic-gate * were not packed and that longs and shorts need to be byte swapped
16197c478bd9Sstevel@tonic-gate * (we've kept everything in host order up until now). A new architecture
16207c478bd9Sstevel@tonic-gate * might not need to swap or might not need to pack, in which case
16217c478bd9Sstevel@tonic-gate * new routines will have to be written. Of course if an architecture
16227c478bd9Sstevel@tonic-gate * supports both packing and little-endian host order, it can follow the
16237c478bd9Sstevel@tonic-gate * same path as the x86 code.
16247c478bd9Sstevel@tonic-gate */
16257c478bd9Sstevel@tonic-gate static
16267c478bd9Sstevel@tonic-gate void
swap_pack_bpbcpy(struct _boot_sector * bsp,bpb_t * wbpb)16277c478bd9Sstevel@tonic-gate swap_pack_bpbcpy(struct _boot_sector *bsp, bpb_t *wbpb)
16287c478bd9Sstevel@tonic-gate {
16297c478bd9Sstevel@tonic-gate uchar_t *fillp;
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate fillp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]);
16327c478bd9Sstevel@tonic-gate
16337c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.bytes_sector);
16347c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.sectors_per_cluster;
16357c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.resv_sectors);
16367c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.num_fats;
16377c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.num_root_entries);
16387c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_in_volume);
16397c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.media;
16407c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_fat);
16417c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_track);
16427c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.heads);
16437c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.hidden_sectors);
16447c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.sectors_in_logical_volume);
16457c478bd9Sstevel@tonic-gate
16467c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.phys_drive_num;
16477c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.reserved;
16487c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.ext_signature;
16497c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->ebpb.volume_id);
16507c478bd9Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.volume_label, 11);
16517c478bd9Sstevel@tonic-gate fillp += 11;
16527c478bd9Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.type, 8);
16537c478bd9Sstevel@tonic-gate }
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate static
16567c478bd9Sstevel@tonic-gate void
swap_pack_bpb32cpy(struct _boot_sector32 * bsp,bpb_t * wbpb)16577c478bd9Sstevel@tonic-gate swap_pack_bpb32cpy(struct _boot_sector32 *bsp, bpb_t *wbpb)
16587c478bd9Sstevel@tonic-gate {
16597c478bd9Sstevel@tonic-gate uchar_t *fillp;
16607c478bd9Sstevel@tonic-gate int r;
16617c478bd9Sstevel@tonic-gate
16627c478bd9Sstevel@tonic-gate fillp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]);
16637c478bd9Sstevel@tonic-gate
16647c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.bytes_sector);
16657c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.sectors_per_cluster;
16667c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.resv_sectors);
16677c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.num_fats;
16687c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.num_root_entries);
16697c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_in_volume);
16707c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.media;
16717c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_fat);
16727c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_track);
16737c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.heads);
16747c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.hidden_sectors);
16757c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.sectors_in_logical_volume);
16767c478bd9Sstevel@tonic-gate
16777c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb32.big_sectors_per_fat);
16787c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.ext_flags);
16797c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb32.fs_vers_lo;
16807c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb32.fs_vers_hi;
16817c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb32.root_dir_clust);
16827c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.fsinfosec);
16837c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.backupboot);
16847c478bd9Sstevel@tonic-gate for (r = 0; r < 6; r++)
16857c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.reserved[r]);
16867c478bd9Sstevel@tonic-gate
16877c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.phys_drive_num;
16887c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.reserved;
16897c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.ext_signature;
16907c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->ebpb.volume_id);
16917c478bd9Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.volume_label, 11);
16927c478bd9Sstevel@tonic-gate fillp += 11;
16937c478bd9Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.type, 8);
16947c478bd9Sstevel@tonic-gate }
16957c478bd9Sstevel@tonic-gate
16967c478bd9Sstevel@tonic-gate static
16977c478bd9Sstevel@tonic-gate void
swap_pack_sebpbcpy(struct _boot_sector * bsp,bpb_t * wbpb)16987c478bd9Sstevel@tonic-gate swap_pack_sebpbcpy(struct _boot_sector *bsp, bpb_t *wbpb)
16997c478bd9Sstevel@tonic-gate {
17007c478bd9Sstevel@tonic-gate uchar_t *fillp;
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate fillp = bsp->bs_sun_bpb;
17037c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->sunbpb.bs_offset_high);
17047c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->sunbpb.bs_offset_low);
17057c478bd9Sstevel@tonic-gate }
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate static
17087c478bd9Sstevel@tonic-gate void
swap_pack_grabbpb(bpb_t * wbpb,struct _boot_sector * bsp)17097c478bd9Sstevel@tonic-gate swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp)
17107c478bd9Sstevel@tonic-gate {
17117c478bd9Sstevel@tonic-gate uchar_t *grabp;
17127c478bd9Sstevel@tonic-gate
17137c478bd9Sstevel@tonic-gate grabp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]);
17147c478bd9Sstevel@tonic-gate
17157c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.bytes_sector))[1] = *grabp++;
17167c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.bytes_sector))[0] = *grabp++;
17177c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = *grabp++;
17187c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.resv_sectors))[1] = *grabp++;
17197c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.resv_sectors))[0] = *grabp++;
17207c478bd9Sstevel@tonic-gate wbpb->bpb.num_fats = *grabp++;
17217c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.num_root_entries))[1] = *grabp++;
17227c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.num_root_entries))[0] = *grabp++;
17237c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_volume))[1] = *grabp++;
17247c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_volume))[0] = *grabp++;
17257c478bd9Sstevel@tonic-gate wbpb->bpb.media = *grabp++;
17267c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_fat))[1] = *grabp++;
17277c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_fat))[0] = *grabp++;
17287c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_track))[1] = *grabp++;
17297c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_track))[0] = *grabp++;
17307c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.heads))[1] = *grabp++;
17317c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.heads))[0] = *grabp++;
17327c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[3] = *grabp++;
17337c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[2] = *grabp++;
17347c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[1] = *grabp++;
17357c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[0] = *grabp++;
17367c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[3] = *grabp++;
17377c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[2] = *grabp++;
17387c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[1] = *grabp++;
17397c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[0] = *grabp++;
17407c478bd9Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = *grabp++;
17417c478bd9Sstevel@tonic-gate wbpb->ebpb.reserved = *grabp++;
17427c478bd9Sstevel@tonic-gate wbpb->ebpb.ext_signature = *grabp++;
17437c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[3] = *grabp++;
17447c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[2] = *grabp++;
17457c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[1] = *grabp++;
17467c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[0] = *grabp++;
17477c478bd9Sstevel@tonic-gate
17487c478bd9Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.volume_label, (char *)grabp, 11);
17497c478bd9Sstevel@tonic-gate grabp += 11;
17507c478bd9Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, (char *)grabp, 8);
17517c478bd9Sstevel@tonic-gate }
17527c478bd9Sstevel@tonic-gate
17537c478bd9Sstevel@tonic-gate static
17547c478bd9Sstevel@tonic-gate void
swap_pack_grabsebpb(bpb_t * wbpb,struct _boot_sector * bsp)17557c478bd9Sstevel@tonic-gate swap_pack_grabsebpb(bpb_t *wbpb, struct _boot_sector *bsp)
17567c478bd9Sstevel@tonic-gate {
17577c478bd9Sstevel@tonic-gate uchar_t *grabp;
17587c478bd9Sstevel@tonic-gate
17597c478bd9Sstevel@tonic-gate grabp = bsp->bs_sun_bpb;
17607c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_high))[1] = *grabp++;
17617c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_high))[0] = *grabp++;
17627c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_low))[1] = *grabp++;
17637c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_low))[0] = *grabp++;
17647c478bd9Sstevel@tonic-gate }
17657c478bd9Sstevel@tonic-gate
17667c478bd9Sstevel@tonic-gate static
17677c478bd9Sstevel@tonic-gate void
swap_pack_grab32bpb(bpb_t * wbpb,struct _boot_sector * bsp)17687c478bd9Sstevel@tonic-gate swap_pack_grab32bpb(bpb_t *wbpb, struct _boot_sector *bsp)
17697c478bd9Sstevel@tonic-gate {
17707c478bd9Sstevel@tonic-gate uchar_t *grabp;
17717c478bd9Sstevel@tonic-gate
17727c478bd9Sstevel@tonic-gate grabp = (uchar_t *)&(bsp->bs_filler[BPB_32_START_INDEX]);
17737c478bd9Sstevel@tonic-gate
17747c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[3] = *grabp++;
17757c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[2] = *grabp++;
17767c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[1] = *grabp++;
17777c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[0] = *grabp++;
17787c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.ext_flags))[1] = *grabp++;
17797c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.ext_flags))[0] = *grabp++;
17807c478bd9Sstevel@tonic-gate wbpb->bpb32.fs_vers_lo = *grabp++;
17817c478bd9Sstevel@tonic-gate wbpb->bpb32.fs_vers_hi = *grabp++;
17827c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[3] = *grabp++;
17837c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[2] = *grabp++;
17847c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[1] = *grabp++;
17857c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[0] = *grabp++;
17867c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.fsinfosec))[1] = *grabp++;
17877c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.fsinfosec))[0] = *grabp++;
17887c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.backupboot))[1] = *grabp++;
17897c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.backupboot))[0] = *grabp++;
17907c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[0]))[1] = *grabp++;
17917c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[0]))[0] = *grabp++;
17927c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[1]))[1] = *grabp++;
17937c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[1]))[0] = *grabp++;
17947c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[2]))[1] = *grabp++;
17957c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[2]))[0] = *grabp++;
17967c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[3]))[1] = *grabp++;
17977c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[3]))[0] = *grabp++;
17987c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[4]))[1] = *grabp++;
17997c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[4]))[0] = *grabp++;
18007c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[5]))[1] = *grabp++;
18017c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[5]))[0] = *grabp++;
18027c478bd9Sstevel@tonic-gate }
18037c478bd9Sstevel@tonic-gate #endif /* ! i386 */
18047c478bd9Sstevel@tonic-gate
18057c478bd9Sstevel@tonic-gate static
18067c478bd9Sstevel@tonic-gate void
dashm_bail(int fd)18077c478bd9Sstevel@tonic-gate dashm_bail(int fd)
18087c478bd9Sstevel@tonic-gate {
18097c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
1810f127cb91Sfrankho gettext("This media does not appear to be "
1811f127cb91Sfrankho "formatted with a FAT file system.\n"));
18127c478bd9Sstevel@tonic-gate (void) close(fd);
18137c478bd9Sstevel@tonic-gate exit(6);
18147c478bd9Sstevel@tonic-gate }
18157c478bd9Sstevel@tonic-gate
18167c478bd9Sstevel@tonic-gate /*
18177c478bd9Sstevel@tonic-gate * read_existing_bpb
18187c478bd9Sstevel@tonic-gate *
18197c478bd9Sstevel@tonic-gate * Grab the first sector, which we think is a bios parameter block.
18207c478bd9Sstevel@tonic-gate * If it looks bad, bail. Otherwise fill in the parameter struct
18217c478bd9Sstevel@tonic-gate * fields that matter.
18227c478bd9Sstevel@tonic-gate */
18237c478bd9Sstevel@tonic-gate static
18247c478bd9Sstevel@tonic-gate void
read_existing_bpb(int fd,bpb_t * wbpb)18257c478bd9Sstevel@tonic-gate read_existing_bpb(int fd, bpb_t *wbpb)
18267c478bd9Sstevel@tonic-gate {
18277c478bd9Sstevel@tonic-gate boot_sector_t ubpb;
18287c478bd9Sstevel@tonic-gate
18297c478bd9Sstevel@tonic-gate if (read(fd, ubpb.buf, BPSEC) < BPSEC) {
18307c478bd9Sstevel@tonic-gate perror(gettext("Read BIOS parameter block "
1831f127cb91Sfrankho "from previously formatted media"));
18327c478bd9Sstevel@tonic-gate (void) close(fd);
18337c478bd9Sstevel@tonic-gate exit(6);
18347c478bd9Sstevel@tonic-gate }
18357c478bd9Sstevel@tonic-gate
18367c478bd9Sstevel@tonic-gate if (ltohs(ubpb.mb.signature) != BOOTSECSIG) {
18377c478bd9Sstevel@tonic-gate dashm_bail(fd);
18387c478bd9Sstevel@tonic-gate }
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate #ifdef i386
18417c478bd9Sstevel@tonic-gate (void) memcpy(&(wbpb->bpb), &(ubpb.bs.bs_front.bs_bpb),
1842f127cb91Sfrankho sizeof (wbpb->bpb));
18437c478bd9Sstevel@tonic-gate (void) memcpy(&(wbpb->ebpb), &(ubpb.bs.bs_ebpb), sizeof (wbpb->ebpb));
18447c478bd9Sstevel@tonic-gate #else
18457c478bd9Sstevel@tonic-gate swap_pack_grabbpb(wbpb, &(ubpb.bs));
18467c478bd9Sstevel@tonic-gate #endif
18477c478bd9Sstevel@tonic-gate if (SunBPBfields) {
18487c478bd9Sstevel@tonic-gate #ifdef i386
18497c478bd9Sstevel@tonic-gate (void) memcpy(&(wbpb->sunbpb), &(ubpb.bs.bs_sebpb),
1850f127cb91Sfrankho sizeof (wbpb->sunbpb));
18517c478bd9Sstevel@tonic-gate #else
18527c478bd9Sstevel@tonic-gate swap_pack_grabsebpb(wbpb, &(ubpb.bs));
18537c478bd9Sstevel@tonic-gate #endif
18547c478bd9Sstevel@tonic-gate }
18557c478bd9Sstevel@tonic-gate if (wbpb->bpb.bytes_sector != BPSEC) {
18567c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
18577c478bd9Sstevel@tonic-gate gettext("Bogus bytes per sector value.\n"));
1858db92b35aSGary Mills if (!(ISP2(wbpb->bpb.bytes_sector) &&
1859db92b35aSGary Mills IN_RANGE(wbpb->bpb.bytes_sector, 1, BPSEC * 8))) {
18607c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
18617c478bd9Sstevel@tonic-gate gettext("The device name may be missing a "
1862f127cb91Sfrankho "logical drive specifier.\n"));
18637c478bd9Sstevel@tonic-gate (void) close(fd);
18647c478bd9Sstevel@tonic-gate exit(6);
18657c478bd9Sstevel@tonic-gate } else {
18667c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
18677c478bd9Sstevel@tonic-gate gettext("Do not know how to build FATs with a\n"
1868f127cb91Sfrankho "non-standard sector size. Standard "
1869f127cb91Sfrankho "size is %d bytes,\nyour sector size "
1870f127cb91Sfrankho "is %d bytes.\n"), BPSEC,
1871f127cb91Sfrankho wbpb->bpb.bytes_sector);
18727c478bd9Sstevel@tonic-gate (void) close(fd);
18737c478bd9Sstevel@tonic-gate exit(6);
18747c478bd9Sstevel@tonic-gate }
18757c478bd9Sstevel@tonic-gate }
1876db92b35aSGary Mills if (!(ISP2(wbpb->bpb.sectors_per_cluster) &&
1877db92b35aSGary Mills IN_RANGE(wbpb->bpb.sectors_per_cluster, 1, 128))) {
18787c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
18797c478bd9Sstevel@tonic-gate gettext("Bogus sectors per cluster value.\n"));
18807c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
18817c478bd9Sstevel@tonic-gate gettext("The device name may be missing a "
1882f127cb91Sfrankho "logical drive specifier.\n"));
18837c478bd9Sstevel@tonic-gate (void) close(fd);
18847c478bd9Sstevel@tonic-gate exit(6);
18857c478bd9Sstevel@tonic-gate }
18867c478bd9Sstevel@tonic-gate
18877c478bd9Sstevel@tonic-gate if (wbpb->bpb.sectors_per_fat == 0) {
18887c478bd9Sstevel@tonic-gate #ifdef i386
18897c478bd9Sstevel@tonic-gate (void) memcpy(&(wbpb->bpb32), &(ubpb.bs32.bs_bpb32),
1890f127cb91Sfrankho sizeof (wbpb->bpb32));
18917c478bd9Sstevel@tonic-gate #else
18927c478bd9Sstevel@tonic-gate swap_pack_grab32bpb(wbpb, &(ubpb.bs));
18937c478bd9Sstevel@tonic-gate #endif
18947c478bd9Sstevel@tonic-gate compute_file_area_size(wbpb);
18957c478bd9Sstevel@tonic-gate if ((wbpb->bpb32.big_sectors_per_fat * BPSEC / 4) >=
18967c478bd9Sstevel@tonic-gate TotalClusters) {
18977c478bd9Sstevel@tonic-gate MakeFAT32 = 1;
18987c478bd9Sstevel@tonic-gate } else {
18997c478bd9Sstevel@tonic-gate dashm_bail(fd);
19007c478bd9Sstevel@tonic-gate }
19017c478bd9Sstevel@tonic-gate } else {
19027c478bd9Sstevel@tonic-gate compute_file_area_size(wbpb);
19037c478bd9Sstevel@tonic-gate }
19047c478bd9Sstevel@tonic-gate }
19057c478bd9Sstevel@tonic-gate
19067c478bd9Sstevel@tonic-gate /*
19077c478bd9Sstevel@tonic-gate * compare_existing_with_computed
19087c478bd9Sstevel@tonic-gate *
19097c478bd9Sstevel@tonic-gate * We use this function when we the user specifies the -m option.
19107c478bd9Sstevel@tonic-gate * We compute and look up things like we would if they had asked
19117c478bd9Sstevel@tonic-gate * us to make the fs, and compare that to what's already layed down
19127c478bd9Sstevel@tonic-gate * in the existing fs. If there's a difference we can tell them what
19137c478bd9Sstevel@tonic-gate * options to specify in order to reproduce their existing layout.
19147c478bd9Sstevel@tonic-gate * Note that they still may not get an exact duplicate, because we
19157c478bd9Sstevel@tonic-gate * don't, for example, preserve their existing boot code. We think
19167c478bd9Sstevel@tonic-gate * we've got all the fields that matter covered, though.
19177c478bd9Sstevel@tonic-gate *
19187c478bd9Sstevel@tonic-gate * XXX - We're basically ignoring sbpb at this point. I'm unsure
19197c478bd9Sstevel@tonic-gate * if we'll ever care about those fields, in terms of the -m option.
19207c478bd9Sstevel@tonic-gate */
19217c478bd9Sstevel@tonic-gate static
19227c478bd9Sstevel@tonic-gate void
compare_existing_with_computed(int fd,char * suffix,bpb_t * wbpb,int * prtsize,int * prtspc,int * prtbpf,int * prtnsect,int * prtntrk,int * prtfdisk,int * prthidden,int * prtrsrvd,int * dashos)19237c478bd9Sstevel@tonic-gate compare_existing_with_computed(int fd, char *suffix,
19247c478bd9Sstevel@tonic-gate bpb_t *wbpb, int *prtsize, int *prtspc, int *prtbpf, int *prtnsect,
19257c478bd9Sstevel@tonic-gate int *prtntrk, int *prtfdisk, int *prthidden, int *prtrsrvd, int *dashos)
19267c478bd9Sstevel@tonic-gate {
19277c478bd9Sstevel@tonic-gate struct dk_geom dginfo;
19287c478bd9Sstevel@tonic-gate struct fd_char fdchar;
19297c478bd9Sstevel@tonic-gate bpb_t compare;
19307c478bd9Sstevel@tonic-gate int fd_ioctl_worked = 0;
19317c478bd9Sstevel@tonic-gate int fatents;
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate /*
19347c478bd9Sstevel@tonic-gate * For all non-floppy cases we expect to find a 16-bit FAT
19357c478bd9Sstevel@tonic-gate */
19367c478bd9Sstevel@tonic-gate int expectfatsize = 16;
19377c478bd9Sstevel@tonic-gate
19387c478bd9Sstevel@tonic-gate compare = *wbpb;
19397c478bd9Sstevel@tonic-gate
19407c478bd9Sstevel@tonic-gate if (!suffix) {
19417c478bd9Sstevel@tonic-gate if (ioctl(fd, FDIOGCHAR, &fdchar) != -1) {
19427c478bd9Sstevel@tonic-gate expectfatsize = 12;
19437c478bd9Sstevel@tonic-gate fd_ioctl_worked++;
19447c478bd9Sstevel@tonic-gate }
19457c478bd9Sstevel@tonic-gate }
19467c478bd9Sstevel@tonic-gate
19477c478bd9Sstevel@tonic-gate if (fd_ioctl_worked) {
19487c478bd9Sstevel@tonic-gate #ifdef sparc
19497c478bd9Sstevel@tonic-gate fdchar.fdc_medium = 3;
19507c478bd9Sstevel@tonic-gate #endif
19517c478bd9Sstevel@tonic-gate GetSize = GetSPT = GetSPC = GetTPC = GetBPF = 1;
19527c478bd9Sstevel@tonic-gate lookup_floppy(&fdchar, &compare);
19537c478bd9Sstevel@tonic-gate if (compare.bpb.heads != wbpb->bpb.heads) {
19547c478bd9Sstevel@tonic-gate (*prtntrk)++;
19557c478bd9Sstevel@tonic-gate (*dashos)++;
19567c478bd9Sstevel@tonic-gate }
19577c478bd9Sstevel@tonic-gate if (compare.bpb.sectors_per_track !=
19587c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track) {
19597c478bd9Sstevel@tonic-gate (*prtnsect)++;
19607c478bd9Sstevel@tonic-gate (*dashos)++;
19617c478bd9Sstevel@tonic-gate }
19627c478bd9Sstevel@tonic-gate } else {
19637c478bd9Sstevel@tonic-gate int dk_ioctl_worked = 1;
19647c478bd9Sstevel@tonic-gate
19657c478bd9Sstevel@tonic-gate if (!suffix) {
19667c478bd9Sstevel@tonic-gate (*prtfdisk)++;
19677c478bd9Sstevel@tonic-gate (*prtsize)++;
19687c478bd9Sstevel@tonic-gate *dashos += 2;
19697c478bd9Sstevel@tonic-gate }
1970f127cb91Sfrankho if (ioctl(fd, DKIOCG_VIRTGEOM, &dginfo) == -1 &&
1971f127cb91Sfrankho ioctl(fd, DKIOCG_PHYGEOM, &dginfo) == -1 &&
1972f127cb91Sfrankho ioctl(fd, DKIOCGGEOM, &dginfo) == -1) {
1973f127cb91Sfrankho *prtnsect = *prtntrk = 1;
1974f127cb91Sfrankho *dashos += 2;
1975f127cb91Sfrankho dk_ioctl_worked = 0;
19767c478bd9Sstevel@tonic-gate }
19777c478bd9Sstevel@tonic-gate if (dk_ioctl_worked) {
19787c478bd9Sstevel@tonic-gate if (dginfo.dkg_nhead != wbpb->bpb.heads) {
19797c478bd9Sstevel@tonic-gate (*prtntrk)++;
19807c478bd9Sstevel@tonic-gate (*dashos)++;
19817c478bd9Sstevel@tonic-gate }
19827c478bd9Sstevel@tonic-gate if (dginfo.dkg_nsect !=
19837c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track) {
19847c478bd9Sstevel@tonic-gate (*prtnsect)++;
19857c478bd9Sstevel@tonic-gate (*dashos)++;
19867c478bd9Sstevel@tonic-gate }
19877c478bd9Sstevel@tonic-gate }
19887c478bd9Sstevel@tonic-gate GetBPF = GetSPC = 1;
19897c478bd9Sstevel@tonic-gate compute_cluster_size(&compare);
19907c478bd9Sstevel@tonic-gate }
19917c478bd9Sstevel@tonic-gate
19927c478bd9Sstevel@tonic-gate if (!*prtfdisk && TotSize != wbpb->bpb.sectors_in_volume &&
1993f127cb91Sfrankho TotSize != wbpb->bpb.sectors_in_logical_volume) {
19947c478bd9Sstevel@tonic-gate (*dashos)++;
19957c478bd9Sstevel@tonic-gate (*prtsize)++;
19967c478bd9Sstevel@tonic-gate }
19977c478bd9Sstevel@tonic-gate
19987c478bd9Sstevel@tonic-gate if (compare.bpb.sectors_per_cluster != wbpb->bpb.sectors_per_cluster) {
19997c478bd9Sstevel@tonic-gate (*dashos)++;
20007c478bd9Sstevel@tonic-gate (*prtspc)++;
20017c478bd9Sstevel@tonic-gate }
20027c478bd9Sstevel@tonic-gate
20037c478bd9Sstevel@tonic-gate if (compare.bpb.hidden_sectors != wbpb->bpb.hidden_sectors) {
20047c478bd9Sstevel@tonic-gate (*dashos)++;
20057c478bd9Sstevel@tonic-gate (*prthidden)++;
20067c478bd9Sstevel@tonic-gate }
20077c478bd9Sstevel@tonic-gate
20087c478bd9Sstevel@tonic-gate if (compare.bpb.resv_sectors != wbpb->bpb.resv_sectors) {
20097c478bd9Sstevel@tonic-gate (*dashos)++;
20107c478bd9Sstevel@tonic-gate (*prtrsrvd)++;
20117c478bd9Sstevel@tonic-gate }
20127c478bd9Sstevel@tonic-gate
20137c478bd9Sstevel@tonic-gate /*
20147c478bd9Sstevel@tonic-gate * Compute approximate Fatentsize. It's approximate because the
20157c478bd9Sstevel@tonic-gate * size of the FAT may not be exactly a multiple of the number of
20167c478bd9Sstevel@tonic-gate * clusters. It should be close, though.
20177c478bd9Sstevel@tonic-gate */
20187c478bd9Sstevel@tonic-gate if (MakeFAT32) {
20197c478bd9Sstevel@tonic-gate Fatentsize = 32;
20207c478bd9Sstevel@tonic-gate (*dashos)++;
20217c478bd9Sstevel@tonic-gate (*prtbpf)++;
20227c478bd9Sstevel@tonic-gate } else {
20237c478bd9Sstevel@tonic-gate fatents = wbpb->bpb.sectors_per_fat * BPSEC * 2 / 3;
20247c478bd9Sstevel@tonic-gate if (fatents >= TotalClusters && wbpb->ebpb.type[4] == '2')
20257c478bd9Sstevel@tonic-gate Fatentsize = 12;
20267c478bd9Sstevel@tonic-gate else
20277c478bd9Sstevel@tonic-gate Fatentsize = 16;
20287c478bd9Sstevel@tonic-gate if (Fatentsize != expectfatsize) {
20297c478bd9Sstevel@tonic-gate (*dashos)++;
20307c478bd9Sstevel@tonic-gate (*prtbpf)++;
20317c478bd9Sstevel@tonic-gate }
20327c478bd9Sstevel@tonic-gate }
20337c478bd9Sstevel@tonic-gate }
20347c478bd9Sstevel@tonic-gate
20357c478bd9Sstevel@tonic-gate static
20367c478bd9Sstevel@tonic-gate void
print_reproducing_command(int fd,char * actualdisk,char * suffix,bpb_t * wbpb)20377c478bd9Sstevel@tonic-gate print_reproducing_command(int fd, char *actualdisk, char *suffix, bpb_t *wbpb)
20387c478bd9Sstevel@tonic-gate {
20397c478bd9Sstevel@tonic-gate int needcomma = 0;
20407c478bd9Sstevel@tonic-gate int prthidden = 0;
20417c478bd9Sstevel@tonic-gate int prtrsrvd = 0;
20427c478bd9Sstevel@tonic-gate int prtfdisk = 0;
20437c478bd9Sstevel@tonic-gate int prtnsect = 0;
20447c478bd9Sstevel@tonic-gate int prtntrk = 0;
20457c478bd9Sstevel@tonic-gate int prtsize = 0;
20467c478bd9Sstevel@tonic-gate int prtbpf = 0;
20477c478bd9Sstevel@tonic-gate int prtspc = 0;
20487c478bd9Sstevel@tonic-gate int dashos = 0;
20497c478bd9Sstevel@tonic-gate int ll, i;
20507c478bd9Sstevel@tonic-gate
20517c478bd9Sstevel@tonic-gate compare_existing_with_computed(fd, suffix, wbpb,
20527c478bd9Sstevel@tonic-gate &prtsize, &prtspc, &prtbpf, &prtnsect, &prtntrk,
20537c478bd9Sstevel@tonic-gate &prtfdisk, &prthidden, &prtrsrvd, &dashos);
20547c478bd9Sstevel@tonic-gate
20557c478bd9Sstevel@tonic-gate /*
20567c478bd9Sstevel@tonic-gate * Print out the command line they can use to reproduce the
20577c478bd9Sstevel@tonic-gate * file system.
20587c478bd9Sstevel@tonic-gate */
20597c478bd9Sstevel@tonic-gate (void) printf("mkfs -F pcfs");
20607c478bd9Sstevel@tonic-gate
20617c478bd9Sstevel@tonic-gate ll = min(11, (int)strlen((char *)wbpb->ebpb.volume_label));
20627c478bd9Sstevel@tonic-gate /*
20637c478bd9Sstevel@tonic-gate * First, eliminate trailing spaces. Now compare the name against
20647c478bd9Sstevel@tonic-gate * our default label. If there's a match we don't need to print
20657c478bd9Sstevel@tonic-gate * any label info.
20667c478bd9Sstevel@tonic-gate */
20677c478bd9Sstevel@tonic-gate i = ll;
2068f127cb91Sfrankho while (wbpb->ebpb.volume_label[--i] == ' ')
2069f127cb91Sfrankho ;
20707c478bd9Sstevel@tonic-gate ll = i;
20717c478bd9Sstevel@tonic-gate
20727c478bd9Sstevel@tonic-gate if (ll == strlen(DEFAULT_LABEL) - 1) {
20737c478bd9Sstevel@tonic-gate char cmpbuf[11];
20747c478bd9Sstevel@tonic-gate
20757c478bd9Sstevel@tonic-gate (void) strcpy(cmpbuf, DEFAULT_LABEL);
20767c478bd9Sstevel@tonic-gate for (i = ll; i >= 0; i--) {
20777c478bd9Sstevel@tonic-gate if (cmpbuf[i] !=
20787c478bd9Sstevel@tonic-gate toupper((int)(wbpb->ebpb.volume_label[i]))) {
20797c478bd9Sstevel@tonic-gate break;
20807c478bd9Sstevel@tonic-gate }
20817c478bd9Sstevel@tonic-gate }
20827c478bd9Sstevel@tonic-gate if (i < 0)
20837c478bd9Sstevel@tonic-gate ll = i;
20847c478bd9Sstevel@tonic-gate }
20857c478bd9Sstevel@tonic-gate
20867c478bd9Sstevel@tonic-gate if (ll >= 0) {
20877c478bd9Sstevel@tonic-gate (void) printf(" -o ");
20887c478bd9Sstevel@tonic-gate (void) printf("b=\"");
20897c478bd9Sstevel@tonic-gate for (i = 0; i <= ll; i++) {
20907c478bd9Sstevel@tonic-gate (void) printf("%c", wbpb->ebpb.volume_label[i]);
20917c478bd9Sstevel@tonic-gate }
20927c478bd9Sstevel@tonic-gate (void) printf("\"");
20937c478bd9Sstevel@tonic-gate needcomma++;
20947c478bd9Sstevel@tonic-gate } else if (dashos) {
20957c478bd9Sstevel@tonic-gate (void) printf(" -o ");
20967c478bd9Sstevel@tonic-gate }
20977c478bd9Sstevel@tonic-gate
20987c478bd9Sstevel@tonic-gate #define NEXT_DASH_O dashos--; needcomma++; continue
20997c478bd9Sstevel@tonic-gate
21007c478bd9Sstevel@tonic-gate while (dashos) {
21017c478bd9Sstevel@tonic-gate if (needcomma) {
21027c478bd9Sstevel@tonic-gate (void) printf(",");
21037c478bd9Sstevel@tonic-gate needcomma = 0;
21047c478bd9Sstevel@tonic-gate }
21057c478bd9Sstevel@tonic-gate if (prtfdisk) {
21067c478bd9Sstevel@tonic-gate (void) printf("nofdisk");
21077c478bd9Sstevel@tonic-gate prtfdisk--;
21087c478bd9Sstevel@tonic-gate NEXT_DASH_O;
21097c478bd9Sstevel@tonic-gate }
21107c478bd9Sstevel@tonic-gate if (prtsize) {
21117c478bd9Sstevel@tonic-gate (void) printf("size=%u", wbpb->bpb.sectors_in_volume ?
21127c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume :
21137c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume);
21147c478bd9Sstevel@tonic-gate prtsize--;
21157c478bd9Sstevel@tonic-gate NEXT_DASH_O;
21167c478bd9Sstevel@tonic-gate }
21177c478bd9Sstevel@tonic-gate if (prtnsect) {
21187c478bd9Sstevel@tonic-gate (void) printf("nsect=%d", wbpb->bpb.sectors_per_track);
21197c478bd9Sstevel@tonic-gate prtnsect--;
21207c478bd9Sstevel@tonic-gate NEXT_DASH_O;
21217c478bd9Sstevel@tonic-gate }
21227c478bd9Sstevel@tonic-gate if (prtspc) {
21237c478bd9Sstevel@tonic-gate (void) printf("spc=%d", wbpb->bpb.sectors_per_cluster);
21247c478bd9Sstevel@tonic-gate prtspc--;
21257c478bd9Sstevel@tonic-gate NEXT_DASH_O;
21267c478bd9Sstevel@tonic-gate }
21277c478bd9Sstevel@tonic-gate if (prtntrk) {
21287c478bd9Sstevel@tonic-gate (void) printf("ntrack=%d", wbpb->bpb.heads);
21297c478bd9Sstevel@tonic-gate prtntrk--;
21307c478bd9Sstevel@tonic-gate NEXT_DASH_O;
21317c478bd9Sstevel@tonic-gate }
21327c478bd9Sstevel@tonic-gate if (prtbpf) {
21337c478bd9Sstevel@tonic-gate (void) printf("fat=%d", Fatentsize);
21347c478bd9Sstevel@tonic-gate prtbpf--;
21357c478bd9Sstevel@tonic-gate NEXT_DASH_O;
21367c478bd9Sstevel@tonic-gate }
21377c478bd9Sstevel@tonic-gate if (prthidden) {
21387c478bd9Sstevel@tonic-gate (void) printf("hidden=%u", wbpb->bpb.hidden_sectors);
21397c478bd9Sstevel@tonic-gate prthidden--;
21407c478bd9Sstevel@tonic-gate NEXT_DASH_O;
21417c478bd9Sstevel@tonic-gate }
21427c478bd9Sstevel@tonic-gate if (prtrsrvd) {
21437c478bd9Sstevel@tonic-gate (void) printf("reserve=%d", wbpb->bpb.resv_sectors);
21447c478bd9Sstevel@tonic-gate prtrsrvd--;
21457c478bd9Sstevel@tonic-gate NEXT_DASH_O;
21467c478bd9Sstevel@tonic-gate }
21477c478bd9Sstevel@tonic-gate }
21487c478bd9Sstevel@tonic-gate
21497c478bd9Sstevel@tonic-gate (void) printf(" %s%c%c\n", actualdisk,
21507c478bd9Sstevel@tonic-gate suffix ? ':' : '\0', suffix ? *suffix : '\0');
21517c478bd9Sstevel@tonic-gate }
21527c478bd9Sstevel@tonic-gate
21537c478bd9Sstevel@tonic-gate /*
21547c478bd9Sstevel@tonic-gate * open_and_examine
21557c478bd9Sstevel@tonic-gate *
21567c478bd9Sstevel@tonic-gate * Open the requested 'dev_name'. Seek to point where
21577c478bd9Sstevel@tonic-gate * we'd expect to find boot sectors, etc., based on any ':partition'
21587c478bd9Sstevel@tonic-gate * attachments to the dev_name.
21597c478bd9Sstevel@tonic-gate *
21607c478bd9Sstevel@tonic-gate * Examine the fields of any existing boot sector and display best
21617c478bd9Sstevel@tonic-gate * approximation of how this fs could be reproduced with this command.
21627c478bd9Sstevel@tonic-gate */
21637c478bd9Sstevel@tonic-gate static
21647c478bd9Sstevel@tonic-gate int
open_and_examine(char * dn,bpb_t * wbpb)21657c478bd9Sstevel@tonic-gate open_and_examine(char *dn, bpb_t *wbpb)
21667c478bd9Sstevel@tonic-gate {
21677c478bd9Sstevel@tonic-gate struct stat di;
21687c478bd9Sstevel@tonic-gate off64_t ignored;
21697c478bd9Sstevel@tonic-gate char *actualdisk = NULL;
21707c478bd9Sstevel@tonic-gate char *suffix = NULL;
21717c478bd9Sstevel@tonic-gate int fd;
217265908c77Syu, larry liu - Sun Microsystems - Beijing China struct dk_minfo dkminfo;
21737c478bd9Sstevel@tonic-gate
21747c478bd9Sstevel@tonic-gate if (Verbose)
21757c478bd9Sstevel@tonic-gate (void) printf(gettext("Opening destination device/file.\n"));
21767c478bd9Sstevel@tonic-gate
21777c478bd9Sstevel@tonic-gate actualdisk = stat_actual_disk(dn, &di, &suffix);
21787c478bd9Sstevel@tonic-gate
21797c478bd9Sstevel@tonic-gate /*
21807c478bd9Sstevel@tonic-gate * Destination exists, now find more about it.
21817c478bd9Sstevel@tonic-gate */
21827c478bd9Sstevel@tonic-gate if (!(S_ISCHR(di.st_mode))) {
21837c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
21847c478bd9Sstevel@tonic-gate gettext("\n%s: device name must be a "
2185f127cb91Sfrankho "character special device.\n"), actualdisk);
21867c478bd9Sstevel@tonic-gate exit(2);
21872d700530Sartem } else if ((fd = open(actualdisk, O_RDWR)) < 0) {
21887c478bd9Sstevel@tonic-gate perror(actualdisk);
21897c478bd9Sstevel@tonic-gate exit(2);
21907c478bd9Sstevel@tonic-gate }
21917c478bd9Sstevel@tonic-gate
219265908c77Syu, larry liu - Sun Microsystems - Beijing China /*
219365908c77Syu, larry liu - Sun Microsystems - Beijing China * Check the media sector size
219465908c77Syu, larry liu - Sun Microsystems - Beijing China */
219565908c77Syu, larry liu - Sun Microsystems - Beijing China if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) {
219665908c77Syu, larry liu - Sun Microsystems - Beijing China if (dkminfo.dki_lbsize != 0 &&
219765908c77Syu, larry liu - Sun Microsystems - Beijing China ISP2(dkminfo.dki_lbsize / DEV_BSIZE) &&
219865908c77Syu, larry liu - Sun Microsystems - Beijing China dkminfo.dki_lbsize != DEV_BSIZE) {
219965908c77Syu, larry liu - Sun Microsystems - Beijing China (void) fprintf(stderr,
220065908c77Syu, larry liu - Sun Microsystems - Beijing China gettext("The device sector size %u is not "
220165908c77Syu, larry liu - Sun Microsystems - Beijing China "supported by pcfs!\n"), dkminfo.dki_lbsize);
220265908c77Syu, larry liu - Sun Microsystems - Beijing China (void) close(fd);
220365908c77Syu, larry liu - Sun Microsystems - Beijing China exit(1);
220465908c77Syu, larry liu - Sun Microsystems - Beijing China }
220565908c77Syu, larry liu - Sun Microsystems - Beijing China }
220665908c77Syu, larry liu - Sun Microsystems - Beijing China
22077c478bd9Sstevel@tonic-gate /*
22087c478bd9Sstevel@tonic-gate * Find appropriate partition if we were requested to do so.
22097c478bd9Sstevel@tonic-gate */
22107c478bd9Sstevel@tonic-gate if (suffix && !(seek_partn(fd, suffix, wbpb, &ignored))) {
22117c478bd9Sstevel@tonic-gate (void) close(fd);
22127c478bd9Sstevel@tonic-gate exit(2);
22137c478bd9Sstevel@tonic-gate }
22147c478bd9Sstevel@tonic-gate
22157c478bd9Sstevel@tonic-gate read_existing_bpb(fd, wbpb);
22167c478bd9Sstevel@tonic-gate print_reproducing_command(fd, actualdisk, suffix, wbpb);
22177c478bd9Sstevel@tonic-gate
22187c478bd9Sstevel@tonic-gate return (fd);
22197c478bd9Sstevel@tonic-gate }
22207c478bd9Sstevel@tonic-gate
2221*5b5a71c4SToomas Soome /*
2222*5b5a71c4SToomas Soome * getdiskinfo
2223*5b5a71c4SToomas Soome *
2224*5b5a71c4SToomas Soome * Extracts information about disk path in dn. We need to return both a
2225*5b5a71c4SToomas Soome * file descriptor and the device's suffix.
2226*5b5a71c4SToomas Soome * Secondarily, we need to detect the FAT type and size when dealing with
2227*5b5a71c4SToomas Soome * GPT partitions.
2228*5b5a71c4SToomas Soome */
2229*5b5a71c4SToomas Soome static int
getdiskinfo(char * dn,char ** suffix)2230*5b5a71c4SToomas Soome getdiskinfo(char *dn, char **suffix)
2231*5b5a71c4SToomas Soome {
2232*5b5a71c4SToomas Soome struct dk_minfo dkminfo;
2233*5b5a71c4SToomas Soome struct stat di;
2234*5b5a71c4SToomas Soome int rv, fd, reserved;
2235*5b5a71c4SToomas Soome char *actualdisk = NULL;
2236*5b5a71c4SToomas Soome dk_gpt_t *gpt = NULL;
2237*5b5a71c4SToomas Soome
2238*5b5a71c4SToomas Soome actualdisk = stat_actual_disk(dn, &di, suffix);
2239*5b5a71c4SToomas Soome
2240*5b5a71c4SToomas Soome /*
2241*5b5a71c4SToomas Soome * Destination exists, now find more about it.
2242*5b5a71c4SToomas Soome */
2243*5b5a71c4SToomas Soome if (!(S_ISCHR(di.st_mode))) {
2244*5b5a71c4SToomas Soome (void) fprintf(stderr,
2245*5b5a71c4SToomas Soome gettext("Device name must indicate a "
2246*5b5a71c4SToomas Soome "character special device: %s\n"), actualdisk);
2247*5b5a71c4SToomas Soome exit(2);
2248*5b5a71c4SToomas Soome } else if ((fd = open(actualdisk, O_RDWR)) < 0) {
2249*5b5a71c4SToomas Soome perror(actualdisk);
2250*5b5a71c4SToomas Soome exit(2);
2251*5b5a71c4SToomas Soome }
2252*5b5a71c4SToomas Soome
2253*5b5a71c4SToomas Soome /*
2254*5b5a71c4SToomas Soome * Check the media sector size
2255*5b5a71c4SToomas Soome */
2256*5b5a71c4SToomas Soome if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) {
2257*5b5a71c4SToomas Soome if (dkminfo.dki_lbsize != 0 &&
2258*5b5a71c4SToomas Soome ISP2(dkminfo.dki_lbsize / DEV_BSIZE) &&
2259*5b5a71c4SToomas Soome dkminfo.dki_lbsize != DEV_BSIZE) {
2260*5b5a71c4SToomas Soome (void) fprintf(stderr,
2261*5b5a71c4SToomas Soome gettext("The device sector size %u is not "
2262*5b5a71c4SToomas Soome "supported by pcfs!\n"), dkminfo.dki_lbsize);
2263*5b5a71c4SToomas Soome (void) close(fd);
2264*5b5a71c4SToomas Soome exit(2);
2265*5b5a71c4SToomas Soome }
2266*5b5a71c4SToomas Soome }
2267*5b5a71c4SToomas Soome
2268*5b5a71c4SToomas Soome rv = efi_alloc_and_read(fd, &gpt);
2269*5b5a71c4SToomas Soome /*
2270*5b5a71c4SToomas Soome * We should see only VT_EINVAL, VT_EIO and VT_ERROR.
2271*5b5a71c4SToomas Soome * VT_EINVAL is for the case there is no GPT label.
2272*5b5a71c4SToomas Soome * VT_ERROR will happen if device does no support the ioctl, so
2273*5b5a71c4SToomas Soome * we will exit only in case of VT_EIO and unknown value of rv.
2274*5b5a71c4SToomas Soome */
2275*5b5a71c4SToomas Soome if (rv < 0 && rv != VT_EINVAL && rv != VT_ERROR) {
2276*5b5a71c4SToomas Soome switch (rv) {
2277*5b5a71c4SToomas Soome case VT_EIO:
2278*5b5a71c4SToomas Soome (void) fprintf(stderr,
2279*5b5a71c4SToomas Soome gettext("IO Error reading EFI label\n"));
2280*5b5a71c4SToomas Soome break;
2281*5b5a71c4SToomas Soome default:
2282*5b5a71c4SToomas Soome (void) fprintf(stderr,
2283*5b5a71c4SToomas Soome gettext("Unknown Error %d reading EFI label\n"),
2284*5b5a71c4SToomas Soome rv);
2285*5b5a71c4SToomas Soome break;
2286*5b5a71c4SToomas Soome }
2287*5b5a71c4SToomas Soome (void) close(fd);
2288*5b5a71c4SToomas Soome exit(2);
2289*5b5a71c4SToomas Soome }
2290*5b5a71c4SToomas Soome if (rv >= 0) {
2291*5b5a71c4SToomas Soome DontUseFdisk = 1;
2292*5b5a71c4SToomas Soome if (*suffix != NULL) {
2293*5b5a71c4SToomas Soome (void) fprintf(stderr,
2294*5b5a71c4SToomas Soome gettext("Can not use drive specifier \"%s\" with "
2295*5b5a71c4SToomas Soome "GPT partitioning.\n"), *suffix);
2296*5b5a71c4SToomas Soome efi_free(gpt);
2297*5b5a71c4SToomas Soome (void) close(fd);
2298*5b5a71c4SToomas Soome exit(2);
2299*5b5a71c4SToomas Soome }
2300*5b5a71c4SToomas Soome /* Can not use whole disk, 7 is GPT minor node "wd" */
2301*5b5a71c4SToomas Soome if (rv == 7) {
2302*5b5a71c4SToomas Soome (void) fprintf(stderr,
2303*5b5a71c4SToomas Soome gettext("Device name must indicate a "
2304*5b5a71c4SToomas Soome "partition: %s\n"), actualdisk);
2305*5b5a71c4SToomas Soome efi_free(gpt);
2306*5b5a71c4SToomas Soome (void) close(fd);
2307*5b5a71c4SToomas Soome exit(2);
2308*5b5a71c4SToomas Soome }
2309*5b5a71c4SToomas Soome
2310*5b5a71c4SToomas Soome if (GetSize == 1) {
2311*5b5a71c4SToomas Soome TotSize = gpt->efi_parts[rv].p_size;
2312*5b5a71c4SToomas Soome GetSize = 0;
2313*5b5a71c4SToomas Soome }
2314*5b5a71c4SToomas Soome
2315*5b5a71c4SToomas Soome if (GetBPF == 1) {
2316*5b5a71c4SToomas Soome if (GetResrvd == 1) {
2317*5b5a71c4SToomas Soome /* FAT32 has 32 reserved sectors */
2318*5b5a71c4SToomas Soome reserved = 32;
2319*5b5a71c4SToomas Soome } else {
2320*5b5a71c4SToomas Soome reserved = Resrvd;
2321*5b5a71c4SToomas Soome }
2322*5b5a71c4SToomas Soome /*
2323*5b5a71c4SToomas Soome * The type of FAT is determined by the size of
2324*5b5a71c4SToomas Soome * the partition - reserved sectors.
2325*5b5a71c4SToomas Soome * The calculation is based on logic used in
2326*5b5a71c4SToomas Soome * compute_cluster_size() and therefore we will not
2327*5b5a71c4SToomas Soome * get into error situation when
2328*5b5a71c4SToomas Soome * compute_cluster_size() will be called.
2329*5b5a71c4SToomas Soome */
2330*5b5a71c4SToomas Soome if (TotSize - reserved < FAT16_MAX_CLUSTERS) {
2331*5b5a71c4SToomas Soome if (GetResrvd == 1)
2332*5b5a71c4SToomas Soome reserved = 1;
2333*5b5a71c4SToomas Soome
2334*5b5a71c4SToomas Soome if (TotSize - reserved < FAT12_MAX_CLUSTERS) {
2335*5b5a71c4SToomas Soome int spc;
2336*5b5a71c4SToomas Soome MakeFAT32 = 0;
2337*5b5a71c4SToomas Soome Fatentsize = 12;
2338*5b5a71c4SToomas Soome /*
2339*5b5a71c4SToomas Soome * compute sectors per cluster
2340*5b5a71c4SToomas Soome * for fat12
2341*5b5a71c4SToomas Soome */
2342*5b5a71c4SToomas Soome for (spc = 1; spc <= 64;
2343*5b5a71c4SToomas Soome spc = spc * 2) {
2344*5b5a71c4SToomas Soome if (TotSize - reserved <
2345*5b5a71c4SToomas Soome spc * FAT12_MAX_CLUSTERS)
2346*5b5a71c4SToomas Soome break;
2347*5b5a71c4SToomas Soome }
2348*5b5a71c4SToomas Soome if (GetSPC == 1) {
2349*5b5a71c4SToomas Soome GetSPC = 0;
2350*5b5a71c4SToomas Soome SecPerClust = spc;
2351*5b5a71c4SToomas Soome }
2352*5b5a71c4SToomas Soome } else {
2353*5b5a71c4SToomas Soome MakeFAT32 = 0;
2354*5b5a71c4SToomas Soome Fatentsize = 16;
2355*5b5a71c4SToomas Soome }
2356*5b5a71c4SToomas Soome } else {
2357*5b5a71c4SToomas Soome MakeFAT32 = 1;
2358*5b5a71c4SToomas Soome Fatentsize = 32;
2359*5b5a71c4SToomas Soome }
2360*5b5a71c4SToomas Soome }
2361*5b5a71c4SToomas Soome efi_free(gpt);
2362*5b5a71c4SToomas Soome }
2363*5b5a71c4SToomas Soome return (fd);
2364*5b5a71c4SToomas Soome }
2365*5b5a71c4SToomas Soome
23667c478bd9Sstevel@tonic-gate /*
23677c478bd9Sstevel@tonic-gate * open_and_seek
23687c478bd9Sstevel@tonic-gate *
23697c478bd9Sstevel@tonic-gate * Open the requested 'dev_name'. Seek to point where
23707c478bd9Sstevel@tonic-gate * we'll write boot sectors, etc., based on any ':partition'
23717c478bd9Sstevel@tonic-gate * attachments to the dev_name.
23727c478bd9Sstevel@tonic-gate *
23737c478bd9Sstevel@tonic-gate * By the time we are finished here, the entire BPB will be
23747c478bd9Sstevel@tonic-gate * filled in, excepting the volume label.
23757c478bd9Sstevel@tonic-gate */
23767c478bd9Sstevel@tonic-gate static
23777c478bd9Sstevel@tonic-gate int
open_and_seek(char * dn,bpb_t * wbpb,off64_t * seekto)23787c478bd9Sstevel@tonic-gate open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto)
23797c478bd9Sstevel@tonic-gate {
23807c478bd9Sstevel@tonic-gate struct fd_char fdchar;
2381f69e9be8Sps struct dk_geom dg;
23827c478bd9Sstevel@tonic-gate char *actualdisk = NULL;
23837c478bd9Sstevel@tonic-gate char *suffix = NULL;
23847c478bd9Sstevel@tonic-gate int fd;
23857c478bd9Sstevel@tonic-gate
23867c478bd9Sstevel@tonic-gate if (Verbose)
23877c478bd9Sstevel@tonic-gate (void) printf(gettext("Opening destination device/file.\n"));
23887c478bd9Sstevel@tonic-gate
23897c478bd9Sstevel@tonic-gate /*
23907c478bd9Sstevel@tonic-gate * We hold these truths to be self evident, all BPBs we create
23917c478bd9Sstevel@tonic-gate * will have these values in these fields.
23927c478bd9Sstevel@tonic-gate */
23937c478bd9Sstevel@tonic-gate wbpb->bpb.num_fats = 2;
23947c478bd9Sstevel@tonic-gate wbpb->bpb.bytes_sector = BPSEC;
23957c478bd9Sstevel@tonic-gate
23967c478bd9Sstevel@tonic-gate /*
23977c478bd9Sstevel@tonic-gate * Assign or use supplied numbers for hidden and
23987c478bd9Sstevel@tonic-gate * reserved sectors in the file system.
23997c478bd9Sstevel@tonic-gate */
24007c478bd9Sstevel@tonic-gate if (GetResrvd)
24017c478bd9Sstevel@tonic-gate if (MakeFAT32)
24027c478bd9Sstevel@tonic-gate wbpb->bpb.resv_sectors = 32;
24037c478bd9Sstevel@tonic-gate else
24047c478bd9Sstevel@tonic-gate wbpb->bpb.resv_sectors = 1;
24057c478bd9Sstevel@tonic-gate else
24067c478bd9Sstevel@tonic-gate wbpb->bpb.resv_sectors = Resrvd;
24077c478bd9Sstevel@tonic-gate
24087c478bd9Sstevel@tonic-gate wbpb->ebpb.ext_signature = 0x29; /* Magic number for modern format */
24097c478bd9Sstevel@tonic-gate wbpb->ebpb.volume_id = 0;
24107c478bd9Sstevel@tonic-gate
24117c478bd9Sstevel@tonic-gate if (MakeFAT32)
24127c478bd9Sstevel@tonic-gate fill_fat32_bpb(wbpb);
24137c478bd9Sstevel@tonic-gate
24147c478bd9Sstevel@tonic-gate /*
24157c478bd9Sstevel@tonic-gate * If all output goes to a simple file, call a routine to setup
24167c478bd9Sstevel@tonic-gate * that scenario. Otherwise, try to find the device.
24177c478bd9Sstevel@tonic-gate */
24187c478bd9Sstevel@tonic-gate if (Outputtofile)
2419*5b5a71c4SToomas Soome return (prepare_image_file(dn, wbpb));
24207c478bd9Sstevel@tonic-gate
2421*5b5a71c4SToomas Soome /* Collect info about device */
2422*5b5a71c4SToomas Soome fd = getdiskinfo(dn, &suffix);
24237c478bd9Sstevel@tonic-gate
24247c478bd9Sstevel@tonic-gate /*
24257c478bd9Sstevel@tonic-gate * Sanity check. If we've been provided a partition-specifying
24267c478bd9Sstevel@tonic-gate * suffix, we shouldn't also have been told to ignore the
24277c478bd9Sstevel@tonic-gate * fdisk table.
24287c478bd9Sstevel@tonic-gate */
24297c478bd9Sstevel@tonic-gate if (DontUseFdisk && suffix) {
24307c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
24317c478bd9Sstevel@tonic-gate gettext("Using 'nofdisk' option precludes "
2432f127cb91Sfrankho "appending logical drive\nspecifier "
2433f127cb91Sfrankho "to the device name.\n"));
2434*5b5a71c4SToomas Soome goto err_out;
243565908c77Syu, larry liu - Sun Microsystems - Beijing China }
243665908c77Syu, larry liu - Sun Microsystems - Beijing China
24377c478bd9Sstevel@tonic-gate /*
24387c478bd9Sstevel@tonic-gate * Find appropriate partition if we were requested to do so.
24397c478bd9Sstevel@tonic-gate */
2440*5b5a71c4SToomas Soome if (suffix && !(seek_partn(fd, suffix, wbpb, seekto)))
2441*5b5a71c4SToomas Soome goto err_out;
24427c478bd9Sstevel@tonic-gate
24437c478bd9Sstevel@tonic-gate if (!suffix) {
24447c478bd9Sstevel@tonic-gate /*
24457c478bd9Sstevel@tonic-gate * We have one of two possibilities. Chances are we have
24467c478bd9Sstevel@tonic-gate * a floppy drive. But the user may be trying to format
24477c478bd9Sstevel@tonic-gate * some weird drive that we don't know about and is supplying
24487c478bd9Sstevel@tonic-gate * all the important values. In that case, they should have set
24497c478bd9Sstevel@tonic-gate * the 'nofdisk' flag.
24507c478bd9Sstevel@tonic-gate *
24517c478bd9Sstevel@tonic-gate * If 'nofdisk' isn't set, do a floppy-specific ioctl to
24527c478bd9Sstevel@tonic-gate * get the remainder of our info. If the ioctl fails, we have
24537c478bd9Sstevel@tonic-gate * a good idea that they aren't really on a floppy. In that
24547c478bd9Sstevel@tonic-gate * case, they should have given us a partition specifier.
24557c478bd9Sstevel@tonic-gate */
24567c478bd9Sstevel@tonic-gate if (DontUseFdisk) {
2457*5b5a71c4SToomas Soome if (!(seek_nofdisk(fd, wbpb, seekto)))
2458*5b5a71c4SToomas Soome goto err_out;
2459*5b5a71c4SToomas Soome
24607c478bd9Sstevel@tonic-gate find_fixed_details(fd, wbpb);
24617c478bd9Sstevel@tonic-gate } else if (ioctl(fd, FDIOGCHAR, &fdchar) == -1) {
2462f69e9be8Sps /*
2463f69e9be8Sps * It is possible that we are trying to use floppy
2464f69e9be8Sps * specific FDIOGCHAR ioctl on USB floppy. Since sd
2465f69e9be8Sps * driver, by which USB floppy is handled, doesn't
2466f69e9be8Sps * support it, we can try to use disk DKIOCGGEOM ioctl
2467f69e9be8Sps * to retrieve data we need. sd driver itself
2468f69e9be8Sps * determines floppy disk by number of blocks
2469f69e9be8Sps * (<=0x1000), then it sets geometry to 80 cylinders,
2470f69e9be8Sps * 2 heads.
2471f69e9be8Sps *
2472f69e9be8Sps * Note that DKIOCGGEOM cannot supply us with type
2473f69e9be8Sps * of media (e.g. 3.5" or 5.25"). We will set it to
2474f69e9be8Sps * 3 (3.5") which is most probable value.
2475f69e9be8Sps */
24767c478bd9Sstevel@tonic-gate if (errno == ENOTTY) {
2477f69e9be8Sps if (ioctl(fd, DKIOCGGEOM, &dg) != -1 &&
2478f69e9be8Sps dg.dkg_ncyl == 80 && dg.dkg_nhead == 2) {
2479f69e9be8Sps fdchar.fdc_ncyl = dg.dkg_ncyl;
2480f69e9be8Sps fdchar.fdc_medium = 3;
2481f69e9be8Sps fdchar.fdc_secptrack = dg.dkg_nsect;
2482f69e9be8Sps fdchar.fdc_nhead = dg.dkg_nhead;
2483f69e9be8Sps lookup_floppy(&fdchar, wbpb);
2484f69e9be8Sps } else {
2485f69e9be8Sps partn_lecture(actualdisk);
2486*5b5a71c4SToomas Soome goto err_out;
2487f69e9be8Sps }
24887c478bd9Sstevel@tonic-gate }
24897c478bd9Sstevel@tonic-gate } else {
24907c478bd9Sstevel@tonic-gate #ifdef sparc
24917c478bd9Sstevel@tonic-gate fdchar.fdc_medium = 3;
24927c478bd9Sstevel@tonic-gate #endif
24937c478bd9Sstevel@tonic-gate lookup_floppy(&fdchar, wbpb);
24947c478bd9Sstevel@tonic-gate }
24957c478bd9Sstevel@tonic-gate } else {
24967c478bd9Sstevel@tonic-gate find_fixed_details(fd, wbpb);
24977c478bd9Sstevel@tonic-gate }
24987c478bd9Sstevel@tonic-gate
24997c478bd9Sstevel@tonic-gate return (fd);
2500*5b5a71c4SToomas Soome
2501*5b5a71c4SToomas Soome err_out:
2502*5b5a71c4SToomas Soome (void) close(fd);
2503*5b5a71c4SToomas Soome exit(2);
25047c478bd9Sstevel@tonic-gate }
25057c478bd9Sstevel@tonic-gate
25067c478bd9Sstevel@tonic-gate /*
25077c478bd9Sstevel@tonic-gate * The following is a copy of MS-DOS 4.0 boot block.
25087c478bd9Sstevel@tonic-gate * It consists of the BIOS parameter block, and a disk
25097c478bd9Sstevel@tonic-gate * bootstrap program.
25107c478bd9Sstevel@tonic-gate *
25117c478bd9Sstevel@tonic-gate * The BIOS parameter block contains the right values
25127c478bd9Sstevel@tonic-gate * for the 3.5" high-density 1.44MB floppy format.
25137c478bd9Sstevel@tonic-gate *
25147c478bd9Sstevel@tonic-gate * This will be our default boot sector, if the user
25157c478bd9Sstevel@tonic-gate * didn't point us at a different one.
25167c478bd9Sstevel@tonic-gate *
25177c478bd9Sstevel@tonic-gate */
25187c478bd9Sstevel@tonic-gate static
25197c478bd9Sstevel@tonic-gate uchar_t DefBootSec[512] = {
25207c478bd9Sstevel@tonic-gate 0xeb, 0x3c, 0x90, /* 8086 short jump + displacement + NOP */
25217c478bd9Sstevel@tonic-gate 'M', 'S', 'D', 'O', 'S', '4', '.', '0', /* OEM name & version */
25227c478bd9Sstevel@tonic-gate 0x00, 0x02, 0x01, 0x01, 0x00,
25237c478bd9Sstevel@tonic-gate 0x02, 0xe0, 0x00, 0x40, 0x0b,
25247c478bd9Sstevel@tonic-gate 0xf0, 0x09, 0x00, 0x12, 0x00,
25257c478bd9Sstevel@tonic-gate 0x02, 0x00,
25267c478bd9Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00,
25277c478bd9Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00,
25287c478bd9Sstevel@tonic-gate 0x00, 0x00,
25297c478bd9Sstevel@tonic-gate 0x29, 0x00, 0x00, 0x00, 0x00,
25307c478bd9Sstevel@tonic-gate 'N', 'O', 'N', 'A', 'M', 'E', ' ', ' ', ' ', ' ', ' ',
25317c478bd9Sstevel@tonic-gate 'F', 'A', 'T', '1', '2', ' ', ' ', ' ',
25327c478bd9Sstevel@tonic-gate 0xfa, 0x33,
25337c478bd9Sstevel@tonic-gate 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x16, 0x07,
25347c478bd9Sstevel@tonic-gate 0xbb, 0x78, 0x00, 0x36, 0xc5, 0x37, 0x1e, 0x56,
25357c478bd9Sstevel@tonic-gate 0x16, 0x53, 0xbf, 0x3e, 0x7c, 0xb9, 0x0b, 0x00,
25367c478bd9Sstevel@tonic-gate 0xfc, 0xf3, 0xa4, 0x06, 0x1f, 0xc6, 0x45, 0xfe,
25377c478bd9Sstevel@tonic-gate 0x0f, 0x8b, 0x0e, 0x18, 0x7c, 0x88, 0x4d, 0xf9,
25387c478bd9Sstevel@tonic-gate 0x89, 0x47, 0x02, 0xc7, 0x07, 0x3e, 0x7c, 0xfb,
25397c478bd9Sstevel@tonic-gate 0xcd, 0x13, 0x72, 0x7c, 0x33, 0xc0, 0x39, 0x06,
25407c478bd9Sstevel@tonic-gate 0x13, 0x7c, 0x74, 0x08, 0x8b, 0x0e, 0x13, 0x7c,
25417c478bd9Sstevel@tonic-gate 0x89, 0x0e, 0x20, 0x7c, 0xa0, 0x10, 0x7c, 0xf7,
25427c478bd9Sstevel@tonic-gate 0x26, 0x16, 0x7c, 0x03, 0x06, 0x1c, 0x7c, 0x13,
25437c478bd9Sstevel@tonic-gate 0x16, 0x1e, 0x7c, 0x03, 0x06, 0x0e, 0x7c, 0x83,
25447c478bd9Sstevel@tonic-gate 0xd2, 0x00, 0xa3, 0x50, 0x7c, 0x89, 0x16, 0x52,
25457c478bd9Sstevel@tonic-gate 0x7c, 0xa3, 0x49, 0x7c, 0x89, 0x16, 0x4b, 0x7c,
25467c478bd9Sstevel@tonic-gate 0xb8, 0x20, 0x00, 0xf7, 0x26, 0x11, 0x7c, 0x8b,
25477c478bd9Sstevel@tonic-gate 0x1e, 0x0b, 0x7c, 0x03, 0xc3, 0x48, 0xf7, 0xf3,
25487c478bd9Sstevel@tonic-gate 0x01, 0x06, 0x49, 0x7c, 0x83, 0x16, 0x4b, 0x7c,
25497c478bd9Sstevel@tonic-gate 0x00, 0xbb, 0x00, 0x05, 0x8b, 0x16, 0x52, 0x7c,
25507c478bd9Sstevel@tonic-gate 0xa1, 0x50, 0x7c, 0xe8, 0x87, 0x00, 0x72, 0x20,
25517c478bd9Sstevel@tonic-gate 0xb0, 0x01, 0xe8, 0xa1, 0x00, 0x72, 0x19, 0x8b,
25527c478bd9Sstevel@tonic-gate 0xfb, 0xb9, 0x0b, 0x00, 0xbe, 0xdb, 0x7d, 0xf3,
25537c478bd9Sstevel@tonic-gate 0xa6, 0x75, 0x0d, 0x8d, 0x7f, 0x20, 0xbe, 0xe6,
25547c478bd9Sstevel@tonic-gate 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x18,
25557c478bd9Sstevel@tonic-gate 0xbe, 0x93, 0x7d, 0xe8, 0x51, 0x00, 0x32, 0xe4,
25567c478bd9Sstevel@tonic-gate 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x04, 0x8f, 0x44,
25577c478bd9Sstevel@tonic-gate 0x02, 0xcd, 0x19, 0x58, 0x58, 0x58, 0xeb, 0xe8,
25587c478bd9Sstevel@tonic-gate 0xbb, 0x00, 0x07, 0xb9, 0x03, 0x00, 0xa1, 0x49,
25597c478bd9Sstevel@tonic-gate 0x7c, 0x8b, 0x16, 0x4b, 0x7c, 0x50, 0x52, 0x51,
25607c478bd9Sstevel@tonic-gate 0xe8, 0x3a, 0x00, 0x72, 0xe6, 0xb0, 0x01, 0xe8,
25617c478bd9Sstevel@tonic-gate 0x54, 0x00, 0x59, 0x5a, 0x58, 0x72, 0xc9, 0x05,
25627c478bd9Sstevel@tonic-gate 0x01, 0x00, 0x83, 0xd2, 0x00, 0x03, 0x1e, 0x0b,
25637c478bd9Sstevel@tonic-gate 0x7c, 0xe2, 0xe2, 0x8a, 0x2e, 0x15, 0x7c, 0x8a,
25647c478bd9Sstevel@tonic-gate 0x16, 0x24, 0x7c, 0x8b, 0x1e, 0x49, 0x7c, 0xa1,
25657c478bd9Sstevel@tonic-gate 0x4b, 0x7c, 0xea, 0x00, 0x00, 0x70, 0x00, 0xac,
25667c478bd9Sstevel@tonic-gate 0x0a, 0xc0, 0x74, 0x29, 0xb4, 0x0e, 0xbb, 0x07,
25677c478bd9Sstevel@tonic-gate 0x00, 0xcd, 0x10, 0xeb, 0xf2, 0x3b, 0x16, 0x18,
25687c478bd9Sstevel@tonic-gate 0x7c, 0x73, 0x19, 0xf7, 0x36, 0x18, 0x7c, 0xfe,
25697c478bd9Sstevel@tonic-gate 0xc2, 0x88, 0x16, 0x4f, 0x7c, 0x33, 0xd2, 0xf7,
25707c478bd9Sstevel@tonic-gate 0x36, 0x1a, 0x7c, 0x88, 0x16, 0x25, 0x7c, 0xa3,
25717c478bd9Sstevel@tonic-gate 0x4d, 0x7c, 0xf8, 0xc3, 0xf9, 0xc3, 0xb4, 0x02,
25727c478bd9Sstevel@tonic-gate 0x8b, 0x16, 0x4d, 0x7c, 0xb1, 0x06, 0xd2, 0xe6,
25737c478bd9Sstevel@tonic-gate 0x0a, 0x36, 0x4f, 0x7c, 0x8b, 0xca, 0x86, 0xe9,
25747c478bd9Sstevel@tonic-gate 0x8a, 0x16, 0x24, 0x7c, 0x8a, 0x36, 0x25, 0x7c,
25757c478bd9Sstevel@tonic-gate 0xcd, 0x13, 0xc3, 0x0d, 0x0a, 0x4e, 0x6f, 0x6e,
25767c478bd9Sstevel@tonic-gate 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20,
25777c478bd9Sstevel@tonic-gate 0x64, 0x69, 0x73, 0x6b, 0x20, 0x6f, 0x72, 0x20,
25787c478bd9Sstevel@tonic-gate 0x64, 0x69, 0x73, 0x6b, 0x20, 0x65, 0x72, 0x72,
25797c478bd9Sstevel@tonic-gate 0x6f, 0x72, 0x0d, 0x0a, 0x52, 0x65, 0x70, 0x6c,
25807c478bd9Sstevel@tonic-gate 0x61, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
25817c478bd9Sstevel@tonic-gate 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e,
25827c478bd9Sstevel@tonic-gate 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x77, 0x68,
25837c478bd9Sstevel@tonic-gate 0x65, 0x6e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79,
25847c478bd9Sstevel@tonic-gate 0x0d, 0x0a, 0x00, 0x49, 0x4f, 0x20, 0x20, 0x20,
25857c478bd9Sstevel@tonic-gate 0x20, 0x20, 0x20, 0x53, 0x59, 0x53, 0x4d, 0x53,
25867c478bd9Sstevel@tonic-gate 0x44, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x53, 0x59,
25877c478bd9Sstevel@tonic-gate 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25887c478bd9Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
25897c478bd9Sstevel@tonic-gate };
25907c478bd9Sstevel@tonic-gate
25917c478bd9Sstevel@tonic-gate /*
25927c478bd9Sstevel@tonic-gate * verify_bootblkfile
25937c478bd9Sstevel@tonic-gate *
25947c478bd9Sstevel@tonic-gate * We were provided with the name of a file containing the bootblk
25957c478bd9Sstevel@tonic-gate * to install. Verify it has a valid boot sector as best we can. Any
25967c478bd9Sstevel@tonic-gate * errors and we return a bad file descriptor. Otherwise we fill up the
25977c478bd9Sstevel@tonic-gate * provided buffer with the boot sector, return the file
25987c478bd9Sstevel@tonic-gate * descriptor for later use and leave the file pointer just
25997c478bd9Sstevel@tonic-gate * past the boot sector part of the boot block file.
26007c478bd9Sstevel@tonic-gate */
26017c478bd9Sstevel@tonic-gate static
26027c478bd9Sstevel@tonic-gate int
verify_bootblkfile(char * fn,boot_sector_t * bs,ulong_t * blkfilesize)26037c478bd9Sstevel@tonic-gate verify_bootblkfile(char *fn, boot_sector_t *bs, ulong_t *blkfilesize)
26047c478bd9Sstevel@tonic-gate {
26057c478bd9Sstevel@tonic-gate struct stat fi;
26067c478bd9Sstevel@tonic-gate int bsfd = -1;
26077c478bd9Sstevel@tonic-gate
26087c478bd9Sstevel@tonic-gate if (stat(fn, &fi)) {
26097c478bd9Sstevel@tonic-gate perror(fn);
26107c478bd9Sstevel@tonic-gate } else if (fi.st_size < BPSEC) {
26117c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
26127c478bd9Sstevel@tonic-gate gettext("%s: Too short to be a boot sector.\n"), fn);
26137c478bd9Sstevel@tonic-gate } else if ((bsfd = open(fn, O_RDONLY)) < 0) {
26147c478bd9Sstevel@tonic-gate perror(fn);
26157c478bd9Sstevel@tonic-gate } else if (read(bsfd, bs->buf, BPSEC) < BPSEC) {
26167c478bd9Sstevel@tonic-gate (void) close(bsfd);
26177c478bd9Sstevel@tonic-gate bsfd = -1;
26187c478bd9Sstevel@tonic-gate perror(gettext("Boot block read"));
26197c478bd9Sstevel@tonic-gate } else {
2620f127cb91Sfrankho if ((bs->bs.bs_signature[0] != (BOOTSECSIG & 0xFF) &&
2621f127cb91Sfrankho bs->bs.bs_signature[1] != ((BOOTSECSIG >> 8) & 0xFF)) ||
26227c478bd9Sstevel@tonic-gate #ifdef i386
2623f127cb91Sfrankho (bs->bs.bs_front.bs_jump_code[0] != OPCODE1 &&
2624f127cb91Sfrankho bs->bs.bs_front.bs_jump_code[0] != OPCODE2)
26257c478bd9Sstevel@tonic-gate #else
2626f127cb91Sfrankho (bs->bs.bs_jump_code[0] != OPCODE1 &&
2627f127cb91Sfrankho bs->bs.bs_jump_code[0] != OPCODE2)
26287c478bd9Sstevel@tonic-gate #endif
2629a9fcfb29Sfrankho /* CSTYLED */
2630f127cb91Sfrankho ) {
26317c478bd9Sstevel@tonic-gate (void) close(bsfd);
26327c478bd9Sstevel@tonic-gate bsfd = -1;
26337c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
26347c478bd9Sstevel@tonic-gate gettext("Boot block (%s) bogus.\n"), fn);
26357c478bd9Sstevel@tonic-gate }
26367c478bd9Sstevel@tonic-gate *blkfilesize = fi.st_size;
26377c478bd9Sstevel@tonic-gate }
26387c478bd9Sstevel@tonic-gate return (bsfd);
26397c478bd9Sstevel@tonic-gate }
26407c478bd9Sstevel@tonic-gate
26417c478bd9Sstevel@tonic-gate /*
26427c478bd9Sstevel@tonic-gate * verify_firstfile
26437c478bd9Sstevel@tonic-gate *
26447c478bd9Sstevel@tonic-gate * We were provided with the name of a file to be the first file
26457c478bd9Sstevel@tonic-gate * installed on the disk. We just need to verify it exists and
26467c478bd9Sstevel@tonic-gate * find out how big it is. If it doesn't exist, we print a warning
26477c478bd9Sstevel@tonic-gate * message about how the file wasn't found. We don't exit fatally,
26487c478bd9Sstevel@tonic-gate * though, rather we return a size of 0 and the FAT will be built
26497c478bd9Sstevel@tonic-gate * without installing any first file. They can then presumably
26507c478bd9Sstevel@tonic-gate * install the correct first file by hand.
26517c478bd9Sstevel@tonic-gate */
26527c478bd9Sstevel@tonic-gate static
26537c478bd9Sstevel@tonic-gate int
verify_firstfile(char * fn,ulong_t * filesize)26547c478bd9Sstevel@tonic-gate verify_firstfile(char *fn, ulong_t *filesize)
26557c478bd9Sstevel@tonic-gate {
26567c478bd9Sstevel@tonic-gate struct stat fi;
26577c478bd9Sstevel@tonic-gate int fd = -1;
26587c478bd9Sstevel@tonic-gate
26597c478bd9Sstevel@tonic-gate *filesize = 0;
26607c478bd9Sstevel@tonic-gate if (stat(fn, &fi) || (fd = open(fn, O_RDONLY)) < 0) {
26617c478bd9Sstevel@tonic-gate perror(fn);
26627c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
26637c478bd9Sstevel@tonic-gate gettext("Could not access requested file. It will not\n"
2664f127cb91Sfrankho "be installed in the new file system.\n"));
26657c478bd9Sstevel@tonic-gate } else {
26667c478bd9Sstevel@tonic-gate *filesize = fi.st_size;
26677c478bd9Sstevel@tonic-gate }
26687c478bd9Sstevel@tonic-gate
26697c478bd9Sstevel@tonic-gate return (fd);
26707c478bd9Sstevel@tonic-gate }
26717c478bd9Sstevel@tonic-gate
26727c478bd9Sstevel@tonic-gate /*
26737c478bd9Sstevel@tonic-gate * label_volume
26747c478bd9Sstevel@tonic-gate *
26757c478bd9Sstevel@tonic-gate * Fill in BPB with volume label.
26767c478bd9Sstevel@tonic-gate */
26777c478bd9Sstevel@tonic-gate static
26787c478bd9Sstevel@tonic-gate void
label_volume(char * lbl,bpb_t * wbpb)26797c478bd9Sstevel@tonic-gate label_volume(char *lbl, bpb_t *wbpb)
26807c478bd9Sstevel@tonic-gate {
26817c478bd9Sstevel@tonic-gate int ll, i;
26827c478bd9Sstevel@tonic-gate
26837c478bd9Sstevel@tonic-gate /* Put a volume label into our BPB. */
26847c478bd9Sstevel@tonic-gate if (!lbl)
26857c478bd9Sstevel@tonic-gate lbl = DEFAULT_LABEL;
26867c478bd9Sstevel@tonic-gate
26877c478bd9Sstevel@tonic-gate ll = min(11, (int)strlen(lbl));
26887c478bd9Sstevel@tonic-gate for (i = 0; i < ll; i++) {
26897c478bd9Sstevel@tonic-gate wbpb->ebpb.volume_label[i] = toupper(lbl[i]);
26907c478bd9Sstevel@tonic-gate }
26917c478bd9Sstevel@tonic-gate for (; i < 11; i++) {
26927c478bd9Sstevel@tonic-gate wbpb->ebpb.volume_label[i] = ' ';
26937c478bd9Sstevel@tonic-gate }
26947c478bd9Sstevel@tonic-gate }
26957c478bd9Sstevel@tonic-gate
26967c478bd9Sstevel@tonic-gate static
26977c478bd9Sstevel@tonic-gate int
copy_bootblk(char * fn,boot_sector_t * bootsect,ulong_t * bootblksize)26987c478bd9Sstevel@tonic-gate copy_bootblk(char *fn, boot_sector_t *bootsect, ulong_t *bootblksize)
26997c478bd9Sstevel@tonic-gate {
27007c478bd9Sstevel@tonic-gate int bsfd = -1;
27017c478bd9Sstevel@tonic-gate
27027c478bd9Sstevel@tonic-gate if (Verbose && fn)
27037c478bd9Sstevel@tonic-gate (void) printf(gettext("Request to install boot "
27047c478bd9Sstevel@tonic-gate "block file %s.\n"), fn);
27057c478bd9Sstevel@tonic-gate else if (Verbose)
27067c478bd9Sstevel@tonic-gate (void) printf(gettext("Request to install DOS boot block.\n"));
27077c478bd9Sstevel@tonic-gate
27087c478bd9Sstevel@tonic-gate /*
27097c478bd9Sstevel@tonic-gate * If they want to install their own boot block, sanity check
27107c478bd9Sstevel@tonic-gate * that block.
27117c478bd9Sstevel@tonic-gate */
27127c478bd9Sstevel@tonic-gate if (fn) {
27137c478bd9Sstevel@tonic-gate bsfd = verify_bootblkfile(fn, bootsect, bootblksize);
27147c478bd9Sstevel@tonic-gate if (bsfd < 0) {
27157c478bd9Sstevel@tonic-gate exit(3);
27167c478bd9Sstevel@tonic-gate }
27177c478bd9Sstevel@tonic-gate *bootblksize = roundup(*bootblksize, BPSEC);
27187c478bd9Sstevel@tonic-gate } else {
27197c478bd9Sstevel@tonic-gate (void) memcpy(bootsect, DefBootSec, BPSEC);
27207c478bd9Sstevel@tonic-gate *bootblksize = BPSEC;
27217c478bd9Sstevel@tonic-gate }
27227c478bd9Sstevel@tonic-gate
27237c478bd9Sstevel@tonic-gate return (bsfd);
27247c478bd9Sstevel@tonic-gate }
27257c478bd9Sstevel@tonic-gate
27267c478bd9Sstevel@tonic-gate /*
27277c478bd9Sstevel@tonic-gate * mark_cluster
27287c478bd9Sstevel@tonic-gate *
27297c478bd9Sstevel@tonic-gate * This routine fills a FAT entry with the value supplied to it as an
27307c478bd9Sstevel@tonic-gate * argument. The fatp argument is assumed to be a pointer to the FAT's
27317c478bd9Sstevel@tonic-gate * 0th entry. The clustnum is the cluster entry that should be updated.
27327c478bd9Sstevel@tonic-gate * The value is the new value for the entry.
27337c478bd9Sstevel@tonic-gate */
27347c478bd9Sstevel@tonic-gate static
27357c478bd9Sstevel@tonic-gate void
mark_cluster(uchar_t * fatp,pc_cluster32_t clustnum,uint32_t value)27367c478bd9Sstevel@tonic-gate mark_cluster(uchar_t *fatp, pc_cluster32_t clustnum, uint32_t value)
27377c478bd9Sstevel@tonic-gate {
27387c478bd9Sstevel@tonic-gate uchar_t *ep;
27397c478bd9Sstevel@tonic-gate ulong_t idx;
27407c478bd9Sstevel@tonic-gate
27417c478bd9Sstevel@tonic-gate idx = (Fatentsize == 32) ? clustnum * 4 :
2742f127cb91Sfrankho (Fatentsize == 16) ? clustnum * 2 : clustnum + clustnum/2;
27437c478bd9Sstevel@tonic-gate ep = fatp + idx;
27447c478bd9Sstevel@tonic-gate
27457c478bd9Sstevel@tonic-gate if (Fatentsize == 32) {
27467c478bd9Sstevel@tonic-gate store_32_bits(&ep, value);
27477c478bd9Sstevel@tonic-gate } else if (Fatentsize == 16) {
27487c478bd9Sstevel@tonic-gate store_16_bits(&ep, value);
27497c478bd9Sstevel@tonic-gate } else {
27507c478bd9Sstevel@tonic-gate if (clustnum & 1) {
27517c478bd9Sstevel@tonic-gate *ep = (*ep & 0x0f) | ((value << 4) & 0xf0);
27527c478bd9Sstevel@tonic-gate ep++;
27537c478bd9Sstevel@tonic-gate *ep = (value >> 4) & 0xff;
27547c478bd9Sstevel@tonic-gate } else {
27557c478bd9Sstevel@tonic-gate *ep++ = value & 0xff;
27567c478bd9Sstevel@tonic-gate *ep = (*ep & 0xf0) | ((value >> 8) & 0x0f);
27577c478bd9Sstevel@tonic-gate }
27587c478bd9Sstevel@tonic-gate }
27597c478bd9Sstevel@tonic-gate }
27607c478bd9Sstevel@tonic-gate
27617c478bd9Sstevel@tonic-gate static
27627c478bd9Sstevel@tonic-gate uchar_t *
build_fat(bpb_t * wbpb,struct fat_od_fsi * fsinfop,ulong_t bootblksize,ulong_t * fatsize,char * ffn,int * fffd,ulong_t * ffsize,pc_cluster32_t * ffstartclust)2763f127cb91Sfrankho build_fat(bpb_t *wbpb, struct fat_od_fsi *fsinfop, ulong_t bootblksize,
27647c478bd9Sstevel@tonic-gate ulong_t *fatsize, char *ffn, int *fffd, ulong_t *ffsize,
27657c478bd9Sstevel@tonic-gate pc_cluster32_t *ffstartclust)
27667c478bd9Sstevel@tonic-gate {
27677c478bd9Sstevel@tonic-gate pc_cluster32_t nextfree, ci;
27687c478bd9Sstevel@tonic-gate uchar_t *fatp;
27697c478bd9Sstevel@tonic-gate ushort_t numclust, numsect;
27707c478bd9Sstevel@tonic-gate int remclust;
27717c478bd9Sstevel@tonic-gate
27727c478bd9Sstevel@tonic-gate /* Alloc space for a FAT and then null it out. */
27737c478bd9Sstevel@tonic-gate if (Verbose) {
27747c478bd9Sstevel@tonic-gate (void) printf(gettext("BUILD FAT.\n%d sectors per fat.\n"),
27757c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat ? wbpb->bpb.sectors_per_fat :
2776f127cb91Sfrankho wbpb->bpb32.big_sectors_per_fat);
27777c478bd9Sstevel@tonic-gate }
27787c478bd9Sstevel@tonic-gate
27797c478bd9Sstevel@tonic-gate if (MakeFAT32) {
27807c478bd9Sstevel@tonic-gate *fatsize = BPSEC * wbpb->bpb32.big_sectors_per_fat;
27817c478bd9Sstevel@tonic-gate } else {
27827c478bd9Sstevel@tonic-gate *fatsize = BPSEC * wbpb->bpb.sectors_per_fat;
27837c478bd9Sstevel@tonic-gate }
27840576819eSwyllys
27857c478bd9Sstevel@tonic-gate if (!(fatp = (uchar_t *)malloc(*fatsize))) {
27867c478bd9Sstevel@tonic-gate perror(gettext("FAT table alloc"));
27877c478bd9Sstevel@tonic-gate exit(4);
27887c478bd9Sstevel@tonic-gate } else {
27897c478bd9Sstevel@tonic-gate (void) memset(fatp, 0, *fatsize);
27907c478bd9Sstevel@tonic-gate }
27917c478bd9Sstevel@tonic-gate
27927c478bd9Sstevel@tonic-gate /* Build in-memory FAT */
27937c478bd9Sstevel@tonic-gate *fatp = wbpb->bpb.media;
27947c478bd9Sstevel@tonic-gate *(fatp + 1) = 0xFF;
27957c478bd9Sstevel@tonic-gate *(fatp + 2) = 0xFF;
27967c478bd9Sstevel@tonic-gate
27977c478bd9Sstevel@tonic-gate if (Fatentsize == 16) {
27987c478bd9Sstevel@tonic-gate *(fatp + 3) = 0xFF;
27997c478bd9Sstevel@tonic-gate } else if (Fatentsize == 32) {
28007c478bd9Sstevel@tonic-gate *(fatp + 3) = 0x0F;
28017c478bd9Sstevel@tonic-gate *(fatp + 4) = 0xFF;
28027c478bd9Sstevel@tonic-gate *(fatp + 5) = 0xFF;
28037c478bd9Sstevel@tonic-gate *(fatp + 6) = 0xFF;
28047c478bd9Sstevel@tonic-gate *(fatp + 7) = 0x0F;
28057c478bd9Sstevel@tonic-gate }
28067c478bd9Sstevel@tonic-gate
28077c478bd9Sstevel@tonic-gate /*
28087c478bd9Sstevel@tonic-gate * Keep track of clusters used.
28097c478bd9Sstevel@tonic-gate */
28107c478bd9Sstevel@tonic-gate remclust = TotalClusters;
28117c478bd9Sstevel@tonic-gate nextfree = 2;
28127c478bd9Sstevel@tonic-gate
28137c478bd9Sstevel@tonic-gate /*
28147c478bd9Sstevel@tonic-gate * Get info on first file to install, if any.
28157c478bd9Sstevel@tonic-gate */
28167c478bd9Sstevel@tonic-gate if (ffn)
28177c478bd9Sstevel@tonic-gate *fffd = verify_firstfile(ffn, ffsize);
28187c478bd9Sstevel@tonic-gate
28197c478bd9Sstevel@tonic-gate /*
28207c478bd9Sstevel@tonic-gate * Compute number of clusters to preserve for bootblk overage.
28217c478bd9Sstevel@tonic-gate * Remember that we already wrote the first sector of the boot block.
28227c478bd9Sstevel@tonic-gate * These clusters are marked BAD to prevent them from being deleted
28237c478bd9Sstevel@tonic-gate * or used. The first available cluster is 2, so we always offset
28247c478bd9Sstevel@tonic-gate * the clusters.
28257c478bd9Sstevel@tonic-gate */
28267c478bd9Sstevel@tonic-gate numsect = idivceil((bootblksize - BPSEC), BPSEC);
28277c478bd9Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster);
28287c478bd9Sstevel@tonic-gate
28297c478bd9Sstevel@tonic-gate if (Verbose && numclust)
28307c478bd9Sstevel@tonic-gate (void) printf(gettext("Hiding %d excess bootblk cluster(s).\n"),
28317c478bd9Sstevel@tonic-gate numclust);
28327c478bd9Sstevel@tonic-gate for (ci = 0; ci < numclust; ci++)
28337c478bd9Sstevel@tonic-gate mark_cluster(fatp, nextfree++,
2834f127cb91Sfrankho MakeFAT32 ? PCF_BADCLUSTER32 : PCF_BADCLUSTER);
28357c478bd9Sstevel@tonic-gate remclust -= numclust;
28367c478bd9Sstevel@tonic-gate
28377c478bd9Sstevel@tonic-gate /*
28387c478bd9Sstevel@tonic-gate * Reserve a cluster for the root directory on a FAT32.
28397c478bd9Sstevel@tonic-gate */
28407c478bd9Sstevel@tonic-gate if (MakeFAT32) {
28417c478bd9Sstevel@tonic-gate mark_cluster(fatp, nextfree, PCF_LASTCLUSTER32);
28427c478bd9Sstevel@tonic-gate wbpb->bpb32.root_dir_clust = nextfree++;
28437c478bd9Sstevel@tonic-gate remclust--;
28447c478bd9Sstevel@tonic-gate }
28457c478bd9Sstevel@tonic-gate
28467c478bd9Sstevel@tonic-gate /*
28477c478bd9Sstevel@tonic-gate * Compute and preserve number of clusters for first file.
28487c478bd9Sstevel@tonic-gate */
28497c478bd9Sstevel@tonic-gate if (*fffd >= 0) {
28507c478bd9Sstevel@tonic-gate *ffstartclust = nextfree;
28517c478bd9Sstevel@tonic-gate numsect = idivceil(*ffsize, BPSEC);
28527c478bd9Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster);
28537c478bd9Sstevel@tonic-gate
28547c478bd9Sstevel@tonic-gate if (numclust > remclust) {
28557c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
2856f127cb91Sfrankho gettext("Requested first file too large to be\n"
2857f127cb91Sfrankho "installed in the new file system.\n"));
28587c478bd9Sstevel@tonic-gate (void) close(*fffd);
28597c478bd9Sstevel@tonic-gate *fffd = -1;
28607c478bd9Sstevel@tonic-gate goto finish;
28617c478bd9Sstevel@tonic-gate }
28627c478bd9Sstevel@tonic-gate
28637c478bd9Sstevel@tonic-gate if (Verbose)
28647c478bd9Sstevel@tonic-gate (void) printf(gettext("Reserving %d first file "
28657c478bd9Sstevel@tonic-gate "cluster(s).\n"), numclust);
28667c478bd9Sstevel@tonic-gate for (ci = 0; (int)ci < (int)(numclust-1); ci++, nextfree++)
28677c478bd9Sstevel@tonic-gate mark_cluster(fatp, nextfree, nextfree + 1);
28687c478bd9Sstevel@tonic-gate mark_cluster(fatp, nextfree++,
2869f127cb91Sfrankho MakeFAT32 ? PCF_LASTCLUSTER32 : PCF_LASTCLUSTER);
28707c478bd9Sstevel@tonic-gate remclust -= numclust;
28717c478bd9Sstevel@tonic-gate }
28727c478bd9Sstevel@tonic-gate
28737c478bd9Sstevel@tonic-gate finish:
28747c478bd9Sstevel@tonic-gate if (Verbose) {
28757c478bd9Sstevel@tonic-gate (void) printf(gettext("First sector of FAT"));
28767c478bd9Sstevel@tonic-gate header_for_dump();
28777c478bd9Sstevel@tonic-gate dump_bytes(fatp, BPSEC);
28787c478bd9Sstevel@tonic-gate }
28797c478bd9Sstevel@tonic-gate
2880f127cb91Sfrankho (void) memset(fsinfop, 0, sizeof (*fsinfop));
2881f127cb91Sfrankho fsinfop->fsi_leadsig = LE_32(FSI_LEADSIG);
2882f127cb91Sfrankho fsinfop->fsi_strucsig = LE_32(FSI_STRUCSIG);
2883f127cb91Sfrankho fsinfop->fsi_trailsig = LE_32(FSI_TRAILSIG);
2884f127cb91Sfrankho fsinfop->fsi_incore.fs_free_clusters = LE_32(remclust);
2885f127cb91Sfrankho fsinfop->fsi_incore.fs_next_free = LE_32(nextfree);
28867c478bd9Sstevel@tonic-gate return (fatp);
28877c478bd9Sstevel@tonic-gate }
28887c478bd9Sstevel@tonic-gate
28897c478bd9Sstevel@tonic-gate static
28907c478bd9Sstevel@tonic-gate void
dirent_time_fill(struct pcdir * dep)28917c478bd9Sstevel@tonic-gate dirent_time_fill(struct pcdir *dep)
28927c478bd9Sstevel@tonic-gate {
28937c478bd9Sstevel@tonic-gate struct timeval tv;
28947c478bd9Sstevel@tonic-gate struct tm *tp;
28957c478bd9Sstevel@tonic-gate ushort_t dostime;
28967c478bd9Sstevel@tonic-gate ushort_t dosday;
28977c478bd9Sstevel@tonic-gate
28987c478bd9Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)0);
28997c478bd9Sstevel@tonic-gate tp = localtime(&tv.tv_sec);
29007c478bd9Sstevel@tonic-gate /* get the time & day into DOS format */
29017c478bd9Sstevel@tonic-gate dostime = tp->tm_sec / 2;
29027c478bd9Sstevel@tonic-gate dostime |= tp->tm_min << 5;
29037c478bd9Sstevel@tonic-gate dostime |= tp->tm_hour << 11;
29047c478bd9Sstevel@tonic-gate dosday = tp->tm_mday;
29057c478bd9Sstevel@tonic-gate dosday |= (tp->tm_mon + 1) << 5;
29067c478bd9Sstevel@tonic-gate dosday |= (tp->tm_year - 80) << 9;
29077c478bd9Sstevel@tonic-gate dep->pcd_mtime.pct_time = htols(dostime);
29087c478bd9Sstevel@tonic-gate dep->pcd_mtime.pct_date = htols(dosday);
29097c478bd9Sstevel@tonic-gate }
29107c478bd9Sstevel@tonic-gate
29117c478bd9Sstevel@tonic-gate static
29127c478bd9Sstevel@tonic-gate void
dirent_label_fill(struct pcdir * dep,char * fn)29137c478bd9Sstevel@tonic-gate dirent_label_fill(struct pcdir *dep, char *fn)
29147c478bd9Sstevel@tonic-gate {
29157c478bd9Sstevel@tonic-gate int nl, i;
29167c478bd9Sstevel@tonic-gate
29177c478bd9Sstevel@tonic-gate /*
29187c478bd9Sstevel@tonic-gate * We spread the volume label across both the NAME and EXT fields
29197c478bd9Sstevel@tonic-gate */
29207c478bd9Sstevel@tonic-gate nl = min(PCFNAMESIZE, strlen(fn));
29217c478bd9Sstevel@tonic-gate for (i = 0; i < nl; i++) {
29227c478bd9Sstevel@tonic-gate dep->pcd_filename[i] = toupper(fn[i]);
29237c478bd9Sstevel@tonic-gate }
29247c478bd9Sstevel@tonic-gate if (i < PCFNAMESIZE) {
29257c478bd9Sstevel@tonic-gate for (; i < PCFNAMESIZE; i++)
29267c478bd9Sstevel@tonic-gate dep->pcd_filename[i] = ' ';
29277c478bd9Sstevel@tonic-gate for (i = 0; i < PCFEXTSIZE; i++)
29287c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = ' ';
29297c478bd9Sstevel@tonic-gate return;
29307c478bd9Sstevel@tonic-gate }
29317c478bd9Sstevel@tonic-gate nl = min(PCFEXTSIZE, strlen(fn) - PCFNAMESIZE);
29327c478bd9Sstevel@tonic-gate for (i = 0; i < nl; i++)
29337c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = toupper(fn[i + PCFNAMESIZE]);
29347c478bd9Sstevel@tonic-gate if (i < PCFEXTSIZE) {
29357c478bd9Sstevel@tonic-gate for (; i < PCFEXTSIZE; i++)
29367c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = ' ';
29377c478bd9Sstevel@tonic-gate }
29387c478bd9Sstevel@tonic-gate }
29397c478bd9Sstevel@tonic-gate
29407c478bd9Sstevel@tonic-gate static
29417c478bd9Sstevel@tonic-gate void
dirent_fname_fill(struct pcdir * dep,char * fn)29427c478bd9Sstevel@tonic-gate dirent_fname_fill(struct pcdir *dep, char *fn)
29437c478bd9Sstevel@tonic-gate {
29447c478bd9Sstevel@tonic-gate char *fname, *fext;
29457c478bd9Sstevel@tonic-gate int nl, i;
29467c478bd9Sstevel@tonic-gate
29477c478bd9Sstevel@tonic-gate if (fname = strrchr(fn, '/')) {
29487c478bd9Sstevel@tonic-gate fname++;
29497c478bd9Sstevel@tonic-gate } else {
29507c478bd9Sstevel@tonic-gate fname = fn;
29517c478bd9Sstevel@tonic-gate }
29527c478bd9Sstevel@tonic-gate
29537c478bd9Sstevel@tonic-gate if (fext = strrchr(fname, '.')) {
29547c478bd9Sstevel@tonic-gate fext++;
29557c478bd9Sstevel@tonic-gate } else {
29567c478bd9Sstevel@tonic-gate fext = "";
29577c478bd9Sstevel@tonic-gate }
29587c478bd9Sstevel@tonic-gate
29597c478bd9Sstevel@tonic-gate fname = strtok(fname, ".");
29607c478bd9Sstevel@tonic-gate
29617c478bd9Sstevel@tonic-gate nl = min(PCFNAMESIZE, (int)strlen(fname));
29627c478bd9Sstevel@tonic-gate for (i = 0; i < nl; i++) {
29637c478bd9Sstevel@tonic-gate dep->pcd_filename[i] = toupper(fname[i]);
29647c478bd9Sstevel@tonic-gate }
29657c478bd9Sstevel@tonic-gate for (; i < PCFNAMESIZE; i++) {
29667c478bd9Sstevel@tonic-gate dep->pcd_filename[i] = ' ';
29677c478bd9Sstevel@tonic-gate }
29687c478bd9Sstevel@tonic-gate
29697c478bd9Sstevel@tonic-gate nl = min(PCFEXTSIZE, (int)strlen(fext));
29707c478bd9Sstevel@tonic-gate for (i = 0; i < nl; i++) {
29717c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = toupper(fext[i]);
29727c478bd9Sstevel@tonic-gate }
29737c478bd9Sstevel@tonic-gate for (; i < PCFEXTSIZE; i++) {
29747c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = ' ';
29757c478bd9Sstevel@tonic-gate }
29767c478bd9Sstevel@tonic-gate }
29777c478bd9Sstevel@tonic-gate
29787c478bd9Sstevel@tonic-gate static
29797c478bd9Sstevel@tonic-gate uchar_t *
build_rootdir(bpb_t * wbpb,char * ffn,int fffd,ulong_t ffsize,pc_cluster32_t ffstart,ulong_t * rdirsize)29807c478bd9Sstevel@tonic-gate build_rootdir(bpb_t *wbpb, char *ffn, int fffd,
29817c478bd9Sstevel@tonic-gate ulong_t ffsize, pc_cluster32_t ffstart, ulong_t *rdirsize)
29827c478bd9Sstevel@tonic-gate {
29837c478bd9Sstevel@tonic-gate struct pcdir *rootdirp;
29847c478bd9Sstevel@tonic-gate struct pcdir *entry;
29857c478bd9Sstevel@tonic-gate
29867c478bd9Sstevel@tonic-gate /*
29877c478bd9Sstevel@tonic-gate * Build a root directory. It will have at least one entry,
29887c478bd9Sstevel@tonic-gate * the volume label and a second if the first file was defined.
29897c478bd9Sstevel@tonic-gate */
29907c478bd9Sstevel@tonic-gate if (MakeFAT32) {
29917c478bd9Sstevel@tonic-gate /*
29927c478bd9Sstevel@tonic-gate * We devote an entire cluster to the root
29937c478bd9Sstevel@tonic-gate * directory on FAT32.
29947c478bd9Sstevel@tonic-gate */
29957c478bd9Sstevel@tonic-gate *rdirsize = wbpb->bpb.sectors_per_cluster * BPSEC;
29967c478bd9Sstevel@tonic-gate } else {
29977c478bd9Sstevel@tonic-gate *rdirsize = wbpb->bpb.num_root_entries * sizeof (struct pcdir);
29987c478bd9Sstevel@tonic-gate }
29997c478bd9Sstevel@tonic-gate if ((rootdirp = (struct pcdir *)malloc(*rdirsize)) == NULL) {
30007c478bd9Sstevel@tonic-gate perror(gettext("Root directory allocation"));
30017c478bd9Sstevel@tonic-gate exit(4);
30027c478bd9Sstevel@tonic-gate } else {
30037c478bd9Sstevel@tonic-gate entry = rootdirp;
30047c478bd9Sstevel@tonic-gate (void) memset((char *)rootdirp, 0, *rdirsize);
30057c478bd9Sstevel@tonic-gate }
30067c478bd9Sstevel@tonic-gate
30077c478bd9Sstevel@tonic-gate /* Create directory entry for first file, if there is one */
30087c478bd9Sstevel@tonic-gate if (fffd >= 0) {
30097c478bd9Sstevel@tonic-gate dirent_fname_fill(entry, ffn);
30107c478bd9Sstevel@tonic-gate entry->pcd_attr = Firstfileattr;
30117c478bd9Sstevel@tonic-gate dirent_time_fill(entry);
30127c478bd9Sstevel@tonic-gate entry->pcd_scluster_lo = htols(ffstart);
30137c478bd9Sstevel@tonic-gate if (MakeFAT32) {
30147c478bd9Sstevel@tonic-gate ffstart = ffstart >> 16;
30157c478bd9Sstevel@tonic-gate entry->un.pcd_scluster_hi = htols(ffstart);
30167c478bd9Sstevel@tonic-gate }
30177c478bd9Sstevel@tonic-gate entry->pcd_size = htoli(ffsize);
30187c478bd9Sstevel@tonic-gate entry++;
30197c478bd9Sstevel@tonic-gate }
30207c478bd9Sstevel@tonic-gate
30217c478bd9Sstevel@tonic-gate /* Create directory entry for volume label, if there is one */
30227c478bd9Sstevel@tonic-gate if (Label != NULL) {
30237c478bd9Sstevel@tonic-gate dirent_label_fill(entry, Label);
30247c478bd9Sstevel@tonic-gate entry->pcd_attr = PCA_ARCH | PCA_LABEL;
30257c478bd9Sstevel@tonic-gate dirent_time_fill(entry);
30267c478bd9Sstevel@tonic-gate entry->pcd_scluster_lo = 0;
30277c478bd9Sstevel@tonic-gate if (MakeFAT32) {
30287c478bd9Sstevel@tonic-gate entry->un.pcd_scluster_hi = 0;
30297c478bd9Sstevel@tonic-gate }
30307c478bd9Sstevel@tonic-gate entry->pcd_size = 0;
30317c478bd9Sstevel@tonic-gate entry++;
30327c478bd9Sstevel@tonic-gate }
30337c478bd9Sstevel@tonic-gate
30347c478bd9Sstevel@tonic-gate if (Verbose) {
30357c478bd9Sstevel@tonic-gate (void) printf(gettext("First two directory entries"));
30367c478bd9Sstevel@tonic-gate header_for_dump();
30377c478bd9Sstevel@tonic-gate dump_bytes((uchar_t *)rootdirp, 2 * sizeof (struct pcdir));
30387c478bd9Sstevel@tonic-gate }
30397c478bd9Sstevel@tonic-gate
30407c478bd9Sstevel@tonic-gate return ((uchar_t *)rootdirp);
30417c478bd9Sstevel@tonic-gate }
30427c478bd9Sstevel@tonic-gate
30437c478bd9Sstevel@tonic-gate /*
30447c478bd9Sstevel@tonic-gate * write_rest
30457c478bd9Sstevel@tonic-gate *
30467c478bd9Sstevel@tonic-gate * Write all the bytes from the current file pointer to end of file
30477c478bd9Sstevel@tonic-gate * in the source file out to the destination file. The writes should
30487c478bd9Sstevel@tonic-gate * be padded to whole clusters with 0's if necessary.
30497c478bd9Sstevel@tonic-gate */
30507c478bd9Sstevel@tonic-gate static
30517c478bd9Sstevel@tonic-gate void
write_rest(bpb_t * wbpb,char * efn,int dfd,int sfd,int remaining)30527c478bd9Sstevel@tonic-gate write_rest(bpb_t *wbpb, char *efn, int dfd, int sfd, int remaining)
30537c478bd9Sstevel@tonic-gate {
30547c478bd9Sstevel@tonic-gate char buf[BPSEC];
30557c478bd9Sstevel@tonic-gate ushort_t numsect, numclust;
30567c478bd9Sstevel@tonic-gate ushort_t wnumsect, s;
30577c478bd9Sstevel@tonic-gate int doneread = 0;
30587c478bd9Sstevel@tonic-gate int rstat;
30597c478bd9Sstevel@tonic-gate
30607c478bd9Sstevel@tonic-gate /*
30617c478bd9Sstevel@tonic-gate * Compute number of clusters required to contain remaining bytes.
30627c478bd9Sstevel@tonic-gate */
30637c478bd9Sstevel@tonic-gate numsect = idivceil(remaining, BPSEC);
30647c478bd9Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster);
30657c478bd9Sstevel@tonic-gate
30667c478bd9Sstevel@tonic-gate wnumsect = numclust * wbpb->bpb.sectors_per_cluster;
30677c478bd9Sstevel@tonic-gate for (s = 0; s < wnumsect; s++) {
30687c478bd9Sstevel@tonic-gate if (!doneread) {
30697c478bd9Sstevel@tonic-gate if ((rstat = read(sfd, buf, BPSEC)) < 0) {
30707c478bd9Sstevel@tonic-gate perror(efn);
30717c478bd9Sstevel@tonic-gate doneread = 1;
30727c478bd9Sstevel@tonic-gate rstat = 0;
30737c478bd9Sstevel@tonic-gate } else if (rstat == 0) {
30747c478bd9Sstevel@tonic-gate doneread = 1;
30757c478bd9Sstevel@tonic-gate }
30767c478bd9Sstevel@tonic-gate (void) memset(&(buf[rstat]), 0, BPSEC - rstat);
30777c478bd9Sstevel@tonic-gate }
30787c478bd9Sstevel@tonic-gate if (write(dfd, buf, BPSEC) != BPSEC) {
30797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Copying "));
30807c478bd9Sstevel@tonic-gate perror(efn);
30817c478bd9Sstevel@tonic-gate }
30827c478bd9Sstevel@tonic-gate }
30837c478bd9Sstevel@tonic-gate }
30847c478bd9Sstevel@tonic-gate
30857c478bd9Sstevel@tonic-gate static
30867c478bd9Sstevel@tonic-gate void
write_fat32_bootstuff(int fd,boot_sector_t * bsp,struct fat_od_fsi * fsinfop,off64_t seekto)30877c478bd9Sstevel@tonic-gate write_fat32_bootstuff(int fd, boot_sector_t *bsp,
3088*5b5a71c4SToomas Soome struct fat_od_fsi *fsinfop, off64_t seekto)
30897c478bd9Sstevel@tonic-gate {
30907c478bd9Sstevel@tonic-gate if (Verbose) {
30917c478bd9Sstevel@tonic-gate (void) printf(gettext("Dump of the fs info sector"));
30927c478bd9Sstevel@tonic-gate header_for_dump();
3093f127cb91Sfrankho dump_bytes((uchar_t *)fsinfop, sizeof (*fsinfop));
30947c478bd9Sstevel@tonic-gate }
30957c478bd9Sstevel@tonic-gate
30967c478bd9Sstevel@tonic-gate if (!Notreally) {
30977c478bd9Sstevel@tonic-gate /*
30987c478bd9Sstevel@tonic-gate * FAT32's have an FS info sector, then a backup of the boot
30997c478bd9Sstevel@tonic-gate * sector, and a modified backup of the FS Info sector.
31007c478bd9Sstevel@tonic-gate */
3101f127cb91Sfrankho if (write(fd, fsinfop, sizeof (*fsinfop)) != BPSEC) {
31027c478bd9Sstevel@tonic-gate perror(gettext("FS info sector write"));
31037c478bd9Sstevel@tonic-gate exit(4);
31047c478bd9Sstevel@tonic-gate }
31057c478bd9Sstevel@tonic-gate if (lseek64(fd, seekto + BKUP_BOOTSECT_OFFSET, SEEK_SET) < 0) {
31067c478bd9Sstevel@tonic-gate (void) close(fd);
31077c478bd9Sstevel@tonic-gate perror(gettext("Boot sector backup seek"));
31087c478bd9Sstevel@tonic-gate exit(4);
31097c478bd9Sstevel@tonic-gate }
31107c478bd9Sstevel@tonic-gate if (write(fd, bsp->buf, sizeof (bsp->buf)) != BPSEC) {
31117c478bd9Sstevel@tonic-gate perror(gettext("Boot sector backup write"));
31127c478bd9Sstevel@tonic-gate exit(4);
31137c478bd9Sstevel@tonic-gate }
31147c478bd9Sstevel@tonic-gate }
31157c478bd9Sstevel@tonic-gate
31167c478bd9Sstevel@tonic-gate /*
31177c478bd9Sstevel@tonic-gate * Second copy of fs info sector is modified to have "don't know"
31187c478bd9Sstevel@tonic-gate * as the number of free clusters
31197c478bd9Sstevel@tonic-gate */
3120f127cb91Sfrankho fsinfop->fsi_incore.fs_next_free = LE_32(FSINFO_UNKNOWN);
31217c478bd9Sstevel@tonic-gate
31227c478bd9Sstevel@tonic-gate if (Verbose) {
31237c478bd9Sstevel@tonic-gate (void) printf(gettext("Dump of the backup fs info sector"));
31247c478bd9Sstevel@tonic-gate header_for_dump();
3125f127cb91Sfrankho dump_bytes((uchar_t *)fsinfop, sizeof (*fsinfop));
31267c478bd9Sstevel@tonic-gate }
31277c478bd9Sstevel@tonic-gate
31287c478bd9Sstevel@tonic-gate if (!Notreally) {
3129f127cb91Sfrankho if (write(fd, fsinfop, sizeof (*fsinfop)) != BPSEC) {
31307c478bd9Sstevel@tonic-gate perror(gettext("FS info sector backup write"));
31317c478bd9Sstevel@tonic-gate exit(4);
31327c478bd9Sstevel@tonic-gate }
31337c478bd9Sstevel@tonic-gate }
31347c478bd9Sstevel@tonic-gate }
31357c478bd9Sstevel@tonic-gate
31367c478bd9Sstevel@tonic-gate static
31377c478bd9Sstevel@tonic-gate void
write_bootsects(int fd,boot_sector_t * bsp,bpb_t * wbpb,struct fat_od_fsi * fsinfop,off64_t seekto)31387c478bd9Sstevel@tonic-gate write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb,
3139*5b5a71c4SToomas Soome struct fat_od_fsi *fsinfop, off64_t seekto)
31407c478bd9Sstevel@tonic-gate {
31417c478bd9Sstevel@tonic-gate if (MakeFAT32) {
31427c478bd9Sstevel@tonic-gate /* Copy our BPB into bootsec structure */
31437c478bd9Sstevel@tonic-gate #ifdef i386
31447c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_front.bs_bpb), &(wbpb->bpb),
3145f127cb91Sfrankho sizeof (wbpb->bpb));
31467c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_bpb32), &(wbpb->bpb32),
3147f127cb91Sfrankho sizeof (wbpb->bpb32));
31487c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_ebpb), &(wbpb->ebpb),
3149f127cb91Sfrankho sizeof (wbpb->ebpb));
31507c478bd9Sstevel@tonic-gate #else
31517c478bd9Sstevel@tonic-gate swap_pack_bpb32cpy(&(bsp->bs32), wbpb);
31527c478bd9Sstevel@tonic-gate #endif
31537c478bd9Sstevel@tonic-gate } else {
31547c478bd9Sstevel@tonic-gate /* Copy our BPB into bootsec structure */
31557c478bd9Sstevel@tonic-gate #ifdef i386
31567c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_front.bs_bpb), &(wbpb->bpb),
3157f127cb91Sfrankho sizeof (wbpb->bpb));
31587c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_ebpb), &(wbpb->ebpb),
3159f127cb91Sfrankho sizeof (wbpb->ebpb));
31607c478bd9Sstevel@tonic-gate #else
31617c478bd9Sstevel@tonic-gate swap_pack_bpbcpy(&(bsp->bs), wbpb);
31627c478bd9Sstevel@tonic-gate #endif
31637c478bd9Sstevel@tonic-gate
31647c478bd9Sstevel@tonic-gate /* Copy SUN BPB extensions into bootsec structure */
31657c478bd9Sstevel@tonic-gate if (SunBPBfields) {
31667c478bd9Sstevel@tonic-gate #ifdef i386
31677c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_sebpb), &(wbpb->sunbpb),
3168f127cb91Sfrankho sizeof (wbpb->sunbpb));
31697c478bd9Sstevel@tonic-gate #else
31707c478bd9Sstevel@tonic-gate swap_pack_sebpbcpy(&(bsp->bs), wbpb);
31717c478bd9Sstevel@tonic-gate #endif
31727c478bd9Sstevel@tonic-gate }
31737c478bd9Sstevel@tonic-gate }
31747c478bd9Sstevel@tonic-gate
31757c478bd9Sstevel@tonic-gate /* Write boot sector */
31767c478bd9Sstevel@tonic-gate if (!Notreally && write(fd, bsp->buf, sizeof (bsp->buf)) != BPSEC) {
31777c478bd9Sstevel@tonic-gate perror(gettext("Boot sector write"));
31787c478bd9Sstevel@tonic-gate exit(4);
31797c478bd9Sstevel@tonic-gate }
31807c478bd9Sstevel@tonic-gate
31817c478bd9Sstevel@tonic-gate if (Verbose) {
31827c478bd9Sstevel@tonic-gate (void) printf(gettext("Dump of the boot sector"));
31837c478bd9Sstevel@tonic-gate header_for_dump();
31847c478bd9Sstevel@tonic-gate dump_bytes(bsp->buf, sizeof (bsp->buf));
31857c478bd9Sstevel@tonic-gate }
31867c478bd9Sstevel@tonic-gate
31877c478bd9Sstevel@tonic-gate if (MakeFAT32)
31887c478bd9Sstevel@tonic-gate write_fat32_bootstuff(fd, bsp, fsinfop, seekto);
31897c478bd9Sstevel@tonic-gate }
31907c478bd9Sstevel@tonic-gate
31917c478bd9Sstevel@tonic-gate static
31927c478bd9Sstevel@tonic-gate void
write_fat(int fd,off64_t seekto,char * fn,char * lbl,char * ffn,bpb_t * wbpb)31937c478bd9Sstevel@tonic-gate write_fat(int fd, off64_t seekto, char *fn, char *lbl, char *ffn, bpb_t *wbpb)
31947c478bd9Sstevel@tonic-gate {
3195f127cb91Sfrankho struct fat_od_fsi fsinfo;
31967c478bd9Sstevel@tonic-gate pc_cluster32_t ffsc;
31977c478bd9Sstevel@tonic-gate boot_sector_t bootsect;
31987c478bd9Sstevel@tonic-gate uchar_t *fatp, *rdirp;
31997c478bd9Sstevel@tonic-gate ulong_t bootblksize, fatsize, rdirsize, ffsize;
32007c478bd9Sstevel@tonic-gate int bsfd = -1;
32017c478bd9Sstevel@tonic-gate int fffd = -1;
32027c478bd9Sstevel@tonic-gate
32037c478bd9Sstevel@tonic-gate compute_file_area_size(wbpb);
32047c478bd9Sstevel@tonic-gate
32057c478bd9Sstevel@tonic-gate bsfd = copy_bootblk(fn, &bootsect, &bootblksize);
32067c478bd9Sstevel@tonic-gate label_volume(lbl, wbpb);
32077c478bd9Sstevel@tonic-gate
32087c478bd9Sstevel@tonic-gate if (Verbose)
32097c478bd9Sstevel@tonic-gate (void) printf(gettext("Building FAT.\n"));
32107c478bd9Sstevel@tonic-gate fatp = build_fat(wbpb, &fsinfo, bootblksize, &fatsize,
32117c478bd9Sstevel@tonic-gate ffn, &fffd, &ffsize, &ffsc);
32127c478bd9Sstevel@tonic-gate
32137c478bd9Sstevel@tonic-gate write_bootsects(fd, &bootsect, wbpb, &fsinfo, seekto);
32147c478bd9Sstevel@tonic-gate
32157c478bd9Sstevel@tonic-gate if (lseek64(fd,
32167c478bd9Sstevel@tonic-gate seekto + (BPSEC * wbpb->bpb.resv_sectors), SEEK_SET) < 0) {
32177c478bd9Sstevel@tonic-gate (void) close(fd);
32187c478bd9Sstevel@tonic-gate perror(gettext("Seek to end of reserved sectors"));
32197c478bd9Sstevel@tonic-gate exit(4);
32207c478bd9Sstevel@tonic-gate }
32217c478bd9Sstevel@tonic-gate
32227c478bd9Sstevel@tonic-gate /* Write FAT */
32237c478bd9Sstevel@tonic-gate if (Verbose)
32247c478bd9Sstevel@tonic-gate (void) printf(gettext("Writing FAT(s). %d bytes times %d.\n"),
32257c478bd9Sstevel@tonic-gate fatsize, wbpb->bpb.num_fats);
32267c478bd9Sstevel@tonic-gate if (!Notreally) {
32277c478bd9Sstevel@tonic-gate int nf, wb;
32287c478bd9Sstevel@tonic-gate for (nf = 0; nf < (int)wbpb->bpb.num_fats; nf++)
32297c478bd9Sstevel@tonic-gate if ((wb = write(fd, fatp, fatsize)) != fatsize) {
32307c478bd9Sstevel@tonic-gate perror(gettext("FAT write"));
32317c478bd9Sstevel@tonic-gate exit(4);
32327c478bd9Sstevel@tonic-gate } else {
32337c478bd9Sstevel@tonic-gate if (Verbose)
32347c478bd9Sstevel@tonic-gate (void) printf(
32357c478bd9Sstevel@tonic-gate gettext("Wrote %d bytes\n"), wb);
32367c478bd9Sstevel@tonic-gate }
32377c478bd9Sstevel@tonic-gate }
32387c478bd9Sstevel@tonic-gate free(fatp);
32397c478bd9Sstevel@tonic-gate
32407c478bd9Sstevel@tonic-gate if (Verbose)
32417c478bd9Sstevel@tonic-gate (void) printf(gettext("Building root directory.\n"));
32427c478bd9Sstevel@tonic-gate rdirp = build_rootdir(wbpb, ffn, fffd, ffsize, ffsc, &rdirsize);
32437c478bd9Sstevel@tonic-gate
32447c478bd9Sstevel@tonic-gate /*
32457c478bd9Sstevel@tonic-gate * In non FAT32, root directory exists outside of the file area
32467c478bd9Sstevel@tonic-gate */
32477c478bd9Sstevel@tonic-gate if (!MakeFAT32) {
32487c478bd9Sstevel@tonic-gate if (Verbose)
3249f127cb91Sfrankho (void) printf(gettext("Writing root directory. "
3250f127cb91Sfrankho "%d bytes.\n"), rdirsize);
32517c478bd9Sstevel@tonic-gate if (!Notreally) {
32527c478bd9Sstevel@tonic-gate if (write(fd, rdirp, rdirsize) != rdirsize) {
32537c478bd9Sstevel@tonic-gate perror(gettext("Root directory write"));
32547c478bd9Sstevel@tonic-gate exit(4);
32557c478bd9Sstevel@tonic-gate }
32567c478bd9Sstevel@tonic-gate }
32577c478bd9Sstevel@tonic-gate free(rdirp);
32587c478bd9Sstevel@tonic-gate }
32597c478bd9Sstevel@tonic-gate
32607c478bd9Sstevel@tonic-gate /*
32617c478bd9Sstevel@tonic-gate * Now write anything that needs to be in the file space.
32627c478bd9Sstevel@tonic-gate */
32637c478bd9Sstevel@tonic-gate if (bootblksize > BPSEC) {
32647c478bd9Sstevel@tonic-gate if (Verbose)
32657c478bd9Sstevel@tonic-gate (void) printf(gettext("Writing remainder of "
3266f127cb91Sfrankho "boot block.\n"));
32677c478bd9Sstevel@tonic-gate if (!Notreally)
32687c478bd9Sstevel@tonic-gate write_rest(wbpb, fn, fd, bsfd, bootblksize - BPSEC);
32697c478bd9Sstevel@tonic-gate }
32707c478bd9Sstevel@tonic-gate
32717c478bd9Sstevel@tonic-gate if (MakeFAT32) {
32727c478bd9Sstevel@tonic-gate if (Verbose)
3273f127cb91Sfrankho (void) printf(gettext("Writing root directory. "
3274f127cb91Sfrankho "%d bytes.\n"), rdirsize);
32757c478bd9Sstevel@tonic-gate if (!Notreally) {
32767c478bd9Sstevel@tonic-gate if (write(fd, rdirp, rdirsize) != rdirsize) {
32777c478bd9Sstevel@tonic-gate perror(gettext("Root directory write"));
32787c478bd9Sstevel@tonic-gate exit(4);
32797c478bd9Sstevel@tonic-gate }
32807c478bd9Sstevel@tonic-gate }
32817c478bd9Sstevel@tonic-gate free(rdirp);
32827c478bd9Sstevel@tonic-gate }
32837c478bd9Sstevel@tonic-gate
32847c478bd9Sstevel@tonic-gate if (fffd >= 0) {
32857c478bd9Sstevel@tonic-gate if (Verbose)
32867c478bd9Sstevel@tonic-gate (void) printf(gettext("Writing first file.\n"));
32877c478bd9Sstevel@tonic-gate if (!Notreally)
32887c478bd9Sstevel@tonic-gate write_rest(wbpb, ffn, fd, fffd, ffsize);
32897c478bd9Sstevel@tonic-gate }
32907c478bd9Sstevel@tonic-gate }
32917c478bd9Sstevel@tonic-gate
32927c478bd9Sstevel@tonic-gate static
32937c478bd9Sstevel@tonic-gate char *LegalOpts[] = {
32947c478bd9Sstevel@tonic-gate #define NFLAG 0
32957c478bd9Sstevel@tonic-gate "N",
32967c478bd9Sstevel@tonic-gate #define VFLAG 1
32977c478bd9Sstevel@tonic-gate "v",
32987c478bd9Sstevel@tonic-gate #define RFLAG 2
32997c478bd9Sstevel@tonic-gate "r",
33007c478bd9Sstevel@tonic-gate #define HFLAG 3
33017c478bd9Sstevel@tonic-gate "h",
33027c478bd9Sstevel@tonic-gate #define SFLAG 4
33037c478bd9Sstevel@tonic-gate "s",
33047c478bd9Sstevel@tonic-gate #define SUNFLAG 5
33057c478bd9Sstevel@tonic-gate "S",
33067c478bd9Sstevel@tonic-gate #define LABFLAG 6
33077c478bd9Sstevel@tonic-gate "b",
33087c478bd9Sstevel@tonic-gate #define BTRFLAG 7
33097c478bd9Sstevel@tonic-gate "B",
33107c478bd9Sstevel@tonic-gate #define INITFLAG 8
33117c478bd9Sstevel@tonic-gate "i",
33127c478bd9Sstevel@tonic-gate #define SZFLAG 9
33137c478bd9Sstevel@tonic-gate "size",
33147c478bd9Sstevel@tonic-gate #define SECTFLAG 10
33157c478bd9Sstevel@tonic-gate "nsect",
33167c478bd9Sstevel@tonic-gate #define TRKFLAG 11
33177c478bd9Sstevel@tonic-gate "ntrack",
33187c478bd9Sstevel@tonic-gate #define SPCFLAG 12
33197c478bd9Sstevel@tonic-gate "spc",
33207c478bd9Sstevel@tonic-gate #define BPFFLAG 13
33217c478bd9Sstevel@tonic-gate "fat",
33227c478bd9Sstevel@tonic-gate #define FFLAG 14
33237c478bd9Sstevel@tonic-gate "f",
33247c478bd9Sstevel@tonic-gate #define DFLAG 15
33257c478bd9Sstevel@tonic-gate "d",
33267c478bd9Sstevel@tonic-gate #define NOFDISKFLAG 16
33277c478bd9Sstevel@tonic-gate "nofdisk",
33287c478bd9Sstevel@tonic-gate #define RESRVFLAG 17
33297c478bd9Sstevel@tonic-gate "reserve",
33307c478bd9Sstevel@tonic-gate #define HIDDENFLAG 18
33317c478bd9Sstevel@tonic-gate "hidden",
33327c478bd9Sstevel@tonic-gate NULL
33337c478bd9Sstevel@tonic-gate };
33347c478bd9Sstevel@tonic-gate
33357c478bd9Sstevel@tonic-gate static
33367c478bd9Sstevel@tonic-gate void
bad_arg(char * option)33377c478bd9Sstevel@tonic-gate bad_arg(char *option)
33387c478bd9Sstevel@tonic-gate {
33397c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
3340f127cb91Sfrankho gettext("Unrecognized option %s.\n"), option);
33417c478bd9Sstevel@tonic-gate usage();
33427c478bd9Sstevel@tonic-gate exit(2);
33437c478bd9Sstevel@tonic-gate }
33447c478bd9Sstevel@tonic-gate
33457c478bd9Sstevel@tonic-gate static
33467c478bd9Sstevel@tonic-gate void
missing_arg(char * option)33477c478bd9Sstevel@tonic-gate missing_arg(char *option)
33487c478bd9Sstevel@tonic-gate {
33497c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
3350f127cb91Sfrankho gettext("Option %s requires a value.\n"), option);
33517c478bd9Sstevel@tonic-gate usage();
33527c478bd9Sstevel@tonic-gate exit(3);
33537c478bd9Sstevel@tonic-gate }
33547c478bd9Sstevel@tonic-gate
33557c478bd9Sstevel@tonic-gate static
33567c478bd9Sstevel@tonic-gate void
parse_suboptions(char * optsstr)33577c478bd9Sstevel@tonic-gate parse_suboptions(char *optsstr)
33587c478bd9Sstevel@tonic-gate {
33597c478bd9Sstevel@tonic-gate char *value;
33607c478bd9Sstevel@tonic-gate int c;
33617c478bd9Sstevel@tonic-gate
33627c478bd9Sstevel@tonic-gate while (*optsstr != '\0') {
33637c478bd9Sstevel@tonic-gate switch (c = getsubopt(&optsstr, LegalOpts, &value)) {
33647c478bd9Sstevel@tonic-gate case NFLAG:
33657c478bd9Sstevel@tonic-gate Notreally++;
33667c478bd9Sstevel@tonic-gate break;
33677c478bd9Sstevel@tonic-gate case VFLAG:
33687c478bd9Sstevel@tonic-gate Verbose++;
33697c478bd9Sstevel@tonic-gate break;
33707c478bd9Sstevel@tonic-gate case RFLAG:
33717c478bd9Sstevel@tonic-gate Firstfileattr |= 0x01;
33727c478bd9Sstevel@tonic-gate break;
33737c478bd9Sstevel@tonic-gate case HFLAG:
33747c478bd9Sstevel@tonic-gate Firstfileattr |= 0x02;
33757c478bd9Sstevel@tonic-gate break;
33767c478bd9Sstevel@tonic-gate case SFLAG:
33777c478bd9Sstevel@tonic-gate Firstfileattr |= 0x04;
33787c478bd9Sstevel@tonic-gate break;
33797c478bd9Sstevel@tonic-gate case SUNFLAG:
33807c478bd9Sstevel@tonic-gate SunBPBfields = 1;
33817c478bd9Sstevel@tonic-gate break;
33827c478bd9Sstevel@tonic-gate case LABFLAG:
33837c478bd9Sstevel@tonic-gate if (value == NULL) {
33847c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33857c478bd9Sstevel@tonic-gate } else {
33867c478bd9Sstevel@tonic-gate Label = value;
33877c478bd9Sstevel@tonic-gate }
33887c478bd9Sstevel@tonic-gate break;
33897c478bd9Sstevel@tonic-gate case BTRFLAG:
33907c478bd9Sstevel@tonic-gate if (value == NULL) {
33917c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33927c478bd9Sstevel@tonic-gate } else {
33937c478bd9Sstevel@tonic-gate BootBlkFn = value;
33947c478bd9Sstevel@tonic-gate }
33957c478bd9Sstevel@tonic-gate break;
33967c478bd9Sstevel@tonic-gate case INITFLAG:
33977c478bd9Sstevel@tonic-gate if (value == NULL) {
33987c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
33997c478bd9Sstevel@tonic-gate } else {
34007c478bd9Sstevel@tonic-gate FirstFn = value;
34017c478bd9Sstevel@tonic-gate }
34027c478bd9Sstevel@tonic-gate break;
34037c478bd9Sstevel@tonic-gate case SZFLAG:
34047c478bd9Sstevel@tonic-gate if (value == NULL) {
34057c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34067c478bd9Sstevel@tonic-gate } else {
34077c478bd9Sstevel@tonic-gate TotSize = atoi(value);
34087c478bd9Sstevel@tonic-gate GetSize = 0;
34097c478bd9Sstevel@tonic-gate }
34107c478bd9Sstevel@tonic-gate break;
34117c478bd9Sstevel@tonic-gate case SECTFLAG:
34127c478bd9Sstevel@tonic-gate if (value == NULL) {
34137c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34147c478bd9Sstevel@tonic-gate } else {
34157c478bd9Sstevel@tonic-gate SecPerTrk = atoi(value);
34167c478bd9Sstevel@tonic-gate GetSPT = 0;
34177c478bd9Sstevel@tonic-gate }
34187c478bd9Sstevel@tonic-gate break;
34197c478bd9Sstevel@tonic-gate case TRKFLAG:
34207c478bd9Sstevel@tonic-gate if (value == NULL) {
34217c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34227c478bd9Sstevel@tonic-gate } else {
34237c478bd9Sstevel@tonic-gate TrkPerCyl = atoi(value);
34247c478bd9Sstevel@tonic-gate GetTPC = 0;
34257c478bd9Sstevel@tonic-gate }
34267c478bd9Sstevel@tonic-gate break;
34277c478bd9Sstevel@tonic-gate case SPCFLAG:
34287c478bd9Sstevel@tonic-gate if (value == NULL) {
34297c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34307c478bd9Sstevel@tonic-gate } else {
34317c478bd9Sstevel@tonic-gate SecPerClust = atoi(value);
34327c478bd9Sstevel@tonic-gate GetSPC = 0;
34337c478bd9Sstevel@tonic-gate }
34347c478bd9Sstevel@tonic-gate break;
34357c478bd9Sstevel@tonic-gate case BPFFLAG:
34367c478bd9Sstevel@tonic-gate if (value == NULL) {
34377c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34387c478bd9Sstevel@tonic-gate } else {
34397c478bd9Sstevel@tonic-gate BitsPerFAT = atoi(value);
34407c478bd9Sstevel@tonic-gate GetBPF = 0;
34417c478bd9Sstevel@tonic-gate }
34427c478bd9Sstevel@tonic-gate break;
34437c478bd9Sstevel@tonic-gate case NOFDISKFLAG:
34447c478bd9Sstevel@tonic-gate DontUseFdisk = 1;
34457c478bd9Sstevel@tonic-gate break;
34467c478bd9Sstevel@tonic-gate case RESRVFLAG:
34477c478bd9Sstevel@tonic-gate if (value == NULL) {
34487c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34497c478bd9Sstevel@tonic-gate } else {
34507c478bd9Sstevel@tonic-gate Resrvd = atoi(value);
34517c478bd9Sstevel@tonic-gate GetResrvd = 0;
34527c478bd9Sstevel@tonic-gate }
34537c478bd9Sstevel@tonic-gate break;
34547c478bd9Sstevel@tonic-gate case HIDDENFLAG:
34557c478bd9Sstevel@tonic-gate if (value == NULL) {
34567c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34577c478bd9Sstevel@tonic-gate } else {
34587c478bd9Sstevel@tonic-gate RelOffset = atoi(value);
34597c478bd9Sstevel@tonic-gate GetOffset = 0;
34607c478bd9Sstevel@tonic-gate }
34617c478bd9Sstevel@tonic-gate break;
34627c478bd9Sstevel@tonic-gate case FFLAG:
34637c478bd9Sstevel@tonic-gate if (value == NULL) {
34647c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34657c478bd9Sstevel@tonic-gate } else {
34667c478bd9Sstevel@tonic-gate DiskName = value;
34677c478bd9Sstevel@tonic-gate Outputtofile = 1;
34687c478bd9Sstevel@tonic-gate }
34697c478bd9Sstevel@tonic-gate break;
34707c478bd9Sstevel@tonic-gate case DFLAG:
34717c478bd9Sstevel@tonic-gate if (value == NULL) {
34727c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]);
34737c478bd9Sstevel@tonic-gate } else {
34747c478bd9Sstevel@tonic-gate Imagesize = atoi(value);
34757c478bd9Sstevel@tonic-gate }
34767c478bd9Sstevel@tonic-gate break;
34777c478bd9Sstevel@tonic-gate default:
34787c478bd9Sstevel@tonic-gate bad_arg(value);
34797c478bd9Sstevel@tonic-gate break;
34807c478bd9Sstevel@tonic-gate }
34817c478bd9Sstevel@tonic-gate }
34827c478bd9Sstevel@tonic-gate }
34837c478bd9Sstevel@tonic-gate
34847c478bd9Sstevel@tonic-gate static
34857c478bd9Sstevel@tonic-gate void
sanity_check_options(int argc,int optind)34867c478bd9Sstevel@tonic-gate sanity_check_options(int argc, int optind)
34877c478bd9Sstevel@tonic-gate {
34887c478bd9Sstevel@tonic-gate if (GetFsParams) {
34897c478bd9Sstevel@tonic-gate if (argc - optind != 1)
34907c478bd9Sstevel@tonic-gate usage();
34917c478bd9Sstevel@tonic-gate return;
34927c478bd9Sstevel@tonic-gate }
34937c478bd9Sstevel@tonic-gate
34947c478bd9Sstevel@tonic-gate if (DontUseFdisk && GetOffset) {
34957c478bd9Sstevel@tonic-gate /* Set default relative offset of zero */
34967c478bd9Sstevel@tonic-gate RelOffset = 0;
34977c478bd9Sstevel@tonic-gate }
34987c478bd9Sstevel@tonic-gate
34997c478bd9Sstevel@tonic-gate if (BitsPerFAT == 32)
35007c478bd9Sstevel@tonic-gate MakeFAT32 = 1;
35017c478bd9Sstevel@tonic-gate
35027c478bd9Sstevel@tonic-gate if (Outputtofile && (argc - optind)) {
35037c478bd9Sstevel@tonic-gate usage();
35047c478bd9Sstevel@tonic-gate } else if (Outputtofile && !DiskName) {
35057c478bd9Sstevel@tonic-gate usage();
35067c478bd9Sstevel@tonic-gate } else if (!Outputtofile && (argc - optind != 1)) {
35077c478bd9Sstevel@tonic-gate usage();
35087c478bd9Sstevel@tonic-gate } else if (SunBPBfields && !BootBlkFn) {
35097c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
35107c478bd9Sstevel@tonic-gate gettext("Use of the 'S' option requires that\n"
3511f127cb91Sfrankho "the 'B=' option also be used.\n\n"));
35127c478bd9Sstevel@tonic-gate usage();
35137c478bd9Sstevel@tonic-gate } else if (Firstfileattr != 0x20 && !FirstFn) {
35147c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
35157c478bd9Sstevel@tonic-gate gettext("Use of the 'r', 'h', or 's' options requires\n"
3516f127cb91Sfrankho "that the 'i=' option also be used.\n\n"));
35177c478bd9Sstevel@tonic-gate usage();
35187c478bd9Sstevel@tonic-gate } else if (!GetOffset && !DontUseFdisk) {
35197c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
35207c478bd9Sstevel@tonic-gate gettext("Use of the 'hidden' option requires that\n"
3521f127cb91Sfrankho "the 'nofdisk' option also be used.\n\n"));
35227c478bd9Sstevel@tonic-gate usage();
35237c478bd9Sstevel@tonic-gate } else if (DontUseFdisk && GetSize) {
35247c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
35257c478bd9Sstevel@tonic-gate gettext("Use of the 'nofdisk' option requires that\n"
3526f127cb91Sfrankho "the 'size=' option also be used.\n\n"));
35277c478bd9Sstevel@tonic-gate usage();
35287c478bd9Sstevel@tonic-gate } else if (!GetBPF &&
3529f127cb91Sfrankho BitsPerFAT != 12 && BitsPerFAT != 16 && BitsPerFAT != 32) {
3530f127cb91Sfrankho (void) fprintf(stderr, gettext("Invalid Bits/Fat value."
3531f127cb91Sfrankho " Must be 12, 16 or 32.\n"));
35327c478bd9Sstevel@tonic-gate exit(2);
3533db92b35aSGary Mills } else if (!GetSPC && !(ISP2(SecPerClust) &&
3534db92b35aSGary Mills IN_RANGE(SecPerClust, 1, 128))) {
35357c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
35367c478bd9Sstevel@tonic-gate gettext("Invalid Sectors/Cluster value. Must be a "
3537f127cb91Sfrankho "power of 2 between 1 and 128.\n"));
35387c478bd9Sstevel@tonic-gate exit(2);
35397c478bd9Sstevel@tonic-gate } else if (!GetResrvd && (Resrvd < 1 || Resrvd > 0xffff)) {
35407c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
35417c478bd9Sstevel@tonic-gate gettext("Invalid number of reserved sectors. "
3542f127cb91Sfrankho "Must be at least 1 but\nno larger than 65535."));
35437c478bd9Sstevel@tonic-gate exit(2);
35447c478bd9Sstevel@tonic-gate } else if (!GetResrvd && MakeFAT32 &&
3545f127cb91Sfrankho (Resrvd < 32 || Resrvd > 0xffff)) {
35467c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
35477c478bd9Sstevel@tonic-gate gettext("Invalid number of reserved sectors. "
3548f127cb91Sfrankho "Must be at least 32 but\nno larger than 65535."));
35497c478bd9Sstevel@tonic-gate exit(2);
35507c478bd9Sstevel@tonic-gate } else if (Imagesize != 3 && Imagesize != 5) {
35517c478bd9Sstevel@tonic-gate usage();
35527c478bd9Sstevel@tonic-gate }
35537c478bd9Sstevel@tonic-gate }
35547c478bd9Sstevel@tonic-gate
3555c719c59aSjkennedy int
main(int argc,char ** argv)35567c478bd9Sstevel@tonic-gate main(int argc, char **argv)
35577c478bd9Sstevel@tonic-gate {
35587c478bd9Sstevel@tonic-gate off64_t AbsBootSect = 0;
35597c478bd9Sstevel@tonic-gate bpb_t dskparamblk;
35607c478bd9Sstevel@tonic-gate char *string;
35617c478bd9Sstevel@tonic-gate int fd;
35627c478bd9Sstevel@tonic-gate int c;
35637c478bd9Sstevel@tonic-gate
35647c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
35657c478bd9Sstevel@tonic-gate
35667c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
35677c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
35687c478bd9Sstevel@tonic-gate #endif
35697c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
35707c478bd9Sstevel@tonic-gate
35717c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "F:Vmo:")) != EOF) {
35727c478bd9Sstevel@tonic-gate switch (c) {
35737c478bd9Sstevel@tonic-gate case 'F':
35747c478bd9Sstevel@tonic-gate string = optarg;
35757c478bd9Sstevel@tonic-gate if (strcmp(string, "pcfs") != 0)
35767c478bd9Sstevel@tonic-gate usage();
35777c478bd9Sstevel@tonic-gate break;
35787c478bd9Sstevel@tonic-gate case 'V':
35797c478bd9Sstevel@tonic-gate {
35807c478bd9Sstevel@tonic-gate char *opt_text;
35817c478bd9Sstevel@tonic-gate int opt_count;
35827c478bd9Sstevel@tonic-gate
35837c478bd9Sstevel@tonic-gate (void) fprintf(stdout,
35847c478bd9Sstevel@tonic-gate gettext("mkfs -F pcfs "));
35857c478bd9Sstevel@tonic-gate for (opt_count = 1; opt_count < argc;
3586f127cb91Sfrankho opt_count++) {
35877c478bd9Sstevel@tonic-gate opt_text = argv[opt_count];
35887c478bd9Sstevel@tonic-gate if (opt_text)
3589f127cb91Sfrankho (void) fprintf(stdout,
3590f127cb91Sfrankho " %s ", opt_text);
35917c478bd9Sstevel@tonic-gate }
35927c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n");
35937c478bd9Sstevel@tonic-gate }
35947c478bd9Sstevel@tonic-gate break;
35957c478bd9Sstevel@tonic-gate case 'm':
35967c478bd9Sstevel@tonic-gate GetFsParams++;
35977c478bd9Sstevel@tonic-gate break;
35987c478bd9Sstevel@tonic-gate case 'o':
35997c478bd9Sstevel@tonic-gate string = optarg;
36007c478bd9Sstevel@tonic-gate parse_suboptions(string);
36017c478bd9Sstevel@tonic-gate break;
36027c478bd9Sstevel@tonic-gate }
36037c478bd9Sstevel@tonic-gate }
36047c478bd9Sstevel@tonic-gate
36057c478bd9Sstevel@tonic-gate sanity_check_options(argc, optind);
36067c478bd9Sstevel@tonic-gate
36077c478bd9Sstevel@tonic-gate if (!Outputtofile)
36087c478bd9Sstevel@tonic-gate DiskName = argv[optind];
36097c478bd9Sstevel@tonic-gate
36107c478bd9Sstevel@tonic-gate (void) memset(&dskparamblk, 0, sizeof (dskparamblk));
36117c478bd9Sstevel@tonic-gate
36127c478bd9Sstevel@tonic-gate if (GetFsParams) {
36137c478bd9Sstevel@tonic-gate fd = open_and_examine(DiskName, &dskparamblk);
36147c478bd9Sstevel@tonic-gate } else {
36157c478bd9Sstevel@tonic-gate fd = open_and_seek(DiskName, &dskparamblk, &AbsBootSect);
36167c478bd9Sstevel@tonic-gate if (ask_nicely(DiskName))
36177c478bd9Sstevel@tonic-gate write_fat(fd, AbsBootSect, BootBlkFn, Label,
36187c478bd9Sstevel@tonic-gate FirstFn, &dskparamblk);
36197c478bd9Sstevel@tonic-gate }
36207c478bd9Sstevel@tonic-gate (void) close(fd);
3621c719c59aSjkennedy return (0);
36227c478bd9Sstevel@tonic-gate }
3623