From 6dd637f44c0523958012f3c28068c631a73b0569 Mon Sep 17 00:00:00 2001 From: Alan Korr Date: Fri, 19 Apr 2002 12:16:19 +0000 Subject: 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 --- firmware/test/fat/fat-bpb_sector.h | 211 ++++++++++++++++++++++ firmware/test/fat/fat-fsi_sector.c | 105 +++++++++++ firmware/test/fat/fat-fsi_sector.h | 80 +++++++++ firmware/test/fat/fat-mbr_sector.c | 65 +++++++ firmware/test/fat/fat-mbr_sector.h | 69 +++++++ firmware/test/fat/fat-partition.h | 161 +++++++++++++++++ firmware/test/fat/fat-volume.c | 355 +++++++++++++++++++++++++++++++++++++ firmware/test/fat/inlines.h | 1 + firmware/test/fat/makefile | 19 +- firmware/test/fat/return_values.h | 7 + firmware/test/fat/types.h | 19 ++ 11 files changed, 1083 insertions(+), 9 deletions(-) create mode 100644 firmware/test/fat/fat-bpb_sector.h create mode 100644 firmware/test/fat/fat-fsi_sector.c create mode 100644 firmware/test/fat/fat-fsi_sector.h create mode 100644 firmware/test/fat/fat-mbr_sector.c create mode 100644 firmware/test/fat/fat-mbr_sector.h create mode 100644 firmware/test/fat/fat-partition.h create mode 100644 firmware/test/fat/fat-volume.c (limited to 'firmware/test/fat') diff --git a/firmware/test/fat/fat-bpb_sector.h b/firmware/test/fat/fat-bpb_sector.h new file mode 100644 index 0000000000..247f53115c --- /dev/null +++ b/firmware/test/fat/fat-bpb_sector.h @@ -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 \ No newline at end of file diff --git a/firmware/test/fat/fat-fsi_sector.c b/firmware/test/fat/fat-fsi_sector.c new file mode 100644 index 0000000000..54863dc2a4 --- /dev/null +++ b/firmware/test/fat/fat-fsi_sector.c @@ -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 +#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 \ No newline at end of file diff --git a/firmware/test/fat/fat-fsi_sector.h b/firmware/test/fat/fat-fsi_sector.h new file mode 100644 index 0000000000..c329148bfa --- /dev/null +++ b/firmware/test/fat/fat-fsi_sector.h @@ -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 \ No newline at end of file diff --git a/firmware/test/fat/fat-mbr_sector.c b/firmware/test/fat/fat-mbr_sector.c new file mode 100644 index 0000000000..f6b510cea5 --- /dev/null +++ b/firmware/test/fat/fat-mbr_sector.c @@ -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 +#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; + } + +// +/////////////////////////////////////////////////////////////////////////////////// diff --git a/firmware/test/fat/fat-mbr_sector.h b/firmware/test/fat/fat-mbr_sector.h new file mode 100644 index 0000000000..11f131e440 --- /dev/null +++ b/firmware/test/fat/fat-mbr_sector.h @@ -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 \ No newline at end of file diff --git a/firmware/test/fat/fat-partition.h b/firmware/test/fat/fat-partition.h new file mode 100644 index 0000000000..1b0e363efb --- /dev/null +++ b/firmware/test/fat/fat-partition.h @@ -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 + +// [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 \ No newline at end of file diff --git a/firmware/test/fat/fat-volume.c b/firmware/test/fat/fat-volume.c new file mode 100644 index 0000000000..dada78c4e6 --- /dev/null +++ b/firmware/test/fat/fat-volume.c @@ -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 +#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); + } diff --git a/firmware/test/fat/inlines.h b/firmware/test/fat/inlines.h index 02242bb4cb..eb776e9792 100644 --- a/firmware/test/fat/inlines.h +++ b/firmware/test/fat/inlines.h @@ -23,4 +23,5 @@ #define __LIBRARY_FAT_INLINES_H__ + #endif \ No newline at end of file diff --git a/firmware/test/fat/makefile b/firmware/test/fat/makefile index 90a8964d40..1cd259b52f 100644 --- a/firmware/test/fat/makefile +++ b/firmware/test/fat/makefile @@ -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 diff --git a/firmware/test/fat/return_values.h b/firmware/test/fat/return_values.h index 114a0abb5f..67747ffc36 100644 --- a/firmware/test/fat/return_values.h +++ b/firmware/test/fat/return_values.h @@ -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 \ No newline at end of file diff --git a/firmware/test/fat/types.h b/firmware/test/fat/types.h index 3a84aa3e97..d83de9e2c1 100644 --- a/firmware/test/fat/types.h +++ b/firmware/test/fat/types.h @@ -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 \ No newline at end of file -- cgit v1.2.3