3 Copyright (C) 1998-2000, 2002, 2004, 2007, 2009-2011 Free Software
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 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. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
31 /* Reads in the boot sector (superblock), and does a minimum of sanity
32 * checking. The goals are:
33 * - to detect fat file systems, even if they are damaged [i.e. not
34 * return an error / throw an exception]
35 * - to fail detection if there's not enough information for
36 * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero)
39 fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom)
41 PED_ASSERT (bs != NULL);
42 PED_ASSERT (geom != NULL);
44 if (!ped_geometry_read (geom, bs, 0, 1))
47 if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) {
48 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
49 _("File system has an invalid signature for a FAT "
54 if (!bs->system_id[0]) {
55 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
56 _("File system has an invalid signature for a FAT "
62 || PED_LE16_TO_CPU (bs->sector_size) % PED_SECTOR_SIZE_DEFAULT) {
63 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
64 _("File system has an invalid sector size for a FAT "
69 if (!bs->cluster_size) {
70 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
71 _("File system has an invalid cluster size for a FAT "
77 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
78 _("File system has an invalid number of reserved "
79 "sectors for a FAT file system."));
83 if (bs->fats < 1 || bs->fats > 4) {
84 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
85 _("File system has an invalid number of FATs."));
93 Don't trust the FAT12, FAT16 or FAT32 label string.
96 fat_boot_sector_probe_type (const FatBootSector* bs, const PedGeometry* geom)
98 PedSector logical_sector_size;
99 PedSector first_cluster_sector;
100 FatCluster cluster_count;
102 if (!PED_LE16_TO_CPU (bs->dir_entries))
103 return FAT_TYPE_FAT32;
105 logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512;
108 = PED_LE16_TO_CPU (bs->reserved) * logical_sector_size
109 + 2 * PED_LE16_TO_CPU (bs->fat_length) * logical_sector_size
110 + PED_LE16_TO_CPU (bs->dir_entries)
111 / (512 / sizeof (FatDirEntry));
112 cluster_count = (geom->length - first_cluster_sector)
113 / bs->cluster_size / logical_sector_size;
114 if (cluster_count > MAX_FAT12_CLUSTERS)
115 return FAT_TYPE_FAT16;
117 return FAT_TYPE_FAT12;
121 _fat_table_entry_size (FatType fat_type)
125 return 2; /* FIXME: how? */
137 /* Analyses the boot sector, and sticks appropriate numbers in
140 Note: you need to subtract (2 * cluster_sectors) off cluster offset,
141 because the first cluster is number 2. (0 and 1 are not real clusters,
142 and referencing them is a bug)
145 fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs)
147 FatSpecific* fs_info = FAT_SPECIFIC (fs);
150 PED_ASSERT (bs != NULL);
152 if (PED_LE16_TO_CPU (bs->sector_size) != 512) {
153 if (ped_exception_throw (
155 PED_EXCEPTION_IGNORE_CANCEL,
156 _("This file system has a logical sector size of %d. "
157 "GNU Parted is known not to work properly with sector "
158 "sizes other than 512 bytes."),
159 (int) PED_LE16_TO_CPU (bs->sector_size))
160 != PED_EXCEPTION_IGNORE)
164 fs_info->logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512;
166 fs_info->sectors_per_track = PED_LE16_TO_CPU (bs->secs_track);
167 fs_info->heads = PED_LE16_TO_CPU (bs->heads);
168 if (fs_info->sectors_per_track < 1 || fs_info->sectors_per_track > 63
169 || fs_info->heads < 1 || fs_info->heads > 255) {
170 PedCHSGeometry* bios_geom = &fs->geom->dev->bios_geom;
173 if (fs_info->heads > 0 && fs_info->sectors_per_track > 0)
174 cyl_count = fs->geom->dev->length / fs_info->heads
175 / fs_info->sectors_per_track;
177 switch (ped_exception_throw (
179 PED_EXCEPTION_FIX + PED_EXCEPTION_IGNORE
180 + PED_EXCEPTION_CANCEL,
181 _("The file system's CHS geometry is (%d, %d, %d), "
182 "which is invalid. The partition table's CHS "
183 "geometry is (%d, %d, %d). If you select Ignore, "
184 "the file system's CHS geometry will be left "
185 "unchanged. If you select Fix, the file system's "
186 "CHS geometry will be set to match the partition "
187 "table's CHS geometry."),
188 cyl_count, fs_info->heads, fs_info->sectors_per_track,
189 bios_geom->cylinders, bios_geom->heads,
190 bios_geom->sectors)) {
192 case PED_EXCEPTION_FIX:
193 fs_info->sectors_per_track = bios_geom->sectors;
194 fs_info->heads = bios_geom->heads;
196 = PED_CPU_TO_LE16 (fs_info->sectors_per_track);
197 bs->heads = PED_CPU_TO_LE16 (fs_info->heads);
198 if (!fat_boot_sector_write (bs, fs))
202 case PED_EXCEPTION_CANCEL:
205 case PED_EXCEPTION_IGNORE:
214 fs_info->sector_count = PED_LE16_TO_CPU (bs->sectors)
215 * fs_info->logical_sector_size;
217 fs_info->sector_count = PED_LE32_TO_CPU (bs->sector_count)
218 * fs_info->logical_sector_size;
220 fs_info->fat_table_count = bs->fats;
221 fs_info->root_dir_entry_count = PED_LE16_TO_CPU (bs->dir_entries);
222 fs_info->fat_offset = PED_LE16_TO_CPU (bs->reserved)
223 * fs_info->logical_sector_size;
224 fs_info->cluster_sectors = bs->cluster_size
225 * fs_info->logical_sector_size;
226 fs_info->cluster_size = fs_info->cluster_sectors * 512;
228 if (fs_info->logical_sector_size == 0) {
229 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
230 _("FAT boot sector says logical sector size is 0. "
234 if (fs_info->fat_table_count == 0) {
235 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
236 _("FAT boot sector says there are no FAT tables. This "
240 if (fs_info->cluster_sectors == 0) {
241 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
242 _("FAT boot sector says clusters are 0 sectors. This "
247 fs_info->fat_type = fat_boot_sector_probe_type (bs, fs->geom);
248 if (fs_info->fat_type == FAT_TYPE_FAT12) {
249 ped_exception_throw (
250 PED_EXCEPTION_NO_FEATURE,
251 PED_EXCEPTION_CANCEL,
252 _("File system is FAT12, which is unsupported."));
255 if (fs_info->fat_type == FAT_TYPE_FAT16) {
256 fs_info->fat_sectors = PED_LE16_TO_CPU (bs->fat_length)
257 * fs_info->logical_sector_size;
258 fs_info->serial_number
259 = PED_LE32_TO_CPU (bs->u.fat16.serial_number);
260 fs_info->root_cluster = 0;
261 fs_info->root_dir_offset
262 = fs_info->fat_offset
263 + fs_info->fat_sectors * fs_info->fat_table_count;
264 fs_info->root_dir_sector_count
265 = fs_info->root_dir_entry_count * sizeof (FatDirEntry)
266 / (512 * fs_info->logical_sector_size);
267 fs_info->cluster_offset
268 = fs_info->root_dir_offset
269 + fs_info->root_dir_sector_count;
271 if (fs_info->fat_type == FAT_TYPE_FAT32) {
272 fs_info->fat_sectors = PED_LE32_TO_CPU (bs->u.fat32.fat_length)
273 * fs_info->logical_sector_size;
274 fs_info->serial_number
275 = PED_LE32_TO_CPU (bs->u.fat32.serial_number);
276 fs_info->info_sector_offset
277 = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.info_sector)
278 * fs_info->logical_sector_size;
279 fs_info->boot_sector_backup_offset
280 = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.backup_sector)
281 * fs_info->logical_sector_size;
282 fs_info->root_cluster
283 = PED_LE32_TO_CPU (bs->u.fat32.root_dir_cluster);
284 fs_info->root_dir_offset = 0;
285 fs_info->root_dir_sector_count = 0;
286 fs_info->cluster_offset
287 = fs_info->fat_offset
288 + fs_info->fat_sectors * fs_info->fat_table_count;
291 fs_info->cluster_count
292 = (fs_info->sector_count - fs_info->cluster_offset)
293 / fs_info->cluster_sectors;
295 fat_entry_size = _fat_table_entry_size (fs_info->fat_type);
296 if (fs_info->cluster_count + 2
297 > fs_info->fat_sectors * 512 / fat_entry_size)
298 fs_info->cluster_count
299 = fs_info->fat_sectors * 512 / fat_entry_size - 2;
301 fs_info->dir_entries_per_cluster
302 = fs_info->cluster_size / sizeof (FatDirEntry);
306 #ifndef DISCOVER_ONLY
308 fat_boot_sector_set_boot_code (FatBootSector* bs)
310 PED_ASSERT (bs != NULL);
313 memcpy (bs->boot_jump, FAT_BOOT_JUMP, 3);
314 memcpy (bs->u.fat32.boot_code, FAT_BOOT_CODE, FAT_BOOT_CODE_LENGTH);
319 fat_boot_sector_generate (FatBootSector* bs, const PedFileSystem* fs)
321 FatSpecific* fs_info = FAT_SPECIFIC (fs);
323 PED_ASSERT (bs != NULL);
325 memcpy (bs->system_id, "MSWIN4.1", 8);
326 bs->sector_size = PED_CPU_TO_LE16 (fs_info->logical_sector_size * 512);
327 bs->cluster_size = fs_info->cluster_sectors
328 / fs_info->logical_sector_size;
329 bs->reserved = PED_CPU_TO_LE16 (fs_info->fat_offset
330 / fs_info->logical_sector_size);
331 bs->fats = fs_info->fat_table_count;
333 bs->dir_entries = (fs_info->fat_type == FAT_TYPE_FAT16)
334 ? PED_CPU_TO_LE16 (fs_info->root_dir_entry_count)
337 if (fs_info->sector_count / fs_info->logical_sector_size > 0xffff
338 || fs_info->fat_type == FAT_TYPE_FAT32) {
340 bs->sector_count = PED_CPU_TO_LE32 (fs_info->sector_count
341 / fs_info->logical_sector_size);
343 bs->sectors = PED_CPU_TO_LE16 (fs_info->sector_count
344 / fs_info->logical_sector_size);
345 bs->sector_count = 0;
350 bs->secs_track = PED_CPU_TO_LE16 (fs_info->sectors_per_track);
351 bs->heads = PED_CPU_TO_LE16 (fs_info->heads);
352 bs->hidden = PED_CPU_TO_LE32 (fs->geom->start);
354 if (fs_info->fat_type == FAT_TYPE_FAT32) {
356 bs->u.fat32.fat_length = PED_CPU_TO_LE32 (fs_info->fat_sectors
357 / fs_info->logical_sector_size);
358 bs->u.fat32.flags = 0; /* FIXME: what the hell are these? */
359 bs->u.fat32.version = 0; /* must be 0, for Win98 bootstrap */
360 bs->u.fat32.root_dir_cluster
361 = PED_CPU_TO_LE32 (fs_info->root_cluster);
362 bs->u.fat32.info_sector
363 = PED_CPU_TO_LE16 (fs_info->info_sector_offset
364 / fs_info->logical_sector_size);
365 bs->u.fat32.backup_sector
366 = PED_CPU_TO_LE16 (fs_info->boot_sector_backup_offset
367 / fs_info->logical_sector_size);
369 bs->u.fat32.drive_num = 0x80; /* _ALWAYS_ 0x80. silly DOS */
371 memset (bs->u.fat32.empty_1, 0, 12);
373 bs->u.fat32.ext_signature = 0x29;
374 bs->u.fat32.serial_number
375 = PED_CPU_TO_LE32 (fs_info->serial_number);
376 memcpy (bs->u.fat32.volume_name, "NO NAME ", 11);
377 memcpy (bs->u.fat32.fat_name, "FAT32 ", 8);
380 = PED_CPU_TO_LE16 (fs_info->fat_sectors
381 / fs_info->logical_sector_size);
383 bs->u.fat16.drive_num = 0x80; /* _ALWAYS_ 0x80. silly DOS */
385 bs->u.fat16.ext_signature = 0x29;
386 bs->u.fat16.serial_number
387 = PED_CPU_TO_LE32 (fs_info->serial_number);
388 memcpy (bs->u.fat16.volume_name, "NO NAME ", 11);
389 memcpy (bs->u.fat16.fat_name, "FAT16 ", 8);
392 bs->boot_sign = PED_CPU_TO_LE16 (0xaa55);
398 fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs)
400 FatSpecific* fs_info = FAT_SPECIFIC (fs);
402 PED_ASSERT (bs != NULL);
404 if (!ped_geometry_write (fs->geom, bs, 0, 1))
406 if (fs_info->fat_type == FAT_TYPE_FAT32) {
407 if (!ped_geometry_write (fs->geom, bs,
408 fs_info->boot_sector_backup_offset, 1))
411 return ped_geometry_sync (fs->geom);
415 fat_info_sector_read (FatInfoSector* is, const PedFileSystem* fs)
417 FatSpecific* fs_info = FAT_SPECIFIC (fs);
420 PED_ASSERT (is != NULL);
422 if (!ped_geometry_read (fs->geom, is, fs_info->info_sector_offset, 1))
425 if (PED_LE32_TO_CPU (is->signature_2) != FAT32_INFO_MAGIC2) {
426 status = ped_exception_throw (PED_EXCEPTION_WARNING,
427 PED_EXCEPTION_IGNORE_CANCEL,
428 _("The information sector has the wrong "
429 "signature (%x). Select cancel for now, "
430 "and send in a bug report. If you're "
431 "desperate, it's probably safe to ignore."),
432 PED_LE32_TO_CPU (is->signature_2));
433 if (status == PED_EXCEPTION_CANCEL) return 0;
439 fat_info_sector_write (const FatInfoSector* is, PedFileSystem *fs)
441 FatSpecific* fs_info = FAT_SPECIFIC (fs);
443 PED_ASSERT (is != NULL);
445 if (!ped_geometry_write (fs->geom, is, fs_info->info_sector_offset, 1))
447 return ped_geometry_sync (fs->geom);
449 #endif /* !DISCOVER_ONLY */