10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*11215Sgdamore@opensolaris.org * Common Development and Distribution License (the "License").
6*11215Sgdamore@opensolaris.org * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*11215Sgdamore@opensolaris.org * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * fdformat program - formats floppy disks, and then adds a label to them
280Sstevel@tonic-gate *
290Sstevel@tonic-gate * ****Warning, Warning, Warning, Warning*****
300Sstevel@tonic-gate * This program runs suid root. This change was made to
310Sstevel@tonic-gate * allow it to umount a file system if it's mounted.
320Sstevel@tonic-gate */
330Sstevel@tonic-gate
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <fcntl.h>
360Sstevel@tonic-gate #include <stdlib.h>
370Sstevel@tonic-gate #include <unistd.h>
380Sstevel@tonic-gate #include <string.h>
390Sstevel@tonic-gate #include <memory.h>
400Sstevel@tonic-gate #include <errno.h>
410Sstevel@tonic-gate #include <locale.h>
420Sstevel@tonic-gate #include <libintl.h>
430Sstevel@tonic-gate #include <volmgt.h>
440Sstevel@tonic-gate #include <sys/isa_defs.h>
450Sstevel@tonic-gate #include <sys/ioccom.h>
460Sstevel@tonic-gate #include <sys/types.h>
470Sstevel@tonic-gate #include <sys/time.h>
480Sstevel@tonic-gate #include <sys/file.h>
490Sstevel@tonic-gate #include <sys/dklabel.h>
500Sstevel@tonic-gate #include <sys/ioctl.h>
510Sstevel@tonic-gate #include <sys/dkio.h>
520Sstevel@tonic-gate #include <sys/fdio.h>
530Sstevel@tonic-gate #include <sys/stat.h>
540Sstevel@tonic-gate #include <sys/vtoc.h>
550Sstevel@tonic-gate #include <sys/mnttab.h>
560Sstevel@tonic-gate
570Sstevel@tonic-gate /* DEFINES */
580Sstevel@tonic-gate #if defined(_BIG_ENDIAN)
590Sstevel@tonic-gate #define getbyte(A, N) (((unsigned char *)(&(A)))[N])
600Sstevel@tonic-gate #define htols(S) ((getbyte(S, 1) <<8) | getbyte(S, 0))
610Sstevel@tonic-gate #elif defined(_LITTLE_ENDIAN)
620Sstevel@tonic-gate #define htols(S) (*((ushort_t *)(&(S))))
630Sstevel@tonic-gate #else
640Sstevel@tonic-gate #error One of _BIG_ENDIAN or LITTLE_ENDIAN must be defined
650Sstevel@tonic-gate #endif
660Sstevel@tonic-gate
670Sstevel@tonic-gate #define getlobyte(A) (A & 0xFF)
680Sstevel@tonic-gate #define gethibyte(A) (A >> 8 & 0xFF)
690Sstevel@tonic-gate #define uppercase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
700Sstevel@tonic-gate #define min(a, b) ((a) < (b) ? (a) : (b))
710Sstevel@tonic-gate
720Sstevel@tonic-gate /* FORMAT PATTERNS */
730Sstevel@tonic-gate #define PATTERN_1 0x55;
740Sstevel@tonic-gate #define PATTERN_2 0xaa;
750Sstevel@tonic-gate #define PATTERN_3 0xff;
760Sstevel@tonic-gate #define PATTERN_4 0x00;
770Sstevel@tonic-gate
780Sstevel@tonic-gate /* UNINITIALIZED DATA */
790Sstevel@tonic-gate static struct fd_char fdchar;
800Sstevel@tonic-gate static struct dk_geom fdgeom;
810Sstevel@tonic-gate static struct dk_allmap allmap;
820Sstevel@tonic-gate static struct dk_cinfo dkinfo;
830Sstevel@tonic-gate
840Sstevel@tonic-gate /* EXTERN */
850Sstevel@tonic-gate extern char *optarg;
860Sstevel@tonic-gate extern int optind;
870Sstevel@tonic-gate
880Sstevel@tonic-gate /* for verify buffers */
890Sstevel@tonic-gate static uchar_t *ibuf1;
900Sstevel@tonic-gate static uchar_t *obuf;
910Sstevel@tonic-gate
920Sstevel@tonic-gate static char *myname;
930Sstevel@tonic-gate
940Sstevel@tonic-gate static int fd_debug = 1; /* 1 if debug XXX */
950Sstevel@tonic-gate static int b_flag = 0; /* install a volume label to the diskette */
960Sstevel@tonic-gate static int d_flag = 0; /* format the diskette in dos format */
970Sstevel@tonic-gate static int D_flag = 0; /* double (aka low) density flag */
980Sstevel@tonic-gate static int e_flag = 0; /* "eject" diskette when done (if supported) */
990Sstevel@tonic-gate static int E_flag = 0; /* extended density */
1000Sstevel@tonic-gate static int f_flag = 0; /* "force" (no confirmation before start) */
1010Sstevel@tonic-gate static int H_flag = 0; /* high density */
1020Sstevel@tonic-gate static int m_flag = 0; /* medium density */
1030Sstevel@tonic-gate static int n_flag = 0; /* format the diskette in NEC-DOS format */
1040Sstevel@tonic-gate static int q_flag = 0; /* quiet format flag */
1050Sstevel@tonic-gate static int U_flag = 0; /* automatically unmount if it's mounted */
1060Sstevel@tonic-gate static int v_flag = 0; /* verify format/diskette flag */
1070Sstevel@tonic-gate static int x_flag = 0; /* skip the format, only install SunOS label */
1080Sstevel@tonic-gate /* or DOS file system */
1090Sstevel@tonic-gate static int z_flag = 0; /* debugging only, setting partial formatting */
1100Sstevel@tonic-gate static int interleave = 1; /* interleave factor */
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate static uid_t euid = 0; /* stores effective user id */
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate struct bios_param_blk {
1150Sstevel@tonic-gate uchar_t b_bps[2]; /* bytes per sector */
1160Sstevel@tonic-gate uchar_t b_spcl; /* sectors per alloction unit */
1170Sstevel@tonic-gate uchar_t b_res_sec[2]; /* reserved sectors, starting at 0 */
1180Sstevel@tonic-gate uchar_t b_nfat; /* number of FATs */
1190Sstevel@tonic-gate uchar_t b_rdirents[2]; /* number of root directory entries */
1200Sstevel@tonic-gate uchar_t b_totalsec[2]; /* total sectors in logical image */
1210Sstevel@tonic-gate char b_mediadescriptor; /* media descriptor byte */
1220Sstevel@tonic-gate uchar_t b_fatsec[2]; /* number of sectors per FAT */
1230Sstevel@tonic-gate uchar_t b_spt[2]; /* sectors per track */
1240Sstevel@tonic-gate uchar_t b_nhead[2]; /* number of heads */
1250Sstevel@tonic-gate uchar_t b_hiddensec[2]; /* number of hidden sectors */
1260Sstevel@tonic-gate };
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate /*
1290Sstevel@tonic-gate * ON-private functions from libvolmgt
1300Sstevel@tonic-gate */
1310Sstevel@tonic-gate char *_media_oldaliases(char *name);
1320Sstevel@tonic-gate int _dev_mounted(char *path);
1330Sstevel@tonic-gate int _dev_unmount(char *path);
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate /*
1360Sstevel@tonic-gate * local functions
1370Sstevel@tonic-gate */
1380Sstevel@tonic-gate static void usage(char *);
1390Sstevel@tonic-gate static int verify(int, int, int);
1400Sstevel@tonic-gate static void write_SunOS_label(int, char *, struct vtoc *);
1410Sstevel@tonic-gate static int valid_DOS_boot(char *, uchar_t **);
1420Sstevel@tonic-gate static void write_DOS_label(int, uchar_t *, int, char *, char *,
1430Sstevel@tonic-gate struct bios_param_blk *, int);
1440Sstevel@tonic-gate static void write_NEC_DOS_label(int, char *);
1450Sstevel@tonic-gate static int check_mount();
1460Sstevel@tonic-gate static void format_diskette(int, char *, struct vtoc *,
1470Sstevel@tonic-gate struct bios_param_blk *, int *);
1480Sstevel@tonic-gate static void restore_default_chars(int fd,
1490Sstevel@tonic-gate struct fd_char save_fdchar,
1500Sstevel@tonic-gate struct dk_allmap save_allmap);
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate int
main(int argc,char ** argv)1530Sstevel@tonic-gate main(int argc, char **argv)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate int altsize = 0;
1560Sstevel@tonic-gate int fd;
1570Sstevel@tonic-gate int i;
1580Sstevel@tonic-gate uchar_t *altboot = NULL;
1590Sstevel@tonic-gate char *altbootname = NULL;
1600Sstevel@tonic-gate char *dev_name = NULL, *real_name, *alias_name;
1610Sstevel@tonic-gate char *vollabel = "";
1620Sstevel@tonic-gate struct vtoc fd_vtoc;
1630Sstevel@tonic-gate struct bios_param_blk bpb;
1640Sstevel@tonic-gate int rdirsec;
1650Sstevel@tonic-gate char *nullstring = "";
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
1700Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
1710Sstevel@tonic-gate #endif
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate myname = argv[0];
1760Sstevel@tonic-gate while ((i = getopt(argc, argv, "B:b:dDeEfhHlLmMxqt:UvVZ?")) != -1) {
1770Sstevel@tonic-gate switch (i) {
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate case 'B':
1800Sstevel@tonic-gate altbootname = strdup(optarg);
1810Sstevel@tonic-gate d_flag++;
1820Sstevel@tonic-gate /* check for valid boot file now */
1830Sstevel@tonic-gate altsize = valid_DOS_boot(altbootname, &altboot);
1840Sstevel@tonic-gate if (!altsize) {
1850Sstevel@tonic-gate (void) fprintf(stderr, gettext(
1860Sstevel@tonic-gate "%s: invalid boot loader\n"), myname);
1870Sstevel@tonic-gate exit(1);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate break;
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate case 'b':
1920Sstevel@tonic-gate b_flag++;
1930Sstevel@tonic-gate vollabel = strdup(optarg);
1940Sstevel@tonic-gate break;
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate case 'd':
1970Sstevel@tonic-gate /* format a MS-DOS diskette */
1980Sstevel@tonic-gate d_flag++;
1990Sstevel@tonic-gate break;
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate case 'D':
2020Sstevel@tonic-gate case 'L':
2030Sstevel@tonic-gate case 'l':
2040Sstevel@tonic-gate /* format a Double density 720KB (or 360KB) disk */
2050Sstevel@tonic-gate D_flag++;
2060Sstevel@tonic-gate break;
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate case 'e':
2090Sstevel@tonic-gate /* eject diskette when done */
2100Sstevel@tonic-gate e_flag++;
2110Sstevel@tonic-gate break;
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate case 'E':
2140Sstevel@tonic-gate /* format an 2.88MB Extended density disk */
2150Sstevel@tonic-gate E_flag++;
2160Sstevel@tonic-gate break;
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate case 'f':
2190Sstevel@tonic-gate /* don't ask for confirmation */
2200Sstevel@tonic-gate f_flag++;
2210Sstevel@tonic-gate break;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate case 'H':
2240Sstevel@tonic-gate case 'h':
2250Sstevel@tonic-gate /* format a High density 1.2MB or 1.44MB disk */
2260Sstevel@tonic-gate H_flag++;
2270Sstevel@tonic-gate break;
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate #if 0
2300Sstevel@tonic-gate case 'i':
2310Sstevel@tonic-gate /* interleave factor */
2320Sstevel@tonic-gate interleave = atol(optarg);
2330Sstevel@tonic-gate if (interleave <= 0) {
2340Sstevel@tonic-gate (void) fprintf(stderr, gettext(
2350Sstevel@tonic-gate "%s: invalid interleave\n"), myname);
2360Sstevel@tonic-gate exit(1);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate break;
2390Sstevel@tonic-gate #endif
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate case 'M':
2420Sstevel@tonic-gate case 'm':
2430Sstevel@tonic-gate /* format a 3.5" HD disk to 1.2MB */
2440Sstevel@tonic-gate m_flag++;
2450Sstevel@tonic-gate break;
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate case 'x':
2480Sstevel@tonic-gate /* skip format, just write label */
2490Sstevel@tonic-gate x_flag++;
2500Sstevel@tonic-gate break;
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate case 'q':
2530Sstevel@tonic-gate /* quiet format */
2540Sstevel@tonic-gate q_flag++;
2550Sstevel@tonic-gate break;
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate case 't':
2580Sstevel@tonic-gate /* Type of DOS formatting: NEC or MS */
2590Sstevel@tonic-gate if (strcmp(optarg, "nec") == 0) {
2600Sstevel@tonic-gate n_flag++;
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate if (strcmp(optarg, "dos") == 0) {
2630Sstevel@tonic-gate d_flag++;
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate break;
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate case 'U':
2680Sstevel@tonic-gate /* umount filesystem if mounted */
2690Sstevel@tonic-gate U_flag++;
2700Sstevel@tonic-gate break;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate case 'v':
2730Sstevel@tonic-gate case 'V':
2740Sstevel@tonic-gate /* verify the diskette after format */
2750Sstevel@tonic-gate v_flag++;
2760Sstevel@tonic-gate break;
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate case 'Z':
2790Sstevel@tonic-gate /* for debug only, format cyl 0 only */
2800Sstevel@tonic-gate if (!fd_debug) {
2810Sstevel@tonic-gate usage(gettext("unknown argument"));
2820Sstevel@tonic-gate /* NOTREACHED */
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate (void) printf(gettext("\nFormat cyl Zero only\n"));
2850Sstevel@tonic-gate z_flag++;
2860Sstevel@tonic-gate break;
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate default:
2890Sstevel@tonic-gate usage(" ");
2900Sstevel@tonic-gate /* NOTREACHED */
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate }
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate if (optind < argc -1) {
2950Sstevel@tonic-gate usage(gettext("more than one device name argument"));
2960Sstevel@tonic-gate /* NOTREACHED */
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate if (optind == argc -1) {
2990Sstevel@tonic-gate dev_name = argv[optind];
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate if (D_flag && H_flag) {
3020Sstevel@tonic-gate usage(gettext("switches -D, -L and -H incompatible"));
3030Sstevel@tonic-gate /* NOTREACHED */
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate if (D_flag && E_flag) {
3060Sstevel@tonic-gate usage(gettext("switches -D, -L and -E incompatible"));
3070Sstevel@tonic-gate /* NOTREACHED */
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate if (H_flag && E_flag) {
3100Sstevel@tonic-gate usage(gettext("switches -H and -E incompatible"));
3110Sstevel@tonic-gate /* NOTREACHED */
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate if (n_flag && d_flag) {
3140Sstevel@tonic-gate usage(gettext("switches nec and dos incompatible"));
3150Sstevel@tonic-gate /* NOTREACHED */
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate if (n_flag && !m_flag) {
3180Sstevel@tonic-gate usage(gettext("switch -M required for NEC-DOS"));
3190Sstevel@tonic-gate /* NOTREACHED */
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate if (D_flag && m_flag) {
3220Sstevel@tonic-gate usage(gettext("switches -D, -L and -M incompatible"));
3230Sstevel@tonic-gate /* NOTREACHED */
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate if (d_flag && m_flag) {
3260Sstevel@tonic-gate usage(gettext("switches -d and -M incompatible"));
3270Sstevel@tonic-gate /* NOTREACHED */
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate if (dev_name == NULL)
3310Sstevel@tonic-gate dev_name = "floppy";
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate if ((real_name = media_findname(dev_name)) == NULL) {
3340Sstevel@tonic-gate if ((alias_name = _media_oldaliases(dev_name)) != NULL)
3350Sstevel@tonic-gate real_name = media_findname(alias_name);
3360Sstevel@tonic-gate if (real_name == NULL) {
3370Sstevel@tonic-gate (void) fprintf(stderr,
3380Sstevel@tonic-gate gettext("No such volume (or no media in specified device): %s\n"),
3390Sstevel@tonic-gate dev_name);
3400Sstevel@tonic-gate exit(1);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * This check is required because program runs suid root.
3460Sstevel@tonic-gate */
3470Sstevel@tonic-gate if (access(real_name, R_OK|W_OK) < 0) {
3480Sstevel@tonic-gate perror(real_name);
3490Sstevel@tonic-gate exit(1);
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate /* store callers euid */
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate euid = geteuid();
3550Sstevel@tonic-gate
3560Sstevel@tonic-gate /*
3570Sstevel@tonic-gate * See if the given device name is mounted. If this check isn't done
3580Sstevel@tonic-gate * before the open, the open will fail. The failed open will not
3590Sstevel@tonic-gate * indicate that the device is mounted, only that it's busy
3600Sstevel@tonic-gate */
3610Sstevel@tonic-gate if (_dev_mounted(real_name)) {
3620Sstevel@tonic-gate if (U_flag) {
3630Sstevel@tonic-gate if (!_dev_unmount(real_name)) {
3640Sstevel@tonic-gate (void) fprintf(stderr,
3650Sstevel@tonic-gate gettext("%s: umount of %s failed\n"),
3660Sstevel@tonic-gate myname, real_name);
3670Sstevel@tonic-gate exit(1);
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate } else {
3700Sstevel@tonic-gate (void) fprintf(stderr,
3710Sstevel@tonic-gate gettext("%s: %s is mounted (use -U flag)\n"),
3720Sstevel@tonic-gate myname, real_name);
3730Sstevel@tonic-gate exit(1);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate
3770Sstevel@tonic-gate /* Set to user access permissions to open file */
3780Sstevel@tonic-gate (void) seteuid(getuid());
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate if ((fd = open(real_name, O_NDELAY | O_RDWR | O_EXCL)) == -1) {
3810Sstevel@tonic-gate if (errno == EROFS) {
3820Sstevel@tonic-gate (void) fprintf(stderr,
3830Sstevel@tonic-gate gettext("%s: \"%s\" is write protected\n"),
3840Sstevel@tonic-gate myname, real_name);
3850Sstevel@tonic-gate exit(1);
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate /* XXX ought to check for "drive not installed", etc. */
3880Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: could not open \"%s\": "),
3890Sstevel@tonic-gate myname, real_name);
3900Sstevel@tonic-gate perror(nullstring);
3910Sstevel@tonic-gate exit(1);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate /* restore effective id */
3950Sstevel@tonic-gate (void) seteuid(euid);
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) {
3980Sstevel@tonic-gate (void) fprintf(stderr,
3990Sstevel@tonic-gate gettext("%s: DKIOCINFO failed, "), myname);
4000Sstevel@tonic-gate perror(nullstring);
4010Sstevel@tonic-gate exit(3);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate /* See if there are any mounted partitions. */
4050Sstevel@tonic-gate if (check_mount() != 0) {
4060Sstevel@tonic-gate exit(3);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate * The fd_vtoc, bpb, and rdirsec structures will be
411*11215Sgdamore@opensolaris.org * partially filled in by format_diskette().
412*11215Sgdamore@opensolaris.org * This was done so that write_DOS_label(),
4130Sstevel@tonic-gate * write_SunOS_label(), and write_NEC_DOS_label() could be
4140Sstevel@tonic-gate * device independent. If a new device needs to be added to
4150Sstevel@tonic-gate * fdformat, a new format function like format_diskette should
4160Sstevel@tonic-gate * be added. This function should fill in fd_vtoc, bpb, and
4170Sstevel@tonic-gate * rdirsec with device dependent information.
4180Sstevel@tonic-gate */
4190Sstevel@tonic-gate (void) memset((void *)&fd_vtoc, (char)0, sizeof (struct vtoc));
4200Sstevel@tonic-gate (void) memset((void *)&bpb, (char)0, sizeof (struct bios_param_blk));
4210Sstevel@tonic-gate
422*11215Sgdamore@opensolaris.org format_diskette(fd, real_name, &fd_vtoc, &bpb, &rdirsec);
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate if (d_flag)
4250Sstevel@tonic-gate write_DOS_label(fd, altboot, altsize, altbootname,
4260Sstevel@tonic-gate vollabel, &bpb, rdirsec);
4270Sstevel@tonic-gate else if (n_flag)
4280Sstevel@tonic-gate write_NEC_DOS_label(fd, vollabel);
4290Sstevel@tonic-gate else
4300Sstevel@tonic-gate write_SunOS_label(fd, vollabel, &fd_vtoc);
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate if (e_flag)
4330Sstevel@tonic-gate /* eject media if possible */
4340Sstevel@tonic-gate if (ioctl(fd, FDEJECT, 0)) {
4350Sstevel@tonic-gate (void) fprintf(stderr,
4360Sstevel@tonic-gate gettext("%s: could not eject diskette, "), myname);
4370Sstevel@tonic-gate perror(nullstring);
4380Sstevel@tonic-gate exit(3);
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate return (0);
4420Sstevel@tonic-gate }
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate /*
4450Sstevel@tonic-gate * Inputs: file descriptor for the device and the device name.
4460Sstevel@tonic-gate * Oututs: the fd_vtoc will be partially filled in with the
4470Sstevel@tonic-gate * device specific information such as partition
4480Sstevel@tonic-gate * information and ascillabel. bpb and rdirsec will
4490Sstevel@tonic-gate * also be partially filled in with device specific information
4500Sstevel@tonic-gate */
4510Sstevel@tonic-gate void
format_diskette(int fd,char * real_name,struct vtoc * fd_vtoc,struct bios_param_blk * bpb,int * rdirsec)4520Sstevel@tonic-gate format_diskette(int fd, char *real_name, struct vtoc *fd_vtoc,
4530Sstevel@tonic-gate struct bios_param_blk *bpb, int *rdirsec)
4540Sstevel@tonic-gate {
4550Sstevel@tonic-gate int transfer_rate = 1000; /* transfer rate code */
4560Sstevel@tonic-gate int sec_size = 512; /* sector size */
4570Sstevel@tonic-gate uchar_t gap = 0x54; /* format gap size */
4580Sstevel@tonic-gate uchar_t *fbuf, *p;
4590Sstevel@tonic-gate char *capacity = NULL;
4600Sstevel@tonic-gate int cyl_size;
4610Sstevel@tonic-gate int i;
4620Sstevel@tonic-gate int chgd; /* for testing disk changed/present */
4630Sstevel@tonic-gate int cyl, hd;
4640Sstevel@tonic-gate int size_of_part, size_of_dev;
4650Sstevel@tonic-gate int spt = 36; /* sectors per track */
4660Sstevel@tonic-gate int drive_size;
4670Sstevel@tonic-gate uchar_t num_cyl = 80; /* max number of cylinders */
4680Sstevel@tonic-gate char *nullstring = "";
4690Sstevel@tonic-gate struct fd_char save_fdchar; /* original diskette characteristics */
4700Sstevel@tonic-gate struct dk_allmap save_allmap; /* original diskette partition info */
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /* FDIOCMD ioctl command structure for formatting */
4740Sstevel@tonic-gate /* LINTED */
4750Sstevel@tonic-gate struct fd_cmd fcmd_fmt = {
4760Sstevel@tonic-gate FDCMD_FORMAT_TRACK,
4770Sstevel@tonic-gate 0xA5,
4780Sstevel@tonic-gate 0,
4790Sstevel@tonic-gate 1,
4800Sstevel@tonic-gate 0,
4810Sstevel@tonic-gate 0
4820Sstevel@tonic-gate };
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate /* FDRAW ioctl command structures for seeking and formatting */
4850Sstevel@tonic-gate struct fd_raw fdr_seek = {
4860Sstevel@tonic-gate FDRAW_SEEK, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4870Sstevel@tonic-gate 3,
4880Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4890Sstevel@tonic-gate 0,
4900Sstevel@tonic-gate 0
4910Sstevel@tonic-gate };
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate struct fd_raw fdr_form = {
4940Sstevel@tonic-gate 0x4D, 0, 2, 0, 0x54, (char)0xA5, 0, 0, 0, 0,
4950Sstevel@tonic-gate 6,
4960Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4970Sstevel@tonic-gate 0, /* nbytes */
4980Sstevel@tonic-gate 0 /* addr */
4990Sstevel@tonic-gate };
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate /*
5030Sstevel@tonic-gate * restore drive to default geometry and characteristics
5040Sstevel@tonic-gate * (probably not implemented on sparc)
5050Sstevel@tonic-gate */
5060Sstevel@tonic-gate (void) ioctl(fd, FDDEFGEOCHAR, NULL);
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate /* get the default partititon maps */
5090Sstevel@tonic-gate if (ioctl(fd, DKIOCGAPART, &allmap) == -1) {
5100Sstevel@tonic-gate (void) fprintf(stderr,
5110Sstevel@tonic-gate gettext("%s: DKIOCGAPART failed, "), myname);
5120Sstevel@tonic-gate perror(nullstring);
5130Sstevel@tonic-gate exit(3);
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate /* Save the original default partition maps */
5170Sstevel@tonic-gate save_allmap = allmap;
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate /* find out the characteristics of the default diskette */
5200Sstevel@tonic-gate if (ioctl(fd, FDIOGCHAR, &fdchar) == -1) {
5210Sstevel@tonic-gate (void) fprintf(stderr,
5220Sstevel@tonic-gate gettext("%s: FDIOGCHAR failed, "), myname);
5230Sstevel@tonic-gate perror(nullstring);
5240Sstevel@tonic-gate exit(3);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate /* Save the original characteristics of the default diskette */
5280Sstevel@tonic-gate save_fdchar = fdchar;
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate /*
5310Sstevel@tonic-gate * The user may only format the entire diskette.
5320Sstevel@tonic-gate * formatting partion a or b is not allowed
5330Sstevel@tonic-gate */
5340Sstevel@tonic-gate size_of_part = allmap.dka_map[dkinfo.dki_partition].dkl_nblk
5350Sstevel@tonic-gate * DEV_BSIZE;
5360Sstevel@tonic-gate size_of_dev = fdchar.fdc_ncyl * fdchar.fdc_nhead
5370Sstevel@tonic-gate * fdchar.fdc_secptrack * fdchar.fdc_sec_size;
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate if (size_of_part != size_of_dev) {
5400Sstevel@tonic-gate (void) fprintf(stderr,
5410Sstevel@tonic-gate /*CSTYLED*/
5420Sstevel@tonic-gate gettext("%s: The entire diskette must be formatted. Invalid device name.\n"),
5430Sstevel@tonic-gate myname);
5440Sstevel@tonic-gate exit(3);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate /* find out the geometry of the drive */
5490Sstevel@tonic-gate if (ioctl(fd, DKIOCGGEOM, &fdgeom) == -1) {
5500Sstevel@tonic-gate (void) fprintf(stderr,
5510Sstevel@tonic-gate gettext("%s: DKIOCGGEOM failed, "), myname);
5520Sstevel@tonic-gate perror(nullstring);
5530Sstevel@tonic-gate exit(3);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate #ifdef sparc
5570Sstevel@tonic-gate fdchar.fdc_medium = 3;
5580Sstevel@tonic-gate #endif
5590Sstevel@tonic-gate if (fdchar.fdc_medium == 5)
5600Sstevel@tonic-gate drive_size = 5;
5610Sstevel@tonic-gate else
5620Sstevel@tonic-gate drive_size = 3;
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate /*
5650Sstevel@tonic-gate * set proper density flag in case we're formating to default
5660Sstevel@tonic-gate * characteristics because no density switch was input
5670Sstevel@tonic-gate */
5680Sstevel@tonic-gate if ((E_flag | H_flag | D_flag | m_flag) == 0) {
5690Sstevel@tonic-gate switch (fdchar.fdc_transfer_rate) {
5700Sstevel@tonic-gate case 1000:
5710Sstevel@tonic-gate /* assumes only ED uses 1.0 MB/sec */
5720Sstevel@tonic-gate E_flag++;
5730Sstevel@tonic-gate break;
5740Sstevel@tonic-gate case 500:
5750Sstevel@tonic-gate default:
5760Sstevel@tonic-gate /*
5770Sstevel@tonic-gate * default to HD even though High density and
5780Sstevel@tonic-gate * "medium" density both use 500 KB/sec
5790Sstevel@tonic-gate */
5800Sstevel@tonic-gate H_flag++;
5810Sstevel@tonic-gate break;
5820Sstevel@tonic-gate #ifndef sparc
5830Sstevel@tonic-gate case 250:
5840Sstevel@tonic-gate /* assumes only DD uses 250 KB/sec */
5850Sstevel@tonic-gate D_flag++;
5860Sstevel@tonic-gate break;
5870Sstevel@tonic-gate #endif
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate if (H_flag) {
5920Sstevel@tonic-gate transfer_rate = 500;
5930Sstevel@tonic-gate num_cyl = 80;
5940Sstevel@tonic-gate sec_size = 512;
5950Sstevel@tonic-gate if (drive_size == 5) {
5960Sstevel@tonic-gate (void) strcpy(fd_vtoc->v_asciilabel,
5970Sstevel@tonic-gate "5.25\" floppy cyl 80 alt 0 hd 2 sec 15");
5980Sstevel@tonic-gate spt = 15;
5990Sstevel@tonic-gate capacity = "1.2 MB";
6000Sstevel@tonic-gate } else {
6010Sstevel@tonic-gate (void) strcpy(fd_vtoc->v_asciilabel,
6020Sstevel@tonic-gate "3.5\" floppy cyl 80 alt 0 hd 2 sec 18");
6030Sstevel@tonic-gate spt = 18;
6040Sstevel@tonic-gate capacity = "1.44 MB";
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate gap = 0x54;
6070Sstevel@tonic-gate } else if (D_flag) {
6080Sstevel@tonic-gate transfer_rate = 250;
6090Sstevel@tonic-gate if (drive_size == 5) {
6100Sstevel@tonic-gate (void) strcpy(fd_vtoc->v_asciilabel,
6110Sstevel@tonic-gate "5.25\" floppy cyl 40 alt 0 hd 2 sec 9");
6120Sstevel@tonic-gate if (fdchar.fdc_transfer_rate == 500) {
6130Sstevel@tonic-gate /*
6140Sstevel@tonic-gate * formatting a 360KB DD diskette in
6150Sstevel@tonic-gate * a 1.2MB drive is not a good idea
6160Sstevel@tonic-gate */
6170Sstevel@tonic-gate transfer_rate = 300;
6180Sstevel@tonic-gate fdchar.fdc_steps = 2;
6190Sstevel@tonic-gate }
6200Sstevel@tonic-gate num_cyl = 40;
6210Sstevel@tonic-gate gap = 0x50;
6220Sstevel@tonic-gate capacity = "360 KB";
6230Sstevel@tonic-gate } else {
6240Sstevel@tonic-gate (void) strcpy(fd_vtoc->v_asciilabel,
6250Sstevel@tonic-gate "3.5\" floppy cyl 80 alt 0 hd 2 sec 9");
6260Sstevel@tonic-gate num_cyl = 80;
6270Sstevel@tonic-gate gap = 0x54;
6280Sstevel@tonic-gate capacity = "720 KB";
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate sec_size = 512;
6310Sstevel@tonic-gate spt = 9;
6320Sstevel@tonic-gate } else if (m_flag) {
6330Sstevel@tonic-gate #ifdef sparc
6340Sstevel@tonic-gate transfer_rate = 500;
6350Sstevel@tonic-gate #else
6360Sstevel@tonic-gate /*
6370Sstevel@tonic-gate * 416.67 KB/sec is the effective transfer rate of a "medium"
6380Sstevel@tonic-gate * density diskette spun at 300 rpm instead of 360 rpm
6390Sstevel@tonic-gate */
6400Sstevel@tonic-gate transfer_rate = 417;
6410Sstevel@tonic-gate #endif
6420Sstevel@tonic-gate (void) strcpy(fd_vtoc->v_asciilabel,
6430Sstevel@tonic-gate "3.5\" floppy cyl 77 alt 0 hd 2 sec 8");
6440Sstevel@tonic-gate num_cyl = 77;
6450Sstevel@tonic-gate sec_size = 1024;
6460Sstevel@tonic-gate spt = 8;
6470Sstevel@tonic-gate gap = 0x74;
6480Sstevel@tonic-gate capacity = "1.2 MB";
6490Sstevel@tonic-gate } else if (E_flag) {
6500Sstevel@tonic-gate (void) strcpy(fd_vtoc->v_asciilabel,
6510Sstevel@tonic-gate "3.5\" floppy cyl 80 alt 0 hd 2 sec 36");
6520Sstevel@tonic-gate transfer_rate = 1000;
6530Sstevel@tonic-gate num_cyl = 80;
6540Sstevel@tonic-gate sec_size = 512;
6550Sstevel@tonic-gate spt = 36;
6560Sstevel@tonic-gate gap = 0x54;
6570Sstevel@tonic-gate capacity = "2.88 MB";
6580Sstevel@tonic-gate }
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate * Medium density diskettes have 1024 byte blocks. The dk_map
6610Sstevel@tonic-gate * structure in dklabel.h assumes the blocks size is DEVBSIZE (512)
6620Sstevel@tonic-gate * bytes. The dkl_nblk field is in terms of DEVBSIZE byte blocks
6630Sstevel@tonic-gate * while the spt variable is in terms of the true block size on
6640Sstevel@tonic-gate * the diskette.
6650Sstevel@tonic-gate */
6660Sstevel@tonic-gate if (allmap.dka_map[2].dkl_nblk !=
6670Sstevel@tonic-gate (2 * num_cyl * spt * (m_flag ? 2 : 1))) {
6680Sstevel@tonic-gate allmap.dka_map[1].dkl_cylno = num_cyl - 1;
6690Sstevel@tonic-gate allmap.dka_map[0].dkl_nblk = 2 * (num_cyl - 1) * spt *
6700Sstevel@tonic-gate (m_flag ? 2 : 1);
6710Sstevel@tonic-gate allmap.dka_map[1].dkl_nblk = 2 * spt * (m_flag ? 2 : 1);
6720Sstevel@tonic-gate allmap.dka_map[2].dkl_nblk = 2 * num_cyl * spt *
6730Sstevel@tonic-gate (m_flag ? 2 : 1);
6740Sstevel@tonic-gate if (allmap.dka_map[3].dkl_nblk)
6750Sstevel@tonic-gate allmap.dka_map[3].dkl_nblk = 2 * (num_cyl - 1) * spt *
6760Sstevel@tonic-gate (m_flag ? 2 : 1);
6770Sstevel@tonic-gate if (allmap.dka_map[4].dkl_nblk)
6780Sstevel@tonic-gate allmap.dka_map[4].dkl_nblk =
6790Sstevel@tonic-gate 2 * spt * (m_flag ? 2 : 1);
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate /* initialize the vtoc structure */
6840Sstevel@tonic-gate fd_vtoc->v_nparts = 3;
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate fd_vtoc->v_part[0].p_start = 0;
6870Sstevel@tonic-gate fd_vtoc->v_part[0].p_size = ((num_cyl - 1) * 2 * spt *
6880Sstevel@tonic-gate (m_flag ? 2 : 1));
6890Sstevel@tonic-gate fd_vtoc->v_part[1].p_start = ((num_cyl - 1) * 2 * spt *
6900Sstevel@tonic-gate (m_flag ? 2 : 1));
6910Sstevel@tonic-gate fd_vtoc->v_part[1].p_size = 2 * spt * (m_flag ? 2 : 1);
6920Sstevel@tonic-gate
6930Sstevel@tonic-gate fd_vtoc->v_part[2].p_start = 0;
6940Sstevel@tonic-gate fd_vtoc->v_part[2].p_size = num_cyl * 2 * spt * (m_flag ? 2 : 1);
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate /* initialize the bios parameter blockstructure */
6970Sstevel@tonic-gate bpb->b_nfat = 2;
6980Sstevel@tonic-gate if (E_flag && drive_size == 3) {
6990Sstevel@tonic-gate bpb->b_spcl = 2;
7000Sstevel@tonic-gate *rdirsec = (ushort_t)240;
7010Sstevel@tonic-gate bpb->b_mediadescriptor = (char)0xF0;
7020Sstevel@tonic-gate bpb->b_fatsec[0] = 9;
7030Sstevel@tonic-gate bpb->b_fatsec[1] = 0;
7040Sstevel@tonic-gate } else if (H_flag) {
7050Sstevel@tonic-gate if (drive_size == 5) {
7060Sstevel@tonic-gate bpb->b_spcl = 1;
7070Sstevel@tonic-gate *rdirsec = 224;
7080Sstevel@tonic-gate bpb->b_mediadescriptor = (char)0xF9;
7090Sstevel@tonic-gate bpb->b_fatsec[0] = 7;
7100Sstevel@tonic-gate bpb->b_fatsec[1] = 0;
7110Sstevel@tonic-gate } else {
7120Sstevel@tonic-gate bpb->b_spcl = 1;
7130Sstevel@tonic-gate *rdirsec = 224;
7140Sstevel@tonic-gate bpb->b_mediadescriptor = (char)0xF0;
7150Sstevel@tonic-gate bpb->b_fatsec[0] = 9;
7160Sstevel@tonic-gate bpb->b_fatsec[1] = 0;
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate } else if (drive_size == 5) {
7190Sstevel@tonic-gate bpb->b_spcl = 2;
7200Sstevel@tonic-gate *rdirsec = 112;
7210Sstevel@tonic-gate bpb->b_mediadescriptor = (char)0xFD;
7220Sstevel@tonic-gate bpb->b_fatsec[0] = 2;
7230Sstevel@tonic-gate bpb->b_fatsec[1] = 0;
7240Sstevel@tonic-gate } else if (drive_size == 3) {
7250Sstevel@tonic-gate bpb->b_spcl = 2;
7260Sstevel@tonic-gate *rdirsec = 112;
7270Sstevel@tonic-gate bpb->b_mediadescriptor = (char)0xF9;
7280Sstevel@tonic-gate bpb->b_fatsec[0] = 3;
7290Sstevel@tonic-gate bpb->b_fatsec[1] = 0;
7300Sstevel@tonic-gate }
7310Sstevel@tonic-gate
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate #ifndef sparc
7350Sstevel@tonic-gate if (num_cyl > fdchar.fdc_ncyl || spt > fdchar.fdc_secptrack ||
7360Sstevel@tonic-gate transfer_rate > fdchar.fdc_transfer_rate) {
7370Sstevel@tonic-gate (void) fprintf(stderr,
7380Sstevel@tonic-gate gettext("%s: drive not capable of requested density, "),
7390Sstevel@tonic-gate myname);
7400Sstevel@tonic-gate perror(nullstring);
7410Sstevel@tonic-gate exit(3);
7420Sstevel@tonic-gate }
7430Sstevel@tonic-gate #endif
7440Sstevel@tonic-gate if (num_cyl != fdchar.fdc_ncyl || spt != fdchar.fdc_secptrack ||
7450Sstevel@tonic-gate transfer_rate != fdchar.fdc_transfer_rate) {
7460Sstevel@tonic-gate /*
7470Sstevel@tonic-gate * -- CAUTION --
7480Sstevel@tonic-gate * The SPARC fd driver is using a non-zero value in
7490Sstevel@tonic-gate * fdc_medium to indicate the 360 rpm, 77 track,
7500Sstevel@tonic-gate * 9 sectors/track, 1024 bytes/sector mode of operation
7510Sstevel@tonic-gate * (similar to an 8", DS/DD, 1.2 MB floppy).
7520Sstevel@tonic-gate *
7530Sstevel@tonic-gate * The x86 fd driver uses fdc_medium as the diameter
7540Sstevel@tonic-gate * indicator, either 3 or 5. It should not be modified.
7550Sstevel@tonic-gate */
7560Sstevel@tonic-gate #ifdef sparc
7570Sstevel@tonic-gate fdchar.fdc_medium = m_flag ? 1 : 0;
7580Sstevel@tonic-gate #endif
7590Sstevel@tonic-gate fdchar.fdc_transfer_rate = transfer_rate;
7600Sstevel@tonic-gate fdchar.fdc_ncyl = num_cyl;
7610Sstevel@tonic-gate fdchar.fdc_sec_size = sec_size;
7620Sstevel@tonic-gate fdchar.fdc_secptrack = spt;
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate if (ioctl(fd, FDIOSCHAR, &fdchar) == -1) {
7650Sstevel@tonic-gate (void) fprintf(stderr, gettext(
7660Sstevel@tonic-gate "%s: FDIOSCHAR (density selection) failed, "),
7670Sstevel@tonic-gate myname);
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate /* restore the default characteristics */
7700Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
7710Sstevel@tonic-gate perror(nullstring);
7720Sstevel@tonic-gate exit(3);
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate if (ioctl(fd, DKIOCSAPART, &allmap) == -1) {
7750Sstevel@tonic-gate (void) fprintf(stderr,
7760Sstevel@tonic-gate gettext("%s: DKIOCSAPART failed, "),
7770Sstevel@tonic-gate myname);
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate /* restore the default characteristics */
7800Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
7810Sstevel@tonic-gate
7820Sstevel@tonic-gate perror(nullstring);
7830Sstevel@tonic-gate exit(3);
7840Sstevel@tonic-gate }
7850Sstevel@tonic-gate }
7860Sstevel@tonic-gate
7870Sstevel@tonic-gate if (interleave != 1 && interleave != fdgeom.dkg_intrlv) {
7880Sstevel@tonic-gate fdgeom.dkg_intrlv = interleave;
7890Sstevel@tonic-gate if (ioctl(fd, DKIOCSGEOM, &fdgeom) == -1) {
7900Sstevel@tonic-gate (void) fprintf(stderr,
7910Sstevel@tonic-gate gettext("%s: DKIOCSGEOM failed, "), myname);
7920Sstevel@tonic-gate perror(nullstring);
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate /* restore the default characteristics */
7950Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate exit(3);
7980Sstevel@tonic-gate }
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate cyl_size = 2 * sec_size * spt;
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate if ((ibuf1 = (uchar_t *)malloc((size_t)cyl_size)) == 0 ||
8040Sstevel@tonic-gate (obuf = (uchar_t *)malloc((size_t)cyl_size)) == 0) {
8050Sstevel@tonic-gate (void) fprintf(stderr,
8060Sstevel@tonic-gate gettext("%s: can't malloc verify buffer, "),
8070Sstevel@tonic-gate myname);
8080Sstevel@tonic-gate perror(nullstring);
8090Sstevel@tonic-gate /* restore the default characteristics */
8100Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate exit(4);
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate (void) memset(ibuf1, (uchar_t)0xA5, cyl_size);
8150Sstevel@tonic-gate
8160Sstevel@tonic-gate if (x_flag)
8170Sstevel@tonic-gate goto skipformat;
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate if (!(q_flag && f_flag))
8200Sstevel@tonic-gate if (interleave != 1)
8210Sstevel@tonic-gate (void) printf(gettext(
8220Sstevel@tonic-gate "Formatting %s, %d cylinders, %d sectors per trk, interleave=%d in %s\n"),
8230Sstevel@tonic-gate capacity, num_cyl, spt, interleave, real_name);
8240Sstevel@tonic-gate else
8250Sstevel@tonic-gate (void) printf(gettext("Formatting %s in %s\n"),
8260Sstevel@tonic-gate capacity, real_name);
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate if (!f_flag) {
8290Sstevel@tonic-gate (void) printf(
8300Sstevel@tonic-gate gettext("Press return to start formatting floppy."));
8310Sstevel@tonic-gate while (getchar() != '\n')
8320Sstevel@tonic-gate ;
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate /*
8350Sstevel@tonic-gate * for those systems that support this ioctl, they will
8360Sstevel@tonic-gate * return whether or not a diskette is in the drive.
8370Sstevel@tonic-gate */
8380Sstevel@tonic-gate if (ioctl(fd, FDGETCHANGE, &chgd) == 0) {
8390Sstevel@tonic-gate if (chgd & FDGC_CURRENT) {
8400Sstevel@tonic-gate (void) fprintf(stderr,
8410Sstevel@tonic-gate gettext("%s: no diskette in drive %s\n"),
8420Sstevel@tonic-gate myname, real_name);
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate /* restore the default characteristics */
8450Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate exit(4);
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate if (chgd & FDGC_CURWPROT) {
8500Sstevel@tonic-gate (void) fprintf(stderr,
8510Sstevel@tonic-gate gettext("%s: \"%s\" is write protected\n"),
8520Sstevel@tonic-gate myname, real_name);
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate /* restore the default characteristics */
8550Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
8560Sstevel@tonic-gate
8570Sstevel@tonic-gate exit(1);
8580Sstevel@tonic-gate }
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate if ((fbuf = (uchar_t *)malloc((unsigned)(4 * spt))) == 0) {
8620Sstevel@tonic-gate (void) fprintf(stderr,
8630Sstevel@tonic-gate gettext("%s: can't malloc format header buffer, "),
8640Sstevel@tonic-gate myname);
8650Sstevel@tonic-gate perror(nullstring);
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate /* restore the default characteristics */
8680Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
8690Sstevel@tonic-gate
8700Sstevel@tonic-gate exit(3);
8710Sstevel@tonic-gate }
8720Sstevel@tonic-gate /*
8730Sstevel@tonic-gate * do the format, a track at a time
8740Sstevel@tonic-gate */
8750Sstevel@tonic-gate fcmd_fmt.fdc_blkno = 0;
8760Sstevel@tonic-gate for (cyl = 0; cyl < (z_flag ? 1 : (int)num_cyl); cyl++) {
8770Sstevel@tonic-gate #if 0
8780Sstevel@tonic-gate /*
8790Sstevel@tonic-gate * This should be the ioctl used to format the floppy.
8800Sstevel@tonic-gate * The device driver should do do the work,
8810Sstevel@tonic-gate * instead of this program mucking with a lot
8820Sstevel@tonic-gate * of low-level, device-dependent code.
8830Sstevel@tonic-gate */
8840Sstevel@tonic-gate for (hd = 0; hd < fdchar.fdc_nhead; hd++) {
8850Sstevel@tonic-gate if (ioctl(fd, FDIOCMD, &fcmd_fmt) == -1) {
8860Sstevel@tonic-gate (void) fprintf(stderr,
8870Sstevel@tonic-gate gettext("%s: format of cyl %d head %d failed\n"),
8880Sstevel@tonic-gate myname, cyl, hd);
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate /* restore the default characteristics */
8910Sstevel@tonic-gate restore_default_chars(fd, save_fdchar,
8920Sstevel@tonic-gate save_allmap);
8930Sstevel@tonic-gate exit(3);
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate fcmd_fmt.fdc_blkno += spt;
8960Sstevel@tonic-gate }
8970Sstevel@tonic-gate #else
8980Sstevel@tonic-gate /*
8990Sstevel@tonic-gate * This is not the optimal ioctl to format the floppy.
9000Sstevel@tonic-gate * The device driver should do do the work,
9010Sstevel@tonic-gate * instead of this program mucking with a lot
9020Sstevel@tonic-gate * of low-level, device-dependent code.
9030Sstevel@tonic-gate */
9040Sstevel@tonic-gate fdr_seek.fdr_cmd[2] = cyl;
9050Sstevel@tonic-gate if (ioctl(fd, FDRAW, &fdr_seek) == -1) {
9060Sstevel@tonic-gate (void) fprintf(stderr,
9070Sstevel@tonic-gate gettext("%s: seek to cyl %d failed\n"),
9080Sstevel@tonic-gate myname, cyl);
9090Sstevel@tonic-gate
9100Sstevel@tonic-gate /* restore the default characteristics */
9110Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
9120Sstevel@tonic-gate
9130Sstevel@tonic-gate exit(3);
9140Sstevel@tonic-gate }
9150Sstevel@tonic-gate /*
9160Sstevel@tonic-gate * Assume that the fd driver has issued a SENSE_INT
9170Sstevel@tonic-gate * command to complete the seek operation.
9180Sstevel@tonic-gate */
9190Sstevel@tonic-gate for (hd = 0; hd < fdchar.fdc_nhead; hd++) {
9200Sstevel@tonic-gate p = (uchar_t *)fbuf;
9210Sstevel@tonic-gate for (i = 1; i <= spt; i++) {
9220Sstevel@tonic-gate *p++ = cyl;
9230Sstevel@tonic-gate *p++ = hd;
9240Sstevel@tonic-gate *p++ = i; /* sector # */
9250Sstevel@tonic-gate *p++ = (sec_size == 1024) ? 3 : 2;
9260Sstevel@tonic-gate }
9270Sstevel@tonic-gate /*
9280Sstevel@tonic-gate * ASSUME the fd driver is going to set drive-select
9290Sstevel@tonic-gate * bits in the second command byte
9300Sstevel@tonic-gate */
9310Sstevel@tonic-gate fdr_form.fdr_cmd[1] = hd << 2;
9320Sstevel@tonic-gate fdr_form.fdr_cmd[2] = (sec_size == 1024) ? 3 : 2;
9330Sstevel@tonic-gate fdr_form.fdr_cmd[3] = spt;
9340Sstevel@tonic-gate fdr_form.fdr_cmd[4] = gap;
9350Sstevel@tonic-gate fdr_form.fdr_nbytes = 4 * spt;
9360Sstevel@tonic-gate fdr_form.fdr_addr = (char *)fbuf;
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate if (ioctl(fd, FDRAW, &fdr_form) == -1) {
9390Sstevel@tonic-gate
9400Sstevel@tonic-gate
9410Sstevel@tonic-gate (void) fprintf(stderr, gettext(
9420Sstevel@tonic-gate "%s: format of cyl %d head %d failed\n"),
9430Sstevel@tonic-gate myname, cyl, hd);
9440Sstevel@tonic-gate
9450Sstevel@tonic-gate /* restore the default characteristics */
9460Sstevel@tonic-gate restore_default_chars(fd, save_fdchar,
9470Sstevel@tonic-gate save_allmap);
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate exit(3);
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate if (fdr_form.fdr_result[0] & 0xC0) {
9520Sstevel@tonic-gate if (fdr_form.fdr_result[1] & 0x02) {
9530Sstevel@tonic-gate (void) fprintf(stderr, gettext(
9540Sstevel@tonic-gate /*CSTYLED*/
9550Sstevel@tonic-gate "%s: diskette is write protected\n"),
9560Sstevel@tonic-gate myname);
9570Sstevel@tonic-gate
9580Sstevel@tonic-gate /*
9590Sstevel@tonic-gate * restore the default
9600Sstevel@tonic-gate * characteristics
9610Sstevel@tonic-gate */
9620Sstevel@tonic-gate restore_default_chars(fd, save_fdchar,
9630Sstevel@tonic-gate save_allmap);
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate exit(3);
9660Sstevel@tonic-gate }
9670Sstevel@tonic-gate (void) fprintf(stderr, gettext(
9680Sstevel@tonic-gate "%s: format of cyl %d head %d failed\n"),
9690Sstevel@tonic-gate myname, cyl, hd);
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate /* restore the default characteristics */
9720Sstevel@tonic-gate restore_default_chars(fd, save_fdchar,
9730Sstevel@tonic-gate save_allmap);
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate exit(3);
9760Sstevel@tonic-gate }
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate }
9790Sstevel@tonic-gate #endif
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate /*
9820Sstevel@tonic-gate * do a quick verify
9830Sstevel@tonic-gate */
9840Sstevel@tonic-gate if (!v_flag) {
9850Sstevel@tonic-gate if (lseek(fd, cyl * cyl_size, 0) != cyl * cyl_size) {
9860Sstevel@tonic-gate (void) fprintf(stderr,
9870Sstevel@tonic-gate gettext("%s: bad seek to format verify, "),
9880Sstevel@tonic-gate myname);
9890Sstevel@tonic-gate perror(nullstring);
9900Sstevel@tonic-gate /* restore the default characteristics */
9910Sstevel@tonic-gate restore_default_chars(fd, save_fdchar,
9920Sstevel@tonic-gate save_allmap);
9930Sstevel@tonic-gate
9940Sstevel@tonic-gate exit(3);
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate if (read(fd, obuf, cyl_size) == cyl_size) {
9970Sstevel@tonic-gate /* write some progress msg */
9980Sstevel@tonic-gate /* when each cylinder is done. */
9990Sstevel@tonic-gate if (!q_flag)
10000Sstevel@tonic-gate (void) printf(".");
10010Sstevel@tonic-gate } else {
10020Sstevel@tonic-gate if (!q_flag)
10030Sstevel@tonic-gate (void) printf(gettext("e\n"));
10040Sstevel@tonic-gate (void) fprintf(stderr, gettext(
10050Sstevel@tonic-gate "%s: can't read format data, "), myname);
10060Sstevel@tonic-gate perror(nullstring);
10070Sstevel@tonic-gate /* restore the default characteristics */
10080Sstevel@tonic-gate restore_default_chars(fd, save_fdchar,
10090Sstevel@tonic-gate save_allmap);
10100Sstevel@tonic-gate
10110Sstevel@tonic-gate exit(3);
10120Sstevel@tonic-gate }
10130Sstevel@tonic-gate } else
10140Sstevel@tonic-gate if (!q_flag)
10150Sstevel@tonic-gate (void) printf(".");
10160Sstevel@tonic-gate if (!q_flag)
10170Sstevel@tonic-gate (void) fflush(stdout);
10180Sstevel@tonic-gate }
10190Sstevel@tonic-gate if (!q_flag)
10200Sstevel@tonic-gate (void) printf("\n");
10210Sstevel@tonic-gate skipformat:
10220Sstevel@tonic-gate if (v_flag) {
10230Sstevel@tonic-gate /*
10240Sstevel@tonic-gate * do a write & read verify of the entire diskette
10250Sstevel@tonic-gate */
10260Sstevel@tonic-gate if (!q_flag && x_flag)
10270Sstevel@tonic-gate (void) printf(gettext("Verifying %s in %s\n"),
10280Sstevel@tonic-gate capacity, real_name);
10290Sstevel@tonic-gate
10300Sstevel@tonic-gate for (cyl = 0; cyl < (int)num_cyl; cyl++) {
10310Sstevel@tonic-gate
10320Sstevel@tonic-gate int val;
10330Sstevel@tonic-gate if ((val = verify(fd, 2 * spt * cyl, cyl_size)) != 0) {
10340Sstevel@tonic-gate perror(nullstring);
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate /* restore the default characteristics */
10370Sstevel@tonic-gate restore_default_chars(fd, save_fdchar,
10380Sstevel@tonic-gate save_allmap);
10390Sstevel@tonic-gate
10400Sstevel@tonic-gate exit(val);
10410Sstevel@tonic-gate
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate /* write some progress msg as */
10440Sstevel@tonic-gate /* each cylinder is done. */
10450Sstevel@tonic-gate if (!q_flag)
10460Sstevel@tonic-gate (void) printf(gettext("v"));
10470Sstevel@tonic-gate (void) fflush(stdout);
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate if (!q_flag)
10500Sstevel@tonic-gate (void) printf("\n");
10510Sstevel@tonic-gate }
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate if (lseek(fd, (off_t)0, 0) != 0) {
10540Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: seek to blk 0 failed, "),
10550Sstevel@tonic-gate myname);
10560Sstevel@tonic-gate perror(nullstring);
10570Sstevel@tonic-gate /* restore the default characteristics */
10580Sstevel@tonic-gate restore_default_chars(fd, save_fdchar, save_allmap);
10590Sstevel@tonic-gate
10600Sstevel@tonic-gate exit(3);
10610Sstevel@tonic-gate }
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate }
10640Sstevel@tonic-gate
10650Sstevel@tonic-gate
10660Sstevel@tonic-gate /*
10670Sstevel@tonic-gate * Restore the default characteristics of the floppy diskette.
10680Sstevel@tonic-gate * Fdformat changes the characteristics in the process of formatting.
10690Sstevel@tonic-gate * If fdformat fails while in the process of doing the format, fdformat
10700Sstevel@tonic-gate * should clean up after itself and reset the driver back to the original
10710Sstevel@tonic-gate * state.
10720Sstevel@tonic-gate */
10730Sstevel@tonic-gate
10740Sstevel@tonic-gate static void
restore_default_chars(int fd,struct fd_char save_fdchar,struct dk_allmap save_allmap)10750Sstevel@tonic-gate restore_default_chars(int fd,
10760Sstevel@tonic-gate struct fd_char save_fdchar,
10770Sstevel@tonic-gate struct dk_allmap save_allmap)
10780Sstevel@tonic-gate {
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate
10810Sstevel@tonic-gate /*
10820Sstevel@tonic-gate * When this function is called, fdformat is failing anyways,
10830Sstevel@tonic-gate * so the errors are not processed.
10840Sstevel@tonic-gate */
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate (void) ioctl(fd, FDIOSCHAR, &save_fdchar);
10870Sstevel@tonic-gate
10880Sstevel@tonic-gate (void) ioctl(fd, DKIOCSAPART, &save_allmap);
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate /*
10910Sstevel@tonic-gate * Before looking at the diskette's characteristics, format_diskette()
10920Sstevel@tonic-gate * sets the x86 floppy driver to the default characteristics.
10930Sstevel@tonic-gate * restore drive to default geometry and
10940Sstevel@tonic-gate * characteristics. This ioctl isn't implemented on
10950Sstevel@tonic-gate * sparc.
10960Sstevel@tonic-gate */
10970Sstevel@tonic-gate (void) ioctl(fd, FDDEFGEOCHAR, NULL);
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate }
11000Sstevel@tonic-gate
11010Sstevel@tonic-gate /*
11020Sstevel@tonic-gate * See if any partitions on the device are mounted. Return 1 if a partition is
11030Sstevel@tonic-gate * mounted. Return 0 otherwise.
11040Sstevel@tonic-gate */
11050Sstevel@tonic-gate static int
check_mount()11060Sstevel@tonic-gate check_mount()
11070Sstevel@tonic-gate {
11080Sstevel@tonic-gate FILE *fp = NULL;
11090Sstevel@tonic-gate int mfd;
11100Sstevel@tonic-gate struct dk_cinfo dkinfo_tmp;
11110Sstevel@tonic-gate struct mnttab mnt_record;
11120Sstevel@tonic-gate struct mnttab *mp = &mnt_record;
11130Sstevel@tonic-gate struct stat stbuf;
11140Sstevel@tonic-gate char raw_device[MAXPATHLEN];
11150Sstevel@tonic-gate int found = 0;
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate if ((fp = fopen(MNTTAB, "r")) == NULL) {
11180Sstevel@tonic-gate perror(MNTTAB);
11190Sstevel@tonic-gate exit(3);
11200Sstevel@tonic-gate }
11210Sstevel@tonic-gate
11220Sstevel@tonic-gate while (getmntent(fp, mp) == 0) {
11230Sstevel@tonic-gate if (strstr(mp->mnt_special, "/dev/fd") == NULL &&
11240Sstevel@tonic-gate strstr(mp->mnt_special, "/dev/disket") == NULL &&
11250Sstevel@tonic-gate strstr(mp->mnt_special, "/dev/c") == NULL) {
11260Sstevel@tonic-gate continue;
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate
11290Sstevel@tonic-gate (void) strcpy(raw_device, "/dev/r");
11300Sstevel@tonic-gate (void) strcat(raw_device, mp->mnt_special + strlen("/dev/"));
11310Sstevel@tonic-gate
11320Sstevel@tonic-gate /*
11330Sstevel@tonic-gate * Attempt to open the device. If it fails, skip it.
11340Sstevel@tonic-gate */
11350Sstevel@tonic-gate if ((mfd = open(raw_device, O_RDWR | O_NDELAY)) < 0) {
11360Sstevel@tonic-gate continue;
11370Sstevel@tonic-gate }
11380Sstevel@tonic-gate
11390Sstevel@tonic-gate /*
11400Sstevel@tonic-gate * Must be a character device
11410Sstevel@tonic-gate */
11420Sstevel@tonic-gate if (fstat(mfd, &stbuf) == -1 || !S_ISCHR(stbuf.st_mode)) {
11430Sstevel@tonic-gate (void) close(mfd);
11440Sstevel@tonic-gate continue;
11450Sstevel@tonic-gate }
11460Sstevel@tonic-gate /*
11470Sstevel@tonic-gate * Attempt to read the configuration info on the disk.
11480Sstevel@tonic-gate */
11490Sstevel@tonic-gate if (ioctl(mfd, DKIOCINFO, &dkinfo_tmp) < 0) {
11500Sstevel@tonic-gate (void) close(mfd);
11510Sstevel@tonic-gate continue;
11520Sstevel@tonic-gate }
11530Sstevel@tonic-gate /*
11540Sstevel@tonic-gate * Finished with the opened device
11550Sstevel@tonic-gate */
11560Sstevel@tonic-gate (void) close(mfd);
11570Sstevel@tonic-gate
11580Sstevel@tonic-gate /*
11590Sstevel@tonic-gate * If it's not the disk we're interested in, it doesn't apply.
11600Sstevel@tonic-gate */
11610Sstevel@tonic-gate if (dkinfo.dki_ctype != dkinfo_tmp.dki_ctype ||
11620Sstevel@tonic-gate dkinfo.dki_cnum != dkinfo_tmp.dki_cnum ||
11630Sstevel@tonic-gate dkinfo.dki_unit != dkinfo_tmp.dki_unit) {
11640Sstevel@tonic-gate continue;
11650Sstevel@tonic-gate }
11660Sstevel@tonic-gate /*
11670Sstevel@tonic-gate * It's a mount on the disk we're checking. If we are
11680Sstevel@tonic-gate * checking whole disk, then we found trouble. We can
11690Sstevel@tonic-gate * quit searching.
11700Sstevel@tonic-gate */
11710Sstevel@tonic-gate
11720Sstevel@tonic-gate if (U_flag) {
11730Sstevel@tonic-gate if (!_dev_unmount(mp->mnt_special)) {
11740Sstevel@tonic-gate (void) fprintf(stderr,
11750Sstevel@tonic-gate gettext("%s: umount of %s failed\n"),
11760Sstevel@tonic-gate myname, mp->mnt_special);
11770Sstevel@tonic-gate found = 1;
11780Sstevel@tonic-gate }
11790Sstevel@tonic-gate } else {
11800Sstevel@tonic-gate (void) fprintf(stderr,
11810Sstevel@tonic-gate gettext("%s: %s is mounted (use -U flag)\n"),
11820Sstevel@tonic-gate myname, mp->mnt_special);
11830Sstevel@tonic-gate found = 1;
11840Sstevel@tonic-gate }
11850Sstevel@tonic-gate }
11860Sstevel@tonic-gate return (found);
11870Sstevel@tonic-gate }
11880Sstevel@tonic-gate
11890Sstevel@tonic-gate static void
usage(char * str)11900Sstevel@tonic-gate usage(char *str)
11910Sstevel@tonic-gate {
11920Sstevel@tonic-gate char *real_name, *alias_name;
11930Sstevel@tonic-gate
11940Sstevel@tonic-gate if ((real_name = media_findname("floppy")) == NULL) {
11950Sstevel@tonic-gate if ((alias_name = _media_oldaliases("floppy")) != NULL)
11960Sstevel@tonic-gate real_name = media_findname(alias_name);
11970Sstevel@tonic-gate }
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate if (str[0] != ' ')
12000Sstevel@tonic-gate (void) printf("%s: %s\n", myname, str);
12010Sstevel@tonic-gate (void) printf(gettext(
12020Sstevel@tonic-gate /*CSTYLED*/
12030Sstevel@tonic-gate "\n usage: %s [-dDeEfHlLmMqUvx] [-b label] [-B file] [-t dostype] [devname]\n"),
12040Sstevel@tonic-gate myname);
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate (void) printf(gettext(
12070Sstevel@tonic-gate /*CSTYLED*/
12080Sstevel@tonic-gate " -b label install \"label\" on media\n"));
12090Sstevel@tonic-gate (void) printf(gettext(
12100Sstevel@tonic-gate " -B file install special boot loader on MS-DOS media\n"));
12110Sstevel@tonic-gate (void) printf(gettext(
12120Sstevel@tonic-gate /*CSTYLED*/
12130Sstevel@tonic-gate " -d format MS-DOS media\n"));
12140Sstevel@tonic-gate (void) printf(gettext(
12150Sstevel@tonic-gate /*CSTYLED*/
12160Sstevel@tonic-gate " -D format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
12170Sstevel@tonic-gate (void) printf(gettext(
12180Sstevel@tonic-gate " -e eject the media when done\n"));
12190Sstevel@tonic-gate /*CSTYLED*/
12200Sstevel@tonic-gate (void) printf(gettext(
12210Sstevel@tonic-gate /*CSTYLED*/
12220Sstevel@tonic-gate " -E format 2.88MB (3.5\") Extended-density diskette\n"));
12230Sstevel@tonic-gate (void) printf(gettext(
12240Sstevel@tonic-gate " -f \"force\" - don't wait for confirmation\n"));
12250Sstevel@tonic-gate (void) printf(gettext(
12260Sstevel@tonic-gate /*CSTYLED*/
12270Sstevel@tonic-gate " -H format 1.44MB (3.5\") or 1.2MB (5.25\") High-density diskette\n"));
12280Sstevel@tonic-gate (void) printf(gettext(
12290Sstevel@tonic-gate /*CSTYLED*/
12300Sstevel@tonic-gate " -l format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
12310Sstevel@tonic-gate (void) printf(gettext(
12320Sstevel@tonic-gate /*CSTYLED*/
12330Sstevel@tonic-gate " -L format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
12340Sstevel@tonic-gate (void) printf(gettext(
12350Sstevel@tonic-gate " -m format 1.2MB (3.5\") Medium-density diskette\n"));
12360Sstevel@tonic-gate (void) printf(gettext(
12370Sstevel@tonic-gate " -M format 1.2MB (3.5\") Medium-density diskette\n"));
12380Sstevel@tonic-gate (void) printf(gettext(
12390Sstevel@tonic-gate " -q quiet\n"));
12400Sstevel@tonic-gate (void) printf(gettext(
12410Sstevel@tonic-gate /*CSTYLED*/
12420Sstevel@tonic-gate " -t dos format MS-DOS media (same as -d)\n"));
12430Sstevel@tonic-gate (void) printf(gettext(
12440Sstevel@tonic-gate " -t nec format NEC-DOS media (with -M only)\n"));
12450Sstevel@tonic-gate (void) printf(gettext(
12460Sstevel@tonic-gate /*CSTYLED*/
12470Sstevel@tonic-gate " -U unmount media if it's mounted\n"));
12480Sstevel@tonic-gate (void) printf(gettext(
12490Sstevel@tonic-gate " -v verify each block of the media\n"));
12500Sstevel@tonic-gate (void) printf(gettext(
12510Sstevel@tonic-gate " -x skip the format, only install SunOS or DOS label\n"));
12520Sstevel@tonic-gate
12530Sstevel@tonic-gate (void) printf(gettext(
12540Sstevel@tonic-gate " devname defaults to '%s'\n"),
12550Sstevel@tonic-gate real_name ? real_name : gettext("no available default device"));
12560Sstevel@tonic-gate
12570Sstevel@tonic-gate exit(1);
12580Sstevel@tonic-gate
12590Sstevel@tonic-gate }
12600Sstevel@tonic-gate
12610Sstevel@tonic-gate
12620Sstevel@tonic-gate static int
verify(int fd,int blk,int len)12630Sstevel@tonic-gate verify(int fd, int blk, int len)
12640Sstevel@tonic-gate {
12650Sstevel@tonic-gate off_t off;
12660Sstevel@tonic-gate char *nullstring = "";
12670Sstevel@tonic-gate
12680Sstevel@tonic-gate off = (off_t)(blk * (m_flag ? 1024 : 512));
12690Sstevel@tonic-gate
12700Sstevel@tonic-gate if (lseek(fd, off, 0) != off) {
12710Sstevel@tonic-gate if (!q_flag)
12720Sstevel@tonic-gate (void) printf(gettext("e\n"));
12730Sstevel@tonic-gate (void) fprintf(stderr,
12740Sstevel@tonic-gate gettext("%s: can't seek to write verify, "), myname);
12750Sstevel@tonic-gate perror(nullstring);
12760Sstevel@tonic-gate return (4);
12770Sstevel@tonic-gate }
12780Sstevel@tonic-gate if (write(fd, ibuf1, len) != len) {
12790Sstevel@tonic-gate if (!q_flag)
12800Sstevel@tonic-gate (void) printf(gettext("e\n"));
12810Sstevel@tonic-gate if (blk == 0)
12820Sstevel@tonic-gate (void) fprintf(stderr,
12830Sstevel@tonic-gate gettext("%s: check diskette density, "),
12840Sstevel@tonic-gate myname);
12850Sstevel@tonic-gate else
12860Sstevel@tonic-gate (void) fprintf(stderr,
12870Sstevel@tonic-gate gettext("%s: can't write verify data, "),
12880Sstevel@tonic-gate myname);
12890Sstevel@tonic-gate perror(nullstring);
12900Sstevel@tonic-gate return (4);
12910Sstevel@tonic-gate }
12920Sstevel@tonic-gate
12930Sstevel@tonic-gate if (lseek(fd, off, 0) != off) {
12940Sstevel@tonic-gate if (!q_flag)
12950Sstevel@tonic-gate (void) printf(gettext("e\n"));
12960Sstevel@tonic-gate (void) fprintf(stderr,
12970Sstevel@tonic-gate gettext("%s: bad seek to read verify, "),
12980Sstevel@tonic-gate myname);
12990Sstevel@tonic-gate perror(nullstring);
13000Sstevel@tonic-gate return (4);
13010Sstevel@tonic-gate }
13020Sstevel@tonic-gate if (read(fd, obuf, len) != len) {
13030Sstevel@tonic-gate if (!q_flag)
13040Sstevel@tonic-gate (void) printf(gettext("e\n"));
13050Sstevel@tonic-gate (void) fprintf(stderr,
13060Sstevel@tonic-gate gettext("%s: can't read verify data, "), myname);
13070Sstevel@tonic-gate perror(nullstring);
13080Sstevel@tonic-gate return (4);
13090Sstevel@tonic-gate }
13100Sstevel@tonic-gate if (memcmp(ibuf1, obuf, len)) {
13110Sstevel@tonic-gate if (!q_flag)
13120Sstevel@tonic-gate (void) printf(gettext("e\n"));
13130Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: verify data failure\n"),
13140Sstevel@tonic-gate myname);
13150Sstevel@tonic-gate return (4);
13160Sstevel@tonic-gate }
13170Sstevel@tonic-gate return (0);
13180Sstevel@tonic-gate }
13190Sstevel@tonic-gate
13200Sstevel@tonic-gate /*
13210Sstevel@tonic-gate * write a SunOS label
13220Sstevel@tonic-gate * NOTE: this function assumes fd_vtoc has been filled in with the
13230Sstevel@tonic-gate * device specific information such as partition information
13240Sstevel@tonic-gate * and the asciilabel
13250Sstevel@tonic-gate */
13260Sstevel@tonic-gate static void
write_SunOS_label(int fd,char * volname,struct vtoc * fd_vtoc)13270Sstevel@tonic-gate write_SunOS_label(int fd, char *volname, struct vtoc *fd_vtoc)
13280Sstevel@tonic-gate {
13290Sstevel@tonic-gate char *nullstring = "";
13300Sstevel@tonic-gate
13310Sstevel@tonic-gate fd_vtoc->v_sanity = VTOC_SANE;
13320Sstevel@tonic-gate
13330Sstevel@tonic-gate /*
13340Sstevel@tonic-gate * The label structure is set up for DEV_BSIZE (512 byte) blocks,
13350Sstevel@tonic-gate * even though a medium density diskette has 1024 byte blocks
13360Sstevel@tonic-gate * See dklabel.h for more details.
13370Sstevel@tonic-gate */
13380Sstevel@tonic-gate fd_vtoc->v_sectorsz = DEV_BSIZE;
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate (void) strncpy(fd_vtoc->v_volume, volname, sizeof (fd_vtoc->v_volume));
13410Sstevel@tonic-gate
13420Sstevel@tonic-gate /* let the fd driver finish constructing the label and writing it */
13430Sstevel@tonic-gate if (ioctl(fd, DKIOCSVTOC, fd_vtoc) == -1) {
13440Sstevel@tonic-gate (void) fprintf(stderr,
13450Sstevel@tonic-gate gettext("%s: write of SunOS label failed, "), myname);
13460Sstevel@tonic-gate perror(nullstring);
13470Sstevel@tonic-gate exit(3);
13480Sstevel@tonic-gate }
13490Sstevel@tonic-gate
13500Sstevel@tonic-gate }
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate
13530Sstevel@tonic-gate /*
13540Sstevel@tonic-gate * MS-DOS Disk layout:
13550Sstevel@tonic-gate *
13560Sstevel@tonic-gate * ---------------------
13570Sstevel@tonic-gate * | Boot sector |
13580Sstevel@tonic-gate * |-------------------|
13590Sstevel@tonic-gate * | Reserved area |
13600Sstevel@tonic-gate * |-------------------|
13610Sstevel@tonic-gate * | FAT #1 |
13620Sstevel@tonic-gate * |-------------------|
13630Sstevel@tonic-gate * | FAT #2 |
13640Sstevel@tonic-gate * |-------------------|
13650Sstevel@tonic-gate * | Root directory |
13660Sstevel@tonic-gate * |-------------------|
13670Sstevel@tonic-gate * | |
13680Sstevel@tonic-gate * | File area |
13690Sstevel@tonic-gate * |___________________|
13700Sstevel@tonic-gate */
13710Sstevel@tonic-gate
13720Sstevel@tonic-gate /*
13730Sstevel@tonic-gate * The following is a copy of MS-DOS 3.3 boot block.
13740Sstevel@tonic-gate * It consists of the BIOS parameter block, and a disk
13750Sstevel@tonic-gate * bootstrap program.
13760Sstevel@tonic-gate *
13770Sstevel@tonic-gate * The BIOS parameter block contains the right values
13780Sstevel@tonic-gate * for the 3.5" high-density 1.44MB floppy format.
13790Sstevel@tonic-gate *
13800Sstevel@tonic-gate */
13810Sstevel@tonic-gate static uchar_t bootsec[512] = {
13820Sstevel@tonic-gate 0xeb, 0x34, 0x90, /* 8086 short jump + displacement + NOP */
13830Sstevel@tonic-gate 'M', 'S', 'D', 'O', 'S', '3', '.', '3', /* OEM name & version */
13840Sstevel@tonic-gate 0, 2, 1, 1, 0, /* Start of BIOS parameter block */
13850Sstevel@tonic-gate 2, 224, 0, 0x40, 0xb, 0xf0, 9, 0,
13860Sstevel@tonic-gate 18, 0, 2, 0, 0, 0, /* End of BIOS parameter block */
13870Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
13880Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12,
13890Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0,
13900Sstevel@tonic-gate 0x1, 0x0, 0xfa, 0x33, /* 0x34, start of the bootstrap. */
13910Sstevel@tonic-gate 0xc0, 0x8e, 0xd0, 0xbc, 0x0, 0x7c, 0x16, 0x7,
13920Sstevel@tonic-gate 0xbb, 0x78, 0x0, 0x36, 0xc5, 0x37, 0x1e, 0x56,
13930Sstevel@tonic-gate 0x16, 0x53, 0xbf, 0x2b, 0x7c, 0xb9, 0xb, 0x0,
13940Sstevel@tonic-gate 0xfc, 0xac, 0x26, 0x80, 0x3d, 0x0, 0x74, 0x3,
13950Sstevel@tonic-gate 0x26, 0x8a, 0x5, 0xaa, 0x8a, 0xc4, 0xe2, 0xf1,
13960Sstevel@tonic-gate 0x6, 0x1f, 0x89, 0x47, 0x2, 0xc7, 0x7, 0x2b,
13970Sstevel@tonic-gate 0x7c, 0xfb, 0xcd, 0x13, 0x72, 0x67, 0xa0, 0x10,
13980Sstevel@tonic-gate 0x7c, 0x98, 0xf7, 0x26, 0x16, 0x7c, 0x3, 0x6,
13990Sstevel@tonic-gate 0x1c, 0x7c, 0x3, 0x6, 0xe, 0x7c, 0xa3, 0x3f,
14000Sstevel@tonic-gate 0x7c, 0xa3, 0x37, 0x7c, 0xb8, 0x20, 0x0, 0xf7,
14010Sstevel@tonic-gate 0x26, 0x11, 0x7c, 0x8b, 0x1e, 0xb, 0x7c, 0x3,
14020Sstevel@tonic-gate 0xc3, 0x48, 0xf7, 0xf3, 0x1, 0x6, 0x37, 0x7c,
14030Sstevel@tonic-gate 0xbb, 0x0, 0x5, 0xa1, 0x3f, 0x7c, 0xe8, 0x9f,
14040Sstevel@tonic-gate 0x0, 0xb8, 0x1, 0x2, 0xe8, 0xb3, 0x0, 0x72,
14050Sstevel@tonic-gate 0x19, 0x8b, 0xfb, 0xb9, 0xb, 0x0, 0xbe, 0xd6,
14060Sstevel@tonic-gate 0x7d, 0xf3, 0xa6, 0x75, 0xd, 0x8d, 0x7f, 0x20,
14070Sstevel@tonic-gate 0xbe, 0xe1, 0x7d, 0xb9, 0xb, 0x0, 0xf3, 0xa6,
14080Sstevel@tonic-gate 0x74, 0x18, 0xbe, 0x77, 0x7d, 0xe8, 0x6a, 0x0,
14090Sstevel@tonic-gate 0x32, 0xe4, 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x4,
14100Sstevel@tonic-gate 0x8f, 0x44, 0x2, 0xcd, 0x19, 0xbe, 0xc0, 0x7d,
14110Sstevel@tonic-gate 0xeb, 0xeb, 0xa1, 0x1c, 0x5, 0x33, 0xd2, 0xf7,
14120Sstevel@tonic-gate 0x36, 0xb, 0x7c, 0xfe, 0xc0, 0xa2, 0x3c, 0x7c,
14130Sstevel@tonic-gate 0xa1, 0x37, 0x7c, 0xa3, 0x3d, 0x7c, 0xbb, 0x0,
14140Sstevel@tonic-gate 0x7, 0xa1, 0x37, 0x7c, 0xe8, 0x49, 0x0, 0xa1,
14150Sstevel@tonic-gate 0x18, 0x7c, 0x2a, 0x6, 0x3b, 0x7c, 0x40, 0x38,
14160Sstevel@tonic-gate 0x6, 0x3c, 0x7c, 0x73, 0x3, 0xa0, 0x3c, 0x7c,
14170Sstevel@tonic-gate 0x50, 0xe8, 0x4e, 0x0, 0x58, 0x72, 0xc6, 0x28,
14180Sstevel@tonic-gate 0x6, 0x3c, 0x7c, 0x74, 0xc, 0x1, 0x6, 0x37,
14190Sstevel@tonic-gate 0x7c, 0xf7, 0x26, 0xb, 0x7c, 0x3, 0xd8, 0xeb,
14200Sstevel@tonic-gate 0xd0, 0x8a, 0x2e, 0x15, 0x7c, 0x8a, 0x16, 0xfd,
14210Sstevel@tonic-gate 0x7d, 0x8b, 0x1e, 0x3d, 0x7c, 0xea, 0x0, 0x0,
14220Sstevel@tonic-gate 0x70, 0x0, 0xac, 0xa, 0xc0, 0x74, 0x22, 0xb4,
14230Sstevel@tonic-gate 0xe, 0xbb, 0x7, 0x0, 0xcd, 0x10, 0xeb, 0xf2,
14240Sstevel@tonic-gate 0x33, 0xd2, 0xf7, 0x36, 0x18, 0x7c, 0xfe, 0xc2,
14250Sstevel@tonic-gate 0x88, 0x16, 0x3b, 0x7c, 0x33, 0xd2, 0xf7, 0x36,
14260Sstevel@tonic-gate 0x1a, 0x7c, 0x88, 0x16, 0x2a, 0x7c, 0xa3, 0x39,
14270Sstevel@tonic-gate 0x7c, 0xc3, 0xb4, 0x2, 0x8b, 0x16, 0x39, 0x7c,
14280Sstevel@tonic-gate 0xb1, 0x6, 0xd2, 0xe6, 0xa, 0x36, 0x3b, 0x7c,
14290Sstevel@tonic-gate 0x8b, 0xca, 0x86, 0xe9, 0x8a, 0x16, 0xfd, 0x7d,
14300Sstevel@tonic-gate 0x8a, 0x36, 0x2a, 0x7c, 0xcd, 0x13, 0xc3, '\r',
14310Sstevel@tonic-gate '\n', 'N', 'o', 'n', '-', 'S', 'y', 's',
14320Sstevel@tonic-gate 't', 'e', 'm', ' ', 'd', 'i', 's', 'k',
14330Sstevel@tonic-gate ' ', 'o', 'r', ' ', 'd', 'i', 's', 'k',
14340Sstevel@tonic-gate ' ', 'e', 'r', 'r', 'o', 'r', '\r', '\n',
14350Sstevel@tonic-gate 'R', 'e', 'p', 'l', 'a', 'c', 'e', ' ',
14360Sstevel@tonic-gate 'a', 'n', 'd', ' ', 's', 't', 'r', 'i',
14370Sstevel@tonic-gate 'k', 'e', ' ', 'a', 'n', 'y', ' ', 'k',
14380Sstevel@tonic-gate 'e', 'y', ' ', 'w', 'h', 'e', 'n', ' ',
14390Sstevel@tonic-gate 'r', 'e', 'a', 'd', 'y', '\r', '\n', '\0',
14400Sstevel@tonic-gate '\r', '\n', 'D', 'i', 's', 'k', ' ', 'B',
14410Sstevel@tonic-gate 'o', 'o', 't', ' ', 'f', 'a', 'i', 'l',
14420Sstevel@tonic-gate 'u', 'r', 'e', '\r', '\n', '\0', 'I', 'O',
14430Sstevel@tonic-gate ' ', ' ', ' ', ' ', ' ', ' ', 'S', 'Y',
14440Sstevel@tonic-gate 'S', 'M', 'S', 'D', 'O', 'S', ' ', ' ',
14450Sstevel@tonic-gate ' ', 'S', 'Y', 'S', '\0', 0, 0, 0,
14460Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0,
14470Sstevel@tonic-gate 0, 0, 0, 0, 0, 0x55, 0xaa
14480Sstevel@tonic-gate };
14490Sstevel@tonic-gate
14500Sstevel@tonic-gate static int
valid_DOS_boot(char * bootfile,uchar_t ** bootloadp)14510Sstevel@tonic-gate valid_DOS_boot(char *bootfile, uchar_t **bootloadp)
14520Sstevel@tonic-gate {
14530Sstevel@tonic-gate struct stat status;
14540Sstevel@tonic-gate size_t sizebootldr;
14550Sstevel@tonic-gate uchar_t *bootloader;
14560Sstevel@tonic-gate int bfd;
14570Sstevel@tonic-gate int boot_size = 0;
14580Sstevel@tonic-gate int err;
14590Sstevel@tonic-gate char *nullstring = "";
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate if (err = stat(bootfile, &status)) {
14620Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: \"%s\" stat error %d\n"),
14630Sstevel@tonic-gate myname, bootfile, err);
14640Sstevel@tonic-gate return (0);
14650Sstevel@tonic-gate }
14660Sstevel@tonic-gate if ((boot_size = status.st_size) < 512) {
14670Sstevel@tonic-gate (void) fprintf(stderr,
14680Sstevel@tonic-gate gettext("%s: short boot sector"), myname);
14690Sstevel@tonic-gate perror(nullstring);
14700Sstevel@tonic-gate return (0);
14710Sstevel@tonic-gate }
14720Sstevel@tonic-gate sizebootldr = (boot_size + 511) / 512 * 512;
14730Sstevel@tonic-gate if ((bootloader = (uchar_t *)malloc((size_t)sizebootldr)) == NULL) {
14740Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: malloc error\n"),
14750Sstevel@tonic-gate myname);
14760Sstevel@tonic-gate return (0);
14770Sstevel@tonic-gate }
14780Sstevel@tonic-gate
14790Sstevel@tonic-gate /* switch to user to access the boot file */
14800Sstevel@tonic-gate (void) seteuid(getuid());
14810Sstevel@tonic-gate
14820Sstevel@tonic-gate if ((bfd = open(bootfile, O_RDONLY)) == -1) {
14830Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: could not open \"%s\": "),
14840Sstevel@tonic-gate myname, bootfile);
14850Sstevel@tonic-gate perror(nullstring);
14860Sstevel@tonic-gate return (0);
14870Sstevel@tonic-gate }
14880Sstevel@tonic-gate
14890Sstevel@tonic-gate /* restore effective id */
14900Sstevel@tonic-gate (void) seteuid(euid);
14910Sstevel@tonic-gate
14920Sstevel@tonic-gate if (read(bfd, bootloader, boot_size) != boot_size) {
14930Sstevel@tonic-gate (void) fprintf(stderr,
14940Sstevel@tonic-gate gettext("%s: read of MS-DOS boot file failed, "), myname);
14950Sstevel@tonic-gate perror(nullstring);
14960Sstevel@tonic-gate (void) close(bfd);
14970Sstevel@tonic-gate return (0);
14980Sstevel@tonic-gate }
14990Sstevel@tonic-gate
15000Sstevel@tonic-gate if (!((*bootloader == 0xE9 ||
15010Sstevel@tonic-gate (*bootloader == 0xEB && *(bootloader + 2) == 0x90)) &&
15020Sstevel@tonic-gate *(bootloader + 510) == 0x55 &&
15030Sstevel@tonic-gate *(bootloader + 511) == 0xAA)) {
15040Sstevel@tonic-gate (void) fprintf(stderr,
15050Sstevel@tonic-gate gettext("%s: invalid MS-DOS boot loader image\n"), myname);
15060Sstevel@tonic-gate boot_size = 0;
15070Sstevel@tonic-gate }
15080Sstevel@tonic-gate
15090Sstevel@tonic-gate (void) close(bfd);
15100Sstevel@tonic-gate *bootloadp = bootloader;
15110Sstevel@tonic-gate return (boot_size);
15120Sstevel@tonic-gate }
15130Sstevel@tonic-gate
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate static void
write_DOS_label(int fd,uchar_t * bootloadr,int bootlen,char * altbootname,char * doslabel,struct bios_param_blk * bpb,int rdirsec)15160Sstevel@tonic-gate write_DOS_label(int fd, uchar_t *bootloadr, int bootlen, char *altbootname,
15170Sstevel@tonic-gate char *doslabel, struct bios_param_blk *bpb, int rdirsec)
15180Sstevel@tonic-gate {
15190Sstevel@tonic-gate int i, j;
15200Sstevel@tonic-gate int bootclen;
15210Sstevel@tonic-gate size_t fat_bsize;
15220Sstevel@tonic-gate ushort_t totalsec;
15230Sstevel@tonic-gate uchar_t *fat_rdir;
15240Sstevel@tonic-gate uchar_t *fatptr;
15250Sstevel@tonic-gate char *nullstring = "";
15260Sstevel@tonic-gate
15270Sstevel@tonic-gate if (bootlen < 512 || !bootloadr) {
15280Sstevel@tonic-gate /* use default boot loader routine */
15290Sstevel@tonic-gate bootloadr = bootsec;
15300Sstevel@tonic-gate bootlen = 512;
15310Sstevel@tonic-gate } else
15320Sstevel@tonic-gate (void) printf
15330Sstevel@tonic-gate (gettext("%s: using \"%s\" for MS-DOS boot loader\n"),
15340Sstevel@tonic-gate myname, altbootname);
15350Sstevel@tonic-gate if (bootlen % 512 > 0)
15360Sstevel@tonic-gate bootlen = (bootlen + 511) / 512 * 512;
15370Sstevel@tonic-gate
15380Sstevel@tonic-gate bpb->b_bps[0] = getlobyte(512);
15390Sstevel@tonic-gate bpb->b_bps[1] = gethibyte(512);
15400Sstevel@tonic-gate /* MS-DOS 5.0 supports only 1 reserved sector :-( */
15410Sstevel@tonic-gate bpb->b_res_sec[0] = 1;
15420Sstevel@tonic-gate bpb->b_res_sec[1] = 0;
15430Sstevel@tonic-gate
15440Sstevel@tonic-gate totalsec = fdchar.fdc_ncyl * fdchar.fdc_nhead * fdchar.fdc_secptrack;
15450Sstevel@tonic-gate bpb->b_totalsec[0] = getlobyte(totalsec);
15460Sstevel@tonic-gate bpb->b_totalsec[1] = gethibyte(totalsec);
15470Sstevel@tonic-gate bpb->b_spt[0] = fdchar.fdc_secptrack;
15480Sstevel@tonic-gate bpb->b_spt[1] = 0;
15490Sstevel@tonic-gate bpb->b_nhead[0] = fdchar.fdc_nhead;
15500Sstevel@tonic-gate bpb->b_nhead[1] = 0;
15510Sstevel@tonic-gate bpb->b_hiddensec[0] = 0;
15520Sstevel@tonic-gate bpb->b_hiddensec[1] = 0;
15530Sstevel@tonic-gate
15540Sstevel@tonic-gate bpb->b_rdirents[0] = getlobyte(rdirsec);
15550Sstevel@tonic-gate bpb->b_rdirents[1] = gethibyte(rdirsec);
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate (void) memcpy((char *)(bootloadr + 0x0B), (char *)bpb,
15580Sstevel@tonic-gate sizeof (struct bios_param_blk));
15590Sstevel@tonic-gate
15600Sstevel@tonic-gate if (write(fd, bootloadr, 512) != 512) {
15610Sstevel@tonic-gate (void) fprintf(stderr,
15620Sstevel@tonic-gate gettext("%s: write of MS-DOS boot sector failed"), myname);
15630Sstevel@tonic-gate perror(nullstring);
15640Sstevel@tonic-gate exit(3);
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate bootloadr += 512;
15670Sstevel@tonic-gate bootlen -= 512;
15680Sstevel@tonic-gate
15690Sstevel@tonic-gate fat_bsize = 512 * bpb->b_fatsec[0];
15700Sstevel@tonic-gate fat_rdir = (uchar_t *)malloc(fat_bsize);
15710Sstevel@tonic-gate (void) memset(fat_rdir, (char)0, fat_bsize);
15720Sstevel@tonic-gate
15730Sstevel@tonic-gate *fat_rdir = bpb->b_mediadescriptor;
15740Sstevel@tonic-gate *(fat_rdir + 1) = 0xFF;
15750Sstevel@tonic-gate *(fat_rdir + 2) = 0xFF;
15760Sstevel@tonic-gate bootclen = (bootlen + 512 * (int)bpb->b_spcl - 1) /
15770Sstevel@tonic-gate (512 * (int)bpb->b_spcl);
15780Sstevel@tonic-gate #define BAD_CLUSTER 0xFF7
15790Sstevel@tonic-gate for (i = 0, fatptr = fat_rdir+3; i < bootclen; i++)
15800Sstevel@tonic-gate /*
15810Sstevel@tonic-gate * pre-allocate any clusters used by boot loader if
15820Sstevel@tonic-gate * loader will occupy more than 1 sector
15830Sstevel@tonic-gate */
15840Sstevel@tonic-gate if (!(i & 01)) {
15850Sstevel@tonic-gate *fatptr++ = BAD_CLUSTER & 0xFF;
15860Sstevel@tonic-gate *fatptr = (BAD_CLUSTER >> 8) & 0x0F;
15870Sstevel@tonic-gate } else {
15880Sstevel@tonic-gate *fatptr = (*fatptr & 0x0F) |
15890Sstevel@tonic-gate ((BAD_CLUSTER << 4) & 0xF0);
15900Sstevel@tonic-gate fatptr++;
15910Sstevel@tonic-gate *fatptr++ = (BAD_CLUSTER >> 4) & 0xFF;
15920Sstevel@tonic-gate }
15930Sstevel@tonic-gate for (i = 0; i < (int)bpb->b_nfat; ++i)
15940Sstevel@tonic-gate if (write(fd, fat_rdir, fat_bsize) != fat_bsize) {
15950Sstevel@tonic-gate (void) fprintf(stderr,
15960Sstevel@tonic-gate gettext("%s: write of MS-DOS File Allocation Table failed, "),
15970Sstevel@tonic-gate myname);
15980Sstevel@tonic-gate perror(nullstring);
15990Sstevel@tonic-gate exit(3);
16000Sstevel@tonic-gate }
16010Sstevel@tonic-gate rdirsec = bpb->b_rdirents[0];
16020Sstevel@tonic-gate rdirsec = 32 * (int)rdirsec / 512;
16030Sstevel@tonic-gate if (b_flag) {
16040Sstevel@tonic-gate struct timeval tv;
16050Sstevel@tonic-gate struct tm *tp;
16060Sstevel@tonic-gate ushort_t dostime;
16070Sstevel@tonic-gate ushort_t dosday;
16080Sstevel@tonic-gate
16090Sstevel@tonic-gate /* the label can be no more than 11 characters */
16100Sstevel@tonic-gate j = min(11, (int)strlen(doslabel));
16110Sstevel@tonic-gate for (i = 0; i < j; i++) {
16120Sstevel@tonic-gate fat_rdir[i] = uppercase(doslabel[i]);
16130Sstevel@tonic-gate }
16140Sstevel@tonic-gate for (; i < 11; i++) {
16150Sstevel@tonic-gate fat_rdir[i] = ' ';
16160Sstevel@tonic-gate }
16170Sstevel@tonic-gate fat_rdir[0x0B] = 0x28;
16180Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)0);
16190Sstevel@tonic-gate tp = localtime(&tv.tv_sec);
16200Sstevel@tonic-gate /* get the time & day into DOS format */
16210Sstevel@tonic-gate dostime = tp->tm_sec / 2;
16220Sstevel@tonic-gate dostime |= tp->tm_min << 5;
16230Sstevel@tonic-gate dostime |= tp->tm_hour << 11;
16240Sstevel@tonic-gate dosday = tp->tm_mday;
16250Sstevel@tonic-gate dosday |= (tp->tm_mon + 1) << 5;
16260Sstevel@tonic-gate dosday |= (tp->tm_year - 80) << 9;
16270Sstevel@tonic-gate fat_rdir[0x16] = getlobyte(dostime);
16280Sstevel@tonic-gate fat_rdir[0x17] = gethibyte(dostime);
16290Sstevel@tonic-gate fat_rdir[0x18] = getlobyte(dosday);
16300Sstevel@tonic-gate fat_rdir[0x19] = gethibyte(dosday);
16310Sstevel@tonic-gate
16320Sstevel@tonic-gate if (write(fd, fat_rdir, 512) != 512) {
16330Sstevel@tonic-gate (void) fprintf(stderr,
16340Sstevel@tonic-gate gettext("%s: write of MS-DOS FAT failed, "),
16350Sstevel@tonic-gate myname);
16360Sstevel@tonic-gate perror(nullstring);
16370Sstevel@tonic-gate exit(3);
16380Sstevel@tonic-gate }
16390Sstevel@tonic-gate i = 1;
16400Sstevel@tonic-gate } else {
16410Sstevel@tonic-gate i = 0;
16420Sstevel@tonic-gate }
16430Sstevel@tonic-gate (void) memset(fat_rdir, (char)0, 512);
16440Sstevel@tonic-gate for (; i < (int)rdirsec; ++i) {
16450Sstevel@tonic-gate if (write(fd, fat_rdir, 512) != 512) {
16460Sstevel@tonic-gate (void) fprintf(stderr,
16470Sstevel@tonic-gate gettext("%s: write of MS-DOS root directory failed, "),
16480Sstevel@tonic-gate myname);
16490Sstevel@tonic-gate perror(nullstring);
16500Sstevel@tonic-gate exit(3);
16510Sstevel@tonic-gate }
16520Sstevel@tonic-gate }
16530Sstevel@tonic-gate /*
16540Sstevel@tonic-gate * Write the rest of the boot loader if it's longer than one sector.
16550Sstevel@tonic-gate * The clusters used are marked Bad in the FAT.
16560Sstevel@tonic-gate * No directory entry exists for this file (so that it cannot be
16570Sstevel@tonic-gate * deleted).
16580Sstevel@tonic-gate */
16590Sstevel@tonic-gate if (bootlen && write(fd, bootloadr, bootlen) != bootlen) {
16600Sstevel@tonic-gate (void) fprintf(stderr,
16610Sstevel@tonic-gate gettext("%s: write of MS-DOS boot sectors failed"), myname);
16620Sstevel@tonic-gate perror(nullstring);
16630Sstevel@tonic-gate exit(3);
16640Sstevel@tonic-gate }
16650Sstevel@tonic-gate }
16660Sstevel@tonic-gate
16670Sstevel@tonic-gate static void
write_NEC_DOS_label(int fd,char * doslabel)16680Sstevel@tonic-gate write_NEC_DOS_label(int fd, char *doslabel)
16690Sstevel@tonic-gate {
16700Sstevel@tonic-gate struct bios_param_blk *bpb;
16710Sstevel@tonic-gate ushort_t fatsec;
16720Sstevel@tonic-gate ushort_t rdirsec;
16730Sstevel@tonic-gate char fat_rdir[1024];
16740Sstevel@tonic-gate int i, j, m = 1;
16750Sstevel@tonic-gate uchar_t bootsec_NEC[1024];
16760Sstevel@tonic-gate char *nullstring = "";
16770Sstevel@tonic-gate
16780Sstevel@tonic-gate uchar_t bios_param_NEC[30] = { 0xeb, 0x1c, 0x90, 0x0, 0x0, 0x0, 0x0,
16790Sstevel@tonic-gate 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x1, 0x1, 0x0,
16800Sstevel@tonic-gate 0x2, 0xc0, 0x0, 0xd0, 0x4, 0xfe, 0x2, 0x0,
16810Sstevel@tonic-gate 0x8, 0x0, 0x2, 0x0, 0x0, 0x0
16820Sstevel@tonic-gate };
16830Sstevel@tonic-gate
16840Sstevel@tonic-gate uchar_t fatdir[32] = { 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
16850Sstevel@tonic-gate 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
16860Sstevel@tonic-gate 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
16870Sstevel@tonic-gate 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5
16880Sstevel@tonic-gate
16890Sstevel@tonic-gate };
16900Sstevel@tonic-gate
16910Sstevel@tonic-gate
16920Sstevel@tonic-gate (void) memset(bootsec_NEC, (char)0, 1024);
16930Sstevel@tonic-gate
16940Sstevel@tonic-gate (void) memcpy(&bootsec_NEC, &bios_param_NEC, 30);
16950Sstevel@tonic-gate
16960Sstevel@tonic-gate bpb = (struct bios_param_blk *)&(bootsec_NEC[0xb]);
16970Sstevel@tonic-gate if (write(fd, &bootsec_NEC[0], 1024) != 1024) {
16980Sstevel@tonic-gate (void) fprintf(stderr, gettext(
16990Sstevel@tonic-gate "%s: write of NEC-DOS boot sector failed, "),
17000Sstevel@tonic-gate myname);
17010Sstevel@tonic-gate perror(nullstring);
17020Sstevel@tonic-gate exit(3);
17030Sstevel@tonic-gate }
17040Sstevel@tonic-gate (void) memset(fat_rdir, (char)0, 1024);
17050Sstevel@tonic-gate fatsec = bpb->b_fatsec[0];
17060Sstevel@tonic-gate for (i = 0; i < (int)bpb->b_nfat * (int)fatsec; ++i) {
17070Sstevel@tonic-gate if ((i % (int)fatsec) == 0) {
17080Sstevel@tonic-gate fat_rdir[0] = bpb->b_mediadescriptor;
17090Sstevel@tonic-gate fat_rdir[1] = (char)0xff;
17100Sstevel@tonic-gate fat_rdir[2] = (char)0xff;
17110Sstevel@tonic-gate fat_rdir[3] = 0;
17120Sstevel@tonic-gate fat_rdir[4] = 0;
17130Sstevel@tonic-gate fat_rdir[5] = 0;
17140Sstevel@tonic-gate } else {
17150Sstevel@tonic-gate fat_rdir[0] = 0;
17160Sstevel@tonic-gate fat_rdir[1] = 0;
17170Sstevel@tonic-gate fat_rdir[2] = 0;
17180Sstevel@tonic-gate fat_rdir[3] = 0;
17190Sstevel@tonic-gate fat_rdir[4] = 0;
17200Sstevel@tonic-gate fat_rdir[5] = 0;
17210Sstevel@tonic-gate }
17220Sstevel@tonic-gate if (write(fd, &fat_rdir[0], 1024) != 1024) {
17230Sstevel@tonic-gate (void) fprintf(stderr,
17240Sstevel@tonic-gate /*CSTYLED*/
17250Sstevel@tonic-gate gettext("%s: write of NEC-DOS File Allocation Table failed, "), myname);
17260Sstevel@tonic-gate perror(nullstring);
17270Sstevel@tonic-gate exit(3);
17280Sstevel@tonic-gate }
17290Sstevel@tonic-gate }
17300Sstevel@tonic-gate #ifndef sparc
17310Sstevel@tonic-gate /* LINTED */
17320Sstevel@tonic-gate rdirsec = (int)htols(bpb->b_rdirents[0]) * 32 /1024;
17330Sstevel@tonic-gate #else
17340Sstevel@tonic-gate rdirsec = (int)htols(bpb->b_rdirents[0]) * 32 /1024;
17350Sstevel@tonic-gate #endif
17360Sstevel@tonic-gate if (b_flag) {
17370Sstevel@tonic-gate struct timeval tv;
17380Sstevel@tonic-gate struct tm *tp;
17390Sstevel@tonic-gate ushort_t dostime;
17400Sstevel@tonic-gate ushort_t dosday;
17410Sstevel@tonic-gate
17420Sstevel@tonic-gate /* the label can be no more than 11 characters */
17430Sstevel@tonic-gate j = min(11, (int)strlen(doslabel));
17440Sstevel@tonic-gate for (i = 0; i < j; i++) {
17450Sstevel@tonic-gate fat_rdir[i] = uppercase(doslabel[i]);
17460Sstevel@tonic-gate }
17470Sstevel@tonic-gate for (; i < 11; i++) {
17480Sstevel@tonic-gate fat_rdir[i] = ' ';
17490Sstevel@tonic-gate }
17500Sstevel@tonic-gate fat_rdir[0xb] = 0x28;
17510Sstevel@tonic-gate (void) gettimeofday(&tv, (struct timezone *)0);
17520Sstevel@tonic-gate tp = localtime(&tv.tv_sec);
17530Sstevel@tonic-gate /* get the time & day into DOS format */
17540Sstevel@tonic-gate dostime = tp->tm_sec / 2;
17550Sstevel@tonic-gate dostime |= tp->tm_min << 5;
17560Sstevel@tonic-gate dostime |= tp->tm_hour << 11;
17570Sstevel@tonic-gate dosday = tp->tm_mday;
17580Sstevel@tonic-gate dosday |= (tp->tm_mon + 1) << 5;
17590Sstevel@tonic-gate dosday |= (tp->tm_year - 80) << 9;
17600Sstevel@tonic-gate fat_rdir[0x16] = getlobyte(dostime);
17610Sstevel@tonic-gate fat_rdir[0x17] = gethibyte(dostime);
17620Sstevel@tonic-gate fat_rdir[0x18] = getlobyte(dosday);
17630Sstevel@tonic-gate fat_rdir[0x19] = gethibyte(dosday);
17640Sstevel@tonic-gate
17650Sstevel@tonic-gate if (write(fd, &fat_rdir[0], 1024) != 1024) {
17660Sstevel@tonic-gate (void) fprintf(stderr,
17670Sstevel@tonic-gate /*CSTYLED*/
17680Sstevel@tonic-gate gettext("%s: write of NEC-DOS root directory failed, "), myname);
17690Sstevel@tonic-gate perror(nullstring);
17700Sstevel@tonic-gate exit(3);
17710Sstevel@tonic-gate }
17720Sstevel@tonic-gate (void) memset(fat_rdir, (char)0, 512);
17730Sstevel@tonic-gate i = 1;
17740Sstevel@tonic-gate } else {
17750Sstevel@tonic-gate i = 0;
17760Sstevel@tonic-gate
17770Sstevel@tonic-gate while (m < 1024) {
17780Sstevel@tonic-gate (void) memcpy(&fat_rdir[m], &fatdir, 31);
17790Sstevel@tonic-gate m = m + 32;
17800Sstevel@tonic-gate }
17810Sstevel@tonic-gate }
17820Sstevel@tonic-gate for (; i < (int)rdirsec; ++i) {
17830Sstevel@tonic-gate
17840Sstevel@tonic-gate if (write(fd, &fat_rdir[0], 1024) != 1024) {
17850Sstevel@tonic-gate (void) fprintf(stderr,
17860Sstevel@tonic-gate /*CSTYLED*/
17870Sstevel@tonic-gate gettext("%s: write of NEC-DOS root directory failed, "), myname);
17880Sstevel@tonic-gate perror(nullstring);
17890Sstevel@tonic-gate exit(3);
17900Sstevel@tonic-gate }
17910Sstevel@tonic-gate }
17920Sstevel@tonic-gate }
1793