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 "param.h" 42#include "compat.h" 43#include "bootsect.h" 44#include "debug.h" 45#include "logging.h" 46 47/** 48 * ntfs_boot_sector_is_ntfs - check if buffer contains a valid ntfs boot sector 49 * @b: buffer containing putative boot sector to analyze 50 * @silent: if zero, output progress messages to stderr 51 * 52 * Check if the buffer @b contains a valid ntfs boot sector. The buffer @b 53 * must be at least 512 bytes in size. 54 * 55 * If @silent is zero, output progress messages to stderr. Otherwise, do not 56 * output any messages (except when configured with --enable-debug in which 57 * case warning/debug messages may be displayed). 58 * 59 * Return TRUE if @b contains a valid ntfs boot sector and FALSE if not. 60 */ 61BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b) 62{ 63 u32 i; 64 BOOL ret = FALSE; 65 u16 sectors_per_cluster; 66 67 ntfs_log_debug("Beginning bootsector check.\n"); 68 69 ntfs_log_debug("Checking OEMid, NTFS signature.\n"); 70 if (b->oem_id != const_cpu_to_le64(0x202020205346544eULL)) { /* "NTFS " */ 71 ntfs_log_error("NTFS signature is missing.\n"); 72 goto not_ntfs; 73 } 74 75 ntfs_log_debug("Checking bytes per sector.\n"); 76 if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 || 77 le16_to_cpu(b->bpb.bytes_per_sector) > 4096) { 78 ntfs_log_error("Unexpected bytes per sector value (%d).\n", 79 le16_to_cpu(b->bpb.bytes_per_sector)); 80 goto not_ntfs; 81 } 82 83 ntfs_log_debug("Checking sectors per cluster.\n"); 84 switch (b->bpb.sectors_per_cluster) { 85 case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: 86 break; 87 default: 88 if ((b->bpb.sectors_per_cluster < 240) 89 || (b->bpb.sectors_per_cluster > 253)) { 90 if (b->bpb.sectors_per_cluster > 128) 91 ntfs_log_error("Unexpected sectors" 92 " per cluster value (code 0x%x)\n", 93 b->bpb.sectors_per_cluster); 94 else 95 ntfs_log_error("Unexpected sectors" 96 " per cluster value (%d).\n", 97 b->bpb.sectors_per_cluster); 98 goto not_ntfs; 99 } 100 } 101 102 ntfs_log_debug("Checking cluster size.\n"); 103 if (b->bpb.sectors_per_cluster > 128) 104 sectors_per_cluster = 1 << (256 - b->bpb.sectors_per_cluster); 105 else 106 sectors_per_cluster = b->bpb.sectors_per_cluster; 107 i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) * sectors_per_cluster; 108 if (i > NTFS_MAX_CLUSTER_SIZE) { 109 ntfs_log_error("Unexpected cluster size (%d).\n", i); 110 goto not_ntfs; 111 } 112 113 ntfs_log_debug("Checking reserved fields are zero.\n"); 114 if (le16_to_cpu(b->bpb.reserved_sectors) || 115 le16_to_cpu(b->bpb.root_entries) || 116 le16_to_cpu(b->bpb.sectors) || 117 le16_to_cpu(b->bpb.sectors_per_fat) || 118 le32_to_cpu(b->bpb.large_sectors) || 119 b->bpb.fats) { 120 ntfs_log_error("Reserved fields aren't zero " 121 "(%d, %d, %d, %d, %d, %d).\n", 122 le16_to_cpu(b->bpb.reserved_sectors), 123 le16_to_cpu(b->bpb.root_entries), 124 le16_to_cpu(b->bpb.sectors), 125 le16_to_cpu(b->bpb.sectors_per_fat), 126 le32_to_cpu(b->bpb.large_sectors), 127 b->bpb.fats); 128 goto not_ntfs; 129 } 130 131 ntfs_log_debug("Checking clusters per mft record.\n"); 132 if ((u8)b->clusters_per_mft_record < 0xe1 || 133 (u8)b->clusters_per_mft_record > 0xf7) { 134 switch (b->clusters_per_mft_record) { 135 case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: 136 break; 137 default: 138 ntfs_log_error("Unexpected clusters per mft record " 139 "(%d).\n", b->clusters_per_mft_record); 140 goto not_ntfs; 141 } 142 } 143 144 ntfs_log_debug("Checking clusters per index block.\n"); 145 if ((u8)b->clusters_per_index_record < 0xe1 || 146 (u8)b->clusters_per_index_record > 0xf7) { 147 switch (b->clusters_per_index_record) { 148 case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: 149 break; 150 default: 151 ntfs_log_error("Unexpected clusters per index record " 152 "(%d).\n", b->clusters_per_index_record); 153 goto not_ntfs; 154 } 155 } 156 157 /* MFT and MFTMirr may not overlap the boot sector or be the same */ 158 if (((s64)sle64_to_cpu(b->mft_lcn) <= 0) 159 || ((s64)sle64_to_cpu(b->mftmirr_lcn) <= 0) 160 || (b->mft_lcn == b->mftmirr_lcn)) { 161 ntfs_log_error("Invalid location of MFT or MFTMirr.\n"); 162 goto not_ntfs; 163 } 164 165 if (b->end_of_sector_marker != const_cpu_to_le16(0xaa55)) 166 ntfs_log_debug("Warning: Bootsector has invalid end of sector " 167 "marker.\n"); 168 169 ntfs_log_debug("Bootsector check completed successfully.\n"); 170 171 ret = TRUE; 172not_ntfs: 173 return ret; 174} 175 176static const char *last_sector_error = 177"HINTS: Either the volume is a RAID/LDM but it wasn't setup yet,\n" 178" or it was not setup correctly (e.g. by not using mdadm --build ...),\n" 179" or a wrong device is tried to be mounted,\n" 180" or the partition table is corrupt (partition is smaller than NTFS),\n" 181" or the NTFS boot sector is corrupt (NTFS size is not valid).\n"; 182 183/** 184 * ntfs_boot_sector_parse - setup an ntfs volume from an ntfs boot sector 185 * @vol: ntfs_volume to setup 186 * @bs: buffer containing ntfs boot sector to parse 187 * 188 * Parse the ntfs bootsector @bs and setup the ntfs volume @vol with the 189 * obtained values. 190 * 191 * Return 0 on success or -1 on error with errno set to the error code EINVAL. 192 */ 193int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs) 194{ 195 s64 sectors; 196 u16 sectors_per_cluster; 197 s8 c; 198 199 /* We return -1 with errno = EINVAL on error. */ 200 errno = EINVAL; 201 202 vol->sector_size = le16_to_cpu(bs->bpb.bytes_per_sector); 203 vol->sector_size_bits = ffs(vol->sector_size) - 1; 204 ntfs_log_debug("SectorSize = 0x%x\n", vol->sector_size); 205 ntfs_log_debug("SectorSizeBits = %u\n", vol->sector_size_bits); 206 /* 207 * The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being 208 * below or equal the number_of_clusters) really belong in the 209 * ntfs_boot_sector_is_ntfs but in this way we can just do this once. 210 */ 211 if (bs->bpb.sectors_per_cluster > 128) 212 sectors_per_cluster = 1 << (256 - bs->bpb.sectors_per_cluster); 213 else 214 sectors_per_cluster = bs->bpb.sectors_per_cluster; 215 ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster); 216 if (sectors_per_cluster & (sectors_per_cluster - 1)) { 217 ntfs_log_error("sectors_per_cluster (%d) is not a power of 2." 218 "\n", sectors_per_cluster); 219 return -1; 220 } 221 222 sectors = sle64_to_cpu(bs->number_of_sectors); 223 ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors); 224 if (!sectors) { 225 ntfs_log_error("Volume size is set to zero.\n"); 226 return -1; 227 } 228 if (vol->dev->d_ops->seek(vol->dev, 229 (sectors - 1) << vol->sector_size_bits, 230 SEEK_SET) == -1) { 231 ntfs_log_perror("Failed to read last sector (%lld)", 232 (long long)(sectors - 1)); 233 ntfs_log_error("%s", last_sector_error); 234 return -1; 235 } 236 237 vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1); 238 239 vol->mft_lcn = sle64_to_cpu(bs->mft_lcn); 240 vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn); 241 ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn); 242 ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn); 243 if ((vol->mft_lcn < 0 || vol->mft_lcn > vol->nr_clusters) || 244 (vol->mftmirr_lcn < 0 || vol->mftmirr_lcn > vol->nr_clusters)) { 245 ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is " 246 "greater than the number of clusters (%lld).\n", 247 (long long)vol->mft_lcn, (long long)vol->mftmirr_lcn, 248 (long long)vol->nr_clusters); 249 return -1; 250 } 251 252 vol->cluster_size = sectors_per_cluster * vol->sector_size; 253 if (vol->cluster_size & (vol->cluster_size - 1)) { 254 ntfs_log_error("cluster_size (%d) is not a power of 2.\n", 255 vol->cluster_size); 256 return -1; 257 } 258 vol->cluster_size_bits = ffs(vol->cluster_size) - 1; 259 /* 260 * Need to get the clusters per mft record and handle it if it is 261 * negative. Then calculate the mft_record_size. A value of 0x80 is 262 * illegal, thus signed char is actually ok! 263 */ 264 c = bs->clusters_per_mft_record; 265 ntfs_log_debug("ClusterSize = 0x%x\n", (unsigned)vol->cluster_size); 266 ntfs_log_debug("ClusterSizeBits = %u\n", vol->cluster_size_bits); 267 ntfs_log_debug("ClustersPerMftRecord = 0x%x\n", c); 268 /* 269 * When clusters_per_mft_record is negative, it means that it is to 270 * be taken to be the negative base 2 logarithm of the mft_record_size 271 * min bytes. Then: 272 * mft_record_size = 2^(-clusters_per_mft_record) bytes. 273 */ 274 if (c < 0) 275 vol->mft_record_size = 1 << -c; 276 else 277 vol->mft_record_size = c << vol->cluster_size_bits; 278 if (vol->mft_record_size & (vol->mft_record_size - 1)) { 279 ntfs_log_error("mft_record_size (%d) is not a power of 2.\n", 280 vol->mft_record_size); 281 return -1; 282 } 283 vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1; 284 ntfs_log_debug("MftRecordSize = 0x%x\n", (unsigned)vol->mft_record_size); 285 ntfs_log_debug("MftRecordSizeBits = %u\n", vol->mft_record_size_bits); 286 /* Same as above for INDX record. */ 287 c = bs->clusters_per_index_record; 288 ntfs_log_debug("ClustersPerINDXRecord = 0x%x\n", c); 289 if (c < 0) 290 vol->indx_record_size = 1 << -c; 291 else 292 vol->indx_record_size = c << vol->cluster_size_bits; 293 vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1; 294 ntfs_log_debug("INDXRecordSize = 0x%x\n", (unsigned)vol->indx_record_size); 295 ntfs_log_debug("INDXRecordSizeBits = %u\n", vol->indx_record_size_bits); 296 /* 297 * Work out the size of the MFT mirror in number of mft records. If the 298 * cluster size is less than or equal to the size taken by four mft 299 * records, the mft mirror stores the first four mft records. If the 300 * cluster size is bigger than the size taken by four mft records, the 301 * mft mirror contains as many mft records as will fit into one 302 * cluster. 303 */ 304 if (vol->cluster_size <= 4 * vol->mft_record_size) 305 vol->mftmirr_size = 4; 306 else 307 vol->mftmirr_size = vol->cluster_size / vol->mft_record_size; 308 return 0; 309} 310 311