1 /* fat.c - FAT filesystem */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
6 * GRUB 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 * GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/disk.h>
22 #include <grub/file.h>
23 #include <grub/types.h>
24 #include <grub/misc.h>
29 #define GRUB_FAT_DIR_ENTRY_SIZE 32
31 #define GRUB_FAT_ATTR_READ_ONLY 0x01
32 #define GRUB_FAT_ATTR_HIDDEN 0x02
33 #define GRUB_FAT_ATTR_SYSTEM 0x04
34 #define GRUB_FAT_ATTR_VOLUME_ID 0x08
35 #define GRUB_FAT_ATTR_DIRECTORY 0x10
36 #define GRUB_FAT_ATTR_ARCHIVE 0x20
38 #define GRUB_FAT_MAXFILE 256
40 #define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
41 | GRUB_FAT_ATTR_HIDDEN \
42 | GRUB_FAT_ATTR_SYSTEM \
43 | GRUB_FAT_ATTR_VOLUME_ID)
44 #define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \
45 | GRUB_FAT_ATTR_HIDDEN \
46 | GRUB_FAT_ATTR_SYSTEM \
47 | GRUB_FAT_ATTR_DIRECTORY \
48 | GRUB_FAT_ATTR_ARCHIVE \
49 | GRUB_FAT_ATTR_VOLUME_ID)
53 grub_uint8_t jmp_boot
[3];
54 grub_uint8_t oem_name
[8];
55 grub_uint16_t bytes_per_sector
;
56 grub_uint8_t sectors_per_cluster
;
57 grub_uint16_t num_reserved_sectors
;
58 grub_uint8_t num_fats
;
59 grub_uint16_t num_root_entries
;
60 grub_uint16_t num_total_sectors_16
;
62 grub_uint16_t sectors_per_fat_16
;
63 grub_uint16_t sectors_per_track
;
64 grub_uint16_t num_heads
;
65 grub_uint32_t num_hidden_sectors
;
66 grub_uint32_t num_total_sectors_32
;
71 grub_uint8_t num_ph_drive
;
72 grub_uint8_t reserved
;
73 grub_uint8_t boot_sig
;
74 grub_uint32_t num_serial
;
75 grub_uint8_t label
[11];
76 grub_uint8_t fstype
[8];
77 } __attribute__ ((packed
)) fat12_or_fat16
;
80 grub_uint32_t sectors_per_fat_32
;
81 grub_uint16_t extended_flags
;
82 grub_uint16_t fs_version
;
83 grub_uint32_t root_cluster
;
84 grub_uint16_t fs_info
;
85 grub_uint16_t backup_boot_sector
;
86 grub_uint8_t reserved
[12];
87 grub_uint8_t num_ph_drive
;
88 grub_uint8_t reserved1
;
89 grub_uint8_t boot_sig
;
90 grub_uint32_t num_serial
;
91 grub_uint8_t label
[11];
92 grub_uint8_t fstype
[8];
93 } __attribute__ ((packed
)) fat32
;
94 } __attribute__ ((packed
)) version_specific
;
95 } __attribute__ ((packed
));
97 struct grub_fat_dir_entry
99 grub_uint8_t name
[11];
101 grub_uint8_t nt_reserved
;
102 grub_uint8_t c_time_tenth
;
103 grub_uint16_t c_time
;
104 grub_uint16_t c_date
;
105 grub_uint16_t a_date
;
106 grub_uint16_t first_cluster_high
;
107 grub_uint16_t w_time
;
108 grub_uint16_t w_date
;
109 grub_uint16_t first_cluster_low
;
110 grub_uint32_t file_size
;
111 } __attribute__ ((packed
));
113 struct grub_fat_long_name_entry
116 grub_uint16_t name1
[5];
118 grub_uint8_t reserved
;
119 grub_uint8_t checksum
;
120 grub_uint16_t name2
[6];
121 grub_uint16_t first_cluster
;
122 grub_uint16_t name3
[2];
123 } __attribute__ ((packed
));
127 int logical_sector_bits
;
128 grub_uint32_t num_sectors
;
130 grub_uint16_t fat_sector
;
131 grub_uint32_t sectors_per_fat
;
134 grub_uint32_t root_cluster
;
135 grub_uint32_t root_sector
;
136 grub_uint32_t num_root_sectors
;
139 grub_uint32_t cluster_eof_mark
;
140 grub_uint32_t cluster_sector
;
141 grub_uint32_t num_clusters
;
144 grub_ssize_t file_size
;
145 grub_uint32_t file_cluster
;
146 grub_uint32_t cur_cluster_num
;
147 grub_uint32_t cur_cluster
;
152 static grub_dl_t my_mod
;
155 fat_log2 (unsigned x
)
162 for (i
= 0; (x
& 1) == 0; i
++)
171 static struct grub_fat_data
*
172 grub_fat_mount (grub_disk_t disk
)
174 struct grub_fat_bpb bpb
;
175 struct grub_fat_data
*data
= 0;
176 grub_uint32_t first_fat
, magic
;
181 data
= (struct grub_fat_data
*) grub_malloc (sizeof (*data
));
186 if (grub_disk_read (disk
, 0, 0, sizeof (bpb
), &bpb
))
189 if (grub_strncmp((const char *) bpb
.version_specific
.fat12_or_fat16
.fstype
, "FAT12", 5)
190 && grub_strncmp((const char *) bpb
.version_specific
.fat12_or_fat16
.fstype
, "FAT16", 5)
191 && grub_strncmp((const char *) bpb
.version_specific
.fat32
.fstype
, "FAT32", 5))
194 /* Get the sizes of logical sectors and clusters. */
195 data
->logical_sector_bits
=
196 fat_log2 (grub_le_to_cpu16 (bpb
.bytes_per_sector
));
197 if (data
->logical_sector_bits
< GRUB_DISK_SECTOR_BITS
)
199 data
->logical_sector_bits
-= GRUB_DISK_SECTOR_BITS
;
201 data
->cluster_bits
= fat_log2 (bpb
.sectors_per_cluster
);
202 if (data
->cluster_bits
< 0)
204 data
->cluster_bits
+= data
->logical_sector_bits
;
206 /* Get information about FATs. */
207 data
->fat_sector
= (grub_le_to_cpu16 (bpb
.num_reserved_sectors
)
208 << data
->logical_sector_bits
);
209 if (data
->fat_sector
== 0)
212 data
->sectors_per_fat
= ((bpb
.sectors_per_fat_16
213 ? grub_le_to_cpu16 (bpb
.sectors_per_fat_16
)
214 : grub_le_to_cpu32 (bpb
.version_specific
.fat32
.sectors_per_fat_32
))
215 << data
->logical_sector_bits
);
216 if (data
->sectors_per_fat
== 0)
219 /* Get the number of sectors in this volume. */
220 data
->num_sectors
= ((bpb
.num_total_sectors_16
221 ? grub_le_to_cpu16 (bpb
.num_total_sectors_16
)
222 : grub_le_to_cpu32 (bpb
.num_total_sectors_32
))
223 << data
->logical_sector_bits
);
224 if (data
->num_sectors
== 0)
227 /* Get information about the root directory. */
228 if (bpb
.num_fats
== 0)
231 data
->root_sector
= data
->fat_sector
+ bpb
.num_fats
* data
->sectors_per_fat
;
232 data
->num_root_sectors
233 = ((((grub_uint32_t
) grub_le_to_cpu16 (bpb
.num_root_entries
)
234 * GRUB_FAT_DIR_ENTRY_SIZE
235 + grub_le_to_cpu16 (bpb
.bytes_per_sector
) - 1)
236 >> (data
->logical_sector_bits
+ GRUB_DISK_SECTOR_BITS
))
237 << (data
->logical_sector_bits
));
239 data
->cluster_sector
= data
->root_sector
+ data
->num_root_sectors
;
240 data
->num_clusters
= (((data
->num_sectors
- data
->cluster_sector
)
241 >> (data
->cluster_bits
+ data
->logical_sector_bits
))
244 if (data
->num_clusters
<= 2)
247 if (! bpb
.sectors_per_fat_16
)
250 grub_uint16_t flags
= grub_le_to_cpu16 (bpb
.version_specific
.fat32
.extended_flags
);
252 data
->root_cluster
= grub_le_to_cpu32 (bpb
.version_specific
.fat32
.root_cluster
);
254 data
->cluster_eof_mark
= 0x0ffffff8;
258 /* Get an active FAT. */
259 unsigned active_fat
= flags
& 0xf;
261 if (active_fat
> bpb
.num_fats
)
264 data
->fat_sector
+= active_fat
* data
->sectors_per_fat
;
267 if (bpb
.num_root_entries
!= 0 || bpb
.version_specific
.fat32
.fs_version
!= 0)
272 /* FAT12 or FAT16. */
273 data
->root_cluster
= ~0U;
275 if (data
->num_clusters
<= 4085 + 2)
279 data
->cluster_eof_mark
= 0x0ff8;
285 data
->cluster_eof_mark
= 0xfff8;
289 /* More sanity checks. */
290 if (data
->num_sectors
<= data
->fat_sector
)
293 if (grub_disk_read (disk
,
300 first_fat
= grub_le_to_cpu32 (first_fat
);
302 if (data
->fat_size
== 32)
304 first_fat
&= 0x0fffffff;
307 else if (data
->fat_size
== 16)
309 first_fat
&= 0x0000ffff;
314 first_fat
&= 0x00000fff;
319 if (bpb
.sectors_per_fat_16
)
320 data
->uuid
= grub_le_to_cpu32 (bpb
.version_specific
.fat12_or_fat16
.num_serial
);
322 data
->uuid
= grub_le_to_cpu32 (bpb
.version_specific
.fat32
.num_serial
);
324 /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
325 descriptor, even if it is a so-called superfloppy (e.g. an USB key).
326 The check may be too strict for this kind of stupid BIOSes, as
327 they overwrite the media descriptor. */
328 if ((first_fat
| 0x8) != (magic
| bpb
.media
| 0x8))
331 /* Start from the root directory. */
332 data
->file_cluster
= data
->root_cluster
;
333 data
->cur_cluster_num
= ~0U;
334 data
->attr
= GRUB_FAT_ATTR_DIRECTORY
;
340 grub_error (GRUB_ERR_BAD_FS
, "not a fat filesystem");
345 grub_fat_read_data (grub_disk_t disk
, struct grub_fat_data
*data
,
346 void NESTED_FUNC_ATTR (*read_hook
) (grub_disk_addr_t sector
,
347 unsigned offset
, unsigned length
),
348 grub_off_t offset
, grub_size_t len
, char *buf
)
351 grub_uint32_t logical_cluster
;
352 unsigned logical_cluster_bits
;
353 grub_ssize_t ret
= 0;
354 unsigned long sector
;
356 /* This is a special case. FAT12 and FAT16 doesn't have the root directory
358 if (data
->file_cluster
== ~0U)
360 size
= (data
->num_root_sectors
<< GRUB_DISK_SECTOR_BITS
) - offset
;
364 if (grub_disk_read (disk
, data
->root_sector
, offset
, size
, buf
))
370 /* Calculate the logical cluster number and offset. */
371 logical_cluster_bits
= (data
->cluster_bits
372 + data
->logical_sector_bits
373 + GRUB_DISK_SECTOR_BITS
);
374 logical_cluster
= offset
>> logical_cluster_bits
;
375 offset
&= (1 << logical_cluster_bits
) - 1;
377 if (logical_cluster
< data
->cur_cluster_num
)
379 data
->cur_cluster_num
= 0;
380 data
->cur_cluster
= data
->file_cluster
;
385 while (logical_cluster
> data
->cur_cluster_num
)
387 /* Find next cluster. */
388 grub_uint32_t next_cluster
;
389 unsigned long fat_offset
;
391 switch (data
->fat_size
)
394 fat_offset
= data
->cur_cluster
<< 2;
397 fat_offset
= data
->cur_cluster
<< 1;
401 fat_offset
= data
->cur_cluster
+ (data
->cur_cluster
>> 1);
406 if (grub_disk_read (disk
, data
->fat_sector
, fat_offset
,
407 (data
->fat_size
+ 7) >> 3,
408 (char *) &next_cluster
))
411 next_cluster
= grub_le_to_cpu32 (next_cluster
);
412 switch (data
->fat_size
)
415 next_cluster
&= 0xFFFF;
418 if (data
->cur_cluster
& 1)
421 next_cluster
&= 0x0FFF;
425 grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
426 data
->fat_size
, next_cluster
);
429 if (next_cluster
>= data
->cluster_eof_mark
)
432 if (next_cluster
< 2 || next_cluster
>= data
->num_clusters
)
434 grub_error (GRUB_ERR_BAD_FS
, "invalid cluster %u",
439 data
->cur_cluster
= next_cluster
;
440 data
->cur_cluster_num
++;
443 /* Read the data here. */
444 sector
= (data
->cluster_sector
445 + ((data
->cur_cluster
- 2)
446 << (data
->cluster_bits
+ data
->logical_sector_bits
)));
447 size
= (1 << logical_cluster_bits
) - offset
;
451 disk
->read_hook
= read_hook
;
452 grub_disk_read (disk
, sector
, offset
, size
, buf
);
468 grub_fat_iterate_dir (grub_disk_t disk
, struct grub_fat_data
*data
,
469 int (*hook
) (const char *filename
,
470 struct grub_fat_dir_entry
*dir
))
472 struct grub_fat_dir_entry dir
;
473 char *filename
, *filep
= 0;
474 grub_uint16_t
*unibuf
;
475 int slot
= -1, slots
= -1;
477 grub_ssize_t offset
= -sizeof(dir
);
479 if (! (data
->attr
& GRUB_FAT_ATTR_DIRECTORY
))
480 return grub_error (GRUB_ERR_BAD_FILE_TYPE
, "not a directory");
482 /* Allocate space enough to hold a long name. */
483 filename
= grub_malloc (0x40 * 13 * 4 + 1);
484 unibuf
= (grub_uint16_t
*) grub_malloc (0x40 * 13 * 2);
485 if (! filename
|| ! unibuf
)
487 grub_free (filename
);
496 /* Adjust the offset. */
497 offset
+= sizeof (dir
);
499 /* Read a directory entry. */
500 if ((grub_fat_read_data (disk
, data
, 0,
501 offset
, sizeof (dir
), (char *) &dir
)
502 != sizeof (dir
) || dir
.name
[0] == 0))
504 /* Handle long name entries. */
505 if (dir
.attr
== GRUB_FAT_ATTR_LONG_NAME
)
507 struct grub_fat_long_name_entry
*long_name
508 = (struct grub_fat_long_name_entry
*) &dir
;
509 grub_uint8_t id
= long_name
->id
;
515 checksum
= long_name
->checksum
;
518 if (id
!= slot
|| slot
== 0 || checksum
!= long_name
->checksum
)
525 grub_memcpy (unibuf
+ slot
* 13, long_name
->name1
, 5 * 2);
526 grub_memcpy (unibuf
+ slot
* 13 + 5, long_name
->name2
, 6 * 2);
527 grub_memcpy (unibuf
+ slot
* 13 + 11, long_name
->name3
, 2 * 2);
531 /* Check if this entry is valid. */
532 if (dir
.name
[0] == 0xe5 || (dir
.attr
& ~GRUB_FAT_ATTR_VALID
))
535 /* This is a workaround for Japanese. */
536 if (dir
.name
[0] == 0x05)
539 if (checksum
!= -1 && slot
== 0)
543 for (sum
= 0, i
= 0; i
< sizeof (dir
.name
); i
++)
544 sum
= ((sum
>> 1) | (sum
<< 7)) + dir
.name
[i
];
550 for (u
= 0; u
< slots
* 13; u
++)
551 unibuf
[u
] = grub_le_to_cpu16 (unibuf
[u
]);
553 *grub_utf16_to_utf8 ((grub_uint8_t
*) filename
, unibuf
,
556 if (hook (filename
, &dir
))
566 /* Convert the 8.3 file name. */
568 if (dir
.attr
& GRUB_FAT_ATTR_VOLUME_ID
)
570 for (i
= 0; i
< sizeof (dir
.name
) && dir
.name
[i
]
571 && ! grub_isspace (dir
.name
[i
]); i
++)
572 *filep
++ = dir
.name
[i
];
576 for (i
= 0; i
< 8 && dir
.name
[i
] && ! grub_isspace (dir
.name
[i
]); i
++)
577 *filep
++ = grub_tolower (dir
.name
[i
]);
581 for (i
= 8; i
< 11 && dir
.name
[i
] && ! grub_isspace (dir
.name
[i
]); i
++)
582 *++filep
= grub_tolower (dir
.name
[i
]);
589 if (hook (filename
, &dir
))
593 grub_free (filename
);
599 /* Find the underlying directory or file in PATH and return the
600 next path. If there is no next path or an error occurs, return NULL.
601 If HOOK is specified, call it with each file name. */
603 grub_fat_find_dir (grub_disk_t disk
, struct grub_fat_data
*data
,
605 int (*hook
) (const char *filename
,
606 const struct grub_dirhook_info
*info
))
608 char *dirname
, *dirp
;
612 auto int iter_hook (const char *filename
, struct grub_fat_dir_entry
*dir
);
613 int iter_hook (const char *filename
, struct grub_fat_dir_entry
*dir
)
615 struct grub_dirhook_info info
;
616 grub_memset (&info
, 0, sizeof (info
));
618 info
.dir
= !! (dir
->attr
& GRUB_FAT_ATTR_DIRECTORY
);
619 info
.case_insensitive
= 1;
621 if (dir
->attr
& GRUB_FAT_ATTR_VOLUME_ID
)
623 if (*dirname
== '\0' && call_hook
)
624 return hook (filename
, &info
);
626 if (grub_strcasecmp (dirname
, filename
) == 0)
629 data
->attr
= dir
->attr
;
630 data
->file_size
= grub_le_to_cpu32 (dir
->file_size
);
631 data
->file_cluster
= ((grub_le_to_cpu16 (dir
->first_cluster_high
) << 16)
632 | grub_le_to_cpu16 (dir
->first_cluster_low
));
633 data
->cur_cluster_num
= ~0U;
636 hook (filename
, &info
);
643 if (! (data
->attr
& GRUB_FAT_ATTR_DIRECTORY
))
645 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "not a directory");
649 /* Extract a directory name. */
653 dirp
= grub_strchr (path
, '/');
656 unsigned len
= dirp
- path
;
658 dirname
= grub_malloc (len
+ 1);
662 grub_memcpy (dirname
, path
, len
);
666 /* This is actually a file. */
667 dirname
= grub_strdup (path
);
669 call_hook
= (! dirp
&& hook
);
671 grub_fat_iterate_dir (disk
, data
, iter_hook
);
672 if (grub_errno
== GRUB_ERR_NONE
&& ! found
&& !call_hook
)
673 grub_error (GRUB_ERR_FILE_NOT_FOUND
, "file not found");
677 return found
? dirp
: 0;
681 grub_fat_dir (grub_device_t device
, const char *path
,
682 int (*hook
) (const char *filename
,
683 const struct grub_dirhook_info
*info
))
685 struct grub_fat_data
*data
= 0;
686 grub_disk_t disk
= device
->disk
;
691 grub_dl_ref (my_mod
);
693 data
= grub_fat_mount (disk
);
697 /* Make sure that DIRNAME terminates with '/'. */
698 len
= grub_strlen (path
);
699 dirname
= grub_malloc (len
+ 1 + 1);
702 grub_memcpy (dirname
, path
, len
);
704 if (path
[len
- 1] != '/')
711 p
= grub_fat_find_dir (disk
, data
, p
, hook
);
713 while (p
&& grub_errno
== GRUB_ERR_NONE
);
720 grub_dl_unref (my_mod
);
726 grub_fat_open (grub_file_t file
, const char *name
)
728 struct grub_fat_data
*data
= 0;
729 char *p
= (char *) name
;
731 grub_dl_ref (my_mod
);
733 data
= grub_fat_mount (file
->device
->disk
);
739 p
= grub_fat_find_dir (file
->device
->disk
, data
, p
, 0);
740 if (grub_errno
!= GRUB_ERR_NONE
)
745 if (data
->attr
& GRUB_FAT_ATTR_DIRECTORY
)
747 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "not a file");
752 file
->size
= data
->file_size
;
754 return GRUB_ERR_NONE
;
760 grub_dl_unref (my_mod
);
766 grub_fat_read (grub_file_t file
, char *buf
, grub_size_t len
)
768 return grub_fat_read_data (file
->device
->disk
, file
->data
, file
->read_hook
,
769 file
->offset
, len
, buf
);
773 grub_fat_close (grub_file_t file
)
775 grub_free (file
->data
);
777 grub_dl_unref (my_mod
);
783 grub_fat_label (grub_device_t device
, char **label
)
785 struct grub_fat_data
*data
;
786 grub_disk_t disk
= device
->disk
;
788 auto int iter_hook (const char *filename
, struct grub_fat_dir_entry
*dir
);
789 int iter_hook (const char *filename
, struct grub_fat_dir_entry
*dir
)
791 if (dir
->attr
== GRUB_FAT_ATTR_VOLUME_ID
)
793 *label
= grub_strdup (filename
);
799 grub_dl_ref (my_mod
);
801 data
= grub_fat_mount (disk
);
805 if (! (data
->attr
& GRUB_FAT_ATTR_DIRECTORY
))
807 grub_error (GRUB_ERR_BAD_FILE_TYPE
, "not a directory");
813 grub_fat_iterate_dir (disk
, data
, iter_hook
);
817 grub_dl_unref (my_mod
);
825 grub_fat_uuid (grub_device_t device
, char **uuid
)
827 struct grub_fat_data
*data
;
828 grub_disk_t disk
= device
->disk
;
830 grub_dl_ref (my_mod
);
832 data
= grub_fat_mount (disk
);
835 *uuid
= grub_malloc (sizeof ("xxxx-xxxx"));
836 grub_sprintf (*uuid
, "%04x-%04x", (grub_uint16_t
) (data
->uuid
>> 16),
837 (grub_uint16_t
) data
->uuid
);
842 grub_dl_unref (my_mod
);
849 static struct grub_fs grub_fat_fs
=
853 .open
= grub_fat_open
,
854 .read
= grub_fat_read
,
855 .close
= grub_fat_close
,
856 .label
= grub_fat_label
,
857 .uuid
= grub_fat_uuid
,
859 .reserved_first_sector
= 1,
866 grub_fs_register (&grub_fat_fs
);
872 grub_fs_unregister (&grub_fat_fs
);