3 Copyright (C) 1998, 1999, 2000, 2002, 2004, 2007 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include <sys/types.h>
30 /* Reads in the boot sector (superblock), and does a minimum of sanity
31 * checking. The goals are:
32 * - to detect fat file systems, even if they are damaged [i.e. not
33 * return an error / throw an exception]
34 * - to fail detection if there's not enough information for
35 * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero)
38 fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom)
40 PED_ASSERT (bs != NULL, return 0);
41 PED_ASSERT (geom != NULL, return 0);
43 if (!ped_geometry_read (geom, bs, 0, 1))
46 if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) {
47 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
48 _("File system has an invalid signature for a FAT "
53 if (!bs->system_id[0]) {
54 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
55 _("File system has an invalid signature for a FAT "
60 if (!bs->sector_size || PED_LE16_TO_CPU (bs->sector_size) % 512) {
61 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
62 _("File system has an invalid sector size for a FAT "
67 if (!bs->cluster_size) {
68 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
69 _("File system has an invalid cluster size for a FAT "
75 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
76 _("File system has an invalid number of reserved "
77 "sectors for a FAT file system."));
81 if (bs->fats < 1 || bs->fats > 4) {
82 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
83 _("File system has an invalid number of FATs."));
91 Don't trust the FAT12, FAT16 or FAT32 label string.
94 fat_boot_sector_probe_type (const FatBootSector* bs, const PedGeometry* geom)
96 PedSector logical_sector_size;
97 PedSector first_cluster_sector;
98 FatCluster cluster_count;
100 if (!PED_LE16_TO_CPU (bs->dir_entries))
101 return FAT_TYPE_FAT32;
103 logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512;
106 = PED_LE16_TO_CPU (bs->reserved) * logical_sector_size
107 + 2 * PED_LE16_TO_CPU (bs->fat_length) * logical_sector_size
108 + PED_LE16_TO_CPU (bs->dir_entries)
109 / (512 / sizeof (FatDirEntry));
110 cluster_count = (geom->length - first_cluster_sector)
111 / bs->cluster_size / logical_sector_size;
112 if (cluster_count > MAX_FAT12_CLUSTERS)
113 return FAT_TYPE_FAT16;
115 return FAT_TYPE_FAT12;
118 /* Analyses the boot sector, and sticks appropriate numbers in
121 Note: you need to subtract (2 * cluster_sectors) off cluster offset,
122 because the first cluster is number 2. (0 and 1 are not real clusters,
123 and referencing them is a bug)
126 fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs)
128 FatSpecific* fs_info = FAT_SPECIFIC (fs);
131 PED_ASSERT (bs != NULL, return 0);
133 if (PED_LE16_TO_CPU (bs->sector_size) != 512) {
134 if (ped_exception_throw (
136 PED_EXCEPTION_IGNORE_CANCEL,
137 _("This file system has a logical sector size of %d. "
138 "GNU Parted is known not to work properly with sector "
139 "sizes other than 512 bytes."),
140 (int) PED_LE16_TO_CPU (bs->sector_size))
141 != PED_EXCEPTION_IGNORE)
145 fs_info->logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512;
147 fs_info->sectors_per_track = PED_LE16_TO_CPU (bs->secs_track);
148 fs_info->heads = PED_LE16_TO_CPU (bs->heads);
149 if (fs_info->sectors_per_track < 1 || fs_info->sectors_per_track > 63
150 || fs_info->heads < 1 || fs_info->heads > 255) {
151 PedCHSGeometry* bios_geom = &fs->geom->dev->bios_geom;
154 if (fs_info->heads > 0 && fs_info->sectors_per_track > 0)
155 cyl_count = fs->geom->dev->length / fs_info->heads
156 / fs_info->sectors_per_track;
158 switch (ped_exception_throw (
160 PED_EXCEPTION_FIX + PED_EXCEPTION_IGNORE
161 + PED_EXCEPTION_CANCEL,
162 _("The file system's CHS geometry is (%d, %d, %d), "
163 "which is invalid. The partition table's CHS "
164 "geometry is (%d, %d, %d). If you select Ignore, "
165 "the file system's CHS geometry will be left "
166 "unchanged. If you select Fix, the file system's "
167 "CHS geometry will be set to match the partition "
168 "table's CHS geometry."),
169 cyl_count, fs_info->heads, fs_info->sectors_per_track,
170 bios_geom->cylinders, bios_geom->heads,
171 bios_geom->sectors)) {
173 case PED_EXCEPTION_FIX:
174 fs_info->sectors_per_track = bios_geom->sectors;
175 fs_info->heads = bios_geom->heads;
177 = PED_CPU_TO_LE16 (fs_info->sectors_per_track);
178 bs->heads = PED_CPU_TO_LE16 (fs_info->heads);
179 if (!fat_boot_sector_write (bs, fs))
183 case PED_EXCEPTION_CANCEL:
186 case PED_EXCEPTION_IGNORE:
195 fs_info->sector_count = PED_LE16_TO_CPU (bs->sectors)
196 * fs_info->logical_sector_size;
198 fs_info->sector_count = PED_LE32_TO_CPU (bs->sector_count)
199 * fs_info->logical_sector_size;
201 fs_info->fat_table_count = bs->fats;
202 fs_info->root_dir_entry_count = PED_LE16_TO_CPU (bs->dir_entries);
203 fs_info->fat_offset = PED_LE16_TO_CPU (bs->reserved)
204 * fs_info->logical_sector_size;
205 fs_info->cluster_sectors = bs->cluster_size
206 * fs_info->logical_sector_size;
207 fs_info->cluster_size = fs_info->cluster_sectors * 512;
209 if (fs_info->logical_sector_size == 0) {
210 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
211 _("FAT boot sector says logical sector size is 0. "
215 if (fs_info->fat_table_count == 0) {
216 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
217 _("FAT boot sector says there are no FAT tables. This "
221 if (fs_info->cluster_sectors == 0) {
222 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
223 _("FAT boot sector says clusters are 0 sectors. This "
228 fs_info->fat_type = fat_boot_sector_probe_type (bs, fs->geom);
229 if (fs_info->fat_type == FAT_TYPE_FAT12) {
230 ped_exception_throw (
231 PED_EXCEPTION_NO_FEATURE,
232 PED_EXCEPTION_CANCEL,
233 _("File system is FAT12, which is unsupported."));
236 if (fs_info->fat_type == FAT_TYPE_FAT16) {
237 fs_info->fat_sectors = PED_LE16_TO_CPU (bs->fat_length)
238 * fs_info->logical_sector_size;
239 fs_info->serial_number
240 = PED_LE32_TO_CPU (bs->u.fat16.serial_number);
241 fs_info->root_cluster = 0;
242 fs_info->root_dir_offset
243 = fs_info->fat_offset
244 + fs_info->fat_sectors * fs_info->fat_table_count;
245 fs_info->root_dir_sector_count
246 = fs_info->root_dir_entry_count * sizeof (FatDirEntry)
247 / (512 * fs_info->logical_sector_size);
248 fs_info->cluster_offset
249 = fs_info->root_dir_offset
250 + fs_info->root_dir_sector_count;
252 if (fs_info->fat_type == FAT_TYPE_FAT32) {
253 fs_info->fat_sectors = PED_LE32_TO_CPU (bs->u.fat32.fat_length)
254 * fs_info->logical_sector_size;
255 fs_info->serial_number
256 = PED_LE32_TO_CPU (bs->u.fat32.serial_number);
257 fs_info->info_sector_offset
258 = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.info_sector)
259 * fs_info->logical_sector_size;
260 fs_info->boot_sector_backup_offset
261 = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.backup_sector)
262 * fs_info->logical_sector_size;
263 fs_info->root_cluster
264 = PED_LE32_TO_CPU (bs->u.fat32.root_dir_cluster);
265 fs_info->root_dir_offset = 0;
266 fs_info->root_dir_sector_count = 0;
267 fs_info->cluster_offset
268 = fs_info->fat_offset
269 + fs_info->fat_sectors * fs_info->fat_table_count;
272 fs_info->cluster_count
273 = (fs_info->sector_count - fs_info->cluster_offset)
274 / fs_info->cluster_sectors;
276 fat_entry_size = fat_table_entry_size (fs_info->fat_type);
277 if (fs_info->cluster_count + 2
278 > fs_info->fat_sectors * 512 / fat_entry_size)
279 fs_info->cluster_count
280 = fs_info->fat_sectors * 512 / fat_entry_size - 2;
282 fs_info->dir_entries_per_cluster
283 = fs_info->cluster_size / sizeof (FatDirEntry);
287 #ifndef DISCOVER_ONLY
289 fat_boot_sector_set_boot_code (FatBootSector* bs)
291 PED_ASSERT (bs != NULL, return 0);
294 memcpy (bs->boot_jump, FAT_BOOT_JUMP, 3);
295 memcpy (bs->u.fat32.boot_code, FAT_BOOT_CODE, FAT_BOOT_CODE_LENGTH);
300 fat_boot_sector_generate (FatBootSector* bs, const PedFileSystem* fs)
302 FatSpecific* fs_info = FAT_SPECIFIC (fs);
304 PED_ASSERT (bs != NULL, return 0);
306 memcpy (bs->system_id, "MSWIN4.1", 8);
307 bs->sector_size = PED_CPU_TO_LE16 (fs_info->logical_sector_size * 512);
308 bs->cluster_size = fs_info->cluster_sectors
309 / fs_info->logical_sector_size;
310 bs->reserved = PED_CPU_TO_LE16 (fs_info->fat_offset
311 / fs_info->logical_sector_size);
312 bs->fats = fs_info->fat_table_count;
314 bs->dir_entries = (fs_info->fat_type == FAT_TYPE_FAT16)
315 ? PED_CPU_TO_LE16 (fs_info->root_dir_entry_count)
318 if (fs_info->sector_count / fs_info->logical_sector_size > 0xffff
319 || fs_info->fat_type == FAT_TYPE_FAT32) {
321 bs->sector_count = PED_CPU_TO_LE32 (fs_info->sector_count
322 / fs_info->logical_sector_size);
324 bs->sectors = PED_CPU_TO_LE16 (fs_info->sector_count
325 / fs_info->logical_sector_size);
326 bs->sector_count = 0;
331 bs->secs_track = PED_CPU_TO_LE16 (fs_info->sectors_per_track);
332 bs->heads = PED_CPU_TO_LE16 (fs_info->heads);
333 bs->hidden = PED_CPU_TO_LE32 (fs->geom->start);
335 if (fs_info->fat_type == FAT_TYPE_FAT32) {
337 bs->u.fat32.fat_length = PED_CPU_TO_LE32 (fs_info->fat_sectors
338 / fs_info->logical_sector_size);
339 bs->u.fat32.flags = 0; /* FIXME: what the hell are these? */
340 bs->u.fat32.version = 0; /* must be 0, for Win98 bootstrap */
341 bs->u.fat32.root_dir_cluster
342 = PED_CPU_TO_LE32 (fs_info->root_cluster);
343 bs->u.fat32.info_sector
344 = PED_CPU_TO_LE16 (fs_info->info_sector_offset
345 / fs_info->logical_sector_size);
346 bs->u.fat32.backup_sector
347 = PED_CPU_TO_LE16 (fs_info->boot_sector_backup_offset
348 / fs_info->logical_sector_size);
350 bs->u.fat32.drive_num = 0x80; /* _ALWAYS_ 0x80. silly DOS */
352 memset (bs->u.fat32.empty_1, 0, 12);
354 bs->u.fat32.ext_signature = 0x29;
355 bs->u.fat32.serial_number
356 = PED_CPU_TO_LE32 (fs_info->serial_number);
357 memcpy (bs->u.fat32.volume_name, "NO NAME ", 11);
358 memcpy (bs->u.fat32.fat_name, "FAT32 ", 8);
361 = PED_CPU_TO_LE16 (fs_info->fat_sectors
362 / fs_info->logical_sector_size);
364 bs->u.fat16.drive_num = 0x80; /* _ALWAYS_ 0x80. silly DOS */
366 bs->u.fat16.ext_signature = 0x29;
367 bs->u.fat16.serial_number
368 = PED_CPU_TO_LE32 (fs_info->serial_number);
369 memcpy (bs->u.fat16.volume_name, "NO NAME ", 11);
370 memcpy (bs->u.fat16.fat_name, "FAT16 ", 8);
373 bs->boot_sign = PED_CPU_TO_LE16 (0xaa55);
379 fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs)
381 FatSpecific* fs_info = FAT_SPECIFIC (fs);
383 PED_ASSERT (bs != NULL, return 0);
385 if (!ped_geometry_write (fs->geom, bs, 0, 1))
387 if (fs_info->fat_type == FAT_TYPE_FAT32) {
388 if (!ped_geometry_write (fs->geom, bs,
389 fs_info->boot_sector_backup_offset, 1))
392 return ped_geometry_sync (fs->geom);
396 fat_info_sector_read (FatInfoSector* is, const PedFileSystem* fs)
398 FatSpecific* fs_info = FAT_SPECIFIC (fs);
401 PED_ASSERT (is != NULL, return 0);
403 if (!ped_geometry_read (fs->geom, is, fs_info->info_sector_offset, 1))
406 if (PED_LE32_TO_CPU (is->signature_2) != FAT32_INFO_MAGIC2) {
407 status = ped_exception_throw (PED_EXCEPTION_WARNING,
408 PED_EXCEPTION_IGNORE_CANCEL,
409 _("The information sector has the wrong "
410 "signature (%x). Select cancel for now, "
411 "and send in a bug report. If you're "
412 "desperate, it's probably safe to ignore."),
413 PED_LE32_TO_CPU (is->signature_2));
414 if (status == PED_EXCEPTION_CANCEL) return 0;
420 fat_info_sector_generate (FatInfoSector* is, const PedFileSystem* fs)
422 FatSpecific* fs_info = FAT_SPECIFIC (fs);
424 PED_ASSERT (is != NULL, return 0);
426 fat_table_count_stats (fs_info->fat);
430 is->signature_1 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC1);
431 is->signature_2 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC2);
432 is->free_clusters = PED_CPU_TO_LE32 (fs_info->fat->free_cluster_count);
433 is->next_cluster = PED_CPU_TO_LE32 (fs_info->fat->last_alloc);
434 is->signature_3 = PED_CPU_TO_LE16 (FAT32_INFO_MAGIC3);
440 fat_info_sector_write (const FatInfoSector* is, PedFileSystem *fs)
442 FatSpecific* fs_info = FAT_SPECIFIC (fs);
444 PED_ASSERT (is != NULL, return 0);
446 if (!ped_geometry_write (fs->geom, is, fs_info->info_sector_offset, 1))
448 return ped_geometry_sync (fs->geom);
450 #endif /* !DISCOVER_ONLY */