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