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