1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1991-2002 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * fdformat program - formats floppy disks, and then adds a label to them 31 * 32 * ****Warning, Warning, Warning, Warning***** 33 * This program runs suid root. This change was made to 34 * allow it to umount a file system if it's mounted. 35 */ 36 37 #include <stdio.h> 38 #include <fcntl.h> 39 #include <stdlib.h> 40 #include <unistd.h> 41 #include <string.h> 42 #include <memory.h> 43 #include <errno.h> 44 #include <locale.h> 45 #include <libintl.h> 46 #include <volmgt.h> 47 #include <sys/isa_defs.h> 48 #include <sys/ioccom.h> 49 #include <sys/types.h> 50 #include <sys/time.h> 51 #include <sys/file.h> 52 #include <sys/dklabel.h> 53 #include <sys/ioctl.h> 54 #include <sys/dkio.h> 55 #include <sys/fdio.h> 56 #include <sys/stat.h> 57 #include <sys/vtoc.h> 58 #include <sys/mnttab.h> 59 60 /* DEFINES */ 61 #if defined(_BIG_ENDIAN) 62 #define getbyte(A, N) (((unsigned char *)(&(A)))[N]) 63 #define htols(S) ((getbyte(S, 1) <<8) | getbyte(S, 0)) 64 #elif defined(_LITTLE_ENDIAN) 65 #define htols(S) (*((ushort_t *)(&(S)))) 66 #else 67 #error One of _BIG_ENDIAN or LITTLE_ENDIAN must be defined 68 #endif 69 70 #define getlobyte(A) (A & 0xFF) 71 #define gethibyte(A) (A >> 8 & 0xFF) 72 #define uppercase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c)) 73 #define min(a, b) ((a) < (b) ? (a) : (b)) 74 75 /* 76 * These defines are from the PCMCIA memory driver driver 77 * header files (pcramio.h/pcramvar.h) and they are in 78 * the Platform Specific (PS) train. 79 */ 80 #ifndef PCRAM_PROBESIZE 81 #define PCRAMIOC ('P' << 8) 82 #define PCRAM_PROBESIZE (PCRAMIOC|22) /* Probe memory card size */ 83 #endif 84 85 /* FORMAT PATTERNS */ 86 #define PATTERN_1 0x55; 87 #define PATTERN_2 0xaa; 88 #define PATTERN_3 0xff; 89 #define PATTERN_4 0x00; 90 91 /* UNINITIALIZED DATA */ 92 static struct fd_char fdchar; 93 static struct dk_geom fdgeom; 94 static struct dk_allmap allmap; 95 static struct dk_cinfo dkinfo; 96 static struct dk_geom dkg; 97 98 /* EXTERN */ 99 extern char *optarg; 100 extern int optind; 101 102 /* for verify buffers */ 103 static uchar_t *ibuf1; 104 static uchar_t *obuf; 105 106 static char *myname; 107 108 static int fd_debug = 1; /* 1 if debug XXX */ 109 static int b_flag = 0; /* install a volume label to the diskette */ 110 static int d_flag = 0; /* format the diskette in dos format */ 111 static int D_flag = 0; /* double (aka low) density flag */ 112 static int e_flag = 0; /* "eject" diskette when done (if supported) */ 113 static int E_flag = 0; /* extended density */ 114 static int f_flag = 0; /* "force" (no confirmation before start) */ 115 static int H_flag = 0; /* high density */ 116 static int m_flag = 0; /* medium density */ 117 static int n_flag = 0; /* format the diskette in NEC-DOS format */ 118 static int q_flag = 0; /* quiet format flag */ 119 static int U_flag = 0; /* automatically unmount if it's mounted */ 120 static int v_flag = 0; /* verify format/diskette flag */ 121 static int x_flag = 0; /* skip the format, only install SunOS label */ 122 /* or DOS file system */ 123 static int z_flag = 0; /* debugging only, setting partial formatting */ 124 static int interleave = 1; /* interleave factor */ 125 static int pcmcia = 0; /* 1 if media is a pcmcia card */ 126 127 static uid_t euid = 0; /* stores effective user id */ 128 129 struct bios_param_blk { 130 uchar_t b_bps[2]; /* bytes per sector */ 131 uchar_t b_spcl; /* sectors per alloction unit */ 132 uchar_t b_res_sec[2]; /* reserved sectors, starting at 0 */ 133 uchar_t b_nfat; /* number of FATs */ 134 uchar_t b_rdirents[2]; /* number of root directory entries */ 135 uchar_t b_totalsec[2]; /* total sectors in logical image */ 136 char b_mediadescriptor; /* media descriptor byte */ 137 uchar_t b_fatsec[2]; /* number of sectors per FAT */ 138 uchar_t b_spt[2]; /* sectors per track */ 139 uchar_t b_nhead[2]; /* number of heads */ 140 uchar_t b_hiddensec[2]; /* number of hidden sectors */ 141 }; 142 143 /* 144 * ON-private functions from libvolmgt 145 */ 146 char *_media_oldaliases(char *name); 147 int _dev_mounted(char *path); 148 int _dev_unmount(char *path); 149 150 /* 151 * local functions 152 */ 153 static void usage(char *); 154 static int verify(int, int, int); 155 static void write_SunOS_label(int, char *, struct vtoc *); 156 static int valid_DOS_boot(char *, uchar_t **); 157 static void write_DOS_label(int, uchar_t *, int, char *, char *, 158 struct bios_param_blk *, int); 159 static void write_NEC_DOS_label(int, char *); 160 static int check_mount(); 161 static void format_diskette(int, char *, struct vtoc *, 162 struct bios_param_blk *, int *); 163 static void format_pcmcia_card(int, char *, struct vtoc *, 164 struct bios_param_blk *, int *); 165 static void restore_default_chars(int fd, 166 struct fd_char save_fdchar, 167 struct dk_allmap save_allmap); 168 169 int 170 main(int argc, char **argv) 171 { 172 int altsize = 0; 173 int fd; 174 int i; 175 uchar_t *altboot = NULL; 176 char *altbootname = NULL; 177 char *dev_name = NULL, *real_name, *alias_name; 178 char *vollabel = ""; 179 struct vtoc fd_vtoc; 180 struct bios_param_blk bpb; 181 int rdirsec; 182 char *nullstring = ""; 183 184 (void) setlocale(LC_ALL, ""); 185 186 #if !defined(TEXT_DOMAIN) 187 #define TEXT_DOMAIN "SYS_TEST" 188 #endif 189 190 (void) textdomain(TEXT_DOMAIN); 191 192 myname = argv[0]; 193 while ((i = getopt(argc, argv, "B:b:dDeEfhHlLmMxqt:UvVZ?")) != -1) { 194 switch (i) { 195 196 case 'B': 197 altbootname = strdup(optarg); 198 d_flag++; 199 /* check for valid boot file now */ 200 altsize = valid_DOS_boot(altbootname, &altboot); 201 if (!altsize) { 202 (void) fprintf(stderr, gettext( 203 "%s: invalid boot loader\n"), myname); 204 exit(1); 205 } 206 break; 207 208 case 'b': 209 b_flag++; 210 vollabel = strdup(optarg); 211 break; 212 213 case 'd': 214 /* format a MS-DOS diskette */ 215 d_flag++; 216 break; 217 218 case 'D': 219 case 'L': 220 case 'l': 221 /* format a Double density 720KB (or 360KB) disk */ 222 D_flag++; 223 break; 224 225 case 'e': 226 /* eject diskette when done */ 227 e_flag++; 228 break; 229 230 case 'E': 231 /* format an 2.88MB Extended density disk */ 232 E_flag++; 233 break; 234 235 case 'f': 236 /* don't ask for confirmation */ 237 f_flag++; 238 break; 239 240 case 'H': 241 case 'h': 242 /* format a High density 1.2MB or 1.44MB disk */ 243 H_flag++; 244 break; 245 246 #if 0 247 case 'i': 248 /* interleave factor */ 249 interleave = atol(optarg); 250 if (interleave <= 0) { 251 (void) fprintf(stderr, gettext( 252 "%s: invalid interleave\n"), myname); 253 exit(1); 254 } 255 break; 256 #endif 257 258 case 'M': 259 case 'm': 260 /* format a 3.5" HD disk to 1.2MB */ 261 m_flag++; 262 break; 263 264 case 'x': 265 /* skip format, just write label */ 266 x_flag++; 267 break; 268 269 case 'q': 270 /* quiet format */ 271 q_flag++; 272 break; 273 274 case 't': 275 /* Type of DOS formatting: NEC or MS */ 276 if (strcmp(optarg, "nec") == 0) { 277 n_flag++; 278 } 279 if (strcmp(optarg, "dos") == 0) { 280 d_flag++; 281 } 282 break; 283 284 case 'U': 285 /* umount filesystem if mounted */ 286 U_flag++; 287 break; 288 289 case 'v': 290 case 'V': 291 /* verify the diskette after format */ 292 v_flag++; 293 break; 294 295 case 'Z': 296 /* for debug only, format cyl 0 only */ 297 if (!fd_debug) { 298 usage(gettext("unknown argument")); 299 /* NOTREACHED */ 300 } 301 (void) printf(gettext("\nFormat cyl Zero only\n")); 302 z_flag++; 303 break; 304 305 default: 306 usage(" "); 307 /* NOTREACHED */ 308 } 309 } 310 311 if (optind < argc -1) { 312 usage(gettext("more than one device name argument")); 313 /* NOTREACHED */ 314 } 315 if (optind == argc -1) { 316 dev_name = argv[optind]; 317 } 318 if (D_flag && H_flag) { 319 usage(gettext("switches -D, -L and -H incompatible")); 320 /* NOTREACHED */ 321 } 322 if (D_flag && E_flag) { 323 usage(gettext("switches -D, -L and -E incompatible")); 324 /* NOTREACHED */ 325 } 326 if (H_flag && E_flag) { 327 usage(gettext("switches -H and -E incompatible")); 328 /* NOTREACHED */ 329 } 330 if (n_flag && d_flag) { 331 usage(gettext("switches nec and dos incompatible")); 332 /* NOTREACHED */ 333 } 334 if (n_flag && !m_flag) { 335 usage(gettext("switch -M required for NEC-DOS")); 336 /* NOTREACHED */ 337 } 338 if (D_flag && m_flag) { 339 usage(gettext("switches -D, -L and -M incompatible")); 340 /* NOTREACHED */ 341 } 342 if (d_flag && m_flag) { 343 usage(gettext("switches -d and -M incompatible")); 344 /* NOTREACHED */ 345 } 346 347 if (dev_name == NULL) 348 dev_name = "floppy"; 349 350 if ((real_name = media_findname(dev_name)) == NULL) { 351 if ((alias_name = _media_oldaliases(dev_name)) != NULL) 352 real_name = media_findname(alias_name); 353 if (real_name == NULL) { 354 (void) fprintf(stderr, 355 gettext("No such volume (or no media in specified device): %s\n"), 356 dev_name); 357 exit(1); 358 } 359 } 360 361 /* 362 * This check is required because program runs suid root. 363 */ 364 if (access(real_name, R_OK|W_OK) < 0) { 365 perror(real_name); 366 exit(1); 367 } 368 369 /* store callers euid */ 370 371 euid = geteuid(); 372 373 /* 374 * See if the given device name is mounted. If this check isn't done 375 * before the open, the open will fail. The failed open will not 376 * indicate that the device is mounted, only that it's busy 377 */ 378 if (_dev_mounted(real_name)) { 379 if (U_flag) { 380 if (!_dev_unmount(real_name)) { 381 (void) fprintf(stderr, 382 gettext("%s: umount of %s failed\n"), 383 myname, real_name); 384 exit(1); 385 } 386 } else { 387 (void) fprintf(stderr, 388 gettext("%s: %s is mounted (use -U flag)\n"), 389 myname, real_name); 390 exit(1); 391 } 392 } 393 394 /* Set to user access permissions to open file */ 395 (void) seteuid(getuid()); 396 397 if ((fd = open(real_name, O_NDELAY | O_RDWR | O_EXCL)) == -1) { 398 if (errno == EROFS) { 399 (void) fprintf(stderr, 400 gettext("%s: \"%s\" is write protected\n"), 401 myname, real_name); 402 exit(1); 403 } 404 /* XXX ought to check for "drive not installed", etc. */ 405 (void) fprintf(stderr, gettext("%s: could not open \"%s\": "), 406 myname, real_name); 407 perror(nullstring); 408 exit(1); 409 } 410 411 /* restore effective id */ 412 (void) seteuid(euid); 413 414 if (ioctl(fd, DKIOCINFO, &dkinfo) < 0) { 415 (void) fprintf(stderr, 416 gettext("%s: DKIOCINFO failed, "), myname); 417 perror(nullstring); 418 exit(3); 419 } 420 421 /* See if there are any mounted partitions. */ 422 if (check_mount() != 0) { 423 exit(3); 424 } 425 426 /* See if the device is a PCMCIA card */ 427 if (dkinfo.dki_ctype == DKC_PCMCIA_MEM) 428 pcmcia = 1; 429 430 431 /* 432 * The fd_vtoc, bpb, and rdirsec structures will be 433 * partially filled in by format_pcmcia_card() or 434 * format_diskette(). This was done so that write_DOS_label(), 435 * write_SunOS_label(), and write_NEC_DOS_label() could be 436 * device independent. If a new device needs to be added to 437 * fdformat, a new format function like format_diskette should 438 * be added. This function should fill in fd_vtoc, bpb, and 439 * rdirsec with device dependent information. 440 */ 441 (void) memset((void *)&fd_vtoc, (char)0, sizeof (struct vtoc)); 442 (void) memset((void *)&bpb, (char)0, sizeof (struct bios_param_blk)); 443 444 if (pcmcia) 445 format_pcmcia_card(fd, real_name, &fd_vtoc, &bpb, &rdirsec); 446 else 447 format_diskette(fd, real_name, &fd_vtoc, &bpb, &rdirsec); 448 449 if (d_flag) 450 write_DOS_label(fd, altboot, altsize, altbootname, 451 vollabel, &bpb, rdirsec); 452 else if (n_flag) 453 write_NEC_DOS_label(fd, vollabel); 454 else 455 write_SunOS_label(fd, vollabel, &fd_vtoc); 456 457 if (e_flag) 458 /* eject media if possible */ 459 if (ioctl(fd, FDEJECT, 0)) { 460 (void) fprintf(stderr, 461 gettext("%s: could not eject diskette, "), myname); 462 perror(nullstring); 463 exit(3); 464 } 465 466 return (0); 467 } 468 469 /* 470 * Inputs: file descriptor for the device and the device name. 471 * Oututs: the fd_vtoc will be partially filled in with the 472 * device specific information such as partition 473 * information and ascillabel. bpb and rdirsec will 474 * also be partially filled in with device specific information 475 */ 476 void 477 format_diskette(int fd, char *real_name, struct vtoc *fd_vtoc, 478 struct bios_param_blk *bpb, int *rdirsec) 479 { 480 int transfer_rate = 1000; /* transfer rate code */ 481 int sec_size = 512; /* sector size */ 482 uchar_t gap = 0x54; /* format gap size */ 483 uchar_t *fbuf, *p; 484 char *capacity = NULL; 485 int cyl_size; 486 int i; 487 int chgd; /* for testing disk changed/present */ 488 int cyl, hd; 489 int size_of_part, size_of_dev; 490 int spt = 36; /* sectors per track */ 491 int drive_size; 492 uchar_t num_cyl = 80; /* max number of cylinders */ 493 char *nullstring = ""; 494 struct fd_char save_fdchar; /* original diskette characteristics */ 495 struct dk_allmap save_allmap; /* original diskette partition info */ 496 497 498 /* FDIOCMD ioctl command structure for formatting */ 499 /* LINTED */ 500 struct fd_cmd fcmd_fmt = { 501 FDCMD_FORMAT_TRACK, 502 0xA5, 503 0, 504 1, 505 0, 506 0 507 }; 508 509 /* FDRAW ioctl command structures for seeking and formatting */ 510 struct fd_raw fdr_seek = { 511 FDRAW_SEEK, 0, 0, 0, 0, 0, 0, 0, 0, 0, 512 3, 513 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 514 0, 515 0 516 }; 517 518 struct fd_raw fdr_form = { 519 0x4D, 0, 2, 0, 0x54, (char)0xA5, 0, 0, 0, 0, 520 6, 521 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 522 0, /* nbytes */ 523 0 /* addr */ 524 }; 525 526 527 /* 528 * restore drive to default geometry and characteristics 529 * (probably not implemented on sparc) 530 */ 531 (void) ioctl(fd, FDDEFGEOCHAR, NULL); 532 533 /* get the default partititon maps */ 534 if (ioctl(fd, DKIOCGAPART, &allmap) == -1) { 535 (void) fprintf(stderr, 536 gettext("%s: DKIOCGAPART failed, "), myname); 537 perror(nullstring); 538 exit(3); 539 } 540 541 /* Save the original default partition maps */ 542 save_allmap = allmap; 543 544 /* find out the characteristics of the default diskette */ 545 if (ioctl(fd, FDIOGCHAR, &fdchar) == -1) { 546 (void) fprintf(stderr, 547 gettext("%s: FDIOGCHAR failed, "), myname); 548 perror(nullstring); 549 exit(3); 550 } 551 552 /* Save the original characteristics of the default diskette */ 553 save_fdchar = fdchar; 554 555 /* 556 * The user may only format the entire diskette. 557 * formatting partion a or b is not allowed 558 */ 559 size_of_part = allmap.dka_map[dkinfo.dki_partition].dkl_nblk 560 * DEV_BSIZE; 561 size_of_dev = fdchar.fdc_ncyl * fdchar.fdc_nhead 562 * fdchar.fdc_secptrack * fdchar.fdc_sec_size; 563 564 if (size_of_part != size_of_dev) { 565 (void) fprintf(stderr, 566 /*CSTYLED*/ 567 gettext("%s: The entire diskette must be formatted. Invalid device name.\n"), 568 myname); 569 exit(3); 570 } 571 572 573 /* find out the geometry of the drive */ 574 if (ioctl(fd, DKIOCGGEOM, &fdgeom) == -1) { 575 (void) fprintf(stderr, 576 gettext("%s: DKIOCGGEOM failed, "), myname); 577 perror(nullstring); 578 exit(3); 579 } 580 581 #ifdef sparc 582 fdchar.fdc_medium = 3; 583 #endif 584 if (fdchar.fdc_medium == 5) 585 drive_size = 5; 586 else 587 drive_size = 3; 588 589 /* 590 * set proper density flag in case we're formating to default 591 * characteristics because no density switch was input 592 */ 593 if ((E_flag | H_flag | D_flag | m_flag) == 0) { 594 switch (fdchar.fdc_transfer_rate) { 595 case 1000: 596 /* assumes only ED uses 1.0 MB/sec */ 597 E_flag++; 598 break; 599 case 500: 600 default: 601 /* 602 * default to HD even though High density and 603 * "medium" density both use 500 KB/sec 604 */ 605 H_flag++; 606 break; 607 #ifndef sparc 608 case 250: 609 /* assumes only DD uses 250 KB/sec */ 610 D_flag++; 611 break; 612 #endif 613 } 614 } 615 616 if (H_flag) { 617 transfer_rate = 500; 618 num_cyl = 80; 619 sec_size = 512; 620 if (drive_size == 5) { 621 (void) strcpy(fd_vtoc->v_asciilabel, 622 "5.25\" floppy cyl 80 alt 0 hd 2 sec 15"); 623 spt = 15; 624 capacity = "1.2 MB"; 625 } else { 626 (void) strcpy(fd_vtoc->v_asciilabel, 627 "3.5\" floppy cyl 80 alt 0 hd 2 sec 18"); 628 spt = 18; 629 capacity = "1.44 MB"; 630 } 631 gap = 0x54; 632 } else if (D_flag) { 633 transfer_rate = 250; 634 if (drive_size == 5) { 635 (void) strcpy(fd_vtoc->v_asciilabel, 636 "5.25\" floppy cyl 40 alt 0 hd 2 sec 9"); 637 if (fdchar.fdc_transfer_rate == 500) { 638 /* 639 * formatting a 360KB DD diskette in 640 * a 1.2MB drive is not a good idea 641 */ 642 transfer_rate = 300; 643 fdchar.fdc_steps = 2; 644 } 645 num_cyl = 40; 646 gap = 0x50; 647 capacity = "360 KB"; 648 } else { 649 (void) strcpy(fd_vtoc->v_asciilabel, 650 "3.5\" floppy cyl 80 alt 0 hd 2 sec 9"); 651 num_cyl = 80; 652 gap = 0x54; 653 capacity = "720 KB"; 654 } 655 sec_size = 512; 656 spt = 9; 657 } else if (m_flag) { 658 #ifdef sparc 659 transfer_rate = 500; 660 #else 661 /* 662 * 416.67 KB/sec is the effective transfer rate of a "medium" 663 * density diskette spun at 300 rpm instead of 360 rpm 664 */ 665 transfer_rate = 417; 666 #endif 667 (void) strcpy(fd_vtoc->v_asciilabel, 668 "3.5\" floppy cyl 77 alt 0 hd 2 sec 8"); 669 num_cyl = 77; 670 sec_size = 1024; 671 spt = 8; 672 gap = 0x74; 673 capacity = "1.2 MB"; 674 } else if (E_flag) { 675 (void) strcpy(fd_vtoc->v_asciilabel, 676 "3.5\" floppy cyl 80 alt 0 hd 2 sec 36"); 677 transfer_rate = 1000; 678 num_cyl = 80; 679 sec_size = 512; 680 spt = 36; 681 gap = 0x54; 682 capacity = "2.88 MB"; 683 } 684 /* 685 * Medium density diskettes have 1024 byte blocks. The dk_map 686 * structure in dklabel.h assumes the blocks size is DEVBSIZE (512) 687 * bytes. The dkl_nblk field is in terms of DEVBSIZE byte blocks 688 * while the spt variable is in terms of the true block size on 689 * the diskette. 690 */ 691 if (allmap.dka_map[2].dkl_nblk != 692 (2 * num_cyl * spt * (m_flag ? 2 : 1))) { 693 allmap.dka_map[1].dkl_cylno = num_cyl - 1; 694 allmap.dka_map[0].dkl_nblk = 2 * (num_cyl - 1) * spt * 695 (m_flag ? 2 : 1); 696 allmap.dka_map[1].dkl_nblk = 2 * spt * (m_flag ? 2 : 1); 697 allmap.dka_map[2].dkl_nblk = 2 * num_cyl * spt * 698 (m_flag ? 2 : 1); 699 if (allmap.dka_map[3].dkl_nblk) 700 allmap.dka_map[3].dkl_nblk = 2 * (num_cyl - 1) * spt * 701 (m_flag ? 2 : 1); 702 if (allmap.dka_map[4].dkl_nblk) 703 allmap.dka_map[4].dkl_nblk = 704 2 * spt * (m_flag ? 2 : 1); 705 } 706 707 708 /* initialize the vtoc structure */ 709 fd_vtoc->v_nparts = 3; 710 711 fd_vtoc->v_part[0].p_start = 0; 712 fd_vtoc->v_part[0].p_size = ((num_cyl - 1) * 2 * spt * 713 (m_flag ? 2 : 1)); 714 fd_vtoc->v_part[1].p_start = ((num_cyl - 1) * 2 * spt * 715 (m_flag ? 2 : 1)); 716 fd_vtoc->v_part[1].p_size = 2 * spt * (m_flag ? 2 : 1); 717 718 fd_vtoc->v_part[2].p_start = 0; 719 fd_vtoc->v_part[2].p_size = num_cyl * 2 * spt * (m_flag ? 2 : 1); 720 721 /* initialize the bios parameter blockstructure */ 722 bpb->b_nfat = 2; 723 if (E_flag && drive_size == 3) { 724 bpb->b_spcl = 2; 725 *rdirsec = (ushort_t)240; 726 bpb->b_mediadescriptor = (char)0xF0; 727 bpb->b_fatsec[0] = 9; 728 bpb->b_fatsec[1] = 0; 729 } else if (H_flag) { 730 if (drive_size == 5) { 731 bpb->b_spcl = 1; 732 *rdirsec = 224; 733 bpb->b_mediadescriptor = (char)0xF9; 734 bpb->b_fatsec[0] = 7; 735 bpb->b_fatsec[1] = 0; 736 } else { 737 bpb->b_spcl = 1; 738 *rdirsec = 224; 739 bpb->b_mediadescriptor = (char)0xF0; 740 bpb->b_fatsec[0] = 9; 741 bpb->b_fatsec[1] = 0; 742 } 743 } else if (drive_size == 5) { 744 bpb->b_spcl = 2; 745 *rdirsec = 112; 746 bpb->b_mediadescriptor = (char)0xFD; 747 bpb->b_fatsec[0] = 2; 748 bpb->b_fatsec[1] = 0; 749 } else if (drive_size == 3) { 750 bpb->b_spcl = 2; 751 *rdirsec = 112; 752 bpb->b_mediadescriptor = (char)0xF9; 753 bpb->b_fatsec[0] = 3; 754 bpb->b_fatsec[1] = 0; 755 } 756 757 758 759 #ifndef sparc 760 if (num_cyl > fdchar.fdc_ncyl || spt > fdchar.fdc_secptrack || 761 transfer_rate > fdchar.fdc_transfer_rate) { 762 (void) fprintf(stderr, 763 gettext("%s: drive not capable of requested density, "), 764 myname); 765 perror(nullstring); 766 exit(3); 767 } 768 #endif 769 if (num_cyl != fdchar.fdc_ncyl || spt != fdchar.fdc_secptrack || 770 transfer_rate != fdchar.fdc_transfer_rate) { 771 /* 772 * -- CAUTION -- 773 * The SPARC fd driver is using a non-zero value in 774 * fdc_medium to indicate the 360 rpm, 77 track, 775 * 9 sectors/track, 1024 bytes/sector mode of operation 776 * (similar to an 8", DS/DD, 1.2 MB floppy). 777 * 778 * The x86 fd driver uses fdc_medium as the diameter 779 * indicator, either 3 or 5. It should not be modified. 780 */ 781 #ifdef sparc 782 fdchar.fdc_medium = m_flag ? 1 : 0; 783 #endif 784 fdchar.fdc_transfer_rate = transfer_rate; 785 fdchar.fdc_ncyl = num_cyl; 786 fdchar.fdc_sec_size = sec_size; 787 fdchar.fdc_secptrack = spt; 788 789 if (ioctl(fd, FDIOSCHAR, &fdchar) == -1) { 790 (void) fprintf(stderr, gettext( 791 "%s: FDIOSCHAR (density selection) failed, "), 792 myname); 793 794 /* restore the default characteristics */ 795 restore_default_chars(fd, save_fdchar, save_allmap); 796 perror(nullstring); 797 exit(3); 798 } 799 if (ioctl(fd, DKIOCSAPART, &allmap) == -1) { 800 (void) fprintf(stderr, 801 gettext("%s: DKIOCSAPART failed, "), 802 myname); 803 804 /* restore the default characteristics */ 805 restore_default_chars(fd, save_fdchar, save_allmap); 806 807 perror(nullstring); 808 exit(3); 809 } 810 } 811 812 if (interleave != 1 && interleave != fdgeom.dkg_intrlv) { 813 fdgeom.dkg_intrlv = interleave; 814 if (ioctl(fd, DKIOCSGEOM, &fdgeom) == -1) { 815 (void) fprintf(stderr, 816 gettext("%s: DKIOCSGEOM failed, "), myname); 817 perror(nullstring); 818 819 /* restore the default characteristics */ 820 restore_default_chars(fd, save_fdchar, save_allmap); 821 822 exit(3); 823 } 824 } 825 826 cyl_size = 2 * sec_size * spt; 827 828 if ((ibuf1 = (uchar_t *)malloc((size_t)cyl_size)) == 0 || 829 (obuf = (uchar_t *)malloc((size_t)cyl_size)) == 0) { 830 (void) fprintf(stderr, 831 gettext("%s: can't malloc verify buffer, "), 832 myname); 833 perror(nullstring); 834 /* restore the default characteristics */ 835 restore_default_chars(fd, save_fdchar, save_allmap); 836 837 exit(4); 838 } 839 (void) memset(ibuf1, (uchar_t)0xA5, cyl_size); 840 841 if (x_flag) 842 goto skipformat; 843 844 if (!(q_flag && f_flag)) 845 if (interleave != 1) 846 (void) printf(gettext( 847 "Formatting %s, %d cylinders, %d sectors per trk, interleave=%d in %s\n"), 848 capacity, num_cyl, spt, interleave, real_name); 849 else 850 (void) printf(gettext("Formatting %s in %s\n"), 851 capacity, real_name); 852 853 if (!f_flag) { 854 (void) printf( 855 gettext("Press return to start formatting floppy.")); 856 while (getchar() != '\n') 857 ; 858 } 859 /* 860 * for those systems that support this ioctl, they will 861 * return whether or not a diskette is in the drive. 862 */ 863 if (ioctl(fd, FDGETCHANGE, &chgd) == 0) { 864 if (chgd & FDGC_CURRENT) { 865 (void) fprintf(stderr, 866 gettext("%s: no diskette in drive %s\n"), 867 myname, real_name); 868 869 /* restore the default characteristics */ 870 restore_default_chars(fd, save_fdchar, save_allmap); 871 872 exit(4); 873 } 874 if (chgd & FDGC_CURWPROT) { 875 (void) fprintf(stderr, 876 gettext("%s: \"%s\" is write protected\n"), 877 myname, real_name); 878 879 /* restore the default characteristics */ 880 restore_default_chars(fd, save_fdchar, save_allmap); 881 882 exit(1); 883 } 884 } 885 886 if ((fbuf = (uchar_t *)malloc((unsigned)(4 * spt))) == 0) { 887 (void) fprintf(stderr, 888 gettext("%s: can't malloc format header buffer, "), 889 myname); 890 perror(nullstring); 891 892 /* restore the default characteristics */ 893 restore_default_chars(fd, save_fdchar, save_allmap); 894 895 exit(3); 896 } 897 /* 898 * do the format, a track at a time 899 */ 900 fcmd_fmt.fdc_blkno = 0; 901 for (cyl = 0; cyl < (z_flag ? 1 : (int)num_cyl); cyl++) { 902 #if 0 903 /* 904 * This should be the ioctl used to format the floppy. 905 * The device driver should do do the work, 906 * instead of this program mucking with a lot 907 * of low-level, device-dependent code. 908 */ 909 for (hd = 0; hd < fdchar.fdc_nhead; hd++) { 910 if (ioctl(fd, FDIOCMD, &fcmd_fmt) == -1) { 911 (void) fprintf(stderr, 912 gettext("%s: format of cyl %d head %d failed\n"), 913 myname, cyl, hd); 914 915 /* restore the default characteristics */ 916 restore_default_chars(fd, save_fdchar, 917 save_allmap); 918 exit(3); 919 } 920 fcmd_fmt.fdc_blkno += spt; 921 } 922 #else 923 /* 924 * This is not the optimal ioctl to format the floppy. 925 * The device driver should do do the work, 926 * instead of this program mucking with a lot 927 * of low-level, device-dependent code. 928 */ 929 fdr_seek.fdr_cmd[2] = cyl; 930 if (ioctl(fd, FDRAW, &fdr_seek) == -1) { 931 (void) fprintf(stderr, 932 gettext("%s: seek to cyl %d failed\n"), 933 myname, cyl); 934 935 /* restore the default characteristics */ 936 restore_default_chars(fd, save_fdchar, save_allmap); 937 938 exit(3); 939 } 940 /* 941 * Assume that the fd driver has issued a SENSE_INT 942 * command to complete the seek operation. 943 */ 944 for (hd = 0; hd < fdchar.fdc_nhead; hd++) { 945 p = (uchar_t *)fbuf; 946 for (i = 1; i <= spt; i++) { 947 *p++ = cyl; 948 *p++ = hd; 949 *p++ = i; /* sector # */ 950 *p++ = (sec_size == 1024) ? 3 : 2; 951 } 952 /* 953 * ASSUME the fd driver is going to set drive-select 954 * bits in the second command byte 955 */ 956 fdr_form.fdr_cmd[1] = hd << 2; 957 fdr_form.fdr_cmd[2] = (sec_size == 1024) ? 3 : 2; 958 fdr_form.fdr_cmd[3] = spt; 959 fdr_form.fdr_cmd[4] = gap; 960 fdr_form.fdr_nbytes = 4 * spt; 961 fdr_form.fdr_addr = (char *)fbuf; 962 963 if (ioctl(fd, FDRAW, &fdr_form) == -1) { 964 965 966 (void) fprintf(stderr, gettext( 967 "%s: format of cyl %d head %d failed\n"), 968 myname, cyl, hd); 969 970 /* restore the default characteristics */ 971 restore_default_chars(fd, save_fdchar, 972 save_allmap); 973 974 exit(3); 975 } 976 if (fdr_form.fdr_result[0] & 0xC0) { 977 if (fdr_form.fdr_result[1] & 0x02) { 978 (void) fprintf(stderr, gettext( 979 /*CSTYLED*/ 980 "%s: diskette is write protected\n"), 981 myname); 982 983 /* 984 * restore the default 985 * characteristics 986 */ 987 restore_default_chars(fd, save_fdchar, 988 save_allmap); 989 990 exit(3); 991 } 992 (void) fprintf(stderr, gettext( 993 "%s: format of cyl %d head %d failed\n"), 994 myname, cyl, hd); 995 996 /* restore the default characteristics */ 997 restore_default_chars(fd, save_fdchar, 998 save_allmap); 999 1000 exit(3); 1001 } 1002 1003 } 1004 #endif 1005 1006 /* 1007 * do a quick verify 1008 */ 1009 if (!v_flag) { 1010 if (lseek(fd, cyl * cyl_size, 0) != cyl * cyl_size) { 1011 (void) fprintf(stderr, 1012 gettext("%s: bad seek to format verify, "), 1013 myname); 1014 perror(nullstring); 1015 /* restore the default characteristics */ 1016 restore_default_chars(fd, save_fdchar, 1017 save_allmap); 1018 1019 exit(3); 1020 } 1021 if (read(fd, obuf, cyl_size) == cyl_size) { 1022 /* write some progress msg */ 1023 /* when each cylinder is done. */ 1024 if (!q_flag) 1025 (void) printf("."); 1026 } else { 1027 if (!q_flag) 1028 (void) printf(gettext("e\n")); 1029 (void) fprintf(stderr, gettext( 1030 "%s: can't read format data, "), myname); 1031 perror(nullstring); 1032 /* restore the default characteristics */ 1033 restore_default_chars(fd, save_fdchar, 1034 save_allmap); 1035 1036 exit(3); 1037 } 1038 } else 1039 if (!q_flag) 1040 (void) printf("."); 1041 if (!q_flag) 1042 (void) fflush(stdout); 1043 } 1044 if (!q_flag) 1045 (void) printf("\n"); 1046 skipformat: 1047 if (v_flag) { 1048 /* 1049 * do a write & read verify of the entire diskette 1050 */ 1051 if (!q_flag && x_flag) 1052 (void) printf(gettext("Verifying %s in %s\n"), 1053 capacity, real_name); 1054 1055 for (cyl = 0; cyl < (int)num_cyl; cyl++) { 1056 1057 int val; 1058 if ((val = verify(fd, 2 * spt * cyl, cyl_size)) != 0) { 1059 perror(nullstring); 1060 1061 /* restore the default characteristics */ 1062 restore_default_chars(fd, save_fdchar, 1063 save_allmap); 1064 1065 exit(val); 1066 1067 } 1068 /* write some progress msg as */ 1069 /* each cylinder is done. */ 1070 if (!q_flag) 1071 (void) printf(gettext("v")); 1072 (void) fflush(stdout); 1073 } 1074 if (!q_flag) 1075 (void) printf("\n"); 1076 } 1077 1078 if (lseek(fd, (off_t)0, 0) != 0) { 1079 (void) fprintf(stderr, gettext("%s: seek to blk 0 failed, "), 1080 myname); 1081 perror(nullstring); 1082 /* restore the default characteristics */ 1083 restore_default_chars(fd, save_fdchar, save_allmap); 1084 1085 exit(3); 1086 } 1087 1088 } 1089 1090 1091 /* 1092 * Restore the default characteristics of the floppy diskette. 1093 * Fdformat changes the characteristics in the process of formatting. 1094 * If fdformat fails while in the process of doing the format, fdformat 1095 * should clean up after itself and reset the driver back to the original 1096 * state. 1097 */ 1098 1099 static void 1100 restore_default_chars(int fd, 1101 struct fd_char save_fdchar, 1102 struct dk_allmap save_allmap) 1103 { 1104 1105 1106 /* 1107 * When this function is called, fdformat is failing anyways, 1108 * so the errors are not processed. 1109 */ 1110 1111 (void) ioctl(fd, FDIOSCHAR, &save_fdchar); 1112 1113 (void) ioctl(fd, DKIOCSAPART, &save_allmap); 1114 1115 /* 1116 * Before looking at the diskette's characteristics, format_diskette() 1117 * sets the x86 floppy driver to the default characteristics. 1118 * restore drive to default geometry and 1119 * characteristics. This ioctl isn't implemented on 1120 * sparc. 1121 */ 1122 (void) ioctl(fd, FDDEFGEOCHAR, NULL); 1123 1124 } 1125 1126 /* 1127 * Inputs: file descriptor for the device and the device name. 1128 * Oututs: the fd_vtoc will be partially filled in with the 1129 * device specific information such as partition 1130 * information and ascillabel. The bpb structure and rdirsec will also be 1131 * partially filled in with device specific information. 1132 */ 1133 void 1134 format_pcmcia_card(int fd, char *real_name, struct vtoc *fd_vtoc, 1135 struct bios_param_blk *bpb, int *rdirsec) 1136 { 1137 int sec_size; /* sector size */ 1138 int i, j; 1139 char wrpat; 1140 char wrbuf[512]; 1141 char rdbuf[512]; 1142 enum dkio_state state = DKIO_NONE; 1143 int card_size; /* PCMCIA memory card size */ 1144 ulong_t max_cyl; /* max number of cylinders */ 1145 int sec_fat; 1146 1147 /* 1148 * Using DKIOCSTATE ioctl() 1149 * to replace FDGETCHANGE ioctl() 1150 * start out with state=DKIO_NONE 1151 */ 1152 if (ioctl(fd, DKIOCSTATE, &state) < 0) { 1153 (void) fprintf(stderr, 1154 gettext("%s: DKIOCSTATE failed, "), 1155 myname); 1156 perror(""); 1157 exit(3); 1158 } 1159 1160 if (state != DKIO_INSERTED) { 1161 (void) fprintf(stderr, 1162 gettext("%s: no media in %s\n"), 1163 myname, real_name); 1164 exit(4); 1165 } 1166 1167 1168 /* initialize the asciilabel */ 1169 (void) strcpy(fd_vtoc->v_asciilabel, "PCMCIA Memory Card"); 1170 1171 /* Get card cyl/head/secptrack info */ 1172 if (ioctl(fd, DKIOCGGEOM, &dkg) == -1) { 1173 /* 1174 * Card doesn't have a CIS. So, ask driver to probe 1175 * card size info 1176 */ 1177 if (ioctl(fd, PCRAM_PROBESIZE, &dkg) == -1) { 1178 (void) fprintf(stderr, 1179 gettext("%s: Unable to get card size information"), 1180 myname); 1181 perror(""); 1182 exit(3); 1183 } 1184 } 1185 1186 /* PCMCIA memory default sector size */ 1187 sec_size = DEV_BSIZE; 1188 1189 fdchar.fdc_sec_size = sec_size; 1190 fdchar.fdc_ncyl = dkg.dkg_ncyl; 1191 fdchar.fdc_nhead = dkg.dkg_nhead; 1192 fdchar.fdc_secptrack = dkg.dkg_nsect; 1193 1194 max_cyl = fdchar.fdc_ncyl; 1195 1196 /* Initialize the vtoc information */ 1197 fd_vtoc->v_part[2].p_start = 0; 1198 fd_vtoc->v_part[2].p_size = max_cyl * fdchar.fdc_nhead 1199 * fdchar.fdc_secptrack; 1200 fd_vtoc->v_nparts = 1; 1201 1202 card_size = fdchar.fdc_ncyl * fdchar.fdc_nhead * 1203 fdchar.fdc_secptrack * fdchar.fdc_sec_size; 1204 1205 /* Initialize the bios parameter block information */ 1206 bpb->b_nfat = 1; 1207 if (card_size < 1048576) { 1208 bpb->b_spcl = 2; 1209 *rdirsec = 112; 1210 } else { 1211 bpb->b_spcl = 1; 1212 *rdirsec = 224; 1213 } 1214 bpb->b_mediadescriptor = (char)0xf8; /* fixed disk */ 1215 1216 /* 1217 * card_size sec_fat 1218 * 524288 3 1219 * 1048576 6 1220 * 2097152 12 1221 */ 1222 1223 sec_fat = (card_size * 3) / 524288; 1224 bpb->b_fatsec[0] = sec_fat % 0x100; 1225 bpb->b_fatsec[1] = sec_fat / 0x100; 1226 1227 1228 (void) printf(gettext("Formatting %d bytes in %s\n"), 1229 card_size, real_name); 1230 1231 if (!f_flag && !x_flag) { 1232 (void) printf(gettext( 1233 /*CSTYLED*/ 1234 "Press return to start formatting PCMCIA memory card.")); 1235 while (getchar() != '\n') 1236 ; 1237 } 1238 1239 1240 /* 1241 * Skip the format, only install SunOS label or DOS file system. 1242 */ 1243 if (x_flag) 1244 goto skipformat; 1245 1246 /* 1247 * First try to format only 512 bytes with four different 1248 * patterns. 1249 */ 1250 for (i = 0; i < 4; ++i) { 1251 switch (i) { 1252 1253 case 0: 1254 wrpat = (uchar_t)PATTERN_1; 1255 break; 1256 case 1: 1257 wrpat = (uchar_t)PATTERN_2; 1258 break; 1259 case 2: 1260 wrpat = (uchar_t)PATTERN_3; 1261 break; 1262 case 3: 1263 wrpat = PATTERN_4; 1264 break; 1265 } 1266 1267 if (lseek(fd, (off_t)0, 0) != 0) { 1268 (void) fprintf(stderr, 1269 gettext("%s: seek to blk 0 failed, "), 1270 myname); 1271 perror(""); 1272 exit(3); 1273 } 1274 1275 (void) memset(wrbuf, wrpat, 512); 1276 1277 if (write(fd, &wrbuf[0], 512) != 512) { 1278 (void) fprintf(stderr, 1279 /*CSTYLED*/ 1280 gettext("%s: Format Write failed, "), myname); 1281 perror(""); 1282 exit(3); 1283 } 1284 1285 if (lseek(fd, (off_t)0, 0) != 0) { 1286 (void) fprintf(stderr, 1287 gettext("%s: seek to blk 0 failed, "), 1288 myname); 1289 perror(""); 1290 exit(3); 1291 } 1292 1293 if (read(fd, &rdbuf[0], 512) != 512) { 1294 (void) fprintf(stderr, 1295 /*CSTYLED*/ 1296 gettext("%s: Format Read failed, "), myname); 1297 perror(""); 1298 exit(3); 1299 } 1300 1301 if (memcmp(wrbuf, rdbuf, 512) != 0) { 1302 (void) fprintf(stderr, 1303 /*CSTYLED*/ 1304 gettext("%s: Format Compare Error, "), myname); 1305 perror(""); 1306 exit(3); 1307 } 1308 } 1309 /* 1310 * Then format the whole memory card with patterns 1311 * 0xff and 0x00 to erase the card. 1312 */ 1313 for (i = 0; i < 2; ++i) { 1314 1315 if (i == 0) { 1316 wrpat = (uchar_t)PATTERN_3; 1317 } else { 1318 wrpat = PATTERN_4; 1319 } 1320 1321 if (lseek(fd, (off_t)0, 0) != 0) { 1322 (void) fprintf(stderr, 1323 gettext("%s: seek to blk 0 failed, "), 1324 myname); 1325 perror(""); 1326 exit(3); 1327 } 1328 1329 (void) memset(wrbuf, wrpat, 512); 1330 1331 for (j = 0; j < (card_size/512); ++j) { 1332 if (write(fd, &wrbuf[0], 512) != 512) { 1333 (void) fprintf(stderr, 1334 /*CSTYLED*/ 1335 gettext("%s: Format Write failed, "), myname); 1336 perror(""); 1337 exit(3); 1338 } 1339 /* 1340 * write some progress msg when each 1341 * 512KB block is done. 1342 */ 1343 if (((j%1024) == 0) && (!q_flag)) { 1344 (void) printf("."); 1345 (void) fflush(stdout); 1346 } 1347 } 1348 /* 1349 * do a verify 1350 */ 1351 1352 if (lseek(fd, (off_t)0, 0) != 0) { 1353 (void) fprintf(stderr, 1354 gettext("%s: seek to blk 0 failed, "), 1355 myname); 1356 perror(""); 1357 exit(3); 1358 } 1359 1360 for (j = 0; j < (card_size/512); ++j) { 1361 if (read(fd, &rdbuf[0], 512) != 512) { 1362 (void) fprintf(stderr, 1363 /*CSTYLED*/ 1364 gettext("%s: Format Read failed, "), myname); 1365 perror(""); 1366 exit(3); 1367 } 1368 if (memcmp(wrbuf, rdbuf, 512) != 0) { 1369 (void) fprintf(stderr, 1370 /*CSTYLED*/ 1371 gettext("%s: Format Compare Error, "), myname); 1372 perror(""); 1373 exit(3); 1374 } 1375 /*CSTYLED*/ 1376 /* write some progress msg when each 512KB block is done. */ 1377 if ((j%1024) == 0) { 1378 if (!q_flag) { 1379 (void) printf("."); 1380 (void) fflush(stdout); 1381 } 1382 } 1383 } 1384 } 1385 if (!q_flag) 1386 (void) printf("\n"); 1387 1388 skipformat: 1389 if (lseek(fd, (off_t)0, 0) != 0) { 1390 (void) fprintf(stderr, gettext("%s: seek to blk 0 failed, "), 1391 myname); 1392 perror(""); 1393 exit(3); 1394 } 1395 } 1396 1397 1398 1399 /* 1400 * See if any partitions on the device are mounted. Return 1 if a partition is 1401 * mounted. Return 0 otherwise. 1402 */ 1403 static int 1404 check_mount() 1405 { 1406 FILE *fp = NULL; 1407 int mfd; 1408 struct dk_cinfo dkinfo_tmp; 1409 struct mnttab mnt_record; 1410 struct mnttab *mp = &mnt_record; 1411 struct stat stbuf; 1412 char raw_device[MAXPATHLEN]; 1413 int found = 0; 1414 1415 if ((fp = fopen(MNTTAB, "r")) == NULL) { 1416 perror(MNTTAB); 1417 exit(3); 1418 } 1419 1420 while (getmntent(fp, mp) == 0) { 1421 if (strstr(mp->mnt_special, "/dev/fd") == NULL && 1422 strstr(mp->mnt_special, "/dev/disket") == NULL && 1423 strstr(mp->mnt_special, "/dev/c") == NULL) { 1424 continue; 1425 } 1426 1427 (void) strcpy(raw_device, "/dev/r"); 1428 (void) strcat(raw_device, mp->mnt_special + strlen("/dev/")); 1429 1430 /* 1431 * Attempt to open the device. If it fails, skip it. 1432 */ 1433 if ((mfd = open(raw_device, O_RDWR | O_NDELAY)) < 0) { 1434 continue; 1435 } 1436 1437 /* 1438 * Must be a character device 1439 */ 1440 if (fstat(mfd, &stbuf) == -1 || !S_ISCHR(stbuf.st_mode)) { 1441 (void) close(mfd); 1442 continue; 1443 } 1444 /* 1445 * Attempt to read the configuration info on the disk. 1446 */ 1447 if (ioctl(mfd, DKIOCINFO, &dkinfo_tmp) < 0) { 1448 (void) close(mfd); 1449 continue; 1450 } 1451 /* 1452 * Finished with the opened device 1453 */ 1454 (void) close(mfd); 1455 1456 /* 1457 * If it's not the disk we're interested in, it doesn't apply. 1458 */ 1459 if (dkinfo.dki_ctype != dkinfo_tmp.dki_ctype || 1460 dkinfo.dki_cnum != dkinfo_tmp.dki_cnum || 1461 dkinfo.dki_unit != dkinfo_tmp.dki_unit) { 1462 continue; 1463 } 1464 /* 1465 * It's a mount on the disk we're checking. If we are 1466 * checking whole disk, then we found trouble. We can 1467 * quit searching. 1468 */ 1469 1470 if (U_flag) { 1471 if (!_dev_unmount(mp->mnt_special)) { 1472 (void) fprintf(stderr, 1473 gettext("%s: umount of %s failed\n"), 1474 myname, mp->mnt_special); 1475 found = 1; 1476 } 1477 } else { 1478 (void) fprintf(stderr, 1479 gettext("%s: %s is mounted (use -U flag)\n"), 1480 myname, mp->mnt_special); 1481 found = 1; 1482 } 1483 } 1484 return (found); 1485 } 1486 1487 static void 1488 usage(char *str) 1489 { 1490 char *real_name, *alias_name; 1491 1492 if ((real_name = media_findname("floppy")) == NULL) { 1493 if ((alias_name = _media_oldaliases("floppy")) != NULL) 1494 real_name = media_findname(alias_name); 1495 } 1496 1497 if (str[0] != ' ') 1498 (void) printf("%s: %s\n", myname, str); 1499 (void) printf(gettext( 1500 /*CSTYLED*/ 1501 "\n usage: %s [-dDeEfHlLmMqUvx] [-b label] [-B file] [-t dostype] [devname]\n"), 1502 myname); 1503 1504 (void) printf(gettext( 1505 /*CSTYLED*/ 1506 " -b label install \"label\" on media\n")); 1507 (void) printf(gettext( 1508 " -B file install special boot loader on MS-DOS media\n")); 1509 (void) printf(gettext( 1510 /*CSTYLED*/ 1511 " -d format MS-DOS media\n")); 1512 (void) printf(gettext( 1513 /*CSTYLED*/ 1514 " -D format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n")); 1515 (void) printf(gettext( 1516 " -e eject the media when done\n")); 1517 /*CSTYLED*/ 1518 (void) printf(gettext( 1519 /*CSTYLED*/ 1520 " -E format 2.88MB (3.5\") Extended-density diskette\n")); 1521 (void) printf(gettext( 1522 " -f \"force\" - don't wait for confirmation\n")); 1523 (void) printf(gettext( 1524 /*CSTYLED*/ 1525 " -H format 1.44MB (3.5\") or 1.2MB (5.25\") High-density diskette\n")); 1526 (void) printf(gettext( 1527 /*CSTYLED*/ 1528 " -l format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n")); 1529 (void) printf(gettext( 1530 /*CSTYLED*/ 1531 " -L format 720KB (3.5\") or 360KB (5.25\") Double-density diskette\n")); 1532 (void) printf(gettext( 1533 " -m format 1.2MB (3.5\") Medium-density diskette\n")); 1534 (void) printf(gettext( 1535 " -M format 1.2MB (3.5\") Medium-density diskette\n")); 1536 (void) printf(gettext( 1537 " -q quiet\n")); 1538 (void) printf(gettext( 1539 /*CSTYLED*/ 1540 " -t dos format MS-DOS media (same as -d)\n")); 1541 (void) printf(gettext( 1542 " -t nec format NEC-DOS media (with -M only)\n")); 1543 (void) printf(gettext( 1544 /*CSTYLED*/ 1545 " -U unmount media if it's mounted\n")); 1546 (void) printf(gettext( 1547 " -v verify each block of the media\n")); 1548 (void) printf(gettext( 1549 " -x skip the format, only install SunOS or DOS label\n")); 1550 1551 (void) printf(gettext( 1552 " devname defaults to '%s'\n"), 1553 real_name ? real_name : gettext("no available default device")); 1554 1555 exit(1); 1556 1557 } 1558 1559 1560 static int 1561 verify(int fd, int blk, int len) 1562 { 1563 off_t off; 1564 char *nullstring = ""; 1565 1566 off = (off_t)(blk * (m_flag ? 1024 : 512)); 1567 1568 if (lseek(fd, off, 0) != off) { 1569 if (!q_flag) 1570 (void) printf(gettext("e\n")); 1571 (void) fprintf(stderr, 1572 gettext("%s: can't seek to write verify, "), myname); 1573 perror(nullstring); 1574 return (4); 1575 } 1576 if (write(fd, ibuf1, len) != len) { 1577 if (!q_flag) 1578 (void) printf(gettext("e\n")); 1579 if (blk == 0) 1580 (void) fprintf(stderr, 1581 gettext("%s: check diskette density, "), 1582 myname); 1583 else 1584 (void) fprintf(stderr, 1585 gettext("%s: can't write verify data, "), 1586 myname); 1587 perror(nullstring); 1588 return (4); 1589 } 1590 1591 if (lseek(fd, off, 0) != off) { 1592 if (!q_flag) 1593 (void) printf(gettext("e\n")); 1594 (void) fprintf(stderr, 1595 gettext("%s: bad seek to read verify, "), 1596 myname); 1597 perror(nullstring); 1598 return (4); 1599 } 1600 if (read(fd, obuf, len) != len) { 1601 if (!q_flag) 1602 (void) printf(gettext("e\n")); 1603 (void) fprintf(stderr, 1604 gettext("%s: can't read verify data, "), myname); 1605 perror(nullstring); 1606 return (4); 1607 } 1608 if (memcmp(ibuf1, obuf, len)) { 1609 if (!q_flag) 1610 (void) printf(gettext("e\n")); 1611 (void) fprintf(stderr, gettext("%s: verify data failure\n"), 1612 myname); 1613 return (4); 1614 } 1615 return (0); 1616 } 1617 1618 /* 1619 * write a SunOS label 1620 * NOTE: this function assumes fd_vtoc has been filled in with the 1621 * device specific information such as partition information 1622 * and the asciilabel 1623 */ 1624 static void 1625 write_SunOS_label(int fd, char *volname, struct vtoc *fd_vtoc) 1626 { 1627 char *nullstring = ""; 1628 1629 fd_vtoc->v_sanity = VTOC_SANE; 1630 1631 /* 1632 * The label structure is set up for DEV_BSIZE (512 byte) blocks, 1633 * even though a medium density diskette has 1024 byte blocks 1634 * See dklabel.h for more details. 1635 */ 1636 fd_vtoc->v_sectorsz = DEV_BSIZE; 1637 1638 (void) strncpy(fd_vtoc->v_volume, volname, sizeof (fd_vtoc->v_volume)); 1639 1640 /* let the fd driver finish constructing the label and writing it */ 1641 if (ioctl(fd, DKIOCSVTOC, fd_vtoc) == -1) { 1642 (void) fprintf(stderr, 1643 gettext("%s: write of SunOS label failed, "), myname); 1644 perror(nullstring); 1645 exit(3); 1646 } 1647 1648 } 1649 1650 1651 /* 1652 * MS-DOS Disk layout: 1653 * 1654 * --------------------- 1655 * | Boot sector | 1656 * |-------------------| 1657 * | Reserved area | 1658 * |-------------------| 1659 * | FAT #1 | 1660 * |-------------------| 1661 * | FAT #2 | 1662 * |-------------------| 1663 * | Root directory | 1664 * |-------------------| 1665 * | | 1666 * | File area | 1667 * |___________________| 1668 */ 1669 1670 /* 1671 * The following is a copy of MS-DOS 3.3 boot block. 1672 * It consists of the BIOS parameter block, and a disk 1673 * bootstrap program. 1674 * 1675 * The BIOS parameter block contains the right values 1676 * for the 3.5" high-density 1.44MB floppy format. 1677 * 1678 */ 1679 static uchar_t bootsec[512] = { 1680 0xeb, 0x34, 0x90, /* 8086 short jump + displacement + NOP */ 1681 'M', 'S', 'D', 'O', 'S', '3', '.', '3', /* OEM name & version */ 1682 0, 2, 1, 1, 0, /* Start of BIOS parameter block */ 1683 2, 224, 0, 0x40, 0xb, 0xf0, 9, 0, 1684 18, 0, 2, 0, 0, 0, /* End of BIOS parameter block */ 1685 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 1686 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 1687 0x0, 0x0, 0x0, 0x0, 1688 0x1, 0x0, 0xfa, 0x33, /* 0x34, start of the bootstrap. */ 1689 0xc0, 0x8e, 0xd0, 0xbc, 0x0, 0x7c, 0x16, 0x7, 1690 0xbb, 0x78, 0x0, 0x36, 0xc5, 0x37, 0x1e, 0x56, 1691 0x16, 0x53, 0xbf, 0x2b, 0x7c, 0xb9, 0xb, 0x0, 1692 0xfc, 0xac, 0x26, 0x80, 0x3d, 0x0, 0x74, 0x3, 1693 0x26, 0x8a, 0x5, 0xaa, 0x8a, 0xc4, 0xe2, 0xf1, 1694 0x6, 0x1f, 0x89, 0x47, 0x2, 0xc7, 0x7, 0x2b, 1695 0x7c, 0xfb, 0xcd, 0x13, 0x72, 0x67, 0xa0, 0x10, 1696 0x7c, 0x98, 0xf7, 0x26, 0x16, 0x7c, 0x3, 0x6, 1697 0x1c, 0x7c, 0x3, 0x6, 0xe, 0x7c, 0xa3, 0x3f, 1698 0x7c, 0xa3, 0x37, 0x7c, 0xb8, 0x20, 0x0, 0xf7, 1699 0x26, 0x11, 0x7c, 0x8b, 0x1e, 0xb, 0x7c, 0x3, 1700 0xc3, 0x48, 0xf7, 0xf3, 0x1, 0x6, 0x37, 0x7c, 1701 0xbb, 0x0, 0x5, 0xa1, 0x3f, 0x7c, 0xe8, 0x9f, 1702 0x0, 0xb8, 0x1, 0x2, 0xe8, 0xb3, 0x0, 0x72, 1703 0x19, 0x8b, 0xfb, 0xb9, 0xb, 0x0, 0xbe, 0xd6, 1704 0x7d, 0xf3, 0xa6, 0x75, 0xd, 0x8d, 0x7f, 0x20, 1705 0xbe, 0xe1, 0x7d, 0xb9, 0xb, 0x0, 0xf3, 0xa6, 1706 0x74, 0x18, 0xbe, 0x77, 0x7d, 0xe8, 0x6a, 0x0, 1707 0x32, 0xe4, 0xcd, 0x16, 0x5e, 0x1f, 0x8f, 0x4, 1708 0x8f, 0x44, 0x2, 0xcd, 0x19, 0xbe, 0xc0, 0x7d, 1709 0xeb, 0xeb, 0xa1, 0x1c, 0x5, 0x33, 0xd2, 0xf7, 1710 0x36, 0xb, 0x7c, 0xfe, 0xc0, 0xa2, 0x3c, 0x7c, 1711 0xa1, 0x37, 0x7c, 0xa3, 0x3d, 0x7c, 0xbb, 0x0, 1712 0x7, 0xa1, 0x37, 0x7c, 0xe8, 0x49, 0x0, 0xa1, 1713 0x18, 0x7c, 0x2a, 0x6, 0x3b, 0x7c, 0x40, 0x38, 1714 0x6, 0x3c, 0x7c, 0x73, 0x3, 0xa0, 0x3c, 0x7c, 1715 0x50, 0xe8, 0x4e, 0x0, 0x58, 0x72, 0xc6, 0x28, 1716 0x6, 0x3c, 0x7c, 0x74, 0xc, 0x1, 0x6, 0x37, 1717 0x7c, 0xf7, 0x26, 0xb, 0x7c, 0x3, 0xd8, 0xeb, 1718 0xd0, 0x8a, 0x2e, 0x15, 0x7c, 0x8a, 0x16, 0xfd, 1719 0x7d, 0x8b, 0x1e, 0x3d, 0x7c, 0xea, 0x0, 0x0, 1720 0x70, 0x0, 0xac, 0xa, 0xc0, 0x74, 0x22, 0xb4, 1721 0xe, 0xbb, 0x7, 0x0, 0xcd, 0x10, 0xeb, 0xf2, 1722 0x33, 0xd2, 0xf7, 0x36, 0x18, 0x7c, 0xfe, 0xc2, 1723 0x88, 0x16, 0x3b, 0x7c, 0x33, 0xd2, 0xf7, 0x36, 1724 0x1a, 0x7c, 0x88, 0x16, 0x2a, 0x7c, 0xa3, 0x39, 1725 0x7c, 0xc3, 0xb4, 0x2, 0x8b, 0x16, 0x39, 0x7c, 1726 0xb1, 0x6, 0xd2, 0xe6, 0xa, 0x36, 0x3b, 0x7c, 1727 0x8b, 0xca, 0x86, 0xe9, 0x8a, 0x16, 0xfd, 0x7d, 1728 0x8a, 0x36, 0x2a, 0x7c, 0xcd, 0x13, 0xc3, '\r', 1729 '\n', 'N', 'o', 'n', '-', 'S', 'y', 's', 1730 't', 'e', 'm', ' ', 'd', 'i', 's', 'k', 1731 ' ', 'o', 'r', ' ', 'd', 'i', 's', 'k', 1732 ' ', 'e', 'r', 'r', 'o', 'r', '\r', '\n', 1733 'R', 'e', 'p', 'l', 'a', 'c', 'e', ' ', 1734 'a', 'n', 'd', ' ', 's', 't', 'r', 'i', 1735 'k', 'e', ' ', 'a', 'n', 'y', ' ', 'k', 1736 'e', 'y', ' ', 'w', 'h', 'e', 'n', ' ', 1737 'r', 'e', 'a', 'd', 'y', '\r', '\n', '\0', 1738 '\r', '\n', 'D', 'i', 's', 'k', ' ', 'B', 1739 'o', 'o', 't', ' ', 'f', 'a', 'i', 'l', 1740 'u', 'r', 'e', '\r', '\n', '\0', 'I', 'O', 1741 ' ', ' ', ' ', ' ', ' ', ' ', 'S', 'Y', 1742 'S', 'M', 'S', 'D', 'O', 'S', ' ', ' ', 1743 ' ', 'S', 'Y', 'S', '\0', 0, 0, 0, 1744 0, 0, 0, 0, 0, 0, 0, 0, 0, 1745 0, 0, 0, 0, 0, 0x55, 0xaa 1746 }; 1747 1748 static int 1749 valid_DOS_boot(char *bootfile, uchar_t **bootloadp) 1750 { 1751 struct stat status; 1752 size_t sizebootldr; 1753 uchar_t *bootloader; 1754 int bfd; 1755 int boot_size = 0; 1756 int err; 1757 char *nullstring = ""; 1758 1759 if (err = stat(bootfile, &status)) { 1760 (void) fprintf(stderr, gettext("%s: \"%s\" stat error %d\n"), 1761 myname, bootfile, err); 1762 return (0); 1763 } 1764 if ((boot_size = status.st_size) < 512) { 1765 (void) fprintf(stderr, 1766 gettext("%s: short boot sector"), myname); 1767 perror(nullstring); 1768 return (0); 1769 } 1770 sizebootldr = (boot_size + 511) / 512 * 512; 1771 if ((bootloader = (uchar_t *)malloc((size_t)sizebootldr)) == NULL) { 1772 (void) fprintf(stderr, gettext("%s: malloc error\n"), 1773 myname); 1774 return (0); 1775 } 1776 1777 /* switch to user to access the boot file */ 1778 (void) seteuid(getuid()); 1779 1780 if ((bfd = open(bootfile, O_RDONLY)) == -1) { 1781 (void) fprintf(stderr, gettext("%s: could not open \"%s\": "), 1782 myname, bootfile); 1783 perror(nullstring); 1784 return (0); 1785 } 1786 1787 /* restore effective id */ 1788 (void) seteuid(euid); 1789 1790 if (read(bfd, bootloader, boot_size) != boot_size) { 1791 (void) fprintf(stderr, 1792 gettext("%s: read of MS-DOS boot file failed, "), myname); 1793 perror(nullstring); 1794 (void) close(bfd); 1795 return (0); 1796 } 1797 1798 if (!((*bootloader == 0xE9 || 1799 (*bootloader == 0xEB && *(bootloader + 2) == 0x90)) && 1800 *(bootloader + 510) == 0x55 && 1801 *(bootloader + 511) == 0xAA)) { 1802 (void) fprintf(stderr, 1803 gettext("%s: invalid MS-DOS boot loader image\n"), myname); 1804 boot_size = 0; 1805 } 1806 1807 (void) close(bfd); 1808 *bootloadp = bootloader; 1809 return (boot_size); 1810 } 1811 1812 1813 static void 1814 write_DOS_label(int fd, uchar_t *bootloadr, int bootlen, char *altbootname, 1815 char *doslabel, struct bios_param_blk *bpb, int rdirsec) 1816 { 1817 int i, j; 1818 int bootclen; 1819 size_t fat_bsize; 1820 ushort_t totalsec; 1821 uchar_t *fat_rdir; 1822 uchar_t *fatptr; 1823 char *nullstring = ""; 1824 1825 if (bootlen < 512 || !bootloadr) { 1826 /* use default boot loader routine */ 1827 bootloadr = bootsec; 1828 bootlen = 512; 1829 } else 1830 (void) printf 1831 (gettext("%s: using \"%s\" for MS-DOS boot loader\n"), 1832 myname, altbootname); 1833 if (bootlen % 512 > 0) 1834 bootlen = (bootlen + 511) / 512 * 512; 1835 1836 bpb->b_bps[0] = getlobyte(512); 1837 bpb->b_bps[1] = gethibyte(512); 1838 /* MS-DOS 5.0 supports only 1 reserved sector :-( */ 1839 bpb->b_res_sec[0] = 1; 1840 bpb->b_res_sec[1] = 0; 1841 1842 totalsec = fdchar.fdc_ncyl * fdchar.fdc_nhead * fdchar.fdc_secptrack; 1843 bpb->b_totalsec[0] = getlobyte(totalsec); 1844 bpb->b_totalsec[1] = gethibyte(totalsec); 1845 bpb->b_spt[0] = fdchar.fdc_secptrack; 1846 bpb->b_spt[1] = 0; 1847 bpb->b_nhead[0] = fdchar.fdc_nhead; 1848 bpb->b_nhead[1] = 0; 1849 bpb->b_hiddensec[0] = 0; 1850 bpb->b_hiddensec[1] = 0; 1851 1852 bpb->b_rdirents[0] = getlobyte(rdirsec); 1853 bpb->b_rdirents[1] = gethibyte(rdirsec); 1854 1855 (void) memcpy((char *)(bootloadr + 0x0B), (char *)bpb, 1856 sizeof (struct bios_param_blk)); 1857 1858 if (write(fd, bootloadr, 512) != 512) { 1859 (void) fprintf(stderr, 1860 gettext("%s: write of MS-DOS boot sector failed"), myname); 1861 perror(nullstring); 1862 exit(3); 1863 } 1864 bootloadr += 512; 1865 bootlen -= 512; 1866 1867 fat_bsize = 512 * bpb->b_fatsec[0]; 1868 fat_rdir = (uchar_t *)malloc(fat_bsize); 1869 (void) memset(fat_rdir, (char)0, fat_bsize); 1870 1871 *fat_rdir = bpb->b_mediadescriptor; 1872 *(fat_rdir + 1) = 0xFF; 1873 *(fat_rdir + 2) = 0xFF; 1874 bootclen = (bootlen + 512 * (int)bpb->b_spcl - 1) / 1875 (512 * (int)bpb->b_spcl); 1876 #define BAD_CLUSTER 0xFF7 1877 for (i = 0, fatptr = fat_rdir+3; i < bootclen; i++) 1878 /* 1879 * pre-allocate any clusters used by boot loader if 1880 * loader will occupy more than 1 sector 1881 */ 1882 if (!(i & 01)) { 1883 *fatptr++ = BAD_CLUSTER & 0xFF; 1884 *fatptr = (BAD_CLUSTER >> 8) & 0x0F; 1885 } else { 1886 *fatptr = (*fatptr & 0x0F) | 1887 ((BAD_CLUSTER << 4) & 0xF0); 1888 fatptr++; 1889 *fatptr++ = (BAD_CLUSTER >> 4) & 0xFF; 1890 } 1891 for (i = 0; i < (int)bpb->b_nfat; ++i) 1892 if (write(fd, fat_rdir, fat_bsize) != fat_bsize) { 1893 (void) fprintf(stderr, 1894 gettext("%s: write of MS-DOS File Allocation Table failed, "), 1895 myname); 1896 perror(nullstring); 1897 exit(3); 1898 } 1899 rdirsec = bpb->b_rdirents[0]; 1900 rdirsec = 32 * (int)rdirsec / 512; 1901 if (b_flag) { 1902 struct timeval tv; 1903 struct tm *tp; 1904 ushort_t dostime; 1905 ushort_t dosday; 1906 1907 /* the label can be no more than 11 characters */ 1908 j = min(11, (int)strlen(doslabel)); 1909 for (i = 0; i < j; i++) { 1910 fat_rdir[i] = uppercase(doslabel[i]); 1911 } 1912 for (; i < 11; i++) { 1913 fat_rdir[i] = ' '; 1914 } 1915 fat_rdir[0x0B] = 0x28; 1916 (void) gettimeofday(&tv, (struct timezone *)0); 1917 tp = localtime(&tv.tv_sec); 1918 /* get the time & day into DOS format */ 1919 dostime = tp->tm_sec / 2; 1920 dostime |= tp->tm_min << 5; 1921 dostime |= tp->tm_hour << 11; 1922 dosday = tp->tm_mday; 1923 dosday |= (tp->tm_mon + 1) << 5; 1924 dosday |= (tp->tm_year - 80) << 9; 1925 fat_rdir[0x16] = getlobyte(dostime); 1926 fat_rdir[0x17] = gethibyte(dostime); 1927 fat_rdir[0x18] = getlobyte(dosday); 1928 fat_rdir[0x19] = gethibyte(dosday); 1929 1930 if (write(fd, fat_rdir, 512) != 512) { 1931 (void) fprintf(stderr, 1932 gettext("%s: write of MS-DOS FAT failed, "), 1933 myname); 1934 perror(nullstring); 1935 exit(3); 1936 } 1937 i = 1; 1938 } else { 1939 i = 0; 1940 } 1941 (void) memset(fat_rdir, (char)0, 512); 1942 for (; i < (int)rdirsec; ++i) { 1943 if (write(fd, fat_rdir, 512) != 512) { 1944 (void) fprintf(stderr, 1945 gettext("%s: write of MS-DOS root directory failed, "), 1946 myname); 1947 perror(nullstring); 1948 exit(3); 1949 } 1950 } 1951 /* 1952 * Write the rest of the boot loader if it's longer than one sector. 1953 * The clusters used are marked Bad in the FAT. 1954 * No directory entry exists for this file (so that it cannot be 1955 * deleted). 1956 */ 1957 if (bootlen && write(fd, bootloadr, bootlen) != bootlen) { 1958 (void) fprintf(stderr, 1959 gettext("%s: write of MS-DOS boot sectors failed"), myname); 1960 perror(nullstring); 1961 exit(3); 1962 } 1963 } 1964 1965 static void 1966 write_NEC_DOS_label(int fd, char *doslabel) 1967 { 1968 struct bios_param_blk *bpb; 1969 ushort_t fatsec; 1970 ushort_t rdirsec; 1971 char fat_rdir[1024]; 1972 int i, j, m = 1; 1973 uchar_t bootsec_NEC[1024]; 1974 char *nullstring = ""; 1975 1976 uchar_t bios_param_NEC[30] = { 0xeb, 0x1c, 0x90, 0x0, 0x0, 0x0, 0x0, 1977 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x1, 0x1, 0x0, 1978 0x2, 0xc0, 0x0, 0xd0, 0x4, 0xfe, 0x2, 0x0, 1979 0x8, 0x0, 0x2, 0x0, 0x0, 0x0 1980 }; 1981 1982 uchar_t fatdir[32] = { 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 1983 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 1984 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 1985 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5 1986 1987 }; 1988 1989 1990 (void) memset(bootsec_NEC, (char)0, 1024); 1991 1992 (void) memcpy(&bootsec_NEC, &bios_param_NEC, 30); 1993 1994 bpb = (struct bios_param_blk *)&(bootsec_NEC[0xb]); 1995 if (write(fd, &bootsec_NEC[0], 1024) != 1024) { 1996 (void) fprintf(stderr, gettext( 1997 "%s: write of NEC-DOS boot sector failed, "), 1998 myname); 1999 perror(nullstring); 2000 exit(3); 2001 } 2002 (void) memset(fat_rdir, (char)0, 1024); 2003 fatsec = bpb->b_fatsec[0]; 2004 for (i = 0; i < (int)bpb->b_nfat * (int)fatsec; ++i) { 2005 if ((i % (int)fatsec) == 0) { 2006 fat_rdir[0] = bpb->b_mediadescriptor; 2007 fat_rdir[1] = (char)0xff; 2008 fat_rdir[2] = (char)0xff; 2009 fat_rdir[3] = 0; 2010 fat_rdir[4] = 0; 2011 fat_rdir[5] = 0; 2012 } else { 2013 fat_rdir[0] = 0; 2014 fat_rdir[1] = 0; 2015 fat_rdir[2] = 0; 2016 fat_rdir[3] = 0; 2017 fat_rdir[4] = 0; 2018 fat_rdir[5] = 0; 2019 } 2020 if (write(fd, &fat_rdir[0], 1024) != 1024) { 2021 (void) fprintf(stderr, 2022 /*CSTYLED*/ 2023 gettext("%s: write of NEC-DOS File Allocation Table failed, "), myname); 2024 perror(nullstring); 2025 exit(3); 2026 } 2027 } 2028 #ifndef sparc 2029 /* LINTED */ 2030 rdirsec = (int)htols(bpb->b_rdirents[0]) * 32 /1024; 2031 #else 2032 rdirsec = (int)htols(bpb->b_rdirents[0]) * 32 /1024; 2033 #endif 2034 if (b_flag) { 2035 struct timeval tv; 2036 struct tm *tp; 2037 ushort_t dostime; 2038 ushort_t dosday; 2039 2040 /* the label can be no more than 11 characters */ 2041 j = min(11, (int)strlen(doslabel)); 2042 for (i = 0; i < j; i++) { 2043 fat_rdir[i] = uppercase(doslabel[i]); 2044 } 2045 for (; i < 11; i++) { 2046 fat_rdir[i] = ' '; 2047 } 2048 fat_rdir[0xb] = 0x28; 2049 (void) gettimeofday(&tv, (struct timezone *)0); 2050 tp = localtime(&tv.tv_sec); 2051 /* get the time & day into DOS format */ 2052 dostime = tp->tm_sec / 2; 2053 dostime |= tp->tm_min << 5; 2054 dostime |= tp->tm_hour << 11; 2055 dosday = tp->tm_mday; 2056 dosday |= (tp->tm_mon + 1) << 5; 2057 dosday |= (tp->tm_year - 80) << 9; 2058 fat_rdir[0x16] = getlobyte(dostime); 2059 fat_rdir[0x17] = gethibyte(dostime); 2060 fat_rdir[0x18] = getlobyte(dosday); 2061 fat_rdir[0x19] = gethibyte(dosday); 2062 2063 if (write(fd, &fat_rdir[0], 1024) != 1024) { 2064 (void) fprintf(stderr, 2065 /*CSTYLED*/ 2066 gettext("%s: write of NEC-DOS root directory failed, "), myname); 2067 perror(nullstring); 2068 exit(3); 2069 } 2070 (void) memset(fat_rdir, (char)0, 512); 2071 i = 1; 2072 } else { 2073 i = 0; 2074 2075 while (m < 1024) { 2076 (void) memcpy(&fat_rdir[m], &fatdir, 31); 2077 m = m + 32; 2078 } 2079 } 2080 for (; i < (int)rdirsec; ++i) { 2081 2082 if (write(fd, &fat_rdir[0], 1024) != 1024) { 2083 (void) fprintf(stderr, 2084 /*CSTYLED*/ 2085 gettext("%s: write of NEC-DOS root directory failed, "), myname); 2086 perror(nullstring); 2087 exit(3); 2088 } 2089 } 2090 } 2091