mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
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:
parent
b41596560e
commit
6dd637f44c
11 changed files with 1083 additions and 9 deletions
211
firmware/test/fat/fat-bpb_sector.h
Normal file
211
firmware/test/fat/fat-bpb_sector.h
Normal 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
|
105
firmware/test/fat/fat-fsi_sector.c
Normal file
105
firmware/test/fat/fat-fsi_sector.c
Normal 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
|
80
firmware/test/fat/fat-fsi_sector.h
Normal file
80
firmware/test/fat/fat-fsi_sector.h
Normal 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
|
65
firmware/test/fat/fat-mbr_sector.c
Normal file
65
firmware/test/fat/fat-mbr_sector.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
69
firmware/test/fat/fat-mbr_sector.h
Normal file
69
firmware/test/fat/fat-mbr_sector.h
Normal 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
|
161
firmware/test/fat/fat-partition.h
Normal file
161
firmware/test/fat/fat-partition.h
Normal 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
|
355
firmware/test/fat/fat-volume.c
Normal file
355
firmware/test/fat/fat-volume.c
Normal 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);
|
||||||
|
}
|
|
@ -23,4 +23,5 @@
|
||||||
#define __LIBRARY_FAT_INLINES_H__
|
#define __LIBRARY_FAT_INLINES_H__
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,20 +1,21 @@
|
||||||
#############################################################################
|
##############################################################################
|
||||||
## __________ __ ___.
|
## __________ __ ___.
|
||||||
## Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
## Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
## Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
## Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
## Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
## Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
## Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
## Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
## \/ \/ \/ \/ \/
|
## \/ \/ \/ \/ \/
|
||||||
## Copyright Alan Korr, 2002. All rights reserved.
|
## $Id:
|
||||||
##
|
##
|
||||||
## Permission to use, copy, modify, and distribute this software for any
|
## Copyright (C) 2002 by Alan Korr
|
||||||
## 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.
|
|
||||||
##
|
##
|
||||||
## 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
|
ARCH = test
|
||||||
PACKAGE = fat
|
PACKAGE = fat
|
||||||
VERSION = 0.0.0
|
VERSION = 0.0.0
|
||||||
|
|
|
@ -21,4 +21,11 @@
|
||||||
#endif
|
#endif
|
||||||
#ifndef __LIBRARY_FAT_RETURN_VALUES_H__
|
#ifndef __LIBRARY_FAT_RETURN_VALUES_H__
|
||||||
# define __LIBRARY_FAT_RETURN_VALUES_H__
|
# define __LIBRARY_FAT_RETURN_VALUES_H__
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FAT_RETURN_SUCCESS = 1,
|
||||||
|
FAT_RETURN_FAILURE = 0
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -21,4 +21,23 @@
|
||||||
#endif
|
#endif
|
||||||
#ifndef __LIBRARY_FAT_TYPES_H__
|
#ifndef __LIBRARY_FAT_TYPES_H__
|
||||||
# define __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
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue