summaryrefslogtreecommitdiffstats
path: root/usr.sbin/mkdosfs
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>1995-11-05 16:02:04 +0000
committerjoerg <joerg@FreeBSD.org>1995-11-05 16:02:04 +0000
commita7d823cf623b0577a4b37407e2e05e46a1ae9e6f (patch)
tree08b49f583e7d4c0790cc6b5b9af46f5d7479cd81 /usr.sbin/mkdosfs
downloadFreeBSD-src-a7d823cf623b0577a4b37407e2e05e46a1ae9e6f.zip
FreeBSD-src-a7d823cf623b0577a4b37407e2e05e46a1ae9e6f.tar.gz
mkdosfs -- a tool to create an MS-DOS file system on a device or file.
Since msdosfs is part of the base system, it's not wise to rely on something like mtools to provide this functionality. This utility is the agreed fix for PR # misc/804 fdformat did not ...
Diffstat (limited to 'usr.sbin/mkdosfs')
-rw-r--r--usr.sbin/mkdosfs/Makefile59
-rw-r--r--usr.sbin/mkdosfs/bootcode.asm102
-rw-r--r--usr.sbin/mkdosfs/bootcode.h54
-rw-r--r--usr.sbin/mkdosfs/dosfs.h135
-rw-r--r--usr.sbin/mkdosfs/mkdosfs.1128
-rw-r--r--usr.sbin/mkdosfs/mkdosfs.c239
6 files changed, 717 insertions, 0 deletions
diff --git a/usr.sbin/mkdosfs/Makefile b/usr.sbin/mkdosfs/Makefile
new file mode 100644
index 0000000..1d8ff5d
--- /dev/null
+++ b/usr.sbin/mkdosfs/Makefile
@@ -0,0 +1,59 @@
+# $Id$
+#
+PROG= mkdosfs
+
+CFLAGS+= -Wall
+
+###################################################################
+#
+# 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/usr.sbin/mkdosfs/bootcode.asm b/usr.sbin/mkdosfs/bootcode.asm
new file mode 100644
index 0000000..9213cba
--- /dev/null
+++ b/usr.sbin/mkdosfs/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$
+;;;
+;;; 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/usr.sbin/mkdosfs/bootcode.h b/usr.sbin/mkdosfs/bootcode.h
new file mode 100644
index 0000000..7b3f325
--- /dev/null
+++ b/usr.sbin/mkdosfs/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/usr.sbin/mkdosfs/dosfs.h b/usr.sbin/mkdosfs/dosfs.h
new file mode 100644
index 0000000..08afd4c
--- /dev/null
+++ b/usr.sbin/mkdosfs/dosfs.h
@@ -0,0 +1,135 @@
+/*
+ * 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$
+ */
+
+#ifndef DOSFS_H
+#define DOSFS_H 1
+
+typedef u_char Long[4];
+typedef u_char Short[2];
+
+union bootsector
+{
+ unsigned 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 */
+};
+
+/* handle endiannes: */
+#define s_to_little_s(dst, src) dst[0]=(src)&0xff; dst[1]=((src)&0xff00)>>8
+#define l_to_little_l(dst, src) \
+dst[0]=(src)&0xff; dst[1]=((src)&0xff00)>>8; \
+dst[2]=((src)&0xff0000)>>16; dst[3]=((src)&0xff000000)>>24
+
+#endif /* DOSFS_H */
diff --git a/usr.sbin/mkdosfs/mkdosfs.1 b/usr.sbin/mkdosfs/mkdosfs.1
new file mode 100644
index 0000000..e6b06ac
--- /dev/null
+++ b/usr.sbin/mkdosfs/mkdosfs.1
@@ -0,0 +1,128 @@
+.\"
+.\" 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.
+.\"
+.\" $Id$
+.\"
+.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.
+.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/usr.sbin/mkdosfs/mkdosfs.c b/usr.sbin/mkdosfs/mkdosfs.c
new file mode 100644
index 0000000..2e88d16
--- /dev/null
+++ b/usr.sbin/mkdosfs/mkdosfs.c
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ */
+
+/*
+ * Create an MS-DOS (FAT) file system.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <memory.h>
+#include <err.h>
+#include <fcntl.h>
+
+#include "bootcode.h"
+#include "dosfs.h"
+
+struct descrip
+{
+ /* our database key */
+ unsigned kilobytes;
+ /* MSDOS 3.3 BPB fields */
+ u_short sectsiz;
+ u_char clustsiz;
+ u_short ressecs;
+ u_char fatcnt;
+ u_short rootsiz;
+ u_short totsecs;
+ u_char media;
+ u_short fatsize;
+ u_short trksecs;
+ u_short headcnt;
+ u_short hidnsec;
+ /* MSDOS 4 BPB extensions */
+ u_long ext_totsecs;
+ u_short ext_physdrv;
+ u_char ext_extboot;
+ char ext_label[11];
+ char ext_fsysid[8];
+};
+
+static struct descrip
+table[] =
+{
+ /*
+ * kilobytes
+ * sec cls res fat rot tot med fsz spt hds hid
+ * tot phs ebt label fsysid
+ */
+ { 720,
+ 512, 2, 1, 2, 112, 1440, 0xf9, 3, 9, 2, 0,
+ 0, 0, 0, "4.4BSD ", "FAT12 "},
+ {1440,
+ 512, 1, 1, 2, 224, 2880, 0xf0, 9, 18, 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 "},
+ {1200,
+ 512, 1, 1, 2, 224, 2400, 0xf9, 7, 15, 2, 0,
+ 0, 0, 0, "4.4BSD ", "FAT12 "},
+};
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: ");
+ errx(2, "[-f kbytes] [-L label] device");
+}
+
+void
+setup_boot_sector_from_template(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(int argc, char **argv)
+{
+ union bootsector bs;
+ struct descrip *dp;
+ struct fat *fat;
+ struct direntry *rootdir;
+ struct tm *tp;
+ time_t now;
+
+ int c, i, fd, format = 0, rootdirsize;
+ const char *label = 0;
+
+ while((c = getopt(argc, argv, "f:L:")) != EOF)
+ switch(c)
+ {
+ case 'f':
+ format = atoi(optarg);
+ break;
+
+ case 'L':
+ label = optarg;
+ break;
+
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if(argc != 1)
+ usage();
+
+ 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);
+
+ if((fd = open(argv[0], O_RDWR|O_EXCL, 0)) == -1)
+ err(1, "open(%s)", argv[0]);
+
+ /* 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;
+}
+
OpenPOWER on IntegriCloud