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/fshelp.h>
35 #include <grub/i18n.h>
36 #include <grub/time.h>
37 #include <grub/ventoy.h>
39 GRUB_MOD_LICENSE ("GPLv3+");
43 GRUB_FAT_ATTR_READ_ONLY
= 0x01,
44 GRUB_FAT_ATTR_HIDDEN
= 0x02,
45 GRUB_FAT_ATTR_SYSTEM
= 0x04,
47 GRUB_FAT_ATTR_VOLUME_ID
= 0x08,
49 GRUB_FAT_ATTR_DIRECTORY
= 0x10,
50 GRUB_FAT_ATTR_ARCHIVE
= 0x20,
53 GRUB_FAT_ATTR_LONG_NAME
= (GRUB_FAT_ATTR_READ_ONLY
54 | GRUB_FAT_ATTR_HIDDEN
55 | GRUB_FAT_ATTR_SYSTEM
56 | GRUB_FAT_ATTR_VOLUME_ID
),
58 GRUB_FAT_ATTR_VALID
= (GRUB_FAT_ATTR_READ_ONLY
59 | GRUB_FAT_ATTR_HIDDEN
60 | GRUB_FAT_ATTR_SYSTEM
61 | GRUB_FAT_ATTR_DIRECTORY
62 | GRUB_FAT_ATTR_ARCHIVE
64 | GRUB_FAT_ATTR_VOLUME_ID
70 typedef struct grub_exfat_bpb grub_current_fat_bpb_t
;
72 typedef struct grub_fat_bpb grub_current_fat_bpb_t
;
80 struct grub_fat_dir_entry
82 grub_uint8_t entry_type
;
85 grub_uint8_t placeholder
[31];
87 grub_uint8_t secondary_count
;
88 grub_uint16_t checksum
;
90 grub_uint16_t reserved1
;
94 grub_uint8_t c_time_tenth
;
95 grub_uint8_t m_time_tenth
;
96 grub_uint8_t a_time_tenth
;
97 grub_uint8_t reserved2
[9];
101 grub_uint8_t reserved1
;
102 grub_uint8_t name_length
;
103 grub_uint16_t name_hash
;
104 grub_uint16_t reserved2
;
105 grub_uint64_t valid_size
;
106 grub_uint32_t reserved3
;
107 grub_uint32_t first_cluster
;
108 grub_uint64_t file_size
;
109 } GRUB_PACKED stream_extension
;
112 grub_uint16_t str
[15];
113 } GRUB_PACKED file_name
;
115 grub_uint8_t character_count
;
116 grub_uint16_t str
[15];
117 } GRUB_PACKED volume_label
;
118 } GRUB_PACKED type_specific
;
121 struct grub_fat_dir_node
124 grub_uint32_t first_cluster
;
125 grub_uint64_t file_size
;
126 grub_uint64_t valid_size
;
131 typedef struct grub_fat_dir_node grub_fat_dir_node_t
;
134 struct grub_fat_dir_entry
136 grub_uint8_t name
[11];
138 grub_uint8_t nt_reserved
;
139 grub_uint8_t c_time_tenth
;
140 grub_uint16_t c_time
;
141 grub_uint16_t c_date
;
142 grub_uint16_t a_date
;
143 grub_uint16_t first_cluster_high
;
144 grub_uint16_t w_time
;
145 grub_uint16_t w_date
;
146 grub_uint16_t first_cluster_low
;
147 grub_uint32_t file_size
;
150 struct grub_fat_long_name_entry
153 grub_uint16_t name1
[5];
155 grub_uint8_t reserved
;
156 grub_uint8_t checksum
;
157 grub_uint16_t name2
[6];
158 grub_uint16_t first_cluster
;
159 grub_uint16_t name3
[2];
162 typedef struct grub_fat_dir_entry grub_fat_dir_node_t
;
168 int logical_sector_bits
;
169 grub_uint32_t num_sectors
;
171 grub_uint32_t fat_sector
;
172 grub_uint32_t sectors_per_fat
;
175 grub_uint32_t root_cluster
;
177 grub_uint32_t root_sector
;
178 grub_uint32_t num_root_sectors
;
182 grub_uint32_t cluster_eof_mark
;
183 grub_uint32_t cluster_sector
;
184 grub_uint32_t num_clusters
;
189 struct grub_fshelp_node
{
191 struct grub_fat_data
*data
;
195 grub_uint32_t file_size
;
197 grub_uint64_t file_size
;
199 grub_uint32_t file_cluster
;
200 grub_uint32_t cur_cluster_num
;
201 grub_uint32_t cur_cluster
;
208 static grub_dl_t my_mod
;
212 fat_log2 (unsigned x
)
219 for (i
= 0; (x
& 1) == 0; i
++)
229 static struct grub_fat_data
*
230 grub_fat_mount (grub_disk_t disk
)
232 grub_current_fat_bpb_t bpb
;
233 struct grub_fat_data
*data
= 0;
234 grub_uint32_t first_fat
, magic
;
239 data
= (struct grub_fat_data
*) grub_malloc (sizeof (*data
));
244 if (grub_disk_read (disk
, 0, 0, sizeof (bpb
), &bpb
))
248 if (grub_memcmp ((const char *) bpb
.oem_name
, "EXFAT ",
249 sizeof (bpb
.oem_name
)) != 0)
253 /* Get the sizes of logical sectors and clusters. */
255 data
->logical_sector_bits
= bpb
.bytes_per_sector_shift
;
257 data
->logical_sector_bits
=
258 fat_log2 (grub_le_to_cpu16 (bpb
.bytes_per_sector
));
260 if (data
->logical_sector_bits
< GRUB_DISK_SECTOR_BITS
261 || data
->logical_sector_bits
>= 16)
263 data
->logical_sector_bits
-= GRUB_DISK_SECTOR_BITS
;
266 data
->cluster_bits
= bpb
.sectors_per_cluster_shift
;
268 data
->cluster_bits
= fat_log2 (bpb
.sectors_per_cluster
);
270 if (data
->cluster_bits
< 0 || data
->cluster_bits
> 25)
272 data
->cluster_bits
+= data
->logical_sector_bits
;
274 /* Get information about FATs. */
276 data
->fat_sector
= (grub_le_to_cpu32 (bpb
.num_reserved_sectors
)
277 << data
->logical_sector_bits
);
279 data
->fat_sector
= (grub_le_to_cpu16 (bpb
.num_reserved_sectors
)
280 << data
->logical_sector_bits
);
282 if (data
->fat_sector
== 0)
286 data
->sectors_per_fat
= (grub_le_to_cpu32 (bpb
.sectors_per_fat
)
287 << data
->logical_sector_bits
);
289 data
->sectors_per_fat
= ((bpb
.sectors_per_fat_16
290 ? grub_le_to_cpu16 (bpb
.sectors_per_fat_16
)
291 : grub_le_to_cpu32 (bpb
.version_specific
.fat32
.sectors_per_fat_32
))
292 << data
->logical_sector_bits
);
294 if (data
->sectors_per_fat
== 0)
297 /* Get the number of sectors in this volume. */
299 data
->num_sectors
= ((grub_le_to_cpu64 (bpb
.num_total_sectors
))
300 << data
->logical_sector_bits
);
302 data
->num_sectors
= ((bpb
.num_total_sectors_16
303 ? grub_le_to_cpu16 (bpb
.num_total_sectors_16
)
304 : grub_le_to_cpu32 (bpb
.num_total_sectors_32
))
305 << data
->logical_sector_bits
);
307 if (data
->num_sectors
== 0)
310 /* Get information about the root directory. */
311 if (bpb
.num_fats
== 0)
315 data
->root_sector
= data
->fat_sector
+ bpb
.num_fats
* data
->sectors_per_fat
;
316 data
->num_root_sectors
317 = ((((grub_uint32_t
) grub_le_to_cpu16 (bpb
.num_root_entries
)
318 * sizeof (struct grub_fat_dir_entry
)
319 + grub_le_to_cpu16 (bpb
.bytes_per_sector
) - 1)
320 >> (data
->logical_sector_bits
+ GRUB_DISK_SECTOR_BITS
))
321 << (data
->logical_sector_bits
));
325 data
->cluster_sector
= (grub_le_to_cpu32 (bpb
.cluster_offset
)
326 << data
->logical_sector_bits
);
327 data
->num_clusters
= (grub_le_to_cpu32 (bpb
.cluster_count
)
328 << data
->logical_sector_bits
);
330 data
->cluster_sector
= data
->root_sector
+ data
->num_root_sectors
;
331 data
->num_clusters
= (((data
->num_sectors
- data
->cluster_sector
)
332 >> data
->cluster_bits
)
336 if (data
->num_clusters
<= 2)
342 data
->root_cluster
= grub_le_to_cpu32 (bpb
.root_cluster
);
344 data
->cluster_eof_mark
= 0xffffffff;
346 if ((bpb
.volume_flags
& grub_cpu_to_le16_compile_time (0x1))
348 data
->fat_sector
+= data
->sectors_per_fat
;
351 if (! bpb
.sectors_per_fat_16
)
354 grub_uint16_t flags
= grub_le_to_cpu16 (bpb
.version_specific
.fat32
.extended_flags
);
356 data
->root_cluster
= grub_le_to_cpu32 (bpb
.version_specific
.fat32
.root_cluster
);
358 data
->cluster_eof_mark
= 0x0ffffff8;
362 /* Get an active FAT. */
363 unsigned active_fat
= flags
& 0xf;
365 if (active_fat
> bpb
.num_fats
)
368 data
->fat_sector
+= active_fat
* data
->sectors_per_fat
;
371 if (bpb
.num_root_entries
!= 0 || bpb
.version_specific
.fat32
.fs_version
!= 0)
376 /* FAT12 or FAT16. */
377 data
->root_cluster
= ~0U;
379 if (data
->num_clusters
<= 4085 + 2)
383 data
->cluster_eof_mark
= 0x0ff8;
389 data
->cluster_eof_mark
= 0xfff8;
394 /* More sanity checks. */
395 if (data
->num_sectors
<= data
->fat_sector
)
398 if (grub_disk_read (disk
,
405 first_fat
= grub_le_to_cpu32 (first_fat
);
407 if (data
->fat_size
== 32)
409 first_fat
&= 0x0fffffff;
412 else if (data
->fat_size
== 16)
414 first_fat
&= 0x0000ffff;
419 first_fat
&= 0x00000fff;
425 data
->uuid
= grub_le_to_cpu32 (bpb
.num_serial
);
427 if (bpb
.sectors_per_fat_16
)
428 data
->uuid
= grub_le_to_cpu32 (bpb
.version_specific
.fat12_or_fat16
.num_serial
);
430 data
->uuid
= grub_le_to_cpu32 (bpb
.version_specific
.fat32
.num_serial
);
434 /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
435 descriptor, even if it is a so-called superfloppy (e.g. an USB key).
436 The check may be too strict for this kind of stupid BIOSes, as
437 they overwrite the media descriptor. */
438 if ((first_fat
| 0x8) != (magic
| bpb
.media
| 0x8))
449 grub_error (GRUB_ERR_BAD_FS
, "not a FAT filesystem");
454 grub_fat_read_data (grub_disk_t disk
, grub_fshelp_node_t node
,
455 grub_disk_read_hook_t read_hook
, void *read_hook_data
,
456 grub_off_t offset
, grub_size_t len
, char *buf
)
459 grub_uint32_t logical_cluster
;
460 unsigned logical_cluster_bits
;
461 grub_ssize_t ret
= 0;
462 unsigned long sector
;
465 /* This is a special case. FAT12 and FAT16 doesn't have the root directory
467 if (node
->file_cluster
== ~0U)
469 size
= (node
->data
->num_root_sectors
<< GRUB_DISK_SECTOR_BITS
) - offset
;
473 if (grub_disk_read (disk
, node
->data
->root_sector
, offset
, size
, buf
))
481 if (node
->is_contiguous
)
483 /* Read the data here. */
484 sector
= (node
->data
->cluster_sector
485 + ((node
->file_cluster
- 2)
486 << node
->data
->cluster_bits
));
488 disk
->read_hook
= read_hook
;
489 disk
->read_hook_data
= read_hook_data
;
490 grub_disk_read (disk
, sector
+ (offset
>> GRUB_DISK_SECTOR_BITS
),
491 offset
& (GRUB_DISK_SECTOR_SIZE
- 1), len
, buf
);
500 /* Calculate the logical cluster number and offset. */
501 logical_cluster_bits
= (node
->data
->cluster_bits
502 + GRUB_DISK_SECTOR_BITS
);
503 logical_cluster
= offset
>> logical_cluster_bits
;
504 offset
&= (1ULL << logical_cluster_bits
) - 1;
506 if (logical_cluster
< node
->cur_cluster_num
)
508 node
->cur_cluster_num
= 0;
509 node
->cur_cluster
= node
->file_cluster
;
514 while (logical_cluster
> node
->cur_cluster_num
)
516 /* Find next cluster. */
517 grub_uint32_t next_cluster
;
518 grub_uint32_t fat_offset
;
520 switch (node
->data
->fat_size
)
523 fat_offset
= node
->cur_cluster
<< 2;
526 fat_offset
= node
->cur_cluster
<< 1;
530 fat_offset
= node
->cur_cluster
+ (node
->cur_cluster
>> 1);
535 if (grub_disk_read (disk
, node
->data
->fat_sector
, fat_offset
,
536 (node
->data
->fat_size
+ 7) >> 3,
537 (char *) &next_cluster
))
540 next_cluster
= grub_le_to_cpu32 (next_cluster
);
541 switch (node
->data
->fat_size
)
544 next_cluster
&= 0xFFFF;
547 if (node
->cur_cluster
& 1)
550 next_cluster
&= 0x0FFF;
554 grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
555 node
->data
->fat_size
, next_cluster
);
558 if (next_cluster
>= node
->data
->cluster_eof_mark
)
561 if (next_cluster
< 2 || (next_cluster
- 2) >= node
->data
->num_clusters
)
563 grub_error (GRUB_ERR_BAD_FS
, "invalid cluster %u",
568 node
->cur_cluster
= next_cluster
;
569 node
->cur_cluster_num
++;
572 /* Read the data here. */
573 sector
= (node
->data
->cluster_sector
574 + ((node
->cur_cluster
- 2)
575 << node
->data
->cluster_bits
));
576 size
= (1 << logical_cluster_bits
) - offset
;
580 disk
->read_hook
= read_hook
;
581 disk
->read_hook_data
= read_hook_data
;
582 grub_disk_read (disk
, sector
, offset
, size
, buf
);
597 struct grub_fat_iterate_context
600 struct grub_fat_dir_node dir
;
602 struct grub_fat_dir_entry dir
;
605 grub_uint16_t
*unibuf
;
610 grub_fat_iterate_init (struct grub_fat_iterate_context
*ctxt
)
612 ctxt
->offset
= -sizeof (struct grub_fat_dir_entry
);
615 /* Allocate space enough to hold a long name. */
616 ctxt
->filename
= grub_malloc (0x40 * 13 * GRUB_MAX_UTF8_PER_UTF16
+ 1);
617 ctxt
->unibuf
= (grub_uint16_t
*) grub_malloc (0x40 * 13 * 2);
619 ctxt
->unibuf
= grub_malloc (15 * 256 * 2);
620 ctxt
->filename
= grub_malloc (15 * 256 * GRUB_MAX_UTF8_PER_UTF16
+ 1);
623 if (! ctxt
->filename
|| ! ctxt
->unibuf
)
625 grub_free (ctxt
->filename
);
626 grub_free (ctxt
->unibuf
);
629 return GRUB_ERR_NONE
;
633 grub_fat_iterate_fini (struct grub_fat_iterate_context
*ctxt
)
635 grub_free (ctxt
->filename
);
636 grub_free (ctxt
->unibuf
);
641 grub_fat_iterate_dir_next (grub_fshelp_node_t node
,
642 struct grub_fat_iterate_context
*ctxt
)
644 grub_memset (&ctxt
->dir
, 0, sizeof (ctxt
->dir
));
647 struct grub_fat_dir_entry dir
;
649 ctxt
->offset
+= sizeof (dir
);
651 if (grub_fat_read_data (node
->disk
, node
, 0, 0, ctxt
->offset
, sizeof (dir
),
656 if (dir
.entry_type
== 0)
658 if (!(dir
.entry_type
& 0x80))
661 if (dir
.entry_type
== 0x85)
663 unsigned i
, nsec
, slots
= 0;
665 nsec
= dir
.type_specific
.file
.secondary_count
;
667 ctxt
->dir
.attr
= grub_cpu_to_le16 (dir
.type_specific
.file
.attr
);
668 ctxt
->dir
.have_stream
= 0;
669 for (i
= 0; i
< nsec
; i
++)
671 struct grub_fat_dir_entry sec
;
672 ctxt
->offset
+= sizeof (sec
);
673 if (grub_fat_read_data (node
->disk
, node
, 0, 0,
674 ctxt
->offset
, sizeof (sec
), (char *) &sec
)
677 if (!(sec
.entry_type
& 0x80))
679 if (!(sec
.entry_type
& 0x40))
681 switch (sec
.entry_type
)
684 ctxt
->dir
.first_cluster
= grub_cpu_to_le32 (sec
.type_specific
.stream_extension
.first_cluster
);
686 = grub_cpu_to_le64 (sec
.type_specific
.stream_extension
.valid_size
);
688 = grub_cpu_to_le64 (sec
.type_specific
.stream_extension
.file_size
);
689 ctxt
->dir
.have_stream
= 1;
690 ctxt
->dir
.is_contiguous
= !!(sec
.type_specific
.stream_extension
.flags
691 & grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS
));
696 for (j
= 0; j
< 15; j
++)
697 ctxt
->unibuf
[slots
* 15 + j
]
698 = grub_le_to_cpu16 (sec
.type_specific
.file_name
.str
[j
]);
703 grub_dprintf ("exfat", "unknown secondary type 0x%02x\n",
710 ctxt
->offset
-= sizeof (dir
);
714 *grub_utf16_to_utf8 ((grub_uint8_t
*) ctxt
->filename
, ctxt
->unibuf
,
719 /* Allocation bitmap. */
720 if (dir
.entry_type
== 0x81)
723 if (dir
.entry_type
== 0x82)
726 if (dir
.entry_type
== 0x83)
728 grub_dprintf ("exfat", "unknown primary type 0x%02x\n",
731 return grub_errno
? : GRUB_ERR_EOF
;
737 grub_fat_iterate_dir_next (grub_fshelp_node_t node
,
738 struct grub_fat_iterate_context
*ctxt
)
742 int slot
= -1, slots
= -1;
748 /* Adjust the offset. */
749 ctxt
->offset
+= sizeof (ctxt
->dir
);
751 /* Read a directory entry. */
752 if (grub_fat_read_data (node
->disk
, node
, 0, 0,
753 ctxt
->offset
, sizeof (ctxt
->dir
),
755 != sizeof (ctxt
->dir
) || ctxt
->dir
.name
[0] == 0)
758 /* Handle long name entries. */
759 if (ctxt
->dir
.attr
== GRUB_FAT_ATTR_LONG_NAME
)
761 struct grub_fat_long_name_entry
*long_name
762 = (struct grub_fat_long_name_entry
*) &ctxt
->dir
;
763 grub_uint8_t id
= long_name
->id
;
769 checksum
= long_name
->checksum
;
772 if (id
!= slot
|| slot
== 0 || checksum
!= long_name
->checksum
)
779 grub_memcpy (ctxt
->unibuf
+ slot
* 13, long_name
->name1
, 5 * 2);
780 grub_memcpy (ctxt
->unibuf
+ slot
* 13 + 5, long_name
->name2
, 6 * 2);
781 grub_memcpy (ctxt
->unibuf
+ slot
* 13 + 11, long_name
->name3
, 2 * 2);
785 /* Check if this entry is valid. */
786 if (ctxt
->dir
.name
[0] == 0xe5 || (ctxt
->dir
.attr
& ~GRUB_FAT_ATTR_VALID
))
789 /* This is a workaround for Japanese. */
790 if (ctxt
->dir
.name
[0] == 0x05)
791 ctxt
->dir
.name
[0] = 0xe5;
793 if (checksum
!= -1 && slot
== 0)
797 for (sum
= 0, i
= 0; i
< sizeof (ctxt
->dir
.name
); i
++)
798 sum
= ((sum
>> 1) | (sum
<< 7)) + ctxt
->dir
.name
[i
];
804 for (u
= 0; u
< slots
* 13; u
++)
805 ctxt
->unibuf
[u
] = grub_le_to_cpu16 (ctxt
->unibuf
[u
]);
807 *grub_utf16_to_utf8 ((grub_uint8_t
*) ctxt
->filename
,
811 return GRUB_ERR_NONE
;
817 /* Convert the 8.3 file name. */
818 filep
= ctxt
->filename
;
819 if (ctxt
->dir
.attr
& GRUB_FAT_ATTR_VOLUME_ID
)
821 for (i
= 0; i
< sizeof (ctxt
->dir
.name
) && ctxt
->dir
.name
[i
]; i
++)
822 *filep
++ = ctxt
->dir
.name
[i
];
823 while (i
> 0 && ctxt
->dir
.name
[i
- 1] == ' ')
831 for (i
= 0; i
< 8 && ctxt
->dir
.name
[i
]; i
++)
832 *filep
++ = grub_tolower (ctxt
->dir
.name
[i
]);
833 while (i
> 0 && ctxt
->dir
.name
[i
- 1] == ' ')
839 /* XXX should we check that dir position is 0 or 1? */
840 if (i
> 2 || filep
[0] != '.' || (i
== 2 && filep
[1] != '.'))
843 for (i
= 8; i
< 11 && ctxt
->dir
.name
[i
]; i
++)
844 *filep
++ = grub_tolower (ctxt
->dir
.name
[i
]);
845 while (i
> 8 && ctxt
->dir
.name
[i
- 1] == ' ')
855 return GRUB_ERR_NONE
;
858 return grub_errno
? : GRUB_ERR_EOF
;
863 static grub_err_t
lookup_file (grub_fshelp_node_t node
,
865 grub_fshelp_node_t
*foundnode
,
866 enum grub_fshelp_filetype
*foundtype
)
869 struct grub_fat_iterate_context ctxt
;
871 err
= grub_fat_iterate_init (&ctxt
);
875 while (!(err
= grub_fat_iterate_dir_next (node
, &ctxt
)))
879 if (!ctxt
.dir
.have_stream
)
882 if (ctxt
.dir
.attr
& GRUB_FAT_ATTR_VOLUME_ID
)
886 if (grub_strcasecmp (name
, ctxt
.filename
) == 0)
888 *foundnode
= grub_malloc (sizeof (struct grub_fshelp_node
));
891 (*foundnode
)->attr
= ctxt
.dir
.attr
;
893 (*foundnode
)->file_size
= ctxt
.dir
.file_size
;
894 (*foundnode
)->file_cluster
= ctxt
.dir
.first_cluster
;
895 (*foundnode
)->is_contiguous
= ctxt
.dir
.is_contiguous
;
897 (*foundnode
)->file_size
= grub_le_to_cpu32 (ctxt
.dir
.file_size
);
898 (*foundnode
)->file_cluster
= ((grub_le_to_cpu16 (ctxt
.dir
.first_cluster_high
) << 16)
899 | grub_le_to_cpu16 (ctxt
.dir
.first_cluster_low
));
900 /* If directory points to root, starting cluster is 0 */
901 if (!(*foundnode
)->file_cluster
)
902 (*foundnode
)->file_cluster
= node
->data
->root_cluster
;
904 (*foundnode
)->cur_cluster_num
= ~0U;
905 (*foundnode
)->data
= node
->data
;
906 (*foundnode
)->disk
= node
->disk
;
908 *foundtype
= ((*foundnode
)->attr
& GRUB_FAT_ATTR_DIRECTORY
) ? GRUB_FSHELP_DIR
: GRUB_FSHELP_REG
;
910 grub_fat_iterate_fini (&ctxt
);
911 return GRUB_ERR_NONE
;
915 grub_fat_iterate_fini (&ctxt
);
916 if (err
== GRUB_ERR_EOF
)
924 grub_fat_dir (grub_device_t device
, const char *path
, grub_fs_dir_hook_t hook
,
927 struct grub_fat_data
*data
= 0;
928 grub_disk_t disk
= device
->disk
;
929 grub_fshelp_node_t found
= NULL
;
931 struct grub_fat_iterate_context ctxt
;
933 grub_dl_ref (my_mod
);
935 data
= grub_fat_mount (disk
);
939 struct grub_fshelp_node root
= {
942 .attr
= GRUB_FAT_ATTR_DIRECTORY
,
944 .file_cluster
= data
->root_cluster
,
945 .cur_cluster_num
= ~0U,
952 err
= grub_fshelp_find_file_lookup (path
, &root
, &found
, lookup_file
, NULL
, GRUB_FSHELP_DIR
);
956 err
= grub_fat_iterate_init (&ctxt
);
960 while (!(err
= grub_fat_iterate_dir_next (found
, &ctxt
)))
962 struct grub_dirhook_info info
;
963 grub_memset (&info
, 0, sizeof (info
));
965 info
.dir
= !! (ctxt
.dir
.attr
& GRUB_FAT_ATTR_DIRECTORY
);
966 info
.case_insensitive
= 1;
969 info
.size
= ctxt
.dir
.file_size
;
972 if (!ctxt
.dir
.have_stream
)
975 if (ctxt
.dir
.attr
& GRUB_FAT_ATTR_VOLUME_ID
)
979 if (hook (ctxt
.filename
, &info
, hook_data
))
982 grub_fat_iterate_fini (&ctxt
);
983 if (err
== GRUB_ERR_EOF
)
992 grub_dl_unref (my_mod
);
998 grub_fat_open (grub_file_t file
, const char *name
)
1000 struct grub_fat_data
*data
= 0;
1001 grub_fshelp_node_t found
= NULL
;
1003 grub_disk_t disk
= file
->device
->disk
;
1005 grub_dl_ref (my_mod
);
1007 data
= grub_fat_mount (disk
);
1011 struct grub_fshelp_node root
= {
1014 .attr
= GRUB_FAT_ATTR_DIRECTORY
,
1016 .file_cluster
= data
->root_cluster
,
1017 .cur_cluster_num
= ~0U,
1024 err
= grub_fshelp_find_file_lookup (name
, &root
, &found
, lookup_file
, NULL
, GRUB_FSHELP_REG
);
1029 file
->size
= found
->file_size
;
1031 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_fshelp_node_t node
= file
->data
;
1058 grub_free (node
->data
);
1061 grub_dl_unref (my_mod
);
1068 grub_fat_label (grub_device_t device
, char **label
)
1070 struct grub_fat_dir_entry dir
;
1071 grub_ssize_t offset
= -sizeof(dir
);
1072 grub_disk_t disk
= device
->disk
;
1073 struct grub_fshelp_node root
= {
1075 .attr
= GRUB_FAT_ATTR_DIRECTORY
,
1077 .cur_cluster_num
= ~0U,
1082 root
.data
= grub_fat_mount (disk
);
1086 root
.file_cluster
= root
.data
->root_cluster
;
1092 offset
+= sizeof (dir
);
1094 if (grub_fat_read_data (disk
, &root
, 0, 0,
1095 offset
, sizeof (dir
), (char *) &dir
)
1099 if (dir
.entry_type
== 0)
1101 if (!(dir
.entry_type
& 0x80))
1105 if (dir
.entry_type
== 0x83)
1108 grub_uint16_t t
[ARRAY_SIZE (dir
.type_specific
.volume_label
.str
)];
1110 *label
= grub_malloc (ARRAY_SIZE (dir
.type_specific
.volume_label
.str
)
1111 * GRUB_MAX_UTF8_PER_UTF16
+ 1);
1114 grub_free (root
.data
);
1117 chc
= dir
.type_specific
.volume_label
.character_count
;
1118 if (chc
> ARRAY_SIZE (dir
.type_specific
.volume_label
.str
))
1119 chc
= ARRAY_SIZE (dir
.type_specific
.volume_label
.str
);
1120 for (i
= 0; i
< chc
; i
++)
1121 t
[i
] = grub_le_to_cpu16 (dir
.type_specific
.volume_label
.str
[i
]);
1122 *grub_utf16_to_utf8 ((grub_uint8_t
*) *label
, t
, chc
) = '\0';
1126 grub_free (root
.data
);
1133 grub_fat_label (grub_device_t device
, char **label
)
1135 grub_disk_t disk
= device
->disk
;
1137 struct grub_fat_iterate_context ctxt
;
1138 struct grub_fshelp_node root
= {
1140 .attr
= GRUB_FAT_ATTR_DIRECTORY
,
1142 .cur_cluster_num
= ~0U,
1148 grub_dl_ref (my_mod
);
1150 root
.data
= grub_fat_mount (disk
);
1154 root
.file_cluster
= root
.data
->root_cluster
;
1156 err
= grub_fat_iterate_init (&ctxt
);
1160 while (!(err
= grub_fat_iterate_dir_next (&root
, &ctxt
)))
1161 if ((ctxt
.dir
.attr
& ~GRUB_FAT_ATTR_ARCHIVE
) == GRUB_FAT_ATTR_VOLUME_ID
)
1163 *label
= grub_strdup (ctxt
.filename
);
1167 grub_fat_iterate_fini (&ctxt
);
1171 grub_dl_unref (my_mod
);
1173 grub_free (root
.data
);
1181 grub_fat_uuid (grub_device_t device
, char **uuid
)
1183 struct grub_fat_data
*data
;
1184 grub_disk_t disk
= device
->disk
;
1186 grub_dl_ref (my_mod
);
1188 data
= grub_fat_mount (disk
);
1192 *uuid
= grub_xasprintf ("%04x-%04x",
1193 (grub_uint16_t
) (data
->uuid
>> 16),
1194 (grub_uint16_t
) data
->uuid
);
1195 for (ptr
= *uuid
; ptr
&& *ptr
; ptr
++)
1196 *ptr
= grub_toupper (*ptr
);
1201 grub_dl_unref (my_mod
);
1211 grub_fat_get_cluster_sector (grub_disk_t disk
, grub_uint64_t
*sec_per_lcn
)
1214 grub_exfat_get_cluster_sector (grub_disk_t disk
, grub_uint64_t
*sec_per_lcn
)
1217 grub_disk_addr_t ret
;
1218 struct grub_fat_data
*data
;
1219 data
= grub_fat_mount (disk
);
1222 ret
= data
->cluster_sector
;
1224 *sec_per_lcn
= 1ULL << data
->cluster_bits
;
1231 static struct grub_fs grub_fat_fs
=
1238 .fs_dir
= grub_fat_dir
,
1239 .fs_open
= grub_fat_open
,
1240 .fs_read
= grub_fat_read
,
1241 .fs_close
= grub_fat_close
,
1242 .fs_label
= grub_fat_label
,
1243 .fs_uuid
= grub_fat_uuid
,
1246 /* ExFAT BPB is 30 larger than FAT32 one. */
1247 .reserved_first_sector
= 0,
1249 .reserved_first_sector
= 1,
1251 .blocklist_install
= 1,
1257 GRUB_MOD_INIT(exfat
)
1262 COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry
) == 32);
1263 grub_fs_register (&grub_fat_fs
);
1267 GRUB_MOD_FINI(exfat
)
1272 grub_fs_unregister (&grub_fat_fs
);
1277 int grub_fat_get_file_chunk(grub_uint64_t part_start
, grub_file_t file
, ventoy_img_chunk_list
*chunk_list
)
1281 grub_uint32_t logical_cluster
;
1282 unsigned logical_cluster_bits
;
1283 unsigned long sector
;
1284 grub_fshelp_node_t node
;
1288 disk
= file
->device
->disk
;
1292 if (node
->is_contiguous
)
1294 /* Read the data here. */
1295 sector
= (node
->data
->cluster_sector
+ ((node
->file_cluster
- 2) << node
->data
->cluster_bits
));
1297 chunk_list
->chunk
[0].img_start_sector
= 0;
1298 chunk_list
->chunk
[0].img_end_sector
= (file
->size
>> 11) - 1;
1299 chunk_list
->chunk
[0].disk_start_sector
= sector
;
1300 chunk_list
->chunk
[0].disk_end_sector
= sector
+ (file
->size
>> disk
->log_sector_size
) - 1;
1301 chunk_list
->cur_chunk
= 1;
1306 /* Calculate the logical cluster number and offset. */
1307 logical_cluster
= 0;
1308 logical_cluster_bits
= (node
->data
->cluster_bits
+ GRUB_DISK_SECTOR_BITS
);
1310 if (logical_cluster
< node
->cur_cluster_num
)
1312 node
->cur_cluster_num
= 0;
1313 node
->cur_cluster
= node
->file_cluster
;
1318 while (logical_cluster
> node
->cur_cluster_num
)
1320 /* Find next cluster. */
1321 grub_uint32_t next_cluster
;
1322 grub_uint32_t fat_offset
;
1324 switch (node
->data
->fat_size
)
1327 fat_offset
= node
->cur_cluster
<< 2;
1330 fat_offset
= node
->cur_cluster
<< 1;
1334 fat_offset
= node
->cur_cluster
+ (node
->cur_cluster
>> 1);
1339 if (grub_disk_read (disk
, node
->data
->fat_sector
, fat_offset
,
1340 (node
->data
->fat_size
+ 7) >> 3,
1341 (char *) &next_cluster
))
1346 next_cluster
= grub_le_to_cpu32 (next_cluster
);
1347 switch (node
->data
->fat_size
)
1350 next_cluster
&= 0xFFFF;
1353 if (node
->cur_cluster
& 1)
1356 next_cluster
&= 0x0FFF;
1360 grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n", node
->data
->fat_size
, next_cluster
);
1362 /* Check the end. */
1363 if (next_cluster
>= node
->data
->cluster_eof_mark
)
1368 if (next_cluster
< 2 || (next_cluster
- 2) >= node
->data
->num_clusters
)
1370 grub_error (GRUB_ERR_BAD_FS
, "invalid cluster %u", next_cluster
);
1374 node
->cur_cluster
= next_cluster
;
1375 node
->cur_cluster_num
++;
1378 /* Read the data here. */
1379 sector
= (node
->data
->cluster_sector
1380 + ((node
->cur_cluster
- 2)
1381 << node
->data
->cluster_bits
));
1382 size
= (1 << logical_cluster_bits
);
1386 grub_disk_blocklist_read(chunk_list
, sector
, size
, disk
->log_sector_size
);
1394 for (i
= 0; i
< chunk_list
->cur_chunk
; i
++)
1396 chunk_list
->chunk
[i
].disk_start_sector
+= part_start
;
1397 chunk_list
->chunk
[i
].disk_end_sector
+= part_start
;