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