summaryrefslogtreecommitdiff
path: root/sbin/newfs_msdos
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-06-10 06:37:17 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-06-10 06:37:17 +0000
commit672b6272b68664323e61a94849b7cba009cfa663 (patch)
tree30bda9f43b7785f885167e9e3aa861524164c481 /sbin/newfs_msdos
parent4e3779893f81b3793ff10ee98d705bf5353ad646 (diff)
add newfs_msdos (from freebsd); does not know how to make non-floppy filesystems yet
Diffstat (limited to 'sbin/newfs_msdos')
-rw-r--r--sbin/newfs_msdos/Makefile58
-rw-r--r--sbin/newfs_msdos/bootcode.asm102
-rw-r--r--sbin/newfs_msdos/bootcode.h54
-rw-r--r--sbin/newfs_msdos/dosfs.h133
-rw-r--r--sbin/newfs_msdos/newfs_msdos.8135
-rw-r--r--sbin/newfs_msdos/newfs_msdos.c299
6 files changed, 781 insertions, 0 deletions
diff --git a/sbin/newfs_msdos/Makefile b/sbin/newfs_msdos/Makefile
new file mode 100644
index 00000000000..4b06e5b97fa
--- /dev/null
+++ b/sbin/newfs_msdos/Makefile
@@ -0,0 +1,58 @@
+# $OpenBSD: Makefile,v 1.1 1996/06/10 06:37:11 deraadt Exp $
+
+PROG= newfs_msdos
+MAN= newfs_msdos.8
+
+###################################################################
+#
+# Everything below is solely intented for maintenance.
+# As you can see, it requires as86/ld86 from the ``bcc'' package.
+#
+# For this reason, the bootcode.h target puts the result into
+# ${.CURDIR}
+
+AS86= as86
+LD86= ld86
+AS86FLAGS= -0
+LD86FLAGS= -0 -s
+
+CLEANFILES+= *.obj *.bin *.com
+.SUFFIXES: .asm .obj .bin .com
+
+.asm.obj:
+ ${AS86} ${AS86FLAGS} -o ${.TARGET} ${.IMPSRC}
+
+.obj.bin:
+ ${LD86} ${LD86FLAGS} -T 0x7c00 -o ${.PREFIX}.tmp ${.IMPSRC}
+ dd bs=32 skip=1 of=${.TARGET} if=${.PREFIX}.tmp
+ rm -f ${.PREFIX}.tmp
+
+# .com file is just for testing
+.obj.com:
+ ${LD86} ${LD86FLAGS} -T 0x100 -o ${.PREFIX}.tmp ${.IMPSRC}
+ dd bs=32 skip=1 of=${.TARGET} if=${.PREFIX}.tmp
+ rm -f ${.PREFIX}.tmp
+
+## Do NOT depend this on bootcode.bin unless you've installed the
+## bcc package!
+bootcode.h: ## bootcode.bin
+ @echo converting bootcode.bin into bootcode.h...
+ @perl -e 'if(read(STDIN,$$buf,512)<512) { \
+ die "Read error on .bin file\n"; \
+ } \
+ @arr = unpack("C*",$$buf); \
+ print "#ifndef BOOTCODE_H\n"; \
+ print "#define BOOTCODE_H 1\n\n"; \
+ print "/*\n * This file has been generated\n"; \
+ print " * automatically. Do not edit.\n */\n\n"; \
+ print "static unsigned char bootcode[512] = {\n"; \
+ for($$i=0; $$i<512; $$i++) { \
+ printf "0x%02x, ",$$arr[$$i]; \
+ if($$i % 12 == 11) {print "\n";} \
+ } \
+ print "};\n\n"; \
+ print "#endif /* BOOTCODE_H */\n";' \
+ < bootcode.bin > ${.CURDIR}/bootcode.h
+
+.include <bsd.prog.mk>
+
diff --git a/sbin/newfs_msdos/bootcode.asm b/sbin/newfs_msdos/bootcode.asm
new file mode 100644
index 00000000000..2451e0fe990
--- /dev/null
+++ b/sbin/newfs_msdos/bootcode.asm
@@ -0,0 +1,102 @@
+;;; Hello emacs, this looks like -*- asm -*- code, doesn't it?
+;;;
+;;; This forms a simple dummy boot program for use with a tool to
+;;; format DOS floppies. All it does is displaying a message, and
+;;; recover gracefully by re-initializing the CPU.
+;;;
+;;; Written by Joerg Wunsch, Dresden. Placed in the public domain.
+;;; This software is provided as is, neither kind of warranty applies.
+;;; Use at your own risk.
+;;;
+;;; (This is written in as86 syntax. as86 is part of Bruce Evans'
+;;; bcc package.)
+;;;
+;;; $Id: bootcode.asm,v 1.1 1996/06/10 06:37:12 deraadt Exp $
+;;;
+;;; This code must be linked to address 0x7c00 in order to function
+;;; correctly (the BIOS boot address).
+;;;
+;;; It's 16-bit code, and we don't care for a data segment.
+ use16
+ .text
+
+ entry _begin
+_begin: jmp init ; jump to boot prog
+ nop ; historical baggage ;-)
+;;;
+;;; Reserve space for the "BIOS parameter block".
+;;; This will be overwritten by the actual formatting routine.
+;;;
+bpb: .ascii "BSD 4.4" ; "OEM" name
+ .word 512 ; sector size
+ .byte 2 ; cluster size
+ .word 1 ; reserved sectors (just the boot sector)
+ .byte 2 ; FAT count
+ .word 112 ; # of entries in root dir
+ .word 1440 ; total number of sectors, MSDOS 3.3 or below
+ .byte 0xf9 ; "media descriptor"
+ .word 3 ; FAT size (sectors)
+ .word 9 ; sectors per track
+ .word 2 ; heads per cylinder
+ .word 0 ; hidden sectors
+ ;; MSDOS 4.0++ -- only valid iff total number of sectors == 0
+ .word 0 ; unused
+ .long 0 ; total number of sectors
+ .short 0 ; physical drive (0, 1, ..., 0x80) %-)
+ .byte 0 ; "extented boot signature"
+ .long 0 ; volume serial number (i.e., garbage :)
+ .ascii " " ; label -- same as vol label in root dir
+ .ascii "FAT12 " ; file system ID
+;;;
+;;; Executable code starts here.
+;;;
+init:
+ ;; First, display our message.
+ mov si, *message
+lp1: seg cs
+ movb al, [si]
+ inc si
+ testb al, al
+ jz lp2 ; null-terminated string
+ movb bl, *7 ; display with regular attribute
+ movb ah, *0x0e ; int 0x10, fnc 0x0e -- emulate tty
+ int 0x10
+ jmp lp1
+lp2: xorb ah, ah ; int 0x16, fnc 0x00 -- wait for keystroke
+ int 0x16
+ mov ax, *0x40 ; write 0x1234 to address 0x472 --
+ push ax ; tell the BIOS that this is a warm boot
+ pop dx
+ mov 0x72, *0x1234
+ jmpf 0xfff0,0xf000 ; jump to CPU initialization code
+
+message:
+ .byte 7
+ .byte 0xc9
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xbb, 13, 10, 0xba
+ .ascii " Sorry, this disc does actually not contain "
+ .byte 0xba, 13, 10, 0xba
+ .ascii " a bootable system. "
+ .byte 0xba, 13, 10, 0xba
+ .ascii " Press any key to reboot. "
+ .byte 0xba, 13, 10, 0xc8
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
+ .byte 0xbc, 13,10
+ .byte 0
+
+ ;; Adjust the value below after changing the length of
+ ;; the code above!
+ .space 0x1fe-0x161 ; pad to 512 bytes
+
+ .byte 0x55, 0xaa ; yes, we are bootable (cheating :)
+ end
+ \ No newline at end of file
diff --git a/sbin/newfs_msdos/bootcode.h b/sbin/newfs_msdos/bootcode.h
new file mode 100644
index 00000000000..7b3f325f456
--- /dev/null
+++ b/sbin/newfs_msdos/bootcode.h
@@ -0,0 +1,54 @@
+#ifndef BOOTCODE_H
+#define BOOTCODE_H 1
+
+/*
+ * This file has been generated
+ * automatically. Do not edit.
+ */
+
+static unsigned char bootcode[512] = {
+0xeb, 0x3c, 0x90, 0x42, 0x53, 0x44, 0x20, 0x20, 0x34, 0x2e, 0x34, 0x00,
+0x02, 0x02, 0x01, 0x00, 0x02, 0x70, 0x00, 0xa0, 0x05, 0xf9, 0x03, 0x00,
+0x09, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20,
+0x20, 0x20, 0xbe, 0x65, 0x7c, 0x2e, 0x8a, 0x04, 0x46, 0x84, 0xc0, 0x74,
+0x08, 0xb3, 0x07, 0xb4, 0x0e, 0xcd, 0x10, 0xeb, 0xf0, 0x30, 0xe4, 0xcd,
+0x16, 0xb8, 0x40, 0x00, 0x50, 0x5a, 0xc7, 0x06, 0x72, 0x00, 0x34, 0x12,
+0xea, 0xf0, 0xff, 0x00, 0xf0, 0x07, 0xc9, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xbb, 0x0d, 0x0a, 0xba, 0x20, 0x20, 0x53,
+0x6f, 0x72, 0x72, 0x79, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64,
+0x69, 0x73, 0x63, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x61, 0x63, 0x74,
+0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f,
+0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x20, 0xba, 0x0d, 0x0a, 0xba, 0x20,
+0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20,
+0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xba, 0x0d, 0x0a,
+0xba, 0x20, 0x20, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x79,
+0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x62, 0x6f,
+0x6f, 0x74, 0x2e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xba,
+0x0d, 0x0a, 0xc8, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+0xcd, 0xbc, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, };
+
+#endif /* BOOTCODE_H */
diff --git a/sbin/newfs_msdos/dosfs.h b/sbin/newfs_msdos/dosfs.h
new file mode 100644
index 00000000000..f783718651c
--- /dev/null
+++ b/sbin/newfs_msdos/dosfs.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1995 Joerg Wunsch
+ *
+ * All rights reserved.
+ *
+ * This program is free software.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * MS-DOS (FAT) file system structure definitions.
+ *
+ * $Id: dosfs.h,v 1.1 1996/06/10 06:37:14 deraadt Exp $
+ */
+
+#ifndef DOSFS_H
+#define DOSFS_H 1
+
+typedef u_int8_t Long[4];
+typedef u_int8_t Short[2];
+
+union bootsector {
+ u_char raw[512];
+ struct bsec {
+ u_char jump_boot[3]; /* jump code to boot-up partition */
+ char oem_name[8]; /* OEM company name & version */
+ Short sectsiz;/* bytes per sector */
+ u_char clustsiz; /* sectors per cluster */
+ Short ressecs;/* reserved sectors [before 1st FAT] */
+ u_char fatcnt; /* # of FAT's */
+ Short rootsiz;/* number of root dir entries */
+ Short totsecs;/* total # of sectors */
+ u_char media; /* media descriptor */
+ Short fatsize;/* # of sectors per FAT */
+ Short trksecs;/* sectors per track (cylinder) */
+ Short headcnt;/* # of r/w heads */
+ Short hidnsec;/* hidden sectors */
+ union {
+ /* case totsecs != 0: */
+ /* This is a partition of MS-DOS 3.3 format (< 32 MB) */
+ u_char bootprogram[480];
+
+ /* case totsecs == 0: */
+ /* partition of MS-DOS 4.0+ format, or > 32 MB */
+ struct {
+ Short unused;
+ Long totsecs; /* total # of sectors,
+ * as a 32-bit */
+ Short physdrv; /* physical drive #
+ * [0x80...] */
+ u_char extboot; /* extended boot
+ * signature??? */
+ Long serial; /* volume serial number */
+ char label[11]; /* same as volume label
+ * in root dir */
+ char fsysid[8]; /* some like `FAT16' */
+ u_char bootprogram[448];
+ } extended;
+ } variable_part;
+ u_char signature[2]; /* always {0x55, 0xaa} */
+ } bsec;
+};
+
+struct fat {
+ u_char media; /* the media descriptor again */
+ u_char padded; /* alway 0xff */
+ u_char contents[1]; /* the `1' is a placeholder only */
+};
+/* DOS file attributes */
+#define FA_RONLY 1 /* read/only */
+#define FA_HIDDEN 2 /* hidden */
+#define FA_SYSTEM 4 /* system */
+#define FA_VOLLABEL 8 /* this is the volume label */
+#define FA_SUBDIR 0x10 /* sub-directory */
+#define FA_ARCH 0x20 /* archive - file hasn't been backed up */
+
+struct dosftime {
+ u_char time[2]; /* [0] & 0x1f - seconds div 2 ([1] & 7) * 8 +
+ * ([0] >> 5) - minutes [1] >> 3 - hours */
+ u_char date[2]; /* [0] & 0x1f - day ([1] & 1) * 8 + ([0] >> 5)
+ * - month [1] >> 1 - year - 1980 */
+};
+#define dosft_hour(dft) ((dft).time[1] >> 3)
+#define dosft_minute(dft) (((dft).time[1] & 7) * 8 + ((dft).time[0] >> 5))
+#define dosft_second(dft) (((dft).time[0] & 0x1f) * 2)
+#define dosft_year(dft) (((dft).date[1] >> 1) + 1980)
+#define dosft_month(dft) (((dft).date[1] & 1) * 8 + ((dft).date[0] >> 5))
+#define dosft_day(dft) ((dft).date[0] & 0x1f)
+
+
+struct direntry {
+ char name[8]; /* file name portion */
+ char ext[3]; /* file extension */
+ u_char attr; /* file attribute as above */
+ char reserved[10];
+ struct dosftime fdate; /* time created/last modified */
+ Short startclstr; /* starting cluster number */
+ Long filesiz; /* file size in bytes */
+};
+
+#define s_to_little_s(dst, src) do { \
+ u_int16_t tmp = htons(src); \
+ dst[0] = (tmp&0xff00)>>8; \
+ dst[1] = (tmp&0x00ff); \
+ } while (0);
+#define l_to_little_l(dst, src) do { \
+ u_int32_t tmp = htonl(src); \
+ dst[0] = (tmp&0xff000000)>>24; \
+ dst[1] = (tmp&0x00ff0000)>>16; \
+ dst[2] = (tmp&0x0000ff00)>>8; \
+ dst[3] = (tmp&0x000000ff); \
+ } while (0);
+
+#endif /* DOSFS_H */
diff --git a/sbin/newfs_msdos/newfs_msdos.8 b/sbin/newfs_msdos/newfs_msdos.8
new file mode 100644
index 00000000000..30ea85b145d
--- /dev/null
+++ b/sbin/newfs_msdos/newfs_msdos.8
@@ -0,0 +1,135 @@
+.\"
+.\" Copyright (c) 1995, 1996 Joerg Wunsch
+.\"
+.\" All rights reserved.
+.\"
+.\" This program is free software.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $Id: newfs_msdos.8,v 1.1 1996/06/10 06:37:15 deraadt Exp $
+.\"
+.Dd November 5, 1995
+.Os
+.Dt MKDOSFS 1
+.Sh NAME
+.Nm mkdosfs
+.Nd create an MS-DOS (FAT) file system
+.Sh SYNOPSIS
+.Nm mkdosfs
+.Bq Fl f Ar capacity
+.Bq Fl L Ar vollabel
+.Ar device
+.Sh DESCRIPTION
+.Nm Mkdosfs
+establishes a file system structure on
+.Ar device
+that is understood by
+.Xr mount_msdos
+and some ancient program loader.
+.Ar Device
+will typically be the character device node for a floppy disk drive,
+.Pq e.\ g. Pa /dev/rfd0 ,
+although any existing writable file or device is acceptable. In case
+of a regular file it is treated as a dumped image of an MS-DOS file
+system; only the file system structure will be written to it, and it
+won't be truncated.
+.Pp
+The options are as follows:
+.Bl -tag -width 10n -offset indent
+.It Fl f Ar capacity
+Use defaults for a typical file system with
+.Ar capacity
+kilobytes. Currently, the values 360, 720, 1200, and 1440 are
+recognized.
+.Pp
+If this option is not specified,
+.Nm
+attempts to determine the size of the
+.Ar device .
+This is not reliably possible in all cases, but is believed to work
+for the more common situations.
+.It Fl L Ar vollabel
+Use
+.Ar vollabel
+to describe the file system, instead of the default
+.Ql 4.4BSD .
+.El
+.Pp
+The file system structure consists of three major areas:
+.Bl -tag -width 10n -offset indent
+.It Em The bootsector
+This is the very first (512-byte) sector. It contains executable
+code that normally would bootstrap an operating system when loaded.
+Since it's beyond the scope of
+.Nm
+to install an operating system on the medium, this boot code will only
+print a message that the disk does not contain a bootable system.
+Inside the
+.Em bootsector
+is the
+.Em BIOS parameter block (BPB) ,
+where several statistical parameters of the file system are being
+held.
+.It Em The file allocation table(s) (FAT)
+Sectors next to the
+.Em bootsector
+hold the FAT, which is used to register file system allocation,
+as well as keeping pointer chains for the chunks constituting
+one file. There are usually two identical copies of the FAT.
+.It Em The root directory
+The final structure is the root directory for this medium. It is
+merely a space reservation, padded with 0's, and unfortunately fixed
+in its size.
+.Nm mkdosfs
+initializes it to empty, and enters a volume label record into the
+very first directory slot.
+.Sh DIAGNOSTICS
+An exit status of 0 is returned upon successful operation. Exit status
+1 is returned on any errors during file system creation, and an exit status
+of 2 reflects invalid arguments given to the program (along with an
+appropriate information written to diagnostic output).
+.Sh SEE ALSO
+.Xr fdformat 1 ,
+.Xr mount_msdos 8 ,
+.Xr newfs 8 .
+.Sh BUGS
+There is currently no way to specify obscure file system parameters.
+Thus, only media with one of the supported capacity values can be
+formatted. For the same reason, it's not possible to handle hard disk
+partitions. More options should be added to allow this. More entries
+should be added to the table of known formats, too.
+.Pp
+No attempt is made to handle media defects. However, this is beyond
+the scope of
+.Nm mkdosfs
+and should better be handled by the (nonexistent)
+.Xr dosfsck 1
+utility.
+.Sh HISTORY
+.Nm Mkdosfs
+appeared in
+.Em FreeBSD 2.2 .
+.Sh AUTHOR
+The program has been contributed by
+.if n Joerg Wunsch,
+.if t J\(:org Wunsch,
+Dresden.
diff --git a/sbin/newfs_msdos/newfs_msdos.c b/sbin/newfs_msdos/newfs_msdos.c
new file mode 100644
index 00000000000..af667433705
--- /dev/null
+++ b/sbin/newfs_msdos/newfs_msdos.c
@@ -0,0 +1,299 @@
+/* $OpenBSD: newfs_msdos.c,v 1.1 1996/06/10 06:37:16 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1995, 1996 Joerg Wunsch
+ *
+ * All rights reserved.
+ *
+ * This program is free software.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Create an MS-DOS (FAT) file system.
+ *
+ * from: FreeBSD Id: mkdosfs.c,v 1.2 1996/01/30 02:35:08 joerg Exp
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <memory.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "bootcode.h"
+#include "dosfs.h"
+
+struct descrip {
+ /* our database key */
+ u_int32_t kilobytes;
+
+ /* MSDOS 3.3 BPB fields */
+ u_int16_t sectsiz;
+ u_int8_t clustsiz;
+ u_int16_t ressecs;
+ u_int8_t fatcnt;
+ u_int16_t rootsiz;
+ u_int16_t totsecs;
+ u_int8_t media;
+ u_int16_t fatsize;
+ u_int16_t trksecs;
+ u_int16_t headcnt;
+ u_int16_t hidnsec;
+
+ /* MSDOS 4 BPB extensions */
+ u_int32_t ext_totsecs;
+ u_int16_t ext_physdrv;
+ u_int8_t ext_extboot;
+ int8_t ext_label[11];
+ int8_t ext_fsysid[8];
+};
+
+static struct descrip table[] = {
+ /* NB: must be sorted, starting with the largest format! */
+ /*
+ * kilobytes
+ * sec cls res fat rot tot med fsz spt hds hid
+ * tot phs ebt label fsysid
+ */
+ {1440, 512, 1, 1, 2, 224, 2880, 0xf0, 9, 18, 2, 0,
+ 0, 0, 0, "4.4BSD ", "FAT12 "},
+ {1200, 512, 1, 1, 2, 224, 2400, 0xf9, 7, 15, 2, 0,
+ 0, 0, 0, "4.4BSD ", "FAT12 "},
+ {720, 512, 2, 1, 2, 112, 1440, 0xf9, 3, 9, 2, 0,
+ 0, 0, 0, "4.4BSD ", "FAT12 "},
+ {360, 512, 2, 1, 2, 112, 720, 0xfd, 2, 9, 2, 0,
+ 0, 0, 0, "4.4BSD ", "FAT12 "},
+};
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: ");
+ errx(2, "[-s kbytes] [-L label] device");
+}
+
+unsigned
+findformat(fd)
+ int fd;
+{
+ struct stat sb;
+
+ /*
+ * This is a bit tricky. If the argument is a regular file, we can
+ * lseek() to its end and get the size reported. If it's a device
+ * however, lseeking doesn't report us any useful number. Instead,
+ * we try to seek just to the end of the device and try reading a
+ * block there. In the case where we've hit exactly the device
+ * boundary, we get a zero read, and thus have found the size.
+ * Since our knowledge of distinct formats is limited anyway, this
+ * is not a big deal at all.
+ */
+
+ if (fstat(fd, &sb) == -1)
+ err(1, "Huh? Cannot fstat()"); /* Cannot happen */
+ if (S_ISREG(sb.st_mode)) {
+ off_t o;
+ if (lseek(fd, (off_t) 0, SEEK_END) == -1 ||
+ (o = lseek(fd, (off_t) 0, SEEK_CUR)) == -1)
+ /* Hmm, hmm. Hard luck. */
+ return 0;
+ return (int) (o / 1024);
+ } else if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+ char b[512];
+ int i, rv;
+ struct descrip *dp;
+
+ for (i = 0, dp = table;
+ i < sizeof table / sizeof(struct descrip);
+ i++, dp++) {
+ if (lseek(fd, (off_t) (dp->kilobytes * 1024),
+ SEEK_SET) == 1)
+ /* Uh-oh, lseek() is not supposed to
+ * fail. */
+ return 0;
+ if ((rv = read(fd, b, 512)) == 0)
+ break;
+ /* XXX The ENOSPC is for the bogus fd(4)
+ * driver return value. */
+ if (rv == -1 && errno != EINVAL && errno != ENOSPC)
+ return 0;
+ /* else: continue */
+ }
+ if (i == sizeof table / sizeof(struct descrip))
+ return 0;
+ (void) lseek(fd, (off_t) 0, SEEK_SET);
+ return dp->kilobytes;
+ }
+ return 0;
+}
+
+
+void
+setup_boot_sector_from_template(bs, dp)
+ union bootsector *bs;
+ struct descrip *dp;
+{
+ memcpy((void *)bs->raw, (void *)bootcode, 512);
+
+ /* historical part of BPB */
+ s_to_little_s(bs->bsec.sectsiz, dp->sectsiz);
+ bs->bsec.clustsiz = dp->clustsiz;
+ s_to_little_s(bs->bsec.ressecs, dp->ressecs);
+ bs->bsec.fatcnt = dp->fatcnt;
+ s_to_little_s(bs->bsec.rootsiz, dp->rootsiz);
+ s_to_little_s(bs->bsec.totsecs, dp->totsecs);
+ bs->bsec.media = dp->media;
+ s_to_little_s(bs->bsec.fatsize, dp->fatsize);
+ s_to_little_s(bs->bsec.trksecs, dp->trksecs);
+ s_to_little_s(bs->bsec.headcnt, dp->headcnt);
+ s_to_little_s(bs->bsec.hidnsec, dp->hidnsec);
+
+ /* MSDOS 4 extensions */
+ l_to_little_l(bs->bsec.variable_part.extended.totsecs, dp->ext_totsecs);
+ s_to_little_s(bs->bsec.variable_part.extended.physdrv, dp->ext_physdrv);
+ bs->bsec.variable_part.extended.extboot = dp->ext_extboot;
+
+ /* assign a "serial number" :) */
+ srandom((unsigned) time((time_t) 0));
+ l_to_little_l(bs->bsec.variable_part.extended.serial, random());
+
+ memcpy((void *) bs->bsec.variable_part.extended.label,
+ (void *) dp->ext_label, 11);
+ memcpy((void *) bs->bsec.variable_part.extended.fsysid,
+ (void *) dp->ext_fsysid, 8);
+}
+#define roundup(dst, limit) dst = (((dst) | ((limit) - 1)) & ~(limit)) + 1
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ union bootsector bs;
+ struct descrip *dp;
+ struct fat *fat;
+ struct direntry *rootdir;
+ const char *label = 0;
+ struct tm *tp;
+ time_t now;
+ int c, i, fd, format = 0, rootdirsize;
+
+ while ((c = getopt(argc, argv, "s:L:")) != EOF)
+ switch (c) {
+ case 's':
+ format = atoi(optarg);
+ break;
+ case 'L':
+ label = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ if ((fd = open(argv[0], O_RDWR | O_EXCL, 0)) == -1)
+ err(1, "open(%s)", argv[0]);
+
+ if (format == 0) {
+ /*
+ * No format specified, try to figure it out.
+ */
+ if ((format = findformat(fd)) == 0)
+ errx(1, "cannot determine size, must use -s format");
+ }
+ for (i = 0, dp = table; i < sizeof table / sizeof(struct descrip); i++, dp++)
+ if (dp->kilobytes == format)
+ break;
+ if (i == sizeof table / sizeof(struct descrip))
+ errx(1, "cannot find format description for %d KB", format);
+
+ /* prepare and write the boot sector */
+ setup_boot_sector_from_template(&bs, dp);
+
+ /* if we've got an explicit label, use it */
+ if (label)
+ strncpy(bs.bsec.variable_part.extended.label, label, 11);
+
+ if (write(fd, (char *) bs.raw, sizeof bs) != sizeof bs)
+ err(1, "boot sector write()");
+
+ /* now, go on with the FATs */
+ if ((fat = (struct fat *) malloc(dp->sectsiz * dp->fatsize)) == 0)
+ abort();
+ memset((void *) fat, 0, dp->sectsiz * dp->fatsize);
+
+ fat->media = dp->media;
+ fat->padded = 0xff;
+ fat->contents[0] = 0xff;
+ if (dp->totsecs > 20740 || (dp->totsecs == 0 && dp->ext_totsecs > 20740))
+ /* 16-bit FAT */
+ fat->contents[1] = 0xff;
+
+ for (i = 0; i < dp->fatcnt; i++)
+ if (write(fd, (char *) fat, dp->sectsiz * dp->fatsize)
+ != dp->sectsiz * dp->fatsize)
+ err(1, "FAT write()");
+
+ free((void *) fat);
+
+ /* finally, build the root dir */
+ rootdirsize = dp->rootsiz * sizeof(struct direntry);
+ roundup(rootdirsize, dp->clustsiz * dp->sectsiz);
+
+ if ((rootdir = (struct direntry *) malloc(rootdirsize)) == 0)
+ abort();
+ memset((void *) fat, 0, rootdirsize);
+
+ /* set up a volume label inside the root dir :) */
+ if (label)
+ strncpy(rootdir[0].name, label, 11);
+ else
+ memcpy(rootdir[0].name, dp->ext_label, 11);
+ rootdir[0].attr = FA_VOLLABEL;
+ now = time((time_t) 0);
+ tp = localtime(&now);
+ rootdir[0].fdate.time[0] = tp->tm_sec / 2;
+ rootdir[0].fdate.time[0] |= (tp->tm_min & 7) << 5;
+ rootdir[0].fdate.time[1] = ((tp->tm_min >> 3) & 7);
+ rootdir[0].fdate.time[1] |= tp->tm_hour << 3;
+ rootdir[0].fdate.date[0] = tp->tm_mday;
+ rootdir[0].fdate.date[0] |= ((tp->tm_mon + 1) & 7) << 5;
+ rootdir[0].fdate.date[1] = ((tp->tm_mon + 1) >> 3) & 1;
+ rootdir[0].fdate.date[1] |= (tp->tm_year - 80) << 1;
+
+ if (write(fd, (char *) rootdir, rootdirsize) != rootdirsize)
+ err(1, "root dir write()");
+
+ (void) close(fd);
+ return 0;
+}