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 #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0) 34 /* don't divide by zero */ 35 36 /* cut-over cluster counts for FAT12 and FAT16 */ 37 #define FAT12_THRESHOLD 4085 38 #define FAT16_THRESHOLD 65525 39 40 static struct { 41 uint8_t media; 42 const char *descr; 43 } mediabytes[] = { 44 { 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 /* Unaligned fields must first be accessed byte-wise */ 57 #define GET_UNALIGNED_W(f) \ 58 ( (uint16_t)f[0] | ((uint16_t)f[1]<<8) ) 59 60 static const char *get_media_descr(unsigned char media) 61 { 62 int i; 63 64 for (i = 0; i < sizeof(mediabytes) / sizeof(*mediabytes); ++i) { 65 if (mediabytes[i].media == media) 66 return (mediabytes[i].descr); 67 } 68 return ("undefined"); 69 } 70 71 static void dump_boot(DOS_FS * fs, struct boot_sector *b, unsigned lss) 72 { 73 unsigned short sectors; 74 75 printf("Boot sector contents:\n"); 76 if (!atari_format) { 77 char id[9]; 78 strncpy(id, (const char *)b->system_id, 8); 79 id[8] = 0; 80 printf("System ID \"%s\"\n", id); 81 } else { 82 /* On Atari, a 24 bit serial number is stored at offset 8 of the boot 83 * sector */ 84 printf("Serial number 0x%x\n", 85 b->system_id[5] | (b->system_id[6] << 8) | (b-> 86 system_id[7] << 16)); 87 } 88 printf("Media byte 0x%02x (%s)\n", b->media, get_media_descr(b->media)); 89 printf("%10d bytes per logical sector\n", GET_UNALIGNED_W(b->sector_size)); 90 printf("%10d bytes per cluster\n", fs->cluster_size); 91 printf("%10d reserved sector%s\n", le16toh(b->reserved), 92 le16toh(b->reserved) == 1 ? "" : "s"); 93 printf("First FAT starts at byte %llu (sector %llu)\n", 94 (unsigned long long)fs->fat_start, 95 (unsigned long long)fs->fat_start / lss); 96 printf("%10d FATs, %d bit entries\n", b->fats, fs->fat_bits); 97 printf("%10lld bytes per FAT (= %llu sectors)\n", (long long)fs->fat_size, 98 (long long)fs->fat_size / lss); 99 if (!fs->root_cluster) { 100 printf("Root directory starts at byte %llu (sector %llu)\n", 101 (unsigned long long)fs->root_start, 102 (unsigned long long)fs->root_start / lss); 103 printf("%10d root directory entries\n", fs->root_entries); 104 } else { 105 printf("Root directory start at cluster %lu (arbitrary size)\n", 106 (unsigned long)fs->root_cluster); 107 } 108 printf("Data area starts at byte %llu (sector %llu)\n", 109 (unsigned long long)fs->data_start, 110 (unsigned long long)fs->data_start / lss); 111 printf("%10lu data clusters (%llu bytes)\n", 112 (unsigned long)fs->data_clusters, 113 (unsigned long long)fs->data_clusters * fs->cluster_size); 114 printf("%u sectors/track, %u heads\n", le16toh(b->secs_track), 115 le16toh(b->heads)); 116 printf("%10u hidden sectors\n", atari_format ? 117 /* On Atari, the hidden field is only 16 bit wide and unused */ 118 (((unsigned char *)&b->hidden)[0] | 119 ((unsigned char *)&b->hidden)[1] << 8) : le32toh(b->hidden)); 120 sectors = GET_UNALIGNED_W(b->sectors); 121 printf("%10u sectors total\n", sectors ? sectors : le32toh(b->total_sect)); 122 } 123 124 static void check_backup_boot(DOS_FS * fs, struct boot_sector *b, unsigned int lss) 125 { 126 struct boot_sector b2; 127 128 if (!fs->backupboot_start) { 129 printf("There is no backup boot sector.\n"); 130 if (le16toh(b->reserved) < 3) { 131 printf("And there is no space for creating one!\n"); 132 return; 133 } 134 if (interactive) 135 printf("1) Create one\n2) Do without a backup\n"); 136 else 137 printf(" Auto-creating backup boot block.\n"); 138 if (!interactive || get_key("12", "?") == '1') { 139 unsigned int bbs; 140 /* The usual place for the backup boot sector is sector 6. Choose 141 * that or the last reserved sector. */ 142 if (le16toh(b->reserved) >= 7 && le16toh(b->info_sector) != 6) 143 bbs = 6; 144 else { 145 bbs = le16toh(b->reserved) - 1; 146 if (bbs == le16toh(b->info_sector)) 147 --bbs; /* this is never 0, as we checked reserved >= 3! */ 148 } 149 fs->backupboot_start = bbs * lss; 150 b->backup_boot = htole16(bbs); 151 fs_write(fs->backupboot_start, sizeof(*b), b); 152 fs_write(offsetof(struct boot_sector, backup_boot), 153 sizeof(b->backup_boot), &b->backup_boot); 154 printf("Created backup of boot sector in sector %d\n", bbs); 155 return; 156 } else 157 return; 158 } 159 160 fs_read(fs->backupboot_start, sizeof(b2), &b2); 161 if (memcmp(b, &b2, sizeof(b2)) != 0) { 162 /* there are any differences */ 163 uint8_t *p, *q; 164 int i, pos, first = 1; 165 char buf[20]; 166 167 printf("There are differences between boot sector and its backup.\n"); 168 printf("This is mostly harmless. Differences: (offset:original/backup)\n "); 169 pos = 2; 170 for (p = (uint8_t *) b, q = (uint8_t *) & b2, i = 0; i < sizeof(b2); 171 ++p, ++q, ++i) { 172 if (*p != *q) { 173 sprintf(buf, "%s%u:%02x/%02x", first ? "" : ", ", 174 (unsigned)(p - (uint8_t *) b), *p, *q); 175 if (pos + strlen(buf) > 78) 176 printf("\n "), pos = 2; 177 printf("%s", buf); 178 pos += strlen(buf); 179 first = 0; 180 } 181 } 182 printf("\n"); 183 184 if (interactive) 185 printf("1) Copy original to backup\n" 186 "2) Copy backup to original\n" "3) No action\n"); 187 else 188 printf(" Not automatically fixing this.\n"); 189 switch (interactive ? get_key("123", "?") : '3') { 190 case '1': 191 fs_write(fs->backupboot_start, sizeof(*b), b); 192 break; 193 case '2': 194 fs_write(0, sizeof(b2), &b2); 195 break; 196 default: 197 break; 198 } 199 } 200 } 201 202 static void init_fsinfo(struct info_sector *i) 203 { 204 memset(i, 0, sizeof (struct info_sector)); 205 i->magic = htole32(0x41615252); 206 i->signature = htole32(0x61417272); 207 i->free_clusters = htole32(-1); 208 i->next_cluster = htole32(2); 209 i->boot_sign = htole32(0xaa550000); 210 } 211 212 static void read_fsinfo(DOS_FS * fs, struct boot_sector *b, unsigned int lss) 213 { 214 struct info_sector i; 215 216 if (!b->info_sector) { 217 printf("No FSINFO sector\n"); 218 if (interactive) 219 printf("1) Create one\n2) Do without FSINFO\n"); 220 else 221 printf(" Not automatically creating it.\n"); 222 if (interactive && get_key("12", "?") == '1') { 223 /* search for a free reserved sector (not boot sector and not 224 * backup boot sector) */ 225 uint32_t s; 226 for (s = 1; s < le16toh(b->reserved); ++s) 227 if (s != le16toh(b->backup_boot)) 228 break; 229 if (s > 0 && s < le16toh(b->reserved)) { 230 init_fsinfo(&i); 231 fs_write((off_t)s * lss, sizeof(i), &i); 232 b->info_sector = htole16(s); 233 fs_write(offsetof(struct boot_sector, info_sector), 234 sizeof(b->info_sector), &b->info_sector); 235 if (fs->backupboot_start) 236 fs_write(fs->backupboot_start + 237 offsetof(struct boot_sector, info_sector), 238 sizeof(b->info_sector), &b->info_sector); 239 } else { 240 printf("No free reserved sector found -- " 241 "no space for FSINFO sector!\n"); 242 return; 243 } 244 } else 245 return; 246 } 247 248 fs->fsinfo_start = le16toh(b->info_sector) * lss; 249 fs_read(fs->fsinfo_start, sizeof(i), &i); 250 251 if (i.magic != htole32(0x41615252) || 252 i.signature != htole32(0x61417272) || i.boot_sign != htole32(0xaa550000)) { 253 printf("FSINFO sector has bad magic number(s):\n"); 254 if (i.magic != htole32(0x41615252)) 255 printf(" Offset %llu: 0x%08x != expected 0x%08x\n", 256 (unsigned long long)offsetof(struct info_sector, magic), 257 le32toh(i.magic), 0x41615252); 258 if (i.signature != htole32(0x61417272)) 259 printf(" Offset %llu: 0x%08x != expected 0x%08x\n", 260 (unsigned long long)offsetof(struct info_sector, signature), 261 le32toh(i.signature), 0x61417272); 262 if (i.boot_sign != htole32(0xaa550000)) 263 printf(" Offset %llu: 0x%08x != expected 0x%08x\n", 264 (unsigned long long)offsetof(struct info_sector, boot_sign), 265 le32toh(i.boot_sign), 0xaa550000); 266 if (interactive) 267 printf("1) Correct\n2) Don't correct (FSINFO invalid then)\n"); 268 else 269 printf(" Auto-correcting it.\n"); 270 if (!interactive || get_key("12", "?") == '1') { 271 init_fsinfo(&i); 272 fs_write(fs->fsinfo_start, sizeof(i), &i); 273 } else 274 fs->fsinfo_start = 0; 275 } 276 277 if (fs->fsinfo_start) 278 fs->free_clusters = le32toh(i.free_clusters); 279 } 280 281 static char print_fat_dirty_state(void) 282 { 283 printf("Dirty bit is set. Fs was not properly unmounted and" 284 " some data may be corrupt.\n"); 285 286 if (interactive) { 287 printf("1) Remove dirty bit\n" "2) No action\n"); 288 return get_key("12", "?"); 289 #ifndef __REACTOS__ 290 } else 291 #else 292 } else if (rw) { 293 #endif 294 printf(" Automatically removing dirty bit.\n"); 295 return '1'; 296 #ifdef __REACTOS__ 297 } 298 return '2'; 299 #endif 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 int logical_sector_size, sectors; 332 off_t fat_length; 333 unsigned total_fat_entries; 334 off_t data_size; 335 336 fs_read(0, sizeof(b), &b); 337 logical_sector_size = GET_UNALIGNED_W(b.sector_size); 338 if (!logical_sector_size) 339 die("Logical sector size is zero."); 340 341 /* This was moved up because it's the first thing that will fail */ 342 /* if the platform needs special handling of unaligned multibyte accesses */ 343 /* but such handling isn't being provided. See GET_UNALIGNED_W() above. */ 344 if (logical_sector_size & (SECTOR_SIZE - 1)) 345 die("Logical sector size (%d bytes) is not a multiple of the physical " 346 "sector size.", logical_sector_size); 347 348 fs->cluster_size = b.cluster_size * logical_sector_size; 349 if (!fs->cluster_size) 350 die("Cluster size is zero."); 351 if (b.fats != 2 && b.fats != 1) 352 die("Currently, only 1 or 2 FATs are supported, not %d.\n", b.fats); 353 fs->nfats = b.fats; 354 sectors = GET_UNALIGNED_W(b.sectors); 355 total_sectors = sectors ? sectors : le32toh(b.total_sect); 356 if (verbose) 357 printf("Checking we can access the last sector of the filesystem\n"); 358 /* Can't access last odd sector anyway, so round down */ 359 fs_test((off_t)((total_sectors & ~1) - 1) * logical_sector_size, 360 logical_sector_size); 361 362 fat_length = le16toh(b.fat_length) ? 363 le16toh(b.fat_length) : le32toh(b.fat32_length); 364 if (!fat_length) 365 die("FAT size is zero."); 366 367 fs->fat_start = (off_t)le16toh(b.reserved) * logical_sector_size; 368 fs->root_start = ((off_t)le16toh(b.reserved) + b.fats * fat_length) * 369 logical_sector_size; 370 fs->root_entries = GET_UNALIGNED_W(b.dir_entries); 371 fs->data_start = fs->root_start + ROUND_TO_MULTIPLE(fs->root_entries << 372 MSDOS_DIR_BITS, 373 logical_sector_size); 374 375 data_size = (off_t)total_sectors * logical_sector_size - fs->data_start; 376 if (data_size < fs->cluster_size) 377 die("Filesystem has no space for any data clusters"); 378 379 fs->data_clusters = data_size / fs->cluster_size; 380 fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */ 381 fs->fsinfo_start = 0; /* no FSINFO structure */ 382 fs->free_clusters = -1; /* unknown */ 383 if (!b.fat_length && b.fat32_length) { 384 fs->fat_bits = 32; 385 fs->root_cluster = le32toh(b.root_cluster); 386 if (!fs->root_cluster && fs->root_entries) 387 /* M$ hasn't specified this, but it looks reasonable: If 388 * root_cluster is 0 but there is a separate root dir 389 * (root_entries != 0), we handle the root dir the old way. Give a 390 * warning, but convertig to a root dir in a cluster chain seems 391 * to complex for now... */ 392 printf("Warning: FAT32 root dir not in cluster chain! " 393 "Compatibility mode...\n"); 394 else if (!fs->root_cluster && !fs->root_entries) 395 die("No root directory!"); 396 else if (fs->root_cluster && fs->root_entries) 397 printf("Warning: FAT32 root dir is in a cluster chain, but " 398 "a separate root dir\n" 399 " area is defined. Cannot fix this easily.\n"); 400 if (fs->data_clusters < FAT16_THRESHOLD) 401 printf("Warning: Filesystem is FAT32 according to fat_length " 402 "and fat32_length fields,\n" 403 " but has only %lu clusters, less than the required " 404 "minimum of %d.\n" 405 " This may lead to problems on some systems.\n", 406 (unsigned long)fs->data_clusters, FAT16_THRESHOLD); 407 408 check_fat_state_bit(fs, &b); 409 fs->backupboot_start = le16toh(b.backup_boot) * logical_sector_size; 410 check_backup_boot(fs, &b, logical_sector_size); 411 412 read_fsinfo(fs, &b, logical_sector_size); 413 } else if (!atari_format) { 414 /* On real MS-DOS, a 16 bit FAT is used whenever there would be too 415 * much clusers otherwise. */ 416 fs->fat_bits = (fs->data_clusters >= FAT12_THRESHOLD) ? 16 : 12; 417 if (fs->data_clusters >= FAT16_THRESHOLD) 418 die("Too many clusters (%lu) for FAT16 filesystem.", 419 (unsigned long)fs->data_clusters); 420 check_fat_state_bit(fs, &b); 421 } else { 422 /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs 423 * on floppies, and always 16 bit on harddisks. */ 424 fs->fat_bits = 16; /* assume 16 bit FAT for now */ 425 /* If more clusters than fat entries in 16-bit fat, we assume 426 * it's a real MSDOS FS with 12-bit fat. */ 427 if (fs->data_clusters + 2 > fat_length * logical_sector_size * 8 / 16 || 428 /* if it has one of the usual floppy sizes -> 12bit FAT */ 429 (total_sectors == 720 || total_sectors == 1440 || 430 total_sectors == 2880)) 431 fs->fat_bits = 12; 432 } 433 /* On FAT32, the high 4 bits of a FAT entry are reserved */ 434 fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits; 435 fs->fat_size = fat_length * logical_sector_size; 436 437 fs->label = calloc(12, sizeof(uint8_t)); 438 if (fs->fat_bits == 12 || fs->fat_bits == 16) { 439 struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b; 440 if (b16->extended_sig == 0x29) 441 memmove(fs->label, b16->label, 11); 442 else 443 #ifdef __REACTOS__ 444 { 445 free(fs->label); 446 #endif 447 fs->label = NULL; 448 #ifdef __REACTOS__ 449 } 450 #endif 451 } else if (fs->fat_bits == 32) { 452 if (b.extended_sig == 0x29) 453 memmove(fs->label, &b.label, 11); 454 else 455 #ifdef __REACTOS__ 456 { 457 free(fs->label); 458 #endif 459 fs->label = NULL; 460 #ifdef __REACTOS__ 461 } 462 #endif 463 } 464 465 total_fat_entries = (uint64_t)fs->fat_size * 8 / fs->fat_bits; 466 if (fs->data_clusters > total_fat_entries - 2) 467 die("Filesystem has %u clusters but only space for %u FAT entries.", 468 fs->data_clusters, total_fat_entries - 2); 469 if (!fs->root_entries && !fs->root_cluster) 470 die("Root directory has zero size."); 471 if (fs->root_entries & (MSDOS_DPS - 1)) 472 die("Root directory (%d entries) doesn't span an integral number of " 473 "sectors.", fs->root_entries); 474 if (logical_sector_size & (SECTOR_SIZE - 1)) 475 die("Logical sector size (%u bytes) is not a multiple of the physical " 476 "sector size.", logical_sector_size); 477 #if 0 /* linux kernel doesn't check that either */ 478 /* ++roman: On Atari, these two fields are often left uninitialized */ 479 if (!atari_format && (!b.secs_track || !b.heads)) 480 die("Invalid disk format in boot sector."); 481 #endif 482 if (verbose) 483 dump_boot(fs, &b, logical_sector_size); 484 } 485 486 #ifndef __REACTOS__ 487 static void write_boot_label(DOS_FS * fs, char *label) 488 { 489 if (fs->fat_bits == 12 || fs->fat_bits == 16) { 490 struct boot_sector_16 b16; 491 492 fs_read(0, sizeof(b16), &b16); 493 if (b16.extended_sig != 0x29) { 494 b16.extended_sig = 0x29; 495 b16.serial = 0; 496 memmove(b16.fs_type, fs->fat_bits == 12 ? "FAT12 " : "FAT16 ", 497 8); 498 } 499 memmove(b16.label, label, 11); 500 fs_write(0, sizeof(b16), &b16); 501 } else if (fs->fat_bits == 32) { 502 struct boot_sector b; 503 504 fs_read(0, sizeof(b), &b); 505 if (b.extended_sig != 0x29) { 506 b.extended_sig = 0x29; 507 b.serial = 0; 508 memmove(b.fs_type, "FAT32 ", 8); 509 } 510 memmove(b.label, label, 11); 511 fs_write(0, sizeof(b), &b); 512 if (fs->backupboot_start) 513 fs_write(fs->backupboot_start, sizeof(b), &b); 514 } 515 } 516 517 off_t find_volume_de(DOS_FS * fs, DIR_ENT * de) 518 { 519 uint32_t cluster; 520 off_t offset; 521 int i; 522 523 if (fs->root_cluster) { 524 for (cluster = fs->root_cluster; 525 cluster != 0 && cluster != -1; 526 cluster = next_cluster(fs, cluster)) { 527 offset = cluster_start(fs, cluster); 528 for (i = 0; i * sizeof(DIR_ENT) < fs->cluster_size; i++) { 529 fs_read(offset, sizeof(DIR_ENT), de); 530 if (de->attr != VFAT_LN_ATTR && de->attr & ATTR_VOLUME) 531 return offset; 532 offset += sizeof(DIR_ENT); 533 } 534 } 535 } else { 536 for (i = 0; i < fs->root_entries; i++) { 537 offset = fs->root_start + i * sizeof(DIR_ENT); 538 fs_read(offset, sizeof(DIR_ENT), de); 539 if (de->attr != VFAT_LN_ATTR && de->attr & ATTR_VOLUME) 540 return offset; 541 } 542 } 543 544 return 0; 545 } 546 547 static void write_volume_label(DOS_FS * fs, char *label) 548 { 549 time_t now = time(NULL); 550 struct tm *mtime = localtime(&now); 551 off_t offset; 552 int created; 553 DIR_ENT de; 554 555 created = 0; 556 offset = find_volume_de(fs, &de); 557 if (offset == 0) { 558 created = 1; 559 offset = alloc_rootdir_entry(fs, &de, label, 0); 560 } 561 memcpy(de.name, label, 11); 562 de.time = htole16((unsigned short)((mtime->tm_sec >> 1) + 563 (mtime->tm_min << 5) + 564 (mtime->tm_hour << 11))); 565 de.date = htole16((unsigned short)(mtime->tm_mday + 566 ((mtime->tm_mon + 1) << 5) + 567 ((mtime->tm_year - 80) << 9))); 568 if (created) { 569 de.attr = ATTR_VOLUME; 570 de.ctime_ms = 0; 571 de.ctime = de.time; 572 de.cdate = de.date; 573 de.adate = de.date; 574 de.starthi = 0; 575 de.start = 0; 576 de.size = 0; 577 } 578 579 fs_write(offset, sizeof(DIR_ENT), &de); 580 } 581 582 void write_label(DOS_FS * fs, char *label) 583 { 584 int l = strlen(label); 585 586 while (l < 11) 587 label[l++] = ' '; 588 589 write_boot_label(fs, label); 590 write_volume_label(fs, label); 591 } 592 #endif 593