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>
28 #include <grub/charset.h>
32 #include <grub/exfat.h>
34 #include <grub/i18n.h>
36 GRUB_MOD_LICENSE ("GPLv3+");
40 GRUB_FAT_ATTR_READ_ONLY
= 0x01,
41 GRUB_FAT_ATTR_HIDDEN
= 0x02,
42 GRUB_FAT_ATTR_SYSTEM
= 0x04,
44 GRUB_FAT_ATTR_VOLUME_ID
= 0x08,
46 GRUB_FAT_ATTR_DIRECTORY
= 0x10,
47 GRUB_FAT_ATTR_ARCHIVE
= 0x20,
50 GRUB_FAT_ATTR_LONG_NAME
= (GRUB_FAT_ATTR_READ_ONLY
51 | GRUB_FAT_ATTR_HIDDEN
52 | GRUB_FAT_ATTR_SYSTEM
53 | GRUB_FAT_ATTR_VOLUME_ID
),
55 GRUB_FAT_ATTR_VALID
= (GRUB_FAT_ATTR_READ_ONLY
56 | GRUB_FAT_ATTR_HIDDEN
57 | GRUB_FAT_ATTR_SYSTEM
58 | GRUB_FAT_ATTR_DIRECTORY
59 | GRUB_FAT_ATTR_ARCHIVE
61 | GRUB_FAT_ATTR_VOLUME_ID
67 typedef struct grub_exfat_bpb grub_current_fat_bpb_t
;
69 typedef struct grub_fat_bpb grub_current_fat_bpb_t
;
77 struct grub_fat_dir_entry
79 grub_uint8_t entry_type
;
82 grub_uint8_t placeholder
[31];
84 grub_uint8_t secondary_count
;
85 grub_uint16_t checksum
;
87 grub_uint16_t reserved1
;
91 grub_uint8_t c_time_tenth
;
92 grub_uint8_t m_time_tenth
;
93 grub_uint8_t a_time_tenth
;
94 grub_uint8_t reserved2
[9];
98 grub_uint8_t reserved1
;
99 grub_uint8_t name_length
;
100 grub_uint16_t name_hash
;
101 grub_uint16_t reserved2
;
102 grub_uint64_t valid_size
;
103 grub_uint32_t reserved3
;
104 grub_uint32_t first_cluster
;
105 grub_uint64_t file_size
;
106 } GRUB_PACKED stream_extension
;
109 grub_uint16_t str
[15];
110 } GRUB_PACKED file_name
;
112 grub_uint8_t character_count
;
113 grub_uint16_t str
[15];
114 } GRUB_PACKED volume_label
;
115 } GRUB_PACKED type_specific
;
118 struct grub_fat_dir_node
121 grub_uint32_t first_cluster
;
122 grub_uint64_t file_size
;
123 grub_uint64_t valid_size
;
128 typedef struct grub_fat_dir_node grub_fat_dir_node_t
;
131 struct grub_fat_dir_entry
133 grub_uint8_t name
[11];
135 grub_uint8_t nt_reserved
;
136 grub_uint8_t c_time_tenth
;
137 grub_uint16_t c_time
;
138 grub_uint16_t c_date
;
139 grub_uint16_t a_date
;
140 grub_uint16_t first_cluster_high
;
141 grub_uint16_t w_time
;
142 grub_uint16_t w_date
;
143 grub_uint16_t first_cluster_low
;
144 grub_uint32_t file_size
;
147 struct grub_fat_long_name_entry
150 grub_uint16_t name1
[5];
152 grub_uint8_t reserved
;
153 grub_uint8_t checksum
;
154 grub_uint16_t name2
[6];
155 grub_uint16_t first_cluster
;
156 grub_uint16_t name3
[2];
159 typedef struct grub_fat_dir_entry grub_fat_dir_node_t
;
165 int logical_sector_bits
;
166 grub_uint32_t num_sectors
;
168 grub_uint32_t fat_sector
;
169 grub_uint32_t sectors_per_fat
;
172 grub_uint32_t root_cluster
;
174 grub_uint32_t root_sector
;
175 grub_uint32_t num_root_sectors
;
181 grub_uint32_t cluster_eof_mark
;
182 grub_uint32_t cluster_sector
;
183 grub_uint32_t num_clusters
;
186 grub_ssize_t file_size
;
187 grub_uint32_t file_cluster
;
188 grub_uint32_t cur_cluster_num
;
189 grub_uint32_t cur_cluster
;
194 static grub_dl_t my_mod
;
198 fat_log2 (unsigned x
)
205 for (i
= 0; (x
& 1) == 0; i
++)
215 static struct grub_fat_data
*
216 grub_fat_mount (grub_disk_t disk
)
218 grub_current_fat_bpb_t bpb
;
219 struct grub_fat_data
*data
= 0;
220 grub_uint32_t first_fat
, magic
;
225 data
= (struct grub_fat_data
*) grub_malloc (sizeof (*data
));
230 if (grub_disk_read (disk
, 0, 0, sizeof (bpb
), &bpb
))
234 if (grub_memcmp ((const char *) bpb
.oem_name
, "EXFAT ",
235 sizeof (bpb
.oem_name
)) != 0)
239 /* Get the sizes of logical sectors and clusters. */
241 data
->logical_sector_bits
= bpb
.bytes_per_sector_shift
;
243 data
->logical_sector_bits
=
244 fat_log2 (grub_le_to_cpu16 (bpb
.bytes_per_sector
));
246 if (data
->logical_sector_bits
< GRUB_DISK_SECTOR_BITS
247 || data
->logical_sector_bits
>= 16)
249 data
->logical_sector_bits
-= GRUB_DISK_SECTOR_BITS
;
252 data
->cluster_bits
= bpb
.sectors_per_cluster_shift
;
254 data
->cluster_bits
= fat_log2 (bpb
.sectors_per_cluster
);
256 if (data
->cluster_bits
< 0 || data
->cluster_bits
> 25)
258 data
->cluster_bits
+= data
->logical_sector_bits
;
260 /* Get information about FATs. */
262 data
->fat_sector
= (grub_le_to_cpu32 (bpb
.num_reserved_sectors
)
263 << data
->logical_sector_bits
);
265 data
->fat_sector
= (grub_le_to_cpu16 (bpb
.num_reserved_sectors
)
266 << data
->logical_sector_bits
);
268 if (data
->fat_sector
== 0)
272 data
->sectors_per_fat
= (grub_le_to_cpu32 (bpb
.sectors_per_fat
)
273 << data
->logical_sector_bits
);
275 data
->sectors_per_fat
= ((bpb
.sectors_per_fat_16
276 ? grub_le_to_cpu16 (bpb
.sectors_per_fat_16
)
277 : grub_le_to_cpu32 (bpb
.version_specific
.fat32
.sectors_per_fat_32
))
278 << data
->logical_sector_bits
);
280 if (data
->sectors_per_fat
== 0)
283 /* Get the number of sectors in this volume. */
285 data
->num_sectors
= ((grub_le_to_cpu64 (bpb
.num_total_sectors
))
286 << data
->logical_sector_bits
);
288 data
->num_sectors
= ((bpb
.num_total_sectors_16
289 ? grub_le_to_cpu16 (bpb
.num_total_sectors_16
)
290 : grub_le_to_cpu32 (bpb
.num_total_sectors_32
))
291 << data
->logical_sector_bits
);
293 if (data
->num_sectors
== 0)
296 /* Get information about the root directory. */
297 if (bpb
.num_fats
== 0)
301 data
->root_sector
= data
->fat_sector
+ bpb
.num_fats
* data
->sectors_per_fat
;
302 data
->num_root_sectors
303 = ((((grub_uint32_t
) grub_le_to_cpu16 (bpb
.num_root_entries
)
304 * sizeof (struct grub_fat_dir_entry
)
305 + grub_le_to_cpu16 (bpb
.bytes_per_sector
) - 1)
306 >> (data
->logical_sector_bits
+ GRUB_DISK_SECTOR_BITS
))
307 << (data
->logical_sector_bits
));
311 data
->cluster_sector
= (grub_le_to_cpu32 (bpb
.cluster_offset
)
312 << data
->logical_sector_bits
);
313 data
->num_clusters
= (grub_le_to_cpu32 (bpb
.cluster_count
)
314 << data
->logical_sector_bits
);
316 data
->cluster_sector
= data
->root_sector
+ data
->num_root_sectors
;
317 data
->num_clusters
= (((data
->num_sectors
- data
->cluster_sector
)
318 >> data
->cluster_bits
)
322 if (data
->num_clusters
<= 2)
328 data
->root_cluster
= grub_le_to_cpu32 (bpb
.root_cluster
);
330 data
->cluster_eof_mark
= 0xffffffff;
332 if ((bpb
.volume_flags
& grub_cpu_to_le16_compile_time (0x1))
334 data
->fat_sector
+= data
->sectors_per_fat
;
337 if (! bpb
.sectors_per_fat_16
)
340 grub_uint16_t flags
= grub_le_to_cpu16 (bpb
.version_specific
.fat32
.extended_flags
);
342 data
->root_cluster
= grub_le_to_cpu32 (bpb
.version_specific
.fat32
.root_cluster
);
344 data
->cluster_eof_mark
= 0x0ffffff8;
348 /* Get an active FAT. */
349 unsigned active_fat
= flags
& 0xf;
351 if (active_fat
> bpb
.num_fats
)
354 data
->fat_sector
+= active_fat
* data
->sectors_per_fat
;
357 if (bpb
.num_root_entries
!= 0 || bpb
.version_specific
.fat32
.fs_version
!= 0)
362 /* FAT12 or FAT16. */
363 data
->root_cluster
= ~0U;
365 if (data
->num_clusters
<= 4085 + 2)
369 data
->cluster_eof_mark
= 0x0ff8;
375 data
->cluster_eof_mark
= 0xfff8;
380 /* More sanity checks. */
381 if (data
->num_sectors
<= data
->fat_sector
)
384 if (grub_disk_read (disk
,
391 first_fat
= grub_le_to_cpu32 (first_fat
);
393 if (data
->fat_size
== 32)
395 first_fat
&= 0x0fffffff;
398 else if (data
->fat_size
== 16)
400 first_fat
&= 0x0000ffff;
405 first_fat
&= 0x00000fff;
411 data
->uuid
= grub_le_to_cpu32 (bpb
.num_serial
);
413 if (bpb
.sectors_per_fat_16
)
414 data
->uuid
= grub_le_to_cpu32 (bpb
.version_specific
.fat12_or_fat16
.num_serial
);
416 data
->uuid
= grub_le_to_cpu32 (bpb
.version_specific
.fat32
.num_serial
);
420 /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
421 descriptor, even if it is a so-called superfloppy (e.g. an USB key).
422 The check may be too strict for this kind of stupid BIOSes, as
423 they overwrite the media descriptor. */
424 if ((first_fat
| 0x8) != (magic
| bpb
.media
| 0x8))
430 /* Start from the root directory. */
431 data
->file_cluster
= data
->root_cluster
;
432 data
->cur_cluster_num
= ~0U;
433 data
->attr
= GRUB_FAT_ATTR_DIRECTORY
;
435 data
->is_contiguous
= 0;
442 grub_error (GRUB_ERR_BAD_FS
, "not a FAT filesystem");
447 grub_fat_read_data (grub_disk_t disk
, struct grub_fat_data
*data
,
448 grub_disk_read_hook_t read_hook
, void *read_hook_data
,
449 grub_off_t offset
, grub_size_t len
, char *buf
)
452 grub_uint32_t logical_cluster
;
453 unsigned logical_cluster_bits
;
454 grub_ssize_t ret
= 0;
455 unsigned long sector
;
458 /* This is a special case. FAT12 and FAT16 doesn't have the root directory
460 if (data
->file_cluster
== ~0U)
462 size
= (data
->num_root_sectors
<< GRUB_DISK_SECTOR_BITS
) - offset
;
466 if (grub_disk_read (disk
, data
->root_sector
, offset
, size
, buf
))
474 if (data
->is_contiguous
)
476 /* Read the data here. */
477 sector
= (data
->cluster_sector
478 + ((data
->file_cluster
- 2)
479 << data
->cluster_bits
));
481 disk
->read_hook
= read_hook
;
482 disk
->read_hook_data
= read_hook_data
;
483 grub_disk_read (disk
, sector
+ (offset
>> GRUB_DISK_SECTOR_BITS
),
484 offset
& (GRUB_DISK_SECTOR_SIZE
- 1), len
, buf
);
493 /* Calculate the logical cluster number and offset. */
494 logical_cluster_bits
= (data
->cluster_bits
495 + GRUB_DISK_SECTOR_BITS
);
496 logical_cluster
= offset
>> logical_cluster_bits
;
497 offset
&= (1ULL << logical_cluster_bits
) - 1;
499 if (logical_cluster
< data
->cur_cluster_num
)
501 data
->cur_cluster_num
= 0;
502 data
->cur_cluster
= data
->file_cluster
;
507 while (logical_cluster
> data
->cur_cluster_num
)
509 /* Find next cluster. */
510 grub_uint32_t next_cluster
;
511 grub_uint32_t fat_offset
;
513 switch (data
->fat_size
)
516 fat_offset
= data
->cur_cluster
<< 2;
519 fat_offset
= data
->cur_cluster
<< 1;
523 fat_offset
= data
->cur_cluster
+ (data
->cur_cluster
>> 1);
528 if (grub_disk_read (disk
, data
->fat_sector
, fat_offset
,
529 (data
->fat_size
+ 7) >> 3,
530 (char *) &next_cluster
))
533 next_cluster
= grub_le_to_cpu32 (next_cluster
);
534 switch (data
->fat_size
)
537 next_cluster
&= 0xFFFF;
540 if (data
->cur_cluster
& 1)
543 next_cluster
&= 0x0FFF;
547 grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
548 data
->fat_size
, next_cluster
);
551 if (next_cluster
>= data
->cluster_eof_mark
)
554 if (next_cluster
< 2 || next_cluster
>= data
->num_clusters
)
556 grub_error (GRUB_ERR_BAD_FS
, "invalid cluster %u",
561 data
->cur_cluster
= next_cluster
;
562 data
->cur_cluster_num
++;
565 /* Read the data here. */
566 sector
= (data
->cluster_sector
567 + ((data
->cur_cluster
- 2)
568 << data
->cluster_bits
));
569 size
= (1 << logical_cluster_bits
) - offset
;
573 disk
->read_hook
= read_hook
;
574 disk
->read_hook_data
= read_hook_data
;
575 grub_disk_read (disk
, sector
, offset
, size
, buf
);
590 struct grub_fat_iterate_context
593 struct grub_fat_dir_node dir
;
595 struct grub_fat_dir_entry dir
;
598 grub_uint16_t
*unibuf
;
603 grub_fat_iterate_init (struct grub_fat_iterate_context
*ctxt
)
605 ctxt
->offset
= -sizeof (struct grub_fat_dir_entry
);
608 /* Allocate space enough to hold a long name. */
609 ctxt
->filename
= grub_malloc (0x40 * 13 * GRUB_MAX_UTF8_PER_UTF16
+ 1);
610 ctxt
->unibuf
= (grub_uint16_t
*) grub_malloc (0x40 * 13 * 2);
612 ctxt
->unibuf
= grub_malloc (15 * 256 * 2);
613 ctxt
->filename
= grub_malloc (15 * 256 * GRUB_MAX_UTF8_PER_UTF16
+ 1);
616 if (! ctxt
->filename
|| ! ctxt
->unibuf
)
618 grub_free (ctxt
->filename
);
619 grub_free (ctxt
->unibuf
);
622 return GRUB_ERR_NONE
;
626 grub_fat_iterate_fini (struct grub_fat_iterate_context
*ctxt
)
628 grub_free (ctxt
->filename
);
629 grub_free (ctxt
->unibuf
);
634 grub_fat_iterate_dir_next (grub_disk_t disk
, struct grub_fat_data
*data
,
635 struct grub_fat_iterate_context
*ctxt
)
637 grub_memset (&ctxt
->dir
, 0, sizeof (ctxt
->dir
));
640 struct grub_fat_dir_entry dir
;
642 ctxt
->offset
+= sizeof (dir
);
644 if (grub_fat_read_data (disk
, data
, 0, 0, ctxt
->offset
, sizeof (dir
),
649 if (dir
.entry_type
== 0)
651 if (!(dir
.entry_type
& 0x80))
654 if (dir
.entry_type
== 0x85)
656 unsigned i
, nsec
, slots
= 0;
658 nsec
= dir
.type_specific
.file
.secondary_count
;
660 ctxt
->dir
.attr
= grub_cpu_to_le16 (dir
.type_specific
.file
.attr
);
661 ctxt
->dir
.have_stream
= 0;
662 for (i
= 0; i
< nsec
; i
++)
664 struct grub_fat_dir_entry sec
;
665 ctxt
->offset
+= sizeof (sec
);
666 if (grub_fat_read_data (disk
, data
, 0, 0,
667 ctxt
->offset
, sizeof (sec
), (char *) &sec
)
670 if (!(sec
.entry_type
& 0x80))
672 if (!(sec
.entry_type
& 0x40))
674 switch (sec
.entry_type
)
677 ctxt
->dir
.first_cluster
= grub_cpu_to_le32 (sec
.type_specific
.stream_extension
.first_cluster
);
679 = grub_cpu_to_le64 (sec
.type_specific
.stream_extension
.valid_size
);
681 = grub_cpu_to_le64 (sec
.type_specific
.stream_extension
.file_size
);
682 ctxt
->dir
.have_stream
= 1;
683 ctxt
->dir
.is_contiguous
= !!(dir
.type_specific
.stream_extension
.flags
684 & grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS
));
689 for (j
= 0; j
< 15; j
++)
690 ctxt
->unibuf
[slots
* 15 + j
]
691 = grub_le_to_cpu16 (sec
.type_specific
.file_name
.str
[j
]);
696 grub_dprintf ("exfat", "unknown secondary type 0x%02x\n",
703 ctxt
->offset
-= sizeof (dir
);
707 *grub_utf16_to_utf8 ((grub_uint8_t
*) ctxt
->filename
, ctxt
->unibuf
,
712 /* Allocation bitmap. */
713 if (dir
.entry_type
== 0x81)
716 if (dir
.entry_type
== 0x82)
719 if (dir
.entry_type
== 0x83)
721 grub_dprintf ("exfat", "unknown primary type 0x%02x\n",
724 return grub_errno
? : GRUB_ERR_EOF
;
730 grub_fat_iterate_dir_next (grub_disk_t disk
, struct grub_fat_data
*data
,
731 struct grub_fat_iterate_context
*ctxt
)
735 int slot
= -1, slots
= -1;
741 /* Adjust the offset. */
742 ctxt
->offset
+= sizeof (ctxt
->dir
);
744 /* Read a directory entry. */
745 if (grub_fat_read_data (disk
, data
, 0, 0,
746 ctxt
->offset
, sizeof (ctxt
->dir
),
748 != sizeof (ctxt
->dir
) || ctxt
->dir
.name
[0] == 0)
751 /* Handle long name entries. */
752 if (ctxt
->dir
.attr
== GRUB_FAT_ATTR_LONG_NAME
)
754 struct grub_fat_long_name_entry
*long_name
755 = (struct grub_fat_long_name_entry
*) &ctxt
->dir
;
756 grub_uint8_t id
= long_name
->id
;
762 checksum
= long_name
->checksum
;
765 if (id
!= slot
|| slot
== 0 || checksum
!= long_name
->checksum
)
772 grub_memcpy (ctxt
->unibuf
+ slot
* 13, long_name
->name1
, 5 * 2);
773 grub_memcpy (ctxt
->unibuf
+ slot
* 13 + 5, long_name
->name2
, 6 * 2);
774 grub_memcpy (ctxt
->unibuf
+ slot
* 13 + 11, long_name
->name3
, 2 * 2);
778 /* Check if this entry is valid. */
779 if (ctxt
->dir
.name
[0] == 0xe5 || (ctxt
->dir
.attr
& ~GRUB_FAT_ATTR_VALID
))
782 /* This is a workaround for Japanese. */
783 if (ctxt
->dir
.name
[0] == 0x05)
784 ctxt
->dir
.name
[0] = 0xe5;
786 if (checksum
!= -1 && slot
== 0)
790 for (sum
= 0, i
= 0; i
< sizeof (ctxt
->dir
.name
); i
++)
791 sum
= ((sum
>> 1) | (sum
<< 7)) + ctxt
->dir
.name
[i
];
797 for (u
= 0; u
< slots
* 13; u
++)
798 ctxt
->unibuf
[u
] = grub_le_to_cpu16 (ctxt
->unibuf
[u
]);
800 *grub_utf16_to_utf8 ((grub_uint8_t
*) ctxt
->filename
,
804 return GRUB_ERR_NONE
;
810 /* Convert the 8.3 file name. */
811 filep
= ctxt
->filename
;
812 if (ctxt
->dir
.attr
& GRUB_FAT_ATTR_VOLUME_ID
)
814 for (i
= 0; i
< sizeof (ctxt
->dir
.name
) && ctxt
->dir
.name
[i
]; i
++)
815 *filep
++ = ctxt
->dir
.name
[i
];
816 while (i
> 0 && ctxt
->dir
.name
[i
- 1] == ' ')
824 for (i
= 0; i
< 8 && ctxt
->dir
.name
[i
]; i
++)
825 *filep
++ = grub_tolower (ctxt
->dir
.name
[i
]);
826 while (i
> 0 && ctxt
->dir
.name
[i
- 1] == ' ')
834 for (i
= 8; i
< 11 && ctxt
->dir
.name
[i
]; i
++)
835 *filep
++ = grub_tolower (ctxt
->dir
.name
[i
]);
836 while (i
> 8 && ctxt
->dir
.name
[i
- 1] == ' ')
846 return GRUB_ERR_NONE
;
849 return grub_errno
? : GRUB_ERR_EOF
;
854 /* Find the underlying directory or file in PATH and return the
855 next path. If there is no next path or an error occurs, return NULL.
856 If HOOK is specified, call it with each file name. */
858 grub_fat_find_dir (grub_disk_t disk
, struct grub_fat_data
*data
,
859 const char *path
, const char *origpath
,
860 grub_fs_dir_hook_t hook
, void *hook_data
)
862 char *dirname
, *dirp
;
865 struct grub_fat_iterate_context ctxt
;
868 if (! (data
->attr
& GRUB_FAT_ATTR_DIRECTORY
))
870 grub_error (GRUB_ERR_BAD_FILE_TYPE
, N_("not a directory"));
874 /* Extract a directory name. */
878 dirp
= grub_strchr (path
, '/');
881 unsigned len
= dirp
- path
;
883 dirname
= grub_malloc (len
+ 1);
887 grub_memcpy (dirname
, path
, len
);
891 /* This is actually a file. */
892 dirname
= grub_strdup (path
);
894 call_hook
= (! dirp
&& hook
);
896 err
= grub_fat_iterate_init (&ctxt
);
903 while (!(err
= grub_fat_iterate_dir_next (disk
, data
, &ctxt
)))
905 struct grub_dirhook_info info
;
906 grub_memset (&info
, 0, sizeof (info
));
908 info
.dir
= !! (ctxt
.dir
.attr
& GRUB_FAT_ATTR_DIRECTORY
);
909 info
.case_insensitive
= 1;
912 if (!ctxt
.dir
.have_stream
)
915 if (ctxt
.dir
.attr
& GRUB_FAT_ATTR_VOLUME_ID
)
918 if (*dirname
== '\0' && call_hook
)
920 if (hook (ctxt
.filename
, &info
, hook_data
))
926 if (grub_strcasecmp (dirname
, ctxt
.filename
) == 0)
929 data
->attr
= ctxt
.dir
.attr
;
931 data
->file_size
= ctxt
.dir
.file_size
;
932 data
->file_cluster
= ctxt
.dir
.first_cluster
;
933 data
->is_contiguous
= ctxt
.dir
.is_contiguous
;
935 data
->file_size
= grub_le_to_cpu32 (ctxt
.dir
.file_size
);
936 data
->file_cluster
= ((grub_le_to_cpu16 (ctxt
.dir
.first_cluster_high
) << 16)
937 | grub_le_to_cpu16 (ctxt
.dir
.first_cluster_low
));
939 data
->cur_cluster_num
= ~0U;
942 hook (ctxt
.filename
, &info
, hook_data
);
948 grub_fat_iterate_fini (&ctxt
);
949 if (err
== GRUB_ERR_EOF
)
952 if (grub_errno
== GRUB_ERR_NONE
&& ! found
&& !call_hook
)
953 grub_error (GRUB_ERR_FILE_NOT_FOUND
, N_("file `%s' not found"), origpath
);
958 return found
? dirp
: 0;
962 grub_fat_dir (grub_device_t device
, const char *path
, grub_fs_dir_hook_t hook
,
965 struct grub_fat_data
*data
= 0;
966 grub_disk_t disk
= device
->disk
;
971 grub_dl_ref (my_mod
);
973 data
= grub_fat_mount (disk
);
977 /* Make sure that DIRNAME terminates with '/'. */
978 len
= grub_strlen (path
);
979 dirname
= grub_malloc (len
+ 1 + 1);
982 grub_memcpy (dirname
, path
, len
);
984 if (path
[len
- 1] != '/')
991 p
= grub_fat_find_dir (disk
, data
, p
, path
, hook
, hook_data
);
993 while (p
&& grub_errno
== GRUB_ERR_NONE
);
1000 grub_dl_unref (my_mod
);
1006 grub_fat_open (grub_file_t file
, const char *name
)
1008 struct grub_fat_data
*data
= 0;
1009 char *p
= (char *) name
;
1011 grub_dl_ref (my_mod
);
1013 data
= grub_fat_mount (file
->device
->disk
);
1019 p
= grub_fat_find_dir (file
->device
->disk
, data
, p
, name
, 0, 0);
1020 if (grub_errno
!= GRUB_ERR_NONE
)
1025 if (data
->attr
& GRUB_FAT_ATTR_DIRECTORY
)
1027 grub_error (GRUB_ERR_BAD_FILE_TYPE
, N_("not a regular file"));
1032 file
->size
= data
->file_size
;
1034 return GRUB_ERR_NONE
;
1040 grub_dl_unref (my_mod
);
1046 grub_fat_read (grub_file_t file
, char *buf
, grub_size_t len
)
1048 return grub_fat_read_data (file
->device
->disk
, file
->data
,
1049 file
->read_hook
, file
->read_hook_data
,
1050 file
->offset
, len
, buf
);
1054 grub_fat_close (grub_file_t file
)
1056 grub_free (file
->data
);
1058 grub_dl_unref (my_mod
);
1065 grub_fat_label (grub_device_t device
, char **label
)
1067 struct grub_fat_dir_entry dir
;
1068 grub_ssize_t offset
= -sizeof(dir
);
1069 struct grub_fat_data
*data
;
1070 grub_disk_t disk
= device
->disk
;
1072 data
= grub_fat_mount (disk
);
1080 offset
+= sizeof (dir
);
1082 if (grub_fat_read_data (disk
, data
, 0, 0,
1083 offset
, sizeof (dir
), (char *) &dir
)
1087 if (dir
.entry_type
== 0)
1089 if (!(dir
.entry_type
& 0x80))
1093 if (dir
.entry_type
== 0x83)
1096 grub_uint16_t t
[ARRAY_SIZE (dir
.type_specific
.volume_label
.str
)];
1098 *label
= grub_malloc (ARRAY_SIZE (dir
.type_specific
.volume_label
.str
)
1099 * GRUB_MAX_UTF8_PER_UTF16
+ 1);
1105 chc
= dir
.type_specific
.volume_label
.character_count
;
1106 if (chc
> ARRAY_SIZE (dir
.type_specific
.volume_label
.str
))
1107 chc
= ARRAY_SIZE (dir
.type_specific
.volume_label
.str
);
1108 for (i
= 0; i
< chc
; i
++)
1109 t
[i
] = grub_le_to_cpu16 (dir
.type_specific
.volume_label
.str
[i
]);
1110 *grub_utf16_to_utf8 ((grub_uint8_t
*) *label
, t
, chc
) = '\0';
1121 grub_fat_label (grub_device_t device
, char **label
)
1123 struct grub_fat_data
*data
;
1124 grub_disk_t disk
= device
->disk
;
1126 struct grub_fat_iterate_context ctxt
;
1130 grub_dl_ref (my_mod
);
1132 data
= grub_fat_mount (disk
);
1136 if (! (data
->attr
& GRUB_FAT_ATTR_DIRECTORY
))
1138 grub_error (GRUB_ERR_BAD_FILE_TYPE
, N_("not a directory"));
1142 err
= grub_fat_iterate_init (&ctxt
);
1146 while (!(err
= grub_fat_iterate_dir_next (disk
, data
, &ctxt
)))
1147 if ((ctxt
.dir
.attr
& ~GRUB_FAT_ATTR_ARCHIVE
) == GRUB_FAT_ATTR_VOLUME_ID
)
1149 *label
= grub_strdup (ctxt
.filename
);
1153 grub_fat_iterate_fini (&ctxt
);
1157 grub_dl_unref (my_mod
);
1167 grub_fat_uuid (grub_device_t device
, char **uuid
)
1169 struct grub_fat_data
*data
;
1170 grub_disk_t disk
= device
->disk
;
1172 grub_dl_ref (my_mod
);
1174 data
= grub_fat_mount (disk
);
1178 *uuid
= grub_xasprintf ("%04x-%04x",
1179 (grub_uint16_t
) (data
->uuid
>> 16),
1180 (grub_uint16_t
) data
->uuid
);
1181 for (ptr
= *uuid
; ptr
&& *ptr
; ptr
++)
1182 *ptr
= grub_toupper (*ptr
);
1187 grub_dl_unref (my_mod
);
1197 grub_fat_get_cluster_sector (grub_disk_t disk
, grub_uint64_t
*sec_per_lcn
)
1200 grub_exfat_get_cluster_sector (grub_disk_t disk
, grub_uint64_t
*sec_per_lcn
)
1203 grub_disk_addr_t ret
;
1204 struct grub_fat_data
*data
;
1205 data
= grub_fat_mount (disk
);
1208 ret
= data
->cluster_sector
;
1210 *sec_per_lcn
= 1ULL << data
->cluster_bits
;
1217 static struct grub_fs grub_fat_fs
=
1224 .dir
= grub_fat_dir
,
1225 .open
= grub_fat_open
,
1226 .read
= grub_fat_read
,
1227 .close
= grub_fat_close
,
1228 .label
= grub_fat_label
,
1229 .uuid
= grub_fat_uuid
,
1232 /* ExFAT BPB is 30 larger than FAT32 one. */
1233 .reserved_first_sector
= 0,
1235 .reserved_first_sector
= 1,
1237 .blocklist_install
= 1,
1243 GRUB_MOD_INIT(exfat
)
1248 COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry
) == 32);
1249 grub_fs_register (&grub_fat_fs
);
1253 GRUB_MOD_FINI(exfat
)
1258 grub_fs_unregister (&grub_fat_fs
);