1/** 2 * bootsect.c - Boot sector handling code. Originated from the Linux-NTFS project. 3 * 4 * Copyright (c) 2000-2006 Anton Altaparmakov 5 * Copyright (c) 2003-2008 Szabolcs Szakacsits 6 * Copyright (c) 2005 Yura Pakhuchiy 7 * 8 * This program/include file is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as published 10 * by the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program/include file is distributed in the hope that it will be 14 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15 * of 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 (in the main directory of the NTFS-3G 20 * distribution in the file COPYING); if not, write to the Free Software 21 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#ifdef HAVE_STDIO_H 29#include <stdio.h> 30#endif 31#ifdef HAVE_STDLIB_H 32#include <stdlib.h> 33#endif 34#ifdef HAVE_STRING_H 35#include <string.h> 36#endif 37#ifdef HAVE_ERRNO_H 38#include <errno.h> 39#endif 40 41#include "compat.h" 42#include "bootsect.h" 43#include "debug.h" 44#include "logging.h" 45 46/** 47 * ntfs_boot_sector_is_ntfs - check if buffer contains a valid ntfs boot sector 48 * @b: buffer containing putative boot sector to analyze 49 * @silent: if zero, output progress messages to stderr 50 * 51 * Check if the buffer @b contains a valid ntfs boot sector. The buffer @b 52 * must be at least 512 bytes in size. 53 * 54 * If @silent is zero, output progress messages to stderr. Otherwise, do not 55 * output any messages (except when configured with --enable-debug in which 56 * case warning/debug messages may be displayed). 57 * 58 * Return TRUE if @b contains a valid ntfs boot sector and FALSE if not. 59 */ 60BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b) 61{ 62 u32 i; 63 BOOL ret = FALSE; 64 65 ntfs_log_debug("Beginning bootsector check.\n"); 66 67 ntfs_log_debug("Checking OEMid, NTFS signature.\n"); 68 if (b->oem_id != cpu_to_le64(0x202020205346544eULL)) { /* "NTFS " */ 69 ntfs_log_error("NTFS signature is missing.\n"); 70 goto not_ntfs; 71 } 72 73 ntfs_log_debug("Checking bytes per sector.\n"); 74 if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 || 75 le16_to_cpu(b->bpb.bytes_per_sector) > 4096) { 76 ntfs_log_error("Unexpected bytes per sector value (%d).\n", 77 le16_to_cpu(b->bpb.bytes_per_sector)); 78 goto not_ntfs; 79 } 80 81 ntfs_log_debug("Checking sectors per cluster.\n"); 82 switch (b->bpb.sectors_per_cluster) { 83 case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: 84 break; 85 default: 86 ntfs_log_error("Unexpected sectors per cluster value (%d).\n", 87 b->bpb.sectors_per_cluster); 88 goto not_ntfs; 89 } 90 91 ntfs_log_debug("Checking cluster size.\n"); 92 i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) * 93 b->bpb.sectors_per_cluster; 94 if (i > 65536) { 95 ntfs_log_error("Unexpected cluster size (%d).\n", i); 96 goto not_ntfs; 97 } 98 99 ntfs_log_debug("Checking reserved fields are zero.\n"); 100 if (le16_to_cpu(b->bpb.reserved_sectors) || 101 le16_to_cpu(b->bpb.root_entries) || 102 le16_to_cpu(b->bpb.sectors) || 103 le16_to_cpu(b->bpb.sectors_per_fat) || 104 le32_to_cpu(b->bpb.large_sectors) || 105 b->bpb.fats) { 106 ntfs_log_error("Reserved fields aren't zero " 107 "(%d, %d, %d, %d, %d, %d).\n", 108 le16_to_cpu(b->bpb.reserved_sectors), 109 le16_to_cpu(b->bpb.root_entries), 110 le16_to_cpu(b->bpb.sectors), 111 le16_to_cpu(b->bpb.sectors_per_fat), 112 le32_to_cpu(b->bpb.large_sectors), 113 b->bpb.fats); 114 goto not_ntfs; 115 } 116 117 ntfs_log_debug("Checking clusters per mft record.\n"); 118 if ((u8)b->clusters_per_mft_record < 0xe1 || 119 (u8)b->clusters_per_mft_record > 0xf7) { 120 switch (b->clusters_per_mft_record) { 121 case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: 122 break; 123 default: 124 ntfs_log_error("Unexpected clusters per mft record " 125 "(%d).\n", b->clusters_per_mft_record); 126 goto not_ntfs; 127 } 128 } 129 130 ntfs_log_debug("Checking clusters per index block.\n"); 131 if ((u8)b->clusters_per_index_record < 0xe1 || 132 (u8)b->clusters_per_index_record > 0xf7) { 133 switch (b->clusters_per_index_record) { 134 case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: 135 break; 136 default: 137 ntfs_log_error("Unexpected clusters per index record " 138 "(%d).\n", b->clusters_per_index_record); 139 goto not_ntfs; 140 } 141 } 142 143 if (b->end_of_sector_marker != cpu_to_le16(0xaa55)) 144 ntfs_log_debug("Warning: Bootsector has invalid end of sector " 145 "marker.\n"); 146 147 ntfs_log_debug("Bootsector check completed successfully.\n"); 148 149 ret = TRUE; 150not_ntfs: 151 return ret; 152} 153 154static const char *last_sector_error = 155"HINTS: Either the volume is a RAID/LDM but it wasn't setup yet,\n" 156" or it was not setup correctly (e.g. by not using mdadm --build ...),\n" 157" or a wrong device is tried to be mounted,\n" 158" or the partition table is corrupt (partition is smaller than NTFS),\n" 159" or the NTFS boot sector is corrupt (NTFS size is not valid).\n"; 160 161/** 162 * ntfs_boot_sector_parse - setup an ntfs volume from an ntfs boot sector 163 * @vol: ntfs_volume to setup 164 * @bs: buffer containing ntfs boot sector to parse 165 * 166 * Parse the ntfs bootsector @bs and setup the ntfs volume @vol with the 167 * obtained values. 168 * 169 * Return 0 on success or -1 on error with errno set to the error code EINVAL. 170 */ 171int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs) 172{ 173 s64 sectors; 174 u8 sectors_per_cluster; 175 s8 c; 176 177 /* We return -1 with errno = EINVAL on error. */ 178 errno = EINVAL; 179 180 vol->sector_size = le16_to_cpu(bs->bpb.bytes_per_sector); 181 vol->sector_size_bits = ffs(vol->sector_size) - 1; 182 ntfs_log_debug("SectorSize = 0x%x\n", vol->sector_size); 183 ntfs_log_debug("SectorSizeBits = %u\n", vol->sector_size_bits); 184 /* 185 * The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being 186 * below or equal the number_of_clusters) really belong in the 187 * ntfs_boot_sector_is_ntfs but in this way we can just do this once. 188 */ 189 sectors_per_cluster = bs->bpb.sectors_per_cluster; 190 ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster); 191 if (sectors_per_cluster & (sectors_per_cluster - 1)) { 192 ntfs_log_error("sectors_per_cluster (%d) is not a power of 2." 193 "\n", sectors_per_cluster); 194 return -1; 195 } 196 197 sectors = sle64_to_cpu(bs->number_of_sectors); 198 ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors); 199 if (!sectors) { 200 ntfs_log_error("Volume size is set to zero.\n"); 201 return -1; 202 } 203 if (vol->dev->d_ops->seek(vol->dev, 204 (sectors - 1) << vol->sector_size_bits, 205 SEEK_SET) == -1) { 206 ntfs_log_perror("Failed to read last sector (%lld)", 207 (long long)sectors); 208 ntfs_log_error("%s", last_sector_error); 209 return -1; 210 } 211 212 vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1); 213 214 vol->mft_lcn = sle64_to_cpu(bs->mft_lcn); 215 vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn); 216 ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn); 217 ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn); 218 if (vol->mft_lcn > vol->nr_clusters || 219 vol->mftmirr_lcn > vol->nr_clusters) { 220 ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is " 221 "greater than the number of clusters (%lld).\n", 222 (long long)vol->mft_lcn, (long long)vol->mftmirr_lcn, 223 (long long)vol->nr_clusters); 224 return -1; 225 } 226 227 vol->cluster_size = sectors_per_cluster * vol->sector_size; 228 if (vol->cluster_size & (vol->cluster_size - 1)) { 229 ntfs_log_error("cluster_size (%d) is not a power of 2.\n", 230 vol->cluster_size); 231 return -1; 232 } 233 vol->cluster_size_bits = ffs(vol->cluster_size) - 1; 234 /* 235 * Need to get the clusters per mft record and handle it if it is 236 * negative. Then calculate the mft_record_size. A value of 0x80 is 237 * illegal, thus signed char is actually ok! 238 */ 239 c = bs->clusters_per_mft_record; 240 ntfs_log_debug("ClusterSize = 0x%x\n", (unsigned)vol->cluster_size); 241 ntfs_log_debug("ClusterSizeBits = %u\n", vol->cluster_size_bits); 242 ntfs_log_debug("ClustersPerMftRecord = 0x%x\n", c); 243 /* 244 * When clusters_per_mft_record is negative, it means that it is to 245 * be taken to be the negative base 2 logarithm of the mft_record_size 246 * min bytes. Then: 247 * mft_record_size = 2^(-clusters_per_mft_record) bytes. 248 */ 249 if (c < 0) 250 vol->mft_record_size = 1 << -c; 251 else 252 vol->mft_record_size = c << vol->cluster_size_bits; 253 if (vol->mft_record_size & (vol->mft_record_size - 1)) { 254 ntfs_log_error("mft_record_size (%d) is not a power of 2.\n", 255 vol->mft_record_size); 256 return -1; 257 } 258 vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1; 259 ntfs_log_debug("MftRecordSize = 0x%x\n", (unsigned)vol->mft_record_size); 260 ntfs_log_debug("MftRecordSizeBits = %u\n", vol->mft_record_size_bits); 261 /* Same as above for INDX record. */ 262 c = bs->clusters_per_index_record; 263 ntfs_log_debug("ClustersPerINDXRecord = 0x%x\n", c); 264 if (c < 0) 265 vol->indx_record_size = 1 << -c; 266 else 267 vol->indx_record_size = c << vol->cluster_size_bits; 268 vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1; 269 ntfs_log_debug("INDXRecordSize = 0x%x\n", (unsigned)vol->indx_record_size); 270 ntfs_log_debug("INDXRecordSizeBits = %u\n", vol->indx_record_size_bits); 271 /* 272 * Work out the size of the MFT mirror in number of mft records. If the 273 * cluster size is less than or equal to the size taken by four mft 274 * records, the mft mirror stores the first four mft records. If the 275 * cluster size is bigger than the size taken by four mft records, the 276 * mft mirror contains as many mft records as will fit into one 277 * cluster. 278 */ 279 if (vol->cluster_size <= 4 * vol->mft_record_size) 280 vol->mftmirr_size = 4; 281 else 282 vol->mftmirr_size = vol->cluster_size / vol->mft_record_size; 283 return 0; 284} 285 286