4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * fdformat program - formats floppy disks, and then adds a label to them
29 * ****Warning, Warning, Warning, Warning*****
30 * This program runs suid root. This change was made to
31 * allow it to umount a file system if it's mounted.
44 #include <sys/isa_defs.h>
45 #include <sys/ioccom.h>
46 #include <sys/types.h>
49 #include <sys/dklabel.h>
50 #include <sys/ioctl.h>
55 #include <sys/mnttab.h>
58 #if defined(_BIG_ENDIAN)
59 #define getbyte(A, N) (((unsigned char *)(&(A)))[N])
60 #define htols(S) ((getbyte(S, 1) <<8) | getbyte(S, 0))
61 #elif defined(_LITTLE_ENDIAN)
62 #define htols(S) (*((ushort_t *)(&(S))))
64 #error One of _BIG_ENDIAN or LITTLE_ENDIAN must be defined
67 #define getlobyte(A) (A & 0xFF)
68 #define gethibyte(A) (A >> 8 & 0xFF)
69 #define uppercase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
70 #define min(a, b) ((a) < (b) ? (a) : (b))
73 #define PATTERN_1 0x55;
74 #define PATTERN_2 0xaa;
75 #define PATTERN_3 0xff;
76 #define PATTERN_4 0x00;
78 /* UNINITIALIZED DATA */
79 static struct fd_char fdchar
;
80 static struct dk_geom fdgeom
;
81 static struct dk_allmap allmap
;
82 static struct dk_cinfo dkinfo
;
88 /* for verify buffers */
89 static uchar_t
*ibuf1
;
94 static int fd_debug
= 1; /* 1 if debug XXX */
95 static int b_flag
= 0; /* install a volume label to the diskette */
96 static int d_flag
= 0; /* format the diskette in dos format */
97 static int D_flag
= 0; /* double (aka low) density flag */
98 static int e_flag
= 0; /* "eject" diskette when done (if supported) */
99 static int E_flag
= 0; /* extended density */
100 static int f_flag
= 0; /* "force" (no confirmation before start) */
101 static int H_flag
= 0; /* high density */
102 static int m_flag
= 0; /* medium density */
103 static int n_flag
= 0; /* format the diskette in NEC-DOS format */
104 static int q_flag
= 0; /* quiet format flag */
105 static int U_flag
= 0; /* automatically unmount if it's mounted */
106 static int v_flag
= 0; /* verify format/diskette flag */
107 static int x_flag
= 0; /* skip the format, only install SunOS label */
108 /* or DOS file system */
109 static int z_flag
= 0; /* debugging only, setting partial formatting */
110 static int interleave
= 1; /* interleave factor */
112 static uid_t euid
= 0; /* stores effective user id */
114 struct bios_param_blk
{
115 uchar_t b_bps
[2]; /* bytes per sector */
116 uchar_t b_spcl
; /* sectors per alloction unit */
117 uchar_t b_res_sec
[2]; /* reserved sectors, starting at 0 */
118 uchar_t b_nfat
; /* number of FATs */
119 uchar_t b_rdirents
[2]; /* number of root directory entries */
120 uchar_t b_totalsec
[2]; /* total sectors in logical image */
121 char b_mediadescriptor
; /* media descriptor byte */
122 uchar_t b_fatsec
[2]; /* number of sectors per FAT */
123 uchar_t b_spt
[2]; /* sectors per track */
124 uchar_t b_nhead
[2]; /* number of heads */
125 uchar_t b_hiddensec
[2]; /* number of hidden sectors */
129 * ON-private functions from libvolmgt
131 char *_media_oldaliases(char *name
);
132 int _dev_mounted(char *path
);
133 int _dev_unmount(char *path
);
138 static void usage(char *);
139 static int verify(int, int, int);
140 static void write_SunOS_label(int, char *, struct vtoc
*);
141 static int valid_DOS_boot(char *, uchar_t
**);
142 static void write_DOS_label(int, uchar_t
*, int, char *, char *,
143 struct bios_param_blk
*, int);
144 static void write_NEC_DOS_label(int, char *);
145 static int check_mount();
146 static void format_diskette(int, char *, struct vtoc
*,
147 struct bios_param_blk
*, int *);
148 static void restore_default_chars(int fd
,
149 struct fd_char save_fdchar
,
150 struct dk_allmap save_allmap
);
153 main(int argc
, char **argv
)
158 uchar_t
*altboot
= NULL
;
159 char *altbootname
= NULL
;
160 char *dev_name
= NULL
, *real_name
, *alias_name
;
163 struct bios_param_blk bpb
;
165 char *nullstring
= "";
167 (void) setlocale(LC_ALL
, "");
169 #if !defined(TEXT_DOMAIN)
170 #define TEXT_DOMAIN "SYS_TEST"
173 (void) textdomain(TEXT_DOMAIN
);
176 while ((i
= getopt(argc
, argv
, "B:b:dDeEfhHlLmMxqt:UvVZ?")) != -1) {
180 altbootname
= strdup(optarg
);
182 /* check for valid boot file now */
183 altsize
= valid_DOS_boot(altbootname
, &altboot
);
185 (void) fprintf(stderr
, gettext(
186 "%s: invalid boot loader\n"), myname
);
193 vollabel
= strdup(optarg
);
197 /* format a MS-DOS diskette */
204 /* format a Double density 720KB (or 360KB) disk */
209 /* eject diskette when done */
214 /* format an 2.88MB Extended density disk */
219 /* don't ask for confirmation */
225 /* format a High density 1.2MB or 1.44MB disk */
231 /* interleave factor */
232 interleave
= atol(optarg
);
233 if (interleave
<= 0) {
234 (void) fprintf(stderr
, gettext(
235 "%s: invalid interleave\n"), myname
);
243 /* format a 3.5" HD disk to 1.2MB */
248 /* skip format, just write label */
258 /* Type of DOS formatting: NEC or MS */
259 if (strcmp(optarg
, "nec") == 0) {
262 if (strcmp(optarg
, "dos") == 0) {
268 /* umount filesystem if mounted */
274 /* verify the diskette after format */
279 /* for debug only, format cyl 0 only */
281 usage(gettext("unknown argument"));
284 (void) printf(gettext("\nFormat cyl Zero only\n"));
294 if (optind
< argc
-1) {
295 usage(gettext("more than one device name argument"));
298 if (optind
== argc
-1) {
299 dev_name
= argv
[optind
];
301 if (D_flag
&& H_flag
) {
302 usage(gettext("switches -D, -L and -H incompatible"));
305 if (D_flag
&& E_flag
) {
306 usage(gettext("switches -D, -L and -E incompatible"));
309 if (H_flag
&& E_flag
) {
310 usage(gettext("switches -H and -E incompatible"));
313 if (n_flag
&& d_flag
) {
314 usage(gettext("switches nec and dos incompatible"));
317 if (n_flag
&& !m_flag
) {
318 usage(gettext("switch -M required for NEC-DOS"));
321 if (D_flag
&& m_flag
) {
322 usage(gettext("switches -D, -L and -M incompatible"));
325 if (d_flag
&& m_flag
) {
326 usage(gettext("switches -d and -M incompatible"));
330 if (dev_name
== NULL
)
333 if ((real_name
= media_findname(dev_name
)) == NULL
) {
334 if ((alias_name
= _media_oldaliases(dev_name
)) != NULL
)
335 real_name
= media_findname(alias_name
);
336 if (real_name
== NULL
) {
337 (void) fprintf(stderr
,
338 gettext("No such volume (or no media in specified device): %s\n"),
345 * This check is required because program runs suid root.
347 if (access(real_name
, R_OK
|W_OK
) < 0) {
352 /* store callers euid */
357 * See if the given device name is mounted. If this check isn't done
358 * before the open, the open will fail. The failed open will not
359 * indicate that the device is mounted, only that it's busy
361 if (_dev_mounted(real_name
)) {
363 if (!_dev_unmount(real_name
)) {
364 (void) fprintf(stderr
,
365 gettext("%s: umount of %s failed\n"),
370 (void) fprintf(stderr
,
371 gettext("%s: %s is mounted (use -U flag)\n"),
377 /* Set to user access permissions to open file */
378 (void) seteuid(getuid());
380 if ((fd
= open(real_name
, O_NDELAY
| O_RDWR
| O_EXCL
)) == -1) {
381 if (errno
== EROFS
) {
382 (void) fprintf(stderr
,
383 gettext("%s: \"%s\" is write protected\n"),
387 /* XXX ought to check for "drive not installed", etc. */
388 (void) fprintf(stderr
, gettext("%s: could not open \"%s\": "),
394 /* restore effective id */
395 (void) seteuid(euid
);
397 if (ioctl(fd
, DKIOCINFO
, &dkinfo
) < 0) {
398 (void) fprintf(stderr
,
399 gettext("%s: DKIOCINFO failed, "), myname
);
404 /* See if there are any mounted partitions. */
405 if (check_mount() != 0) {
410 * The fd_vtoc, bpb, and rdirsec structures will be
411 * partially filled in by format_diskette().
412 * This was done so that write_DOS_label(),
413 * write_SunOS_label(), and write_NEC_DOS_label() could be
414 * device independent. If a new device needs to be added to
415 * fdformat, a new format function like format_diskette should
416 * be added. This function should fill in fd_vtoc, bpb, and
417 * rdirsec with device dependent information.
419 (void) memset((void *)&fd_vtoc
, 0, sizeof (struct vtoc
));
420 (void) memset((void *)&bpb
, 0, sizeof (struct bios_param_blk
));
422 format_diskette(fd
, real_name
, &fd_vtoc
, &bpb
, &rdirsec
);
425 write_DOS_label(fd
, altboot
, altsize
, altbootname
,
426 vollabel
, &bpb
, rdirsec
);
428 write_NEC_DOS_label(fd
, vollabel
);
430 write_SunOS_label(fd
, vollabel
, &fd_vtoc
);
433 /* eject media if possible */
434 if (ioctl(fd
, FDEJECT
, 0)) {
435 (void) fprintf(stderr
,
436 gettext("%s: could not eject diskette, "), myname
);
445 * Inputs: file descriptor for the device and the device name.
446 * Oututs: the fd_vtoc will be partially filled in with the
447 * device specific information such as partition
448 * information and ascillabel. bpb and rdirsec will
449 * also be partially filled in with device specific information
452 format_diskette(int fd
, char *real_name
, struct vtoc
*fd_vtoc
,
453 struct bios_param_blk
*bpb
, int *rdirsec
)
455 int transfer_rate
= 1000; /* transfer rate code */
456 int sec_size
= 512; /* sector size */
457 uchar_t gap
= 0x54; /* format gap size */
459 char *capacity
= NULL
;
462 int chgd
; /* for testing disk changed/present */
464 int size_of_part
, size_of_dev
;
465 int spt
= 36; /* sectors per track */
467 uchar_t num_cyl
= 80; /* max number of cylinders */
468 char *nullstring
= "";
469 struct fd_char save_fdchar
; /* original diskette characteristics */
470 struct dk_allmap save_allmap
; /* original diskette partition info */
472 /* FDRAW ioctl command structures for seeking and formatting */
473 struct fd_raw fdr_seek
= {
474 FDRAW_SEEK
, 0, 0, 0, 0, 0, 0, 0, 0, 0,
476 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
481 struct fd_raw fdr_form
= {
482 0x4D, 0, 2, 0, 0x54, (char)0xA5, 0, 0, 0, 0,
484 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
491 * restore drive to default geometry and characteristics
492 * (probably not implemented on sparc)
494 (void) ioctl(fd
, FDDEFGEOCHAR
, NULL
);
496 /* get the default partititon maps */
497 if (ioctl(fd
, DKIOCGAPART
, &allmap
) == -1) {
498 (void) fprintf(stderr
,
499 gettext("%s: DKIOCGAPART failed, "), myname
);
504 /* Save the original default partition maps */
505 save_allmap
= allmap
;
507 /* find out the characteristics of the default diskette */
508 if (ioctl(fd
, FDIOGCHAR
, &fdchar
) == -1) {
509 (void) fprintf(stderr
,
510 gettext("%s: FDIOGCHAR failed, "), myname
);
515 /* Save the original characteristics of the default diskette */
516 save_fdchar
= fdchar
;
519 * The user may only format the entire diskette.
520 * formatting partion a or b is not allowed
522 size_of_part
= allmap
.dka_map
[dkinfo
.dki_partition
].dkl_nblk
524 size_of_dev
= fdchar
.fdc_ncyl
* fdchar
.fdc_nhead
525 * fdchar
.fdc_secptrack
* fdchar
.fdc_sec_size
;
527 if (size_of_part
!= size_of_dev
) {
528 (void) fprintf(stderr
,
530 gettext("%s: The entire diskette must be formatted. Invalid device name.\n"),
536 /* find out the geometry of the drive */
537 if (ioctl(fd
, DKIOCGGEOM
, &fdgeom
) == -1) {
538 (void) fprintf(stderr
,
539 gettext("%s: DKIOCGGEOM failed, "), myname
);
545 fdchar
.fdc_medium
= 3;
547 if (fdchar
.fdc_medium
== 5)
553 * set proper density flag in case we're formating to default
554 * characteristics because no density switch was input
556 if ((E_flag
| H_flag
| D_flag
| m_flag
) == 0) {
557 switch (fdchar
.fdc_transfer_rate
) {
559 /* assumes only ED uses 1.0 MB/sec */
565 * default to HD even though High density and
566 * "medium" density both use 500 KB/sec
572 /* assumes only DD uses 250 KB/sec */
583 if (drive_size
== 5) {
584 (void) strcpy(fd_vtoc
->v_asciilabel
,
585 "5.25\" floppy cyl 80 alt 0 hd 2 sec 15");
589 (void) strcpy(fd_vtoc
->v_asciilabel
,
590 "3.5\" floppy cyl 80 alt 0 hd 2 sec 18");
592 capacity
= "1.44 MB";
597 if (drive_size
== 5) {
598 (void) strcpy(fd_vtoc
->v_asciilabel
,
599 "5.25\" floppy cyl 40 alt 0 hd 2 sec 9");
600 if (fdchar
.fdc_transfer_rate
== 500) {
602 * formatting a 360KB DD diskette in
603 * a 1.2MB drive is not a good idea
606 fdchar
.fdc_steps
= 2;
612 (void) strcpy(fd_vtoc
->v_asciilabel
,
613 "3.5\" floppy cyl 80 alt 0 hd 2 sec 9");
625 * 416.67 KB/sec is the effective transfer rate of a "medium"
626 * density diskette spun at 300 rpm instead of 360 rpm
630 (void) strcpy(fd_vtoc
->v_asciilabel
,
631 "3.5\" floppy cyl 77 alt 0 hd 2 sec 8");
638 (void) strcpy(fd_vtoc
->v_asciilabel
,
639 "3.5\" floppy cyl 80 alt 0 hd 2 sec 36");
640 transfer_rate
= 1000;
645 capacity
= "2.88 MB";
648 * Medium density diskettes have 1024 byte blocks. The dk_map
649 * structure in dklabel.h assumes the blocks size is DEVBSIZE (512)
650 * bytes. The dkl_nblk field is in terms of DEVBSIZE byte blocks
651 * while the spt variable is in terms of the true block size on
654 if (allmap
.dka_map
[2].dkl_nblk
!=
655 (2 * num_cyl
* spt
* (m_flag
? 2 : 1))) {
656 allmap
.dka_map
[1].dkl_cylno
= num_cyl
- 1;
657 allmap
.dka_map
[0].dkl_nblk
= 2 * (num_cyl
- 1) * spt
*
659 allmap
.dka_map
[1].dkl_nblk
= 2 * spt
* (m_flag
? 2 : 1);
660 allmap
.dka_map
[2].dkl_nblk
= 2 * num_cyl
* spt
*
662 if (allmap
.dka_map
[3].dkl_nblk
)
663 allmap
.dka_map
[3].dkl_nblk
= 2 * (num_cyl
- 1) * spt
*
665 if (allmap
.dka_map
[4].dkl_nblk
)
666 allmap
.dka_map
[4].dkl_nblk
=
667 2 * spt
* (m_flag
? 2 : 1);
671 /* initialize the vtoc structure */
672 fd_vtoc
->v_nparts
= 3;
674 fd_vtoc
->v_part
[0].p_start
= 0;
675 fd_vtoc
->v_part
[0].p_size
= ((num_cyl
- 1) * 2 * spt
*
677 fd_vtoc
->v_part
[1].p_start
= ((num_cyl
- 1) * 2 * spt
*
679 fd_vtoc
->v_part
[1].p_size
= 2 * spt
* (m_flag
? 2 : 1);
681 fd_vtoc
->v_part
[2].p_start
= 0;
682 fd_vtoc
->v_part
[2].p_size
= num_cyl
* 2 * spt
* (m_flag
? 2 : 1);
684 /* initialize the bios parameter blockstructure */
686 if (E_flag
&& drive_size
== 3) {
688 *rdirsec
= (ushort_t
)240;
689 bpb
->b_mediadescriptor
= (char)0xF0;
690 bpb
->b_fatsec
[0] = 9;
691 bpb
->b_fatsec
[1] = 0;
693 if (drive_size
== 5) {
696 bpb
->b_mediadescriptor
= (char)0xF9;
697 bpb
->b_fatsec
[0] = 7;
698 bpb
->b_fatsec
[1] = 0;
702 bpb
->b_mediadescriptor
= (char)0xF0;
703 bpb
->b_fatsec
[0] = 9;
704 bpb
->b_fatsec
[1] = 0;
706 } else if (drive_size
== 5) {
709 bpb
->b_mediadescriptor
= (char)0xFD;
710 bpb
->b_fatsec
[0] = 2;
711 bpb
->b_fatsec
[1] = 0;
712 } else if (drive_size
== 3) {
715 bpb
->b_mediadescriptor
= (char)0xF9;
716 bpb
->b_fatsec
[0] = 3;
717 bpb
->b_fatsec
[1] = 0;
723 if (num_cyl
> fdchar
.fdc_ncyl
|| spt
> fdchar
.fdc_secptrack
||
724 transfer_rate
> fdchar
.fdc_transfer_rate
) {
725 (void) fprintf(stderr
,
726 gettext("%s: drive not capable of requested density, "),
732 if (num_cyl
!= fdchar
.fdc_ncyl
|| spt
!= fdchar
.fdc_secptrack
||
733 transfer_rate
!= fdchar
.fdc_transfer_rate
) {
736 * The SPARC fd driver is using a non-zero value in
737 * fdc_medium to indicate the 360 rpm, 77 track,
738 * 9 sectors/track, 1024 bytes/sector mode of operation
739 * (similar to an 8", DS/DD, 1.2 MB floppy).
741 * The x86 fd driver uses fdc_medium as the diameter
742 * indicator, either 3 or 5. It should not be modified.
745 fdchar
.fdc_medium
= m_flag
? 1 : 0;
747 fdchar
.fdc_transfer_rate
= transfer_rate
;
748 fdchar
.fdc_ncyl
= num_cyl
;
749 fdchar
.fdc_sec_size
= sec_size
;
750 fdchar
.fdc_secptrack
= spt
;
752 if (ioctl(fd
, FDIOSCHAR
, &fdchar
) == -1) {
753 (void) fprintf(stderr
, gettext(
754 "%s: FDIOSCHAR (density selection) failed, "),
757 /* restore the default characteristics */
758 restore_default_chars(fd
, save_fdchar
, save_allmap
);
762 if (ioctl(fd
, DKIOCSAPART
, &allmap
) == -1) {
763 (void) fprintf(stderr
,
764 gettext("%s: DKIOCSAPART failed, "),
767 /* restore the default characteristics */
768 restore_default_chars(fd
, save_fdchar
, save_allmap
);
775 if (interleave
!= 1 && interleave
!= fdgeom
.dkg_intrlv
) {
776 fdgeom
.dkg_intrlv
= interleave
;
777 if (ioctl(fd
, DKIOCSGEOM
, &fdgeom
) == -1) {
778 (void) fprintf(stderr
,
779 gettext("%s: DKIOCSGEOM failed, "), myname
);
782 /* restore the default characteristics */
783 restore_default_chars(fd
, save_fdchar
, save_allmap
);
789 cyl_size
= 2 * sec_size
* spt
;
791 if ((ibuf1
= (uchar_t
*)malloc((size_t)cyl_size
)) == 0 ||
792 (obuf
= (uchar_t
*)malloc((size_t)cyl_size
)) == 0) {
793 (void) fprintf(stderr
,
794 gettext("%s: can't malloc verify buffer, "),
797 /* restore the default characteristics */
798 restore_default_chars(fd
, save_fdchar
, save_allmap
);
802 (void) memset(ibuf1
, (uchar_t
)0xA5, cyl_size
);
807 if (!(q_flag
&& f_flag
)) {
808 if (interleave
!= 1) {
809 (void) printf(gettext(
810 "Formatting %s, %d cylinders, %d sectors per trk, interleave=%d in %s\n"),
811 capacity
, num_cyl
, spt
, interleave
, real_name
);
813 (void) printf(gettext("Formatting %s in %s\n"),
814 capacity
, real_name
);
819 gettext("Press return to start formatting floppy."));
820 while (getchar() != '\n')
824 * for those systems that support this ioctl, they will
825 * return whether or not a diskette is in the drive.
827 if (ioctl(fd
, FDGETCHANGE
, &chgd
) == 0) {
828 if (chgd
& FDGC_CURRENT
) {
829 (void) fprintf(stderr
,
830 gettext("%s: no diskette in drive %s\n"),
833 /* restore the default characteristics */
834 restore_default_chars(fd
, save_fdchar
, save_allmap
);
838 if (chgd
& FDGC_CURWPROT
) {
839 (void) fprintf(stderr
,
840 gettext("%s: \"%s\" is write protected\n"),
843 /* restore the default characteristics */
844 restore_default_chars(fd
, save_fdchar
, save_allmap
);
850 if ((fbuf
= (uchar_t
*)malloc((unsigned)(4 * spt
))) == 0) {
851 (void) fprintf(stderr
,
852 gettext("%s: can't malloc format header buffer, "),
856 /* restore the default characteristics */
857 restore_default_chars(fd
, save_fdchar
, save_allmap
);
862 * do the format, a track at a time
864 for (cyl
= 0; cyl
< (z_flag
? 1 : (int)num_cyl
); cyl
++) {
866 * This is not the optimal ioctl to format the floppy.
867 * The device driver should do do the work,
868 * instead of this program mucking with a lot
869 * of low-level, device-dependent code.
871 fdr_seek
.fdr_cmd
[2] = cyl
;
872 if (ioctl(fd
, FDRAW
, &fdr_seek
) == -1) {
873 (void) fprintf(stderr
,
874 gettext("%s: seek to cyl %d failed\n"),
877 /* restore the default characteristics */
878 restore_default_chars(fd
, save_fdchar
, save_allmap
);
883 * Assume that the fd driver has issued a SENSE_INT
884 * command to complete the seek operation.
886 for (hd
= 0; hd
< fdchar
.fdc_nhead
; hd
++) {
888 for (i
= 1; i
<= spt
; i
++) {
891 *p
++ = i
; /* sector # */
892 *p
++ = (sec_size
== 1024) ? 3 : 2;
895 * ASSUME the fd driver is going to set drive-select
896 * bits in the second command byte
898 fdr_form
.fdr_cmd
[1] = hd
<< 2;
899 fdr_form
.fdr_cmd
[2] = (sec_size
== 1024) ? 3 : 2;
900 fdr_form
.fdr_cmd
[3] = spt
;
901 fdr_form
.fdr_cmd
[4] = gap
;
902 fdr_form
.fdr_nbytes
= 4 * spt
;
903 fdr_form
.fdr_addr
= (char *)fbuf
;
905 if (ioctl(fd
, FDRAW
, &fdr_form
) == -1) {
908 (void) fprintf(stderr
, gettext(
909 "%s: format of cyl %d head %d failed\n"),
912 /* restore the default characteristics */
913 restore_default_chars(fd
, save_fdchar
,
918 if (fdr_form
.fdr_result
[0] & 0xC0) {
919 if (fdr_form
.fdr_result
[1] & 0x02) {
920 (void) fprintf(stderr
, gettext(
922 "%s: diskette is write protected\n"),
926 * restore the default
929 restore_default_chars(fd
, save_fdchar
,
934 (void) fprintf(stderr
, gettext(
935 "%s: format of cyl %d head %d failed\n"),
938 /* restore the default characteristics */
939 restore_default_chars(fd
, save_fdchar
,
951 if (lseek(fd
, cyl
* cyl_size
, 0) != cyl
* cyl_size
) {
952 (void) fprintf(stderr
,
953 gettext("%s: bad seek to format verify, "),
956 /* restore the default characteristics */
957 restore_default_chars(fd
, save_fdchar
,
962 if (read(fd
, obuf
, cyl_size
) == cyl_size
) {
963 /* write some progress msg */
964 /* when each cylinder is done. */
969 (void) printf(gettext("e\n"));
970 (void) fprintf(stderr
, gettext(
971 "%s: can't read format data, "), myname
);
973 /* restore the default characteristics */
974 restore_default_chars(fd
, save_fdchar
,
983 (void) fflush(stdout
);
990 * do a write & read verify of the entire diskette
992 if (!q_flag
&& x_flag
)
993 (void) printf(gettext("Verifying %s in %s\n"),
994 capacity
, real_name
);
996 for (cyl
= 0; cyl
< (int)num_cyl
; cyl
++) {
999 if ((val
= verify(fd
, 2 * spt
* cyl
, cyl_size
)) != 0) {
1002 /* restore the default characteristics */
1003 restore_default_chars(fd
, save_fdchar
,
1009 /* write some progress msg as */
1010 /* each cylinder is done. */
1012 (void) printf(gettext("v"));
1013 (void) fflush(stdout
);
1016 (void) printf("\n");
1019 if (lseek(fd
, (off_t
)0, 0) != 0) {
1020 (void) fprintf(stderr
, gettext("%s: seek to blk 0 failed, "),
1023 /* restore the default characteristics */
1024 restore_default_chars(fd
, save_fdchar
, save_allmap
);
1033 * Restore the default characteristics of the floppy diskette.
1034 * Fdformat changes the characteristics in the process of formatting.
1035 * If fdformat fails while in the process of doing the format, fdformat
1036 * should clean up after itself and reset the driver back to the original
1041 restore_default_chars(int fd
,
1042 struct fd_char save_fdchar
,
1043 struct dk_allmap save_allmap
)
1048 * When this function is called, fdformat is failing anyways,
1049 * so the errors are not processed.
1052 (void) ioctl(fd
, FDIOSCHAR
, &save_fdchar
);
1054 (void) ioctl(fd
, DKIOCSAPART
, &save_allmap
);
1057 * Before looking at the diskette's characteristics, format_diskette()
1058 * sets the x86 floppy driver to the default characteristics.
1059 * restore drive to default geometry and
1060 * characteristics. This ioctl isn't implemented on
1063 (void) ioctl(fd
, FDDEFGEOCHAR
, NULL
);
1068 * See if any partitions on the device are mounted. Return 1 if a partition is
1069 * mounted. Return 0 otherwise.
1076 struct dk_cinfo dkinfo_tmp
;
1077 struct mnttab mnt_record
;
1078 struct mnttab
*mp
= &mnt_record
;
1080 char raw_device
[MAXPATHLEN
];
1083 if ((fp
= fopen(MNTTAB
, "r")) == NULL
) {
1088 while (getmntent(fp
, mp
) == 0) {
1089 if (strstr(mp
->mnt_special
, "/dev/fd") == NULL
&&
1090 strstr(mp
->mnt_special
, "/dev/disket") == NULL
&&
1091 strstr(mp
->mnt_special
, "/dev/c") == NULL
) {
1095 (void) strcpy(raw_device
, "/dev/r");
1096 (void) strcat(raw_device
, mp
->mnt_special
+ strlen("/dev/"));
1099 * Attempt to open the device. If it fails, skip it.
1101 if ((mfd
= open(raw_device
, O_RDWR
| O_NDELAY
)) < 0) {
1106 * Must be a character device
1108 if (fstat(mfd
, &stbuf
) == -1 || !S_ISCHR(stbuf
.st_mode
)) {
1113 * Attempt to read the configuration info on the disk.
1115 if (ioctl(mfd
, DKIOCINFO
, &dkinfo_tmp
) < 0) {
1120 * Finished with the opened device
1125 * If it's not the disk we're interested in, it doesn't apply.
1127 if (dkinfo
.dki_ctype
!= dkinfo_tmp
.dki_ctype
||
1128 dkinfo
.dki_cnum
!= dkinfo_tmp
.dki_cnum
||
1129 dkinfo
.dki_unit
!= dkinfo_tmp
.dki_unit
) {
1133 * It's a mount on the disk we're checking. If we are
1134 * checking whole disk, then we found trouble. We can
1139 if (!_dev_unmount(mp
->mnt_special
)) {
1140 (void) fprintf(stderr
,
1141 gettext("%s: umount of %s failed\n"),
1142 myname
, mp
->mnt_special
);
1146 (void) fprintf(stderr
,
1147 gettext("%s: %s is mounted (use -U flag)\n"),
1148 myname
, mp
->mnt_special
);
1158 char *real_name
, *alias_name
;
1160 if ((real_name
= media_findname("floppy")) == NULL
) {
1161 if ((alias_name
= _media_oldaliases("floppy")) != NULL
)
1162 real_name
= media_findname(alias_name
);
1166 (void) printf("%s: %s\n", myname
, str
);
1167 (void) printf(gettext(
1169 "\n usage: %s [-dDeEfHlLmMqUvx] [-b label] [-B file] [-t dostype] [devname]\n"),
1172 (void) printf(gettext(
1174 " -b label install \"label\" on media\n"));
1175 (void) printf(gettext(
1176 " -B file install special boot loader on MS-DOS media\n"));
1177 (void) printf(gettext(
1179 " -d format MS-DOS media\n"));
1180 (void) printf(gettext(
1182 " -D format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
1183 (void) printf(gettext(
1184 " -e eject the media when done\n"));
1186 (void) printf(gettext(
1188 " -E format 2.88MB (3.5\") Extended-density diskette\n"));
1189 (void) printf(gettext(
1190 " -f \"force\" - don't wait for confirmation\n"));
1191 (void) printf(gettext(
1193 " -H format 1.44MB (3.5\") or 1.2MB (5.25\") High-density diskette\n"));
1194 (void) printf(gettext(
1196 " -l format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
1197 (void) printf(gettext(
1199 " -L format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n"));
1200 (void) printf(gettext(
1201 " -m format 1.2MB (3.5\") Medium-density diskette\n"));
1202 (void) printf(gettext(
1203 " -M format 1.2MB (3.5\") Medium-density diskette\n"));
1204 (void) printf(gettext(
1206 (void) printf(gettext(
1208 " -t dos format MS-DOS media (same as -d)\n"));
1209 (void) printf(gettext(
1210 " -t nec format NEC-DOS media (with -M only)\n"));
1211 (void) printf(gettext(
1213 " -U unmount media if it's mounted\n"));
1214 (void) printf(gettext(
1215 " -v verify each block of the media\n"));
1216 (void) printf(gettext(
1217 " -x skip the format, only install SunOS or DOS label\n"));
1219 (void) printf(gettext(
1220 " devname defaults to '%s'\n"),
1221 real_name
? real_name
: gettext("no available default device"));
1229 verify(int fd
, int blk
, int len
)
1232 char *nullstring
= "";
1234 off
= (off_t
)(blk
* (m_flag
? 1024 : 512));
1236 if (lseek(fd
, off
, 0) != off
) {
1238 (void) printf(gettext("e\n"));
1239 (void) fprintf(stderr
,
1240 gettext("%s: can't seek to write verify, "), myname
);
1244 if (write(fd
, ibuf1
, len
) != len
) {
1246 (void) printf(gettext("e\n"));
1248 (void) fprintf(stderr
,
1249 gettext("%s: check diskette density, "),
1252 (void) fprintf(stderr
,
1253 gettext("%s: can't write verify data, "),
1259 if (lseek(fd
, off
, 0) != off
) {
1261 (void) printf(gettext("e\n"));
1262 (void) fprintf(stderr
,
1263 gettext("%s: bad seek to read verify, "),
1268 if (read(fd
, obuf
, len
) != len
) {
1270 (void) printf(gettext("e\n"));
1271 (void) fprintf(stderr
,
1272 gettext("%s: can't read verify data, "), myname
);
1276 if (memcmp(ibuf1
, obuf
, len
)) {
1278 (void) printf(gettext("e\n"));
1279 (void) fprintf(stderr
, gettext("%s: verify data failure\n"),
1287 * write a SunOS label
1288 * NOTE: this function assumes fd_vtoc has been filled in with the
1289 * device specific information such as partition information
1290 * and the asciilabel
1293 write_SunOS_label(int fd
, char *volname
, struct vtoc
*fd_vtoc
)
1295 char *nullstring
= "";
1297 fd_vtoc
->v_sanity
= VTOC_SANE
;
1300 * The label structure is set up for DEV_BSIZE (512 byte) blocks,
1301 * even though a medium density diskette has 1024 byte blocks
1302 * See dklabel.h for more details.
1304 fd_vtoc
->v_sectorsz
= DEV_BSIZE
;
1306 (void) strncpy(fd_vtoc
->v_volume
, volname
, sizeof (fd_vtoc
->v_volume
));
1308 /* let the fd driver finish constructing the label and writing it */
1309 if (ioctl(fd
, DKIOCSVTOC
, fd_vtoc
) == -1) {
1310 (void) fprintf(stderr
,
1311 gettext("%s: write of SunOS label failed, "), myname
);
1320 * MS-DOS Disk layout:
1322 * ---------------------
1324 * |-------------------|
1326 * |-------------------|
1328 * |-------------------|
1330 * |-------------------|
1331 * | Root directory |
1332 * |-------------------|
1335 * |___________________|
1339 * The following is a copy of MS-DOS 3.3 boot block.
1340 * It consists of the BIOS parameter block, and a disk
1341 * bootstrap program.
1343 * The BIOS parameter block contains the right values
1344 * for the 3.5" high-density 1.44MB floppy format.
1347 static uchar_t bootsec
[512] = {
1348 0xeb, 0x34, 0x90, /* 8086 short jump + displacement + NOP */
1349 'M', 'S', 'D', 'O', 'S', '3', '.', '3', /* OEM name & version */
1350 0, 2, 1, 1, 0, /* Start of BIOS parameter block */
1351 2, 224, 0, 0x40, 0xb, 0xf0, 9, 0,
1352 18, 0, 2, 0, 0, 0, /* End of BIOS parameter block */
1353 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
1354 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12,
1356 0x1, 0x0, 0xfa, 0x33, /* 0x34, start of the bootstrap. */
1357 0xc0, 0x8e, 0xd0, 0xbc, 0x0, 0x7c, 0x16, 0x7,
1358 0xbb, 0x78, 0x0, 0x36, 0xc5, 0x37, 0x1e, 0x56,
1359 0x16, 0x53, 0xbf, 0x2b, 0x7c, 0xb9, 0xb, 0x0,
1360 0xfc, 0xac, 0x26, 0x80, 0x3d, 0x0, 0x74, 0x3,
1361 0x26, 0x8a, 0x5, 0xaa, 0x8a, 0xc4, 0xe2, 0xf1,
1362 0x6, 0x1f, 0x89, 0x47, 0x2, 0xc7, 0x7, 0x2b,
1363 0x7c, 0xfb, 0xcd, 0x13, 0x72, 0x67, 0xa0, 0x10,
1364 0x7c, 0x98, 0xf7, 0x26, 0x16, 0x7c, 0x3, 0x6,
1365 0x1c, 0x7c, 0x3, 0x6, 0xe, 0x7c, 0xa3, 0x3f,
1366 0x7c, 0xa3, 0x37, 0x7c, 0xb8, 0x20, 0x0, 0xf7,
1367 0x26, 0x11, 0x7c, 0x8b, 0x1e, 0xb, 0x7c, 0x3,
1368 0xc3, 0x48, 0xf7, 0xf3, 0x1, 0x6, 0x37, 0x7c,
1369 0xbb, 0x0, 0x5, 0xa1, 0x3f, 0x7c, 0xe8, 0x9f,
1370 0x0, 0xb8, 0x1, 0x2, 0xe8, 0xb3, 0x0, 0x72,
1371 0x19, 0x8b, 0xfb, 0xb9, 0xb, 0x0, 0xbe, 0xd6,
1372 0x7d, 0xf3, 0xa6, 0x75, 0xd, 0x8d, 0x7f, 0x20,
1373 0xbe, 0xe1, 0x7d, 0xb9, 0xb, 0x0, 0xf3, 0xa6,
1374 0x74, 0x18, 0xbe, 0x77, 0x7d, 0xe8, 0x6a, 0x0,
1375 0x32, 0xe4, 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x4,
1376 0x8f, 0x44, 0x2, 0xcd, 0x19, 0xbe, 0xc0, 0x7d,
1377 0xeb, 0xeb, 0xa1, 0x1c, 0x5, 0x33, 0xd2, 0xf7,
1378 0x36, 0xb, 0x7c, 0xfe, 0xc0, 0xa2, 0x3c, 0x7c,
1379 0xa1, 0x37, 0x7c, 0xa3, 0x3d, 0x7c, 0xbb, 0x0,
1380 0x7, 0xa1, 0x37, 0x7c, 0xe8, 0x49, 0x0, 0xa1,
1381 0x18, 0x7c, 0x2a, 0x6, 0x3b, 0x7c, 0x40, 0x38,
1382 0x6, 0x3c, 0x7c, 0x73, 0x3, 0xa0, 0x3c, 0x7c,
1383 0x50, 0xe8, 0x4e, 0x0, 0x58, 0x72, 0xc6, 0x28,
1384 0x6, 0x3c, 0x7c, 0x74, 0xc, 0x1, 0x6, 0x37,
1385 0x7c, 0xf7, 0x26, 0xb, 0x7c, 0x3, 0xd8, 0xeb,
1386 0xd0, 0x8a, 0x2e, 0x15, 0x7c, 0x8a, 0x16, 0xfd,
1387 0x7d, 0x8b, 0x1e, 0x3d, 0x7c, 0xea, 0x0, 0x0,
1388 0x70, 0x0, 0xac, 0xa, 0xc0, 0x74, 0x22, 0xb4,
1389 0xe, 0xbb, 0x7, 0x0, 0xcd, 0x10, 0xeb, 0xf2,
1390 0x33, 0xd2, 0xf7, 0x36, 0x18, 0x7c, 0xfe, 0xc2,
1391 0x88, 0x16, 0x3b, 0x7c, 0x33, 0xd2, 0xf7, 0x36,
1392 0x1a, 0x7c, 0x88, 0x16, 0x2a, 0x7c, 0xa3, 0x39,
1393 0x7c, 0xc3, 0xb4, 0x2, 0x8b, 0x16, 0x39, 0x7c,
1394 0xb1, 0x6, 0xd2, 0xe6, 0xa, 0x36, 0x3b, 0x7c,
1395 0x8b, 0xca, 0x86, 0xe9, 0x8a, 0x16, 0xfd, 0x7d,
1396 0x8a, 0x36, 0x2a, 0x7c, 0xcd, 0x13, 0xc3, '\r',
1397 '\n', 'N', 'o', 'n', '-', 'S', 'y', 's',
1398 't', 'e', 'm', ' ', 'd', 'i', 's', 'k',
1399 ' ', 'o', 'r', ' ', 'd', 'i', 's', 'k',
1400 ' ', 'e', 'r', 'r', 'o', 'r', '\r', '\n',
1401 'R', 'e', 'p', 'l', 'a', 'c', 'e', ' ',
1402 'a', 'n', 'd', ' ', 's', 't', 'r', 'i',
1403 'k', 'e', ' ', 'a', 'n', 'y', ' ', 'k',
1404 'e', 'y', ' ', 'w', 'h', 'e', 'n', ' ',
1405 'r', 'e', 'a', 'd', 'y', '\r', '\n', '\0',
1406 '\r', '\n', 'D', 'i', 's', 'k', ' ', 'B',
1407 'o', 'o', 't', ' ', 'f', 'a', 'i', 'l',
1408 'u', 'r', 'e', '\r', '\n', '\0', 'I', 'O',
1409 ' ', ' ', ' ', ' ', ' ', ' ', 'S', 'Y',
1410 'S', 'M', 'S', 'D', 'O', 'S', ' ', ' ',
1411 ' ', 'S', 'Y', 'S', '\0', 0, 0, 0,
1412 0, 0, 0, 0, 0, 0, 0, 0, 0,
1413 0, 0, 0, 0, 0, 0x55, 0xaa
1417 valid_DOS_boot(char *bootfile
, uchar_t
**bootloadp
)
1421 uchar_t
*bootloader
;
1425 char *nullstring
= "";
1427 if ((err
= stat(bootfile
, &status
)) != 0) {
1428 (void) fprintf(stderr
, gettext("%s: \"%s\" stat error %d\n"),
1429 myname
, bootfile
, err
);
1432 if ((boot_size
= status
.st_size
) < 512) {
1433 (void) fprintf(stderr
,
1434 gettext("%s: short boot sector"), myname
);
1438 sizebootldr
= (boot_size
+ 511) / 512 * 512;
1439 if ((bootloader
= (uchar_t
*)malloc((size_t)sizebootldr
)) == NULL
) {
1440 (void) fprintf(stderr
, gettext("%s: malloc error\n"),
1445 /* switch to user to access the boot file */
1446 (void) seteuid(getuid());
1448 if ((bfd
= open(bootfile
, O_RDONLY
)) == -1) {
1449 (void) fprintf(stderr
, gettext("%s: could not open \"%s\": "),
1455 /* restore effective id */
1456 (void) seteuid(euid
);
1458 if (read(bfd
, bootloader
, boot_size
) != boot_size
) {
1459 (void) fprintf(stderr
,
1460 gettext("%s: read of MS-DOS boot file failed, "), myname
);
1466 if (!((*bootloader
== 0xE9 ||
1467 (*bootloader
== 0xEB && *(bootloader
+ 2) == 0x90)) &&
1468 *(bootloader
+ 510) == 0x55 &&
1469 *(bootloader
+ 511) == 0xAA)) {
1470 (void) fprintf(stderr
,
1471 gettext("%s: invalid MS-DOS boot loader image\n"), myname
);
1476 *bootloadp
= bootloader
;
1482 write_DOS_label(int fd
, uchar_t
*bootloadr
, int bootlen
, char *altbootname
,
1483 char *doslabel
, struct bios_param_blk
*bpb
, int rdirsec
)
1491 char *nullstring
= "";
1493 if (bootlen
< 512 || !bootloadr
) {
1494 /* use default boot loader routine */
1495 bootloadr
= bootsec
;
1499 (gettext("%s: using \"%s\" for MS-DOS boot loader\n"),
1500 myname
, altbootname
);
1501 if (bootlen
% 512 > 0)
1502 bootlen
= (bootlen
+ 511) / 512 * 512;
1504 bpb
->b_bps
[0] = getlobyte(512);
1505 bpb
->b_bps
[1] = gethibyte(512);
1506 /* MS-DOS 5.0 supports only 1 reserved sector :-( */
1507 bpb
->b_res_sec
[0] = 1;
1508 bpb
->b_res_sec
[1] = 0;
1510 totalsec
= fdchar
.fdc_ncyl
* fdchar
.fdc_nhead
* fdchar
.fdc_secptrack
;
1511 bpb
->b_totalsec
[0] = getlobyte(totalsec
);
1512 bpb
->b_totalsec
[1] = gethibyte(totalsec
);
1513 bpb
->b_spt
[0] = fdchar
.fdc_secptrack
;
1515 bpb
->b_nhead
[0] = fdchar
.fdc_nhead
;
1516 bpb
->b_nhead
[1] = 0;
1517 bpb
->b_hiddensec
[0] = 0;
1518 bpb
->b_hiddensec
[1] = 0;
1520 bpb
->b_rdirents
[0] = getlobyte(rdirsec
);
1521 bpb
->b_rdirents
[1] = gethibyte(rdirsec
);
1523 (void) memcpy((char *)(bootloadr
+ 0x0B), (char *)bpb
,
1524 sizeof (struct bios_param_blk
));
1526 if (write(fd
, bootloadr
, 512) != 512) {
1527 (void) fprintf(stderr
,
1528 gettext("%s: write of MS-DOS boot sector failed"), myname
);
1535 fat_bsize
= 512 * bpb
->b_fatsec
[0];
1536 fat_rdir
= (uchar_t
*)malloc(fat_bsize
);
1537 (void) memset(fat_rdir
, 0, fat_bsize
);
1539 *fat_rdir
= bpb
->b_mediadescriptor
;
1540 *(fat_rdir
+ 1) = 0xFF;
1541 *(fat_rdir
+ 2) = 0xFF;
1542 bootclen
= (bootlen
+ 512 * (int)bpb
->b_spcl
- 1) /
1543 (512 * (int)bpb
->b_spcl
);
1544 #define BAD_CLUSTER 0xFF7
1545 for (i
= 0, fatptr
= fat_rdir
+3; i
< bootclen
; i
++)
1547 * pre-allocate any clusters used by boot loader if
1548 * loader will occupy more than 1 sector
1551 *fatptr
++ = BAD_CLUSTER
& 0xFF;
1552 *fatptr
= (BAD_CLUSTER
>> 8) & 0x0F;
1554 *fatptr
= (*fatptr
& 0x0F) |
1555 ((BAD_CLUSTER
<< 4) & 0xF0);
1557 *fatptr
++ = (BAD_CLUSTER
>> 4) & 0xFF;
1559 for (i
= 0; i
< (int)bpb
->b_nfat
; ++i
)
1560 if (write(fd
, fat_rdir
, fat_bsize
) != fat_bsize
) {
1561 (void) fprintf(stderr
,
1562 gettext("%s: write of MS-DOS File Allocation Table failed, "),
1567 rdirsec
= bpb
->b_rdirents
[0];
1568 rdirsec
= 32 * (int)rdirsec
/ 512;
1575 /* the label can be no more than 11 characters */
1576 j
= min(11, (int)strlen(doslabel
));
1577 for (i
= 0; i
< j
; i
++) {
1578 fat_rdir
[i
] = uppercase(doslabel
[i
]);
1580 for (; i
< 11; i
++) {
1583 fat_rdir
[0x0B] = 0x28;
1584 (void) gettimeofday(&tv
, NULL
);
1585 tp
= localtime(&tv
.tv_sec
);
1586 /* get the time & day into DOS format */
1587 dostime
= tp
->tm_sec
/ 2;
1588 dostime
|= tp
->tm_min
<< 5;
1589 dostime
|= tp
->tm_hour
<< 11;
1590 dosday
= tp
->tm_mday
;
1591 dosday
|= (tp
->tm_mon
+ 1) << 5;
1592 dosday
|= (tp
->tm_year
- 80) << 9;
1593 fat_rdir
[0x16] = getlobyte(dostime
);
1594 fat_rdir
[0x17] = gethibyte(dostime
);
1595 fat_rdir
[0x18] = getlobyte(dosday
);
1596 fat_rdir
[0x19] = gethibyte(dosday
);
1598 if (write(fd
, fat_rdir
, 512) != 512) {
1599 (void) fprintf(stderr
,
1600 gettext("%s: write of MS-DOS FAT failed, "),
1609 (void) memset(fat_rdir
, 0, 512);
1610 for (; i
< (int)rdirsec
; ++i
) {
1611 if (write(fd
, fat_rdir
, 512) != 512) {
1612 (void) fprintf(stderr
,
1613 gettext("%s: write of MS-DOS root directory failed, "),
1620 * Write the rest of the boot loader if it's longer than one sector.
1621 * The clusters used are marked Bad in the FAT.
1622 * No directory entry exists for this file (so that it cannot be
1625 if (bootlen
&& write(fd
, bootloadr
, bootlen
) != bootlen
) {
1626 (void) fprintf(stderr
,
1627 gettext("%s: write of MS-DOS boot sectors failed"), myname
);
1634 write_NEC_DOS_label(int fd
, char *doslabel
)
1636 struct bios_param_blk
*bpb
;
1639 char fat_rdir
[1024];
1641 uchar_t bootsec_NEC
[1024];
1642 char *nullstring
= "";
1644 uchar_t bios_param_NEC
[30] = { 0xeb, 0x1c, 0x90, 0x0, 0x0, 0x0, 0x0,
1645 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x1, 0x1, 0x0,
1646 0x2, 0xc0, 0x0, 0xd0, 0x4, 0xfe, 0x2, 0x0,
1647 0x8, 0x0, 0x2, 0x0, 0x0, 0x0
1650 uchar_t fatdir
[32] = { 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
1651 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
1652 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
1653 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5
1658 (void) memset(bootsec_NEC
, 0, 1024);
1660 (void) memcpy(&bootsec_NEC
, &bios_param_NEC
, 30);
1662 bpb
= (struct bios_param_blk
*)&(bootsec_NEC
[0xb]);
1663 if (write(fd
, &bootsec_NEC
[0], 1024) != 1024) {
1664 (void) fprintf(stderr
, gettext(
1665 "%s: write of NEC-DOS boot sector failed, "),
1670 (void) memset(fat_rdir
, 0, 1024);
1671 fatsec
= bpb
->b_fatsec
[0];
1672 for (i
= 0; i
< (int)bpb
->b_nfat
* (int)fatsec
; ++i
) {
1673 if ((i
% (int)fatsec
) == 0) {
1674 fat_rdir
[0] = bpb
->b_mediadescriptor
;
1675 fat_rdir
[1] = (char)0xff;
1676 fat_rdir
[2] = (char)0xff;
1688 if (write(fd
, &fat_rdir
[0], 1024) != 1024) {
1689 (void) fprintf(stderr
,
1691 gettext("%s: write of NEC-DOS File Allocation Table failed, "), myname
);
1698 rdirsec
= (int)htols(bpb
->b_rdirents
[0]) * 32 /1024;
1700 rdirsec
= (int)htols(bpb
->b_rdirents
[0]) * 32 /1024;
1708 /* the label can be no more than 11 characters */
1709 j
= min(11, (int)strlen(doslabel
));
1710 for (i
= 0; i
< j
; i
++) {
1711 fat_rdir
[i
] = uppercase(doslabel
[i
]);
1713 for (; i
< 11; i
++) {
1716 fat_rdir
[0xb] = 0x28;
1717 (void) gettimeofday(&tv
, NULL
);
1718 tp
= localtime(&tv
.tv_sec
);
1719 /* get the time & day into DOS format */
1720 dostime
= tp
->tm_sec
/ 2;
1721 dostime
|= tp
->tm_min
<< 5;
1722 dostime
|= tp
->tm_hour
<< 11;
1723 dosday
= tp
->tm_mday
;
1724 dosday
|= (tp
->tm_mon
+ 1) << 5;
1725 dosday
|= (tp
->tm_year
- 80) << 9;
1726 fat_rdir
[0x16] = getlobyte(dostime
);
1727 fat_rdir
[0x17] = gethibyte(dostime
);
1728 fat_rdir
[0x18] = getlobyte(dosday
);
1729 fat_rdir
[0x19] = gethibyte(dosday
);
1731 if (write(fd
, &fat_rdir
[0], 1024) != 1024) {
1732 (void) fprintf(stderr
,
1734 gettext("%s: write of NEC-DOS root directory failed, "), myname
);
1738 (void) memset(fat_rdir
, 0, 512);
1744 (void) memcpy(&fat_rdir
[m
], &fatdir
, 31);
1748 for (; i
< (int)rdirsec
; ++i
) {
1750 if (write(fd
, &fat_rdir
[0], 1024) != 1024) {
1751 (void) fprintf(stderr
,
1753 gettext("%s: write of NEC-DOS root directory failed, "), myname
);