adding files... nothin working... a lot of thing missing

not speaking about possible drastic changes...


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@144 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Alan Korr 2002-04-19 12:16:19 +00:00
parent b41596560e
commit 6dd637f44c
11 changed files with 1083 additions and 9 deletions

View file

@ -0,0 +1,211 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Alan Korr
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __LIBRARY_FAT_BPB_SECTOR_H__
#define __LIBRARY_FAT_BPB_SECTOR_H__
// [Alan]:
// I would like to draw your attention about the fact that SH1
// cannot use misaligned address access so you must be very cautious
// with structures stored in FAT32 partition because they come from
// PC world where misaligned address accesses are usual and not
// problematic. To avoid such a trouble, I decide to use special
// structures where fields are moved in such a way they can be
// accessed by SH1. It is possible thanks to the callback mechanism
// I use for reading or writing from/to an ATA device in ata.h/c.
// So don't be puzzled if those structures seem odd compared
// with the usual ones from PC world. I use this mechanism for structures
// 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but
// not for structure 'bpb_sector' which is too much complex to handle
// that way, I think.
// By the way, SH1 is big endian, not little endian as PC is.
///////////////////////////////////////////////////////////////////////////////////
// BPB SECTOR :
///////////////
//
//
struct __fat_bpb_sector /* Bios Parameters Block Sector */
{
// jmp_boot has two valid ways to look like in a FAT BPB.
// Either EBXX90 or E9XXXX.
// Not used by Rockbox.
unsigned char
jmp_boot[3];
// Creator system of the fat-drive.
// Usually looks like "MSWIN4.x".
char
oem_name[8];
// It should be 512 if you don't want any trouble
// with Rockbox firmware.
unsigned char
bytes_per_sector[2];
// Must be a power of two.
unsigned char
sectors_per_cluster[1];
// Number of reserved sectors in the reserved region of the volume
// starting at the first sector of the volume.
// Usually 32 for FAT32.
unsigned char
reserved_sectors[2];
// Number of FAT structures.
// This value should always be 2.
unsigned char
number_of_fats[1];
// For FAT32, this field must be set to zero.
// Not used by Rockbox.
unsigned char
number_of_root_entries[2];
// Must be zero for FAT32, since the real value
// can be found in total_sectors.
// Not used by Rockbox.
unsigned char
total_sectors_16[2];
// Not used by Rockbox.
unsigned char
media[1];
// In FAT32 this must be zero.
// Not used by Rockbox.
unsigned char
sectors_per_fat_16[2];
// Sectors per track used on this media.
// Not used by Rockbox.
unsigned char
sectors_per_track[2];
// Number of heads used on this media.
// Not used by Rockbox.
unsigned char
number_of_heads[2];
// Number of hidden sectors.
// Not used by Rockbox.
unsigned char
hidden_sectors[4];
// Number of total sectors.
// For FAT32 volumes, this must be specified.
unsigned char
total_sectors[4];
// Here follows FAT12/16 or FAT32 specific data. */
// This is the number of sectors for one FAT.
unsigned char
sectors_per_fat[4];
// Extended FAT32 flags follow.
unsigned char
flags[2];
// bits 15-8: reserved
// mirroring, bit 7:
// 0 -> FAT is mirrored at runtime into all FATs.
// 1 -> only the one specified in the following field
// is active.
// Rockbox always sets it.
// bits 7-4 : reserved
// active_fat, bits 3-0:
// this specifies the "active" FAT mentioned previously.
// This specifies the file system version.
// High byte is major number, low byte is minor.
// The current version is 0.0.
unsigned char
filesystem_version[2];
// This is set to the cluster number of the first cluster
// of the root directory. Usually 2, but not required.
unsigned char
root_cluster[4];
// This specifies the sector number of the 'FSINFO' structure
// in the reserved area.
unsigned char
filesystem_info[2];
// If zero, this specifies where the backup of bpb
// can be found.
// Usually 6.
// No value other than 6 is recommended by Microsoft.
unsigned char
backup_bpb[2];
// The following area should always be set to zero
// when the volume is initialised.
unsigned char
zeros[12];
// Drive number for BIOS.
// Not used by Rockbox.
unsigned char
drive_number[0];
// Reserved for Windows NT.
// Should always be set to 0.
unsigned char
reserved_for_nt[0];
// Extended boot signature.
// If this is 0x29, the following three fields are present.
unsigned char
boot_signature[0];
// Volume serial number.
unsigned char
volume_id[4];
// Volume label.
// This field must be updated when the volume label
// in the root directory is updated.
char
volume_label[11];
// One of the strings "FAT12", "FAT16" or "FAT32".
// This can not be used to determine the type of the FAT,
// but it should be updated when creating file systems.
char
filesystem_type[8];
char
reserved[420];
long
signature;
};
static inline int __fat_get_bpb_sector (unsigned long partition_start,unsigned long lba,struct __fat_bpb_sector *bpb_sector)
{ return ata_read_sectors (partition_start + lba,1,bpb_sector,0); }
static inline int __fat_put_bpb_sector (unsigned long partition_start,unsigned long lba,struct __fat_bpb_sector *bpb_sector)
{ return FAT_RETURN_SUCCESS && ata_write_sectors (partition_start + lba,1,bpb_sector,0); }
//
///////////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -0,0 +1,105 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Alan Korr
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <fat.h>
#include "fat-fsi_sector.h"
// [Alan]:
// I would like to draw your attention about the fact that SH1
// cannot use misaligned address access so you must be very cautious
// with structures stored in FAT32 partition because they come from
// PC world where misaligned address accesses are usual and not
// problematic. To avoid such a trouble, I decide to use special
// structures where fields are moved in such a way they can be
// accessed by SH1. It is possible thanks to the callback mechanism
// I use for reading or writing from/to an ATA device in ata.h/c.
// So don't be puzzled if those structures seem odd compared
// with the usual ones from PC world. I use this mechanism for structures
// 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but
// not for structure 'bpb_sector' which is too much complex to handle
// that way, I think.
// By the way, SH1 is big endian, not little endian as PC is.
///////////////////////////////////////////////////////////////////////////////////
// FSI SECTOR :
///////////////
//
//
int __fat_get_fsi_sector_callback (struct __fat_fsi_sector *fsi_sector)
{
short *data = fsi_sector->data,*end;
union { unsigned long si[2]; unsigned short hi[4]; unsigned char qi[8]; } words;
for (end = fsi_sector->end0; data < end; ++data)
*data = ata_get_word (0);
#ifdef __little__
words.hi[0] = ata_get_word (0);
words.hi[1] = ata_get_word (0);
words.hi[2] = ata_get_word (0);
words.hi[3] = ata_get_word (0);
#else
words.hi[1] = ata_get_word (0);
words.hi[0] = ata_get_word (0);
words.hi[3] = ata_get_word (0);
words.hi[2] = ata_get_word (0);
#endif
for (end = fsi_sector->end1; data < end; ++data)
*data = ata_get_word (0);
#ifdef __little__
fsi_sector->left_free_clusters = words.si[0];
fsi_sector->next_free_cluster = words.si[1];
#else
fsi_sector->left_free_clusters = swawSI (words.si[0]);
fsi_sector->next_free_cluster = swawSI (words.si[1]);
#endif
return ATA_RETURN_SUCCESS;
}
int __fat_put_fsi_sector_callback (struct __fat_fsi_sector *fsi_sector)
{
short *data = fsi_sector->data,*end;
union { unsigned long si[2]; unsigned short hi[4]; unsigned char qi[8]; } words;
#ifdef __little__
words.si[0] = swawSI (fsi_sector->left_free_clusters);
words.si[1] = swawSI (fsi_sector->next_free_cluster);
#else
words.si[0] = swawSI (fsi_sector->left_free_clusters);
words.si[1] = swawSI (fsi_sector->next_free_cluster);
#endif
for (end = fsi_sector->end0; data < end;)
ata_put_word (*data++);
#ifdef __little__
ata_put_word (words.hi[0],0);
ata_put_word (words.hi[1],0);
ata_put_word (words.hi[2],0);
ata_put_word (words.hi[3],0);
#else
ata_put_word (words.hi[1],0);
ata_put_word (words.hi[0],0);
ata_put_word (words.hi[3],0);
ata_put_word (words.hi[2],0);
#endif
for (end = fsi_sector->end1; data < end;)
ata_put_word (*data++);
return ATA_RETURN_SUCCESS;
}
//
///////////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -0,0 +1,80 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Alan Korr
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __LIBRARY_FAT_FSI_SECTOR_H__
#define __LIBRARY_FAT_FSI_SECTOR_H__
// [Alan]:
// I would like to draw your attention about the fact that SH1
// cannot use misaligned address access so you must be very cautious
// with structures stored in FAT32 partition because they come from
// PC world where misaligned address accesses are usual and not
// problematic. To avoid such a trouble, I decide to use special
// structures where fields are moved in such a way they can be
// accessed by SH1. It is possible thanks to the callback mechanism
// I use for reading or writing from/to an ATA device in ata.h/c.
// So don't be puzzled if those structures seem odd compared
// with the usual ones from PC world. I use this mechanism for structures
// 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but
// not for structure 'bpb_sector' which is too much complex to handle
// that way, I think.
// By the way, SH1 is big endian, not little endian as PC is.
///////////////////////////////////////////////////////////////////////////////////
// FSI SECTOR :
///////////////
//
//
struct __fat_fsi_sector /* File System Info Sector */
{
unsigned long
left_free_clusters;
unsigned long
next_free_cluster;
short
data[0];
long /* 0x61415252 - aARR */
fsi_signature0;
char
reserved0[480];
long /* 0x41617272 - Aarr */
fsi_signature1;
short
end0[0];
char
reserved1[12];
long /* 0x000055AA */
signature;
short
end1[0];
};
int __fat_get_fsi_sector_callback (struct __fat_fsi_sector *fsi_sector);
int __fat_put_fsi_sector_callback (struct __fat_fsi_sector *fsi_sector);
static inline int __fat_get_fsi_sector (unsigned long partition_start,unsigned long lba,struct __fat_fsi_sector *fsi_sector)
{ return ata_read_sectors (partition_start + lba,1,fsi_sector,(int(*)(void *))get_fsi_sector_callback); }
static inline int __fat_put_fsi_sector (unsigned long partition_start,unsigned long lba,struct __fat_fsi_sector *fsi_sector)
{ return ata_write_sectors (partition_start + lba,1,fsi_sector,(int(*)(void *))put_fsi_sector_callback); }
//
///////////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -0,0 +1,65 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Alan Korr
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <fat.h>
#include "fat-mbr_sector.h"
// [Alan]:
// I would like to draw your attention about the fact that SH1
// cannot use misaligned address access so you must be very cautious
// with structures stored in FAT32 partition because they come from
// PC world where misaligned address accesses are usual and not
// problematic. To avoid such a trouble, I decide to use special
// structures where fields are moved in such a way they can be
// accessed by SH1. It is possible thanks to the callback mechanism
// I use for reading or writing from/to an ATA device in ata.h/c.
// So don't be puzzled if those structures seem odd compared
// with the usual ones from PC world. I use this mechanism for structures
// 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but
// not for structure 'bpb_sector' which is too much complex to handle
// that way, I think.
// By the way, SH1 is big endian, not little endian as PC is.
///////////////////////////////////////////////////////////////////////////////////
// MBR SECTOR :
///////////////
//
//
int __fat_get_mbr_sector_callback (struct __fat_mbr_sector *mbr_sector)
{
short *data = mbr_sector->data,*end;
for (end = mbr_sector->end; data < end; ++data)
*data = ata_get_word (0);
__fat_get_partition_table (mbr_sector->partition_table);
mbr_sector->signature = HI(ATAR_DATA);
return FAT_RETURN_SUCCESS;
}
int __fat_put_mbr_sector_callback (struct __fat_mbr_sector *mbr_sector)
{
short const *data = mbr_sector->data,*end;
for (end = mbr_sector->end; data < end;)
HI(ATAR_DATA) = *data++;
__fat_put_partition_table (mbr_sector->partition_table);
ata_put_word (mbr_sector->signature,0);
return FAT_RETURN_SUCCESS;
}
//
///////////////////////////////////////////////////////////////////////////////////

View file

@ -0,0 +1,69 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Alan Korr
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __LIBRARY_FAT_MBR_SECTOR_H__
#define __LIBRARY_FAT_MBR_SECTOR_H__
#include "fat-partition.h"
// [Alan]:
// I would like to draw your attention about the fact that SH1
// cannot use misaligned address access so you must be very cautious
// with structures stored in FAT32 partition because they come from
// PC world where misaligned address accesses are usual and not
// problematic. To avoid such a trouble, I decide to use special
// structures where fields are moved in such a way they can be
// accessed by SH1. It is possible thanks to the callback mechanism
// I use for reading or writing from/to an ATA device in ata.h/c.
// So don't be puzzled if those structures seem odd compared
// with the usual ones from PC world. I use this mechanism for structures
// 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but
// not for structure 'bpb_sector' which is too much complex to handle
// that way, I think.
// By the way, SH1 is big endian, not little endian as PC is.
///////////////////////////////////////////////////////////////////////////////////
// MBR SECTOR :
///////////////
//
//
struct __fat_mbr_sector /* Master Boot Record Sector */
{
struct
__fat_partition_info partition_table[4];
short
data[0x1BE/2];
short
end[0];
short
signature;
};
int __fat_get_mbr_sector_callback (struct __fat_mbr_sector *mbr_sector);
int __fat_put_mbr_sector_callback (struct __fat_mbr_sector *mbr_sector);
static inline int __fat_get_mbr_sector (struct mbr_sector *__fat_mbr_sector)
{ return ata_read_sectors (0,1,mbr_sector,(int(*)(void *))__fat_get_mbr_sector_callback); }
static inline int __fat_put_mbr_sector (struct mbr_sector *__fat_mbr_sector)
{ return ata_write_sectors (0,1,mbr_sector,(int(*)(void *))__fat_put_mbr_sector_callback); }
//
///////////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -0,0 +1,161 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:
*
* Copyright (C) 2002 by Alan Korr
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __LIBRARY_FAT_PARTITION_H__
#define __LIBRARY_FAT_PARTITION_H__
#include <ata/ata.h>
// [Alan]:
// I would like to draw your attention about the fact that SH1
// cannot use misaligned address access so you must be very cautious
// with structures stored in FAT32 partition because they come from
// PC world where misaligned address accesses are usual and not
// problematic. To avoid such a trouble, I decide to use special
// structures where fields are moved in such a way they can be
// accessed by SH1. It is possible thanks to the callback mechanism
// I use for reading or writing from/to an ATA device in ata.h/c.
// So don't be puzzled if those structures seem odd compared
// with the usual ones from PC world. I use this mechanism for structures
// 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but
// not for structure 'bpb_sector' which is too much complex to handle
// that way, I think.
// By the way, SH1 is big endian, not little endian as PC is.
///////////////////////////////////////////////////////////////////////////////////
// PARTITION INFO :
///////////////////
//
//
struct __fat_partition_info
{
// Absolute start sector in this partition :
// start = start_cylinder * heads * sectors + start_head * sectors + start_sector - 1
unsigned long
start;
// Number of sectors in this partition :
// sectors = end_cylinder * heads * sectors + end_head * sectors + end_sector - start_sector
unsigned long
sectors;
// File system type.
// Must be a FAT32 file system type (0x0B or 0x0C)
// for Rockbox.
char
filesystem_type;
// Is this partition bootable ?
// Not used by Rockbox.
char
bootable;
// Not used by Rockbox.
unsigned char
start_head;
// Not used by Rockbox.
unsigned char
start_cylinder;
// Not used by Rockbox.
unsigned char
start_sector;
// Not used by Rockbox.
unsigned char
end_head;
// Not used by Rockbox.
unsigned char
end_cylinder;
// Not used by Rockbox.
unsigned char
end_sector;
};
// load partition info into memory
static inline void __fat_get_partition_info (struct partition_info *__fat_partition_info)
{
//
union { unsigned long si[4]; unsigned short hi[8]; unsigned char qi[16]; } words;
short *data = words.hi,*end;
for (end = data + 8; data < end; ++data)
*data = HI(ATAR_DATA);
partition_info->start = swawSI(words.si[2]);
partition_info->sectors = swawSI(words.si[3]);
partition_info->bootable = words.qi[1];
partition_info->filesystem_type = words.qi[5];
partition_info->start_head = words.qi[0];
partition_info->start_cylinder = words.qi[3];
partition_info->start_sector = words.qi[2];
partition_info->end_head = words.qi[4];
partition_info->end_cylinder = words.qi[7];
partition_info->end_sector = words.qi[6];
}
// store partition info into harddisk
static inline void __fat_put_partition_info (struct partition_info *__fat_partition_info)
{
union { unsigned long si[4]; short hi[8]; unsigned char qi[16]; } words;
short *data = words.hi,*end;
words.si[2] = swawSI(partition_info->start);
words.si[3] = swawSI(partition_info->sectors);
words.qi[1] = partition_info->bootable;
words.qi[5] = partition_info->filesystem_type;
words.qi[0] = partition_info->start_head;
words.qi[3] = partition_info->start_cylinder;
words.qi[2] = partition_info->start_sector;
words.qi[4] = partition_info->end_head;
words.qi[7] = partition_info->end_cylinder;
words.qi[6] = partition_info->end_sector;
for (end = data + 8; data < end;)
HI(ATAR_DATA) = *data++;
}
//
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
// PARTITION TABLE :
////////////////////
//
//
// load the partition table from a mbr sector
static inline void __fat_get_partition_table (struct partition_info table[4])
{
struct partition_info *last;
for (last = table + 4; table < last;)
__fat_get_partition_info (table++);
}
// store the partition table into a mbr sector
static inline void __fat_put_partition_table (struct partition_info const table[4])
{
struct partition_info const *last;
for (last = table + 4; table < last;)
__fat_put_partition_info (table++);
}
//
///////////////////////////////////////////////////////////////////////////////////
#endif

View file

@ -0,0 +1,355 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id:
*
* Copyright (C) 2002 by Alan Korr
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#define __LIBRARY_FAT_VOLUME_C__
#include <fat.h>
#include "fat-mbr_sector.h"
#include "fat-bpb_sector.h"
#include "fat-fsi_sector.h"
///////////////////////////////////////////////////////////////////////////////////
// FAT VOLUME :
///////////////
//
//
// check fsi sector integrity
static int __fat_check_fsi_sector (struct fat_volume *volume,struct __fat_fsi_sector *fsi_sector,unsigned long lba)
{
int error;
if (!lba)
// no FSI sector
{
volume->next_free_cluster = 2;
return FAT_RETURN_SUCCESS;
}
if ((error = __fat_get_fsi_sector (volume->partition_start,lba,fsi_sector)) > 0)
{
if ((fsi_sector->signature != 0x0000AA55) ||
(fsi_sector->fsi_signature0 != 0x52524161) ||
(fsi_sector->fsi_signature1 != 0x72726141))
{
return FAT_RETURN_BAD_FSI;
}
if (fsi_sector->left_free_clusters == -1)
fsi_sector->next_free_cluster = 2;
else if (fsi_sector->next_free_cluster >= volume->sectors_per_fat)
return FAT_RETURN_BAD_FSI;
volume->next_free_cluster = fsi_sector->next_free_cluster;
fsi_sector->left_free_clusters = -1;
fsi_sector->next_free_cluster = 2;
error = __fat_put_fsi_sector (volume->partition_start,lba,fsi_sector)));
}
return error;
}
static inline int bit_in_range (int value,int min,int max)
{
for (;min < max; min <<= 1)
if (value == min)
return 1;
return 0;
}
// check bpb sector integrity
static int __fat_check_bpb_sector (struct fat_volume *volume,struct __fat_bpb_sector *bpb_sector,struct __fat_fsi_sector *fsi_sector)
{
long unsigned bpb_lba = 0,fsi_lba;
long unsigned sectors_per_cluster,sectors_per_fat,sectors,reserved_sectors,total_sectors;
long unsigned first_cluster_of_root,first_sector_of_fat,first_sector_of_data;
long unsigned clusters_per_fat,bytes_per_sector;
int error,backup;
for (backup = 0; !backup ; backup = 1)
{
if ((error = __fat_get_bpb_sector (volume->partition_start,bpb_lba,bpb_sector)) > 0)
{
bytes_per_sector = peekHI (bpb_sector->bytes_per_sector );
sectors_per_cluster = peekQI (bpb_sector->sectors_per_cluster);
sectors_per_fat = peekSI (bpb_sector->sectors_per_fat );
sectors = peekQI (bpb_sector->number_of_fats ) * sectors_per_fat;
reserved_sectors = peekHI (bpb_sector->reserved_sectors );
total_sectors = peekSI (bpb_sector->total_sectors );
first_cluster_of_root = peekSI (bpb_sector->root_cluster );
first_sector_of_fat = reserved_sectors + volume->partition_start;
first_sector_of_data = first_sector_of_fat + sectors;
clusters_per_fat = (total_sectors - first_sector_of_data) / sectors_per_cluster;
if (!bpb_lba)
{
bpb_lba = peekHI(bpb_sector->backup_bpb);
if (bpb_lba == -1)
bpb_lba = 0;
}
if ((bpb_lba >= reserved_sectors) ||
(bpb_sector->signature != 0x000055AA) ||
(clusters_per_fat < 65525) ||
(bytes_per_sector != 512) ||
(!bit_in_range (sectors_per_cluster,1,128)) ||
(bytes_per_sector * sectors_per_cluster >= 32 KB) ||
(peekHI (bpb_sector->total_sectors_16)) ||
(peekHI (bpb_sector->sectors_per_fat_16)) ||
(peekHI (bpb_sector->number_of_root_entries)) ||
((bpb_sector->media[0] != 0xF0) && (bpb_sector->media[0] < 0xF8)))
{
error = FAT_RETURN_BAD_BPB;
if (bpb_lba) // try with backup BPB sector ?
continue;
return error;
}
if ((signed char)bpb_sector->flags[0] >= 0)
{
bpb_sector->flags[0] = 0x80;
if (!backup && (error = __fat_put_bpb_sector (volume->partition_start,0,bpb_sector)) <= 0)
return error;
if ((error = __fat_put_bpb_sector (volume->partition_start,bpb_lba,bpb_sector)) <= 0)
return error;
}
volume->sectors_per_cluster = sectors_per_cluster;
volume->sectors_per_fat = sectors_per_fat;
volume->first_cluster_of_root = first_cluster_of_root;
volume->first_sector_of_fat = first_sector_of_fat;
volume->first_sector_of_data = first_sector_of_data;
volume->clusters_per_fat = clusters_per_fat;
fsi_lba = ((long)peekHI(bpb_sector->filesystem_info));
if (fsi_lba == -1)
fsi_lba = 0;
else if (fsi_lba >= reserved_sectors)
{
error = FAT_RETURN_BAD_FSI;
if (bpb_lba) // try with backup BPB sector ?
continue;
return error;
}
if (((error = __fat_check_fsi_sector (volume,fsi_sector,fsi_lba + (backup ? 0 : bpb_lba))) <= 0) && bpb_lba)
continue;
if (backup)
{
error = __fat_put_bpb_sector (volume,0,bpb_sector)) <= 0);
if (!error)
error = __fat_put_fsi_sector (volume,fsi_lba,fsi_sector)) <= 0);
}
break;
}
}
return error;
}
static inline int __fat_compare_volume_name (char const *name,struct fat_volume *volume)
{
return !name ? -1 : strncpy (name,volume->name,11);
}
static struct fat_volume *__fat_splay_volume (struct fat_volume *root,char const *name)
{
struct fat_volume *down;
struct fat_volume *less;
struct fat_volume *more;
struct fat_volume *head[2];
((struct fat_volume *)head)->less =
((struct fat_volume *)head)->more = 0;
less =
more = head;
while (1)
{
int sign = __fat_compare_volume_name (name,root);
if (sign < 0)
{
if ((down = root->less))
{
sign = __fat_compare_volume_name (name,down);
if (sign < 0)
{
root->less = down->more;
down->more = root;
root = down;
if (!root->less)
break;
}
more->less = root;
more = root;
root = root->less;
continue;
}
break;
}
if (0 < sign)
{
if ((down = root->more))
{
sign = __fat_compare_volume_name (name,down);
if (0 < sign)
{
root->more = down->less;
down->less = root;
root = down;
if (!root->more)
break;
}
less->more = root;
less = root;
root = root->more;
continue;
}
}
break;
}
less->more = root->less;
more->less = root->more;
root->less = ((struct fat_volume *)head)->more;
root->more = ((struct fat_volume *)head)->less;
return root;
}
static inline struct fat_volume *__fat_insert_volume (struct fat_volume *root,struct fat_volume *node)
{
if (!root)
{
node->less =
node->more = 0;
}
else if (node < (root = __fat_splay_volume (root,node->name)))
{
node->less = root->less;
node->more = root;
root->less = 0;
}
else if
{
node->less = root;
node->more = root->more;
node->more = 0;
}
return node;
}
#if 0
static inline struct fat_volume *__fat_remove_volume (struct fat_volume *root,struct memory_free_page *node)
{
root = __fat_splay_volume (root,node->name);
if (root->less)
{
node = __fat_splay_volume (root->less,node->name);
node->more = root->more;
}
else
node = root->more;
return node;
}
#endif
static inline struct fat_volume *__fat_lookup_volume (struct fat_volume *root,char const *name)
{
return __fat_splay_volume (root,0);
}
static struct fat_volume *__fat_first_volume (struct fat_volume *root)
{
struct fat_volume *down;
struct fat_volume *less;
struct fat_volume *more;
struct fat_volume *head[2];
((struct fat_volume *)head)->less =
((struct fat_volume *)head)->more = 0;
less =
more = &head;
if (root)
while (1)
{
if ((down = root->less))
{
root->less = down->more;
down->more = root;
root = down;
if (!root->less)
break;
more->less = root;
more = root;
root = root->less;
continue;
}
break;
}
less->more = root->less;
more->less = root->more;
root->less = ((struct fat_volume *)head)->more;
root->more = ((struct fat_volume *)head)->less;
return root;
}
static inline struct fat_volume *__fat_scan_volume (struct fat_volume *root,int next)
{
return __fat_first_volume (next ? root->more : root,0);
}
static int __fat_build_volume_tree (struct fat_volume *root)
{
struct fat_volume *volume;
int number = 4;
struct __fat_partition_info *partition_info;
struct __fat_mbr_sector mbr_sector;
struct __fat_bpb_sector bpb_sector;
struct __fat_fsi_sector fsi_sector;
if (__fat_get_mbr_sector (&mbr_sector) <= 0)
return 0;
partition_info = mbr_sector.partition_table;
for (;number-- > 0; ++partition_info)
{
switch (partition_info->filesystem_type)
{
case 0x05: // extended partition - handle it as well
{
if (!__fat_build_volume_list (list))
return 0;
break;
}
case 0x0B: // FAT32 partitions
case 0x0C:
{
if (!(volume = memory_allocate_page (0)))
return 0;
volume->next = 0;
volume->partition_start = partition_info->start;
volume->partition_sectors = partition_info->sectors;
if (__fat_check_bpb_sector (volume,&mbr_sector,&fsi_sector) > 0)
{
dump_volume (volume);
*root = volume;
list = &volume->next;
break;
}
else
memory_release_page (volume,0);
}
}
}
return 1;
}
static struct fat_volume *__fat_volume_root;
void fat_setup (void)
{
//build_volume_list (&root);
}

View file

@ -23,4 +23,5 @@
#define __LIBRARY_FAT_INLINES_H__
#endif

View file

@ -1,20 +1,21 @@
#############################################################################
##############################################################################
## __________ __ ___.
## Open \______ \ ____ ____ | | _\_ |__ _______ ___
## Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
## Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
## Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
## \/ \/ \/ \/ \/
## Copyright Alan Korr, 2002. All rights reserved.
## $Id:
##
## Permission to use, copy, modify, and distribute this software for any
## purpose is hereby granted without fee, provided that this copyright and
## permissions notice appear in all copies and derivatives, and that no
## charge may be made for the software and its documentation except to cover
## cost of distribution.
## Copyright (C) 2002 by Alan Korr
##
## This software is provided "as is" without express or implied warranty.
#############################################################################
## All files in this archive are subject to the GNU General Public License.
## See the file COPYING in the source tree root for full license agreement.
##
## This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
## KIND, either express or implied.
##
##############################################################################
ARCH = test
PACKAGE = fat
VERSION = 0.0.0

View file

@ -21,4 +21,11 @@
#endif
#ifndef __LIBRARY_FAT_RETURN_VALUES_H__
# define __LIBRARY_FAT_RETURN_VALUES_H__
enum
{
FAT_RETURN_SUCCESS = 1,
FAT_RETURN_FAILURE = 0
};
#endif

View file

@ -21,4 +21,23 @@
#endif
#ifndef __LIBRARY_FAT_TYPES_H__
# define __LIBRARY_FAT_TYPES_H__
// [Alan]:
// I would like to draw your attention about the fact that SH1
// cannot use misaligned address access so you must be very cautious
// with structures stored in FAT32 partition because they come from
// PC world where misaligned address accesses are usual and not
// problematic. To avoid such a trouble, I decide to use special
// structures where fields are moved in such a way they can be
// accessed by SH1. It is possible thanks to the callback mechanism
// I use for reading or writing from/to an ATA device in ata.h/c.
// So don't be puzzled if those structures seem odd compared
// with the usual ones from PC world. I use this mechanism for structures
// 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but
// not for structure 'bpb_sector' which is too much complex to handle
// that way, I think.
// By the way, SH1 is big endian, not little endian as PC is.
#endif