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>
30
#define GRUB_FAT_DIR_ENTRY_SIZE 32
32
#define GRUB_FAT_ATTR_READ_ONLY 0x01
33
#define GRUB_FAT_ATTR_HIDDEN 0x02
34
#define GRUB_FAT_ATTR_SYSTEM 0x04
35
#define GRUB_FAT_ATTR_VOLUME_ID 0x08
36
#define GRUB_FAT_ATTR_DIRECTORY 0x10
37
#define GRUB_FAT_ATTR_ARCHIVE 0x20
39
#define GRUB_FAT_MAXFILE 256
41
#define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \
42
| GRUB_FAT_ATTR_HIDDEN \
43
| GRUB_FAT_ATTR_SYSTEM \
44
| GRUB_FAT_ATTR_VOLUME_ID)
45
#define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \
46
| GRUB_FAT_ATTR_HIDDEN \
47
| GRUB_FAT_ATTR_SYSTEM \
48
| GRUB_FAT_ATTR_DIRECTORY \
49
| GRUB_FAT_ATTR_ARCHIVE \
50
| GRUB_FAT_ATTR_VOLUME_ID)
54
grub_uint8_t jmp_boot[3];
55
grub_uint8_t oem_name[8];
56
grub_uint16_t bytes_per_sector;
57
grub_uint8_t sectors_per_cluster;
58
grub_uint16_t num_reserved_sectors;
59
grub_uint8_t num_fats;
60
grub_uint16_t num_root_entries;
61
grub_uint16_t num_total_sectors_16;
63
grub_uint16_t sectors_per_fat_16;
64
grub_uint16_t sectors_per_track;
65
grub_uint16_t num_heads;
66
grub_uint32_t num_hidden_sectors;
67
grub_uint32_t num_total_sectors_32;
72
grub_uint8_t num_ph_drive;
73
grub_uint8_t reserved;
74
grub_uint8_t boot_sig;
75
grub_uint32_t num_serial;
76
grub_uint8_t label[11];
77
grub_uint8_t fstype[8];
78
} __attribute__ ((packed)) fat12_or_fat16;
81
grub_uint32_t sectors_per_fat_32;
82
grub_uint16_t extended_flags;
83
grub_uint16_t fs_version;
84
grub_uint32_t root_cluster;
85
grub_uint16_t fs_info;
86
grub_uint16_t backup_boot_sector;
87
grub_uint8_t reserved[12];
88
grub_uint8_t num_ph_drive;
89
grub_uint8_t reserved1;
90
grub_uint8_t boot_sig;
91
grub_uint32_t num_serial;
92
grub_uint8_t label[11];
93
grub_uint8_t fstype[8];
94
} __attribute__ ((packed)) fat32;
95
} __attribute__ ((packed)) version_specific;
96
} __attribute__ ((packed));
98
struct grub_fat_dir_entry
100
grub_uint8_t name[11];
102
grub_uint8_t nt_reserved;
103
grub_uint8_t c_time_tenth;
104
grub_uint16_t c_time;
105
grub_uint16_t c_date;
106
grub_uint16_t a_date;
107
grub_uint16_t first_cluster_high;
108
grub_uint16_t w_time;
109
grub_uint16_t w_date;
110
grub_uint16_t first_cluster_low;
111
grub_uint32_t file_size;
112
} __attribute__ ((packed));
114
struct grub_fat_long_name_entry
117
grub_uint16_t name1[5];
119
grub_uint8_t reserved;
120
grub_uint8_t checksum;
121
grub_uint16_t name2[6];
122
grub_uint16_t first_cluster;
123
grub_uint16_t name3[2];
124
} __attribute__ ((packed));
128
int logical_sector_bits;
129
grub_uint32_t num_sectors;
131
grub_uint16_t fat_sector;
132
grub_uint32_t sectors_per_fat;
135
grub_uint32_t root_cluster;
136
grub_uint32_t root_sector;
137
grub_uint32_t num_root_sectors;
140
grub_uint32_t cluster_eof_mark;
141
grub_uint32_t cluster_sector;
142
grub_uint32_t num_clusters;
145
grub_ssize_t file_size;
146
grub_uint32_t file_cluster;
147
grub_uint32_t cur_cluster_num;
148
grub_uint32_t cur_cluster;
153
static grub_dl_t my_mod;
156
fat_log2 (unsigned x)
163
for (i = 0; (x & 1) == 0; i++)
172
static struct grub_fat_data *
173
grub_fat_mount (grub_disk_t disk)
175
struct grub_fat_bpb bpb;
176
struct grub_fat_data *data = 0;
177
grub_uint32_t first_fat, magic;
182
data = (struct grub_fat_data *) grub_malloc (sizeof (*data));
187
if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
190
if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5)
191
&& grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5)
192
&& grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5))
195
/* Get the sizes of logical sectors and clusters. */
196
data->logical_sector_bits =
197
fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
198
if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS)
200
data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
202
data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
203
if (data->cluster_bits < 0)
205
data->cluster_bits += data->logical_sector_bits;
207
/* Get information about FATs. */
208
data->fat_sector = (grub_le_to_cpu16 (bpb.num_reserved_sectors)
209
<< data->logical_sector_bits);
210
if (data->fat_sector == 0)
213
data->sectors_per_fat = ((bpb.sectors_per_fat_16
214
? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
215
: grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
216
<< data->logical_sector_bits);
217
if (data->sectors_per_fat == 0)
220
/* Get the number of sectors in this volume. */
221
data->num_sectors = ((bpb.num_total_sectors_16
222
? grub_le_to_cpu16 (bpb.num_total_sectors_16)
223
: grub_le_to_cpu32 (bpb.num_total_sectors_32))
224
<< data->logical_sector_bits);
225
if (data->num_sectors == 0)
228
/* Get information about the root directory. */
229
if (bpb.num_fats == 0)
232
data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
233
data->num_root_sectors
234
= ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
235
* GRUB_FAT_DIR_ENTRY_SIZE
236
+ grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
237
>> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
238
<< (data->logical_sector_bits));
240
data->cluster_sector = data->root_sector + data->num_root_sectors;
241
data->num_clusters = (((data->num_sectors - data->cluster_sector)
242
>> (data->cluster_bits + data->logical_sector_bits))
245
if (data->num_clusters <= 2)
248
if (! bpb.sectors_per_fat_16)
251
grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags);
253
data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster);
255
data->cluster_eof_mark = 0x0ffffff8;
259
/* Get an active FAT. */
260
unsigned active_fat = flags & 0xf;
262
if (active_fat > bpb.num_fats)
265
data->fat_sector += active_fat * data->sectors_per_fat;
268
if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0)
273
/* FAT12 or FAT16. */
274
data->root_cluster = ~0U;
276
if (data->num_clusters <= 4085 + 2)
280
data->cluster_eof_mark = 0x0ff8;
286
data->cluster_eof_mark = 0xfff8;
290
/* More sanity checks. */
291
if (data->num_sectors <= data->fat_sector)
294
if (grub_disk_read (disk,
301
first_fat = grub_le_to_cpu32 (first_fat);
303
if (data->fat_size == 32)
305
first_fat &= 0x0fffffff;
308
else if (data->fat_size == 16)
310
first_fat &= 0x0000ffff;
315
first_fat &= 0x00000fff;
320
if (bpb.sectors_per_fat_16)
321
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
323
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
325
/* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
326
descriptor, even if it is a so-called superfloppy (e.g. an USB key).
327
The check may be too strict for this kind of stupid BIOSes, as
328
they overwrite the media descriptor. */
329
if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
332
/* Start from the root directory. */
333
data->file_cluster = data->root_cluster;
334
data->cur_cluster_num = ~0U;
335
data->attr = GRUB_FAT_ATTR_DIRECTORY;
341
grub_error (GRUB_ERR_BAD_FS, "not a FAT filesystem");
346
grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
347
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
348
unsigned offset, unsigned length),
349
grub_off_t offset, grub_size_t len, char *buf)
352
grub_uint32_t logical_cluster;
353
unsigned logical_cluster_bits;
354
grub_ssize_t ret = 0;
355
unsigned long sector;
357
/* This is a special case. FAT12 and FAT16 doesn't have the root directory
359
if (data->file_cluster == ~0U)
361
size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
365
if (grub_disk_read (disk, data->root_sector, offset, size, buf))
371
/* Calculate the logical cluster number and offset. */
372
logical_cluster_bits = (data->cluster_bits
373
+ data->logical_sector_bits
374
+ GRUB_DISK_SECTOR_BITS);
375
logical_cluster = offset >> logical_cluster_bits;
376
offset &= (1 << logical_cluster_bits) - 1;
378
if (logical_cluster < data->cur_cluster_num)
380
data->cur_cluster_num = 0;
381
data->cur_cluster = data->file_cluster;
386
while (logical_cluster > data->cur_cluster_num)
388
/* Find next cluster. */
389
grub_uint32_t next_cluster;
390
unsigned long fat_offset;
392
switch (data->fat_size)
395
fat_offset = data->cur_cluster << 2;
398
fat_offset = data->cur_cluster << 1;
402
fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
407
if (grub_disk_read (disk, data->fat_sector, fat_offset,
408
(data->fat_size + 7) >> 3,
409
(char *) &next_cluster))
412
next_cluster = grub_le_to_cpu32 (next_cluster);
413
switch (data->fat_size)
416
next_cluster &= 0xFFFF;
419
if (data->cur_cluster & 1)
422
next_cluster &= 0x0FFF;
426
grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
427
data->fat_size, next_cluster);
430
if (next_cluster >= data->cluster_eof_mark)
433
if (next_cluster < 2 || next_cluster >= data->num_clusters)
435
grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u",
440
data->cur_cluster = next_cluster;
441
data->cur_cluster_num++;
444
/* Read the data here. */
445
sector = (data->cluster_sector
446
+ ((data->cur_cluster - 2)
447
<< (data->cluster_bits + data->logical_sector_bits)));
448
size = (1 << logical_cluster_bits) - offset;
452
disk->read_hook = read_hook;
453
grub_disk_read (disk, sector, offset, size, buf);
469
grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
470
int (*hook) (const char *filename,
471
struct grub_fat_dir_entry *dir))
473
struct grub_fat_dir_entry dir;
474
char *filename, *filep = 0;
475
grub_uint16_t *unibuf;
476
int slot = -1, slots = -1;
478
grub_ssize_t offset = -sizeof(dir);
480
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
481
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
483
/* Allocate space enough to hold a long name. */
484
filename = grub_malloc (0x40 * 13 * 4 + 1);
485
unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2);
486
if (! filename || ! unibuf)
488
grub_free (filename);
497
/* Adjust the offset. */
498
offset += sizeof (dir);
500
/* Read a directory entry. */
501
if ((grub_fat_read_data (disk, data, 0,
502
offset, sizeof (dir), (char *) &dir)
503
!= sizeof (dir) || dir.name[0] == 0))
505
/* Handle long name entries. */
506
if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
508
struct grub_fat_long_name_entry *long_name
509
= (struct grub_fat_long_name_entry *) &dir;
510
grub_uint8_t id = long_name->id;
516
checksum = long_name->checksum;
519
if (id != slot || slot == 0 || checksum != long_name->checksum)
526
grub_memcpy (unibuf + slot * 13, long_name->name1, 5 * 2);
527
grub_memcpy (unibuf + slot * 13 + 5, long_name->name2, 6 * 2);
528
grub_memcpy (unibuf + slot * 13 + 11, long_name->name3, 2 * 2);
532
/* Check if this entry is valid. */
533
if (dir.name[0] == 0xe5 || (dir.attr & ~GRUB_FAT_ATTR_VALID))
536
/* This is a workaround for Japanese. */
537
if (dir.name[0] == 0x05)
540
if (checksum != -1 && slot == 0)
544
for (sum = 0, i = 0; i < sizeof (dir.name); i++)
545
sum = ((sum >> 1) | (sum << 7)) + dir.name[i];
551
for (u = 0; u < slots * 13; u++)
552
unibuf[u] = grub_le_to_cpu16 (unibuf[u]);
554
*grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
557
if (hook (filename, &dir))
567
/* Convert the 8.3 file name. */
569
if (dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
571
for (i = 0; i < sizeof (dir.name) && dir.name[i]
572
&& ! grub_isspace (dir.name[i]); i++)
573
*filep++ = dir.name[i];
577
for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
578
*filep++ = grub_tolower (dir.name[i]);
582
for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
583
*++filep = grub_tolower (dir.name[i]);
590
if (hook (filename, &dir))
594
grub_free (filename);
601
/* Find the underlying directory or file in PATH and return the
602
next path. If there is no next path or an error occurs, return NULL.
603
If HOOK is specified, call it with each file name. */
605
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
607
int (*hook) (const char *filename,
608
const struct grub_dirhook_info *info))
610
char *dirname, *dirp;
614
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
615
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
617
struct grub_dirhook_info info;
618
grub_memset (&info, 0, sizeof (info));
620
info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY);
621
info.case_insensitive = 1;
623
if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
625
if (*dirname == '\0' && call_hook)
626
return hook (filename, &info);
628
if (grub_strcasecmp (dirname, filename) == 0)
631
data->attr = dir->attr;
632
data->file_size = grub_le_to_cpu32 (dir->file_size);
633
data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
634
| grub_le_to_cpu16 (dir->first_cluster_low));
635
data->cur_cluster_num = ~0U;
638
hook (filename, &info);
645
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
647
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
651
/* Extract a directory name. */
655
dirp = grub_strchr (path, '/');
658
unsigned len = dirp - path;
660
dirname = grub_malloc (len + 1);
664
grub_memcpy (dirname, path, len);
668
/* This is actually a file. */
669
dirname = grub_strdup (path);
671
call_hook = (! dirp && hook);
673
grub_fat_iterate_dir (disk, data, iter_hook);
674
if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook)
675
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
679
return found ? dirp : 0;
683
grub_fat_dir (grub_device_t device, const char *path,
684
int (*hook) (const char *filename,
685
const struct grub_dirhook_info *info))
687
struct grub_fat_data *data = 0;
688
grub_disk_t disk = device->disk;
693
grub_dl_ref (my_mod);
695
data = grub_fat_mount (disk);
699
/* Make sure that DIRNAME terminates with '/'. */
700
len = grub_strlen (path);
701
dirname = grub_malloc (len + 1 + 1);
704
grub_memcpy (dirname, path, len);
706
if (path[len - 1] != '/')
713
p = grub_fat_find_dir (disk, data, p, hook);
715
while (p && grub_errno == GRUB_ERR_NONE);
722
grub_dl_unref (my_mod);
728
grub_fat_open (grub_file_t file, const char *name)
730
struct grub_fat_data *data = 0;
731
char *p = (char *) name;
733
grub_dl_ref (my_mod);
735
data = grub_fat_mount (file->device->disk);
741
p = grub_fat_find_dir (file->device->disk, data, p, 0);
742
if (grub_errno != GRUB_ERR_NONE)
747
if (data->attr & GRUB_FAT_ATTR_DIRECTORY)
749
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
754
file->size = data->file_size;
756
return GRUB_ERR_NONE;
762
grub_dl_unref (my_mod);
768
grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
770
return grub_fat_read_data (file->device->disk, file->data, file->read_hook,
771
file->offset, len, buf);
775
grub_fat_close (grub_file_t file)
777
grub_free (file->data);
779
grub_dl_unref (my_mod);
785
grub_fat_label (grub_device_t device, char **label)
787
struct grub_fat_data *data;
788
grub_disk_t disk = device->disk;
790
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
791
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
793
if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID)
795
*label = grub_strdup (filename);
801
grub_dl_ref (my_mod);
803
data = grub_fat_mount (disk);
807
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
809
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
815
grub_fat_iterate_dir (disk, data, iter_hook);
819
grub_dl_unref (my_mod);
827
grub_fat_uuid (grub_device_t device, char **uuid)
829
struct grub_fat_data *data;
830
grub_disk_t disk = device->disk;
832
grub_dl_ref (my_mod);
834
data = grub_fat_mount (disk);
837
*uuid = grub_xasprintf ("%04x-%04x",
838
(grub_uint16_t) (data->uuid >> 16),
839
(grub_uint16_t) data->uuid);
844
grub_dl_unref (my_mod);
851
static struct grub_fs grub_fat_fs =
855
.open = grub_fat_open,
856
.read = grub_fat_read,
857
.close = grub_fat_close,
858
.label = grub_fat_label,
859
.uuid = grub_fat_uuid,
861
.reserved_first_sector = 1,
868
grub_fs_register (&grub_fat_fs);
874
grub_fs_unregister (&grub_fat_fs);