158d4c6c35633437182289e3d226d156d31d3e801San Mehat/* 258d4c6c35633437182289e3d226d156d31d3e801San Mehat * Copyright (C) 1995, 1997 Wolfgang Solfrank 358d4c6c35633437182289e3d226d156d31d3e801San Mehat * Copyright (c) 1995 Martin Husemann 458d4c6c35633437182289e3d226d156d31d3e801San Mehat * 558d4c6c35633437182289e3d226d156d31d3e801San Mehat * Redistribution and use in source and binary forms, with or without 658d4c6c35633437182289e3d226d156d31d3e801San Mehat * modification, are permitted provided that the following conditions 758d4c6c35633437182289e3d226d156d31d3e801San Mehat * are met: 858d4c6c35633437182289e3d226d156d31d3e801San Mehat * 1. Redistributions of source code must retain the above copyright 958d4c6c35633437182289e3d226d156d31d3e801San Mehat * notice, this list of conditions and the following disclaimer. 1058d4c6c35633437182289e3d226d156d31d3e801San Mehat * 2. Redistributions in binary form must reproduce the above copyright 1158d4c6c35633437182289e3d226d156d31d3e801San Mehat * notice, this list of conditions and the following disclaimer in the 1258d4c6c35633437182289e3d226d156d31d3e801San Mehat * documentation and/or other materials provided with the distribution. 1358d4c6c35633437182289e3d226d156d31d3e801San Mehat * 3. All advertising materials mentioning features or use of this software 1458d4c6c35633437182289e3d226d156d31d3e801San Mehat * must display the following acknowledgement: 1558d4c6c35633437182289e3d226d156d31d3e801San Mehat * This product includes software developed by Martin Husemann 1658d4c6c35633437182289e3d226d156d31d3e801San Mehat * and Wolfgang Solfrank. 1758d4c6c35633437182289e3d226d156d31d3e801San Mehat * 4. Neither the name of the University nor the names of its contributors 1858d4c6c35633437182289e3d226d156d31d3e801San Mehat * may be used to endorse or promote products derived from this software 1958d4c6c35633437182289e3d226d156d31d3e801San Mehat * without specific prior written permission. 2058d4c6c35633437182289e3d226d156d31d3e801San Mehat * 2158d4c6c35633437182289e3d226d156d31d3e801San Mehat * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 2258d4c6c35633437182289e3d226d156d31d3e801San Mehat * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2358d4c6c35633437182289e3d226d156d31d3e801San Mehat * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2458d4c6c35633437182289e3d226d156d31d3e801San Mehat * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2558d4c6c35633437182289e3d226d156d31d3e801San Mehat * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2658d4c6c35633437182289e3d226d156d31d3e801San Mehat * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2758d4c6c35633437182289e3d226d156d31d3e801San Mehat * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2858d4c6c35633437182289e3d226d156d31d3e801San Mehat * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2958d4c6c35633437182289e3d226d156d31d3e801San Mehat * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3058d4c6c35633437182289e3d226d156d31d3e801San Mehat * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3158d4c6c35633437182289e3d226d156d31d3e801San Mehat */ 3258d4c6c35633437182289e3d226d156d31d3e801San Mehat 3358d4c6c35633437182289e3d226d156d31d3e801San Mehat 3458d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <sys/cdefs.h> 3558d4c6c35633437182289e3d226d156d31d3e801San Mehat#ifndef lint 3658d4c6c35633437182289e3d226d156d31d3e801San Mehat__RCSID("$NetBSD: boot.c,v 1.9 2003/07/24 19:25:46 ws Exp $"); 3758d4c6c35633437182289e3d226d156d31d3e801San Mehatstatic const char rcsid[] = 3858d4c6c35633437182289e3d226d156d31d3e801San Mehat "$FreeBSD: src/sbin/fsck_msdosfs/boot.c,v 1.4.28.1 2009/04/15 03:14:26 kensmith Exp $"; 3958d4c6c35633437182289e3d226d156d31d3e801San Mehat#endif /* not lint */ 4058d4c6c35633437182289e3d226d156d31d3e801San Mehat 4158d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <stdlib.h> 4258d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <string.h> 4358d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <ctype.h> 4458d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <stdio.h> 4558d4c6c35633437182289e3d226d156d31d3e801San Mehat#include <unistd.h> 4658d4c6c35633437182289e3d226d156d31d3e801San Mehat 4758d4c6c35633437182289e3d226d156d31d3e801San Mehat#include "ext.h" 4858d4c6c35633437182289e3d226d156d31d3e801San Mehat#include "fsutil.h" 4958d4c6c35633437182289e3d226d156d31d3e801San Mehat 5058d4c6c35633437182289e3d226d156d31d3e801San Mehatint 5158d4c6c35633437182289e3d226d156d31d3e801San Mehatreadboot(dosfs, boot) 5258d4c6c35633437182289e3d226d156d31d3e801San Mehat int dosfs; 5358d4c6c35633437182289e3d226d156d31d3e801San Mehat struct bootblock *boot; 5458d4c6c35633437182289e3d226d156d31d3e801San Mehat{ 5558d4c6c35633437182289e3d226d156d31d3e801San Mehat u_char block[DOSBOOTBLOCKSIZE]; 5658d4c6c35633437182289e3d226d156d31d3e801San Mehat u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; 5758d4c6c35633437182289e3d226d156d31d3e801San Mehat u_char backup[DOSBOOTBLOCKSIZE]; 5858d4c6c35633437182289e3d226d156d31d3e801San Mehat int ret = FSOK; 5958d4c6c35633437182289e3d226d156d31d3e801San Mehat 6058d4c6c35633437182289e3d226d156d31d3e801San Mehat if (read(dosfs, block, sizeof block) < sizeof block) { 6158d4c6c35633437182289e3d226d156d31d3e801San Mehat perror("could not read boot block"); 6258d4c6c35633437182289e3d226d156d31d3e801San Mehat exit(2); 6358d4c6c35633437182289e3d226d156d31d3e801San Mehat } 6458d4c6c35633437182289e3d226d156d31d3e801San Mehat 6558d4c6c35633437182289e3d226d156d31d3e801San Mehat if (block[510] != 0x55 || block[511] != 0xaa) { 6658d4c6c35633437182289e3d226d156d31d3e801San Mehat pfatal("Invalid signature in boot block: %02x%02x", block[511], block[510]); 6758d4c6c35633437182289e3d226d156d31d3e801San Mehat exit(2); 6858d4c6c35633437182289e3d226d156d31d3e801San Mehat } 6958d4c6c35633437182289e3d226d156d31d3e801San Mehat 7058d4c6c35633437182289e3d226d156d31d3e801San Mehat memset(boot, 0, sizeof *boot); 7158d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->ValidFat = -1; 7258d4c6c35633437182289e3d226d156d31d3e801San Mehat 7358d4c6c35633437182289e3d226d156d31d3e801San Mehat /* decode bios parameter block */ 7458d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->BytesPerSec = block[11] + (block[12] << 8); 7558d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->SecPerClust = block[13]; 7658d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->ResSectors = block[14] + (block[15] << 8); 7758d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->FATs = block[16]; 7858d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->RootDirEnts = block[17] + (block[18] << 8); 7958d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->Sectors = block[19] + (block[20] << 8); 8058d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->Media = block[21]; 8158d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->FATsmall = block[22] + (block[23] << 8); 8258d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->SecPerTrack = block[24] + (block[25] << 8); 8358d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->Heads = block[26] + (block[27] << 8); 8458d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->HiddenSecs = block[28] + (block[29] << 8) + (block[30] << 16) + (block[31] << 24); 8558d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->HugeSectors = block[32] + (block[33] << 8) + (block[34] << 16) + (block[35] << 24); 8658d4c6c35633437182289e3d226d156d31d3e801San Mehat 8758d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->FATsecs = boot->FATsmall; 8858d4c6c35633437182289e3d226d156d31d3e801San Mehat 8958d4c6c35633437182289e3d226d156d31d3e801San Mehat if (!boot->RootDirEnts) 9058d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->flags |= FAT32; 9158d4c6c35633437182289e3d226d156d31d3e801San Mehat if (boot->flags & FAT32) { 9258d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->FATsecs = block[36] + (block[37] << 8) 9358d4c6c35633437182289e3d226d156d31d3e801San Mehat + (block[38] << 16) + (block[39] << 24); 9458d4c6c35633437182289e3d226d156d31d3e801San Mehat if (block[40] & 0x80) 9558d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->ValidFat = block[40] & 0x0f; 9658d4c6c35633437182289e3d226d156d31d3e801San Mehat 9758d4c6c35633437182289e3d226d156d31d3e801San Mehat /* check version number: */ 9858d4c6c35633437182289e3d226d156d31d3e801San Mehat if (block[42] || block[43]) { 9958d4c6c35633437182289e3d226d156d31d3e801San Mehat /* Correct? XXX */ 10058d4c6c35633437182289e3d226d156d31d3e801San Mehat pfatal("Unknown file system version: %x.%x", 10158d4c6c35633437182289e3d226d156d31d3e801San Mehat block[43], block[42]); 10258d4c6c35633437182289e3d226d156d31d3e801San Mehat exit(2); 10358d4c6c35633437182289e3d226d156d31d3e801San Mehat } 10458d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->RootCl = block[44] + (block[45] << 8) 10558d4c6c35633437182289e3d226d156d31d3e801San Mehat + (block[46] << 16) + (block[47] << 24); 10658d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->FSInfo = block[48] + (block[49] << 8); 10758d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->Backup = block[50] + (block[51] << 8); 10858d4c6c35633437182289e3d226d156d31d3e801San Mehat 10958d4c6c35633437182289e3d226d156d31d3e801San Mehat if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) 11058d4c6c35633437182289e3d226d156d31d3e801San Mehat != boot->FSInfo * boot->BytesPerSec 11158d4c6c35633437182289e3d226d156d31d3e801San Mehat || read(dosfs, fsinfo, sizeof fsinfo) 11258d4c6c35633437182289e3d226d156d31d3e801San Mehat != sizeof fsinfo) { 11358d4c6c35633437182289e3d226d156d31d3e801San Mehat perror("could not read fsinfo block"); 11458d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 11558d4c6c35633437182289e3d226d156d31d3e801San Mehat } 11658d4c6c35633437182289e3d226d156d31d3e801San Mehat if (memcmp(fsinfo, "RRaA", 4) 11758d4c6c35633437182289e3d226d156d31d3e801San Mehat || memcmp(fsinfo + 0x1e4, "rrAa", 4) 11858d4c6c35633437182289e3d226d156d31d3e801San Mehat || fsinfo[0x1fc] 11958d4c6c35633437182289e3d226d156d31d3e801San Mehat || fsinfo[0x1fd] 12058d4c6c35633437182289e3d226d156d31d3e801San Mehat || fsinfo[0x1fe] != 0x55 12158d4c6c35633437182289e3d226d156d31d3e801San Mehat || fsinfo[0x1ff] != 0xaa 12258d4c6c35633437182289e3d226d156d31d3e801San Mehat || fsinfo[0x3fc] 12358d4c6c35633437182289e3d226d156d31d3e801San Mehat || fsinfo[0x3fd] 12458d4c6c35633437182289e3d226d156d31d3e801San Mehat || fsinfo[0x3fe] != 0x55 12558d4c6c35633437182289e3d226d156d31d3e801San Mehat || fsinfo[0x3ff] != 0xaa) { 12658d4c6c35633437182289e3d226d156d31d3e801San Mehat pwarn("Invalid signature in fsinfo block\n"); 12758d4c6c35633437182289e3d226d156d31d3e801San Mehat if (ask(1, "fix")) { 12858d4c6c35633437182289e3d226d156d31d3e801San Mehat memcpy(fsinfo, "RRaA", 4); 12958d4c6c35633437182289e3d226d156d31d3e801San Mehat memcpy(fsinfo + 0x1e4, "rrAa", 4); 13058d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1fc] = fsinfo[0x1fd] = 0; 13158d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1fe] = 0x55; 13258d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1ff] = 0xaa; 13358d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x3fc] = fsinfo[0x3fd] = 0; 13458d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x3fe] = 0x55; 13558d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x3ff] = 0xaa; 13658d4c6c35633437182289e3d226d156d31d3e801San Mehat if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) 13758d4c6c35633437182289e3d226d156d31d3e801San Mehat != boot->FSInfo * boot->BytesPerSec 13858d4c6c35633437182289e3d226d156d31d3e801San Mehat || write(dosfs, fsinfo, sizeof fsinfo) 13958d4c6c35633437182289e3d226d156d31d3e801San Mehat != sizeof fsinfo) { 14058d4c6c35633437182289e3d226d156d31d3e801San Mehat perror("Unable to write FSInfo"); 14158d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 14258d4c6c35633437182289e3d226d156d31d3e801San Mehat } 14358d4c6c35633437182289e3d226d156d31d3e801San Mehat ret = FSBOOTMOD; 14458d4c6c35633437182289e3d226d156d31d3e801San Mehat } else 14558d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->FSInfo = 0; 14658d4c6c35633437182289e3d226d156d31d3e801San Mehat } 14758d4c6c35633437182289e3d226d156d31d3e801San Mehat if (boot->FSInfo) { 14858d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->FSFree = fsinfo[0x1e8] + (fsinfo[0x1e9] << 8) 14958d4c6c35633437182289e3d226d156d31d3e801San Mehat + (fsinfo[0x1ea] << 16) 15058d4c6c35633437182289e3d226d156d31d3e801San Mehat + (fsinfo[0x1eb] << 24); 15158d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->FSNext = fsinfo[0x1ec] + (fsinfo[0x1ed] << 8) 15258d4c6c35633437182289e3d226d156d31d3e801San Mehat + (fsinfo[0x1ee] << 16) 15358d4c6c35633437182289e3d226d156d31d3e801San Mehat + (fsinfo[0x1ef] << 24); 15458d4c6c35633437182289e3d226d156d31d3e801San Mehat } 15558d4c6c35633437182289e3d226d156d31d3e801San Mehat 15658d4c6c35633437182289e3d226d156d31d3e801San Mehat if (lseek(dosfs, boot->Backup * boot->BytesPerSec, SEEK_SET) 15758d4c6c35633437182289e3d226d156d31d3e801San Mehat != boot->Backup * boot->BytesPerSec 15858d4c6c35633437182289e3d226d156d31d3e801San Mehat || read(dosfs, backup, sizeof backup) != sizeof backup) { 15958d4c6c35633437182289e3d226d156d31d3e801San Mehat perror("could not read backup bootblock"); 16058d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 16158d4c6c35633437182289e3d226d156d31d3e801San Mehat } 16258d4c6c35633437182289e3d226d156d31d3e801San Mehat backup[65] = block[65]; /* XXX */ 16358d4c6c35633437182289e3d226d156d31d3e801San Mehat if (memcmp(block + 11, backup + 11, 79)) { 164b47b16353f3db228711dded9f7c975b820059ddcSan Mehat char tmp[255]; 165b47b16353f3db228711dded9f7c975b820059ddcSan Mehat int i; 166b47b16353f3db228711dded9f7c975b820059ddcSan Mehat 167b47b16353f3db228711dded9f7c975b820059ddcSan Mehat /* 168b47b16353f3db228711dded9f7c975b820059ddcSan Mehat * For now, lets not bail out if they don't match 169b47b16353f3db228711dded9f7c975b820059ddcSan Mehat * It seems a lot of sdcards are formatted with 170b47b16353f3db228711dded9f7c975b820059ddcSan Mehat * the backup either empty or containing garbage. 171b47b16353f3db228711dded9f7c975b820059ddcSan Mehat */ 172b47b16353f3db228711dded9f7c975b820059ddcSan Mehat 173b47b16353f3db228711dded9f7c975b820059ddcSan Mehat pwarn("Primary/Backup bootblock miscompare\n"); 174b47b16353f3db228711dded9f7c975b820059ddcSan Mehat 175b47b16353f3db228711dded9f7c975b820059ddcSan Mehat strcpy(tmp, ""); 176b47b16353f3db228711dded9f7c975b820059ddcSan Mehat pwarn("Primary:\n"); 177b47b16353f3db228711dded9f7c975b820059ddcSan Mehat for (i = 0; i < 79; i++) { 178b47b16353f3db228711dded9f7c975b820059ddcSan Mehat char tmp2[16]; 179b47b16353f3db228711dded9f7c975b820059ddcSan Mehat snprintf(tmp2, sizeof(tmp2), "%.2x ", block[11 + i]); 180b47b16353f3db228711dded9f7c975b820059ddcSan Mehat strcat(tmp, tmp2); 181b47b16353f3db228711dded9f7c975b820059ddcSan Mehat } 182b47b16353f3db228711dded9f7c975b820059ddcSan Mehat pwarn("%s\n", tmp); 183b47b16353f3db228711dded9f7c975b820059ddcSan Mehat 184b47b16353f3db228711dded9f7c975b820059ddcSan Mehat strcpy(tmp, ""); 185b47b16353f3db228711dded9f7c975b820059ddcSan Mehat pwarn("Backup:\n"); 186b47b16353f3db228711dded9f7c975b820059ddcSan Mehat for (i = 0; i < 79; i++) { 187b47b16353f3db228711dded9f7c975b820059ddcSan Mehat char tmp2[16]; 188b47b16353f3db228711dded9f7c975b820059ddcSan Mehat snprintf(tmp2, sizeof(tmp2), "%.2x ", backup[11 + i]); 189b47b16353f3db228711dded9f7c975b820059ddcSan Mehat strcat(tmp, tmp2); 190b47b16353f3db228711dded9f7c975b820059ddcSan Mehat } 191b47b16353f3db228711dded9f7c975b820059ddcSan Mehat pwarn("%s\n", tmp); 19258d4c6c35633437182289e3d226d156d31d3e801San Mehat } 19358d4c6c35633437182289e3d226d156d31d3e801San Mehat /* Check backup FSInfo? XXX */ 19458d4c6c35633437182289e3d226d156d31d3e801San Mehat } 19558d4c6c35633437182289e3d226d156d31d3e801San Mehat 19658d4c6c35633437182289e3d226d156d31d3e801San Mehat if (boot->BytesPerSec % DOSBOOTBLOCKSIZE != 0) { 19758d4c6c35633437182289e3d226d156d31d3e801San Mehat pfatal("Invalid sector size: %u", boot->BytesPerSec); 19858d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 19958d4c6c35633437182289e3d226d156d31d3e801San Mehat } 20058d4c6c35633437182289e3d226d156d31d3e801San Mehat if (boot->SecPerClust == 0) { 20158d4c6c35633437182289e3d226d156d31d3e801San Mehat pfatal("Invalid cluster size: %u", boot->SecPerClust); 20258d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 20358d4c6c35633437182289e3d226d156d31d3e801San Mehat } 204fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen if (boot->BytesPerSec == 0) { 205fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen pfatal("Invalid sector size: %u", boot->BytesPerSec); 206fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen return FSFATAL; 207fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen } 2086c29bbe8d58e6fe8755935a04166ecf82ff31f47Sebastian Rasmussen if (boot->FATs == 0) { 2096c29bbe8d58e6fe8755935a04166ecf82ff31f47Sebastian Rasmussen pfatal("Invalid number of FATs: %u", boot->FATs); 2106c29bbe8d58e6fe8755935a04166ecf82ff31f47Sebastian Rasmussen return FSFATAL; 2116c29bbe8d58e6fe8755935a04166ecf82ff31f47Sebastian Rasmussen } 21258d4c6c35633437182289e3d226d156d31d3e801San Mehat if (boot->Sectors) { 21358d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->HugeSectors = 0; 21458d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumSectors = boot->Sectors; 21558d4c6c35633437182289e3d226d156d31d3e801San Mehat } else 21658d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumSectors = boot->HugeSectors; 217fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen 218fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen boot->ClusterOffset = (boot->RootDirEnts * 32 + boot->BytesPerSec - 1) 219fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen / boot->BytesPerSec 220fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen + boot->ResSectors 221fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen + boot->FATs * boot->FATsecs 222fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen - CLUST_FIRST * boot->SecPerClust; 223fe7400ddb5e99a790cd3977f9e5151d8ea929a14Sebastian Rasmussen 22458d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumClusters = (boot->NumSectors - boot->ClusterOffset) / boot->SecPerClust; 22558d4c6c35633437182289e3d226d156d31d3e801San Mehat 22658d4c6c35633437182289e3d226d156d31d3e801San Mehat if (boot->flags&FAT32) 22758d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->ClustMask = CLUST32_MASK; 22858d4c6c35633437182289e3d226d156d31d3e801San Mehat else if (boot->NumClusters < (CLUST_RSRVD&CLUST12_MASK)) 22958d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->ClustMask = CLUST12_MASK; 23058d4c6c35633437182289e3d226d156d31d3e801San Mehat else if (boot->NumClusters < (CLUST_RSRVD&CLUST16_MASK)) 23158d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->ClustMask = CLUST16_MASK; 23258d4c6c35633437182289e3d226d156d31d3e801San Mehat else { 23358d4c6c35633437182289e3d226d156d31d3e801San Mehat pfatal("Filesystem too big (%u clusters) for non-FAT32 partition", 23458d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumClusters); 23558d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 23658d4c6c35633437182289e3d226d156d31d3e801San Mehat } 23758d4c6c35633437182289e3d226d156d31d3e801San Mehat 23858d4c6c35633437182289e3d226d156d31d3e801San Mehat switch (boot->ClustMask) { 23958d4c6c35633437182289e3d226d156d31d3e801San Mehat case CLUST32_MASK: 24058d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec) / 4; 24158d4c6c35633437182289e3d226d156d31d3e801San Mehat break; 24258d4c6c35633437182289e3d226d156d31d3e801San Mehat case CLUST16_MASK: 24358d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec) / 2; 24458d4c6c35633437182289e3d226d156d31d3e801San Mehat break; 24558d4c6c35633437182289e3d226d156d31d3e801San Mehat default: 24658d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumFatEntries = (boot->FATsecs * boot->BytesPerSec * 2) / 3; 24758d4c6c35633437182289e3d226d156d31d3e801San Mehat break; 24858d4c6c35633437182289e3d226d156d31d3e801San Mehat } 24958d4c6c35633437182289e3d226d156d31d3e801San Mehat 25058d4c6c35633437182289e3d226d156d31d3e801San Mehat if (boot->NumFatEntries < boot->NumClusters) { 25158d4c6c35633437182289e3d226d156d31d3e801San Mehat pfatal("FAT size too small, %u entries won't fit into %u sectors\n", 25258d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumClusters, boot->FATsecs); 25358d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 25458d4c6c35633437182289e3d226d156d31d3e801San Mehat } 25558d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->ClusterSize = boot->BytesPerSec * boot->SecPerClust; 25658d4c6c35633437182289e3d226d156d31d3e801San Mehat 25758d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumFiles = 1; 25858d4c6c35633437182289e3d226d156d31d3e801San Mehat boot->NumFree = 0; 25958d4c6c35633437182289e3d226d156d31d3e801San Mehat 26058d4c6c35633437182289e3d226d156d31d3e801San Mehat return ret; 26158d4c6c35633437182289e3d226d156d31d3e801San Mehat} 26258d4c6c35633437182289e3d226d156d31d3e801San Mehat 26358d4c6c35633437182289e3d226d156d31d3e801San Mehatint 26458d4c6c35633437182289e3d226d156d31d3e801San Mehatwritefsinfo(dosfs, boot) 26558d4c6c35633437182289e3d226d156d31d3e801San Mehat int dosfs; 26658d4c6c35633437182289e3d226d156d31d3e801San Mehat struct bootblock *boot; 26758d4c6c35633437182289e3d226d156d31d3e801San Mehat{ 26858d4c6c35633437182289e3d226d156d31d3e801San Mehat u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; 26958d4c6c35633437182289e3d226d156d31d3e801San Mehat 27058d4c6c35633437182289e3d226d156d31d3e801San Mehat if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) 27158d4c6c35633437182289e3d226d156d31d3e801San Mehat != boot->FSInfo * boot->BytesPerSec 27258d4c6c35633437182289e3d226d156d31d3e801San Mehat || read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { 27358d4c6c35633437182289e3d226d156d31d3e801San Mehat perror("could not read fsinfo block"); 27458d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 27558d4c6c35633437182289e3d226d156d31d3e801San Mehat } 27658d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1e8] = (u_char)boot->FSFree; 27758d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8); 27858d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16); 27958d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1eb] = (u_char)(boot->FSFree >> 24); 28058d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1ec] = (u_char)boot->FSNext; 28158d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8); 28258d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16); 28358d4c6c35633437182289e3d226d156d31d3e801San Mehat fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24); 28458d4c6c35633437182289e3d226d156d31d3e801San Mehat if (lseek(dosfs, boot->FSInfo * boot->BytesPerSec, SEEK_SET) 28558d4c6c35633437182289e3d226d156d31d3e801San Mehat != boot->FSInfo * boot->BytesPerSec 28658d4c6c35633437182289e3d226d156d31d3e801San Mehat || write(dosfs, fsinfo, sizeof fsinfo) 28758d4c6c35633437182289e3d226d156d31d3e801San Mehat != sizeof fsinfo) { 28858d4c6c35633437182289e3d226d156d31d3e801San Mehat perror("Unable to write FSInfo"); 28958d4c6c35633437182289e3d226d156d31d3e801San Mehat return FSFATAL; 29058d4c6c35633437182289e3d226d156d31d3e801San Mehat } 29158d4c6c35633437182289e3d226d156d31d3e801San Mehat /* 29258d4c6c35633437182289e3d226d156d31d3e801San Mehat * Technically, we should return FSBOOTMOD here. 29358d4c6c35633437182289e3d226d156d31d3e801San Mehat * 29458d4c6c35633437182289e3d226d156d31d3e801San Mehat * However, since Win95 OSR2 (the first M$ OS that has 29558d4c6c35633437182289e3d226d156d31d3e801San Mehat * support for FAT32) doesn't maintain the FSINFO block 29658d4c6c35633437182289e3d226d156d31d3e801San Mehat * correctly, it has to be fixed pretty often. 29758d4c6c35633437182289e3d226d156d31d3e801San Mehat * 29858d4c6c35633437182289e3d226d156d31d3e801San Mehat * Therefor, we handle the FSINFO block only informally, 29958d4c6c35633437182289e3d226d156d31d3e801San Mehat * fixing it if necessary, but otherwise ignoring the 30058d4c6c35633437182289e3d226d156d31d3e801San Mehat * fact that it was incorrect. 30158d4c6c35633437182289e3d226d156d31d3e801San Mehat */ 30258d4c6c35633437182289e3d226d156d31d3e801San Mehat return 0; 30358d4c6c35633437182289e3d226d156d31d3e801San Mehat} 304