fsys_fat.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef FSYS_FAT
#include "shared.h"
#include "filesys.h"
#include "fat.h"
struct fat_superblock
{
int fat_offset;
int fat_length;
int fat_size;
int root_offset;
int root_max;
int data_offset;
int num_sectors;
int num_clust;
int clust_eof_marker;
int sects_per_clust;
int sectsize_bits;
int clustsize_bits;
int root_cluster;
int cached_fat;
int file_cluster;
int current_cluster_num;
int current_cluster;
};
/* pointer(s) into filesystem info buffer for DOS stuff */
#define FAT_SUPER ( (struct fat_superblock *) \
#define FAT_CACHE_SIZE 2048
static __inline__ unsigned long
{
__asm__ ("bsfl %1,%0"
: "=r" (word)
: "r" (word));
return word;
}
int
fat_mount (void)
{
/* Check partition type for harddisk */
return 0;
/* Read bpb */
return 0;
/* Check if the number of sectors per cluster is zero here, to avoid
zero division. */
if (bpb.sects_per_clust == 0)
return 0;
/* Fill in info about super block */
/* FAT offset and length */
/* Rootdir offset and length for FAT12/16 */
/* Data offset and number of clusters */
/ bpb.sects_per_clust);
if (!bpb.fat_length)
{
/* This is a FAT32 */
return 0;
{
/* FAT mirroring is disabled, get active FAT */
return 0;
}
/* Yes the following is correct. FAT32 should be called FAT28 :) */
}
else
{
return 0;
{
}
else
{
}
}
/* Now do some sanity checks */
- FAT_SUPER->sectsize_bits))
> FAT_SUPER->fat_length))
return 0;
/* kbs: Media check on first FAT entry [ported from PUPA] */
return 0;
{
first_fat &= 0x0fffffff;
magic = 0x0fffff00;
}
{
first_fat &= 0x0000ffff;
magic = 0xff00;
}
else
{
first_fat &= 0x00000fff;
magic = 0x0f00;
}
return 0;
return 1;
}
int
{
int logical_clust;
int offset;
int ret = 0;
int size;
if (FAT_SUPER->file_cluster < 0)
{
/* root directory for fat16 */
return 0;
return size;
}
{
FAT_SUPER->current_cluster_num = 0;
}
while (len > 0)
{
int sector;
{
/* calculate next cluster */
int fat_entry =
int next_cluster;
if (cached_pos < 0 ||
{
return 0;
}
{
if (cached_pos & 1)
next_cluster >>= 4;
next_cluster &= 0xFFF;
}
next_cluster &= 0xFFFF;
return ret;
{
return 0;
}
}
- FAT_SUPER->sectsize_bits));
offset = 0;
}
}
int
{
int attrib = FAT_ATTRIB_DIR;
#ifndef STAGE1_5
int do_possibilities = 0;
#endif
/* XXX I18N:
* the positions 2,4,6 etc are high bytes of a 16 bit unicode char
*/
static unsigned char longdir_pos[] =
{ 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };
int slot = -2;
int alias_checksum = -1;
filepos = 0;
/* main loop to find desired directory entry */
loop:
/* if we have a real file (and we're not just printing possibilities),
then this is where we want to exit */
{
if (attrib & FAT_ATTRIB_DIR)
{
return 0;
}
return 1;
}
while (*dirname == '/')
dirname++;
if (!(attrib & FAT_ATTRIB_DIR))
{
return 0;
}
/* Directories don't have a file size */
*rest = 0;
# ifndef STAGE1_5
do_possibilities = 1;
# endif
while (1)
{
|| dir_buf[0] == 0)
{
if (!errnum)
{
# ifndef STAGE1_5
if (print_possibilities < 0)
{
#if 0
putchar ('\n');
#endif
return 1;
}
# endif /* STAGE1_5 */
}
return 0;
}
{
/* This is a long filename. The filename is build from back
* to front and may span multiple entries. To bind these
* entries together they all contain the same checksum over
* the short alias.
*
* The id field tells if this is the first entry (the last
* part) of the long filename, and also at which offset this
* belongs.
*
* We just write the part of the long filename this entry
* describes and continue with the next dir entry.
*/
int i, offset;
if ((id & 0x40))
{
id &= 0x3f;
}
{
alias_checksum = -1;
continue;
}
slot--;
for (i=0; i < 13; i++)
continue;
}
if (!FAT_DIRENTRY_VALID (dir_buf))
continue;
{
int i;
unsigned char sum;
slot = -2;
for (sum = 0, i = 0; i< 11; i++)
if (sum == alias_checksum)
{
# ifndef STAGE1_5
if (do_possibilities)
goto print_filename;
# endif /* STAGE1_5 */
break;
}
}
/* XXX convert to 8.3 filename format here */
{
int i, j, c;
&& !isspace (c); i++);
filename[i++] = '.';
&& !isspace (c); j++);
if (j == 0)
i--;
filename[i + j] = 0;
}
# ifndef STAGE1_5
if (do_possibilities)
{
{
if (print_possibilities > 0)
}
continue;
}
# endif /* STAGE1_5 */
break;
}
filepos = 0;
/* go back to main loop at top of function */
goto loop;
}
#endif /* FSYS_FAT */