1#ifndef MTOOLS_MSDOS_H
2#define MTOOLS_MSDOS_H
3
4/*  Copyright 1986-1992 Emmet P. Gray.
5 *  Copyright 1996-1998,2000-2003,2006,2007,2009 Alain Knaff.
6 *  This file is part of mtools.
7 *
8 *  Mtools is free software: you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation, either version 3 of the License, or
11 *  (at your option) any later version.
12 *
13 *  Mtools is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *  GNU General Public License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
20 *
21 * msdos common header file
22 */
23
24#define MAX_SECTOR	8192   		/* largest sector size */
25#define MDIR_SIZE	32		/* MSDOS directory entry size in bytes*/
26#define MAX_CLUSTER	8192		/* largest cluster size */
27#ifndef MAX_PATH
28#define MAX_PATH	128		/* largest MSDOS path length */
29#endif
30#define MAX_DIR_SECS	64		/* largest directory (in sectors) */
31#define MSECTOR_SIZE    msector_size
32
33#define NEW		1
34#define OLD		0
35
36#define _WORD(x) ((unsigned short)((unsigned char)(x)[0] + (((unsigned char)(x)[1]) << 8)))
37#define _DWORD(x) ((unsigned int)(_WORD(x) + (_WORD((x)+2) << 16)))
38
39#define DELMARK ((char) 0xe5)
40
41struct directory {
42	char name[8];			/*  0 file name */
43	char ext[3];			/*  8 file extension */
44	unsigned char attr;		/* 11 attribute byte */
45	unsigned char Case;		/* 12 case of short filename */
46	unsigned char ctime_ms;		/* 13 creation time, milliseconds (?) */
47	unsigned char ctime[2];		/* 14 creation time */
48	unsigned char cdate[2];		/* 16 creation date */
49	unsigned char adate[2];		/* 18 last access date */
50	unsigned char startHi[2];	/* 20 start cluster, Hi */
51	unsigned char time[2];		/* 22 time stamp */
52	unsigned char date[2];		/* 24 date stamp */
53	unsigned char start[2];		/* 26 starting cluster number */
54	unsigned char size[4];		/* 28 size of the file */
55};
56
57#define EXTCASE 0x10
58#define BASECASE 0x8
59
60#define MAX16 0xffff
61#define MAX32 0xffffffff
62#define MAX_SIZE 0x7fffffff
63
64#define FILE_SIZE(dir)  (_DWORD((dir)->size))
65#define START(dir) (_WORD((dir)->start))
66#define STARTHI(dir) (_WORD((dir)->startHi))
67
68/* ASSUMPTION: long is at least 32 bits */
69UNUSED(static __inline__ void set_dword(unsigned char *data, unsigned long value))
70{
71	data[3] = (value >> 24) & 0xff;
72	data[2] = (value >> 16) & 0xff;
73	data[1] = (value >>  8) & 0xff;
74	data[0] = (value >>  0) & 0xff;
75}
76
77
78/* ASSUMPTION: short is at least 16 bits */
79UNUSED(static __inline__ void set_word(unsigned char *data, unsigned short value))
80{
81	data[1] = (value >>  8) & 0xff;
82	data[0] = (value >>  0) & 0xff;
83}
84
85
86/*
87 *	    hi byte     |    low byte
88 *	|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
89 *  | | | | | | | | | | | | | | | | |
90 *  \   7 bits    /\4 bits/\ 5 bits /
91 *     year +80     month     day
92 */
93#define	DOS_YEAR(dir) (((dir)->date[1] >> 1) + 1980)
94#define	DOS_MONTH(dir) (((((dir)->date[1]&0x1) << 3) + ((dir)->date[0] >> 5)))
95#define	DOS_DAY(dir) ((dir)->date[0] & 0x1f)
96
97/*
98 *	    hi byte     |    low byte
99 *	|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
100 *      | | | | | | | | | | | | | | | | |
101 *      \  5 bits /\  6 bits  /\ 5 bits /
102 *         hour      minutes     sec*2
103 */
104#define	DOS_HOUR(dir) ((dir)->time[1] >> 3)
105#define	DOS_MINUTE(dir) (((((dir)->time[1]&0x7) << 3) + ((dir)->time[0] >> 5)))
106#define	DOS_SEC(dir) (((dir)->time[0] & 0x1f) * 2)
107
108
109typedef struct InfoSector_t {
110	unsigned char signature1[4];
111	unsigned char filler1[0x1e0];
112	unsigned char signature2[4];
113	unsigned char count[4];
114	unsigned char pos[4];
115	unsigned char filler2[14];
116	unsigned char signature3[2];
117} InfoSector_t;
118
119#define INFOSECT_SIGNATURE1 0x41615252
120#define INFOSECT_SIGNATURE2 0x61417272
121
122
123typedef struct label_blk_t {
124	unsigned char physdrive;	/* 36 physical drive ? */
125	unsigned char reserved;		/* 37 reserved */
126	unsigned char dos4;		/* 38 dos > 4.0 diskette */
127	unsigned char serial[4];       	/* 39 serial number */
128	char label[11];			/* 43 disk label */
129	char fat_type[8];		/* 54 FAT type */
130} label_blk_t;
131
132/* FAT32 specific info in the bootsector */
133struct fat32_t {
134	unsigned char bigFat[4];	/* 36 nb of sectors per FAT */
135	unsigned char extFlags[2];     	/* 40 extension flags */
136	unsigned char fsVersion[2];	/* 42 ? */
137	unsigned char rootCluster[4];	/* 44 start cluster of root dir */
138	unsigned char infoSector[2];	/* 48 changeable global info */
139	unsigned char backupBoot[2];	/* 50 back up boot sector */
140	unsigned char reserved[6];	/* 52 ? */
141	unsigned char reserved2[6];	/* 52 ? */
142	struct label_blk_t labelBlock;
143}; /* ends at 58 */
144
145typedef struct oldboot_t {
146	struct label_blk_t labelBlock;
147	unsigned char res_2m;		/* 62 reserved by 2M */
148	unsigned char CheckSum;		/* 63 2M checksum (not used) */
149	unsigned char fmt_2mf;		/* 64 2MF format version */
150	unsigned char wt;		/* 65 1 if write track after format */
151	unsigned char rate_0;		/* 66 data transfer rate on track 0 */
152	unsigned char rate_any;		/* 67 data transfer rate on track<>0 */
153	unsigned char BootP[2];		/* 68 offset to boot program */
154	unsigned char Infp0[2];		/* 70 T1: information for track 0 */
155	unsigned char InfpX[2];		/* 72 T2: information for track<>0 */
156	unsigned char InfTm[2];		/* 74 T3: track sectors size table */
157	unsigned char DateF[2];		/* 76 Format date */
158	unsigned char TimeF[2];		/* 78 Format time */
159	unsigned char junk[1024 - 80];	/* 80 remaining data */
160} oldboot_t;
161
162struct bootsector {
163	unsigned char jump[3];		/* 0  Jump to boot code */
164	char banner[8];	       		/* 3  OEM name & version */
165	unsigned char secsiz[2];	/* 11 Bytes per sector hopefully 512 */
166	unsigned char clsiz;    	/* 13 Cluster size in sectors */
167	unsigned char nrsvsect[2];	/* 14 Number of reserved (boot) sectors */
168	unsigned char nfat;		/* 16 Number of FAT tables hopefully 2 */
169	unsigned char dirents[2];	/* 17 Number of directory slots */
170	unsigned char psect[2]; 	/* 19 Total sectors on disk */
171	unsigned char descr;		/* 21 Media descriptor=first byte of FAT */
172	unsigned char fatlen[2];	/* 22 Sectors in FAT */
173	unsigned char nsect[2];		/* 24 Sectors/track */
174	unsigned char nheads[2];	/* 26 Heads */
175	unsigned char nhs[4];		/* 28 number of hidden sectors */
176	unsigned char bigsect[4];	/* 32 big total sectors */
177
178	union {
179		struct fat32_t fat32;
180		struct oldboot_t old;
181	} ext;
182};
183
184#define uchr(boot) ((unsigned char*)boot)
185
186#define MAX_BOOT 4096
187
188
189#define CHAR(x) (boot->x[0])
190#define WORD(x) (_WORD(boot->x))
191#define DWORD(x) (_DWORD(boot->x))
192#define OFFSET(x) (((char *) (boot->x)) - ((char *)(boot->jump)))
193
194
195extern struct OldDos_t {
196	unsigned int tracks;
197	unsigned int sectors;
198	unsigned int heads;
199
200	unsigned int dir_len;
201	unsigned int cluster_size;
202	unsigned int fat_len;
203
204	int media;
205} old_dos[];
206
207/* max FAT12/FAT16 sizes, according to
208
209 http://www.microsoft.com/hwdev/download/hardware/fatgen103.pdf
210
211 interestingly enough, another Microsoft document
212 [http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b67321]
213 gives different values, but the first seems to be more sure about
214 itself, so we believe that one ;-)
215*/
216#define FAT12 4085 /* max. number of clusters described by a 12 bit FAT */
217#define FAT16 65525 /* max number of clusters for a 16 bit FAT */
218
219#define ATTR_ARCHIVE 0x20
220#define ATTR_DIR 0x10
221#define ATTR_LABEL 0x8
222#define ATTR_SYSTEM 0x4
223#define ATTR_HIDDEN 0x2
224#define ATTR_READONLY 0x1
225
226#define HAS_BIT(entry,x) ((entry)->dir.attr & (x))
227
228#define IS_ARCHIVE(entry) (HAS_BIT((entry),ATTR_ARCHIVE))
229#define IS_DIR(entry) (HAS_BIT((entry),ATTR_DIR))
230#define IS_LABEL(entry) (HAS_BIT((entry),ATTR_LABEL))
231#define IS_SYSTEM(entry) (HAS_BIT((entry),ATTR_SYSTEM))
232#define IS_HIDDEN(entry) (HAS_BIT((entry),ATTR_HIDDEN))
233#define IS_READONLY(entry) (HAS_BIT((entry),ATTR_READONLY))
234
235
236#define MAX_BYTES_PER_CLUSTER (32*1024)
237/* Experimentally, it turns out that DOS only accepts cluster sizes
238 * which are powers of two, and less than 128 sectors (else it gets a
239 * divide overflow) */
240
241
242#define FAT_SIZE(bits, sec_siz, clusters) \
243	((((clusters)+2) * ((bits)/4) - 1) / 2 / (sec_siz) + 1)
244
245#define NEEDED_FAT_SIZE(x) FAT_SIZE((x)->fat_bits, (x)->sector_size, \
246				    (x)->num_clus)
247
248/* disk size taken by FAT and clusters */
249#define DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) \
250	((n) * FAT_SIZE(bits, sec_siz, clusters) + \
251	 (clusters) * (cluster_size))
252
253#define TOTAL_DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) \
254	(DISK_SIZE(bits, sec_siz, clusters, n, cluster_size) + 2)
255/* approx. total disk size: assume 1 boot sector and one directory sector */
256
257extern const char *mversion;
258extern const char *mdate;
259extern const char *mformat_banner;
260
261extern char *Version;
262extern char *Date;
263
264
265int init(char drive, int mode);
266
267#define MT_READ 1
268#define MT_WRITE 2
269
270#endif
271
272