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