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