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 /* 22*db92b35aSGary Mills * Copyright (c) 2011 Gary Mills 23*db92b35aSGary 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> 417c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 427c478bd9Sstevel@tonic-gate #include "mkfs_pcfs.h" 437c478bd9Sstevel@tonic-gate #include <sys/fs/pc_fs.h> 447c478bd9Sstevel@tonic-gate #include <sys/fs/pc_dir.h> 457c478bd9Sstevel@tonic-gate #include <sys/fs/pc_label.h> 467c478bd9Sstevel@tonic-gate #include <macros.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * mkfs (for pcfs) 507c478bd9Sstevel@tonic-gate * 517c478bd9Sstevel@tonic-gate * Install a boot block, FAT, and (if desired) the first resident 527c478bd9Sstevel@tonic-gate * of the new fs. 537c478bd9Sstevel@tonic-gate * 547c478bd9Sstevel@tonic-gate * XXX -- floppy opens need O_NDELAY? 557c478bd9Sstevel@tonic-gate */ 56*db92b35aSGary Mills #define IN_RANGE(n, x, y) (((n) >= (x)) && ((n) <= (y))) 577c478bd9Sstevel@tonic-gate #define DEFAULT_LABEL "NONAME" 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate static char *BootBlkFn = NULL; 607c478bd9Sstevel@tonic-gate static char *DiskName = NULL; 617c478bd9Sstevel@tonic-gate static char *FirstFn = NULL; 627c478bd9Sstevel@tonic-gate static char *Label = NULL; 637c478bd9Sstevel@tonic-gate static char Firstfileattr = 0x20; 647c478bd9Sstevel@tonic-gate static int Outputtofile = 0; 657c478bd9Sstevel@tonic-gate static int SunBPBfields = 0; 667c478bd9Sstevel@tonic-gate static int GetFsParams = 0; 677c478bd9Sstevel@tonic-gate static int Fatentsize = 0; 687c478bd9Sstevel@tonic-gate static int Imagesize = 3; 697c478bd9Sstevel@tonic-gate static int Notreally = 0; 707c478bd9Sstevel@tonic-gate static int Verbose = 0; 717c478bd9Sstevel@tonic-gate static int MakeFAT32 = 0; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * If there is an FDISK entry for the device where we're about to 757c478bd9Sstevel@tonic-gate * make the file system, we ought to make a file system that has the 767c478bd9Sstevel@tonic-gate * same size FAT as the FDISK table claims. We track the size FDISK 777c478bd9Sstevel@tonic-gate * thinks in this variable. 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate static int FdiskFATsize = 0; 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate static int GetSize = 1; /* Unless we're given as arg, must look it up */ 827c478bd9Sstevel@tonic-gate static ulong_t TotSize; /* Total size of FS in # of sectors */ 837c478bd9Sstevel@tonic-gate static int GetSPC = 1; /* Unless we're given as arg, must calculate */ 847c478bd9Sstevel@tonic-gate static ulong_t SecPerClust; /* # of sectors per cluster */ 857c478bd9Sstevel@tonic-gate static int GetOffset = 1; /* Unless we're given as arg, must look it up */ 867c478bd9Sstevel@tonic-gate static ulong_t RelOffset; /* Relative start sector (hidden sectors) */ 877c478bd9Sstevel@tonic-gate static int GetSPT = 1; /* Unless we're given as arg, must look it up */ 887c478bd9Sstevel@tonic-gate static ushort_t SecPerTrk; /* # of sectors per track */ 897c478bd9Sstevel@tonic-gate static int GetTPC = 1; /* Unless we're given as arg, must look it up */ 907c478bd9Sstevel@tonic-gate static ushort_t TrkPerCyl; /* # of tracks per cylinder */ 917c478bd9Sstevel@tonic-gate static int GetResrvd = 1; /* Unless we're given as arg, must calculate */ 92c719c59aSjkennedy static int Resrvd; /* Number of reserved sectors */ 937c478bd9Sstevel@tonic-gate static int GetBPF = 1; /* Unless we're given as arg, must calculate */ 947c478bd9Sstevel@tonic-gate static int BitsPerFAT; /* Total size of FS in # of sectors */ 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate static ulong_t TotalClusters; /* Computed total number of clusters */ 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * Unless we are told otherwise, we should use fdisk table for non-diskettes. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate static int DontUseFdisk = 0; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1047c478bd9Sstevel@tonic-gate * Function prototypes 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate #ifndef i386 1077c478bd9Sstevel@tonic-gate static void swap_pack_grabsebpb(bpb_t *wbpb, struct _boot_sector *bsp); 1087c478bd9Sstevel@tonic-gate static void swap_pack_bpb32cpy(struct _boot_sector32 *bsp, bpb_t *wbpb); 1097c478bd9Sstevel@tonic-gate static void swap_pack_sebpbcpy(struct _boot_sector *bsp, bpb_t *wbpb); 1107c478bd9Sstevel@tonic-gate static void swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp); 1117c478bd9Sstevel@tonic-gate static void swap_pack_bpbcpy(struct _boot_sector *bsp, bpb_t *wbpb); 1127c478bd9Sstevel@tonic-gate #endif 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static uchar_t *build_rootdir(bpb_t *wbpb, char *ffn, int fffd, 1157c478bd9Sstevel@tonic-gate ulong_t ffsize, pc_cluster32_t ffstart, ulong_t *rdirsize); 116f127cb91Sfrankho static uchar_t *build_fat(bpb_t *wbpb, struct fat_od_fsi *fsinfop, 1177c478bd9Sstevel@tonic-gate ulong_t bootblksize, ulong_t *fatsize, char *ffn, int *fffd, 1187c478bd9Sstevel@tonic-gate ulong_t *ffsize, pc_cluster32_t *ffstartclust); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate static char *stat_actual_disk(char *diskname, struct stat *info, char **suffix); 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate static void compare_existing_with_computed(int fd, char *suffix, 1237c478bd9Sstevel@tonic-gate bpb_t *wbpb, int *prtsize, int *prtspc, int *prtbpf, int *prtnsect, 1247c478bd9Sstevel@tonic-gate int *prtntrk, int *prtfdisk, int *prthidden, int *prtrsrvd, 1257c478bd9Sstevel@tonic-gate int *dashos); 1267c478bd9Sstevel@tonic-gate static void print_reproducing_command(int fd, char *actualdisk, char *suffix, 1277c478bd9Sstevel@tonic-gate bpb_t *wbpb); 1287c478bd9Sstevel@tonic-gate static void compute_file_area_size(bpb_t *wbpb); 1297c478bd9Sstevel@tonic-gate static void write_fat32_bootstuff(int fd, boot_sector_t *bsp, 130f127cb91Sfrankho struct fat_od_fsi *fsinfop, off64_t seekto); 1317c478bd9Sstevel@tonic-gate static void sanity_check_options(int argc, int optind); 1327c478bd9Sstevel@tonic-gate static void compute_cluster_size(bpb_t *wbpb); 1337c478bd9Sstevel@tonic-gate static void find_fixed_details(int fd, bpb_t *wbpb); 1347c478bd9Sstevel@tonic-gate static void dirent_fname_fill(struct pcdir *dep, char *fn); 1357c478bd9Sstevel@tonic-gate static void floppy_bpb_fillin(bpb_t *wbpb, 1367c478bd9Sstevel@tonic-gate int diam, int hds, int spt); 1377c478bd9Sstevel@tonic-gate static void read_existing_bpb(int fd, bpb_t *wbpb); 1387c478bd9Sstevel@tonic-gate static void warn_funky_fatsize(void); 1397c478bd9Sstevel@tonic-gate static void warn_funky_floppy(void); 1407c478bd9Sstevel@tonic-gate static void dirent_time_fill(struct pcdir *dep); 1417c478bd9Sstevel@tonic-gate static void parse_suboptions(char *optsstr); 1427c478bd9Sstevel@tonic-gate static void header_for_dump(void); 1437c478bd9Sstevel@tonic-gate static void write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb, 144f127cb91Sfrankho struct fat_od_fsi *fsinfop, off64_t seekto); 1457c478bd9Sstevel@tonic-gate static void fill_bpb_sizes(bpb_t *wbpb, struct ipart part[], 1467c478bd9Sstevel@tonic-gate int partno, off64_t offset); 1477c478bd9Sstevel@tonic-gate static void set_fat_string(bpb_t *wbpb, int fatsize); 1487c478bd9Sstevel@tonic-gate static void partn_lecture(char *dn); 1497c478bd9Sstevel@tonic-gate static void store_16_bits(uchar_t **bp, uint32_t v); 1507c478bd9Sstevel@tonic-gate static void store_32_bits(uchar_t **bp, uint32_t v); 1517c478bd9Sstevel@tonic-gate static void lookup_floppy(struct fd_char *fdchar, bpb_t *wbpb); 1527c478bd9Sstevel@tonic-gate static void label_volume(char *lbl, bpb_t *wbpb); 1537c478bd9Sstevel@tonic-gate static void mark_cluster(uchar_t *fatp, pc_cluster32_t clustnum, 1547c478bd9Sstevel@tonic-gate uint32_t value); 1557c478bd9Sstevel@tonic-gate static void missing_arg(char *option); 1567c478bd9Sstevel@tonic-gate static void dashm_bail(int fd); 1577c478bd9Sstevel@tonic-gate static void dump_bytes(uchar_t *, int); 1587c478bd9Sstevel@tonic-gate static void write_rest(bpb_t *wbpb, char *efn, 1597c478bd9Sstevel@tonic-gate int dfd, int sfd, int remaining); 1607c478bd9Sstevel@tonic-gate static void write_fat(int fd, off64_t seekto, char *fn, char *lbl, 1617c478bd9Sstevel@tonic-gate char *ffn, bpb_t *wbpb); 1627c478bd9Sstevel@tonic-gate static void bad_arg(char *option); 1637c478bd9Sstevel@tonic-gate static void usage(void); 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate static int prepare_image_file(char *fn, bpb_t *wbpb); 1667c478bd9Sstevel@tonic-gate static int verify_bootblkfile(char *fn, boot_sector_t *bs, 1677c478bd9Sstevel@tonic-gate ulong_t *blkfilesize); 1687c478bd9Sstevel@tonic-gate static int open_and_examine(char *dn, bpb_t *wbpb); 1697c478bd9Sstevel@tonic-gate static int verify_firstfile(char *fn, ulong_t *filesize); 1707c478bd9Sstevel@tonic-gate static int lookup_FAT_size(uchar_t partid); 1717c478bd9Sstevel@tonic-gate static int open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto); 1727c478bd9Sstevel@tonic-gate static int warn_mismatch(char *desc, char *src, int expect, int assigned); 1737c478bd9Sstevel@tonic-gate static int copy_bootblk(char *fn, boot_sector_t *bootsect, 1747c478bd9Sstevel@tonic-gate ulong_t *bootblksize); 1757c478bd9Sstevel@tonic-gate static int parse_drvnum(char *pn); 1767c478bd9Sstevel@tonic-gate static int seek_nofdisk(int fd, bpb_t *wbpb, off64_t *seekto); 1777c478bd9Sstevel@tonic-gate static int ask_nicely(char *special); 1787c478bd9Sstevel@tonic-gate static int seek_partn(int fd, char *pn, bpb_t *wbpb, off64_t *seekto); 1797c478bd9Sstevel@tonic-gate static int yes(void); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * usage 1837c478bd9Sstevel@tonic-gate * 1847c478bd9Sstevel@tonic-gate * Display usage message and exit. 1857c478bd9Sstevel@tonic-gate */ 1867c478bd9Sstevel@tonic-gate static 1877c478bd9Sstevel@tonic-gate void 1887c478bd9Sstevel@tonic-gate usage(void) 1897c478bd9Sstevel@tonic-gate { 1907c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1917c478bd9Sstevel@tonic-gate gettext("pcfs usage: mkfs [-F FSType] [-V] [-m] " 1927c478bd9Sstevel@tonic-gate "[-o specific_options] special\n")); 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1957c478bd9Sstevel@tonic-gate gettext(" -V: print this command line and return\n" 1967c478bd9Sstevel@tonic-gate " -m: dump command line used to create a FAT on this media\n" 1977c478bd9Sstevel@tonic-gate "\t(other options are ignored if this option is chosen).\n" 1987c478bd9Sstevel@tonic-gate " -o: pcfs_specific_options:\n" 1997c478bd9Sstevel@tonic-gate "\t'pcfs_specific_options' is a comma separated list\n" 2007c478bd9Sstevel@tonic-gate "\tincluding one or more of the following options:\n" 2017c478bd9Sstevel@tonic-gate "\t N,v,r,h,s,b=label,B=filename,i=filename,\n" 2027c478bd9Sstevel@tonic-gate "\t spc=n,fat=n,nsect=n,ntrack=n,nofdisk,size=n,\n" 2037c478bd9Sstevel@tonic-gate "\t reserve=n,hidden=n\n\n")); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2067c478bd9Sstevel@tonic-gate gettext("'Special' should specify a raw diskette " 2077c478bd9Sstevel@tonic-gate "or raw fixed disk device. \"Fixed\"\n" 2087c478bd9Sstevel@tonic-gate "disks (which include high-capacity removable " 2097c478bd9Sstevel@tonic-gate "media such as Zip disks)\n" 2107c478bd9Sstevel@tonic-gate "may be further qualified with a logical " 2117c478bd9Sstevel@tonic-gate "drive specifier.\n" 2127c478bd9Sstevel@tonic-gate "Examples are: /dev/rdiskette and " 2137c478bd9Sstevel@tonic-gate "/dev/rdsk/c0t0d0p0:c\n")); 2147c478bd9Sstevel@tonic-gate exit(1); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate static 2187c478bd9Sstevel@tonic-gate int 2197c478bd9Sstevel@tonic-gate yes(void) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate char *affirmative = gettext("yY"); 2227c478bd9Sstevel@tonic-gate char *a = affirmative; 2237c478bd9Sstevel@tonic-gate int b; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate b = getchar(); 2267c478bd9Sstevel@tonic-gate while (b == '\n' && b != '\0' && b != EOF) 2277c478bd9Sstevel@tonic-gate b = getchar(); 2287c478bd9Sstevel@tonic-gate while (*a) { 2297c478bd9Sstevel@tonic-gate if (b == (int)*a) 2307c478bd9Sstevel@tonic-gate break; 2317c478bd9Sstevel@tonic-gate a++; 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate return (*a); 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate static 2377c478bd9Sstevel@tonic-gate int 2387c478bd9Sstevel@tonic-gate ask_nicely(char *special) 2397c478bd9Sstevel@tonic-gate { 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * 4228473 - No way to non-interactively make a pcfs filesystem 2427c478bd9Sstevel@tonic-gate * 2437c478bd9Sstevel@tonic-gate * If we don't have an input TTY, or we aren't really doing 2447c478bd9Sstevel@tonic-gate * anything, then don't ask questions. Assume a yes answer 2457c478bd9Sstevel@tonic-gate * to any questions we would ask. 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) 2487c478bd9Sstevel@tonic-gate return (1); 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate (void) printf( 2517c478bd9Sstevel@tonic-gate gettext("Construct a new FAT file system on %s: (y/n)? "), special); 2527c478bd9Sstevel@tonic-gate (void) fflush(stdout); 2537c478bd9Sstevel@tonic-gate return (yes()); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * store_16_bits 2587c478bd9Sstevel@tonic-gate * Save the lower 16 bits of a 32 bit value (v) into the provided 2597c478bd9Sstevel@tonic-gate * buffer (pointed at by *bp), and increment the buffer pointer 2607c478bd9Sstevel@tonic-gate * as well. This way the routine can be called multiple times in 2617c478bd9Sstevel@tonic-gate * succession to fill buffers. The value is stored in little-endian 2627c478bd9Sstevel@tonic-gate * order. 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate static 2657c478bd9Sstevel@tonic-gate void 2667c478bd9Sstevel@tonic-gate store_16_bits(uchar_t **bp, uint32_t v) 2677c478bd9Sstevel@tonic-gate { 2687c478bd9Sstevel@tonic-gate uchar_t *l = *bp; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate *l++ = v & 0xff; 2717c478bd9Sstevel@tonic-gate *l = (v >> 8) & 0xff; 2727c478bd9Sstevel@tonic-gate *bp += 2; 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate /* 2767c478bd9Sstevel@tonic-gate * store_32_bits 2777c478bd9Sstevel@tonic-gate * Save the 32 bit value (v) into the provided buffer (pointed 2787c478bd9Sstevel@tonic-gate * at by *bp), and increment the buffer pointer as well. This way 2797c478bd9Sstevel@tonic-gate * the routine can be called multiple times in succession to fill 2807c478bd9Sstevel@tonic-gate * buffers. The value is stored in little-endian order. 2817c478bd9Sstevel@tonic-gate */ 2827c478bd9Sstevel@tonic-gate static 2837c478bd9Sstevel@tonic-gate void 2847c478bd9Sstevel@tonic-gate store_32_bits(uchar_t **bp, uint32_t v) 2857c478bd9Sstevel@tonic-gate { 2867c478bd9Sstevel@tonic-gate uchar_t *l = *bp; 2877c478bd9Sstevel@tonic-gate int b; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate for (b = 0; b < 4; b++) { 2907c478bd9Sstevel@tonic-gate *l++ = v & 0xff; 2917c478bd9Sstevel@tonic-gate v = v >> 8; 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate *bp += 4; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * dump_bytes -- display bytes as hex numbers. 2987c478bd9Sstevel@tonic-gate * b is the pointer to the byte buffer 2997c478bd9Sstevel@tonic-gate * n is the number of bytes in the buffer 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate /* Note: BPL = bytes to display per line */ 3027c478bd9Sstevel@tonic-gate #define BPL 16 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate static 3057c478bd9Sstevel@tonic-gate void 3067c478bd9Sstevel@tonic-gate dump_bytes(uchar_t *b, int n) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate int cd = n; 3097c478bd9Sstevel@tonic-gate int cu = 0; 3107c478bd9Sstevel@tonic-gate int o = 0; 3117c478bd9Sstevel@tonic-gate int bl; 3127c478bd9Sstevel@tonic-gate int ac; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate /* Display offset, 16 bytes per line, and printable ascii version */ 3157c478bd9Sstevel@tonic-gate while (cd > 0) { 3167c478bd9Sstevel@tonic-gate ac = 0; 3177c478bd9Sstevel@tonic-gate (void) printf("\n%06x: ", o); 3187c478bd9Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++) { 3197c478bd9Sstevel@tonic-gate if (cu+bl < n) { 3207c478bd9Sstevel@tonic-gate (void) printf("%02x ", (b[cu+bl] & 0xff)); 3217c478bd9Sstevel@tonic-gate ac++; 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate else 3247c478bd9Sstevel@tonic-gate (void) printf(" "); 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++) { 3277c478bd9Sstevel@tonic-gate if ((cu+bl < n) && 3287c478bd9Sstevel@tonic-gate ((b[cu+bl] >= ' ') && (b[cu+bl] <= '~'))) 3297c478bd9Sstevel@tonic-gate (void) printf("%c", b[cu+bl]); 3307c478bd9Sstevel@tonic-gate else 3317c478bd9Sstevel@tonic-gate (void) printf("."); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate cu += ac; o += ac; cd -= ac; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate (void) printf("\n\n"); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* 3397c478bd9Sstevel@tonic-gate * header_for_dump -- display simple header over what will be output. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate static 3427c478bd9Sstevel@tonic-gate void 3437c478bd9Sstevel@tonic-gate header_for_dump(void) 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate int bl; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate (void) printf("\n "); 3487c478bd9Sstevel@tonic-gate for (bl = 0; bl < BPL; bl++) 3497c478bd9Sstevel@tonic-gate (void) printf("%02x ", bl); 3507c478bd9Sstevel@tonic-gate (void) printf("\n "); 3517c478bd9Sstevel@tonic-gate bl = 3*BPL; 3527c478bd9Sstevel@tonic-gate while (bl-- > 0) 3537c478bd9Sstevel@tonic-gate (void) printf("-"); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * parse_drvnum 3587c478bd9Sstevel@tonic-gate * Convert a partition name into a drive number. 3597c478bd9Sstevel@tonic-gate */ 3607c478bd9Sstevel@tonic-gate static 3617c478bd9Sstevel@tonic-gate int 3627c478bd9Sstevel@tonic-gate parse_drvnum(char *pn) 3637c478bd9Sstevel@tonic-gate { 3647c478bd9Sstevel@tonic-gate int drvnum; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate /* 3677c478bd9Sstevel@tonic-gate * Determine logical drive to seek after. 3687c478bd9Sstevel@tonic-gate */ 3697c478bd9Sstevel@tonic-gate if (strlen(pn) == 1 && *pn >= 'c' && *pn <= 'z') { 3707c478bd9Sstevel@tonic-gate drvnum = *pn - 'c' + 1; 3717c478bd9Sstevel@tonic-gate } else if (*pn >= '0' && *pn <= '9') { 3727c478bd9Sstevel@tonic-gate char *d; 3737c478bd9Sstevel@tonic-gate int v, m, c; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate v = 0; 3767c478bd9Sstevel@tonic-gate d = pn; 3777c478bd9Sstevel@tonic-gate while (*d && *d >= '0' && *d <= '9') { 3787c478bd9Sstevel@tonic-gate c = strlen(d); 3797c478bd9Sstevel@tonic-gate m = 1; 3807c478bd9Sstevel@tonic-gate while (--c) 3817c478bd9Sstevel@tonic-gate m *= 10; 3827c478bd9Sstevel@tonic-gate v += m * (*d - '0'); 3837c478bd9Sstevel@tonic-gate d++; 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate if (*d || v > 24) { 3877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3887c478bd9Sstevel@tonic-gate gettext("%s: bogus logical drive specification.\n"), 3897c478bd9Sstevel@tonic-gate pn); 3907c478bd9Sstevel@tonic-gate return (-1); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate drvnum = v; 3937c478bd9Sstevel@tonic-gate } else if (strcmp(pn, "boot") == 0) { 3947c478bd9Sstevel@tonic-gate drvnum = 99; 3957c478bd9Sstevel@tonic-gate } else { 3967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3977c478bd9Sstevel@tonic-gate gettext("%s: bogus logical drive specification.\n"), pn); 3987c478bd9Sstevel@tonic-gate return (-1); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate return (drvnum); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate 4047c478bd9Sstevel@tonic-gate /* 4057c478bd9Sstevel@tonic-gate * Define some special logical drives we use. 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate #define BOOT_PARTITION_DRIVE 99 4087c478bd9Sstevel@tonic-gate #define PRIMARY_DOS_DRIVE 1 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* 4117c478bd9Sstevel@tonic-gate * isDosDrive() 4127c478bd9Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition 4137c478bd9Sstevel@tonic-gate * and it decides if that's a systid that describes a DOS drive. We 4147c478bd9Sstevel@tonic-gate * use systid values defined in sys/dktp/fdisk.h. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate static int 4177c478bd9Sstevel@tonic-gate isDosDrive(uchar_t checkMe) 4187c478bd9Sstevel@tonic-gate { 4197c478bd9Sstevel@tonic-gate return ((checkMe == DOSOS12) || (checkMe == DOSOS16) || 4207c478bd9Sstevel@tonic-gate (checkMe == DOSHUGE) || (checkMe == FDISK_WINDOWS) || 4217c478bd9Sstevel@tonic-gate (checkMe == FDISK_EXT_WIN) || (checkMe == FDISK_FAT95) || 4227c478bd9Sstevel@tonic-gate (checkMe == DIAGPART)); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * isDosExtended() 4277c478bd9Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition 4287c478bd9Sstevel@tonic-gate * and it decides if that's a systid that describes an extended DOS 4297c478bd9Sstevel@tonic-gate * partition. 4307c478bd9Sstevel@tonic-gate */ 4317c478bd9Sstevel@tonic-gate static int 4327c478bd9Sstevel@tonic-gate isDosExtended(uchar_t checkMe) 4337c478bd9Sstevel@tonic-gate { 4347c478bd9Sstevel@tonic-gate return ((checkMe == EXTDOS) || (checkMe == FDISK_EXTLBA)); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * isBootPart() 4397c478bd9Sstevel@tonic-gate * Boolean function. Give it the systid field for an fdisk partition 4407c478bd9Sstevel@tonic-gate * and it decides if that's a systid that describes a Solaris boot 4417c478bd9Sstevel@tonic-gate * partition. 4427c478bd9Sstevel@tonic-gate */ 4437c478bd9Sstevel@tonic-gate static int 4447c478bd9Sstevel@tonic-gate isBootPart(uchar_t checkMe) 4457c478bd9Sstevel@tonic-gate { 4467c478bd9Sstevel@tonic-gate return (checkMe == X86BOOT); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate static 4507c478bd9Sstevel@tonic-gate int 4517c478bd9Sstevel@tonic-gate warn_mismatch(char *desc, char *src, int expect, int assigned) 4527c478bd9Sstevel@tonic-gate { 4537c478bd9Sstevel@tonic-gate if (expect == assigned) 4547c478bd9Sstevel@tonic-gate return (assigned); 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* 4577c478bd9Sstevel@tonic-gate * 4228473 - No way to non-interactively make a pcfs filesystem 4587c478bd9Sstevel@tonic-gate * 4597c478bd9Sstevel@tonic-gate * If we don't have an input TTY, or we aren't really doing 4607c478bd9Sstevel@tonic-gate * anything, then don't ask questions. Assume a yes answer 4617c478bd9Sstevel@tonic-gate * to any questions we would ask. 4627c478bd9Sstevel@tonic-gate */ 4637c478bd9Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) { 4647c478bd9Sstevel@tonic-gate (void) printf(gettext("WARNING: User supplied %s is %d," 4657c478bd9Sstevel@tonic-gate "\nbut value obtained from the %s is %d.\n" 4667c478bd9Sstevel@tonic-gate "Using user supplied value.\n"), 4677c478bd9Sstevel@tonic-gate desc, assigned, src, expect); 4687c478bd9Sstevel@tonic-gate return (assigned); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate (void) printf(gettext("User supplied %s is %d." 4727c478bd9Sstevel@tonic-gate "\nThe value obtained from the %s is %d.\n"), 4737c478bd9Sstevel@tonic-gate desc, assigned, src, expect); 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate (void) printf( 4767c478bd9Sstevel@tonic-gate gettext("Continue with value given on command line (y/n)? ")); 4777c478bd9Sstevel@tonic-gate (void) fflush(stdout); 4787c478bd9Sstevel@tonic-gate if (yes()) 4797c478bd9Sstevel@tonic-gate return (assigned); 4807c478bd9Sstevel@tonic-gate else 4817c478bd9Sstevel@tonic-gate exit(2); 4827c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4837c478bd9Sstevel@tonic-gate } 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate static 4867c478bd9Sstevel@tonic-gate void 4877c478bd9Sstevel@tonic-gate fill_fat32_bpb(bpb_t *wbpb) 4887c478bd9Sstevel@tonic-gate { 4897c478bd9Sstevel@tonic-gate /* 4907c478bd9Sstevel@tonic-gate * ExtFlags means (according to MSDN BPB (FAT32) document) 4917c478bd9Sstevel@tonic-gate * 4927c478bd9Sstevel@tonic-gate * Bit 8 indicates info written to the active FAT is written 4937c478bd9Sstevel@tonic-gate * to all copies of the FAT. (I think they mean bit 7, with 4947c478bd9Sstevel@tonic-gate * numbering starting at 0) 4957c478bd9Sstevel@tonic-gate * 4967c478bd9Sstevel@tonic-gate * Lowest 4 bits of field are the 0 based FAT number of the 4977c478bd9Sstevel@tonic-gate * Active FAT. (only meaningful if bit 8 is set) 4987c478bd9Sstevel@tonic-gate * 4997c478bd9Sstevel@tonic-gate * Field contains combination of these values: 5007c478bd9Sstevel@tonic-gate * 5017c478bd9Sstevel@tonic-gate * VALUE DESCRIPTION 5027c478bd9Sstevel@tonic-gate * BGBPB_F_ActiveFATMsk Mask for low four bits 5037c478bd9Sstevel@tonic-gate * (0x000F) 5047c478bd9Sstevel@tonic-gate * BGBPB_F_NoFATMirror If set FAT mirroring disabled. 5057c478bd9Sstevel@tonic-gate * (0x0080) If clear, FAT mirroring enabled. 5067c478bd9Sstevel@tonic-gate * 5077c478bd9Sstevel@tonic-gate * We set the value based on what I've seen on all the FAT32 drives 5087c478bd9Sstevel@tonic-gate * I've seen created by Windows. 5097c478bd9Sstevel@tonic-gate * 5107c478bd9Sstevel@tonic-gate */ 5117c478bd9Sstevel@tonic-gate wbpb->bpb32.ext_flags = 0x0; 5127c478bd9Sstevel@tonic-gate /* 5137c478bd9Sstevel@tonic-gate * No real explanation of the fs_vers file in the BPB doc. The 5147c478bd9Sstevel@tonic-gate * high byte is supposed to be the major version and the low the 5157c478bd9Sstevel@tonic-gate * minor version. Again I set according to what I've seen on Windows. 5167c478bd9Sstevel@tonic-gate */ 5177c478bd9Sstevel@tonic-gate wbpb->bpb32.fs_vers_lo = '\0'; 5187c478bd9Sstevel@tonic-gate wbpb->bpb32.fs_vers_hi = '\0'; 5197c478bd9Sstevel@tonic-gate /* 5207c478bd9Sstevel@tonic-gate * The convention appears to be to place the fs info sector 5217c478bd9Sstevel@tonic-gate * immediately after the boot sector, and that the backup boot 5227c478bd9Sstevel@tonic-gate * sector should be at sector 6. (based on what I see with 5237c478bd9Sstevel@tonic-gate * Windows) 5247c478bd9Sstevel@tonic-gate */ 5257c478bd9Sstevel@tonic-gate wbpb->bpb32.fsinfosec = 1; 5267c478bd9Sstevel@tonic-gate wbpb->bpb32.backupboot = 6; 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate static 5307c478bd9Sstevel@tonic-gate void 5317c478bd9Sstevel@tonic-gate fill_bpb_sizes(bpb_t *wbpb, struct ipart part[], int partno, off64_t offset) 5327c478bd9Sstevel@tonic-gate { 5337c478bd9Sstevel@tonic-gate ulong_t usesize; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate if (GetFsParams || GetSize) { 5367c478bd9Sstevel@tonic-gate usesize = ltohi(part[partno].numsect); 5377c478bd9Sstevel@tonic-gate if (Verbose) { 5387c478bd9Sstevel@tonic-gate (void) printf( 5397c478bd9Sstevel@tonic-gate gettext("Partition size (from FDISK table) " 5407c478bd9Sstevel@tonic-gate "= %d sectors.\n"), usesize); 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate } else { 5437c478bd9Sstevel@tonic-gate usesize = warn_mismatch( 5447c478bd9Sstevel@tonic-gate gettext("length of partition (in sectors)"), 5457c478bd9Sstevel@tonic-gate gettext("FDISK table"), 5467c478bd9Sstevel@tonic-gate ltohi(part[partno].numsect), TotSize); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if (GetFsParams) { 5507c478bd9Sstevel@tonic-gate TotSize = usesize; 5517c478bd9Sstevel@tonic-gate } else { 5527c478bd9Sstevel@tonic-gate if (usesize > 0xffff) 5537c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 0; 5547c478bd9Sstevel@tonic-gate else 5557c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = usesize; 5567c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = usesize; 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate wbpb->bpb.hidden_sectors = offset; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate if (GetFsParams) { 5627c478bd9Sstevel@tonic-gate RelOffset = offset; 5637c478bd9Sstevel@tonic-gate } else { 5647c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = offset >> 16; 5657c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = offset & 0xFFFF; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate } 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate /* 5707c478bd9Sstevel@tonic-gate * lookup_FAT_size 5717c478bd9Sstevel@tonic-gate * 5727c478bd9Sstevel@tonic-gate * Given the FDISK partition file system identifier, return the 5737c478bd9Sstevel@tonic-gate * expected FAT size for the partition. 5747c478bd9Sstevel@tonic-gate */ 5757c478bd9Sstevel@tonic-gate static 5767c478bd9Sstevel@tonic-gate int 5777c478bd9Sstevel@tonic-gate lookup_FAT_size(uchar_t partid) 5787c478bd9Sstevel@tonic-gate { 5797c478bd9Sstevel@tonic-gate int rval; 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate switch (partid) { 5827c478bd9Sstevel@tonic-gate case DOSOS12: 5837c478bd9Sstevel@tonic-gate rval = 12; 5847c478bd9Sstevel@tonic-gate break; 5857c478bd9Sstevel@tonic-gate case DOSOS16: 5867c478bd9Sstevel@tonic-gate case DOSHUGE: 5877c478bd9Sstevel@tonic-gate case FDISK_FAT95: 5887c478bd9Sstevel@tonic-gate case X86BOOT: 5897c478bd9Sstevel@tonic-gate rval = 16; 5907c478bd9Sstevel@tonic-gate break; 5917c478bd9Sstevel@tonic-gate case FDISK_WINDOWS: 5927c478bd9Sstevel@tonic-gate case FDISK_EXT_WIN: 5937c478bd9Sstevel@tonic-gate rval = 32; 5947c478bd9Sstevel@tonic-gate break; 5957c478bd9Sstevel@tonic-gate case EXTDOS: 5967c478bd9Sstevel@tonic-gate case FDISK_EXTLBA: 5977c478bd9Sstevel@tonic-gate default: 5987c478bd9Sstevel@tonic-gate rval = -1; 5997c478bd9Sstevel@tonic-gate break; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate return (rval); 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate /* 6067c478bd9Sstevel@tonic-gate * seek_partn 6077c478bd9Sstevel@tonic-gate * 6087c478bd9Sstevel@tonic-gate * Seek to the beginning of the partition where we need to install 6097c478bd9Sstevel@tonic-gate * the new FAT. Zero return for any error, but print error 6107c478bd9Sstevel@tonic-gate * messages here. 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate static 6137c478bd9Sstevel@tonic-gate int 6147c478bd9Sstevel@tonic-gate seek_partn(int fd, char *pn, bpb_t *wbpb, off64_t *seekto) 6157c478bd9Sstevel@tonic-gate { 6167c478bd9Sstevel@tonic-gate struct ipart part[FD_NUMPART]; 6177c478bd9Sstevel@tonic-gate struct mboot extmboot; 6187c478bd9Sstevel@tonic-gate struct mboot mb; 619342440ecSPrasad Singamsetty diskaddr_t xstartsect; 6207c478bd9Sstevel@tonic-gate off64_t nextseek = 0; 6217c478bd9Sstevel@tonic-gate off64_t lastseek = 0; 6227c478bd9Sstevel@tonic-gate int logicalDriveCount = 0; 6237c478bd9Sstevel@tonic-gate int extendedPart = -1; 6247c478bd9Sstevel@tonic-gate int primaryPart = -1; 6257c478bd9Sstevel@tonic-gate int bootPart = -1; 626342440ecSPrasad Singamsetty uint32_t xnumsect = 0; 6277c478bd9Sstevel@tonic-gate int drvnum; 6287c478bd9Sstevel@tonic-gate int driveIndex; 6297c478bd9Sstevel@tonic-gate int i; 6307c478bd9Sstevel@tonic-gate /* 6317c478bd9Sstevel@tonic-gate * Count of drives in the current extended partition's 6327c478bd9Sstevel@tonic-gate * FDISK table, and indexes of the drives themselves. 6337c478bd9Sstevel@tonic-gate */ 6347c478bd9Sstevel@tonic-gate int extndDrives[FD_NUMPART]; 6357c478bd9Sstevel@tonic-gate int numDrives = 0; 6367c478bd9Sstevel@tonic-gate /* 6377c478bd9Sstevel@tonic-gate * Count of drives (beyond primary) in master boot record's 6387c478bd9Sstevel@tonic-gate * FDISK table, and indexes of the drives themselves. 6397c478bd9Sstevel@tonic-gate */ 6407c478bd9Sstevel@tonic-gate int extraDrives[FD_NUMPART]; 6417c478bd9Sstevel@tonic-gate int numExtraDrives = 0; 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate if ((drvnum = parse_drvnum(pn)) < 0) 6447c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate if (read(fd, &mb, sizeof (mb)) != sizeof (mb)) { 6477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6487c478bd9Sstevel@tonic-gate gettext("Couldn't read a Master Boot Record?!\n")); 6497c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate if (ltohs(mb.signature) != BOOTSECSIG) { 6537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6547c478bd9Sstevel@tonic-gate gettext("Bad Sig on master boot record!\n")); 6557c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate *seekto = 0; 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate /* 6617c478bd9Sstevel@tonic-gate * Copy partition table into memory 6627c478bd9Sstevel@tonic-gate */ 6637c478bd9Sstevel@tonic-gate (void) memcpy(part, mb.parts, sizeof (part)); 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate /* 6667c478bd9Sstevel@tonic-gate * Get a summary of what is in the Master FDISK table. 6677c478bd9Sstevel@tonic-gate * Normally we expect to find one partition marked as a DOS drive. 6687c478bd9Sstevel@tonic-gate * This partition is the one Windows calls the primary dos partition. 6697c478bd9Sstevel@tonic-gate * If the machine has any logical drives then we also expect 6707c478bd9Sstevel@tonic-gate * to find a partition marked as an extended DOS partition. 6717c478bd9Sstevel@tonic-gate * 6727c478bd9Sstevel@tonic-gate * Sometimes we'll find multiple partitions marked as DOS drives. 6737c478bd9Sstevel@tonic-gate * The Solaris fdisk program allows these partitions 6747c478bd9Sstevel@tonic-gate * to be created, but Windows fdisk no longer does. We still need 6757c478bd9Sstevel@tonic-gate * to support these, though, since Windows does. We also need to fix 6767c478bd9Sstevel@tonic-gate * our fdisk to behave like the Windows version. 6777c478bd9Sstevel@tonic-gate * 6787c478bd9Sstevel@tonic-gate * It turns out that some off-the-shelf media have *only* an 6797c478bd9Sstevel@tonic-gate * Extended partition, so we need to deal with that case as 6807c478bd9Sstevel@tonic-gate * well. 6817c478bd9Sstevel@tonic-gate * 6827c478bd9Sstevel@tonic-gate * Only a single (the first) Extended or Boot Partition will 6837c478bd9Sstevel@tonic-gate * be recognized. Any others will be ignored. 6847c478bd9Sstevel@tonic-gate */ 6857c478bd9Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 6867c478bd9Sstevel@tonic-gate if (isDosDrive(part[i].systid)) { 6877c478bd9Sstevel@tonic-gate if (primaryPart < 0) { 6887c478bd9Sstevel@tonic-gate logicalDriveCount++; 6897c478bd9Sstevel@tonic-gate primaryPart = i; 6907c478bd9Sstevel@tonic-gate } else { 6917c478bd9Sstevel@tonic-gate extraDrives[numExtraDrives++] = i; 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate continue; 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate if ((extendedPart < 0) && isDosExtended(part[i].systid)) { 6967c478bd9Sstevel@tonic-gate extendedPart = i; 6977c478bd9Sstevel@tonic-gate continue; 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate if ((bootPart < 0) && isBootPart(part[i].systid)) { 7007c478bd9Sstevel@tonic-gate bootPart = i; 7017c478bd9Sstevel@tonic-gate continue; 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate if (drvnum == BOOT_PARTITION_DRIVE) { 7067c478bd9Sstevel@tonic-gate if (bootPart < 0) { 7077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7087c478bd9Sstevel@tonic-gate gettext("No boot partition found on drive\n")); 7097c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate if ((*seekto = ltohi(part[bootPart].relsect)) == 0) { 7127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? " 7137c478bd9Sstevel@tonic-gate "A boot partition starting\nat sector 0 would " 7147c478bd9Sstevel@tonic-gate "collide with the FDISK table!\n")); 7157c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, bootPart, *seekto); 7197c478bd9Sstevel@tonic-gate *seekto *= BPSEC; 7207c478bd9Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size(part[bootPart].systid); 7217c478bd9Sstevel@tonic-gate if (Verbose) 7227c478bd9Sstevel@tonic-gate (void) printf(gettext("Boot partition's offset: " 7237c478bd9Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC); 7247c478bd9Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 7257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Partition %s: "), pn); 7267c478bd9Sstevel@tonic-gate perror(""); 7277c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate return (PART_FOUND); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate 7327c478bd9Sstevel@tonic-gate if (drvnum == PRIMARY_DOS_DRIVE && primaryPart >= 0) { 7337c478bd9Sstevel@tonic-gate if ((*seekto = ltohi(part[primaryPart].relsect)) == 0) { 7347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? " 7357c478bd9Sstevel@tonic-gate "A partition starting\nat sector 0 would " 7367c478bd9Sstevel@tonic-gate "collide with the FDISK table!\n")); 7377c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, primaryPart, *seekto); 7417c478bd9Sstevel@tonic-gate *seekto *= BPSEC; 7427c478bd9Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size(part[primaryPart].systid); 7437c478bd9Sstevel@tonic-gate if (Verbose) 7447c478bd9Sstevel@tonic-gate (void) printf(gettext("Partition's offset: " 7457c478bd9Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC); 7467c478bd9Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 7477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Partition %s: "), pn); 7487c478bd9Sstevel@tonic-gate perror(""); 7497c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate return (PART_FOUND); 7527c478bd9Sstevel@tonic-gate } 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate /* 7557c478bd9Sstevel@tonic-gate * We are not looking for the C: drive (or there was no primary 7567c478bd9Sstevel@tonic-gate * drive found), so we had better have an extended partition or 7577c478bd9Sstevel@tonic-gate * extra drives in the Master FDISK table. 7587c478bd9Sstevel@tonic-gate */ 7597c478bd9Sstevel@tonic-gate if ((extendedPart < 0) && (numExtraDrives == 0)) { 7607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7617c478bd9Sstevel@tonic-gate gettext("No such logical drive " 7627c478bd9Sstevel@tonic-gate "(missing extended partition entry)\n")); 7637c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate if (extendedPart >= 0) { 7677c478bd9Sstevel@tonic-gate nextseek = xstartsect = ltohi(part[extendedPart].relsect); 7687c478bd9Sstevel@tonic-gate xnumsect = ltohi(part[extendedPart].numsect); 7697c478bd9Sstevel@tonic-gate do { 7707c478bd9Sstevel@tonic-gate /* 7717c478bd9Sstevel@tonic-gate * If the seek would not cause us to change 7727c478bd9Sstevel@tonic-gate * position on the drive, then we're out of 7737c478bd9Sstevel@tonic-gate * extended partitions to examine. 7747c478bd9Sstevel@tonic-gate */ 7757c478bd9Sstevel@tonic-gate if (nextseek == lastseek) 7767c478bd9Sstevel@tonic-gate break; 7777c478bd9Sstevel@tonic-gate logicalDriveCount += numDrives; 7787c478bd9Sstevel@tonic-gate /* 7797c478bd9Sstevel@tonic-gate * Seek the next extended partition, and find 7807c478bd9Sstevel@tonic-gate * logical drives within it. 7817c478bd9Sstevel@tonic-gate */ 7827c478bd9Sstevel@tonic-gate if (lseek64(fd, nextseek * BPSEC, SEEK_SET) < 0 || 7837c478bd9Sstevel@tonic-gate read(fd, &extmboot, sizeof (extmboot)) != 7847c478bd9Sstevel@tonic-gate sizeof (extmboot)) { 7857c478bd9Sstevel@tonic-gate perror(gettext("Unable to read extended " 7867c478bd9Sstevel@tonic-gate "partition record")); 7877c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate (void) memcpy(part, extmboot.parts, sizeof (part)); 7907c478bd9Sstevel@tonic-gate lastseek = nextseek; 7917c478bd9Sstevel@tonic-gate if (ltohs(extmboot.signature) != MBB_MAGIC) { 7927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7937c478bd9Sstevel@tonic-gate gettext("Bad signature on " 7947c478bd9Sstevel@tonic-gate "extended partition\n")); 7957c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 7967c478bd9Sstevel@tonic-gate } 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * Count up drives, and track where the next 7997c478bd9Sstevel@tonic-gate * extended partition is in case we need it. We 8007c478bd9Sstevel@tonic-gate * are expecting only one extended partition. If 8017c478bd9Sstevel@tonic-gate * there is more than one we'll only go to the 8027c478bd9Sstevel@tonic-gate * first one we see, but warn about ignoring. 8037c478bd9Sstevel@tonic-gate */ 8047c478bd9Sstevel@tonic-gate numDrives = 0; 8057c478bd9Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 8067c478bd9Sstevel@tonic-gate if (isDosDrive(part[i].systid)) { 8077c478bd9Sstevel@tonic-gate extndDrives[numDrives++] = i; 8087c478bd9Sstevel@tonic-gate continue; 8097c478bd9Sstevel@tonic-gate } else if (isDosExtended(part[i].systid)) { 8107c478bd9Sstevel@tonic-gate if (nextseek != lastseek) { 8117c478bd9Sstevel@tonic-gate /* 8127c478bd9Sstevel@tonic-gate * Already found an extended 8137c478bd9Sstevel@tonic-gate * partition in this table. 8147c478bd9Sstevel@tonic-gate */ 8157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8167c478bd9Sstevel@tonic-gate gettext("WARNING: " 8177c478bd9Sstevel@tonic-gate "Ignoring unexpected " 8187c478bd9Sstevel@tonic-gate "additional extended " 8197c478bd9Sstevel@tonic-gate "partition")); 8207c478bd9Sstevel@tonic-gate continue; 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate nextseek = xstartsect + 8237c478bd9Sstevel@tonic-gate ltohi(part[i].relsect); 8247c478bd9Sstevel@tonic-gate continue; 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate } while (drvnum > logicalDriveCount + numDrives); 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate if (drvnum <= logicalDriveCount + numDrives) { 8307c478bd9Sstevel@tonic-gate /* 8317c478bd9Sstevel@tonic-gate * The number of logical drives we've found thus 8327c478bd9Sstevel@tonic-gate * far is enough to get us to the one we were 8337c478bd9Sstevel@tonic-gate * searching for. 8347c478bd9Sstevel@tonic-gate */ 8357c478bd9Sstevel@tonic-gate driveIndex = logicalDriveCount + numDrives - drvnum; 8367c478bd9Sstevel@tonic-gate *seekto = 8377c478bd9Sstevel@tonic-gate ltohi(part[extndDrives[driveIndex]].relsect) + 8387c478bd9Sstevel@tonic-gate lastseek; 8397c478bd9Sstevel@tonic-gate if (*seekto == lastseek) { 8407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8417c478bd9Sstevel@tonic-gate gettext("Bogus FDISK entry? A logical " 8427c478bd9Sstevel@tonic-gate "drive starting at\nsector 0x%llx would " 8437c478bd9Sstevel@tonic-gate "collide with the\nFDISK information in " 8447c478bd9Sstevel@tonic-gate "that sector.\n"), *seekto); 8457c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 8467c478bd9Sstevel@tonic-gate } else if (*seekto <= xstartsect || 8477c478bd9Sstevel@tonic-gate *seekto >= (xstartsect + xnumsect)) { 8487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8497c478bd9Sstevel@tonic-gate gettext("Bogus FDISK entry? " 8507c478bd9Sstevel@tonic-gate "Logical drive start sector (0x%llx)\n" 8517c478bd9Sstevel@tonic-gate "not within extended partition! " 8527c478bd9Sstevel@tonic-gate "(Expected in range 0x%x - 0x%x)\n"), 8537c478bd9Sstevel@tonic-gate *seekto, xstartsect + 1, 8547c478bd9Sstevel@tonic-gate xstartsect + xnumsect - 1); 8557c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, extndDrives[driveIndex], 8587c478bd9Sstevel@tonic-gate *seekto); 8597c478bd9Sstevel@tonic-gate *seekto *= BPSEC; 8607c478bd9Sstevel@tonic-gate FdiskFATsize = lookup_FAT_size( 8617c478bd9Sstevel@tonic-gate part[extndDrives[driveIndex]].systid); 8627c478bd9Sstevel@tonic-gate if (Verbose) 8637c478bd9Sstevel@tonic-gate (void) printf(gettext("Partition's offset: " 8647c478bd9Sstevel@tonic-gate "Sector 0x%x.\n"), *seekto/BPSEC); 8657c478bd9Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 8667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 8677c478bd9Sstevel@tonic-gate gettext("Partition %s: "), pn); 8687c478bd9Sstevel@tonic-gate perror(""); 8697c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate return (PART_FOUND); 8727c478bd9Sstevel@tonic-gate } else { 8737c478bd9Sstevel@tonic-gate /* 8747c478bd9Sstevel@tonic-gate * We ran out of extended dos partition 8757c478bd9Sstevel@tonic-gate * drives. The only hope now is to go 8767c478bd9Sstevel@tonic-gate * back to extra drives defined in the master 8777c478bd9Sstevel@tonic-gate * fdisk table. But we overwrote that table 8787c478bd9Sstevel@tonic-gate * already, so we must load it in again. 8797c478bd9Sstevel@tonic-gate */ 8807c478bd9Sstevel@tonic-gate logicalDriveCount += numDrives; 8817c478bd9Sstevel@tonic-gate (void) memcpy(part, mb.parts, sizeof (part)); 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate /* 8857c478bd9Sstevel@tonic-gate * Still haven't found the drive, is it an extra 8867c478bd9Sstevel@tonic-gate * drive defined in the main FDISK table? 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate if (drvnum <= logicalDriveCount + numExtraDrives) { 8897c478bd9Sstevel@tonic-gate driveIndex = logicalDriveCount + numExtraDrives - drvnum; 8907c478bd9Sstevel@tonic-gate *seekto = ltohi(part[extraDrives[driveIndex]].relsect); 8917c478bd9Sstevel@tonic-gate if (*seekto == 0) { 8927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bogus FDISK entry? " 8937c478bd9Sstevel@tonic-gate "A partition starting\nat sector 0 would " 8947c478bd9Sstevel@tonic-gate "collide with the FDISK table!\n")); 8957c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate fill_bpb_sizes(wbpb, part, extraDrives[driveIndex], *seekto); 8997c478bd9Sstevel@tonic-gate *seekto *= BPSEC; 9007c478bd9Sstevel@tonic-gate FdiskFATsize = 9017c478bd9Sstevel@tonic-gate lookup_FAT_size(part[extraDrives[driveIndex]].systid); 9027c478bd9Sstevel@tonic-gate if (Verbose) 9037c478bd9Sstevel@tonic-gate (void) printf(gettext("Partition's offset: " 9047c478bd9Sstevel@tonic-gate "Sector %x.\n"), *seekto/BPSEC); 9057c478bd9Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 9067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 9077c478bd9Sstevel@tonic-gate gettext("Partition %s: "), pn); 9087c478bd9Sstevel@tonic-gate perror(""); 9097c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate return (PART_FOUND); 9127c478bd9Sstevel@tonic-gate } 9137c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("No such logical drive\n")); 9147c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate /* 9187c478bd9Sstevel@tonic-gate * seek_nofdisk 9197c478bd9Sstevel@tonic-gate * 9207c478bd9Sstevel@tonic-gate * User is asking us to trust them that they know best. 9217c478bd9Sstevel@tonic-gate * We basically won't do much seeking here, the only seeking we'll do 9227c478bd9Sstevel@tonic-gate * is if the 'hidden' parameter was given. 9237c478bd9Sstevel@tonic-gate */ 9247c478bd9Sstevel@tonic-gate static 9257c478bd9Sstevel@tonic-gate int 9267c478bd9Sstevel@tonic-gate seek_nofdisk(int fd, bpb_t *wbpb, off64_t *seekto) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate if (TotSize > 0xffff) 9297c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 0; 9307c478bd9Sstevel@tonic-gate else 9317c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = (short)TotSize; 9327c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = TotSize; 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate *seekto = RelOffset * BPSEC; 9357c478bd9Sstevel@tonic-gate wbpb->bpb.hidden_sectors = RelOffset; 9367c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = RelOffset >> 16; 9377c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = RelOffset & 0xFFFF; 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate if (Verbose) 9407c478bd9Sstevel@tonic-gate (void) printf(gettext("Requested offset: Sector %x.\n"), 9417c478bd9Sstevel@tonic-gate *seekto/BPSEC); 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate if (lseek64(fd, *seekto, SEEK_SET) < 0) { 9447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 9457c478bd9Sstevel@tonic-gate gettext("User specified start sector %d"), RelOffset); 9467c478bd9Sstevel@tonic-gate perror(""); 9477c478bd9Sstevel@tonic-gate return (PART_NOT_FOUND); 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate return (PART_FOUND); 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate /* 9537c478bd9Sstevel@tonic-gate * set_fat_string 9547c478bd9Sstevel@tonic-gate * 9557c478bd9Sstevel@tonic-gate * Fill in the type string of the FAT 9567c478bd9Sstevel@tonic-gate */ 9577c478bd9Sstevel@tonic-gate static 9587c478bd9Sstevel@tonic-gate void 9597c478bd9Sstevel@tonic-gate set_fat_string(bpb_t *wbpb, int fatsize) 9607c478bd9Sstevel@tonic-gate { 9617c478bd9Sstevel@tonic-gate if (fatsize == 12) { 9627c478bd9Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT12_TYPE_STRING, 9637c478bd9Sstevel@tonic-gate strlen(FAT12_TYPE_STRING)); 9647c478bd9Sstevel@tonic-gate } else if (fatsize == 16) { 9657c478bd9Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT16_TYPE_STRING, 9667c478bd9Sstevel@tonic-gate strlen(FAT16_TYPE_STRING)); 9677c478bd9Sstevel@tonic-gate } else { 9687c478bd9Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, FAT32_TYPE_STRING, 9697c478bd9Sstevel@tonic-gate strlen(FAT32_TYPE_STRING)); 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate /* 9747c478bd9Sstevel@tonic-gate * prepare_image_file 9757c478bd9Sstevel@tonic-gate * 9767c478bd9Sstevel@tonic-gate * Open the file that will hold the image (as opposed to the image 9777c478bd9Sstevel@tonic-gate * being written to the boot sector of an actual disk). 9787c478bd9Sstevel@tonic-gate */ 9797c478bd9Sstevel@tonic-gate static 9807c478bd9Sstevel@tonic-gate int 9817c478bd9Sstevel@tonic-gate prepare_image_file(char *fn, bpb_t *wbpb) 9827c478bd9Sstevel@tonic-gate { 9837c478bd9Sstevel@tonic-gate int fd; 9847c478bd9Sstevel@tonic-gate char zerobyte = '\0'; 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) { 9877c478bd9Sstevel@tonic-gate perror(fn); 9887c478bd9Sstevel@tonic-gate exit(2); 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate if (Imagesize == 5) { 9927c478bd9Sstevel@tonic-gate /* Disk image of a 1.2M floppy */ 9937c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 2 * 80 * 15; 9947c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = 2 * 80 * 15; 9957c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track = 15; 9967c478bd9Sstevel@tonic-gate wbpb->bpb.heads = 2; 9977c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF9; 9987c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224; 9997c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 10007c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 7; 10017c478bd9Sstevel@tonic-gate } else { 10027c478bd9Sstevel@tonic-gate /* Disk image of a 1.44M floppy */ 10037c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 2 * 80 * 18; 10047c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = 2 * 80 * 18; 10057c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track = 18; 10067c478bd9Sstevel@tonic-gate wbpb->bpb.heads = 2; 10077c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF0; 10087c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224; 10097c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 10107c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9; 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate /* 10147c478bd9Sstevel@tonic-gate * Make a holey file, with length the exact 10157c478bd9Sstevel@tonic-gate * size of the floppy image. 10167c478bd9Sstevel@tonic-gate */ 10177c478bd9Sstevel@tonic-gate if (lseek(fd, (wbpb->bpb.sectors_in_volume * BPSEC)-1, SEEK_SET) < 0) { 10187c478bd9Sstevel@tonic-gate (void) close(fd); 10197c478bd9Sstevel@tonic-gate perror(fn); 10207c478bd9Sstevel@tonic-gate exit(2); 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate if (write(fd, &zerobyte, 1) != 1) { 10247c478bd9Sstevel@tonic-gate (void) close(fd); 10257c478bd9Sstevel@tonic-gate perror(fn); 10267c478bd9Sstevel@tonic-gate exit(2); 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate 10297c478bd9Sstevel@tonic-gate if (lseek(fd, 0, SEEK_SET) < 0) { 10307c478bd9Sstevel@tonic-gate (void) close(fd); 10317c478bd9Sstevel@tonic-gate perror(fn); 10327c478bd9Sstevel@tonic-gate exit(2); 10337c478bd9Sstevel@tonic-gate } 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate Fatentsize = 12; /* Size of fat entry in bits */ 10367c478bd9Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize); 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0; 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = 0; 10417c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = 0; 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate return (fd); 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate /* 10477c478bd9Sstevel@tonic-gate * partn_lecture 10487c478bd9Sstevel@tonic-gate * 10497c478bd9Sstevel@tonic-gate * Give a brief sermon on dev_name user should pass to 10507c478bd9Sstevel@tonic-gate * the program from the command line. 10517c478bd9Sstevel@tonic-gate * 10527c478bd9Sstevel@tonic-gate */ 10537c478bd9Sstevel@tonic-gate static 10547c478bd9Sstevel@tonic-gate void 10557c478bd9Sstevel@tonic-gate partn_lecture(char *dn) 10567c478bd9Sstevel@tonic-gate { 10577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10587c478bd9Sstevel@tonic-gate gettext("\nDevice %s was assumed to be a diskette.\n" 10597c478bd9Sstevel@tonic-gate "A diskette specific operation failed on this device.\n" 10607c478bd9Sstevel@tonic-gate "If the device is a hard disk, provide the name of " 10617c478bd9Sstevel@tonic-gate "the full physical disk,\n" 10627c478bd9Sstevel@tonic-gate "and qualify that name with a logical drive specifier.\n\n" 10637c478bd9Sstevel@tonic-gate "Hint: the device is usually something similar to\n\n" 10647c478bd9Sstevel@tonic-gate "/dev/rdsk/c0d0p0 or /dev/rdsk/c0t0d0p0 (x86)\n" 10657c478bd9Sstevel@tonic-gate "/dev/rdsk/c0t5d0s2 (sparc)\n\n" 10667c478bd9Sstevel@tonic-gate "The drive specifier is appended to the device name." 10677c478bd9Sstevel@tonic-gate " For example:\n\n" 10687c478bd9Sstevel@tonic-gate "/dev/rdsk/c0t5d0s2:c or /dev/rdsk/c0d0p0:boot\n\n"), dn); 10697c478bd9Sstevel@tonic-gate } 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate static 10727c478bd9Sstevel@tonic-gate void 10737c478bd9Sstevel@tonic-gate warn_funky_floppy(void) 10747c478bd9Sstevel@tonic-gate { 10757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10767c478bd9Sstevel@tonic-gate gettext("Use the 'nofdisk' option to create file systems\n" 10777c478bd9Sstevel@tonic-gate "on non-standard floppies.\n\n")); 10787c478bd9Sstevel@tonic-gate exit(4); 10797c478bd9Sstevel@tonic-gate } 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate static 10827c478bd9Sstevel@tonic-gate void 10837c478bd9Sstevel@tonic-gate warn_funky_fatsize(void) 10847c478bd9Sstevel@tonic-gate { 10857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 10867c478bd9Sstevel@tonic-gate gettext("Non-standard FAT size requested for floppy.\n" 10877c478bd9Sstevel@tonic-gate "The 'nofdisk' option must be used to\n" 10887c478bd9Sstevel@tonic-gate "override the 12 bit floppy default.\n\n")); 10897c478bd9Sstevel@tonic-gate exit(4); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate static 10937c478bd9Sstevel@tonic-gate void 10947c478bd9Sstevel@tonic-gate floppy_bpb_fillin(bpb_t *wbpb, int diam, int hds, int spt) 10957c478bd9Sstevel@tonic-gate { 10967c478bd9Sstevel@tonic-gate switch (diam) { 10977c478bd9Sstevel@tonic-gate case 3: 10987c478bd9Sstevel@tonic-gate switch (hds) { 10997c478bd9Sstevel@tonic-gate case 2: 11007c478bd9Sstevel@tonic-gate switch (spt) { 11017c478bd9Sstevel@tonic-gate case 9: 11027c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF9; 11037c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112; 11047c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2; 11057c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 3; 11067c478bd9Sstevel@tonic-gate break; 11077c478bd9Sstevel@tonic-gate case 18: 11087c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF0; 11097c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224; 11107c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 11117c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9; 11127c478bd9Sstevel@tonic-gate break; 11137c478bd9Sstevel@tonic-gate case 36: 11147c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF0; 11157c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 240; 11167c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2; 11177c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 9; 11187c478bd9Sstevel@tonic-gate break; 11197c478bd9Sstevel@tonic-gate default: 11207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11217c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! " 11227c478bd9Sstevel@tonic-gate "3.5'' diskette with %d heads " 11237c478bd9Sstevel@tonic-gate "and %d sectors/track.\n"), hds, spt); 11247c478bd9Sstevel@tonic-gate warn_funky_floppy(); 11257c478bd9Sstevel@tonic-gate } 11267c478bd9Sstevel@tonic-gate break; 11277c478bd9Sstevel@tonic-gate case 1: 11287c478bd9Sstevel@tonic-gate default: 11297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11307c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! " 11317c478bd9Sstevel@tonic-gate "3.5'' diskette with %d heads "), hds); 11327c478bd9Sstevel@tonic-gate warn_funky_floppy(); 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate break; 11357c478bd9Sstevel@tonic-gate case 5: 11367c478bd9Sstevel@tonic-gate switch (hds) { 11377c478bd9Sstevel@tonic-gate case 2: 11387c478bd9Sstevel@tonic-gate switch (spt) { 11397c478bd9Sstevel@tonic-gate case 15: 11407c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF9; 11417c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 224; 11427c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 11437c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 7; 11447c478bd9Sstevel@tonic-gate break; 11457c478bd9Sstevel@tonic-gate case 9: 11467c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xFD; 11477c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112; 11487c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 2; 11497c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2; 11507c478bd9Sstevel@tonic-gate break; 11517c478bd9Sstevel@tonic-gate case 8: 11527c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xFF; 11537c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 112; 11547c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 11557c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2; 11567c478bd9Sstevel@tonic-gate break; 11577c478bd9Sstevel@tonic-gate default: 11587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11597c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! " 11607c478bd9Sstevel@tonic-gate "5.25'' diskette with %d heads " 11617c478bd9Sstevel@tonic-gate "and %d sectors/track.\n"), hds, spt); 11627c478bd9Sstevel@tonic-gate warn_funky_floppy(); 11637c478bd9Sstevel@tonic-gate } 11647c478bd9Sstevel@tonic-gate break; 11657c478bd9Sstevel@tonic-gate case 1: 11667c478bd9Sstevel@tonic-gate switch (spt) { 11677c478bd9Sstevel@tonic-gate case 9: 11687c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xFC; 11697c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 64; 11707c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 11717c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 2; 11727c478bd9Sstevel@tonic-gate break; 11737c478bd9Sstevel@tonic-gate case 8: 11747c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xFE; 11757c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 64; 11767c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = 1; 11777c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 1; 11787c478bd9Sstevel@tonic-gate break; 11797c478bd9Sstevel@tonic-gate default: 11807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11817c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! " 11827c478bd9Sstevel@tonic-gate "5.25'' diskette with %d heads " 11837c478bd9Sstevel@tonic-gate "and %d sectors/track.\n"), hds, spt); 11847c478bd9Sstevel@tonic-gate warn_funky_floppy(); 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate break; 11877c478bd9Sstevel@tonic-gate default: 11887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11897c478bd9Sstevel@tonic-gate gettext("Unknown diskette parameters! " 11907c478bd9Sstevel@tonic-gate "5.25'' diskette with %d heads."), hds); 11917c478bd9Sstevel@tonic-gate warn_funky_floppy(); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate break; 11947c478bd9Sstevel@tonic-gate default: 11957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11967c478bd9Sstevel@tonic-gate gettext("\nUnknown diskette type. Only know about " 11977c478bd9Sstevel@tonic-gate "5.25'' and 3.5'' diskettes.\n")); 11987c478bd9Sstevel@tonic-gate warn_funky_floppy(); 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate } 12017c478bd9Sstevel@tonic-gate 12027c478bd9Sstevel@tonic-gate /* 12037c478bd9Sstevel@tonic-gate * lookup_floppy 12047c478bd9Sstevel@tonic-gate * 12057c478bd9Sstevel@tonic-gate * Look up a media descriptor byte and other crucial BPB values 12067c478bd9Sstevel@tonic-gate * based on floppy characteristics. 12077c478bd9Sstevel@tonic-gate */ 12087c478bd9Sstevel@tonic-gate static 12097c478bd9Sstevel@tonic-gate void 12107c478bd9Sstevel@tonic-gate lookup_floppy(struct fd_char *fdchar, bpb_t *wbpb) 12117c478bd9Sstevel@tonic-gate { 12127c478bd9Sstevel@tonic-gate ulong_t tsize; 12137c478bd9Sstevel@tonic-gate ulong_t cyls, spt, hds, diam; 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate cyls = fdchar->fdc_ncyl; 12167c478bd9Sstevel@tonic-gate diam = fdchar->fdc_medium; 12177c478bd9Sstevel@tonic-gate spt = fdchar->fdc_secptrack; 12187c478bd9Sstevel@tonic-gate hds = fdchar->fdc_nhead; 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate tsize = cyls * hds * spt; 12217c478bd9Sstevel@tonic-gate 12227c478bd9Sstevel@tonic-gate if (GetFsParams) 12237c478bd9Sstevel@tonic-gate TotSize = tsize; 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate if (GetSize) { 12267c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = tsize; 12277c478bd9Sstevel@tonic-gate } else { 12287c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume = 12297c478bd9Sstevel@tonic-gate warn_mismatch( 12307c478bd9Sstevel@tonic-gate gettext("length of partition (in sectors)"), 12317c478bd9Sstevel@tonic-gate gettext("FDIOGCHAR call"), tsize, TotSize); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume = 12347c478bd9Sstevel@tonic-gate (short)wbpb->bpb.sectors_in_logical_volume; 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate if (GetSPT) { 12377c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track = spt; 12387c478bd9Sstevel@tonic-gate } else { 12397c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track = 12407c478bd9Sstevel@tonic-gate warn_mismatch( 12417c478bd9Sstevel@tonic-gate gettext("sectors per track"), 12427c478bd9Sstevel@tonic-gate gettext("FDIOGCHAR call"), spt, SecPerTrk); 12437c478bd9Sstevel@tonic-gate spt = wbpb->bpb.sectors_per_track; 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate if (GetTPC) { 12477c478bd9Sstevel@tonic-gate wbpb->bpb.heads = hds; 12487c478bd9Sstevel@tonic-gate } else { 12497c478bd9Sstevel@tonic-gate wbpb->bpb.heads = 12507c478bd9Sstevel@tonic-gate warn_mismatch( 12517c478bd9Sstevel@tonic-gate gettext("number of heads"), 12527c478bd9Sstevel@tonic-gate gettext("FDIOGCHAR call"), hds, TrkPerCyl); 12537c478bd9Sstevel@tonic-gate hds = wbpb->bpb.heads; 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate 12567c478bd9Sstevel@tonic-gate Fatentsize = 12; /* Size of fat entry in bits */ 12577c478bd9Sstevel@tonic-gate if (!GetBPF && BitsPerFAT != Fatentsize) { 12587c478bd9Sstevel@tonic-gate warn_funky_fatsize(); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize); 12617c478bd9Sstevel@tonic-gate 12627c478bd9Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0; 12637c478bd9Sstevel@tonic-gate 12647c478bd9Sstevel@tonic-gate wbpb->bpb.hidden_sectors = 0; 12657c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_high = 0; 12667c478bd9Sstevel@tonic-gate wbpb->sunbpb.bs_offset_low = 0; 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate floppy_bpb_fillin(wbpb, diam, hds, spt); 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate /* 12727c478bd9Sstevel@tonic-gate * compute_cluster_size 12737c478bd9Sstevel@tonic-gate * 12747c478bd9Sstevel@tonic-gate * Compute an acceptable sectors/cluster value. 12757c478bd9Sstevel@tonic-gate * 1276849ee7a1Swyllys * Based on values from the Hardware White Paper 1277849ee7a1Swyllys * from Microsoft. 1278849ee7a1Swyllys * "Microsoft Extensible Firmware Initiative 1279849ee7a1Swyllys * FAT32 File System Specification 1280849ee7a1Swyllys * FAT: General Overview of On-Disk Format" 12817c478bd9Sstevel@tonic-gate * 1282849ee7a1Swyllys * Version 1.03, December 6, 2000 1283849ee7a1Swyllys * 12847c478bd9Sstevel@tonic-gate */ 12857c478bd9Sstevel@tonic-gate static 12867c478bd9Sstevel@tonic-gate void 12877c478bd9Sstevel@tonic-gate compute_cluster_size(bpb_t *wbpb) 12887c478bd9Sstevel@tonic-gate { 128957e22c6cSwyllys ulong_t volsize; 129057e22c6cSwyllys ulong_t spc; 12910576819eSwyllys ulong_t rds, tmpval1, tmpval2; 12920576819eSwyllys ulong_t fatsz; 1293849ee7a1Swyllys int newfat = 16; 1294849ee7a1Swyllys 1295849ee7a1Swyllys #define FAT12_MAX_CLUSTERS 0x0FF4 1296849ee7a1Swyllys #define FAT16_MAX_CLUSTERS 0xFFF4 1297849ee7a1Swyllys #define FAT32_MAX_CLUSTERS 0x0FFFFFF0 1298849ee7a1Swyllys #define FAT32_SUGGESTED_NCLUST 0x400000 1299849ee7a1Swyllys 1300849ee7a1Swyllys /* compute volume size in sectors. */ 13017c478bd9Sstevel@tonic-gate volsize = wbpb->bpb.sectors_in_volume ? wbpb->bpb.sectors_in_volume : 13027c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume; 13037c478bd9Sstevel@tonic-gate volsize -= wbpb->bpb.resv_sectors; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate if (GetSPC) { 1306849ee7a1Swyllys /* 1307849ee7a1Swyllys * User indicated what sort of FAT to create, 1308849ee7a1Swyllys * make sure it is valid with the given size 1309849ee7a1Swyllys * and compute an SPC value. 1310849ee7a1Swyllys */ 1311849ee7a1Swyllys if (!MakeFAT32) { /* FAT16 */ 1312849ee7a1Swyllys /* volsize is in sectors */ 1313849ee7a1Swyllys if (volsize < FAT12_MAX_CLUSTERS) { 1314849ee7a1Swyllys (void) fprintf(stderr, 1315849ee7a1Swyllys gettext("Requested size is too " 1316849ee7a1Swyllys "small for FAT16.\n")); 1317849ee7a1Swyllys exit(4); 13187c478bd9Sstevel@tonic-gate } 1319849ee7a1Swyllys /* SPC must be a power of 2 */ 1320849ee7a1Swyllys for (spc = 1; spc <= 64; spc = spc * 2) { 1321849ee7a1Swyllys if (volsize < spc * FAT16_MAX_CLUSTERS) 1322849ee7a1Swyllys break; 1323849ee7a1Swyllys } 1324849ee7a1Swyllys if (volsize > (spc * FAT16_MAX_CLUSTERS)) { 1325849ee7a1Swyllys (void) fprintf(stderr, 1326849ee7a1Swyllys gettext("Requested size is too " 1327849ee7a1Swyllys "large for FAT16.\n")); 1328849ee7a1Swyllys exit(4); 1329849ee7a1Swyllys } 1330849ee7a1Swyllys } else { /* FAT32 */ 1331849ee7a1Swyllys /* volsize is in sectors */ 1332849ee7a1Swyllys if (volsize < FAT16_MAX_CLUSTERS) { 1333849ee7a1Swyllys (void) fprintf(stderr, 1334849ee7a1Swyllys gettext("Requested size is too " 1335849ee7a1Swyllys "small for FAT32.\n")); 1336849ee7a1Swyllys exit(4); 1337849ee7a1Swyllys } 1338849ee7a1Swyllys /* SPC must be a power of 2 */ 1339849ee7a1Swyllys for (spc = 1; spc <= 64; spc = spc * 2) { 1340849ee7a1Swyllys if (volsize < (spc * FAT32_SUGGESTED_NCLUST)) 1341849ee7a1Swyllys break; 1342849ee7a1Swyllys } 1343849ee7a1Swyllys if (volsize > (spc * FAT32_MAX_CLUSTERS)) { 1344849ee7a1Swyllys (void) fprintf(stderr, 1345849ee7a1Swyllys gettext("Requested size is too " 1346849ee7a1Swyllys "large for FAT32.\n")); 13477c478bd9Sstevel@tonic-gate exit(4); 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate } 13507c478bd9Sstevel@tonic-gate } else { 1351849ee7a1Swyllys /* 1352849ee7a1Swyllys * User gave the SPC as an explicit option, 1353849ee7a1Swyllys * make sure it will work with the requested 1354849ee7a1Swyllys * volume size. 1355849ee7a1Swyllys */ 1356849ee7a1Swyllys int nclust; 1357849ee7a1Swyllys 13587c478bd9Sstevel@tonic-gate spc = SecPerClust; 1359849ee7a1Swyllys nclust = volsize / spc; 1360849ee7a1Swyllys 1361849ee7a1Swyllys if (nclust <= FAT16_MAX_CLUSTERS && MakeFAT32) { 1362f127cb91Sfrankho (void) fprintf(stderr, gettext("Requested size is too " 1363849ee7a1Swyllys "small for FAT32.\n")); 1364849ee7a1Swyllys exit(4); 1365849ee7a1Swyllys } 1366849ee7a1Swyllys if (!MakeFAT32) { 1367849ee7a1Swyllys /* Determine if FAT12 or FAT16 */ 1368849ee7a1Swyllys if (nclust < FAT12_MAX_CLUSTERS) 1369849ee7a1Swyllys newfat = 12; 1370849ee7a1Swyllys else if (nclust < FAT16_MAX_CLUSTERS) 1371849ee7a1Swyllys newfat = 16; 1372849ee7a1Swyllys else { 1373849ee7a1Swyllys (void) fprintf(stderr, 1374849ee7a1Swyllys gettext("Requested size is too " 1375849ee7a1Swyllys "small for FAT32.\n")); 1376849ee7a1Swyllys exit(4); 1377849ee7a1Swyllys } 1378849ee7a1Swyllys } 13797c478bd9Sstevel@tonic-gate } 13807c478bd9Sstevel@tonic-gate 13810576819eSwyllys /* 13820576819eSwyllys * RootDirSectors = ((BPB_RootEntCnt * 32) + 13830576819eSwyllys * (BPB_BytsPerSec 1)) / BPB_BytsPerSec; 13840576819eSwyllys */ 13850576819eSwyllys rds = ((wbpb->bpb.num_root_entries * 32) + 1386f127cb91Sfrankho (wbpb->bpb.bytes_sector - 1)) / wbpb->bpb.bytes_sector; 13870576819eSwyllys 13887c478bd9Sstevel@tonic-gate if (GetBPF) { 13897c478bd9Sstevel@tonic-gate if (MakeFAT32) 13907c478bd9Sstevel@tonic-gate Fatentsize = 32; 13917c478bd9Sstevel@tonic-gate else 1392849ee7a1Swyllys Fatentsize = newfat; 13937c478bd9Sstevel@tonic-gate } else { 13947c478bd9Sstevel@tonic-gate Fatentsize = BitsPerFAT; 13950576819eSwyllys 13960576819eSwyllys if (Fatentsize == 12 && 13970576819eSwyllys (volsize - rds) >= DOS_F12MAXC * spc) { 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate * If we don't have an input TTY, or we aren't 14007c478bd9Sstevel@tonic-gate * really doing anything, then don't ask 14017c478bd9Sstevel@tonic-gate * questions. Assume a yes answer to any 14027c478bd9Sstevel@tonic-gate * questions we would ask. 14037c478bd9Sstevel@tonic-gate */ 14047c478bd9Sstevel@tonic-gate if (Notreally || !isatty(fileno(stdin))) { 14057c478bd9Sstevel@tonic-gate (void) printf( 14067c478bd9Sstevel@tonic-gate gettext("Volume too large for 12 bit FAT," 14077c478bd9Sstevel@tonic-gate " increasing to 16 bit FAT size.\n")); 14087c478bd9Sstevel@tonic-gate (void) fflush(stdout); 14097c478bd9Sstevel@tonic-gate Fatentsize = 16; 14107c478bd9Sstevel@tonic-gate } else { 14117c478bd9Sstevel@tonic-gate (void) printf( 14127c478bd9Sstevel@tonic-gate gettext("Volume too large for a 12 bit FAT.\n" 14137c478bd9Sstevel@tonic-gate "Increase to 16 bit FAT " 14147c478bd9Sstevel@tonic-gate "and continue (y/n)? ")); 14157c478bd9Sstevel@tonic-gate (void) fflush(stdout); 14167c478bd9Sstevel@tonic-gate if (yes()) 14177c478bd9Sstevel@tonic-gate Fatentsize = 16; 14187c478bd9Sstevel@tonic-gate else 14197c478bd9Sstevel@tonic-gate exit(5); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = spc; 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate if (!GetFsParams && FdiskFATsize < 0) { 14267c478bd9Sstevel@tonic-gate (void) printf( 14277c478bd9Sstevel@tonic-gate gettext("Cannot verify chosen/computed FAT " 14287c478bd9Sstevel@tonic-gate "entry size (%d bits) with FDISK table.\n" 14297c478bd9Sstevel@tonic-gate "FDISK table has an unknown file system " 14307c478bd9Sstevel@tonic-gate "type for this device. Giving up...\n"), 14317c478bd9Sstevel@tonic-gate Fatentsize, Fatentsize); 14327c478bd9Sstevel@tonic-gate exit(6); 14337c478bd9Sstevel@tonic-gate } else if (!GetFsParams && FdiskFATsize && FdiskFATsize != Fatentsize) { 14347c478bd9Sstevel@tonic-gate (void) printf( 14357c478bd9Sstevel@tonic-gate gettext("Chosen/computed FAT entry size (%d bits) " 14367c478bd9Sstevel@tonic-gate "does not match FDISK table (%d bits).\n"), 14377c478bd9Sstevel@tonic-gate Fatentsize, FdiskFATsize); 14387c478bd9Sstevel@tonic-gate (void) printf( 14397c478bd9Sstevel@tonic-gate gettext("Use -o fat=%d to build a FAT " 14407c478bd9Sstevel@tonic-gate "that matches the FDISK entry.\n"), FdiskFATsize); 14417c478bd9Sstevel@tonic-gate exit(6); 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate set_fat_string(wbpb, Fatentsize); 14440576819eSwyllys /* 14450576819eSwyllys * Compure the FAT sizes according to algorithm from Microsoft: 14460576819eSwyllys * 14470576819eSwyllys * RootDirSectors = ((BPB_RootEntCnt * 32) + 14480576819eSwyllys * (BPB_BytsPerSec 1)) / BPB_BytsPerSec; 14490576819eSwyllys * TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors); 14500576819eSwyllys * TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs; 14510576819eSwyllys * If (FATType == FAT32) 14520576819eSwyllys * TmpVal2 = TmpVal2 / 2; 14530576819eSwyllys * FATSz = (TMPVal1 + (TmpVal2 1)) / TmpVal2; 14540576819eSwyllys * If (FATType == FAT32) { 14550576819eSwyllys * BPB_FATSz16 = 0; 14560576819eSwyllys * BPB_FATSz32 = FATSz; 14570576819eSwyllys * } else { 14580576819eSwyllys * BPB_FATSz16 = LOWORD(FATSz); 14590576819eSwyllys * // there is no BPB_FATSz32 in a FAT16 BPB 14600576819eSwyllys * } 14610576819eSwyllys */ 14620576819eSwyllys tmpval1 = volsize - (wbpb->bpb.resv_sectors + rds); 14630576819eSwyllys 1464f127cb91Sfrankho tmpval2 = (256 * wbpb->bpb.sectors_per_cluster) + wbpb->bpb.num_fats; 14650576819eSwyllys 14660576819eSwyllys if (Fatentsize == 32) 14670576819eSwyllys tmpval2 = tmpval2 / 2; 14680576819eSwyllys 14690576819eSwyllys fatsz = (tmpval1 + (tmpval2 - 1)) / tmpval2; 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate /* Compute a sector/fat figure */ 14727c478bd9Sstevel@tonic-gate switch (Fatentsize) { 14737c478bd9Sstevel@tonic-gate case 32: 14747c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat = 0; 14750576819eSwyllys wbpb->bpb32.big_sectors_per_fat = fatsz; 14760576819eSwyllys if (Verbose) 147757e22c6cSwyllys (void) printf("compute_cluster_size: Sectors per " 1478f127cb91Sfrankho "FAT32 = %d\n", wbpb->bpb32.big_sectors_per_fat); 14797c478bd9Sstevel@tonic-gate break; 14807c478bd9Sstevel@tonic-gate case 12: 14817c478bd9Sstevel@tonic-gate default: /* 16 bit FAT */ 14820576819eSwyllys wbpb->bpb.sectors_per_fat = (ushort_t)(fatsz & 0x0000FFFF); 14830576819eSwyllys if (Verbose) 148457e22c6cSwyllys (void) printf("compute_cluster_size: Sectors per " 148557e22c6cSwyllys "FAT16 = %d\n", wbpb->bpb.sectors_per_fat); 14867c478bd9Sstevel@tonic-gate break; 14877c478bd9Sstevel@tonic-gate } 14887c478bd9Sstevel@tonic-gate } 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate static 14917c478bd9Sstevel@tonic-gate void 14927c478bd9Sstevel@tonic-gate find_fixed_details(int fd, bpb_t *wbpb) 14937c478bd9Sstevel@tonic-gate { 14947c478bd9Sstevel@tonic-gate struct dk_geom dginfo; 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate /* 14977c478bd9Sstevel@tonic-gate * Look up the last remaining bits of info we need 14987c478bd9Sstevel@tonic-gate * that is specific to the hard drive using a disk ioctl. 14997c478bd9Sstevel@tonic-gate */ 15007c478bd9Sstevel@tonic-gate if (GetSPT || GetTPC) { 1501f127cb91Sfrankho if (ioctl(fd, DKIOCG_VIRTGEOM, &dginfo) == -1 && 1502f127cb91Sfrankho ioctl(fd, DKIOCG_PHYGEOM, &dginfo) == -1 && 1503f127cb91Sfrankho ioctl(fd, DKIOCGGEOM, &dginfo) == -1) { 15047c478bd9Sstevel@tonic-gate (void) close(fd); 15057c478bd9Sstevel@tonic-gate perror( 15067c478bd9Sstevel@tonic-gate gettext("Drive geometry lookup (need " 15077c478bd9Sstevel@tonic-gate "tracks/cylinder and/or sectors/track")); 15087c478bd9Sstevel@tonic-gate exit(2); 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate } 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate wbpb->bpb.heads = (GetTPC ? dginfo.dkg_nhead : TrkPerCyl); 15137c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track = (GetSPT ? dginfo.dkg_nsect : SecPerTrk); 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate if (Verbose) { 15167c478bd9Sstevel@tonic-gate if (GetTPC) { 15177c478bd9Sstevel@tonic-gate (void) printf( 15187c478bd9Sstevel@tonic-gate gettext("DKIOCG determined number of heads = %d\n"), 15197c478bd9Sstevel@tonic-gate dginfo.dkg_nhead); 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate if (GetSPT) { 15227c478bd9Sstevel@tonic-gate (void) printf( 1523f127cb91Sfrankho gettext("DKIOCG determined sectors per track" 1524f127cb91Sfrankho " = %d\n"), dginfo.dkg_nsect); 15257c478bd9Sstevel@tonic-gate } 15267c478bd9Sstevel@tonic-gate } 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate /* 15297c478bd9Sstevel@tonic-gate * XXX - MAY need an additional flag (or flags) to set media 15307c478bd9Sstevel@tonic-gate * and physical drive number fields. That in the case of weird 15317c478bd9Sstevel@tonic-gate * floppies that have to go through 'nofdisk' route for formatting. 15327c478bd9Sstevel@tonic-gate */ 15337c478bd9Sstevel@tonic-gate wbpb->bpb.media = 0xF8; 15347c478bd9Sstevel@tonic-gate if (MakeFAT32) 15357c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 0; 15367c478bd9Sstevel@tonic-gate else 15377c478bd9Sstevel@tonic-gate wbpb->bpb.num_root_entries = 512; 15387c478bd9Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = 0x80; 15397c478bd9Sstevel@tonic-gate compute_cluster_size(wbpb); 15407c478bd9Sstevel@tonic-gate } 15417c478bd9Sstevel@tonic-gate 15427c478bd9Sstevel@tonic-gate static 15437c478bd9Sstevel@tonic-gate char * 15447c478bd9Sstevel@tonic-gate stat_actual_disk(char *diskname, struct stat *info, char **suffix) 15457c478bd9Sstevel@tonic-gate { 15467c478bd9Sstevel@tonic-gate char *actualdisk; 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate if (stat(diskname, info)) { 15497c478bd9Sstevel@tonic-gate /* 15507c478bd9Sstevel@tonic-gate * Device named on command line doesn't exist. That 15517c478bd9Sstevel@tonic-gate * probably means there is a partition-specifying 15527c478bd9Sstevel@tonic-gate * suffix attached to the actual disk name. 15537c478bd9Sstevel@tonic-gate */ 15547c478bd9Sstevel@tonic-gate actualdisk = strtok(strdup(diskname), ":"); 15557c478bd9Sstevel@tonic-gate if (*suffix = strchr(diskname, ':')) 15567c478bd9Sstevel@tonic-gate (*suffix)++; 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate if (stat(actualdisk, info)) { 15597c478bd9Sstevel@tonic-gate perror(actualdisk); 15607c478bd9Sstevel@tonic-gate exit(2); 15617c478bd9Sstevel@tonic-gate } 15627c478bd9Sstevel@tonic-gate } else { 15637c478bd9Sstevel@tonic-gate actualdisk = strdup(diskname); 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate return (actualdisk); 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate 15697c478bd9Sstevel@tonic-gate static 15707c478bd9Sstevel@tonic-gate void 15717c478bd9Sstevel@tonic-gate compute_file_area_size(bpb_t *wbpb) 15727c478bd9Sstevel@tonic-gate { 15730576819eSwyllys int FATSz; 15740576819eSwyllys int TotSec; 15750576819eSwyllys int DataSec; 1576f127cb91Sfrankho int RootDirSectors = 1577f127cb91Sfrankho ((wbpb->bpb.num_root_entries * 32) + (wbpb->bpb.bytes_sector - 1)) / 15780576819eSwyllys wbpb->bpb.bytes_sector; 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate if (wbpb->bpb.sectors_per_fat) { 15817c478bd9Sstevel@tonic-gate /* 15827c478bd9Sstevel@tonic-gate * Good old FAT12 or FAT16 15837c478bd9Sstevel@tonic-gate */ 15840576819eSwyllys FATSz = wbpb->bpb.sectors_per_fat; 15850576819eSwyllys TotSec = wbpb->bpb.sectors_in_volume; 15867c478bd9Sstevel@tonic-gate } else { 15877c478bd9Sstevel@tonic-gate /* 15887c478bd9Sstevel@tonic-gate * FAT32 15897c478bd9Sstevel@tonic-gate */ 15900576819eSwyllys FATSz = wbpb->bpb32.big_sectors_per_fat; 15910576819eSwyllys TotSec = wbpb->bpb.sectors_in_logical_volume; 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate 1594f127cb91Sfrankho DataSec = TotSec - 1595f127cb91Sfrankho (wbpb->bpb.resv_sectors + (wbpb->bpb.num_fats * FATSz) + 15960576819eSwyllys RootDirSectors); 15970576819eSwyllys 15980576819eSwyllys 15997c478bd9Sstevel@tonic-gate /* 16007c478bd9Sstevel@tonic-gate * Now change sectors to clusters 16017c478bd9Sstevel@tonic-gate */ 16020576819eSwyllys TotalClusters = DataSec / wbpb->bpb.sectors_per_cluster; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate if (Verbose) 16057c478bd9Sstevel@tonic-gate (void) printf(gettext("Disk has a file area of %d " 16067c478bd9Sstevel@tonic-gate "allocation units,\neach with %d sectors = %d " 16077c478bd9Sstevel@tonic-gate "bytes.\n"), TotalClusters, wbpb->bpb.sectors_per_cluster, 16087c478bd9Sstevel@tonic-gate TotalClusters * wbpb->bpb.sectors_per_cluster * BPSEC); 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate #ifndef i386 16127c478bd9Sstevel@tonic-gate /* 16137c478bd9Sstevel@tonic-gate * swap_pack_{bpb,bpb32,sebpb}cpy 16147c478bd9Sstevel@tonic-gate * 16157c478bd9Sstevel@tonic-gate * If not on an x86 we assume the structures making up the bpb 16167c478bd9Sstevel@tonic-gate * were not packed and that longs and shorts need to be byte swapped 16177c478bd9Sstevel@tonic-gate * (we've kept everything in host order up until now). A new architecture 16187c478bd9Sstevel@tonic-gate * might not need to swap or might not need to pack, in which case 16197c478bd9Sstevel@tonic-gate * new routines will have to be written. Of course if an architecture 16207c478bd9Sstevel@tonic-gate * supports both packing and little-endian host order, it can follow the 16217c478bd9Sstevel@tonic-gate * same path as the x86 code. 16227c478bd9Sstevel@tonic-gate */ 16237c478bd9Sstevel@tonic-gate static 16247c478bd9Sstevel@tonic-gate void 16257c478bd9Sstevel@tonic-gate swap_pack_bpbcpy(struct _boot_sector *bsp, bpb_t *wbpb) 16267c478bd9Sstevel@tonic-gate { 16277c478bd9Sstevel@tonic-gate uchar_t *fillp; 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate fillp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]); 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.bytes_sector); 16327c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.sectors_per_cluster; 16337c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.resv_sectors); 16347c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.num_fats; 16357c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.num_root_entries); 16367c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_in_volume); 16377c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.media; 16387c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_fat); 16397c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_track); 16407c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.heads); 16417c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.hidden_sectors); 16427c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.sectors_in_logical_volume); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.phys_drive_num; 16457c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.reserved; 16467c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.ext_signature; 16477c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->ebpb.volume_id); 16487c478bd9Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.volume_label, 11); 16497c478bd9Sstevel@tonic-gate fillp += 11; 16507c478bd9Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.type, 8); 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate static 16547c478bd9Sstevel@tonic-gate void 16557c478bd9Sstevel@tonic-gate swap_pack_bpb32cpy(struct _boot_sector32 *bsp, bpb_t *wbpb) 16567c478bd9Sstevel@tonic-gate { 16577c478bd9Sstevel@tonic-gate uchar_t *fillp; 16587c478bd9Sstevel@tonic-gate int r; 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate fillp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]); 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.bytes_sector); 16637c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.sectors_per_cluster; 16647c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.resv_sectors); 16657c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.num_fats; 16667c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.num_root_entries); 16677c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_in_volume); 16687c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb.media; 16697c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_fat); 16707c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.sectors_per_track); 16717c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb.heads); 16727c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.hidden_sectors); 16737c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb.sectors_in_logical_volume); 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb32.big_sectors_per_fat); 16767c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.ext_flags); 16777c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb32.fs_vers_lo; 16787c478bd9Sstevel@tonic-gate *fillp++ = wbpb->bpb32.fs_vers_hi; 16797c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->bpb32.root_dir_clust); 16807c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.fsinfosec); 16817c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.backupboot); 16827c478bd9Sstevel@tonic-gate for (r = 0; r < 6; r++) 16837c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->bpb32.reserved[r]); 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.phys_drive_num; 16867c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.reserved; 16877c478bd9Sstevel@tonic-gate *fillp++ = wbpb->ebpb.ext_signature; 16887c478bd9Sstevel@tonic-gate store_32_bits(&fillp, wbpb->ebpb.volume_id); 16897c478bd9Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.volume_label, 11); 16907c478bd9Sstevel@tonic-gate fillp += 11; 16917c478bd9Sstevel@tonic-gate (void) strncpy((char *)fillp, (char *)wbpb->ebpb.type, 8); 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate static 16957c478bd9Sstevel@tonic-gate void 16967c478bd9Sstevel@tonic-gate swap_pack_sebpbcpy(struct _boot_sector *bsp, bpb_t *wbpb) 16977c478bd9Sstevel@tonic-gate { 16987c478bd9Sstevel@tonic-gate uchar_t *fillp; 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate fillp = bsp->bs_sun_bpb; 17017c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->sunbpb.bs_offset_high); 17027c478bd9Sstevel@tonic-gate store_16_bits(&fillp, wbpb->sunbpb.bs_offset_low); 17037c478bd9Sstevel@tonic-gate } 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate static 17067c478bd9Sstevel@tonic-gate void 17077c478bd9Sstevel@tonic-gate swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp) 17087c478bd9Sstevel@tonic-gate { 17097c478bd9Sstevel@tonic-gate uchar_t *grabp; 17107c478bd9Sstevel@tonic-gate 17117c478bd9Sstevel@tonic-gate grabp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]); 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.bytes_sector))[1] = *grabp++; 17147c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.bytes_sector))[0] = *grabp++; 17157c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_cluster = *grabp++; 17167c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.resv_sectors))[1] = *grabp++; 17177c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.resv_sectors))[0] = *grabp++; 17187c478bd9Sstevel@tonic-gate wbpb->bpb.num_fats = *grabp++; 17197c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.num_root_entries))[1] = *grabp++; 17207c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.num_root_entries))[0] = *grabp++; 17217c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_volume))[1] = *grabp++; 17227c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_volume))[0] = *grabp++; 17237c478bd9Sstevel@tonic-gate wbpb->bpb.media = *grabp++; 17247c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_fat))[1] = *grabp++; 17257c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_fat))[0] = *grabp++; 17267c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_track))[1] = *grabp++; 17277c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_per_track))[0] = *grabp++; 17287c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.heads))[1] = *grabp++; 17297c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.heads))[0] = *grabp++; 17307c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[3] = *grabp++; 17317c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[2] = *grabp++; 17327c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[1] = *grabp++; 17337c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.hidden_sectors))[0] = *grabp++; 17347c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[3] = *grabp++; 17357c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[2] = *grabp++; 17367c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[1] = *grabp++; 17377c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[0] = *grabp++; 17387c478bd9Sstevel@tonic-gate wbpb->ebpb.phys_drive_num = *grabp++; 17397c478bd9Sstevel@tonic-gate wbpb->ebpb.reserved = *grabp++; 17407c478bd9Sstevel@tonic-gate wbpb->ebpb.ext_signature = *grabp++; 17417c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[3] = *grabp++; 17427c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[2] = *grabp++; 17437c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[1] = *grabp++; 17447c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->ebpb.volume_id))[0] = *grabp++; 17457c478bd9Sstevel@tonic-gate 17467c478bd9Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.volume_label, (char *)grabp, 11); 17477c478bd9Sstevel@tonic-gate grabp += 11; 17487c478bd9Sstevel@tonic-gate (void) strncpy((char *)wbpb->ebpb.type, (char *)grabp, 8); 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate static 17527c478bd9Sstevel@tonic-gate void 17537c478bd9Sstevel@tonic-gate swap_pack_grabsebpb(bpb_t *wbpb, struct _boot_sector *bsp) 17547c478bd9Sstevel@tonic-gate { 17557c478bd9Sstevel@tonic-gate uchar_t *grabp; 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate grabp = bsp->bs_sun_bpb; 17587c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_high))[1] = *grabp++; 17597c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_high))[0] = *grabp++; 17607c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_low))[1] = *grabp++; 17617c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->sunbpb.bs_offset_low))[0] = *grabp++; 17627c478bd9Sstevel@tonic-gate } 17637c478bd9Sstevel@tonic-gate 17647c478bd9Sstevel@tonic-gate static 17657c478bd9Sstevel@tonic-gate void 17667c478bd9Sstevel@tonic-gate swap_pack_grab32bpb(bpb_t *wbpb, struct _boot_sector *bsp) 17677c478bd9Sstevel@tonic-gate { 17687c478bd9Sstevel@tonic-gate uchar_t *grabp; 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate grabp = (uchar_t *)&(bsp->bs_filler[BPB_32_START_INDEX]); 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[3] = *grabp++; 17737c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[2] = *grabp++; 17747c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[1] = *grabp++; 17757c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[0] = *grabp++; 17767c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.ext_flags))[1] = *grabp++; 17777c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.ext_flags))[0] = *grabp++; 17787c478bd9Sstevel@tonic-gate wbpb->bpb32.fs_vers_lo = *grabp++; 17797c478bd9Sstevel@tonic-gate wbpb->bpb32.fs_vers_hi = *grabp++; 17807c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[3] = *grabp++; 17817c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[2] = *grabp++; 17827c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[1] = *grabp++; 17837c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.root_dir_clust))[0] = *grabp++; 17847c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.fsinfosec))[1] = *grabp++; 17857c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.fsinfosec))[0] = *grabp++; 17867c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.backupboot))[1] = *grabp++; 17877c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.backupboot))[0] = *grabp++; 17887c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[0]))[1] = *grabp++; 17897c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[0]))[0] = *grabp++; 17907c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[1]))[1] = *grabp++; 17917c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[1]))[0] = *grabp++; 17927c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[2]))[1] = *grabp++; 17937c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[2]))[0] = *grabp++; 17947c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[3]))[1] = *grabp++; 17957c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[3]))[0] = *grabp++; 17967c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[4]))[1] = *grabp++; 17977c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[4]))[0] = *grabp++; 17987c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[5]))[1] = *grabp++; 17997c478bd9Sstevel@tonic-gate ((uchar_t *)&(wbpb->bpb32.reserved[5]))[0] = *grabp++; 18007c478bd9Sstevel@tonic-gate } 18017c478bd9Sstevel@tonic-gate #endif /* ! i386 */ 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate static 18047c478bd9Sstevel@tonic-gate void 18057c478bd9Sstevel@tonic-gate dashm_bail(int fd) 18067c478bd9Sstevel@tonic-gate { 18077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18087c478bd9Sstevel@tonic-gate gettext("This media does not appear to be " 18097c478bd9Sstevel@tonic-gate "formatted with a FAT file system.\n")); 18107c478bd9Sstevel@tonic-gate (void) close(fd); 18117c478bd9Sstevel@tonic-gate exit(6); 18127c478bd9Sstevel@tonic-gate } 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate /* 18157c478bd9Sstevel@tonic-gate * read_existing_bpb 18167c478bd9Sstevel@tonic-gate * 18177c478bd9Sstevel@tonic-gate * Grab the first sector, which we think is a bios parameter block. 18187c478bd9Sstevel@tonic-gate * If it looks bad, bail. Otherwise fill in the parameter struct 18197c478bd9Sstevel@tonic-gate * fields that matter. 18207c478bd9Sstevel@tonic-gate */ 18217c478bd9Sstevel@tonic-gate static 18227c478bd9Sstevel@tonic-gate void 18237c478bd9Sstevel@tonic-gate read_existing_bpb(int fd, bpb_t *wbpb) 18247c478bd9Sstevel@tonic-gate { 18257c478bd9Sstevel@tonic-gate boot_sector_t ubpb; 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate if (read(fd, ubpb.buf, BPSEC) < BPSEC) { 18287c478bd9Sstevel@tonic-gate perror(gettext("Read BIOS parameter block " 18297c478bd9Sstevel@tonic-gate "from previously formatted media")); 18307c478bd9Sstevel@tonic-gate (void) close(fd); 18317c478bd9Sstevel@tonic-gate exit(6); 18327c478bd9Sstevel@tonic-gate } 18337c478bd9Sstevel@tonic-gate 18347c478bd9Sstevel@tonic-gate if (ltohs(ubpb.mb.signature) != BOOTSECSIG) { 18357c478bd9Sstevel@tonic-gate dashm_bail(fd); 18367c478bd9Sstevel@tonic-gate } 18377c478bd9Sstevel@tonic-gate 18387c478bd9Sstevel@tonic-gate #ifdef i386 18397c478bd9Sstevel@tonic-gate (void) memcpy(&(wbpb->bpb), &(ubpb.bs.bs_front.bs_bpb), 18407c478bd9Sstevel@tonic-gate sizeof (wbpb->bpb)); 18417c478bd9Sstevel@tonic-gate (void) memcpy(&(wbpb->ebpb), &(ubpb.bs.bs_ebpb), sizeof (wbpb->ebpb)); 18427c478bd9Sstevel@tonic-gate #else 18437c478bd9Sstevel@tonic-gate swap_pack_grabbpb(wbpb, &(ubpb.bs)); 18447c478bd9Sstevel@tonic-gate #endif 18457c478bd9Sstevel@tonic-gate if (SunBPBfields) { 18467c478bd9Sstevel@tonic-gate #ifdef i386 18477c478bd9Sstevel@tonic-gate (void) memcpy(&(wbpb->sunbpb), &(ubpb.bs.bs_sebpb), 18487c478bd9Sstevel@tonic-gate sizeof (wbpb->sunbpb)); 18497c478bd9Sstevel@tonic-gate #else 18507c478bd9Sstevel@tonic-gate swap_pack_grabsebpb(wbpb, &(ubpb.bs)); 18517c478bd9Sstevel@tonic-gate #endif 18527c478bd9Sstevel@tonic-gate } 18537c478bd9Sstevel@tonic-gate if (wbpb->bpb.bytes_sector != BPSEC) { 18547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18557c478bd9Sstevel@tonic-gate gettext("Bogus bytes per sector value.\n")); 1856*db92b35aSGary Mills if (!(ISP2(wbpb->bpb.bytes_sector) && 1857*db92b35aSGary Mills IN_RANGE(wbpb->bpb.bytes_sector, 1, BPSEC * 8))) { 18587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18597c478bd9Sstevel@tonic-gate gettext("The device name may be missing a " 18607c478bd9Sstevel@tonic-gate "logical drive specifier.\n")); 18617c478bd9Sstevel@tonic-gate (void) close(fd); 18627c478bd9Sstevel@tonic-gate exit(6); 18637c478bd9Sstevel@tonic-gate } else { 18647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18657c478bd9Sstevel@tonic-gate gettext("Do not know how to build FATs with a\n" 18667c478bd9Sstevel@tonic-gate "non-standard sector size. Standard " 18677c478bd9Sstevel@tonic-gate "size is %d bytes,\nyour sector size " 18687c478bd9Sstevel@tonic-gate "is %d bytes.\n"), BPSEC, 18697c478bd9Sstevel@tonic-gate wbpb->bpb.bytes_sector); 18707c478bd9Sstevel@tonic-gate (void) close(fd); 18717c478bd9Sstevel@tonic-gate exit(6); 18727c478bd9Sstevel@tonic-gate } 18737c478bd9Sstevel@tonic-gate } 1874*db92b35aSGary Mills if (!(ISP2(wbpb->bpb.sectors_per_cluster) && 1875*db92b35aSGary Mills IN_RANGE(wbpb->bpb.sectors_per_cluster, 1, 128))) { 18767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18777c478bd9Sstevel@tonic-gate gettext("Bogus sectors per cluster value.\n")); 18787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18797c478bd9Sstevel@tonic-gate gettext("The device name may be missing a " 18807c478bd9Sstevel@tonic-gate "logical drive specifier.\n")); 18817c478bd9Sstevel@tonic-gate (void) close(fd); 18827c478bd9Sstevel@tonic-gate exit(6); 18837c478bd9Sstevel@tonic-gate } 18847c478bd9Sstevel@tonic-gate 18857c478bd9Sstevel@tonic-gate if (wbpb->bpb.sectors_per_fat == 0) { 18867c478bd9Sstevel@tonic-gate #ifdef i386 18877c478bd9Sstevel@tonic-gate (void) memcpy(&(wbpb->bpb32), &(ubpb.bs32.bs_bpb32), 18887c478bd9Sstevel@tonic-gate sizeof (wbpb->bpb32)); 18897c478bd9Sstevel@tonic-gate #else 18907c478bd9Sstevel@tonic-gate swap_pack_grab32bpb(wbpb, &(ubpb.bs)); 18917c478bd9Sstevel@tonic-gate #endif 18927c478bd9Sstevel@tonic-gate compute_file_area_size(wbpb); 18937c478bd9Sstevel@tonic-gate if ((wbpb->bpb32.big_sectors_per_fat * BPSEC / 4) >= 18947c478bd9Sstevel@tonic-gate TotalClusters) { 18957c478bd9Sstevel@tonic-gate MakeFAT32 = 1; 18967c478bd9Sstevel@tonic-gate } else { 18977c478bd9Sstevel@tonic-gate dashm_bail(fd); 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate } else { 19007c478bd9Sstevel@tonic-gate compute_file_area_size(wbpb); 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate } 19037c478bd9Sstevel@tonic-gate 19047c478bd9Sstevel@tonic-gate /* 19057c478bd9Sstevel@tonic-gate * compare_existing_with_computed 19067c478bd9Sstevel@tonic-gate * 19077c478bd9Sstevel@tonic-gate * We use this function when we the user specifies the -m option. 19087c478bd9Sstevel@tonic-gate * We compute and look up things like we would if they had asked 19097c478bd9Sstevel@tonic-gate * us to make the fs, and compare that to what's already layed down 19107c478bd9Sstevel@tonic-gate * in the existing fs. If there's a difference we can tell them what 19117c478bd9Sstevel@tonic-gate * options to specify in order to reproduce their existing layout. 19127c478bd9Sstevel@tonic-gate * Note that they still may not get an exact duplicate, because we 19137c478bd9Sstevel@tonic-gate * don't, for example, preserve their existing boot code. We think 19147c478bd9Sstevel@tonic-gate * we've got all the fields that matter covered, though. 19157c478bd9Sstevel@tonic-gate * 19167c478bd9Sstevel@tonic-gate * XXX - We're basically ignoring sbpb at this point. I'm unsure 19177c478bd9Sstevel@tonic-gate * if we'll ever care about those fields, in terms of the -m option. 19187c478bd9Sstevel@tonic-gate */ 19197c478bd9Sstevel@tonic-gate static 19207c478bd9Sstevel@tonic-gate void 19217c478bd9Sstevel@tonic-gate compare_existing_with_computed(int fd, char *suffix, 19227c478bd9Sstevel@tonic-gate bpb_t *wbpb, int *prtsize, int *prtspc, int *prtbpf, int *prtnsect, 19237c478bd9Sstevel@tonic-gate int *prtntrk, int *prtfdisk, int *prthidden, int *prtrsrvd, int *dashos) 19247c478bd9Sstevel@tonic-gate { 19257c478bd9Sstevel@tonic-gate struct dk_geom dginfo; 19267c478bd9Sstevel@tonic-gate struct fd_char fdchar; 19277c478bd9Sstevel@tonic-gate bpb_t compare; 19287c478bd9Sstevel@tonic-gate int fd_ioctl_worked = 0; 19297c478bd9Sstevel@tonic-gate int fatents; 19307c478bd9Sstevel@tonic-gate 19317c478bd9Sstevel@tonic-gate /* 19327c478bd9Sstevel@tonic-gate * For all non-floppy cases we expect to find a 16-bit FAT 19337c478bd9Sstevel@tonic-gate */ 19347c478bd9Sstevel@tonic-gate int expectfatsize = 16; 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate compare = *wbpb; 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate if (!suffix) { 19397c478bd9Sstevel@tonic-gate if (ioctl(fd, FDIOGCHAR, &fdchar) != -1) { 19407c478bd9Sstevel@tonic-gate expectfatsize = 12; 19417c478bd9Sstevel@tonic-gate fd_ioctl_worked++; 19427c478bd9Sstevel@tonic-gate } 19437c478bd9Sstevel@tonic-gate } 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate if (fd_ioctl_worked) { 19467c478bd9Sstevel@tonic-gate #ifdef sparc 19477c478bd9Sstevel@tonic-gate fdchar.fdc_medium = 3; 19487c478bd9Sstevel@tonic-gate #endif 19497c478bd9Sstevel@tonic-gate GetSize = GetSPT = GetSPC = GetTPC = GetBPF = 1; 19507c478bd9Sstevel@tonic-gate lookup_floppy(&fdchar, &compare); 19517c478bd9Sstevel@tonic-gate if (compare.bpb.heads != wbpb->bpb.heads) { 19527c478bd9Sstevel@tonic-gate (*prtntrk)++; 19537c478bd9Sstevel@tonic-gate (*dashos)++; 19547c478bd9Sstevel@tonic-gate } 19557c478bd9Sstevel@tonic-gate if (compare.bpb.sectors_per_track != 19567c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track) { 19577c478bd9Sstevel@tonic-gate (*prtnsect)++; 19587c478bd9Sstevel@tonic-gate (*dashos)++; 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate } else { 19617c478bd9Sstevel@tonic-gate int dk_ioctl_worked = 1; 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate if (!suffix) { 19647c478bd9Sstevel@tonic-gate (*prtfdisk)++; 19657c478bd9Sstevel@tonic-gate (*prtsize)++; 19667c478bd9Sstevel@tonic-gate *dashos += 2; 19677c478bd9Sstevel@tonic-gate } 1968f127cb91Sfrankho if (ioctl(fd, DKIOCG_VIRTGEOM, &dginfo) == -1 && 1969f127cb91Sfrankho ioctl(fd, DKIOCG_PHYGEOM, &dginfo) == -1 && 1970f127cb91Sfrankho ioctl(fd, DKIOCGGEOM, &dginfo) == -1) { 19717c478bd9Sstevel@tonic-gate *prtnsect = *prtntrk = 1; 19727c478bd9Sstevel@tonic-gate *dashos += 2; 19737c478bd9Sstevel@tonic-gate dk_ioctl_worked = 0; 19747c478bd9Sstevel@tonic-gate } 19757c478bd9Sstevel@tonic-gate if (dk_ioctl_worked) { 19767c478bd9Sstevel@tonic-gate if (dginfo.dkg_nhead != wbpb->bpb.heads) { 19777c478bd9Sstevel@tonic-gate (*prtntrk)++; 19787c478bd9Sstevel@tonic-gate (*dashos)++; 19797c478bd9Sstevel@tonic-gate } 19807c478bd9Sstevel@tonic-gate if (dginfo.dkg_nsect != 19817c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_track) { 19827c478bd9Sstevel@tonic-gate (*prtnsect)++; 19837c478bd9Sstevel@tonic-gate (*dashos)++; 19847c478bd9Sstevel@tonic-gate } 19857c478bd9Sstevel@tonic-gate } 19867c478bd9Sstevel@tonic-gate GetBPF = GetSPC = 1; 19877c478bd9Sstevel@tonic-gate compute_cluster_size(&compare); 19887c478bd9Sstevel@tonic-gate } 19897c478bd9Sstevel@tonic-gate 19907c478bd9Sstevel@tonic-gate if (!*prtfdisk && TotSize != wbpb->bpb.sectors_in_volume && 19917c478bd9Sstevel@tonic-gate TotSize != wbpb->bpb.sectors_in_logical_volume) { 19927c478bd9Sstevel@tonic-gate (*dashos)++; 19937c478bd9Sstevel@tonic-gate (*prtsize)++; 19947c478bd9Sstevel@tonic-gate } 19957c478bd9Sstevel@tonic-gate 19967c478bd9Sstevel@tonic-gate if (compare.bpb.sectors_per_cluster != wbpb->bpb.sectors_per_cluster) { 19977c478bd9Sstevel@tonic-gate (*dashos)++; 19987c478bd9Sstevel@tonic-gate (*prtspc)++; 19997c478bd9Sstevel@tonic-gate } 20007c478bd9Sstevel@tonic-gate 20017c478bd9Sstevel@tonic-gate if (compare.bpb.hidden_sectors != wbpb->bpb.hidden_sectors) { 20027c478bd9Sstevel@tonic-gate (*dashos)++; 20037c478bd9Sstevel@tonic-gate (*prthidden)++; 20047c478bd9Sstevel@tonic-gate } 20057c478bd9Sstevel@tonic-gate 20067c478bd9Sstevel@tonic-gate if (compare.bpb.resv_sectors != wbpb->bpb.resv_sectors) { 20077c478bd9Sstevel@tonic-gate (*dashos)++; 20087c478bd9Sstevel@tonic-gate (*prtrsrvd)++; 20097c478bd9Sstevel@tonic-gate } 20107c478bd9Sstevel@tonic-gate 20117c478bd9Sstevel@tonic-gate /* 20127c478bd9Sstevel@tonic-gate * Compute approximate Fatentsize. It's approximate because the 20137c478bd9Sstevel@tonic-gate * size of the FAT may not be exactly a multiple of the number of 20147c478bd9Sstevel@tonic-gate * clusters. It should be close, though. 20157c478bd9Sstevel@tonic-gate */ 20167c478bd9Sstevel@tonic-gate if (MakeFAT32) { 20177c478bd9Sstevel@tonic-gate Fatentsize = 32; 20187c478bd9Sstevel@tonic-gate (*dashos)++; 20197c478bd9Sstevel@tonic-gate (*prtbpf)++; 20207c478bd9Sstevel@tonic-gate } else { 20217c478bd9Sstevel@tonic-gate fatents = wbpb->bpb.sectors_per_fat * BPSEC * 2 / 3; 20227c478bd9Sstevel@tonic-gate if (fatents >= TotalClusters && wbpb->ebpb.type[4] == '2') 20237c478bd9Sstevel@tonic-gate Fatentsize = 12; 20247c478bd9Sstevel@tonic-gate else 20257c478bd9Sstevel@tonic-gate Fatentsize = 16; 20267c478bd9Sstevel@tonic-gate if (Fatentsize != expectfatsize) { 20277c478bd9Sstevel@tonic-gate (*dashos)++; 20287c478bd9Sstevel@tonic-gate (*prtbpf)++; 20297c478bd9Sstevel@tonic-gate } 20307c478bd9Sstevel@tonic-gate } 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate 20337c478bd9Sstevel@tonic-gate static 20347c478bd9Sstevel@tonic-gate void 20357c478bd9Sstevel@tonic-gate print_reproducing_command(int fd, char *actualdisk, char *suffix, bpb_t *wbpb) 20367c478bd9Sstevel@tonic-gate { 20377c478bd9Sstevel@tonic-gate int needcomma = 0; 20387c478bd9Sstevel@tonic-gate int prthidden = 0; 20397c478bd9Sstevel@tonic-gate int prtrsrvd = 0; 20407c478bd9Sstevel@tonic-gate int prtfdisk = 0; 20417c478bd9Sstevel@tonic-gate int prtnsect = 0; 20427c478bd9Sstevel@tonic-gate int prtntrk = 0; 20437c478bd9Sstevel@tonic-gate int prtsize = 0; 20447c478bd9Sstevel@tonic-gate int prtbpf = 0; 20457c478bd9Sstevel@tonic-gate int prtspc = 0; 20467c478bd9Sstevel@tonic-gate int dashos = 0; 20477c478bd9Sstevel@tonic-gate int ll, i; 20487c478bd9Sstevel@tonic-gate 20497c478bd9Sstevel@tonic-gate compare_existing_with_computed(fd, suffix, wbpb, 20507c478bd9Sstevel@tonic-gate &prtsize, &prtspc, &prtbpf, &prtnsect, &prtntrk, 20517c478bd9Sstevel@tonic-gate &prtfdisk, &prthidden, &prtrsrvd, &dashos); 20527c478bd9Sstevel@tonic-gate 20537c478bd9Sstevel@tonic-gate /* 20547c478bd9Sstevel@tonic-gate * Print out the command line they can use to reproduce the 20557c478bd9Sstevel@tonic-gate * file system. 20567c478bd9Sstevel@tonic-gate */ 20577c478bd9Sstevel@tonic-gate (void) printf("mkfs -F pcfs"); 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate ll = min(11, (int)strlen((char *)wbpb->ebpb.volume_label)); 20607c478bd9Sstevel@tonic-gate /* 20617c478bd9Sstevel@tonic-gate * First, eliminate trailing spaces. Now compare the name against 20627c478bd9Sstevel@tonic-gate * our default label. If there's a match we don't need to print 20637c478bd9Sstevel@tonic-gate * any label info. 20647c478bd9Sstevel@tonic-gate */ 20657c478bd9Sstevel@tonic-gate i = ll; 2066f127cb91Sfrankho while (wbpb->ebpb.volume_label[--i] == ' ') 2067f127cb91Sfrankho ; 20687c478bd9Sstevel@tonic-gate ll = i; 20697c478bd9Sstevel@tonic-gate 20707c478bd9Sstevel@tonic-gate if (ll == strlen(DEFAULT_LABEL) - 1) { 20717c478bd9Sstevel@tonic-gate char cmpbuf[11]; 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate (void) strcpy(cmpbuf, DEFAULT_LABEL); 20747c478bd9Sstevel@tonic-gate for (i = ll; i >= 0; i--) { 20757c478bd9Sstevel@tonic-gate if (cmpbuf[i] != 20767c478bd9Sstevel@tonic-gate toupper((int)(wbpb->ebpb.volume_label[i]))) { 20777c478bd9Sstevel@tonic-gate break; 20787c478bd9Sstevel@tonic-gate } 20797c478bd9Sstevel@tonic-gate } 20807c478bd9Sstevel@tonic-gate if (i < 0) 20817c478bd9Sstevel@tonic-gate ll = i; 20827c478bd9Sstevel@tonic-gate } 20837c478bd9Sstevel@tonic-gate 20847c478bd9Sstevel@tonic-gate if (ll >= 0) { 20857c478bd9Sstevel@tonic-gate (void) printf(" -o "); 20867c478bd9Sstevel@tonic-gate (void) printf("b=\""); 20877c478bd9Sstevel@tonic-gate for (i = 0; i <= ll; i++) { 20887c478bd9Sstevel@tonic-gate (void) printf("%c", wbpb->ebpb.volume_label[i]); 20897c478bd9Sstevel@tonic-gate } 20907c478bd9Sstevel@tonic-gate (void) printf("\""); 20917c478bd9Sstevel@tonic-gate needcomma++; 20927c478bd9Sstevel@tonic-gate } else if (dashos) { 20937c478bd9Sstevel@tonic-gate (void) printf(" -o "); 20947c478bd9Sstevel@tonic-gate } 20957c478bd9Sstevel@tonic-gate 20967c478bd9Sstevel@tonic-gate #define NEXT_DASH_O dashos--; needcomma++; continue 20977c478bd9Sstevel@tonic-gate 20987c478bd9Sstevel@tonic-gate while (dashos) { 20997c478bd9Sstevel@tonic-gate if (needcomma) { 21007c478bd9Sstevel@tonic-gate (void) printf(","); 21017c478bd9Sstevel@tonic-gate needcomma = 0; 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate if (prtfdisk) { 21047c478bd9Sstevel@tonic-gate (void) printf("nofdisk"); 21057c478bd9Sstevel@tonic-gate prtfdisk--; 21067c478bd9Sstevel@tonic-gate NEXT_DASH_O; 21077c478bd9Sstevel@tonic-gate } 21087c478bd9Sstevel@tonic-gate if (prtsize) { 21097c478bd9Sstevel@tonic-gate (void) printf("size=%u", wbpb->bpb.sectors_in_volume ? 21107c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_volume : 21117c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_in_logical_volume); 21127c478bd9Sstevel@tonic-gate prtsize--; 21137c478bd9Sstevel@tonic-gate NEXT_DASH_O; 21147c478bd9Sstevel@tonic-gate } 21157c478bd9Sstevel@tonic-gate if (prtnsect) { 21167c478bd9Sstevel@tonic-gate (void) printf("nsect=%d", wbpb->bpb.sectors_per_track); 21177c478bd9Sstevel@tonic-gate prtnsect--; 21187c478bd9Sstevel@tonic-gate NEXT_DASH_O; 21197c478bd9Sstevel@tonic-gate } 21207c478bd9Sstevel@tonic-gate if (prtspc) { 21217c478bd9Sstevel@tonic-gate (void) printf("spc=%d", wbpb->bpb.sectors_per_cluster); 21227c478bd9Sstevel@tonic-gate prtspc--; 21237c478bd9Sstevel@tonic-gate NEXT_DASH_O; 21247c478bd9Sstevel@tonic-gate } 21257c478bd9Sstevel@tonic-gate if (prtntrk) { 21267c478bd9Sstevel@tonic-gate (void) printf("ntrack=%d", wbpb->bpb.heads); 21277c478bd9Sstevel@tonic-gate prtntrk--; 21287c478bd9Sstevel@tonic-gate NEXT_DASH_O; 21297c478bd9Sstevel@tonic-gate } 21307c478bd9Sstevel@tonic-gate if (prtbpf) { 21317c478bd9Sstevel@tonic-gate (void) printf("fat=%d", Fatentsize); 21327c478bd9Sstevel@tonic-gate prtbpf--; 21337c478bd9Sstevel@tonic-gate NEXT_DASH_O; 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate if (prthidden) { 21367c478bd9Sstevel@tonic-gate (void) printf("hidden=%u", wbpb->bpb.hidden_sectors); 21377c478bd9Sstevel@tonic-gate prthidden--; 21387c478bd9Sstevel@tonic-gate NEXT_DASH_O; 21397c478bd9Sstevel@tonic-gate } 21407c478bd9Sstevel@tonic-gate if (prtrsrvd) { 21417c478bd9Sstevel@tonic-gate (void) printf("reserve=%d", wbpb->bpb.resv_sectors); 21427c478bd9Sstevel@tonic-gate prtrsrvd--; 21437c478bd9Sstevel@tonic-gate NEXT_DASH_O; 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate } 21467c478bd9Sstevel@tonic-gate 21477c478bd9Sstevel@tonic-gate (void) printf(" %s%c%c\n", actualdisk, 21487c478bd9Sstevel@tonic-gate suffix ? ':' : '\0', suffix ? *suffix : '\0'); 21497c478bd9Sstevel@tonic-gate } 21507c478bd9Sstevel@tonic-gate 21517c478bd9Sstevel@tonic-gate /* 21527c478bd9Sstevel@tonic-gate * open_and_examine 21537c478bd9Sstevel@tonic-gate * 21547c478bd9Sstevel@tonic-gate * Open the requested 'dev_name'. Seek to point where 21557c478bd9Sstevel@tonic-gate * we'd expect to find boot sectors, etc., based on any ':partition' 21567c478bd9Sstevel@tonic-gate * attachments to the dev_name. 21577c478bd9Sstevel@tonic-gate * 21587c478bd9Sstevel@tonic-gate * Examine the fields of any existing boot sector and display best 21597c478bd9Sstevel@tonic-gate * approximation of how this fs could be reproduced with this command. 21607c478bd9Sstevel@tonic-gate */ 21617c478bd9Sstevel@tonic-gate static 21627c478bd9Sstevel@tonic-gate int 21637c478bd9Sstevel@tonic-gate open_and_examine(char *dn, bpb_t *wbpb) 21647c478bd9Sstevel@tonic-gate { 21657c478bd9Sstevel@tonic-gate struct stat di; 21667c478bd9Sstevel@tonic-gate off64_t ignored; 21677c478bd9Sstevel@tonic-gate char *actualdisk = NULL; 21687c478bd9Sstevel@tonic-gate char *suffix = NULL; 21697c478bd9Sstevel@tonic-gate int fd; 217065908c77Syu, larry liu - Sun Microsystems - Beijing China struct dk_minfo dkminfo; 21717c478bd9Sstevel@tonic-gate 21727c478bd9Sstevel@tonic-gate if (Verbose) 21737c478bd9Sstevel@tonic-gate (void) printf(gettext("Opening destination device/file.\n")); 21747c478bd9Sstevel@tonic-gate 21757c478bd9Sstevel@tonic-gate actualdisk = stat_actual_disk(dn, &di, &suffix); 21767c478bd9Sstevel@tonic-gate 21777c478bd9Sstevel@tonic-gate /* 21787c478bd9Sstevel@tonic-gate * Destination exists, now find more about it. 21797c478bd9Sstevel@tonic-gate */ 21807c478bd9Sstevel@tonic-gate if (!(S_ISCHR(di.st_mode))) { 21817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 21827c478bd9Sstevel@tonic-gate gettext("\n%s: device name must be a " 21837c478bd9Sstevel@tonic-gate "character special device.\n"), actualdisk); 21847c478bd9Sstevel@tonic-gate exit(2); 21852d700530Sartem } else if ((fd = open(actualdisk, O_RDWR)) < 0) { 21867c478bd9Sstevel@tonic-gate perror(actualdisk); 21877c478bd9Sstevel@tonic-gate exit(2); 21887c478bd9Sstevel@tonic-gate } 21897c478bd9Sstevel@tonic-gate 21907c478bd9Sstevel@tonic-gate /* 219165908c77Syu, larry liu - Sun Microsystems - Beijing China * Check the media sector size 219265908c77Syu, larry liu - Sun Microsystems - Beijing China */ 219365908c77Syu, larry liu - Sun Microsystems - Beijing China if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) { 219465908c77Syu, larry liu - Sun Microsystems - Beijing China if (dkminfo.dki_lbsize != 0 && 219565908c77Syu, larry liu - Sun Microsystems - Beijing China ISP2(dkminfo.dki_lbsize / DEV_BSIZE) && 219665908c77Syu, larry liu - Sun Microsystems - Beijing China dkminfo.dki_lbsize != DEV_BSIZE) { 219765908c77Syu, larry liu - Sun Microsystems - Beijing China (void) fprintf(stderr, 219865908c77Syu, larry liu - Sun Microsystems - Beijing China gettext("The device sector size %u is not " 219965908c77Syu, larry liu - Sun Microsystems - Beijing China "supported by pcfs!\n"), dkminfo.dki_lbsize); 220065908c77Syu, larry liu - Sun Microsystems - Beijing China (void) close(fd); 220165908c77Syu, larry liu - Sun Microsystems - Beijing China exit(1); 220265908c77Syu, larry liu - Sun Microsystems - Beijing China } 220365908c77Syu, larry liu - Sun Microsystems - Beijing China } 220465908c77Syu, larry liu - Sun Microsystems - Beijing China 220565908c77Syu, larry liu - Sun Microsystems - Beijing China /* 22067c478bd9Sstevel@tonic-gate * Find appropriate partition if we were requested to do so. 22077c478bd9Sstevel@tonic-gate */ 22087c478bd9Sstevel@tonic-gate if (suffix && !(seek_partn(fd, suffix, wbpb, &ignored))) { 22097c478bd9Sstevel@tonic-gate (void) close(fd); 22107c478bd9Sstevel@tonic-gate exit(2); 22117c478bd9Sstevel@tonic-gate } 22127c478bd9Sstevel@tonic-gate 22137c478bd9Sstevel@tonic-gate read_existing_bpb(fd, wbpb); 22147c478bd9Sstevel@tonic-gate print_reproducing_command(fd, actualdisk, suffix, wbpb); 22157c478bd9Sstevel@tonic-gate 22167c478bd9Sstevel@tonic-gate return (fd); 22177c478bd9Sstevel@tonic-gate } 22187c478bd9Sstevel@tonic-gate 22197c478bd9Sstevel@tonic-gate /* 22207c478bd9Sstevel@tonic-gate * open_and_seek 22217c478bd9Sstevel@tonic-gate * 22227c478bd9Sstevel@tonic-gate * Open the requested 'dev_name'. Seek to point where 22237c478bd9Sstevel@tonic-gate * we'll write boot sectors, etc., based on any ':partition' 22247c478bd9Sstevel@tonic-gate * attachments to the dev_name. 22257c478bd9Sstevel@tonic-gate * 22267c478bd9Sstevel@tonic-gate * By the time we are finished here, the entire BPB will be 22277c478bd9Sstevel@tonic-gate * filled in, excepting the volume label. 22287c478bd9Sstevel@tonic-gate */ 22297c478bd9Sstevel@tonic-gate static 22307c478bd9Sstevel@tonic-gate int 22317c478bd9Sstevel@tonic-gate open_and_seek(char *dn, bpb_t *wbpb, off64_t *seekto) 22327c478bd9Sstevel@tonic-gate { 22337c478bd9Sstevel@tonic-gate struct fd_char fdchar; 2234f69e9be8Sps156622 struct dk_geom dg; 22357c478bd9Sstevel@tonic-gate struct stat di; 223665908c77Syu, larry liu - Sun Microsystems - Beijing China struct dk_minfo dkminfo; 22377c478bd9Sstevel@tonic-gate char *actualdisk = NULL; 22387c478bd9Sstevel@tonic-gate char *suffix = NULL; 22397c478bd9Sstevel@tonic-gate int fd; 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate if (Verbose) 22427c478bd9Sstevel@tonic-gate (void) printf(gettext("Opening destination device/file.\n")); 22437c478bd9Sstevel@tonic-gate 22447c478bd9Sstevel@tonic-gate /* 22457c478bd9Sstevel@tonic-gate * We hold these truths to be self evident, all BPBs we create 22467c478bd9Sstevel@tonic-gate * will have these values in these fields. 22477c478bd9Sstevel@tonic-gate */ 22487c478bd9Sstevel@tonic-gate wbpb->bpb.num_fats = 2; 22497c478bd9Sstevel@tonic-gate wbpb->bpb.bytes_sector = BPSEC; 22507c478bd9Sstevel@tonic-gate 22517c478bd9Sstevel@tonic-gate /* 22527c478bd9Sstevel@tonic-gate * Assign or use supplied numbers for hidden and 22537c478bd9Sstevel@tonic-gate * reserved sectors in the file system. 22547c478bd9Sstevel@tonic-gate */ 22557c478bd9Sstevel@tonic-gate if (GetResrvd) 22567c478bd9Sstevel@tonic-gate if (MakeFAT32) 22577c478bd9Sstevel@tonic-gate wbpb->bpb.resv_sectors = 32; 22587c478bd9Sstevel@tonic-gate else 22597c478bd9Sstevel@tonic-gate wbpb->bpb.resv_sectors = 1; 22607c478bd9Sstevel@tonic-gate else 22617c478bd9Sstevel@tonic-gate wbpb->bpb.resv_sectors = Resrvd; 22627c478bd9Sstevel@tonic-gate 22637c478bd9Sstevel@tonic-gate wbpb->ebpb.ext_signature = 0x29; /* Magic number for modern format */ 22647c478bd9Sstevel@tonic-gate wbpb->ebpb.volume_id = 0; 22657c478bd9Sstevel@tonic-gate 22667c478bd9Sstevel@tonic-gate if (MakeFAT32) 22677c478bd9Sstevel@tonic-gate fill_fat32_bpb(wbpb); 22687c478bd9Sstevel@tonic-gate 22697c478bd9Sstevel@tonic-gate /* 22707c478bd9Sstevel@tonic-gate * If all output goes to a simple file, call a routine to setup 22717c478bd9Sstevel@tonic-gate * that scenario. Otherwise, try to find the device. 22727c478bd9Sstevel@tonic-gate */ 22737c478bd9Sstevel@tonic-gate if (Outputtofile) 22747c478bd9Sstevel@tonic-gate return (fd = prepare_image_file(dn, wbpb)); 22757c478bd9Sstevel@tonic-gate 22767c478bd9Sstevel@tonic-gate actualdisk = stat_actual_disk(dn, &di, &suffix); 22777c478bd9Sstevel@tonic-gate 22787c478bd9Sstevel@tonic-gate /* 22797c478bd9Sstevel@tonic-gate * Sanity check. If we've been provided a partition-specifying 22807c478bd9Sstevel@tonic-gate * suffix, we shouldn't also have been told to ignore the 22817c478bd9Sstevel@tonic-gate * fdisk table. 22827c478bd9Sstevel@tonic-gate */ 22837c478bd9Sstevel@tonic-gate if (DontUseFdisk && suffix) { 22847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 22857c478bd9Sstevel@tonic-gate gettext("Using 'nofdisk' option precludes " 22867c478bd9Sstevel@tonic-gate "appending logical drive\nspecifier " 22877c478bd9Sstevel@tonic-gate "to the device name.\n")); 22887c478bd9Sstevel@tonic-gate exit(2); 22897c478bd9Sstevel@tonic-gate } 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate /* 22927c478bd9Sstevel@tonic-gate * Destination exists, now find more about it. 22937c478bd9Sstevel@tonic-gate */ 22947c478bd9Sstevel@tonic-gate if (!(S_ISCHR(di.st_mode))) { 22957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 22967c478bd9Sstevel@tonic-gate gettext("\n%s: device name must indicate a " 22977c478bd9Sstevel@tonic-gate "character special device.\n"), actualdisk); 22987c478bd9Sstevel@tonic-gate exit(2); 22992d700530Sartem } else if ((fd = open(actualdisk, O_RDWR)) < 0) { 23007c478bd9Sstevel@tonic-gate perror(actualdisk); 23017c478bd9Sstevel@tonic-gate exit(2); 23027c478bd9Sstevel@tonic-gate } 23037c478bd9Sstevel@tonic-gate 23047c478bd9Sstevel@tonic-gate /* 230565908c77Syu, larry liu - Sun Microsystems - Beijing China * Check the media sector size 230665908c77Syu, larry liu - Sun Microsystems - Beijing China */ 230765908c77Syu, larry liu - Sun Microsystems - Beijing China if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) { 230865908c77Syu, larry liu - Sun Microsystems - Beijing China if (dkminfo.dki_lbsize != 0 && 230965908c77Syu, larry liu - Sun Microsystems - Beijing China ISP2(dkminfo.dki_lbsize / DEV_BSIZE) && 231065908c77Syu, larry liu - Sun Microsystems - Beijing China dkminfo.dki_lbsize != DEV_BSIZE) { 231165908c77Syu, larry liu - Sun Microsystems - Beijing China (void) fprintf(stderr, 231265908c77Syu, larry liu - Sun Microsystems - Beijing China gettext("The device sector size %u is not " 231365908c77Syu, larry liu - Sun Microsystems - Beijing China "supported by pcfs!\n"), dkminfo.dki_lbsize); 231465908c77Syu, larry liu - Sun Microsystems - Beijing China (void) close(fd); 231565908c77Syu, larry liu - Sun Microsystems - Beijing China exit(1); 231665908c77Syu, larry liu - Sun Microsystems - Beijing China } 231765908c77Syu, larry liu - Sun Microsystems - Beijing China } 231865908c77Syu, larry liu - Sun Microsystems - Beijing China 231965908c77Syu, larry liu - Sun Microsystems - Beijing China /* 23207c478bd9Sstevel@tonic-gate * Find appropriate partition if we were requested to do so. 23217c478bd9Sstevel@tonic-gate */ 23227c478bd9Sstevel@tonic-gate if (suffix && !(seek_partn(fd, suffix, wbpb, seekto))) { 23237c478bd9Sstevel@tonic-gate (void) close(fd); 23247c478bd9Sstevel@tonic-gate exit(2); 23257c478bd9Sstevel@tonic-gate } 23267c478bd9Sstevel@tonic-gate 23277c478bd9Sstevel@tonic-gate if (!suffix) { 23287c478bd9Sstevel@tonic-gate /* 23297c478bd9Sstevel@tonic-gate * We have one of two possibilities. Chances are we have 23307c478bd9Sstevel@tonic-gate * a floppy drive. But the user may be trying to format 23317c478bd9Sstevel@tonic-gate * some weird drive that we don't know about and is supplying 23327c478bd9Sstevel@tonic-gate * all the important values. In that case, they should have set 23337c478bd9Sstevel@tonic-gate * the 'nofdisk' flag. 23347c478bd9Sstevel@tonic-gate * 23357c478bd9Sstevel@tonic-gate * If 'nofdisk' isn't set, do a floppy-specific ioctl to 23367c478bd9Sstevel@tonic-gate * get the remainder of our info. If the ioctl fails, we have 23377c478bd9Sstevel@tonic-gate * a good idea that they aren't really on a floppy. In that 23387c478bd9Sstevel@tonic-gate * case, they should have given us a partition specifier. 23397c478bd9Sstevel@tonic-gate */ 23407c478bd9Sstevel@tonic-gate if (DontUseFdisk) { 23417c478bd9Sstevel@tonic-gate if (!(seek_nofdisk(fd, wbpb, seekto))) { 23427c478bd9Sstevel@tonic-gate (void) close(fd); 23437c478bd9Sstevel@tonic-gate exit(2); 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate find_fixed_details(fd, wbpb); 23467c478bd9Sstevel@tonic-gate } else if (ioctl(fd, FDIOGCHAR, &fdchar) == -1) { 2347f69e9be8Sps156622 /* 2348f69e9be8Sps156622 * It is possible that we are trying to use floppy 2349f69e9be8Sps156622 * specific FDIOGCHAR ioctl on USB floppy. Since sd 2350f69e9be8Sps156622 * driver, by which USB floppy is handled, doesn't 2351f69e9be8Sps156622 * support it, we can try to use disk DKIOCGGEOM ioctl 2352f69e9be8Sps156622 * to retrieve data we need. sd driver itself 2353f69e9be8Sps156622 * determines floppy disk by number of blocks 2354f69e9be8Sps156622 * (<=0x1000), then it sets geometry to 80 cylinders, 2355f69e9be8Sps156622 * 2 heads. 2356f69e9be8Sps156622 * 2357f69e9be8Sps156622 * Note that DKIOCGGEOM cannot supply us with type 2358f69e9be8Sps156622 * of media (e.g. 3.5" or 5.25"). We will set it to 2359f69e9be8Sps156622 * 3 (3.5") which is most probable value. 2360f69e9be8Sps156622 */ 23617c478bd9Sstevel@tonic-gate if (errno == ENOTTY) { 2362f69e9be8Sps156622 if (ioctl(fd, DKIOCGGEOM, &dg) != -1 && 2363f69e9be8Sps156622 dg.dkg_ncyl == 80 && dg.dkg_nhead == 2) { 2364f69e9be8Sps156622 fdchar.fdc_ncyl = dg.dkg_ncyl; 2365f69e9be8Sps156622 fdchar.fdc_medium = 3; 2366f69e9be8Sps156622 fdchar.fdc_secptrack = dg.dkg_nsect; 2367f69e9be8Sps156622 fdchar.fdc_nhead = dg.dkg_nhead; 2368f69e9be8Sps156622 lookup_floppy(&fdchar, wbpb); 2369f69e9be8Sps156622 } else { 23707c478bd9Sstevel@tonic-gate partn_lecture(actualdisk); 23717c478bd9Sstevel@tonic-gate (void) close(fd); 23727c478bd9Sstevel@tonic-gate exit(2); 23737c478bd9Sstevel@tonic-gate } 2374f69e9be8Sps156622 } 23757c478bd9Sstevel@tonic-gate } else { 23767c478bd9Sstevel@tonic-gate #ifdef sparc 23777c478bd9Sstevel@tonic-gate fdchar.fdc_medium = 3; 23787c478bd9Sstevel@tonic-gate #endif 23797c478bd9Sstevel@tonic-gate lookup_floppy(&fdchar, wbpb); 23807c478bd9Sstevel@tonic-gate } 23817c478bd9Sstevel@tonic-gate } else { 23827c478bd9Sstevel@tonic-gate find_fixed_details(fd, wbpb); 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate return (fd); 23867c478bd9Sstevel@tonic-gate } 23877c478bd9Sstevel@tonic-gate 23887c478bd9Sstevel@tonic-gate /* 23897c478bd9Sstevel@tonic-gate * The following is a copy of MS-DOS 4.0 boot block. 23907c478bd9Sstevel@tonic-gate * It consists of the BIOS parameter block, and a disk 23917c478bd9Sstevel@tonic-gate * bootstrap program. 23927c478bd9Sstevel@tonic-gate * 23937c478bd9Sstevel@tonic-gate * The BIOS parameter block contains the right values 23947c478bd9Sstevel@tonic-gate * for the 3.5" high-density 1.44MB floppy format. 23957c478bd9Sstevel@tonic-gate * 23967c478bd9Sstevel@tonic-gate * This will be our default boot sector, if the user 23977c478bd9Sstevel@tonic-gate * didn't point us at a different one. 23987c478bd9Sstevel@tonic-gate * 23997c478bd9Sstevel@tonic-gate */ 24007c478bd9Sstevel@tonic-gate static 24017c478bd9Sstevel@tonic-gate uchar_t DefBootSec[512] = { 24027c478bd9Sstevel@tonic-gate 0xeb, 0x3c, 0x90, /* 8086 short jump + displacement + NOP */ 24037c478bd9Sstevel@tonic-gate 'M', 'S', 'D', 'O', 'S', '4', '.', '0', /* OEM name & version */ 24047c478bd9Sstevel@tonic-gate 0x00, 0x02, 0x01, 0x01, 0x00, 24057c478bd9Sstevel@tonic-gate 0x02, 0xe0, 0x00, 0x40, 0x0b, 24067c478bd9Sstevel@tonic-gate 0xf0, 0x09, 0x00, 0x12, 0x00, 24077c478bd9Sstevel@tonic-gate 0x02, 0x00, 24087c478bd9Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00, 24097c478bd9Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00, 24107c478bd9Sstevel@tonic-gate 0x00, 0x00, 24117c478bd9Sstevel@tonic-gate 0x29, 0x00, 0x00, 0x00, 0x00, 24127c478bd9Sstevel@tonic-gate 'N', 'O', 'N', 'A', 'M', 'E', ' ', ' ', ' ', ' ', ' ', 24137c478bd9Sstevel@tonic-gate 'F', 'A', 'T', '1', '2', ' ', ' ', ' ', 24147c478bd9Sstevel@tonic-gate 0xfa, 0x33, 24157c478bd9Sstevel@tonic-gate 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x16, 0x07, 24167c478bd9Sstevel@tonic-gate 0xbb, 0x78, 0x00, 0x36, 0xc5, 0x37, 0x1e, 0x56, 24177c478bd9Sstevel@tonic-gate 0x16, 0x53, 0xbf, 0x3e, 0x7c, 0xb9, 0x0b, 0x00, 24187c478bd9Sstevel@tonic-gate 0xfc, 0xf3, 0xa4, 0x06, 0x1f, 0xc6, 0x45, 0xfe, 24197c478bd9Sstevel@tonic-gate 0x0f, 0x8b, 0x0e, 0x18, 0x7c, 0x88, 0x4d, 0xf9, 24207c478bd9Sstevel@tonic-gate 0x89, 0x47, 0x02, 0xc7, 0x07, 0x3e, 0x7c, 0xfb, 24217c478bd9Sstevel@tonic-gate 0xcd, 0x13, 0x72, 0x7c, 0x33, 0xc0, 0x39, 0x06, 24227c478bd9Sstevel@tonic-gate 0x13, 0x7c, 0x74, 0x08, 0x8b, 0x0e, 0x13, 0x7c, 24237c478bd9Sstevel@tonic-gate 0x89, 0x0e, 0x20, 0x7c, 0xa0, 0x10, 0x7c, 0xf7, 24247c478bd9Sstevel@tonic-gate 0x26, 0x16, 0x7c, 0x03, 0x06, 0x1c, 0x7c, 0x13, 24257c478bd9Sstevel@tonic-gate 0x16, 0x1e, 0x7c, 0x03, 0x06, 0x0e, 0x7c, 0x83, 24267c478bd9Sstevel@tonic-gate 0xd2, 0x00, 0xa3, 0x50, 0x7c, 0x89, 0x16, 0x52, 24277c478bd9Sstevel@tonic-gate 0x7c, 0xa3, 0x49, 0x7c, 0x89, 0x16, 0x4b, 0x7c, 24287c478bd9Sstevel@tonic-gate 0xb8, 0x20, 0x00, 0xf7, 0x26, 0x11, 0x7c, 0x8b, 24297c478bd9Sstevel@tonic-gate 0x1e, 0x0b, 0x7c, 0x03, 0xc3, 0x48, 0xf7, 0xf3, 24307c478bd9Sstevel@tonic-gate 0x01, 0x06, 0x49, 0x7c, 0x83, 0x16, 0x4b, 0x7c, 24317c478bd9Sstevel@tonic-gate 0x00, 0xbb, 0x00, 0x05, 0x8b, 0x16, 0x52, 0x7c, 24327c478bd9Sstevel@tonic-gate 0xa1, 0x50, 0x7c, 0xe8, 0x87, 0x00, 0x72, 0x20, 24337c478bd9Sstevel@tonic-gate 0xb0, 0x01, 0xe8, 0xa1, 0x00, 0x72, 0x19, 0x8b, 24347c478bd9Sstevel@tonic-gate 0xfb, 0xb9, 0x0b, 0x00, 0xbe, 0xdb, 0x7d, 0xf3, 24357c478bd9Sstevel@tonic-gate 0xa6, 0x75, 0x0d, 0x8d, 0x7f, 0x20, 0xbe, 0xe6, 24367c478bd9Sstevel@tonic-gate 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x18, 24377c478bd9Sstevel@tonic-gate 0xbe, 0x93, 0x7d, 0xe8, 0x51, 0x00, 0x32, 0xe4, 24387c478bd9Sstevel@tonic-gate 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x04, 0x8f, 0x44, 24397c478bd9Sstevel@tonic-gate 0x02, 0xcd, 0x19, 0x58, 0x58, 0x58, 0xeb, 0xe8, 24407c478bd9Sstevel@tonic-gate 0xbb, 0x00, 0x07, 0xb9, 0x03, 0x00, 0xa1, 0x49, 24417c478bd9Sstevel@tonic-gate 0x7c, 0x8b, 0x16, 0x4b, 0x7c, 0x50, 0x52, 0x51, 24427c478bd9Sstevel@tonic-gate 0xe8, 0x3a, 0x00, 0x72, 0xe6, 0xb0, 0x01, 0xe8, 24437c478bd9Sstevel@tonic-gate 0x54, 0x00, 0x59, 0x5a, 0x58, 0x72, 0xc9, 0x05, 24447c478bd9Sstevel@tonic-gate 0x01, 0x00, 0x83, 0xd2, 0x00, 0x03, 0x1e, 0x0b, 24457c478bd9Sstevel@tonic-gate 0x7c, 0xe2, 0xe2, 0x8a, 0x2e, 0x15, 0x7c, 0x8a, 24467c478bd9Sstevel@tonic-gate 0x16, 0x24, 0x7c, 0x8b, 0x1e, 0x49, 0x7c, 0xa1, 24477c478bd9Sstevel@tonic-gate 0x4b, 0x7c, 0xea, 0x00, 0x00, 0x70, 0x00, 0xac, 24487c478bd9Sstevel@tonic-gate 0x0a, 0xc0, 0x74, 0x29, 0xb4, 0x0e, 0xbb, 0x07, 24497c478bd9Sstevel@tonic-gate 0x00, 0xcd, 0x10, 0xeb, 0xf2, 0x3b, 0x16, 0x18, 24507c478bd9Sstevel@tonic-gate 0x7c, 0x73, 0x19, 0xf7, 0x36, 0x18, 0x7c, 0xfe, 24517c478bd9Sstevel@tonic-gate 0xc2, 0x88, 0x16, 0x4f, 0x7c, 0x33, 0xd2, 0xf7, 24527c478bd9Sstevel@tonic-gate 0x36, 0x1a, 0x7c, 0x88, 0x16, 0x25, 0x7c, 0xa3, 24537c478bd9Sstevel@tonic-gate 0x4d, 0x7c, 0xf8, 0xc3, 0xf9, 0xc3, 0xb4, 0x02, 24547c478bd9Sstevel@tonic-gate 0x8b, 0x16, 0x4d, 0x7c, 0xb1, 0x06, 0xd2, 0xe6, 24557c478bd9Sstevel@tonic-gate 0x0a, 0x36, 0x4f, 0x7c, 0x8b, 0xca, 0x86, 0xe9, 24567c478bd9Sstevel@tonic-gate 0x8a, 0x16, 0x24, 0x7c, 0x8a, 0x36, 0x25, 0x7c, 24577c478bd9Sstevel@tonic-gate 0xcd, 0x13, 0xc3, 0x0d, 0x0a, 0x4e, 0x6f, 0x6e, 24587c478bd9Sstevel@tonic-gate 0x2d, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 24597c478bd9Sstevel@tonic-gate 0x64, 0x69, 0x73, 0x6b, 0x20, 0x6f, 0x72, 0x20, 24607c478bd9Sstevel@tonic-gate 0x64, 0x69, 0x73, 0x6b, 0x20, 0x65, 0x72, 0x72, 24617c478bd9Sstevel@tonic-gate 0x6f, 0x72, 0x0d, 0x0a, 0x52, 0x65, 0x70, 0x6c, 24627c478bd9Sstevel@tonic-gate 0x61, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 24637c478bd9Sstevel@tonic-gate 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 24647c478bd9Sstevel@tonic-gate 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x77, 0x68, 24657c478bd9Sstevel@tonic-gate 0x65, 0x6e, 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 24667c478bd9Sstevel@tonic-gate 0x0d, 0x0a, 0x00, 0x49, 0x4f, 0x20, 0x20, 0x20, 24677c478bd9Sstevel@tonic-gate 0x20, 0x20, 0x20, 0x53, 0x59, 0x53, 0x4d, 0x53, 24687c478bd9Sstevel@tonic-gate 0x44, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x53, 0x59, 24697c478bd9Sstevel@tonic-gate 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24707c478bd9Sstevel@tonic-gate 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa 24717c478bd9Sstevel@tonic-gate }; 24727c478bd9Sstevel@tonic-gate 24737c478bd9Sstevel@tonic-gate /* 24747c478bd9Sstevel@tonic-gate * verify_bootblkfile 24757c478bd9Sstevel@tonic-gate * 24767c478bd9Sstevel@tonic-gate * We were provided with the name of a file containing the bootblk 24777c478bd9Sstevel@tonic-gate * to install. Verify it has a valid boot sector as best we can. Any 24787c478bd9Sstevel@tonic-gate * errors and we return a bad file descriptor. Otherwise we fill up the 24797c478bd9Sstevel@tonic-gate * provided buffer with the boot sector, return the file 24807c478bd9Sstevel@tonic-gate * descriptor for later use and leave the file pointer just 24817c478bd9Sstevel@tonic-gate * past the boot sector part of the boot block file. 24827c478bd9Sstevel@tonic-gate */ 24837c478bd9Sstevel@tonic-gate static 24847c478bd9Sstevel@tonic-gate int 24857c478bd9Sstevel@tonic-gate verify_bootblkfile(char *fn, boot_sector_t *bs, ulong_t *blkfilesize) 24867c478bd9Sstevel@tonic-gate { 24877c478bd9Sstevel@tonic-gate struct stat fi; 24887c478bd9Sstevel@tonic-gate int bsfd = -1; 24897c478bd9Sstevel@tonic-gate 24907c478bd9Sstevel@tonic-gate if (stat(fn, &fi)) { 24917c478bd9Sstevel@tonic-gate perror(fn); 24927c478bd9Sstevel@tonic-gate } else if (fi.st_size < BPSEC) { 24937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 24947c478bd9Sstevel@tonic-gate gettext("%s: Too short to be a boot sector.\n"), fn); 24957c478bd9Sstevel@tonic-gate } else if ((bsfd = open(fn, O_RDONLY)) < 0) { 24967c478bd9Sstevel@tonic-gate perror(fn); 24977c478bd9Sstevel@tonic-gate } else if (read(bsfd, bs->buf, BPSEC) < BPSEC) { 24987c478bd9Sstevel@tonic-gate (void) close(bsfd); 24997c478bd9Sstevel@tonic-gate bsfd = -1; 25007c478bd9Sstevel@tonic-gate perror(gettext("Boot block read")); 25017c478bd9Sstevel@tonic-gate } else { 2502f127cb91Sfrankho if ((bs->bs.bs_signature[0] != (BOOTSECSIG & 0xFF) && 2503f127cb91Sfrankho bs->bs.bs_signature[1] != ((BOOTSECSIG >> 8) & 0xFF)) || 25047c478bd9Sstevel@tonic-gate #ifdef i386 2505f127cb91Sfrankho (bs->bs.bs_front.bs_jump_code[0] != OPCODE1 && 2506f127cb91Sfrankho bs->bs.bs_front.bs_jump_code[0] != OPCODE2) 25077c478bd9Sstevel@tonic-gate #else 2508f127cb91Sfrankho (bs->bs.bs_jump_code[0] != OPCODE1 && 2509f127cb91Sfrankho bs->bs.bs_jump_code[0] != OPCODE2) 25107c478bd9Sstevel@tonic-gate #endif 2511a9fcfb29Sfrankho /* CSTYLED */ 2512f127cb91Sfrankho ) { 25137c478bd9Sstevel@tonic-gate (void) close(bsfd); 25147c478bd9Sstevel@tonic-gate bsfd = -1; 25157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 25167c478bd9Sstevel@tonic-gate gettext("Boot block (%s) bogus.\n"), fn); 25177c478bd9Sstevel@tonic-gate } 25187c478bd9Sstevel@tonic-gate *blkfilesize = fi.st_size; 25197c478bd9Sstevel@tonic-gate } 25207c478bd9Sstevel@tonic-gate return (bsfd); 25217c478bd9Sstevel@tonic-gate } 25227c478bd9Sstevel@tonic-gate 25237c478bd9Sstevel@tonic-gate /* 25247c478bd9Sstevel@tonic-gate * verify_firstfile 25257c478bd9Sstevel@tonic-gate * 25267c478bd9Sstevel@tonic-gate * We were provided with the name of a file to be the first file 25277c478bd9Sstevel@tonic-gate * installed on the disk. We just need to verify it exists and 25287c478bd9Sstevel@tonic-gate * find out how big it is. If it doesn't exist, we print a warning 25297c478bd9Sstevel@tonic-gate * message about how the file wasn't found. We don't exit fatally, 25307c478bd9Sstevel@tonic-gate * though, rather we return a size of 0 and the FAT will be built 25317c478bd9Sstevel@tonic-gate * without installing any first file. They can then presumably 25327c478bd9Sstevel@tonic-gate * install the correct first file by hand. 25337c478bd9Sstevel@tonic-gate */ 25347c478bd9Sstevel@tonic-gate static 25357c478bd9Sstevel@tonic-gate int 25367c478bd9Sstevel@tonic-gate verify_firstfile(char *fn, ulong_t *filesize) 25377c478bd9Sstevel@tonic-gate { 25387c478bd9Sstevel@tonic-gate struct stat fi; 25397c478bd9Sstevel@tonic-gate int fd = -1; 25407c478bd9Sstevel@tonic-gate 25417c478bd9Sstevel@tonic-gate *filesize = 0; 25427c478bd9Sstevel@tonic-gate if (stat(fn, &fi) || (fd = open(fn, O_RDONLY)) < 0) { 25437c478bd9Sstevel@tonic-gate perror(fn); 25447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 25457c478bd9Sstevel@tonic-gate gettext("Could not access requested file. It will not\n" 25467c478bd9Sstevel@tonic-gate "be installed in the new file system.\n")); 25477c478bd9Sstevel@tonic-gate } else { 25487c478bd9Sstevel@tonic-gate *filesize = fi.st_size; 25497c478bd9Sstevel@tonic-gate } 25507c478bd9Sstevel@tonic-gate 25517c478bd9Sstevel@tonic-gate return (fd); 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate /* 25557c478bd9Sstevel@tonic-gate * label_volume 25567c478bd9Sstevel@tonic-gate * 25577c478bd9Sstevel@tonic-gate * Fill in BPB with volume label. 25587c478bd9Sstevel@tonic-gate */ 25597c478bd9Sstevel@tonic-gate static 25607c478bd9Sstevel@tonic-gate void 25617c478bd9Sstevel@tonic-gate label_volume(char *lbl, bpb_t *wbpb) 25627c478bd9Sstevel@tonic-gate { 25637c478bd9Sstevel@tonic-gate int ll, i; 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate /* Put a volume label into our BPB. */ 25667c478bd9Sstevel@tonic-gate if (!lbl) 25677c478bd9Sstevel@tonic-gate lbl = DEFAULT_LABEL; 25687c478bd9Sstevel@tonic-gate 25697c478bd9Sstevel@tonic-gate ll = min(11, (int)strlen(lbl)); 25707c478bd9Sstevel@tonic-gate for (i = 0; i < ll; i++) { 25717c478bd9Sstevel@tonic-gate wbpb->ebpb.volume_label[i] = toupper(lbl[i]); 25727c478bd9Sstevel@tonic-gate } 25737c478bd9Sstevel@tonic-gate for (; i < 11; i++) { 25747c478bd9Sstevel@tonic-gate wbpb->ebpb.volume_label[i] = ' '; 25757c478bd9Sstevel@tonic-gate } 25767c478bd9Sstevel@tonic-gate } 25777c478bd9Sstevel@tonic-gate 25787c478bd9Sstevel@tonic-gate static 25797c478bd9Sstevel@tonic-gate int 25807c478bd9Sstevel@tonic-gate copy_bootblk(char *fn, boot_sector_t *bootsect, ulong_t *bootblksize) 25817c478bd9Sstevel@tonic-gate { 25827c478bd9Sstevel@tonic-gate int bsfd = -1; 25837c478bd9Sstevel@tonic-gate 25847c478bd9Sstevel@tonic-gate if (Verbose && fn) 25857c478bd9Sstevel@tonic-gate (void) printf(gettext("Request to install boot " 25867c478bd9Sstevel@tonic-gate "block file %s.\n"), fn); 25877c478bd9Sstevel@tonic-gate else if (Verbose) 25887c478bd9Sstevel@tonic-gate (void) printf(gettext("Request to install DOS boot block.\n")); 25897c478bd9Sstevel@tonic-gate 25907c478bd9Sstevel@tonic-gate /* 25917c478bd9Sstevel@tonic-gate * If they want to install their own boot block, sanity check 25927c478bd9Sstevel@tonic-gate * that block. 25937c478bd9Sstevel@tonic-gate */ 25947c478bd9Sstevel@tonic-gate if (fn) { 25957c478bd9Sstevel@tonic-gate bsfd = verify_bootblkfile(fn, bootsect, bootblksize); 25967c478bd9Sstevel@tonic-gate if (bsfd < 0) { 25977c478bd9Sstevel@tonic-gate exit(3); 25987c478bd9Sstevel@tonic-gate } 25997c478bd9Sstevel@tonic-gate *bootblksize = roundup(*bootblksize, BPSEC); 26007c478bd9Sstevel@tonic-gate } else { 26017c478bd9Sstevel@tonic-gate (void) memcpy(bootsect, DefBootSec, BPSEC); 26027c478bd9Sstevel@tonic-gate *bootblksize = BPSEC; 26037c478bd9Sstevel@tonic-gate } 26047c478bd9Sstevel@tonic-gate 26057c478bd9Sstevel@tonic-gate return (bsfd); 26067c478bd9Sstevel@tonic-gate } 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate /* 26097c478bd9Sstevel@tonic-gate * mark_cluster 26107c478bd9Sstevel@tonic-gate * 26117c478bd9Sstevel@tonic-gate * This routine fills a FAT entry with the value supplied to it as an 26127c478bd9Sstevel@tonic-gate * argument. The fatp argument is assumed to be a pointer to the FAT's 26137c478bd9Sstevel@tonic-gate * 0th entry. The clustnum is the cluster entry that should be updated. 26147c478bd9Sstevel@tonic-gate * The value is the new value for the entry. 26157c478bd9Sstevel@tonic-gate */ 26167c478bd9Sstevel@tonic-gate static 26177c478bd9Sstevel@tonic-gate void 26187c478bd9Sstevel@tonic-gate mark_cluster(uchar_t *fatp, pc_cluster32_t clustnum, uint32_t value) 26197c478bd9Sstevel@tonic-gate { 26207c478bd9Sstevel@tonic-gate uchar_t *ep; 26217c478bd9Sstevel@tonic-gate ulong_t idx; 26227c478bd9Sstevel@tonic-gate 26237c478bd9Sstevel@tonic-gate idx = (Fatentsize == 32) ? clustnum * 4 : 26247c478bd9Sstevel@tonic-gate (Fatentsize == 16) ? clustnum * 2 : clustnum + clustnum/2; 26257c478bd9Sstevel@tonic-gate ep = fatp + idx; 26267c478bd9Sstevel@tonic-gate 26277c478bd9Sstevel@tonic-gate if (Fatentsize == 32) { 26287c478bd9Sstevel@tonic-gate store_32_bits(&ep, value); 26297c478bd9Sstevel@tonic-gate } else if (Fatentsize == 16) { 26307c478bd9Sstevel@tonic-gate store_16_bits(&ep, value); 26317c478bd9Sstevel@tonic-gate } else { 26327c478bd9Sstevel@tonic-gate if (clustnum & 1) { 26337c478bd9Sstevel@tonic-gate *ep = (*ep & 0x0f) | ((value << 4) & 0xf0); 26347c478bd9Sstevel@tonic-gate ep++; 26357c478bd9Sstevel@tonic-gate *ep = (value >> 4) & 0xff; 26367c478bd9Sstevel@tonic-gate } else { 26377c478bd9Sstevel@tonic-gate *ep++ = value & 0xff; 26387c478bd9Sstevel@tonic-gate *ep = (*ep & 0xf0) | ((value >> 8) & 0x0f); 26397c478bd9Sstevel@tonic-gate } 26407c478bd9Sstevel@tonic-gate } 26417c478bd9Sstevel@tonic-gate } 26427c478bd9Sstevel@tonic-gate 26437c478bd9Sstevel@tonic-gate static 26447c478bd9Sstevel@tonic-gate uchar_t * 2645f127cb91Sfrankho build_fat(bpb_t *wbpb, struct fat_od_fsi *fsinfop, ulong_t bootblksize, 26467c478bd9Sstevel@tonic-gate ulong_t *fatsize, char *ffn, int *fffd, ulong_t *ffsize, 26477c478bd9Sstevel@tonic-gate pc_cluster32_t *ffstartclust) 26487c478bd9Sstevel@tonic-gate { 26497c478bd9Sstevel@tonic-gate pc_cluster32_t nextfree, ci; 26507c478bd9Sstevel@tonic-gate uchar_t *fatp; 26517c478bd9Sstevel@tonic-gate ushort_t numclust, numsect; 26527c478bd9Sstevel@tonic-gate int remclust; 26537c478bd9Sstevel@tonic-gate 26547c478bd9Sstevel@tonic-gate /* Alloc space for a FAT and then null it out. */ 26557c478bd9Sstevel@tonic-gate if (Verbose) { 26567c478bd9Sstevel@tonic-gate (void) printf(gettext("BUILD FAT.\n%d sectors per fat.\n"), 26577c478bd9Sstevel@tonic-gate wbpb->bpb.sectors_per_fat ? wbpb->bpb.sectors_per_fat : 26587c478bd9Sstevel@tonic-gate wbpb->bpb32.big_sectors_per_fat); 26597c478bd9Sstevel@tonic-gate } 26607c478bd9Sstevel@tonic-gate 26617c478bd9Sstevel@tonic-gate if (MakeFAT32) { 26627c478bd9Sstevel@tonic-gate *fatsize = BPSEC * wbpb->bpb32.big_sectors_per_fat; 26637c478bd9Sstevel@tonic-gate } else { 26647c478bd9Sstevel@tonic-gate *fatsize = BPSEC * wbpb->bpb.sectors_per_fat; 26657c478bd9Sstevel@tonic-gate } 26660576819eSwyllys 26677c478bd9Sstevel@tonic-gate if (!(fatp = (uchar_t *)malloc(*fatsize))) { 26687c478bd9Sstevel@tonic-gate perror(gettext("FAT table alloc")); 26697c478bd9Sstevel@tonic-gate exit(4); 26707c478bd9Sstevel@tonic-gate } else { 26717c478bd9Sstevel@tonic-gate (void) memset(fatp, 0, *fatsize); 26727c478bd9Sstevel@tonic-gate } 26737c478bd9Sstevel@tonic-gate 26747c478bd9Sstevel@tonic-gate /* Build in-memory FAT */ 26757c478bd9Sstevel@tonic-gate *fatp = wbpb->bpb.media; 26767c478bd9Sstevel@tonic-gate *(fatp + 1) = 0xFF; 26777c478bd9Sstevel@tonic-gate *(fatp + 2) = 0xFF; 26787c478bd9Sstevel@tonic-gate 26797c478bd9Sstevel@tonic-gate if (Fatentsize == 16) { 26807c478bd9Sstevel@tonic-gate *(fatp + 3) = 0xFF; 26817c478bd9Sstevel@tonic-gate } else if (Fatentsize == 32) { 26827c478bd9Sstevel@tonic-gate *(fatp + 3) = 0x0F; 26837c478bd9Sstevel@tonic-gate *(fatp + 4) = 0xFF; 26847c478bd9Sstevel@tonic-gate *(fatp + 5) = 0xFF; 26857c478bd9Sstevel@tonic-gate *(fatp + 6) = 0xFF; 26867c478bd9Sstevel@tonic-gate *(fatp + 7) = 0x0F; 26877c478bd9Sstevel@tonic-gate } 26887c478bd9Sstevel@tonic-gate 26897c478bd9Sstevel@tonic-gate /* 26907c478bd9Sstevel@tonic-gate * Keep track of clusters used. 26917c478bd9Sstevel@tonic-gate */ 26927c478bd9Sstevel@tonic-gate remclust = TotalClusters; 26937c478bd9Sstevel@tonic-gate nextfree = 2; 26947c478bd9Sstevel@tonic-gate 26957c478bd9Sstevel@tonic-gate /* 26967c478bd9Sstevel@tonic-gate * Get info on first file to install, if any. 26977c478bd9Sstevel@tonic-gate */ 26987c478bd9Sstevel@tonic-gate if (ffn) 26997c478bd9Sstevel@tonic-gate *fffd = verify_firstfile(ffn, ffsize); 27007c478bd9Sstevel@tonic-gate 27017c478bd9Sstevel@tonic-gate /* 27027c478bd9Sstevel@tonic-gate * Compute number of clusters to preserve for bootblk overage. 27037c478bd9Sstevel@tonic-gate * Remember that we already wrote the first sector of the boot block. 27047c478bd9Sstevel@tonic-gate * These clusters are marked BAD to prevent them from being deleted 27057c478bd9Sstevel@tonic-gate * or used. The first available cluster is 2, so we always offset 27067c478bd9Sstevel@tonic-gate * the clusters. 27077c478bd9Sstevel@tonic-gate */ 27087c478bd9Sstevel@tonic-gate numsect = idivceil((bootblksize - BPSEC), BPSEC); 27097c478bd9Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster); 27107c478bd9Sstevel@tonic-gate 27117c478bd9Sstevel@tonic-gate if (Verbose && numclust) 27127c478bd9Sstevel@tonic-gate (void) printf(gettext("Hiding %d excess bootblk cluster(s).\n"), 27137c478bd9Sstevel@tonic-gate numclust); 27147c478bd9Sstevel@tonic-gate for (ci = 0; ci < numclust; ci++) 27157c478bd9Sstevel@tonic-gate mark_cluster(fatp, nextfree++, 27167c478bd9Sstevel@tonic-gate MakeFAT32 ? PCF_BADCLUSTER32 : PCF_BADCLUSTER); 27177c478bd9Sstevel@tonic-gate remclust -= numclust; 27187c478bd9Sstevel@tonic-gate 27197c478bd9Sstevel@tonic-gate /* 27207c478bd9Sstevel@tonic-gate * Reserve a cluster for the root directory on a FAT32. 27217c478bd9Sstevel@tonic-gate */ 27227c478bd9Sstevel@tonic-gate if (MakeFAT32) { 27237c478bd9Sstevel@tonic-gate mark_cluster(fatp, nextfree, PCF_LASTCLUSTER32); 27247c478bd9Sstevel@tonic-gate wbpb->bpb32.root_dir_clust = nextfree++; 27257c478bd9Sstevel@tonic-gate remclust--; 27267c478bd9Sstevel@tonic-gate } 27277c478bd9Sstevel@tonic-gate 27287c478bd9Sstevel@tonic-gate /* 27297c478bd9Sstevel@tonic-gate * Compute and preserve number of clusters for first file. 27307c478bd9Sstevel@tonic-gate */ 27317c478bd9Sstevel@tonic-gate if (*fffd >= 0) { 27327c478bd9Sstevel@tonic-gate *ffstartclust = nextfree; 27337c478bd9Sstevel@tonic-gate numsect = idivceil(*ffsize, BPSEC); 27347c478bd9Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster); 27357c478bd9Sstevel@tonic-gate 27367c478bd9Sstevel@tonic-gate if (numclust > remclust) { 27377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 27387c478bd9Sstevel@tonic-gate gettext("Requested first file too large to be\n" 27397c478bd9Sstevel@tonic-gate "installed in the new file system.\n")); 27407c478bd9Sstevel@tonic-gate (void) close(*fffd); 27417c478bd9Sstevel@tonic-gate *fffd = -1; 27427c478bd9Sstevel@tonic-gate goto finish; 27437c478bd9Sstevel@tonic-gate } 27447c478bd9Sstevel@tonic-gate 27457c478bd9Sstevel@tonic-gate if (Verbose) 27467c478bd9Sstevel@tonic-gate (void) printf(gettext("Reserving %d first file " 27477c478bd9Sstevel@tonic-gate "cluster(s).\n"), numclust); 27487c478bd9Sstevel@tonic-gate for (ci = 0; (int)ci < (int)(numclust-1); ci++, nextfree++) 27497c478bd9Sstevel@tonic-gate mark_cluster(fatp, nextfree, nextfree + 1); 27507c478bd9Sstevel@tonic-gate mark_cluster(fatp, nextfree++, 27517c478bd9Sstevel@tonic-gate MakeFAT32 ? PCF_LASTCLUSTER32 : PCF_LASTCLUSTER); 27527c478bd9Sstevel@tonic-gate remclust -= numclust; 27537c478bd9Sstevel@tonic-gate } 27547c478bd9Sstevel@tonic-gate 27557c478bd9Sstevel@tonic-gate finish: 27567c478bd9Sstevel@tonic-gate if (Verbose) { 27577c478bd9Sstevel@tonic-gate (void) printf(gettext("First sector of FAT")); 27587c478bd9Sstevel@tonic-gate header_for_dump(); 27597c478bd9Sstevel@tonic-gate dump_bytes(fatp, BPSEC); 27607c478bd9Sstevel@tonic-gate } 27617c478bd9Sstevel@tonic-gate 2762f127cb91Sfrankho (void) memset(fsinfop, 0, sizeof (*fsinfop)); 2763f127cb91Sfrankho fsinfop->fsi_leadsig = LE_32(FSI_LEADSIG); 2764f127cb91Sfrankho fsinfop->fsi_strucsig = LE_32(FSI_STRUCSIG); 2765f127cb91Sfrankho fsinfop->fsi_trailsig = LE_32(FSI_TRAILSIG); 2766f127cb91Sfrankho fsinfop->fsi_incore.fs_free_clusters = LE_32(remclust); 2767f127cb91Sfrankho fsinfop->fsi_incore.fs_next_free = LE_32(nextfree); 27687c478bd9Sstevel@tonic-gate return (fatp); 27697c478bd9Sstevel@tonic-gate } 27707c478bd9Sstevel@tonic-gate 27717c478bd9Sstevel@tonic-gate static 27727c478bd9Sstevel@tonic-gate void 27737c478bd9Sstevel@tonic-gate dirent_time_fill(struct pcdir *dep) 27747c478bd9Sstevel@tonic-gate { 27757c478bd9Sstevel@tonic-gate struct timeval tv; 27767c478bd9Sstevel@tonic-gate struct tm *tp; 27777c478bd9Sstevel@tonic-gate ushort_t dostime; 27787c478bd9Sstevel@tonic-gate ushort_t dosday; 27797c478bd9Sstevel@tonic-gate 27807c478bd9Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)0); 27817c478bd9Sstevel@tonic-gate tp = localtime(&tv.tv_sec); 27827c478bd9Sstevel@tonic-gate /* get the time & day into DOS format */ 27837c478bd9Sstevel@tonic-gate dostime = tp->tm_sec / 2; 27847c478bd9Sstevel@tonic-gate dostime |= tp->tm_min << 5; 27857c478bd9Sstevel@tonic-gate dostime |= tp->tm_hour << 11; 27867c478bd9Sstevel@tonic-gate dosday = tp->tm_mday; 27877c478bd9Sstevel@tonic-gate dosday |= (tp->tm_mon + 1) << 5; 27887c478bd9Sstevel@tonic-gate dosday |= (tp->tm_year - 80) << 9; 27897c478bd9Sstevel@tonic-gate dep->pcd_mtime.pct_time = htols(dostime); 27907c478bd9Sstevel@tonic-gate dep->pcd_mtime.pct_date = htols(dosday); 27917c478bd9Sstevel@tonic-gate } 27927c478bd9Sstevel@tonic-gate 27937c478bd9Sstevel@tonic-gate static 27947c478bd9Sstevel@tonic-gate void 27957c478bd9Sstevel@tonic-gate dirent_label_fill(struct pcdir *dep, char *fn) 27967c478bd9Sstevel@tonic-gate { 27977c478bd9Sstevel@tonic-gate int nl, i; 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate /* 28007c478bd9Sstevel@tonic-gate * We spread the volume label across both the NAME and EXT fields 28017c478bd9Sstevel@tonic-gate */ 28027c478bd9Sstevel@tonic-gate nl = min(PCFNAMESIZE, strlen(fn)); 28037c478bd9Sstevel@tonic-gate for (i = 0; i < nl; i++) { 28047c478bd9Sstevel@tonic-gate dep->pcd_filename[i] = toupper(fn[i]); 28057c478bd9Sstevel@tonic-gate } 28067c478bd9Sstevel@tonic-gate if (i < PCFNAMESIZE) { 28077c478bd9Sstevel@tonic-gate for (; i < PCFNAMESIZE; i++) 28087c478bd9Sstevel@tonic-gate dep->pcd_filename[i] = ' '; 28097c478bd9Sstevel@tonic-gate for (i = 0; i < PCFEXTSIZE; i++) 28107c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = ' '; 28117c478bd9Sstevel@tonic-gate return; 28127c478bd9Sstevel@tonic-gate } 28137c478bd9Sstevel@tonic-gate nl = min(PCFEXTSIZE, strlen(fn) - PCFNAMESIZE); 28147c478bd9Sstevel@tonic-gate for (i = 0; i < nl; i++) 28157c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = toupper(fn[i + PCFNAMESIZE]); 28167c478bd9Sstevel@tonic-gate if (i < PCFEXTSIZE) { 28177c478bd9Sstevel@tonic-gate for (; i < PCFEXTSIZE; i++) 28187c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = ' '; 28197c478bd9Sstevel@tonic-gate } 28207c478bd9Sstevel@tonic-gate } 28217c478bd9Sstevel@tonic-gate 28227c478bd9Sstevel@tonic-gate static 28237c478bd9Sstevel@tonic-gate void 28247c478bd9Sstevel@tonic-gate dirent_fname_fill(struct pcdir *dep, char *fn) 28257c478bd9Sstevel@tonic-gate { 28267c478bd9Sstevel@tonic-gate char *fname, *fext; 28277c478bd9Sstevel@tonic-gate int nl, i; 28287c478bd9Sstevel@tonic-gate 28297c478bd9Sstevel@tonic-gate if (fname = strrchr(fn, '/')) { 28307c478bd9Sstevel@tonic-gate fname++; 28317c478bd9Sstevel@tonic-gate } else { 28327c478bd9Sstevel@tonic-gate fname = fn; 28337c478bd9Sstevel@tonic-gate } 28347c478bd9Sstevel@tonic-gate 28357c478bd9Sstevel@tonic-gate if (fext = strrchr(fname, '.')) { 28367c478bd9Sstevel@tonic-gate fext++; 28377c478bd9Sstevel@tonic-gate } else { 28387c478bd9Sstevel@tonic-gate fext = ""; 28397c478bd9Sstevel@tonic-gate } 28407c478bd9Sstevel@tonic-gate 28417c478bd9Sstevel@tonic-gate fname = strtok(fname, "."); 28427c478bd9Sstevel@tonic-gate 28437c478bd9Sstevel@tonic-gate nl = min(PCFNAMESIZE, (int)strlen(fname)); 28447c478bd9Sstevel@tonic-gate for (i = 0; i < nl; i++) { 28457c478bd9Sstevel@tonic-gate dep->pcd_filename[i] = toupper(fname[i]); 28467c478bd9Sstevel@tonic-gate } 28477c478bd9Sstevel@tonic-gate for (; i < PCFNAMESIZE; i++) { 28487c478bd9Sstevel@tonic-gate dep->pcd_filename[i] = ' '; 28497c478bd9Sstevel@tonic-gate } 28507c478bd9Sstevel@tonic-gate 28517c478bd9Sstevel@tonic-gate nl = min(PCFEXTSIZE, (int)strlen(fext)); 28527c478bd9Sstevel@tonic-gate for (i = 0; i < nl; i++) { 28537c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = toupper(fext[i]); 28547c478bd9Sstevel@tonic-gate } 28557c478bd9Sstevel@tonic-gate for (; i < PCFEXTSIZE; i++) { 28567c478bd9Sstevel@tonic-gate dep->pcd_ext[i] = ' '; 28577c478bd9Sstevel@tonic-gate } 28587c478bd9Sstevel@tonic-gate } 28597c478bd9Sstevel@tonic-gate 28607c478bd9Sstevel@tonic-gate static 28617c478bd9Sstevel@tonic-gate uchar_t * 28627c478bd9Sstevel@tonic-gate build_rootdir(bpb_t *wbpb, char *ffn, int fffd, 28637c478bd9Sstevel@tonic-gate ulong_t ffsize, pc_cluster32_t ffstart, ulong_t *rdirsize) 28647c478bd9Sstevel@tonic-gate { 28657c478bd9Sstevel@tonic-gate struct pcdir *rootdirp; 28667c478bd9Sstevel@tonic-gate struct pcdir *entry; 28677c478bd9Sstevel@tonic-gate 28687c478bd9Sstevel@tonic-gate /* 28697c478bd9Sstevel@tonic-gate * Build a root directory. It will have at least one entry, 28707c478bd9Sstevel@tonic-gate * the volume label and a second if the first file was defined. 28717c478bd9Sstevel@tonic-gate */ 28727c478bd9Sstevel@tonic-gate if (MakeFAT32) { 28737c478bd9Sstevel@tonic-gate /* 28747c478bd9Sstevel@tonic-gate * We devote an entire cluster to the root 28757c478bd9Sstevel@tonic-gate * directory on FAT32. 28767c478bd9Sstevel@tonic-gate */ 28777c478bd9Sstevel@tonic-gate *rdirsize = wbpb->bpb.sectors_per_cluster * BPSEC; 28787c478bd9Sstevel@tonic-gate } else { 28797c478bd9Sstevel@tonic-gate *rdirsize = wbpb->bpb.num_root_entries * sizeof (struct pcdir); 28807c478bd9Sstevel@tonic-gate } 28817c478bd9Sstevel@tonic-gate if ((rootdirp = (struct pcdir *)malloc(*rdirsize)) == NULL) { 28827c478bd9Sstevel@tonic-gate perror(gettext("Root directory allocation")); 28837c478bd9Sstevel@tonic-gate exit(4); 28847c478bd9Sstevel@tonic-gate } else { 28857c478bd9Sstevel@tonic-gate entry = rootdirp; 28867c478bd9Sstevel@tonic-gate (void) memset((char *)rootdirp, 0, *rdirsize); 28877c478bd9Sstevel@tonic-gate } 28887c478bd9Sstevel@tonic-gate 28897c478bd9Sstevel@tonic-gate /* Create directory entry for first file, if there is one */ 28907c478bd9Sstevel@tonic-gate if (fffd >= 0) { 28917c478bd9Sstevel@tonic-gate dirent_fname_fill(entry, ffn); 28927c478bd9Sstevel@tonic-gate entry->pcd_attr = Firstfileattr; 28937c478bd9Sstevel@tonic-gate dirent_time_fill(entry); 28947c478bd9Sstevel@tonic-gate entry->pcd_scluster_lo = htols(ffstart); 28957c478bd9Sstevel@tonic-gate if (MakeFAT32) { 28967c478bd9Sstevel@tonic-gate ffstart = ffstart >> 16; 28977c478bd9Sstevel@tonic-gate entry->un.pcd_scluster_hi = htols(ffstart); 28987c478bd9Sstevel@tonic-gate } 28997c478bd9Sstevel@tonic-gate entry->pcd_size = htoli(ffsize); 29007c478bd9Sstevel@tonic-gate entry++; 29017c478bd9Sstevel@tonic-gate } 29027c478bd9Sstevel@tonic-gate 29037c478bd9Sstevel@tonic-gate /* Create directory entry for volume label, if there is one */ 29047c478bd9Sstevel@tonic-gate if (Label != NULL) { 29057c478bd9Sstevel@tonic-gate dirent_label_fill(entry, Label); 29067c478bd9Sstevel@tonic-gate entry->pcd_attr = PCA_ARCH | PCA_LABEL; 29077c478bd9Sstevel@tonic-gate dirent_time_fill(entry); 29087c478bd9Sstevel@tonic-gate entry->pcd_scluster_lo = 0; 29097c478bd9Sstevel@tonic-gate if (MakeFAT32) { 29107c478bd9Sstevel@tonic-gate entry->un.pcd_scluster_hi = 0; 29117c478bd9Sstevel@tonic-gate } 29127c478bd9Sstevel@tonic-gate entry->pcd_size = 0; 29137c478bd9Sstevel@tonic-gate entry++; 29147c478bd9Sstevel@tonic-gate } 29157c478bd9Sstevel@tonic-gate 29167c478bd9Sstevel@tonic-gate if (Verbose) { 29177c478bd9Sstevel@tonic-gate (void) printf(gettext("First two directory entries")); 29187c478bd9Sstevel@tonic-gate header_for_dump(); 29197c478bd9Sstevel@tonic-gate dump_bytes((uchar_t *)rootdirp, 2 * sizeof (struct pcdir)); 29207c478bd9Sstevel@tonic-gate } 29217c478bd9Sstevel@tonic-gate 29227c478bd9Sstevel@tonic-gate return ((uchar_t *)rootdirp); 29237c478bd9Sstevel@tonic-gate } 29247c478bd9Sstevel@tonic-gate 29257c478bd9Sstevel@tonic-gate /* 29267c478bd9Sstevel@tonic-gate * write_rest 29277c478bd9Sstevel@tonic-gate * 29287c478bd9Sstevel@tonic-gate * Write all the bytes from the current file pointer to end of file 29297c478bd9Sstevel@tonic-gate * in the source file out to the destination file. The writes should 29307c478bd9Sstevel@tonic-gate * be padded to whole clusters with 0's if necessary. 29317c478bd9Sstevel@tonic-gate */ 29327c478bd9Sstevel@tonic-gate static 29337c478bd9Sstevel@tonic-gate void 29347c478bd9Sstevel@tonic-gate write_rest(bpb_t *wbpb, char *efn, int dfd, int sfd, int remaining) 29357c478bd9Sstevel@tonic-gate { 29367c478bd9Sstevel@tonic-gate char buf[BPSEC]; 29377c478bd9Sstevel@tonic-gate ushort_t numsect, numclust; 29387c478bd9Sstevel@tonic-gate ushort_t wnumsect, s; 29397c478bd9Sstevel@tonic-gate int doneread = 0; 29407c478bd9Sstevel@tonic-gate int rstat; 29417c478bd9Sstevel@tonic-gate 29427c478bd9Sstevel@tonic-gate /* 29437c478bd9Sstevel@tonic-gate * Compute number of clusters required to contain remaining bytes. 29447c478bd9Sstevel@tonic-gate */ 29457c478bd9Sstevel@tonic-gate numsect = idivceil(remaining, BPSEC); 29467c478bd9Sstevel@tonic-gate numclust = idivceil(numsect, wbpb->bpb.sectors_per_cluster); 29477c478bd9Sstevel@tonic-gate 29487c478bd9Sstevel@tonic-gate wnumsect = numclust * wbpb->bpb.sectors_per_cluster; 29497c478bd9Sstevel@tonic-gate for (s = 0; s < wnumsect; s++) { 29507c478bd9Sstevel@tonic-gate if (!doneread) { 29517c478bd9Sstevel@tonic-gate if ((rstat = read(sfd, buf, BPSEC)) < 0) { 29527c478bd9Sstevel@tonic-gate perror(efn); 29537c478bd9Sstevel@tonic-gate doneread = 1; 29547c478bd9Sstevel@tonic-gate rstat = 0; 29557c478bd9Sstevel@tonic-gate } else if (rstat == 0) { 29567c478bd9Sstevel@tonic-gate doneread = 1; 29577c478bd9Sstevel@tonic-gate } 29587c478bd9Sstevel@tonic-gate (void) memset(&(buf[rstat]), 0, BPSEC - rstat); 29597c478bd9Sstevel@tonic-gate } 29607c478bd9Sstevel@tonic-gate if (write(dfd, buf, BPSEC) != BPSEC) { 29617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Copying ")); 29627c478bd9Sstevel@tonic-gate perror(efn); 29637c478bd9Sstevel@tonic-gate } 29647c478bd9Sstevel@tonic-gate } 29657c478bd9Sstevel@tonic-gate } 29667c478bd9Sstevel@tonic-gate 29677c478bd9Sstevel@tonic-gate static 29687c478bd9Sstevel@tonic-gate void 29697c478bd9Sstevel@tonic-gate write_fat32_bootstuff(int fd, boot_sector_t *bsp, 2970f127cb91Sfrankho struct fat_od_fsi *fsinfop, off64_t seekto) 29717c478bd9Sstevel@tonic-gate { 29727c478bd9Sstevel@tonic-gate if (Verbose) { 29737c478bd9Sstevel@tonic-gate (void) printf(gettext("Dump of the fs info sector")); 29747c478bd9Sstevel@tonic-gate header_for_dump(); 2975f127cb91Sfrankho dump_bytes((uchar_t *)fsinfop, sizeof (*fsinfop)); 29767c478bd9Sstevel@tonic-gate } 29777c478bd9Sstevel@tonic-gate 29787c478bd9Sstevel@tonic-gate if (!Notreally) { 29797c478bd9Sstevel@tonic-gate /* 29807c478bd9Sstevel@tonic-gate * FAT32's have an FS info sector, then a backup of the boot 29817c478bd9Sstevel@tonic-gate * sector, and a modified backup of the FS Info sector. 29827c478bd9Sstevel@tonic-gate */ 2983f127cb91Sfrankho if (write(fd, fsinfop, sizeof (*fsinfop)) != BPSEC) { 29847c478bd9Sstevel@tonic-gate perror(gettext("FS info sector write")); 29857c478bd9Sstevel@tonic-gate exit(4); 29867c478bd9Sstevel@tonic-gate } 29877c478bd9Sstevel@tonic-gate if (lseek64(fd, seekto + BKUP_BOOTSECT_OFFSET, SEEK_SET) < 0) { 29887c478bd9Sstevel@tonic-gate (void) close(fd); 29897c478bd9Sstevel@tonic-gate perror(gettext("Boot sector backup seek")); 29907c478bd9Sstevel@tonic-gate exit(4); 29917c478bd9Sstevel@tonic-gate } 29927c478bd9Sstevel@tonic-gate if (write(fd, bsp->buf, sizeof (bsp->buf)) != BPSEC) { 29937c478bd9Sstevel@tonic-gate perror(gettext("Boot sector backup write")); 29947c478bd9Sstevel@tonic-gate exit(4); 29957c478bd9Sstevel@tonic-gate } 29967c478bd9Sstevel@tonic-gate } 29977c478bd9Sstevel@tonic-gate 29987c478bd9Sstevel@tonic-gate /* 29997c478bd9Sstevel@tonic-gate * Second copy of fs info sector is modified to have "don't know" 30007c478bd9Sstevel@tonic-gate * as the number of free clusters 30017c478bd9Sstevel@tonic-gate */ 3002f127cb91Sfrankho fsinfop->fsi_incore.fs_next_free = LE_32(FSINFO_UNKNOWN); 30037c478bd9Sstevel@tonic-gate 30047c478bd9Sstevel@tonic-gate if (Verbose) { 30057c478bd9Sstevel@tonic-gate (void) printf(gettext("Dump of the backup fs info sector")); 30067c478bd9Sstevel@tonic-gate header_for_dump(); 3007f127cb91Sfrankho dump_bytes((uchar_t *)fsinfop, sizeof (*fsinfop)); 30087c478bd9Sstevel@tonic-gate } 30097c478bd9Sstevel@tonic-gate 30107c478bd9Sstevel@tonic-gate if (!Notreally) { 3011f127cb91Sfrankho if (write(fd, fsinfop, sizeof (*fsinfop)) != BPSEC) { 30127c478bd9Sstevel@tonic-gate perror(gettext("FS info sector backup write")); 30137c478bd9Sstevel@tonic-gate exit(4); 30147c478bd9Sstevel@tonic-gate } 30157c478bd9Sstevel@tonic-gate } 30167c478bd9Sstevel@tonic-gate } 30177c478bd9Sstevel@tonic-gate 30187c478bd9Sstevel@tonic-gate static 30197c478bd9Sstevel@tonic-gate void 30207c478bd9Sstevel@tonic-gate write_bootsects(int fd, boot_sector_t *bsp, bpb_t *wbpb, 3021f127cb91Sfrankho struct fat_od_fsi *fsinfop, off64_t seekto) 30227c478bd9Sstevel@tonic-gate { 30237c478bd9Sstevel@tonic-gate if (MakeFAT32) { 30247c478bd9Sstevel@tonic-gate /* Copy our BPB into bootsec structure */ 30257c478bd9Sstevel@tonic-gate #ifdef i386 30267c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_front.bs_bpb), &(wbpb->bpb), 30277c478bd9Sstevel@tonic-gate sizeof (wbpb->bpb)); 30287c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_bpb32), &(wbpb->bpb32), 30297c478bd9Sstevel@tonic-gate sizeof (wbpb->bpb32)); 30307c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs32.bs_ebpb), &(wbpb->ebpb), 30317c478bd9Sstevel@tonic-gate sizeof (wbpb->ebpb)); 30327c478bd9Sstevel@tonic-gate #else 30337c478bd9Sstevel@tonic-gate swap_pack_bpb32cpy(&(bsp->bs32), wbpb); 30347c478bd9Sstevel@tonic-gate #endif 30357c478bd9Sstevel@tonic-gate } else { 30367c478bd9Sstevel@tonic-gate /* Copy our BPB into bootsec structure */ 30377c478bd9Sstevel@tonic-gate #ifdef i386 30387c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_front.bs_bpb), &(wbpb->bpb), 30397c478bd9Sstevel@tonic-gate sizeof (wbpb->bpb)); 30407c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_ebpb), &(wbpb->ebpb), 30417c478bd9Sstevel@tonic-gate sizeof (wbpb->ebpb)); 30427c478bd9Sstevel@tonic-gate #else 30437c478bd9Sstevel@tonic-gate swap_pack_bpbcpy(&(bsp->bs), wbpb); 30447c478bd9Sstevel@tonic-gate #endif 30457c478bd9Sstevel@tonic-gate 30467c478bd9Sstevel@tonic-gate /* Copy SUN BPB extensions into bootsec structure */ 30477c478bd9Sstevel@tonic-gate if (SunBPBfields) { 30487c478bd9Sstevel@tonic-gate #ifdef i386 30497c478bd9Sstevel@tonic-gate (void) memcpy(&(bsp->bs.bs_sebpb), &(wbpb->sunbpb), 30507c478bd9Sstevel@tonic-gate sizeof (wbpb->sunbpb)); 30517c478bd9Sstevel@tonic-gate #else 30527c478bd9Sstevel@tonic-gate swap_pack_sebpbcpy(&(bsp->bs), wbpb); 30537c478bd9Sstevel@tonic-gate #endif 30547c478bd9Sstevel@tonic-gate } 30557c478bd9Sstevel@tonic-gate } 30567c478bd9Sstevel@tonic-gate 30577c478bd9Sstevel@tonic-gate /* Write boot sector */ 30587c478bd9Sstevel@tonic-gate if (!Notreally && write(fd, bsp->buf, sizeof (bsp->buf)) != BPSEC) { 30597c478bd9Sstevel@tonic-gate perror(gettext("Boot sector write")); 30607c478bd9Sstevel@tonic-gate exit(4); 30617c478bd9Sstevel@tonic-gate } 30627c478bd9Sstevel@tonic-gate 30637c478bd9Sstevel@tonic-gate if (Verbose) { 30647c478bd9Sstevel@tonic-gate (void) printf(gettext("Dump of the boot sector")); 30657c478bd9Sstevel@tonic-gate header_for_dump(); 30667c478bd9Sstevel@tonic-gate dump_bytes(bsp->buf, sizeof (bsp->buf)); 30677c478bd9Sstevel@tonic-gate } 30687c478bd9Sstevel@tonic-gate 30697c478bd9Sstevel@tonic-gate if (MakeFAT32) 30707c478bd9Sstevel@tonic-gate write_fat32_bootstuff(fd, bsp, fsinfop, seekto); 30717c478bd9Sstevel@tonic-gate } 30727c478bd9Sstevel@tonic-gate 30737c478bd9Sstevel@tonic-gate static 30747c478bd9Sstevel@tonic-gate void 30757c478bd9Sstevel@tonic-gate write_fat(int fd, off64_t seekto, char *fn, char *lbl, char *ffn, bpb_t *wbpb) 30767c478bd9Sstevel@tonic-gate { 3077f127cb91Sfrankho struct fat_od_fsi fsinfo; 30787c478bd9Sstevel@tonic-gate pc_cluster32_t ffsc; 30797c478bd9Sstevel@tonic-gate boot_sector_t bootsect; 30807c478bd9Sstevel@tonic-gate uchar_t *fatp, *rdirp; 30817c478bd9Sstevel@tonic-gate ulong_t bootblksize, fatsize, rdirsize, ffsize; 30827c478bd9Sstevel@tonic-gate int bsfd = -1; 30837c478bd9Sstevel@tonic-gate int fffd = -1; 30847c478bd9Sstevel@tonic-gate 30857c478bd9Sstevel@tonic-gate compute_file_area_size(wbpb); 30867c478bd9Sstevel@tonic-gate 30877c478bd9Sstevel@tonic-gate bsfd = copy_bootblk(fn, &bootsect, &bootblksize); 30887c478bd9Sstevel@tonic-gate label_volume(lbl, wbpb); 30897c478bd9Sstevel@tonic-gate 30907c478bd9Sstevel@tonic-gate if (Verbose) 30917c478bd9Sstevel@tonic-gate (void) printf(gettext("Building FAT.\n")); 30927c478bd9Sstevel@tonic-gate fatp = build_fat(wbpb, &fsinfo, bootblksize, &fatsize, 30937c478bd9Sstevel@tonic-gate ffn, &fffd, &ffsize, &ffsc); 30947c478bd9Sstevel@tonic-gate 30957c478bd9Sstevel@tonic-gate write_bootsects(fd, &bootsect, wbpb, &fsinfo, seekto); 30967c478bd9Sstevel@tonic-gate 30977c478bd9Sstevel@tonic-gate if (lseek64(fd, 30987c478bd9Sstevel@tonic-gate seekto + (BPSEC * wbpb->bpb.resv_sectors), SEEK_SET) < 0) { 30997c478bd9Sstevel@tonic-gate (void) close(fd); 31007c478bd9Sstevel@tonic-gate perror(gettext("Seek to end of reserved sectors")); 31017c478bd9Sstevel@tonic-gate exit(4); 31027c478bd9Sstevel@tonic-gate } 31037c478bd9Sstevel@tonic-gate 31047c478bd9Sstevel@tonic-gate /* Write FAT */ 31057c478bd9Sstevel@tonic-gate if (Verbose) 31067c478bd9Sstevel@tonic-gate (void) printf(gettext("Writing FAT(s). %d bytes times %d.\n"), 31077c478bd9Sstevel@tonic-gate fatsize, wbpb->bpb.num_fats); 31087c478bd9Sstevel@tonic-gate if (!Notreally) { 31097c478bd9Sstevel@tonic-gate int nf, wb; 31107c478bd9Sstevel@tonic-gate for (nf = 0; nf < (int)wbpb->bpb.num_fats; nf++) 31117c478bd9Sstevel@tonic-gate if ((wb = write(fd, fatp, fatsize)) != fatsize) { 31127c478bd9Sstevel@tonic-gate perror(gettext("FAT write")); 31137c478bd9Sstevel@tonic-gate exit(4); 31147c478bd9Sstevel@tonic-gate } else { 31157c478bd9Sstevel@tonic-gate if (Verbose) 31167c478bd9Sstevel@tonic-gate (void) printf( 31177c478bd9Sstevel@tonic-gate gettext("Wrote %d bytes\n"), wb); 31187c478bd9Sstevel@tonic-gate } 31197c478bd9Sstevel@tonic-gate } 31207c478bd9Sstevel@tonic-gate free(fatp); 31217c478bd9Sstevel@tonic-gate 31227c478bd9Sstevel@tonic-gate if (Verbose) 31237c478bd9Sstevel@tonic-gate (void) printf(gettext("Building root directory.\n")); 31247c478bd9Sstevel@tonic-gate rdirp = build_rootdir(wbpb, ffn, fffd, ffsize, ffsc, &rdirsize); 31257c478bd9Sstevel@tonic-gate 31267c478bd9Sstevel@tonic-gate /* 31277c478bd9Sstevel@tonic-gate * In non FAT32, root directory exists outside of the file area 31287c478bd9Sstevel@tonic-gate */ 31297c478bd9Sstevel@tonic-gate if (!MakeFAT32) { 31307c478bd9Sstevel@tonic-gate if (Verbose) 3131f127cb91Sfrankho (void) printf(gettext("Writing root directory. " 31327c478bd9Sstevel@tonic-gate "%d bytes.\n"), rdirsize); 31337c478bd9Sstevel@tonic-gate if (!Notreally) { 31347c478bd9Sstevel@tonic-gate if (write(fd, rdirp, rdirsize) != rdirsize) { 31357c478bd9Sstevel@tonic-gate perror(gettext("Root directory write")); 31367c478bd9Sstevel@tonic-gate exit(4); 31377c478bd9Sstevel@tonic-gate } 31387c478bd9Sstevel@tonic-gate } 31397c478bd9Sstevel@tonic-gate free(rdirp); 31407c478bd9Sstevel@tonic-gate } 31417c478bd9Sstevel@tonic-gate 31427c478bd9Sstevel@tonic-gate /* 31437c478bd9Sstevel@tonic-gate * Now write anything that needs to be in the file space. 31447c478bd9Sstevel@tonic-gate */ 31457c478bd9Sstevel@tonic-gate if (bootblksize > BPSEC) { 31467c478bd9Sstevel@tonic-gate if (Verbose) 31477c478bd9Sstevel@tonic-gate (void) printf(gettext("Writing remainder of " 31487c478bd9Sstevel@tonic-gate "boot block.\n")); 31497c478bd9Sstevel@tonic-gate if (!Notreally) 31507c478bd9Sstevel@tonic-gate write_rest(wbpb, fn, fd, bsfd, bootblksize - BPSEC); 31517c478bd9Sstevel@tonic-gate } 31527c478bd9Sstevel@tonic-gate 31537c478bd9Sstevel@tonic-gate if (MakeFAT32) { 31547c478bd9Sstevel@tonic-gate if (Verbose) 3155f127cb91Sfrankho (void) printf(gettext("Writing root directory. " 31567c478bd9Sstevel@tonic-gate "%d bytes.\n"), rdirsize); 31577c478bd9Sstevel@tonic-gate if (!Notreally) { 31587c478bd9Sstevel@tonic-gate if (write(fd, rdirp, rdirsize) != rdirsize) { 31597c478bd9Sstevel@tonic-gate perror(gettext("Root directory write")); 31607c478bd9Sstevel@tonic-gate exit(4); 31617c478bd9Sstevel@tonic-gate } 31627c478bd9Sstevel@tonic-gate } 31637c478bd9Sstevel@tonic-gate free(rdirp); 31647c478bd9Sstevel@tonic-gate } 31657c478bd9Sstevel@tonic-gate 31667c478bd9Sstevel@tonic-gate if (fffd >= 0) { 31677c478bd9Sstevel@tonic-gate if (Verbose) 31687c478bd9Sstevel@tonic-gate (void) printf(gettext("Writing first file.\n")); 31697c478bd9Sstevel@tonic-gate if (!Notreally) 31707c478bd9Sstevel@tonic-gate write_rest(wbpb, ffn, fd, fffd, ffsize); 31717c478bd9Sstevel@tonic-gate } 31727c478bd9Sstevel@tonic-gate } 31737c478bd9Sstevel@tonic-gate 31747c478bd9Sstevel@tonic-gate static 31757c478bd9Sstevel@tonic-gate char *LegalOpts[] = { 31767c478bd9Sstevel@tonic-gate #define NFLAG 0 31777c478bd9Sstevel@tonic-gate "N", 31787c478bd9Sstevel@tonic-gate #define VFLAG 1 31797c478bd9Sstevel@tonic-gate "v", 31807c478bd9Sstevel@tonic-gate #define RFLAG 2 31817c478bd9Sstevel@tonic-gate "r", 31827c478bd9Sstevel@tonic-gate #define HFLAG 3 31837c478bd9Sstevel@tonic-gate "h", 31847c478bd9Sstevel@tonic-gate #define SFLAG 4 31857c478bd9Sstevel@tonic-gate "s", 31867c478bd9Sstevel@tonic-gate #define SUNFLAG 5 31877c478bd9Sstevel@tonic-gate "S", 31887c478bd9Sstevel@tonic-gate #define LABFLAG 6 31897c478bd9Sstevel@tonic-gate "b", 31907c478bd9Sstevel@tonic-gate #define BTRFLAG 7 31917c478bd9Sstevel@tonic-gate "B", 31927c478bd9Sstevel@tonic-gate #define INITFLAG 8 31937c478bd9Sstevel@tonic-gate "i", 31947c478bd9Sstevel@tonic-gate #define SZFLAG 9 31957c478bd9Sstevel@tonic-gate "size", 31967c478bd9Sstevel@tonic-gate #define SECTFLAG 10 31977c478bd9Sstevel@tonic-gate "nsect", 31987c478bd9Sstevel@tonic-gate #define TRKFLAG 11 31997c478bd9Sstevel@tonic-gate "ntrack", 32007c478bd9Sstevel@tonic-gate #define SPCFLAG 12 32017c478bd9Sstevel@tonic-gate "spc", 32027c478bd9Sstevel@tonic-gate #define BPFFLAG 13 32037c478bd9Sstevel@tonic-gate "fat", 32047c478bd9Sstevel@tonic-gate #define FFLAG 14 32057c478bd9Sstevel@tonic-gate "f", 32067c478bd9Sstevel@tonic-gate #define DFLAG 15 32077c478bd9Sstevel@tonic-gate "d", 32087c478bd9Sstevel@tonic-gate #define NOFDISKFLAG 16 32097c478bd9Sstevel@tonic-gate "nofdisk", 32107c478bd9Sstevel@tonic-gate #define RESRVFLAG 17 32117c478bd9Sstevel@tonic-gate "reserve", 32127c478bd9Sstevel@tonic-gate #define HIDDENFLAG 18 32137c478bd9Sstevel@tonic-gate "hidden", 32147c478bd9Sstevel@tonic-gate NULL 32157c478bd9Sstevel@tonic-gate }; 32167c478bd9Sstevel@tonic-gate 32177c478bd9Sstevel@tonic-gate static 32187c478bd9Sstevel@tonic-gate void 32197c478bd9Sstevel@tonic-gate bad_arg(char *option) 32207c478bd9Sstevel@tonic-gate { 32217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 32227c478bd9Sstevel@tonic-gate gettext("Unrecognized option %s.\n"), option); 32237c478bd9Sstevel@tonic-gate usage(); 32247c478bd9Sstevel@tonic-gate exit(2); 32257c478bd9Sstevel@tonic-gate } 32267c478bd9Sstevel@tonic-gate 32277c478bd9Sstevel@tonic-gate static 32287c478bd9Sstevel@tonic-gate void 32297c478bd9Sstevel@tonic-gate missing_arg(char *option) 32307c478bd9Sstevel@tonic-gate { 32317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 32327c478bd9Sstevel@tonic-gate gettext("Option %s requires a value.\n"), option); 32337c478bd9Sstevel@tonic-gate usage(); 32347c478bd9Sstevel@tonic-gate exit(3); 32357c478bd9Sstevel@tonic-gate } 32367c478bd9Sstevel@tonic-gate 32377c478bd9Sstevel@tonic-gate static 32387c478bd9Sstevel@tonic-gate void 32397c478bd9Sstevel@tonic-gate parse_suboptions(char *optsstr) 32407c478bd9Sstevel@tonic-gate { 32417c478bd9Sstevel@tonic-gate char *value; 32427c478bd9Sstevel@tonic-gate int c; 32437c478bd9Sstevel@tonic-gate 32447c478bd9Sstevel@tonic-gate while (*optsstr != '\0') { 32457c478bd9Sstevel@tonic-gate switch (c = getsubopt(&optsstr, LegalOpts, &value)) { 32467c478bd9Sstevel@tonic-gate case NFLAG: 32477c478bd9Sstevel@tonic-gate Notreally++; 32487c478bd9Sstevel@tonic-gate break; 32497c478bd9Sstevel@tonic-gate case VFLAG: 32507c478bd9Sstevel@tonic-gate Verbose++; 32517c478bd9Sstevel@tonic-gate break; 32527c478bd9Sstevel@tonic-gate case RFLAG: 32537c478bd9Sstevel@tonic-gate Firstfileattr |= 0x01; 32547c478bd9Sstevel@tonic-gate break; 32557c478bd9Sstevel@tonic-gate case HFLAG: 32567c478bd9Sstevel@tonic-gate Firstfileattr |= 0x02; 32577c478bd9Sstevel@tonic-gate break; 32587c478bd9Sstevel@tonic-gate case SFLAG: 32597c478bd9Sstevel@tonic-gate Firstfileattr |= 0x04; 32607c478bd9Sstevel@tonic-gate break; 32617c478bd9Sstevel@tonic-gate case SUNFLAG: 32627c478bd9Sstevel@tonic-gate SunBPBfields = 1; 32637c478bd9Sstevel@tonic-gate break; 32647c478bd9Sstevel@tonic-gate case LABFLAG: 32657c478bd9Sstevel@tonic-gate if (value == NULL) { 32667c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 32677c478bd9Sstevel@tonic-gate } else { 32687c478bd9Sstevel@tonic-gate Label = value; 32697c478bd9Sstevel@tonic-gate } 32707c478bd9Sstevel@tonic-gate break; 32717c478bd9Sstevel@tonic-gate case BTRFLAG: 32727c478bd9Sstevel@tonic-gate if (value == NULL) { 32737c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 32747c478bd9Sstevel@tonic-gate } else { 32757c478bd9Sstevel@tonic-gate BootBlkFn = value; 32767c478bd9Sstevel@tonic-gate } 32777c478bd9Sstevel@tonic-gate break; 32787c478bd9Sstevel@tonic-gate case INITFLAG: 32797c478bd9Sstevel@tonic-gate if (value == NULL) { 32807c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 32817c478bd9Sstevel@tonic-gate } else { 32827c478bd9Sstevel@tonic-gate FirstFn = value; 32837c478bd9Sstevel@tonic-gate } 32847c478bd9Sstevel@tonic-gate break; 32857c478bd9Sstevel@tonic-gate case SZFLAG: 32867c478bd9Sstevel@tonic-gate if (value == NULL) { 32877c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 32887c478bd9Sstevel@tonic-gate } else { 32897c478bd9Sstevel@tonic-gate TotSize = atoi(value); 32907c478bd9Sstevel@tonic-gate GetSize = 0; 32917c478bd9Sstevel@tonic-gate } 32927c478bd9Sstevel@tonic-gate break; 32937c478bd9Sstevel@tonic-gate case SECTFLAG: 32947c478bd9Sstevel@tonic-gate if (value == NULL) { 32957c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 32967c478bd9Sstevel@tonic-gate } else { 32977c478bd9Sstevel@tonic-gate SecPerTrk = atoi(value); 32987c478bd9Sstevel@tonic-gate GetSPT = 0; 32997c478bd9Sstevel@tonic-gate } 33007c478bd9Sstevel@tonic-gate break; 33017c478bd9Sstevel@tonic-gate case TRKFLAG: 33027c478bd9Sstevel@tonic-gate if (value == NULL) { 33037c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 33047c478bd9Sstevel@tonic-gate } else { 33057c478bd9Sstevel@tonic-gate TrkPerCyl = atoi(value); 33067c478bd9Sstevel@tonic-gate GetTPC = 0; 33077c478bd9Sstevel@tonic-gate } 33087c478bd9Sstevel@tonic-gate break; 33097c478bd9Sstevel@tonic-gate case SPCFLAG: 33107c478bd9Sstevel@tonic-gate if (value == NULL) { 33117c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 33127c478bd9Sstevel@tonic-gate } else { 33137c478bd9Sstevel@tonic-gate SecPerClust = atoi(value); 33147c478bd9Sstevel@tonic-gate GetSPC = 0; 33157c478bd9Sstevel@tonic-gate } 33167c478bd9Sstevel@tonic-gate break; 33177c478bd9Sstevel@tonic-gate case BPFFLAG: 33187c478bd9Sstevel@tonic-gate if (value == NULL) { 33197c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 33207c478bd9Sstevel@tonic-gate } else { 33217c478bd9Sstevel@tonic-gate BitsPerFAT = atoi(value); 33227c478bd9Sstevel@tonic-gate GetBPF = 0; 33237c478bd9Sstevel@tonic-gate } 33247c478bd9Sstevel@tonic-gate break; 33257c478bd9Sstevel@tonic-gate case NOFDISKFLAG: 33267c478bd9Sstevel@tonic-gate DontUseFdisk = 1; 33277c478bd9Sstevel@tonic-gate break; 33287c478bd9Sstevel@tonic-gate case RESRVFLAG: 33297c478bd9Sstevel@tonic-gate if (value == NULL) { 33307c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 33317c478bd9Sstevel@tonic-gate } else { 33327c478bd9Sstevel@tonic-gate Resrvd = atoi(value); 33337c478bd9Sstevel@tonic-gate GetResrvd = 0; 33347c478bd9Sstevel@tonic-gate } 33357c478bd9Sstevel@tonic-gate break; 33367c478bd9Sstevel@tonic-gate case HIDDENFLAG: 33377c478bd9Sstevel@tonic-gate if (value == NULL) { 33387c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 33397c478bd9Sstevel@tonic-gate } else { 33407c478bd9Sstevel@tonic-gate RelOffset = atoi(value); 33417c478bd9Sstevel@tonic-gate GetOffset = 0; 33427c478bd9Sstevel@tonic-gate } 33437c478bd9Sstevel@tonic-gate break; 33447c478bd9Sstevel@tonic-gate case FFLAG: 33457c478bd9Sstevel@tonic-gate if (value == NULL) { 33467c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 33477c478bd9Sstevel@tonic-gate } else { 33487c478bd9Sstevel@tonic-gate DiskName = value; 33497c478bd9Sstevel@tonic-gate Outputtofile = 1; 33507c478bd9Sstevel@tonic-gate } 33517c478bd9Sstevel@tonic-gate break; 33527c478bd9Sstevel@tonic-gate case DFLAG: 33537c478bd9Sstevel@tonic-gate if (value == NULL) { 33547c478bd9Sstevel@tonic-gate missing_arg(LegalOpts[c]); 33557c478bd9Sstevel@tonic-gate } else { 33567c478bd9Sstevel@tonic-gate Imagesize = atoi(value); 33577c478bd9Sstevel@tonic-gate } 33587c478bd9Sstevel@tonic-gate break; 33597c478bd9Sstevel@tonic-gate default: 33607c478bd9Sstevel@tonic-gate bad_arg(value); 33617c478bd9Sstevel@tonic-gate break; 33627c478bd9Sstevel@tonic-gate } 33637c478bd9Sstevel@tonic-gate } 33647c478bd9Sstevel@tonic-gate } 33657c478bd9Sstevel@tonic-gate 33667c478bd9Sstevel@tonic-gate static 33677c478bd9Sstevel@tonic-gate void 33687c478bd9Sstevel@tonic-gate sanity_check_options(int argc, int optind) 33697c478bd9Sstevel@tonic-gate { 33707c478bd9Sstevel@tonic-gate if (GetFsParams) { 33717c478bd9Sstevel@tonic-gate if (argc - optind != 1) 33727c478bd9Sstevel@tonic-gate usage(); 33737c478bd9Sstevel@tonic-gate return; 33747c478bd9Sstevel@tonic-gate } 33757c478bd9Sstevel@tonic-gate 33767c478bd9Sstevel@tonic-gate if (DontUseFdisk && GetOffset) { 33777c478bd9Sstevel@tonic-gate /* Set default relative offset of zero */ 33787c478bd9Sstevel@tonic-gate RelOffset = 0; 33797c478bd9Sstevel@tonic-gate } 33807c478bd9Sstevel@tonic-gate 33817c478bd9Sstevel@tonic-gate if (BitsPerFAT == 32) 33827c478bd9Sstevel@tonic-gate MakeFAT32 = 1; 33837c478bd9Sstevel@tonic-gate 33847c478bd9Sstevel@tonic-gate if (Outputtofile && (argc - optind)) { 33857c478bd9Sstevel@tonic-gate usage(); 33867c478bd9Sstevel@tonic-gate } else if (Outputtofile && !DiskName) { 33877c478bd9Sstevel@tonic-gate usage(); 33887c478bd9Sstevel@tonic-gate } else if (!Outputtofile && (argc - optind != 1)) { 33897c478bd9Sstevel@tonic-gate usage(); 33907c478bd9Sstevel@tonic-gate } else if (SunBPBfields && !BootBlkFn) { 33917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 33927c478bd9Sstevel@tonic-gate gettext("Use of the 'S' option requires that\n" 33937c478bd9Sstevel@tonic-gate "the 'B=' option also be used.\n\n")); 33947c478bd9Sstevel@tonic-gate usage(); 33957c478bd9Sstevel@tonic-gate } else if (Firstfileattr != 0x20 && !FirstFn) { 33967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 33977c478bd9Sstevel@tonic-gate gettext("Use of the 'r', 'h', or 's' options requires\n" 33987c478bd9Sstevel@tonic-gate "that the 'i=' option also be used.\n\n")); 33997c478bd9Sstevel@tonic-gate usage(); 34007c478bd9Sstevel@tonic-gate } else if (!GetOffset && !DontUseFdisk) { 34017c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 34027c478bd9Sstevel@tonic-gate gettext("Use of the 'hidden' option requires that\n" 34037c478bd9Sstevel@tonic-gate "the 'nofdisk' option also be used.\n\n")); 34047c478bd9Sstevel@tonic-gate usage(); 34057c478bd9Sstevel@tonic-gate } else if (DontUseFdisk && GetSize) { 34067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 34077c478bd9Sstevel@tonic-gate gettext("Use of the 'nofdisk' option requires that\n" 34087c478bd9Sstevel@tonic-gate "the 'size=' option also be used.\n\n")); 34097c478bd9Sstevel@tonic-gate usage(); 34107c478bd9Sstevel@tonic-gate } else if (!GetBPF && 34117c478bd9Sstevel@tonic-gate BitsPerFAT != 12 && BitsPerFAT != 16 && BitsPerFAT != 32) { 3412f127cb91Sfrankho (void) fprintf(stderr, gettext("Invalid Bits/Fat value." 34137c478bd9Sstevel@tonic-gate " Must be 12, 16 or 32.\n")); 34147c478bd9Sstevel@tonic-gate exit(2); 3415*db92b35aSGary Mills } else if (!GetSPC && !(ISP2(SecPerClust) && 3416*db92b35aSGary Mills IN_RANGE(SecPerClust, 1, 128))) { 34177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 34187c478bd9Sstevel@tonic-gate gettext("Invalid Sectors/Cluster value. Must be a " 34197c478bd9Sstevel@tonic-gate "power of 2 between 1 and 128.\n")); 34207c478bd9Sstevel@tonic-gate exit(2); 34217c478bd9Sstevel@tonic-gate } else if (!GetResrvd && (Resrvd < 1 || Resrvd > 0xffff)) { 34227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 34237c478bd9Sstevel@tonic-gate gettext("Invalid number of reserved sectors. " 34247c478bd9Sstevel@tonic-gate "Must be at least 1 but\nno larger than 65535.")); 34257c478bd9Sstevel@tonic-gate exit(2); 34267c478bd9Sstevel@tonic-gate } else if (!GetResrvd && MakeFAT32 && 34277c478bd9Sstevel@tonic-gate (Resrvd < 32 || Resrvd > 0xffff)) { 34287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 34297c478bd9Sstevel@tonic-gate gettext("Invalid number of reserved sectors. " 34307c478bd9Sstevel@tonic-gate "Must be at least 32 but\nno larger than 65535.")); 34317c478bd9Sstevel@tonic-gate exit(2); 34327c478bd9Sstevel@tonic-gate } else if (Imagesize != 3 && Imagesize != 5) { 34337c478bd9Sstevel@tonic-gate usage(); 34347c478bd9Sstevel@tonic-gate } 34357c478bd9Sstevel@tonic-gate } 34367c478bd9Sstevel@tonic-gate 3437c719c59aSjkennedy int 34387c478bd9Sstevel@tonic-gate main(int argc, char **argv) 34397c478bd9Sstevel@tonic-gate { 34407c478bd9Sstevel@tonic-gate off64_t AbsBootSect = 0; 34417c478bd9Sstevel@tonic-gate bpb_t dskparamblk; 34427c478bd9Sstevel@tonic-gate char *string; 34437c478bd9Sstevel@tonic-gate int fd; 34447c478bd9Sstevel@tonic-gate int c; 34457c478bd9Sstevel@tonic-gate 34467c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 34477c478bd9Sstevel@tonic-gate 34487c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 34497c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 34507c478bd9Sstevel@tonic-gate #endif 34517c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 34527c478bd9Sstevel@tonic-gate 34537c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "F:Vmo:")) != EOF) { 34547c478bd9Sstevel@tonic-gate switch (c) { 34557c478bd9Sstevel@tonic-gate case 'F': 34567c478bd9Sstevel@tonic-gate string = optarg; 34577c478bd9Sstevel@tonic-gate if (strcmp(string, "pcfs") != 0) 34587c478bd9Sstevel@tonic-gate usage(); 34597c478bd9Sstevel@tonic-gate break; 34607c478bd9Sstevel@tonic-gate case 'V': 34617c478bd9Sstevel@tonic-gate { 34627c478bd9Sstevel@tonic-gate char *opt_text; 34637c478bd9Sstevel@tonic-gate int opt_count; 34647c478bd9Sstevel@tonic-gate 34657c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 34667c478bd9Sstevel@tonic-gate gettext("mkfs -F pcfs ")); 34677c478bd9Sstevel@tonic-gate for (opt_count = 1; opt_count < argc; 34687c478bd9Sstevel@tonic-gate opt_count++) { 34697c478bd9Sstevel@tonic-gate opt_text = argv[opt_count]; 34707c478bd9Sstevel@tonic-gate if (opt_text) 3471f127cb91Sfrankho (void) fprintf(stdout, 3472f127cb91Sfrankho " %s ", opt_text); 34737c478bd9Sstevel@tonic-gate } 34747c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "\n"); 34757c478bd9Sstevel@tonic-gate } 34767c478bd9Sstevel@tonic-gate break; 34777c478bd9Sstevel@tonic-gate case 'm': 34787c478bd9Sstevel@tonic-gate GetFsParams++; 34797c478bd9Sstevel@tonic-gate break; 34807c478bd9Sstevel@tonic-gate case 'o': 34817c478bd9Sstevel@tonic-gate string = optarg; 34827c478bd9Sstevel@tonic-gate parse_suboptions(string); 34837c478bd9Sstevel@tonic-gate break; 34847c478bd9Sstevel@tonic-gate } 34857c478bd9Sstevel@tonic-gate } 34867c478bd9Sstevel@tonic-gate 34877c478bd9Sstevel@tonic-gate sanity_check_options(argc, optind); 34887c478bd9Sstevel@tonic-gate 34897c478bd9Sstevel@tonic-gate if (!Outputtofile) 34907c478bd9Sstevel@tonic-gate DiskName = argv[optind]; 34917c478bd9Sstevel@tonic-gate 34927c478bd9Sstevel@tonic-gate (void) memset(&dskparamblk, 0, sizeof (dskparamblk)); 34937c478bd9Sstevel@tonic-gate 34947c478bd9Sstevel@tonic-gate if (GetFsParams) { 34957c478bd9Sstevel@tonic-gate fd = open_and_examine(DiskName, &dskparamblk); 34967c478bd9Sstevel@tonic-gate } else { 34977c478bd9Sstevel@tonic-gate fd = open_and_seek(DiskName, &dskparamblk, &AbsBootSect); 34987c478bd9Sstevel@tonic-gate if (ask_nicely(DiskName)) 34997c478bd9Sstevel@tonic-gate write_fat(fd, AbsBootSect, BootBlkFn, Label, 35007c478bd9Sstevel@tonic-gate FirstFn, &dskparamblk); 35017c478bd9Sstevel@tonic-gate } 35027c478bd9Sstevel@tonic-gate (void) close(fd); 3503c719c59aSjkennedy return (0); 35047c478bd9Sstevel@tonic-gate } 3505