1 /* boot.c - Read and analyze ia PC/MS-DOS boot sector 2 3 Copyright (C) 1993 Werner Almesberger <werner.almesberger@lrc.di.epfl.ch> 4 Copyright (C) 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> 5 Copyright (C) 2008-2014 Daniel Baumann <mail@daniel-baumann.ch> 6 Copyright (C) 2015 Andreas Bombe <aeb@debian.org> 7 8 This program 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 This program 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 this program. If not, see <http://www.gnu.org/licenses/>. 20 21 The complete text of the GNU General Public License 22 can be found in /usr/share/common-licenses/GPL-3 file. 23 */ 24 25 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998 26 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */ 27 28 #include "vfatlib.h" 29 30 #define NDEBUG 31 #include <debug.h> 32 33 34 #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) 35 /* don't divide by zero */ 36 37 /* cut-over cluster counts for FAT12 and FAT16 */ 38 #define FAT12_THRESHOLD 4085 39 #define FAT16_THRESHOLD 65525 40 41 static struct { 42 uint8_t media; 43 const char *descr; 44 } mediabytes[] = { 45 { 0xf0, "5.25\" or 3.5\" HD floppy" }, 46 { 0xf8, "hard disk" }, 47 { 0xf9, "3.5\" 720k floppy 2s/80tr/9sec or " 48 "5.25\" 1.2M floppy 2s/80tr/15sec" }, 49 { 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" }, 50 { 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" }, 51 { 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" }, 52 { 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" }, 53 { 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" }, 54 { 0xff, "5.25\" 320k floppy 2s/40tr/8sec" }, 55 }; 56 57 #if defined __alpha || defined __ia64__ || defined __x86_64__ || defined __ppc64__ 58 /* Unaligned fields must first be copied byte-wise (little endian) */ 59 #define GET_UNALIGNED_W(u) \ 60 (((unsigned char*)(&u))[0] | (((unsigned char*)&(u))[1] << 8)) 61 #elif defined __s390x__ 62 /* Unaligned fields must first be copied byte-wise (big endian) */ 63 #define GET_UNALIGNED_W(pu) \ 64 (((unsigned char*)&(u))[1] | (((unsigned char*)&(u))[0] << 8)) 65 #else 66 #define GET_UNALIGNED_W(f) le16toh( *(unsigned short *)&f ) 67 #endif 68 69 static const char *get_media_descr(unsigned char media) 70 { 71 int i; 72 73 for (i = 0; i < sizeof(mediabytes) / sizeof(*mediabytes); ++i) { 74 if (mediabytes[i].media == media) 75 return (mediabytes[i].descr); 76 } 77 return ("undefined"); 78 } 79 80 static void dump_boot(DOS_FS * fs, struct boot_sector *b, unsigned lss) 81 { 82 unsigned short sectors; 83 84 printf("Boot sector contents:\n"); 85 if (!atari_format) { 86 char id[9]; 87 strncpy(id, (const char *)b->system_id, 8); 88 id[8] = 0; 89 printf("System ID \"%s\"\n", id); 90 } else { 91 /* On Atari, a 24 bit serial number is stored at offset 8 of the boot 92 * sector */ 93 printf("Serial number 0x%x\n", 94 b->system_id[5] | (b->system_id[6] << 8) | (b-> 95 system_id[7] << 16)); 96 } 97 printf("Media byte 0x%02x (%s)\n", b->media, get_media_descr(b->media)); 98 printf("%10d bytes per logical sector\n", GET_UNALIGNED_W(b->sector_size)); 99 printf("%10d bytes per cluster\n", fs->cluster_size); 100 printf("%10d reserved sector%s\n", le16toh(b->reserved), 101 le16toh(b->reserved) == 1 ? "" : "s"); 102 printf("First FAT starts at byte %llu (sector %llu)\n", 103 (unsigned long long)fs->fat_start, 104 (unsigned long long)fs->fat_start / lss); 105 printf("%10d FATs, %d bit entries\n", b->fats, fs->fat_bits); 106 printf("%10d bytes per FAT (= %u sectors)\n", fs->fat_size, 107 fs->fat_size / lss); 108 if (!fs->root_cluster) { 109 printf("Root directory starts at byte %llu (sector %llu)\n", 110 (unsigned long long)fs->root_start, 111 (unsigned long long)fs->root_start / lss); 112 printf("%10d root directory entries\n", fs->root_entries); 113 } else { 114 printf("Root directory start at cluster %lu (arbitrary size)\n", 115 (unsigned long)fs->root_cluster); 116 } 117 printf("Data area starts at byte %llu (sector %llu)\n", 118 (unsigned long long)fs->data_start, 119 (unsigned long long)fs->data_start / lss); 120 printf("%10lu data clusters (%llu bytes)\n", 121 (unsigned long)fs->data_clusters, 122 (unsigned long long)fs->data_clusters * fs->cluster_size); 123 printf("%u sectors/track, %u heads\n", le16toh(b->secs_track), 124 le16toh(b->heads)); 125 printf("%10u hidden sectors\n", atari_format ? 126 /* On Atari, the hidden field is only 16 bit wide and unused */ 127 (((unsigned char *)&b->hidden)[0] | 128 ((unsigned char *)&b->hidden)[1] << 8) : le32toh(b->hidden)); 129 sectors = GET_UNALIGNED_W(b->sectors); 130 printf("%10u sectors total\n", sectors ? sectors : le32toh(b->total_sect)); 131 } 132 133 static void check_backup_boot(DOS_FS * fs, struct boot_sector *b, int lss) 134 { 135 struct boot_sector b2; 136 137 if (!fs->backupboot_start) { 138 printf("There is no backup boot sector.\n"); 139 if (le16toh(b->reserved) < 3) { 140 printf("And there is no space for creating one!\n"); 141 return; 142 } 143 if (interactive) 144 printf("1) Create one\n2) Do without a backup\n"); 145 else 146 printf(" Auto-creating backup boot block.\n"); 147 if (!interactive || get_key("12", "?") == '1') { 148 int bbs; 149 /* The usual place for the backup boot sector is sector 6. Choose 150 * that or the last reserved sector. */ 151 if (le16toh(b->reserved) >= 7 && le16toh(b->info_sector) != 6) 152 bbs = 6; 153 else { 154 bbs = le16toh(b->reserved) - 1; 155 if (bbs == le16toh(b->info_sector)) 156 --bbs; /* this is never 0, as we checked reserved >= 3! */ 157 } 158 fs->backupboot_start = bbs * lss; 159 b->backup_boot = htole16(bbs); 160 fs_write(fs->backupboot_start, sizeof(*b), b); 161 fs_write(offsetof(struct boot_sector, backup_boot), 162 sizeof(b->backup_boot), &b->backup_boot); 163 printf("Created backup of boot sector in sector %d\n", bbs); 164 return; 165 } else 166 return; 167 } 168 169 fs_read(fs->backupboot_start, sizeof(b2), &b2); 170 if (memcmp(b, &b2, sizeof(b2)) != 0) { 171 /* there are any differences */ 172 uint8_t *p, *q; 173 int i, pos, first = 1; 174 char buf[20]; 175 176 printf("There are differences between boot sector and its backup.\n"); 177 printf("This is mostly harmless. Differences: (offset:original/backup)\n "); 178 pos = 2; 179 for (p = (uint8_t *) b, q = (uint8_t *) & b2, i = 0; i < sizeof(b2); 180 ++p, ++q, ++i) { 181 if (*p != *q) { 182 sprintf(buf, "%s%u:%02x/%02x", first ? "" : ", ", 183 (unsigned)(p - (uint8_t *) b), *p, *q); 184 if (pos + strlen(buf) > 78) 185 printf("\n "), pos = 2; 186 printf("%s", buf); 187 pos += strlen(buf); 188 first = 0; 189 } 190 } 191 printf("\n"); 192 193 if (interactive) 194 printf("1) Copy original to backup\n" 195 "2) Copy backup to original\n" "3) No action\n"); 196 else 197 printf(" Not automatically fixing this.\n"); 198 switch (interactive ? get_key("123", "?") : '3') { 199 case '1': 200 fs_write(fs->backupboot_start, sizeof(*b), b); 201 break; 202 case '2': 203 fs_write(0, sizeof(b2), &b2); 204 break; 205 default: 206 break; 207 } 208 } 209 } 210 211 static void init_fsinfo(struct info_sector *i) 212 { 213 i->magic = htole32(0x41615252); 214 i->signature = htole32(0x61417272); 215 i->free_clusters = htole32(-1); 216 i->next_cluster = htole32(2); 217 i->boot_sign = htole16(0xaa55); 218 } 219 220 static void read_fsinfo(DOS_FS * fs, struct boot_sector *b, int lss) 221 { 222 struct info_sector i; 223 224 if (!b->info_sector) { 225 printf("No FSINFO sector\n"); 226 if (interactive) 227 printf("1) Create one\n2) Do without FSINFO\n"); 228 else 229 printf(" Not automatically creating it.\n"); 230 if (interactive && get_key("12", "?") == '1') { 231 /* search for a free reserved sector (not boot sector and not 232 * backup boot sector) */ 233 uint32_t s; 234 for (s = 1; s < le16toh(b->reserved); ++s) 235 if (s != le16toh(b->backup_boot)) 236 break; 237 if (s > 0 && s < le16toh(b->reserved)) { 238 init_fsinfo(&i); 239 fs_write((off_t)s * lss, sizeof(i), &i); 240 b->info_sector = htole16(s); 241 fs_write(offsetof(struct boot_sector, info_sector), 242 sizeof(b->info_sector), &b->info_sector); 243 if (fs->backupboot_start) 244 fs_write(fs->backupboot_start + 245 offsetof(struct boot_sector, info_sector), 246 sizeof(b->info_sector), &b->info_sector); 247 } else { 248 printf("No free reserved sector found -- " 249 "no space for FSINFO sector!\n"); 250 return; 251 } 252 } else 253 return; 254 } 255 256 fs->fsinfo_start = le16toh(b->info_sector) * lss; 257 fs_read(fs->fsinfo_start, sizeof(i), &i); 258 259 if (i.magic != htole32(0x41615252) || 260 i.signature != htole32(0x61417272) || i.boot_sign != htole16(0xaa55)) { 261 printf("FSINFO sector has bad magic number(s):\n"); 262 if (i.magic != htole32(0x41615252)) 263 printf(" Offset %llu: 0x%08x != expected 0x%08x\n", 264 (unsigned long long)offsetof(struct info_sector, magic), 265 le32toh(i.magic), 0x41615252); 266 if (i.signature != htole32(0x61417272)) 267 printf(" Offset %llu: 0x%08x != expected 0x%08x\n", 268 (unsigned long long)offsetof(struct info_sector, signature), 269 le32toh(i.signature), 0x61417272); 270 if (i.boot_sign != htole16(0xaa55)) 271 printf(" Offset %llu: 0x%04x != expected 0x%04x\n", 272 (unsigned long long)offsetof(struct info_sector, boot_sign), 273 le16toh(i.boot_sign), 0xaa55); 274 if (interactive) 275 printf("1) Correct\n2) Don't correct (FSINFO invalid then)\n"); 276 else 277 printf(" Auto-correcting it.\n"); 278 if (!interactive || get_key("12", "?") == '1') { 279 init_fsinfo(&i); 280 fs_write(fs->fsinfo_start, sizeof(i), &i); 281 } else 282 fs->fsinfo_start = 0; 283 } 284 285 if (fs->fsinfo_start) 286 fs->free_clusters = le32toh(i.free_clusters); 287 } 288 289 static char print_fat_dirty_state(void) 290 { 291 printf("Dirty bit is set. Fs was not properly unmounted and" 292 " some data may be corrupt.\n"); 293 294 if (interactive) { 295 printf("1) Remove dirty bit\n" "2) No action\n"); 296 return get_key("12", "?"); 297 } else 298 printf(" Automatically removing dirty bit.\n"); 299 return '1'; 300 } 301 302 static void check_fat_state_bit(DOS_FS * fs, void *b) 303 { 304 if (fs->fat_bits == 32) { 305 struct boot_sector *b32 = b; 306 307 if (b32->reserved3 & FAT_STATE_DIRTY) { 308 printf("0x41: "); 309 if (print_fat_dirty_state() == '1') { 310 b32->reserved3 &= ~FAT_STATE_DIRTY; 311 fs_write(0, sizeof(*b32), b32); 312 } 313 } 314 } else { 315 struct boot_sector_16 *b16 = b; 316 317 if (b16->reserved2 & FAT_STATE_DIRTY) { 318 printf("0x25: "); 319 if (print_fat_dirty_state() == '1') { 320 b16->reserved2 &= ~FAT_STATE_DIRTY; 321 fs_write(0, sizeof(*b16), b16); 322 } 323 } 324 } 325 } 326 327 void read_boot(DOS_FS * fs) 328 { 329 struct boot_sector b; 330 unsigned total_sectors; 331 unsigned short logical_sector_size, sectors; 332 unsigned fat_length; 333 off_t data_size; 334 335 fs_read(0, sizeof(b), &b); 336 logical_sector_size = GET_UNALIGNED_W(b.sector_size); 337 if (!logical_sector_size) 338 die("Logical sector size is zero."); 339 340 /* This was moved up because it's the first thing that will fail */ 341 /* if the platform needs special handling of unaligned multibyte accesses */ 342 /* but such handling isn't being provided. See GET_UNALIGNED_W() above. */ 343 if (logical_sector_size & (SECTOR_SIZE - 1)) 344 die("Logical sector size (%d bytes) is not a multiple of the physical " 345 "sector size.", logical_sector_size); 346 347 fs->cluster_size = b.cluster_size * logical_sector_size; 348 if (!fs->cluster_size) 349 die("Cluster size is zero."); 350 if (b.fats != 2 && b.fats != 1) 351 die("Currently, only 1 or 2 FATs are supported, not %d.\n", b.fats); 352 fs->nfats = b.fats; 353 sectors = GET_UNALIGNED_W(b.sectors); 354 total_sectors = sectors ? sectors : le32toh(b.total_sect); 355 if (verbose) 356 printf("Checking we can access the last sector of the filesystem\n"); 357 /* Can't access last odd sector anyway, so round down */ 358 fs_test((off_t)((total_sectors & ~1) - 1) * logical_sector_size, 359 logical_sector_size); 360 fat_length = le16toh(b.fat_length) ? 361 le16toh(b.fat_length) : le32toh(b.fat32_length); 362 fs->fat_start = (off_t)le16toh(b.reserved) * logical_sector_size; 363 fs->root_start = ((off_t)le16toh(b.reserved) + b.fats * fat_length) * 364 logical_sector_size; 365 fs->root_entries = GET_UNALIGNED_W(b.dir_entries); 366 fs->data_start = fs->root_start + ROUND_TO_MULTIPLE(fs->root_entries << 367 MSDOS_DIR_BITS, 368 logical_sector_size); 369 data_size = (off_t)total_sectors * logical_sector_size - fs->data_start; 370 fs->data_clusters = data_size / fs->cluster_size; 371 fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */ 372 fs->fsinfo_start = 0; /* no FSINFO structure */ 373 fs->free_clusters = -1; /* unknown */ 374 if (!b.fat_length && b.fat32_length) { 375 fs->fat_bits = 32; 376 fs->root_cluster = le32toh(b.root_cluster); 377 if (!fs->root_cluster && fs->root_entries) 378 /* M$ hasn't specified this, but it looks reasonable: If 379 * root_cluster is 0 but there is a separate root dir 380 * (root_entries != 0), we handle the root dir the old way. Give a 381 * warning, but convertig to a root dir in a cluster chain seems 382 * to complex for now... */ 383 printf("Warning: FAT32 root dir not in cluster chain! " 384 "Compatibility mode...\n"); 385 else if (!fs->root_cluster && !fs->root_entries) 386 die("No root directory!"); 387 else if (fs->root_cluster && fs->root_entries) 388 printf("Warning: FAT32 root dir is in a cluster chain, but " 389 "a separate root dir\n" 390 " area is defined. Cannot fix this easily.\n"); 391 if (fs->data_clusters < FAT16_THRESHOLD) 392 printf("Warning: Filesystem is FAT32 according to fat_length " 393 "and fat32_length fields,\n" 394 " but has only %lu clusters, less than the required " 395 "minimum of %d.\n" 396 " This may lead to problems on some systems.\n", 397 (unsigned long)fs->data_clusters, FAT16_THRESHOLD); 398 399 check_fat_state_bit(fs, &b); 400 fs->backupboot_start = le16toh(b.backup_boot) * logical_sector_size; 401 check_backup_boot(fs, &b, logical_sector_size); 402 403 read_fsinfo(fs, &b, logical_sector_size); 404 } else if (!atari_format) { 405 /* On real MS-DOS, a 16 bit FAT is used whenever there would be too 406 * much clusers otherwise. */ 407 fs->fat_bits = (fs->data_clusters >= FAT12_THRESHOLD) ? 16 : 12; 408 if (fs->data_clusters >= FAT16_THRESHOLD) 409 die("Too many clusters (%lu) for FAT16 filesystem.", fs->data_clusters); 410 check_fat_state_bit(fs, &b); 411 } else { 412 /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs 413 * on floppies, and always 16 bit on harddisks. */ 414 fs->fat_bits = 16; /* assume 16 bit FAT for now */ 415 /* If more clusters than fat entries in 16-bit fat, we assume 416 * it's a real MSDOS FS with 12-bit fat. */ 417 if (fs->data_clusters + 2 > fat_length * logical_sector_size * 8 / 16 || 418 /* if it has one of the usual floppy sizes -> 12bit FAT */ 419 (total_sectors == 720 || total_sectors == 1440 || 420 total_sectors == 2880)) 421 fs->fat_bits = 12; 422 } 423 /* On FAT32, the high 4 bits of a FAT entry are reserved */ 424 fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits; 425 fs->fat_size = fat_length * logical_sector_size; 426 427 fs->label = calloc(12, sizeof(uint8_t)); 428 if (fs->fat_bits == 12 || fs->fat_bits == 16) { 429 struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b; 430 if (b16->extended_sig == 0x29) 431 memmove(fs->label, b16->label, 11); 432 else { 433 free(fs->label); 434 fs->label = NULL; 435 } 436 } else if (fs->fat_bits == 32) { 437 if (b.extended_sig == 0x29) 438 memmove(fs->label, &b.label, 11); 439 else { 440 free(fs->label); 441 fs->label = NULL; 442 } 443 } 444 445 if (fs->data_clusters > 446 ((uint64_t)fs->fat_size * 8 / fs->fat_bits) - 2) 447 die("Filesystem has %d clusters but only space for %d FAT entries.", 448 fs->data_clusters, 449 ((unsigned long long)fs->fat_size * 8 / fs->fat_bits) - 2); 450 if (!fs->root_entries && !fs->root_cluster) 451 die("Root directory has zero size."); 452 if (fs->root_entries & (MSDOS_DPS - 1)) 453 die("Root directory (%d entries) doesn't span an integral number of " 454 "sectors.", fs->root_entries); 455 if (logical_sector_size & (SECTOR_SIZE - 1)) 456 die("Logical sector size (%d bytes) is not a multiple of the physical " 457 "sector size.", logical_sector_size); 458 #if 0 /* linux kernel doesn't check that either */ 459 /* ++roman: On Atari, these two fields are often left uninitialized */ 460 if (!atari_format && (!b.secs_track || !b.heads)) 461 die("Invalid disk format in boot sector."); 462 #endif 463 if (verbose) 464 dump_boot(fs, &b, logical_sector_size); 465 } 466