* grub-core/fs/fat.c: Fix handling of exfat contiguous files.

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-10-11 16:13:52 +02:00
parent 145e2369a7
commit 60d4f0bb45
2 changed files with 40 additions and 5 deletions

View file

@ -1,3 +1,7 @@
2013-10-10 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/fs/fat.c: Fix handling of exfat contiguous files.
2013-10-10 Vladimir Testov <vladimir.testov@rosalab.ru> 2013-10-10 Vladimir Testov <vladimir.testov@rosalab.ru>
* grub-core/gfxmenu/gui_list.c: New option `scrollbar_thumb_overlay`. * grub-core/gfxmenu/gui_list.c: New option `scrollbar_thumb_overlay`.

View file

@ -87,6 +87,10 @@ typedef struct grub_fat_bpb grub_current_fat_bpb_t;
#endif #endif
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
enum
{
FLAG_CONTIGUOUS = 2
};
struct grub_fat_dir_entry struct grub_fat_dir_entry
{ {
grub_uint8_t entry_type; grub_uint8_t entry_type;
@ -135,7 +139,7 @@ struct grub_fat_dir_node
grub_uint64_t file_size; grub_uint64_t file_size;
grub_uint64_t valid_size; grub_uint64_t valid_size;
int have_stream; int have_stream;
int is_label; int is_contiguous;
}; };
typedef struct grub_fat_dir_node grub_fat_dir_node_t; typedef struct grub_fat_dir_node grub_fat_dir_node_t;
@ -186,6 +190,8 @@ struct grub_fat_data
#ifndef MODE_EXFAT #ifndef MODE_EXFAT
grub_uint32_t root_sector; grub_uint32_t root_sector;
grub_uint32_t num_root_sectors; grub_uint32_t num_root_sectors;
#else
int is_contiguous;
#endif #endif
int cluster_bits; int cluster_bits;
@ -336,13 +342,12 @@ grub_fat_mount (grub_disk_t disk)
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
{ {
/* exFAT. */ /* exFAT. */
grub_uint16_t flags = grub_le_to_cpu16 (bpb.volume_flags);
data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster); data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster);
data->fat_size = 32; data->fat_size = 32;
data->cluster_eof_mark = 0xffffffff; data->cluster_eof_mark = 0xffffffff;
if ((flags & 0x1) && bpb.num_fats > 1) if ((bpb.volume_flags & grub_cpu_to_le16_compile_time (0x1))
&& bpb.num_fats > 1)
data->fat_sector += data->sectors_per_fat; data->fat_sector += data->sectors_per_fat;
} }
#else #else
@ -443,6 +448,9 @@ grub_fat_mount (grub_disk_t disk)
data->file_cluster = data->root_cluster; data->file_cluster = data->root_cluster;
data->cur_cluster_num = ~0U; data->cur_cluster_num = ~0U;
data->attr = GRUB_FAT_ATTR_DIRECTORY; data->attr = GRUB_FAT_ATTR_DIRECTORY;
#ifdef MODE_EXFAT
data->is_contiguous = 0;
#endif
return data; return data;
fail: fail:
@ -479,6 +487,26 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
} }
#endif #endif
#ifdef MODE_EXFAT
if (data->is_contiguous)
{
/* Read the data here. */
sector = (data->cluster_sector
+ ((data->file_cluster - 2)
<< data->cluster_bits));
disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data;
grub_disk_read (disk, sector + (offset >> GRUB_DISK_SECTOR_BITS),
offset & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
disk->read_hook = 0;
if (grub_errno)
return -1;
return len;
}
#endif
/* Calculate the logical cluster number and offset. */ /* Calculate the logical cluster number and offset. */
logical_cluster_bits = (data->cluster_bits logical_cluster_bits = (data->cluster_bits
+ GRUB_DISK_SECTOR_BITS); + GRUB_DISK_SECTOR_BITS);
@ -497,7 +525,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
{ {
/* Find next cluster. */ /* Find next cluster. */
grub_uint32_t next_cluster; grub_uint32_t next_cluster;
unsigned long fat_offset; grub_uint32_t fat_offset;
switch (data->fat_size) switch (data->fat_size)
{ {
@ -669,6 +697,8 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
ctxt->dir.file_size ctxt->dir.file_size
= grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size); = grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size);
ctxt->dir.have_stream = 1; ctxt->dir.have_stream = 1;
ctxt->dir.is_contiguous = !!(dir.type_specific.stream_extension.flags
& grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS));
break; break;
case 0xc1: case 0xc1:
{ {
@ -917,6 +947,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
data->file_size = ctxt.dir.file_size; data->file_size = ctxt.dir.file_size;
data->file_cluster = ctxt.dir.first_cluster; data->file_cluster = ctxt.dir.first_cluster;
data->is_contiguous = ctxt.dir.is_contiguous;
#else #else
data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size);
data->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) data->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16)