2 * bootsect.c - Boot sector handling code. Part of the Linux-NTFS project.
4 * Copyright (c) 2000-2002 Anton Altaparmakov
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (in the main directory of the Linux-NTFS
18 * distribution in the file COPYING); if not, write to the Free Software
19 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 * ntfs_boot_sector_is_ntfs - check if buffer contains a valid ntfs boot sector
34 * @b: buffer containing putative boot sector to analyze
35 * @silent: if zero, output progress messages to stderr
37 * Check if the buffer @b contains a valid ntfs boot sector. The buffer @b
38 * must be at least 512 bytes in size.
40 * If @silent is zero, output progress messages to stderr. Otherwise, do not
41 * output any messages (except when configured with --enable-debug in which
42 * case warning/debug messages may be displayed).
44 * Return TRUE if @b contains a valid ntfs boot sector and FALSE if not.
46 BOOL ntfs_boot_sector_is_ntfs(const NTFS_BOOT_SECTOR *b, const BOOL silent)
51 fprintf(stderr, "\nBeginning bootsector check...\n");
53 /* Calculate the checksum. Note, this is just a simple addition of
54 all u32 values in the bootsector starting at the beginning and
55 finishing at the offset of the checksum itself (i.e. not including
57 if ((void*)b < (void*)&b->checksum) {
59 u32 *bi = (u32 *)(&b->checksum);
62 fprintf(stderr, "Calculating bootsector checksum... ");
64 for (i = 0; u < bi; ++u)
67 if (le32_to_cpu(b->checksum) && le32_to_cpu(b->checksum) != i)
70 fprintf(stderr, "OK\n");
73 /* Check OEMidentifier is "NTFS " */
75 fprintf(stderr, "Checking OEMid... ");
76 if (b->oem_id != cpu_to_le64(0x202020205346544e)) /* "NTFS " */
79 fprintf(stderr, "OK\n");
81 /* Check bytes per sector value is between 256 and 4096. */
83 fprintf(stderr, "Checking bytes per sector... ");
84 if (le16_to_cpu(b->bpb.bytes_per_sector) < 0x100 ||
85 le16_to_cpu(b->bpb.bytes_per_sector) > 0x1000)
88 fprintf(stderr, "OK\n");
90 /* Check sectors per cluster value is valid. */
92 fprintf(stderr, "Checking sectors per cluster... ");
93 switch (b->bpb.sectors_per_cluster) {
94 case 1: case 2: case 4: case 8: case 16:
95 case 32: case 64: case 128:
101 fprintf(stderr, "OK\n");
103 /* Check the cluster size is not above 65536 bytes. */
105 fprintf(stderr, "Checking cluster size... ");
106 if ((u32)le16_to_cpu(b->bpb.bytes_per_sector) *
107 b->bpb.sectors_per_cluster > 0x10000)
110 fprintf(stderr, "OK\n");
112 /* Check reserved/unused fields are really zero. */
114 fprintf(stderr, "Checking reserved fields are zero... ");
115 if (le16_to_cpu(b->bpb.reserved_sectors) ||
116 le16_to_cpu(b->bpb.root_entries) ||
117 le16_to_cpu(b->bpb.sectors) ||
118 le16_to_cpu(b->bpb.sectors_per_fat) ||
119 le32_to_cpu(b->bpb.large_sectors) ||
123 fprintf(stderr, "OK\n");
125 /* Check clusters per file mft record value is valid. */
127 fprintf(stderr, "Checking clusters per mft record... ");
128 if ((u8)b->clusters_per_mft_record < 0xe1 ||
129 (u8)b->clusters_per_mft_record > 0xf7) {
130 switch (b->clusters_per_mft_record) {
131 case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
138 fprintf(stderr, "OK\n");
140 /* Check clusters per index block value is valid. */
142 fprintf(stderr, "Checking clusters per index block... ");
143 if ((u8)b->clusters_per_index_record < 0xe1 ||
144 (u8)b->clusters_per_index_record > 0xf7) {
145 switch (b->clusters_per_index_record) {
146 case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
153 fprintf(stderr, "OK\n");
155 if (b->end_of_sector_marker != cpu_to_le16(0xaa55))
156 Dputs("Warning: Bootsector has invalid end of sector marker.");
159 fprintf(stderr, "Bootsector check completed successfully.\n");
164 fprintf(stderr, "FAILED\n");
165 fprintf(stderr, "Bootsector check failed. Aborting...\n");
171 * ntfs_boot_sector_parse - setup an ntfs volume from an ntfs boot sector
172 * @vol: ntfs_volume to setup
173 * @bs: buffer containing ntfs boot sector to parse
175 * Parse the ntfs bootsector @bs and setup the ntfs volume @vol with the
178 * Return 0 on success or -1 on error with errno set to the error code EINVAL.
180 int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
182 u8 sectors_per_cluster;
185 /* We return -1 with errno = EINVAL on error. */
188 vol->sector_size = le16_to_cpu(bs->bpb.bytes_per_sector);
189 vol->sector_size_bits = ffs(vol->sector_size) - 1;
190 Dprintf("SectorSize = 0x%x\n", vol->sector_size);
191 Dprintf("SectorSizeBits = %u\n", vol->sector_size_bits);
193 * The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being
194 * below or equal the number_of_clusters) really belong in the
195 * ntfs_boot_sector_is_ntfs but in this way we can just do this once.
197 sectors_per_cluster = bs->bpb.sectors_per_cluster;
198 Dprintf("NumberOfSectors = %Li\n", sle64_to_cpu(bs->number_of_sectors));
199 Dprintf("SectorsPerCluster = 0x%x\n", sectors_per_cluster);
200 if (sectors_per_cluster & (sectors_per_cluster - 1)) {
201 Dprintf("Error: %s is not a valid NTFS partition! "
202 "sectors_per_cluster is not a power of 2.\n",
206 vol->nr_clusters = sle64_to_cpu(bs->number_of_sectors) >>
207 (ffs(sectors_per_cluster) - 1);
209 vol->mft_lcn = sle64_to_cpu(bs->mft_lcn);
210 vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn);
211 Dprintf("MFT LCN = 0x%Lx\n", vol->mft_lcn);
212 Dprintf("MFTMirr LCN = 0x%Lx\n", vol->mftmirr_lcn);
213 if (vol->mft_lcn > vol->nr_clusters ||
214 vol->mftmirr_lcn > vol->nr_clusters) {
215 Dprintf("Error: %s is not a valid NTFS partition! ($Mft LCN "
216 "or\n$MftMirr LCN is greater than the number "
217 "of clusters!\n", vol->dev->d_name);
220 vol->cluster_size = sectors_per_cluster * vol->sector_size;
221 if (vol->cluster_size & (vol->cluster_size - 1)) {
222 Dprintf("Error: %s is not a valid NTFS partition! "
223 "cluster_size is not a power of 2.\n",
227 vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
229 * Need to get the clusters per mft record and handle it if it is
230 * negative. Then calculate the mft_record_size. A value of 0x80 is
231 * illegal, thus signed char is actually ok!
233 c = bs->clusters_per_mft_record;
234 Dprintf("ClusterSize = 0x%x\n", vol->cluster_size);
235 Dprintf("ClusterSizeBits = %u\n", vol->cluster_size_bits);
236 Dprintf("ClustersPerMftRecord = 0x%x\n", c);
238 * When clusters_per_mft_record is negative, it means that it is to
239 * be taken to be the negative base 2 logarithm of the mft_record_size
241 * mft_record_size = 2^(-clusters_per_mft_record) bytes.
244 vol->mft_record_size = 1 << -c;
246 vol->mft_record_size = vol->cluster_size * c;
247 if (vol->mft_record_size & (vol->mft_record_size - 1)) {
248 Dprintf("Error: %s is not a valid NTFS partition! "
249 "mft_record_size is not a power of 2.\n",
253 vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
254 Dprintf("MftRecordSize = 0x%x\n", vol->mft_record_size);
255 Dprintf("MftRecordSizeBits = %u\n", vol->mft_record_size_bits);
257 * Work out the size of the MFT mirror in number of mft records. If the
258 * cluster size is less than or equal to the size taken by four mft
259 * records, the mft mirror stores the first four mft records. If the
260 * cluster size is bigger than the size taken by four mft records, the
261 * mft mirror contains as many mft records as will fit into one
264 if (vol->cluster_size <= 4 * vol->mft_record_size)
265 vol->mftmirr_size = 4;
267 vol->mftmirr_size = vol->cluster_size / vol->mft_record_size;