boot.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /* boot.c - Read and analyze ia PC/MS-DOS boot sector */
  2. /* Written 1993 by Werner Almesberger */
  3. /* FAT32, VFAT, Atari format support, and various fixes additions May 1998
  4. * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <stdlib.h>
  9. #include "common.h"
  10. #include "dosfsck.h"
  11. #include "io.h"
  12. #include "boot.h"
  13. #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
  14. /* don't divide by zero */
  15. static struct {
  16. __u8 media;
  17. char *descr;
  18. } mediabytes[] = {
  19. { 0xf0, "5.25\" or 3.5\" HD floppy" },
  20. { 0xf8, "hard disk" },
  21. { 0xf9, "3,5\" 720k floppy 2s/80tr/9sec or "
  22. "5.25\" 1.2M floppy 2s/80tr/15sec" },
  23. { 0xfa, "5.25\" 320k floppy 1s/80tr/8sec" },
  24. { 0xfb, "3.5\" 640k floppy 2s/80tr/8sec" },
  25. { 0xfc, "5.25\" 180k floppy 1s/40tr/9sec" },
  26. { 0xfd, "5.25\" 360k floppy 2s/40tr/9sec" },
  27. { 0xfe, "5.25\" 160k floppy 1s/40tr/8sec" },
  28. { 0xff, "5.25\" 320k floppy 2s/40tr/8sec" },
  29. };
  30. #if defined __alpha || defined __ia64__ || defined __s390x__ || defined __x86_64__ || defined __ppc64__
  31. /* Unaligned fields must first be copied byte-wise */
  32. #define GET_UNALIGNED_W(f) \
  33. ({ \
  34. unsigned short __v; \
  35. memcpy( &__v, &f, sizeof(__v) ); \
  36. CF_LE_W( *(unsigned short *)&__v ); \
  37. })
  38. #else
  39. #define GET_UNALIGNED_W(f) CF_LE_W( *(unsigned short *)&f )
  40. #endif
  41. static char *get_media_descr( unsigned char media )
  42. {
  43. int i;
  44. for( i = 0; i < sizeof(mediabytes)/sizeof(*mediabytes); ++i ) {
  45. if (mediabytes[i].media == media)
  46. return( mediabytes[i].descr );
  47. }
  48. return( "undefined" );
  49. }
  50. static void dump_boot(DOS_FS *fs,struct boot_sector *b,unsigned lss)
  51. {
  52. unsigned short sectors;
  53. printf("Boot sector contents:\n");
  54. if (!atari_format) {
  55. char id[9];
  56. strncpy(id,b->system_id,8);
  57. id[8] = 0;
  58. printf("System ID \"%s\"\n",id);
  59. }
  60. else {
  61. /* On Atari, a 24 bit serial number is stored at offset 8 of the boot
  62. * sector */
  63. printf("Serial number 0x%x\n",
  64. b->system_id[5] | (b->system_id[6]<<8) | (b->system_id[7]<<16));
  65. }
  66. printf("Media byte 0x%02x (%s)\n",b->media,get_media_descr(b->media));
  67. printf("%10d bytes per logical sector\n",GET_UNALIGNED_W(b->sector_size));
  68. printf("%10d bytes per cluster\n",fs->cluster_size);
  69. printf("%10d reserved sector%s\n",CF_LE_W(b->reserved),
  70. CF_LE_W(b->reserved) == 1 ? "" : "s");
  71. printf("First FAT starts at byte %llu (sector %llu)\n",
  72. (unsigned long long)fs->fat_start,
  73. (unsigned long long)fs->fat_start/lss);
  74. printf("%10d FATs, %d bit entries\n",b->fats,fs->fat_bits);
  75. printf("%10d bytes per FAT (= %u sectors)\n",fs->fat_size,
  76. fs->fat_size/lss);
  77. if (!fs->root_cluster) {
  78. printf("Root directory starts at byte %llu (sector %llu)\n",
  79. (unsigned long long)fs->root_start,
  80. (unsigned long long)fs->root_start/lss);
  81. printf("%10d root directory entries\n",fs->root_entries);
  82. }
  83. else {
  84. printf( "Root directory start at cluster %lu (arbitrary size)\n",
  85. fs->root_cluster);
  86. }
  87. printf("Data area starts at byte %llu (sector %llu)\n",
  88. (unsigned long long)fs->data_start,
  89. (unsigned long long)fs->data_start/lss);
  90. printf("%10lu data clusters (%llu bytes)\n",fs->clusters,
  91. (unsigned long long)fs->clusters*fs->cluster_size);
  92. printf("%u sectors/track, %u heads\n",CF_LE_W(b->secs_track),
  93. CF_LE_W(b->heads));
  94. printf("%10u hidden sectors\n",
  95. atari_format ?
  96. /* On Atari, the hidden field is only 16 bit wide and unused */
  97. (((unsigned char *)&b->hidden)[0] |
  98. ((unsigned char *)&b->hidden)[1] << 8) :
  99. CF_LE_L(b->hidden));
  100. sectors = GET_UNALIGNED_W( b->sectors );
  101. printf("%10u sectors total\n", sectors ? sectors : CF_LE_L(b->total_sect));
  102. }
  103. static void check_backup_boot(DOS_FS *fs, struct boot_sector *b, int lss)
  104. {
  105. struct boot_sector b2;
  106. if (!fs->backupboot_start) {
  107. printf( "There is no backup boot sector.\n" );
  108. if (CF_LE_W(b->reserved) < 3) {
  109. printf( "And there is no space for creating one!\n" );
  110. return;
  111. }
  112. if (interactive)
  113. printf( "1) Create one\n2) Do without a backup\n" );
  114. else printf( " Auto-creating backup boot block.\n" );
  115. if (!interactive || get_key("12","?") == '1') {
  116. int bbs;
  117. /* The usual place for the backup boot sector is sector 6. Choose
  118. * that or the last reserved sector. */
  119. if (CF_LE_W(b->reserved) >= 7 && CF_LE_W(b->info_sector) != 6)
  120. bbs = 6;
  121. else {
  122. bbs = CF_LE_W(b->reserved) - 1;
  123. if (bbs == CF_LE_W(b->info_sector))
  124. --bbs; /* this is never 0, as we checked reserved >= 3! */
  125. }
  126. fs->backupboot_start = bbs*lss;
  127. b->backup_boot = CT_LE_W(bbs);
  128. fs_write(fs->backupboot_start,sizeof(*b),b);
  129. fs_write((off_t)offsetof(struct boot_sector,backup_boot),
  130. sizeof(b->backup_boot),&b->backup_boot);
  131. printf( "Created backup of boot sector in sector %d\n", bbs );
  132. return;
  133. }
  134. else return;
  135. }
  136. fs_read(fs->backupboot_start,sizeof(b2),&b2);
  137. if (memcmp(b,&b2,sizeof(b2)) != 0) {
  138. /* there are any differences */
  139. __u8 *p, *q;
  140. int i, pos, first = 1;
  141. char buf[20];
  142. printf( "There are differences between boot sector and its backup.\n" );
  143. printf( "Differences: (offset:original/backup)\n " );
  144. pos = 2;
  145. for( p = (__u8 *)b, q = (__u8 *)&b2, i = 0; i < sizeof(b2);
  146. ++p, ++q, ++i ) {
  147. if (*p != *q) {
  148. sprintf( buf, "%s%u:%02x/%02x", first ? "" : ", ",
  149. (unsigned)(p-(__u8 *)b), *p, *q );
  150. if (pos + strlen(buf) > 78) printf( "\n " ), pos = 2;
  151. printf( "%s", buf );
  152. pos += strlen(buf);
  153. first = 0;
  154. }
  155. }
  156. printf( "\n" );
  157. if (interactive)
  158. printf( "1) Copy original to backup\n"
  159. "2) Copy backup to original\n"
  160. "3) No action\n" );
  161. else printf( " Not automatically fixing this.\n" );
  162. switch (interactive ? get_key("123","?") : '3') {
  163. case '1':
  164. fs_write(fs->backupboot_start,sizeof(*b),b);
  165. break;
  166. case '2':
  167. fs_write(0,sizeof(b2),&b2);
  168. break;
  169. default:
  170. break;
  171. }
  172. }
  173. }
  174. static void init_fsinfo(struct info_sector *i)
  175. {
  176. i->magic = CT_LE_L(0x41615252);
  177. i->signature = CT_LE_L(0x61417272);
  178. i->free_clusters = CT_LE_L(-1);
  179. i->next_cluster = CT_LE_L(2);
  180. i->boot_sign = CT_LE_W(0xaa55);
  181. }
  182. static void read_fsinfo(DOS_FS *fs, struct boot_sector *b,int lss)
  183. {
  184. struct info_sector i;
  185. if (!b->info_sector) {
  186. printf( "No FSINFO sector\n" );
  187. if (interactive)
  188. printf( "1) Create one\n2) Do without FSINFO\n" );
  189. else printf( " Not automatically creating it.\n" );
  190. if (interactive && get_key("12","?") == '1') {
  191. /* search for a free reserved sector (not boot sector and not
  192. * backup boot sector) */
  193. __u32 s;
  194. for( s = 1; s < CF_LE_W(b->reserved); ++s )
  195. if (s != CF_LE_W(b->backup_boot)) break;
  196. if (s > 0 && s < CF_LE_W(b->reserved)) {
  197. init_fsinfo(&i);
  198. fs_write((off_t)s*lss,sizeof(i),&i);
  199. b->info_sector = CT_LE_W(s);
  200. fs_write((off_t)offsetof(struct boot_sector,info_sector),
  201. sizeof(b->info_sector),&b->info_sector);
  202. if (fs->backupboot_start)
  203. fs_write(fs->backupboot_start+
  204. offsetof(struct boot_sector,info_sector),
  205. sizeof(b->info_sector),&b->info_sector);
  206. }
  207. else {
  208. printf( "No free reserved sector found -- "
  209. "no space for FSINFO sector!\n" );
  210. return;
  211. }
  212. }
  213. else return;
  214. }
  215. fs->fsinfo_start = CF_LE_W(b->info_sector)*lss;
  216. fs_read(fs->fsinfo_start,sizeof(i),&i);
  217. if (i.magic != CT_LE_L(0x41615252) ||
  218. i.signature != CT_LE_L(0x61417272) ||
  219. i.boot_sign != CT_LE_W(0xaa55)) {
  220. printf( "FSINFO sector has bad magic number(s):\n" );
  221. if (i.magic != CT_LE_L(0x41615252))
  222. printf( " Offset %llu: 0x%08x != expected 0x%08x\n",
  223. (unsigned long long)offsetof(struct info_sector,magic),
  224. CF_LE_L(i.magic),0x41615252);
  225. if (i.signature != CT_LE_L(0x61417272))
  226. printf( " Offset %llu: 0x%08x != expected 0x%08x\n",
  227. (unsigned long long)offsetof(struct info_sector,signature),
  228. CF_LE_L(i.signature),0x61417272);
  229. if (i.boot_sign != CT_LE_W(0xaa55))
  230. printf( " Offset %llu: 0x%04x != expected 0x%04x\n",
  231. (unsigned long long)offsetof(struct info_sector,boot_sign),
  232. CF_LE_W(i.boot_sign),0xaa55);
  233. if (interactive)
  234. printf( "1) Correct\n2) Don't correct (FSINFO invalid then)\n" );
  235. else printf( " Auto-correcting it.\n" );
  236. if (!interactive || get_key("12","?") == '1') {
  237. init_fsinfo(&i);
  238. fs_write(fs->fsinfo_start,sizeof(i),&i);
  239. }
  240. else fs->fsinfo_start = 0;
  241. }
  242. if (fs->fsinfo_start)
  243. fs->free_clusters = CF_LE_L(i.free_clusters);
  244. }
  245. void read_boot(DOS_FS *fs)
  246. {
  247. struct boot_sector b;
  248. unsigned total_sectors;
  249. unsigned short logical_sector_size, sectors;
  250. unsigned fat_length;
  251. off_t data_size;
  252. fs_read(0,sizeof(b),&b);
  253. logical_sector_size = GET_UNALIGNED_W(b.sector_size);
  254. if (!logical_sector_size) die("Logical sector size is zero.");
  255. fs->cluster_size = b.cluster_size*logical_sector_size;
  256. if (!fs->cluster_size) die("Cluster size is zero.");
  257. if (b.fats != 2 && b.fats != 1)
  258. die("Currently, only 1 or 2 FATs are supported, not %d.\n",b.fats);
  259. fs->nfats = b.fats;
  260. sectors = GET_UNALIGNED_W(b.sectors);
  261. total_sectors = sectors ? sectors : CF_LE_L(b.total_sect);
  262. if (verbose) printf("Checking we can access the last sector of the filesystem\n");
  263. /* Can't access last odd sector anyway, so round down */
  264. fs_test((off_t)((total_sectors & ~1)-1)*(off_t)logical_sector_size,
  265. logical_sector_size);
  266. fat_length = CF_LE_W(b.fat_length) ?
  267. CF_LE_W(b.fat_length) : CF_LE_L(b.fat32_length);
  268. fs->fat_start = (off_t)CF_LE_W(b.reserved)*logical_sector_size;
  269. fs->root_start = ((off_t)CF_LE_W(b.reserved)+b.fats*fat_length)*
  270. logical_sector_size;
  271. fs->root_entries = GET_UNALIGNED_W(b.dir_entries);
  272. fs->data_start = fs->root_start+ROUND_TO_MULTIPLE(fs->root_entries <<
  273. MSDOS_DIR_BITS,logical_sector_size);
  274. data_size = (off_t)total_sectors*logical_sector_size-fs->data_start;
  275. fs->clusters = data_size/fs->cluster_size;
  276. fs->root_cluster = 0; /* indicates standard, pre-FAT32 root dir */
  277. fs->fsinfo_start = 0; /* no FSINFO structure */
  278. fs->free_clusters = -1; /* unknown */
  279. if (!b.fat_length && b.fat32_length) {
  280. fs->fat_bits = 32;
  281. fs->root_cluster = CF_LE_L(b.root_cluster);
  282. if (!fs->root_cluster && fs->root_entries)
  283. /* M$ hasn't specified this, but it looks reasonable: If
  284. * root_cluster is 0 but there is a separate root dir
  285. * (root_entries != 0), we handle the root dir the old way. Give a
  286. * warning, but convertig to a root dir in a cluster chain seems
  287. * to complex for now... */
  288. printf( "Warning: FAT32 root dir not in cluster chain! "
  289. "Compability mode...\n" );
  290. else if (!fs->root_cluster && !fs->root_entries)
  291. die("No root directory!");
  292. else if (fs->root_cluster && fs->root_entries)
  293. printf( "Warning: FAT32 root dir is in a cluster chain, but "
  294. "a separate root dir\n"
  295. " area is defined. Cannot fix this easily.\n" );
  296. fs->backupboot_start = CF_LE_W(b.backup_boot)*logical_sector_size;
  297. check_backup_boot(fs,&b,logical_sector_size);
  298. read_fsinfo(fs,&b,logical_sector_size);
  299. }
  300. else if (!atari_format) {
  301. /* On real MS-DOS, a 16 bit FAT is used whenever there would be too
  302. * much clusers otherwise. */
  303. fs->fat_bits = (fs->clusters > MSDOS_FAT12) ? 16 : 12;
  304. }
  305. else {
  306. /* On Atari, things are more difficult: GEMDOS always uses 12bit FATs
  307. * on floppies, and always 16 bit on harddisks. */
  308. fs->fat_bits = 16; /* assume 16 bit FAT for now */
  309. /* If more clusters than fat entries in 16-bit fat, we assume
  310. * it's a real MSDOS FS with 12-bit fat. */
  311. if (fs->clusters+2 > fat_length*logical_sector_size*8/16 ||
  312. /* if it's a floppy disk --> 12bit fat */
  313. device_no == 2 ||
  314. /* if it's a ramdisk or loopback device and has one of the usual
  315. * floppy sizes -> 12bit FAT */
  316. ((device_no == 1 || device_no == 7) &&
  317. (total_sectors == 720 || total_sectors == 1440 ||
  318. total_sectors == 2880)))
  319. fs->fat_bits = 12;
  320. }
  321. /* On FAT32, the high 4 bits of a FAT entry are reserved */
  322. fs->eff_fat_bits = (fs->fat_bits == 32) ? 28 : fs->fat_bits;
  323. fs->fat_size = fat_length*logical_sector_size;
  324. fs->label = calloc(12, sizeof (__u8));
  325. if (fs->fat_bits == 12 || fs->fat_bits == 16) {
  326. struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
  327. if (b16->extended_sig == 0x29)
  328. memmove(fs->label, b16->label, 11);
  329. else
  330. fs->label = NULL;
  331. } else if (fs->fat_bits == 32) {
  332. if (b.extended_sig == 0x29)
  333. memmove(fs->label, &b.label, 11);
  334. else
  335. fs->label = NULL;
  336. }
  337. if (fs->clusters > ((unsigned long long)fs->fat_size*8/fs->fat_bits)-2)
  338. die("File system has %d clusters but only space for %d FAT entries.",
  339. fs->clusters,((unsigned long long)fs->fat_size*8/fs->fat_bits)-2);
  340. if (!fs->root_entries && !fs->root_cluster)
  341. die("Root directory has zero size.");
  342. if (fs->root_entries & (MSDOS_DPS-1))
  343. die("Root directory (%d entries) doesn't span an integral number of "
  344. "sectors.",fs->root_entries);
  345. if (logical_sector_size & (SECTOR_SIZE-1))
  346. die("Logical sector size (%d bytes) is not a multiple of the physical "
  347. "sector size.",logical_sector_size);
  348. #if 0 /* linux kernel doesn't check that either */
  349. /* ++roman: On Atari, these two fields are often left uninitialized */
  350. if (!atari_format && (!b.secs_track || !b.heads))
  351. die("Invalid disk format in boot sector.");
  352. #endif
  353. if (verbose) dump_boot(fs,&b,logical_sector_size);
  354. }
  355. void write_label(DOS_FS *fs, char *label)
  356. {
  357. struct boot_sector b;
  358. struct boot_sector_16 *b16 = (struct boot_sector_16 *)&b;
  359. int l = strlen(label);
  360. while (l < 11)
  361. label[l++] = ' ';
  362. fs_read(0, sizeof(b), &b);
  363. if (fs->fat_bits == 12 || fs->fat_bits == 16) {
  364. if (b16->extended_sig != 0x29) {
  365. b16->extended_sig = 0x29;
  366. b16->serial = 0;
  367. memmove(b16->fs_type, fs->fat_bits == 12 ?"FAT12 ":"FAT16 ", 8);
  368. }
  369. memmove(b16->label, label, 11);
  370. } else if (fs->fat_bits == 32) {
  371. if (b.extended_sig != 0x29) {
  372. b.extended_sig = 0x29;
  373. b.serial = 0;
  374. memmove(b.fs_type, "FAT32 ", 8);
  375. }
  376. memmove(b.label, label, 11);
  377. }
  378. fs_write(0, sizeof(b), &b);
  379. if (fs->fat_bits == 32 && fs->backupboot_start)
  380. fs_write(fs->backupboot_start, sizeof(b), &b);
  381. }
  382. /* Local Variables: */
  383. /* tab-width: 8 */
  384. /* End: */