~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to fs/fat.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* fat.c - FAT filesystem */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009  Free Software Foundation, Inc.
5
 
 *
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.
10
 
 *
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.
15
 
 *
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/>.
18
 
 */
19
 
 
20
 
#include <grub/fs.h>
21
 
#include <grub/disk.h>
22
 
#include <grub/file.h>
23
 
#include <grub/types.h>
24
 
#include <grub/misc.h>
25
 
#include <grub/mm.h>
26
 
#include <grub/err.h>
27
 
#include <grub/dl.h>
28
 
#include <grub/charset.h>
29
 
 
30
 
#define GRUB_FAT_DIR_ENTRY_SIZE 32
31
 
 
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
38
 
 
39
 
#define GRUB_FAT_MAXFILE        256
40
 
 
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)
51
 
 
52
 
struct grub_fat_bpb
53
 
{
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;
62
 
  grub_uint8_t media;
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;
68
 
  union
69
 
  {
70
 
    struct
71
 
    {
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;
79
 
    struct
80
 
    {
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));
97
 
 
98
 
struct grub_fat_dir_entry
99
 
{
100
 
  grub_uint8_t name[11];
101
 
  grub_uint8_t attr;
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));
113
 
 
114
 
struct grub_fat_long_name_entry
115
 
{
116
 
  grub_uint8_t id;
117
 
  grub_uint16_t name1[5];
118
 
  grub_uint8_t attr;
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));
125
 
 
126
 
struct grub_fat_data
127
 
{
128
 
  int logical_sector_bits;
129
 
  grub_uint32_t num_sectors;
130
 
 
131
 
  grub_uint16_t fat_sector;
132
 
  grub_uint32_t sectors_per_fat;
133
 
  int fat_size;
134
 
 
135
 
  grub_uint32_t root_cluster;
136
 
  grub_uint32_t root_sector;
137
 
  grub_uint32_t num_root_sectors;
138
 
 
139
 
  int cluster_bits;
140
 
  grub_uint32_t cluster_eof_mark;
141
 
  grub_uint32_t cluster_sector;
142
 
  grub_uint32_t num_clusters;
143
 
 
144
 
  grub_uint8_t attr;
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;
149
 
 
150
 
  grub_uint32_t uuid;
151
 
};
152
 
 
153
 
static grub_dl_t my_mod;
154
 
 
155
 
static int
156
 
fat_log2 (unsigned x)
157
 
{
158
 
  int i;
159
 
 
160
 
  if (x == 0)
161
 
    return -1;
162
 
 
163
 
  for (i = 0; (x & 1) == 0; i++)
164
 
    x >>= 1;
165
 
 
166
 
  if (x != 1)
167
 
    return -1;
168
 
 
169
 
  return i;
170
 
}
171
 
 
172
 
static struct grub_fat_data *
173
 
grub_fat_mount (grub_disk_t disk)
174
 
{
175
 
  struct grub_fat_bpb bpb;
176
 
  struct grub_fat_data *data = 0;
177
 
  grub_uint32_t first_fat, magic;
178
 
 
179
 
  if (! disk)
180
 
    goto fail;
181
 
 
182
 
  data = (struct grub_fat_data *) grub_malloc (sizeof (*data));
183
 
  if (! data)
184
 
    goto fail;
185
 
 
186
 
  /* Read the BPB.  */
187
 
  if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
188
 
    goto fail;
189
 
 
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))
193
 
    goto fail;
194
 
 
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)
199
 
    goto fail;
200
 
  data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
201
 
 
202
 
  data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
203
 
  if (data->cluster_bits < 0)
204
 
    goto fail;
205
 
  data->cluster_bits += data->logical_sector_bits;
206
 
 
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)
211
 
    goto fail;
212
 
 
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)
218
 
    goto fail;
219
 
 
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)
226
 
    goto fail;
227
 
 
228
 
  /* Get information about the root directory.  */
229
 
  if (bpb.num_fats == 0)
230
 
    goto fail;
231
 
 
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));
239
 
 
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))
243
 
                        + 2);
244
 
 
245
 
  if (data->num_clusters <= 2)
246
 
    goto fail;
247
 
 
248
 
  if (! bpb.sectors_per_fat_16)
249
 
    {
250
 
      /* FAT32.  */
251
 
      grub_uint16_t flags = grub_le_to_cpu16 (bpb.version_specific.fat32.extended_flags);
252
 
 
253
 
      data->root_cluster = grub_le_to_cpu32 (bpb.version_specific.fat32.root_cluster);
254
 
      data->fat_size = 32;
255
 
      data->cluster_eof_mark = 0x0ffffff8;
256
 
 
257
 
      if (flags & 0x80)
258
 
        {
259
 
          /* Get an active FAT.  */
260
 
          unsigned active_fat = flags & 0xf;
261
 
 
262
 
          if (active_fat > bpb.num_fats)
263
 
            goto fail;
264
 
 
265
 
          data->fat_sector += active_fat * data->sectors_per_fat;
266
 
        }
267
 
 
268
 
      if (bpb.num_root_entries != 0 || bpb.version_specific.fat32.fs_version != 0)
269
 
        goto fail;
270
 
    }
271
 
  else
272
 
    {
273
 
      /* FAT12 or FAT16.  */
274
 
      data->root_cluster = ~0U;
275
 
 
276
 
      if (data->num_clusters <= 4085 + 2)
277
 
        {
278
 
          /* FAT12.  */
279
 
          data->fat_size = 12;
280
 
          data->cluster_eof_mark = 0x0ff8;
281
 
        }
282
 
      else
283
 
        {
284
 
          /* FAT16.  */
285
 
          data->fat_size = 16;
286
 
          data->cluster_eof_mark = 0xfff8;
287
 
        }
288
 
    }
289
 
 
290
 
  /* More sanity checks.  */
291
 
  if (data->num_sectors <= data->fat_sector)
292
 
    goto fail;
293
 
 
294
 
  if (grub_disk_read (disk,
295
 
                      data->fat_sector,
296
 
                      0,
297
 
                      sizeof (first_fat),
298
 
                      &first_fat))
299
 
    goto fail;
300
 
 
301
 
  first_fat = grub_le_to_cpu32 (first_fat);
302
 
 
303
 
  if (data->fat_size == 32)
304
 
    {
305
 
      first_fat &= 0x0fffffff;
306
 
      magic = 0x0fffff00;
307
 
    }
308
 
  else if (data->fat_size == 16)
309
 
    {
310
 
      first_fat &= 0x0000ffff;
311
 
      magic = 0xff00;
312
 
    }
313
 
  else
314
 
    {
315
 
      first_fat &= 0x00000fff;
316
 
      magic = 0x0f00;
317
 
    }
318
 
 
319
 
  /* Serial number.  */
320
 
  if (bpb.sectors_per_fat_16)
321
 
    data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
322
 
  else
323
 
    data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
324
 
 
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))
330
 
    goto fail;
331
 
 
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;
336
 
  return data;
337
 
 
338
 
 fail:
339
 
 
340
 
  grub_free (data);
341
 
  grub_error (GRUB_ERR_BAD_FS, "not a FAT filesystem");
342
 
  return 0;
343
 
}
344
 
 
345
 
static grub_ssize_t
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)
350
 
{
351
 
  grub_size_t size;
352
 
  grub_uint32_t logical_cluster;
353
 
  unsigned logical_cluster_bits;
354
 
  grub_ssize_t ret = 0;
355
 
  unsigned long sector;
356
 
 
357
 
  /* This is a special case. FAT12 and FAT16 doesn't have the root directory
358
 
     in clusters.  */
359
 
  if (data->file_cluster == ~0U)
360
 
    {
361
 
      size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
362
 
      if (size > len)
363
 
        size = len;
364
 
 
365
 
      if (grub_disk_read (disk, data->root_sector, offset, size, buf))
366
 
        return -1;
367
 
 
368
 
      return size;
369
 
    }
370
 
 
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;
377
 
 
378
 
  if (logical_cluster < data->cur_cluster_num)
379
 
    {
380
 
      data->cur_cluster_num = 0;
381
 
      data->cur_cluster = data->file_cluster;
382
 
    }
383
 
 
384
 
  while (len)
385
 
    {
386
 
      while (logical_cluster > data->cur_cluster_num)
387
 
        {
388
 
          /* Find next cluster.  */
389
 
          grub_uint32_t next_cluster;
390
 
          unsigned long fat_offset;
391
 
 
392
 
          switch (data->fat_size)
393
 
            {
394
 
            case 32:
395
 
              fat_offset = data->cur_cluster << 2;
396
 
              break;
397
 
            case 16:
398
 
              fat_offset = data->cur_cluster << 1;
399
 
              break;
400
 
            default:
401
 
              /* case 12: */
402
 
              fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
403
 
              break;
404
 
            }
405
 
 
406
 
          /* Read the FAT.  */
407
 
          if (grub_disk_read (disk, data->fat_sector, fat_offset,
408
 
                              (data->fat_size + 7) >> 3,
409
 
                              (char *) &next_cluster))
410
 
            return -1;
411
 
 
412
 
          next_cluster = grub_le_to_cpu32 (next_cluster);
413
 
          switch (data->fat_size)
414
 
            {
415
 
            case 16:
416
 
              next_cluster &= 0xFFFF;
417
 
              break;
418
 
            case 12:
419
 
              if (data->cur_cluster & 1)
420
 
                next_cluster >>= 4;
421
 
 
422
 
              next_cluster &= 0x0FFF;
423
 
              break;
424
 
            }
425
 
 
426
 
          grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
427
 
                        data->fat_size, next_cluster);
428
 
 
429
 
          /* Check the end.  */
430
 
          if (next_cluster >= data->cluster_eof_mark)
431
 
            return ret;
432
 
 
433
 
          if (next_cluster < 2 || next_cluster >= data->num_clusters)
434
 
            {
435
 
              grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u",
436
 
                          next_cluster);
437
 
              return -1;
438
 
            }
439
 
 
440
 
          data->cur_cluster = next_cluster;
441
 
          data->cur_cluster_num++;
442
 
        }
443
 
 
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;
449
 
      if (size > len)
450
 
        size = len;
451
 
 
452
 
      disk->read_hook = read_hook;
453
 
      grub_disk_read (disk, sector, offset, size, buf);
454
 
      disk->read_hook = 0;
455
 
      if (grub_errno)
456
 
        return -1;
457
 
 
458
 
      len -= size;
459
 
      buf += size;
460
 
      ret += size;
461
 
      logical_cluster++;
462
 
      offset = 0;
463
 
    }
464
 
 
465
 
  return ret;
466
 
}
467
 
 
468
 
static grub_err_t
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))
472
 
{
473
 
  struct grub_fat_dir_entry dir;
474
 
  char *filename, *filep = 0;
475
 
  grub_uint16_t *unibuf;
476
 
  int slot = -1, slots = -1;
477
 
  int checksum = -1;
478
 
  grub_ssize_t offset = -sizeof(dir);
479
 
 
480
 
  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
481
 
    return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
482
 
 
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)
487
 
    {
488
 
      grub_free (filename);
489
 
      grub_free (unibuf);
490
 
      return 0;
491
 
    }
492
 
 
493
 
  while (1)
494
 
    {
495
 
      unsigned i;
496
 
 
497
 
      /* Adjust the offset.  */
498
 
      offset += sizeof (dir);
499
 
 
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))
504
 
        break;
505
 
      /* Handle long name entries.  */
506
 
      if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
507
 
        {
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;
511
 
 
512
 
          if (id & 0x40)
513
 
            {
514
 
              id &= 0x3f;
515
 
              slots = slot = id;
516
 
              checksum = long_name->checksum;
517
 
            }
518
 
 
519
 
          if (id != slot || slot == 0 || checksum != long_name->checksum)
520
 
            {
521
 
              checksum = -1;
522
 
              continue;
523
 
            }
524
 
 
525
 
          slot--;
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);
529
 
          continue;
530
 
        }
531
 
 
532
 
      /* Check if this entry is valid.  */
533
 
      if (dir.name[0] == 0xe5 || (dir.attr & ~GRUB_FAT_ATTR_VALID))
534
 
        continue;
535
 
 
536
 
      /* This is a workaround for Japanese.  */
537
 
      if (dir.name[0] == 0x05)
538
 
        dir.name[0] = 0xe5;
539
 
 
540
 
      if (checksum != -1 && slot == 0)
541
 
        {
542
 
          grub_uint8_t sum;
543
 
 
544
 
          for (sum = 0, i = 0; i < sizeof (dir.name); i++)
545
 
            sum = ((sum >> 1) | (sum << 7)) + dir.name[i];
546
 
 
547
 
          if (sum == checksum)
548
 
            {
549
 
              int u;
550
 
 
551
 
              for (u = 0; u < slots * 13; u++)
552
 
                unibuf[u] = grub_le_to_cpu16 (unibuf[u]);
553
 
 
554
 
              *grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
555
 
                                   slots * 13) = '\0';
556
 
 
557
 
              if (hook (filename, &dir))
558
 
                break;
559
 
 
560
 
              checksum = -1;
561
 
              continue;
562
 
            }
563
 
 
564
 
          checksum = -1;
565
 
        }
566
 
 
567
 
      /* Convert the 8.3 file name.  */
568
 
      filep = filename;
569
 
      if (dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
570
 
        {
571
 
          for (i = 0; i < sizeof (dir.name) && dir.name[i]
572
 
                 && ! grub_isspace (dir.name[i]); i++)
573
 
            *filep++ = dir.name[i];
574
 
        }
575
 
      else
576
 
        {
577
 
          for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
578
 
            *filep++ = grub_tolower (dir.name[i]);
579
 
 
580
 
          *filep = '.';
581
 
 
582
 
          for (i = 8; i < 11 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
583
 
            *++filep = grub_tolower (dir.name[i]);
584
 
 
585
 
          if (*filep != '.')
586
 
            filep++;
587
 
        }
588
 
      *filep = '\0';
589
 
 
590
 
      if (hook (filename, &dir))
591
 
        break;
592
 
    }
593
 
 
594
 
  grub_free (filename);
595
 
  grub_free (unibuf);
596
 
 
597
 
  return grub_errno;
598
 
}
599
 
 
600
 
 
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.  */
604
 
static char *
605
 
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
606
 
                   const char *path,
607
 
                   int (*hook) (const char *filename,
608
 
                                const struct grub_dirhook_info *info))
609
 
{
610
 
  char *dirname, *dirp;
611
 
  int call_hook;
612
 
  int found = 0;
613
 
 
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)
616
 
  {
617
 
    struct grub_dirhook_info info;
618
 
    grub_memset (&info, 0, sizeof (info));
619
 
 
620
 
    info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY);
621
 
    info.case_insensitive = 1;
622
 
 
623
 
    if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
624
 
      return 0;
625
 
    if (*dirname == '\0' && call_hook)
626
 
      return hook (filename, &info);
627
 
 
628
 
    if (grub_strcasecmp (dirname, filename) == 0)
629
 
      {
630
 
        found = 1;
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;
636
 
 
637
 
        if (call_hook)
638
 
          hook (filename, &info);
639
 
 
640
 
        return 1;
641
 
      }
642
 
    return 0;
643
 
  }
644
 
 
645
 
  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
646
 
    {
647
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
648
 
      return 0;
649
 
    }
650
 
 
651
 
  /* Extract a directory name.  */
652
 
  while (*path == '/')
653
 
    path++;
654
 
 
655
 
  dirp = grub_strchr (path, '/');
656
 
  if (dirp)
657
 
    {
658
 
      unsigned len = dirp - path;
659
 
 
660
 
      dirname = grub_malloc (len + 1);
661
 
      if (! dirname)
662
 
        return 0;
663
 
 
664
 
      grub_memcpy (dirname, path, len);
665
 
      dirname[len] = '\0';
666
 
    }
667
 
  else
668
 
    /* This is actually a file.  */
669
 
    dirname = grub_strdup (path);
670
 
 
671
 
  call_hook = (! dirp && hook);
672
 
 
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");
676
 
 
677
 
  grub_free (dirname);
678
 
 
679
 
  return found ? dirp : 0;
680
 
}
681
 
 
682
 
static grub_err_t
683
 
grub_fat_dir (grub_device_t device, const char *path,
684
 
              int (*hook) (const char *filename,
685
 
                           const struct grub_dirhook_info *info))
686
 
{
687
 
  struct grub_fat_data *data = 0;
688
 
  grub_disk_t disk = device->disk;
689
 
  grub_size_t len;
690
 
  char *dirname = 0;
691
 
  char *p;
692
 
 
693
 
  grub_dl_ref (my_mod);
694
 
 
695
 
  data = grub_fat_mount (disk);
696
 
  if (! data)
697
 
    goto fail;
698
 
 
699
 
  /* Make sure that DIRNAME terminates with '/'.  */
700
 
  len = grub_strlen (path);
701
 
  dirname = grub_malloc (len + 1 + 1);
702
 
  if (! dirname)
703
 
    goto fail;
704
 
  grub_memcpy (dirname, path, len);
705
 
  p = dirname + len;
706
 
  if (path[len - 1] != '/')
707
 
    *p++ = '/';
708
 
  *p = '\0';
709
 
  p = dirname;
710
 
 
711
 
  do
712
 
    {
713
 
      p = grub_fat_find_dir (disk, data, p, hook);
714
 
    }
715
 
  while (p && grub_errno == GRUB_ERR_NONE);
716
 
 
717
 
 fail:
718
 
 
719
 
  grub_free (dirname);
720
 
  grub_free (data);
721
 
 
722
 
  grub_dl_unref (my_mod);
723
 
 
724
 
  return grub_errno;
725
 
}
726
 
 
727
 
static grub_err_t
728
 
grub_fat_open (grub_file_t file, const char *name)
729
 
{
730
 
  struct grub_fat_data *data = 0;
731
 
  char *p = (char *) name;
732
 
 
733
 
  grub_dl_ref (my_mod);
734
 
 
735
 
  data = grub_fat_mount (file->device->disk);
736
 
  if (! data)
737
 
    goto fail;
738
 
 
739
 
  do
740
 
    {
741
 
      p = grub_fat_find_dir (file->device->disk, data, p, 0);
742
 
      if (grub_errno != GRUB_ERR_NONE)
743
 
        goto fail;
744
 
    }
745
 
  while (p);
746
 
 
747
 
  if (data->attr & GRUB_FAT_ATTR_DIRECTORY)
748
 
    {
749
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
750
 
      goto fail;
751
 
    }
752
 
 
753
 
  file->data = data;
754
 
  file->size = data->file_size;
755
 
 
756
 
  return GRUB_ERR_NONE;
757
 
 
758
 
 fail:
759
 
 
760
 
  grub_free (data);
761
 
 
762
 
  grub_dl_unref (my_mod);
763
 
 
764
 
  return grub_errno;
765
 
}
766
 
 
767
 
static grub_ssize_t
768
 
grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
769
 
{
770
 
  return grub_fat_read_data (file->device->disk, file->data, file->read_hook,
771
 
                             file->offset, len, buf);
772
 
}
773
 
 
774
 
static grub_err_t
775
 
grub_fat_close (grub_file_t file)
776
 
{
777
 
  grub_free (file->data);
778
 
 
779
 
  grub_dl_unref (my_mod);
780
 
 
781
 
  return grub_errno;
782
 
}
783
 
 
784
 
static grub_err_t
785
 
grub_fat_label (grub_device_t device, char **label)
786
 
{
787
 
  struct grub_fat_data *data;
788
 
  grub_disk_t disk = device->disk;
789
 
 
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)
792
 
  {
793
 
    if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID)
794
 
      {
795
 
        *label = grub_strdup (filename);
796
 
        return 1;
797
 
      }
798
 
    return 0;
799
 
  }
800
 
 
801
 
  grub_dl_ref (my_mod);
802
 
 
803
 
  data = grub_fat_mount (disk);
804
 
  if (! data)
805
 
    goto fail;
806
 
 
807
 
  if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
808
 
    {
809
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
810
 
      return 0;
811
 
    }
812
 
 
813
 
  *label = 0;
814
 
 
815
 
  grub_fat_iterate_dir (disk, data, iter_hook);
816
 
 
817
 
 fail:
818
 
 
819
 
  grub_dl_unref (my_mod);
820
 
 
821
 
  grub_free (data);
822
 
 
823
 
  return grub_errno;
824
 
}
825
 
 
826
 
static grub_err_t
827
 
grub_fat_uuid (grub_device_t device, char **uuid)
828
 
{
829
 
  struct grub_fat_data *data;
830
 
  grub_disk_t disk = device->disk;
831
 
 
832
 
  grub_dl_ref (my_mod);
833
 
 
834
 
  data = grub_fat_mount (disk);
835
 
  if (data)
836
 
    {
837
 
      *uuid = grub_xasprintf ("%04x-%04x",
838
 
                             (grub_uint16_t) (data->uuid >> 16),
839
 
                             (grub_uint16_t) data->uuid);
840
 
    }
841
 
  else
842
 
    *uuid = NULL;
843
 
 
844
 
  grub_dl_unref (my_mod);
845
 
 
846
 
  grub_free (data);
847
 
 
848
 
  return grub_errno;
849
 
}
850
 
 
851
 
static struct grub_fs grub_fat_fs =
852
 
  {
853
 
    .name = "fat",
854
 
    .dir = grub_fat_dir,
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,
860
 
#ifdef GRUB_UTIL
861
 
    .reserved_first_sector = 1,
862
 
#endif
863
 
    .next = 0
864
 
  };
865
 
 
866
 
GRUB_MOD_INIT(fat)
867
 
{
868
 
  grub_fs_register (&grub_fat_fs);
869
 
  my_mod = mod;
870
 
}
871
 
 
872
 
GRUB_MOD_FINI(fat)
873
 
{
874
 
  grub_fs_unregister (&grub_fat_fs);
875
 
}
876