diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/test/fat/fat-bpb_sector.h | 211 | ||||
-rw-r--r-- | firmware/test/fat/fat-fsi_sector.c | 105 | ||||
-rw-r--r-- | firmware/test/fat/fat-fsi_sector.h | 80 | ||||
-rw-r--r-- | firmware/test/fat/fat-mbr_sector.c | 65 | ||||
-rw-r--r-- | firmware/test/fat/fat-mbr_sector.h | 69 | ||||
-rw-r--r-- | firmware/test/fat/fat-partition.h | 161 | ||||
-rw-r--r-- | firmware/test/fat/fat-volume.c | 355 | ||||
-rw-r--r-- | firmware/test/fat/inlines.h | 1 | ||||
-rw-r--r-- | firmware/test/fat/makefile | 19 | ||||
-rw-r--r-- | firmware/test/fat/return_values.h | 7 | ||||
-rw-r--r-- | firmware/test/fat/types.h | 19 |
11 files changed, 1083 insertions, 9 deletions
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef __LIBRARY_FAT_BPB_SECTOR_H__ | ||
20 | #define __LIBRARY_FAT_BPB_SECTOR_H__ | ||
21 | |||
22 | // [Alan]: | ||
23 | // I would like to draw your attention about the fact that SH1 | ||
24 | // cannot use misaligned address access so you must be very cautious | ||
25 | // with structures stored in FAT32 partition because they come from | ||
26 | // PC world where misaligned address accesses are usual and not | ||
27 | // problematic. To avoid such a trouble, I decide to use special | ||
28 | // structures where fields are moved in such a way they can be | ||
29 | // accessed by SH1. It is possible thanks to the callback mechanism | ||
30 | // I use for reading or writing from/to an ATA device in ata.h/c. | ||
31 | // So don't be puzzled if those structures seem odd compared | ||
32 | // with the usual ones from PC world. I use this mechanism for structures | ||
33 | // 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but | ||
34 | // not for structure 'bpb_sector' which is too much complex to handle | ||
35 | // that way, I think. | ||
36 | // By the way, SH1 is big endian, not little endian as PC is. | ||
37 | |||
38 | /////////////////////////////////////////////////////////////////////////////////// | ||
39 | // BPB SECTOR : | ||
40 | /////////////// | ||
41 | // | ||
42 | // | ||
43 | |||
44 | struct __fat_bpb_sector /* Bios Parameters Block Sector */ | ||
45 | { | ||
46 | // jmp_boot has two valid ways to look like in a FAT BPB. | ||
47 | // Either EBXX90 or E9XXXX. | ||
48 | // Not used by Rockbox. | ||
49 | unsigned char | ||
50 | jmp_boot[3]; | ||
51 | |||
52 | // Creator system of the fat-drive. | ||
53 | // Usually looks like "MSWIN4.x". | ||
54 | char | ||
55 | oem_name[8]; | ||
56 | |||
57 | // It should be 512 if you don't want any trouble | ||
58 | // with Rockbox firmware. | ||
59 | unsigned char | ||
60 | bytes_per_sector[2]; | ||
61 | |||
62 | // Must be a power of two. | ||
63 | unsigned char | ||
64 | sectors_per_cluster[1]; | ||
65 | |||
66 | // Number of reserved sectors in the reserved region of the volume | ||
67 | // starting at the first sector of the volume. | ||
68 | // Usually 32 for FAT32. | ||
69 | unsigned char | ||
70 | reserved_sectors[2]; | ||
71 | |||
72 | // Number of FAT structures. | ||
73 | // This value should always be 2. | ||
74 | unsigned char | ||
75 | number_of_fats[1]; | ||
76 | |||
77 | // For FAT32, this field must be set to zero. | ||
78 | // Not used by Rockbox. | ||
79 | unsigned char | ||
80 | number_of_root_entries[2]; | ||
81 | |||
82 | // Must be zero for FAT32, since the real value | ||
83 | // can be found in total_sectors. | ||
84 | // Not used by Rockbox. | ||
85 | unsigned char | ||
86 | total_sectors_16[2]; | ||
87 | |||
88 | // Not used by Rockbox. | ||
89 | unsigned char | ||
90 | media[1]; | ||
91 | |||
92 | // In FAT32 this must be zero. | ||
93 | // Not used by Rockbox. | ||
94 | unsigned char | ||
95 | sectors_per_fat_16[2]; | ||
96 | |||
97 | // Sectors per track used on this media. | ||
98 | // Not used by Rockbox. | ||
99 | unsigned char | ||
100 | sectors_per_track[2]; | ||
101 | |||
102 | // Number of heads used on this media. | ||
103 | // Not used by Rockbox. | ||
104 | unsigned char | ||
105 | number_of_heads[2]; | ||
106 | |||
107 | // Number of hidden sectors. | ||
108 | // Not used by Rockbox. | ||
109 | unsigned char | ||
110 | hidden_sectors[4]; | ||
111 | |||
112 | // Number of total sectors. | ||
113 | // For FAT32 volumes, this must be specified. | ||
114 | unsigned char | ||
115 | total_sectors[4]; | ||
116 | |||
117 | // Here follows FAT12/16 or FAT32 specific data. */ | ||
118 | |||
119 | // This is the number of sectors for one FAT. | ||
120 | unsigned char | ||
121 | sectors_per_fat[4]; | ||
122 | |||
123 | // Extended FAT32 flags follow. | ||
124 | unsigned char | ||
125 | flags[2]; | ||
126 | // bits 15-8: reserved | ||
127 | // mirroring, bit 7: | ||
128 | // 0 -> FAT is mirrored at runtime into all FATs. | ||
129 | // 1 -> only the one specified in the following field | ||
130 | // is active. | ||
131 | // Rockbox always sets it. | ||
132 | // bits 7-4 : reserved | ||
133 | // active_fat, bits 3-0: | ||
134 | // this specifies the "active" FAT mentioned previously. | ||
135 | |||
136 | // This specifies the file system version. | ||
137 | // High byte is major number, low byte is minor. | ||
138 | // The current version is 0.0. | ||
139 | unsigned char | ||
140 | filesystem_version[2]; | ||
141 | |||
142 | // This is set to the cluster number of the first cluster | ||
143 | // of the root directory. Usually 2, but not required. | ||
144 | unsigned char | ||
145 | root_cluster[4]; | ||
146 | |||
147 | // This specifies the sector number of the 'FSINFO' structure | ||
148 | // in the reserved area. | ||
149 | unsigned char | ||
150 | filesystem_info[2]; | ||
151 | |||
152 | // If zero, this specifies where the backup of bpb | ||
153 | // can be found. | ||
154 | // Usually 6. | ||
155 | // No value other than 6 is recommended by Microsoft. | ||
156 | unsigned char | ||
157 | backup_bpb[2]; | ||
158 | |||
159 | // The following area should always be set to zero | ||
160 | // when the volume is initialised. | ||
161 | unsigned char | ||
162 | zeros[12]; | ||
163 | |||
164 | // Drive number for BIOS. | ||
165 | // Not used by Rockbox. | ||
166 | unsigned char | ||
167 | drive_number[0]; | ||
168 | |||
169 | // Reserved for Windows NT. | ||
170 | // Should always be set to 0. | ||
171 | unsigned char | ||
172 | reserved_for_nt[0]; | ||
173 | |||
174 | // Extended boot signature. | ||
175 | // If this is 0x29, the following three fields are present. | ||
176 | unsigned char | ||
177 | boot_signature[0]; | ||
178 | |||
179 | // Volume serial number. | ||
180 | unsigned char | ||
181 | volume_id[4]; | ||
182 | |||
183 | // Volume label. | ||
184 | // This field must be updated when the volume label | ||
185 | // in the root directory is updated. | ||
186 | char | ||
187 | volume_label[11]; | ||
188 | |||
189 | // One of the strings "FAT12", "FAT16" or "FAT32". | ||
190 | // This can not be used to determine the type of the FAT, | ||
191 | // but it should be updated when creating file systems. | ||
192 | char | ||
193 | filesystem_type[8]; | ||
194 | |||
195 | char | ||
196 | reserved[420]; | ||
197 | |||
198 | long | ||
199 | signature; | ||
200 | }; | ||
201 | |||
202 | static inline int __fat_get_bpb_sector (unsigned long partition_start,unsigned long lba,struct __fat_bpb_sector *bpb_sector) | ||
203 | { return ata_read_sectors (partition_start + lba,1,bpb_sector,0); } | ||
204 | |||
205 | static inline int __fat_put_bpb_sector (unsigned long partition_start,unsigned long lba,struct __fat_bpb_sector *bpb_sector) | ||
206 | { return FAT_RETURN_SUCCESS && ata_write_sectors (partition_start + lba,1,bpb_sector,0); } | ||
207 | |||
208 | // | ||
209 | /////////////////////////////////////////////////////////////////////////////////// | ||
210 | |||
211 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <fat.h> | ||
20 | #include "fat-fsi_sector.h" | ||
21 | |||
22 | // [Alan]: | ||
23 | // I would like to draw your attention about the fact that SH1 | ||
24 | // cannot use misaligned address access so you must be very cautious | ||
25 | // with structures stored in FAT32 partition because they come from | ||
26 | // PC world where misaligned address accesses are usual and not | ||
27 | // problematic. To avoid such a trouble, I decide to use special | ||
28 | // structures where fields are moved in such a way they can be | ||
29 | // accessed by SH1. It is possible thanks to the callback mechanism | ||
30 | // I use for reading or writing from/to an ATA device in ata.h/c. | ||
31 | // So don't be puzzled if those structures seem odd compared | ||
32 | // with the usual ones from PC world. I use this mechanism for structures | ||
33 | // 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but | ||
34 | // not for structure 'bpb_sector' which is too much complex to handle | ||
35 | // that way, I think. | ||
36 | // By the way, SH1 is big endian, not little endian as PC is. | ||
37 | |||
38 | /////////////////////////////////////////////////////////////////////////////////// | ||
39 | // FSI SECTOR : | ||
40 | /////////////// | ||
41 | // | ||
42 | // | ||
43 | |||
44 | int __fat_get_fsi_sector_callback (struct __fat_fsi_sector *fsi_sector) | ||
45 | { | ||
46 | short *data = fsi_sector->data,*end; | ||
47 | union { unsigned long si[2]; unsigned short hi[4]; unsigned char qi[8]; } words; | ||
48 | for (end = fsi_sector->end0; data < end; ++data) | ||
49 | *data = ata_get_word (0); | ||
50 | #ifdef __little__ | ||
51 | words.hi[0] = ata_get_word (0); | ||
52 | words.hi[1] = ata_get_word (0); | ||
53 | words.hi[2] = ata_get_word (0); | ||
54 | words.hi[3] = ata_get_word (0); | ||
55 | #else | ||
56 | words.hi[1] = ata_get_word (0); | ||
57 | words.hi[0] = ata_get_word (0); | ||
58 | words.hi[3] = ata_get_word (0); | ||
59 | words.hi[2] = ata_get_word (0); | ||
60 | #endif | ||
61 | for (end = fsi_sector->end1; data < end; ++data) | ||
62 | *data = ata_get_word (0); | ||
63 | #ifdef __little__ | ||
64 | fsi_sector->left_free_clusters = words.si[0]; | ||
65 | fsi_sector->next_free_cluster = words.si[1]; | ||
66 | #else | ||
67 | fsi_sector->left_free_clusters = swawSI (words.si[0]); | ||
68 | fsi_sector->next_free_cluster = swawSI (words.si[1]); | ||
69 | #endif | ||
70 | return ATA_RETURN_SUCCESS; | ||
71 | } | ||
72 | |||
73 | int __fat_put_fsi_sector_callback (struct __fat_fsi_sector *fsi_sector) | ||
74 | { | ||
75 | short *data = fsi_sector->data,*end; | ||
76 | union { unsigned long si[2]; unsigned short hi[4]; unsigned char qi[8]; } words; | ||
77 | #ifdef __little__ | ||
78 | words.si[0] = swawSI (fsi_sector->left_free_clusters); | ||
79 | words.si[1] = swawSI (fsi_sector->next_free_cluster); | ||
80 | #else | ||
81 | words.si[0] = swawSI (fsi_sector->left_free_clusters); | ||
82 | words.si[1] = swawSI (fsi_sector->next_free_cluster); | ||
83 | #endif | ||
84 | for (end = fsi_sector->end0; data < end;) | ||
85 | ata_put_word (*data++); | ||
86 | #ifdef __little__ | ||
87 | ata_put_word (words.hi[0],0); | ||
88 | ata_put_word (words.hi[1],0); | ||
89 | ata_put_word (words.hi[2],0); | ||
90 | ata_put_word (words.hi[3],0); | ||
91 | #else | ||
92 | ata_put_word (words.hi[1],0); | ||
93 | ata_put_word (words.hi[0],0); | ||
94 | ata_put_word (words.hi[3],0); | ||
95 | ata_put_word (words.hi[2],0); | ||
96 | #endif | ||
97 | for (end = fsi_sector->end1; data < end;) | ||
98 | ata_put_word (*data++); | ||
99 | return ATA_RETURN_SUCCESS; | ||
100 | } | ||
101 | |||
102 | // | ||
103 | /////////////////////////////////////////////////////////////////////////////////// | ||
104 | |||
105 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef __LIBRARY_FAT_FSI_SECTOR_H__ | ||
20 | #define __LIBRARY_FAT_FSI_SECTOR_H__ | ||
21 | |||
22 | // [Alan]: | ||
23 | // I would like to draw your attention about the fact that SH1 | ||
24 | // cannot use misaligned address access so you must be very cautious | ||
25 | // with structures stored in FAT32 partition because they come from | ||
26 | // PC world where misaligned address accesses are usual and not | ||
27 | // problematic. To avoid such a trouble, I decide to use special | ||
28 | // structures where fields are moved in such a way they can be | ||
29 | // accessed by SH1. It is possible thanks to the callback mechanism | ||
30 | // I use for reading or writing from/to an ATA device in ata.h/c. | ||
31 | // So don't be puzzled if those structures seem odd compared | ||
32 | // with the usual ones from PC world. I use this mechanism for structures | ||
33 | // 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but | ||
34 | // not for structure 'bpb_sector' which is too much complex to handle | ||
35 | // that way, I think. | ||
36 | // By the way, SH1 is big endian, not little endian as PC is. | ||
37 | |||
38 | /////////////////////////////////////////////////////////////////////////////////// | ||
39 | // FSI SECTOR : | ||
40 | /////////////// | ||
41 | // | ||
42 | // | ||
43 | |||
44 | struct __fat_fsi_sector /* File System Info Sector */ | ||
45 | { | ||
46 | unsigned long | ||
47 | left_free_clusters; | ||
48 | unsigned long | ||
49 | next_free_cluster; | ||
50 | short | ||
51 | data[0]; | ||
52 | long /* 0x61415252 - aARR */ | ||
53 | fsi_signature0; | ||
54 | char | ||
55 | reserved0[480]; | ||
56 | long /* 0x41617272 - Aarr */ | ||
57 | fsi_signature1; | ||
58 | short | ||
59 | end0[0]; | ||
60 | char | ||
61 | reserved1[12]; | ||
62 | long /* 0x000055AA */ | ||
63 | signature; | ||
64 | short | ||
65 | end1[0]; | ||
66 | }; | ||
67 | |||
68 | int __fat_get_fsi_sector_callback (struct __fat_fsi_sector *fsi_sector); | ||
69 | int __fat_put_fsi_sector_callback (struct __fat_fsi_sector *fsi_sector); | ||
70 | |||
71 | static inline int __fat_get_fsi_sector (unsigned long partition_start,unsigned long lba,struct __fat_fsi_sector *fsi_sector) | ||
72 | { return ata_read_sectors (partition_start + lba,1,fsi_sector,(int(*)(void *))get_fsi_sector_callback); } | ||
73 | |||
74 | static inline int __fat_put_fsi_sector (unsigned long partition_start,unsigned long lba,struct __fat_fsi_sector *fsi_sector) | ||
75 | { return ata_write_sectors (partition_start + lba,1,fsi_sector,(int(*)(void *))put_fsi_sector_callback); } | ||
76 | |||
77 | // | ||
78 | /////////////////////////////////////////////////////////////////////////////////// | ||
79 | |||
80 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <fat.h> | ||
20 | #include "fat-mbr_sector.h" | ||
21 | |||
22 | // [Alan]: | ||
23 | // I would like to draw your attention about the fact that SH1 | ||
24 | // cannot use misaligned address access so you must be very cautious | ||
25 | // with structures stored in FAT32 partition because they come from | ||
26 | // PC world where misaligned address accesses are usual and not | ||
27 | // problematic. To avoid such a trouble, I decide to use special | ||
28 | // structures where fields are moved in such a way they can be | ||
29 | // accessed by SH1. It is possible thanks to the callback mechanism | ||
30 | // I use for reading or writing from/to an ATA device in ata.h/c. | ||
31 | // So don't be puzzled if those structures seem odd compared | ||
32 | // with the usual ones from PC world. I use this mechanism for structures | ||
33 | // 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but | ||
34 | // not for structure 'bpb_sector' which is too much complex to handle | ||
35 | // that way, I think. | ||
36 | // By the way, SH1 is big endian, not little endian as PC is. | ||
37 | |||
38 | /////////////////////////////////////////////////////////////////////////////////// | ||
39 | // MBR SECTOR : | ||
40 | /////////////// | ||
41 | // | ||
42 | // | ||
43 | |||
44 | int __fat_get_mbr_sector_callback (struct __fat_mbr_sector *mbr_sector) | ||
45 | { | ||
46 | short *data = mbr_sector->data,*end; | ||
47 | for (end = mbr_sector->end; data < end; ++data) | ||
48 | *data = ata_get_word (0); | ||
49 | __fat_get_partition_table (mbr_sector->partition_table); | ||
50 | mbr_sector->signature = HI(ATAR_DATA); | ||
51 | return FAT_RETURN_SUCCESS; | ||
52 | } | ||
53 | |||
54 | int __fat_put_mbr_sector_callback (struct __fat_mbr_sector *mbr_sector) | ||
55 | { | ||
56 | short const *data = mbr_sector->data,*end; | ||
57 | for (end = mbr_sector->end; data < end;) | ||
58 | HI(ATAR_DATA) = *data++; | ||
59 | __fat_put_partition_table (mbr_sector->partition_table); | ||
60 | ata_put_word (mbr_sector->signature,0); | ||
61 | return FAT_RETURN_SUCCESS; | ||
62 | } | ||
63 | |||
64 | // | ||
65 | /////////////////////////////////////////////////////////////////////////////////// | ||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef __LIBRARY_FAT_MBR_SECTOR_H__ | ||
20 | #define __LIBRARY_FAT_MBR_SECTOR_H__ | ||
21 | #include "fat-partition.h" | ||
22 | |||
23 | // [Alan]: | ||
24 | // I would like to draw your attention about the fact that SH1 | ||
25 | // cannot use misaligned address access so you must be very cautious | ||
26 | // with structures stored in FAT32 partition because they come from | ||
27 | // PC world where misaligned address accesses are usual and not | ||
28 | // problematic. To avoid such a trouble, I decide to use special | ||
29 | // structures where fields are moved in such a way they can be | ||
30 | // accessed by SH1. It is possible thanks to the callback mechanism | ||
31 | // I use for reading or writing from/to an ATA device in ata.h/c. | ||
32 | // So don't be puzzled if those structures seem odd compared | ||
33 | // with the usual ones from PC world. I use this mechanism for structures | ||
34 | // 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but | ||
35 | // not for structure 'bpb_sector' which is too much complex to handle | ||
36 | // that way, I think. | ||
37 | // By the way, SH1 is big endian, not little endian as PC is. | ||
38 | |||
39 | /////////////////////////////////////////////////////////////////////////////////// | ||
40 | // MBR SECTOR : | ||
41 | /////////////// | ||
42 | // | ||
43 | // | ||
44 | |||
45 | struct __fat_mbr_sector /* Master Boot Record Sector */ | ||
46 | { | ||
47 | struct | ||
48 | __fat_partition_info partition_table[4]; | ||
49 | short | ||
50 | data[0x1BE/2]; | ||
51 | short | ||
52 | end[0]; | ||
53 | short | ||
54 | signature; | ||
55 | }; | ||
56 | |||
57 | int __fat_get_mbr_sector_callback (struct __fat_mbr_sector *mbr_sector); | ||
58 | int __fat_put_mbr_sector_callback (struct __fat_mbr_sector *mbr_sector); | ||
59 | |||
60 | static inline int __fat_get_mbr_sector (struct mbr_sector *__fat_mbr_sector) | ||
61 | { return ata_read_sectors (0,1,mbr_sector,(int(*)(void *))__fat_get_mbr_sector_callback); } | ||
62 | |||
63 | static inline int __fat_put_mbr_sector (struct mbr_sector *__fat_mbr_sector) | ||
64 | { return ata_write_sectors (0,1,mbr_sector,(int(*)(void *))__fat_put_mbr_sector_callback); } | ||
65 | |||
66 | // | ||
67 | /////////////////////////////////////////////////////////////////////////////////// | ||
68 | |||
69 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef __LIBRARY_FAT_PARTITION_H__ | ||
20 | #define __LIBRARY_FAT_PARTITION_H__ | ||
21 | #include <ata/ata.h> | ||
22 | |||
23 | // [Alan]: | ||
24 | // I would like to draw your attention about the fact that SH1 | ||
25 | // cannot use misaligned address access so you must be very cautious | ||
26 | // with structures stored in FAT32 partition because they come from | ||
27 | // PC world where misaligned address accesses are usual and not | ||
28 | // problematic. To avoid such a trouble, I decide to use special | ||
29 | // structures where fields are moved in such a way they can be | ||
30 | // accessed by SH1. It is possible thanks to the callback mechanism | ||
31 | // I use for reading or writing from/to an ATA device in ata.h/c. | ||
32 | // So don't be puzzled if those structures seem odd compared | ||
33 | // with the usual ones from PC world. I use this mechanism for structures | ||
34 | // 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but | ||
35 | // not for structure 'bpb_sector' which is too much complex to handle | ||
36 | // that way, I think. | ||
37 | // By the way, SH1 is big endian, not little endian as PC is. | ||
38 | |||
39 | /////////////////////////////////////////////////////////////////////////////////// | ||
40 | // PARTITION INFO : | ||
41 | /////////////////// | ||
42 | // | ||
43 | // | ||
44 | |||
45 | struct __fat_partition_info | ||
46 | { | ||
47 | // Absolute start sector in this partition : | ||
48 | // start = start_cylinder * heads * sectors + start_head * sectors + start_sector - 1 | ||
49 | unsigned long | ||
50 | start; | ||
51 | |||
52 | // Number of sectors in this partition : | ||
53 | // sectors = end_cylinder * heads * sectors + end_head * sectors + end_sector - start_sector | ||
54 | unsigned long | ||
55 | sectors; | ||
56 | |||
57 | // File system type. | ||
58 | // Must be a FAT32 file system type (0x0B or 0x0C) | ||
59 | // for Rockbox. | ||
60 | char | ||
61 | filesystem_type; | ||
62 | |||
63 | // Is this partition bootable ? | ||
64 | // Not used by Rockbox. | ||
65 | char | ||
66 | bootable; | ||
67 | |||
68 | // Not used by Rockbox. | ||
69 | unsigned char | ||
70 | start_head; | ||
71 | |||
72 | // Not used by Rockbox. | ||
73 | unsigned char | ||
74 | start_cylinder; | ||
75 | |||
76 | // Not used by Rockbox. | ||
77 | unsigned char | ||
78 | start_sector; | ||
79 | |||
80 | // Not used by Rockbox. | ||
81 | unsigned char | ||
82 | end_head; | ||
83 | |||
84 | // Not used by Rockbox. | ||
85 | unsigned char | ||
86 | end_cylinder; | ||
87 | |||
88 | // Not used by Rockbox. | ||
89 | unsigned char | ||
90 | end_sector; | ||
91 | }; | ||
92 | |||
93 | |||
94 | // load partition info into memory | ||
95 | static inline void __fat_get_partition_info (struct partition_info *__fat_partition_info) | ||
96 | { | ||
97 | // | ||
98 | union { unsigned long si[4]; unsigned short hi[8]; unsigned char qi[16]; } words; | ||
99 | short *data = words.hi,*end; | ||
100 | for (end = data + 8; data < end; ++data) | ||
101 | *data = HI(ATAR_DATA); | ||
102 | partition_info->start = swawSI(words.si[2]); | ||
103 | partition_info->sectors = swawSI(words.si[3]); | ||
104 | partition_info->bootable = words.qi[1]; | ||
105 | partition_info->filesystem_type = words.qi[5]; | ||
106 | partition_info->start_head = words.qi[0]; | ||
107 | partition_info->start_cylinder = words.qi[3]; | ||
108 | partition_info->start_sector = words.qi[2]; | ||
109 | partition_info->end_head = words.qi[4]; | ||
110 | partition_info->end_cylinder = words.qi[7]; | ||
111 | partition_info->end_sector = words.qi[6]; | ||
112 | } | ||
113 | |||
114 | // store partition info into harddisk | ||
115 | static inline void __fat_put_partition_info (struct partition_info *__fat_partition_info) | ||
116 | { | ||
117 | union { unsigned long si[4]; short hi[8]; unsigned char qi[16]; } words; | ||
118 | short *data = words.hi,*end; | ||
119 | words.si[2] = swawSI(partition_info->start); | ||
120 | words.si[3] = swawSI(partition_info->sectors); | ||
121 | words.qi[1] = partition_info->bootable; | ||
122 | words.qi[5] = partition_info->filesystem_type; | ||
123 | words.qi[0] = partition_info->start_head; | ||
124 | words.qi[3] = partition_info->start_cylinder; | ||
125 | words.qi[2] = partition_info->start_sector; | ||
126 | words.qi[4] = partition_info->end_head; | ||
127 | words.qi[7] = partition_info->end_cylinder; | ||
128 | words.qi[6] = partition_info->end_sector; | ||
129 | for (end = data + 8; data < end;) | ||
130 | HI(ATAR_DATA) = *data++; | ||
131 | } | ||
132 | |||
133 | // | ||
134 | /////////////////////////////////////////////////////////////////////////////////// | ||
135 | |||
136 | /////////////////////////////////////////////////////////////////////////////////// | ||
137 | // PARTITION TABLE : | ||
138 | //////////////////// | ||
139 | // | ||
140 | // | ||
141 | |||
142 | // load the partition table from a mbr sector | ||
143 | static inline void __fat_get_partition_table (struct partition_info table[4]) | ||
144 | { | ||
145 | struct partition_info *last; | ||
146 | for (last = table + 4; table < last;) | ||
147 | __fat_get_partition_info (table++); | ||
148 | } | ||
149 | |||
150 | // store the partition table into a mbr sector | ||
151 | static inline void __fat_put_partition_table (struct partition_info const table[4]) | ||
152 | { | ||
153 | struct partition_info const *last; | ||
154 | for (last = table + 4; table < last;) | ||
155 | __fat_put_partition_info (table++); | ||
156 | } | ||
157 | |||
158 | // | ||
159 | /////////////////////////////////////////////////////////////////////////////////// | ||
160 | |||
161 | #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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: | ||
9 | * | ||
10 | * Copyright (C) 2002 by Alan Korr | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #define __LIBRARY_FAT_VOLUME_C__ | ||
20 | |||
21 | #include <fat.h> | ||
22 | #include "fat-mbr_sector.h" | ||
23 | #include "fat-bpb_sector.h" | ||
24 | #include "fat-fsi_sector.h" | ||
25 | |||
26 | /////////////////////////////////////////////////////////////////////////////////// | ||
27 | // FAT VOLUME : | ||
28 | /////////////// | ||
29 | // | ||
30 | // | ||
31 | |||
32 | // check fsi sector integrity | ||
33 | static int __fat_check_fsi_sector (struct fat_volume *volume,struct __fat_fsi_sector *fsi_sector,unsigned long lba) | ||
34 | { | ||
35 | int error; | ||
36 | if (!lba) | ||
37 | // no FSI sector | ||
38 | { | ||
39 | volume->next_free_cluster = 2; | ||
40 | return FAT_RETURN_SUCCESS; | ||
41 | } | ||
42 | if ((error = __fat_get_fsi_sector (volume->partition_start,lba,fsi_sector)) > 0) | ||
43 | { | ||
44 | if ((fsi_sector->signature != 0x0000AA55) || | ||
45 | (fsi_sector->fsi_signature0 != 0x52524161) || | ||
46 | (fsi_sector->fsi_signature1 != 0x72726141)) | ||
47 | { | ||
48 | return FAT_RETURN_BAD_FSI; | ||
49 | } | ||
50 | if (fsi_sector->left_free_clusters == -1) | ||
51 | fsi_sector->next_free_cluster = 2; | ||
52 | else if (fsi_sector->next_free_cluster >= volume->sectors_per_fat) | ||
53 | return FAT_RETURN_BAD_FSI; | ||
54 | volume->next_free_cluster = fsi_sector->next_free_cluster; | ||
55 | fsi_sector->left_free_clusters = -1; | ||
56 | fsi_sector->next_free_cluster = 2; | ||
57 | error = __fat_put_fsi_sector (volume->partition_start,lba,fsi_sector))); | ||
58 | } | ||
59 | return error; | ||
60 | } | ||
61 | |||
62 | static inline int bit_in_range (int value,int min,int max) | ||
63 | { | ||
64 | for (;min < max; min <<= 1) | ||
65 | if (value == min) | ||
66 | return 1; | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | // check bpb sector integrity | ||
71 | static int __fat_check_bpb_sector (struct fat_volume *volume,struct __fat_bpb_sector *bpb_sector,struct __fat_fsi_sector *fsi_sector) | ||
72 | { | ||
73 | long unsigned bpb_lba = 0,fsi_lba; | ||
74 | long unsigned sectors_per_cluster,sectors_per_fat,sectors,reserved_sectors,total_sectors; | ||
75 | long unsigned first_cluster_of_root,first_sector_of_fat,first_sector_of_data; | ||
76 | long unsigned clusters_per_fat,bytes_per_sector; | ||
77 | int error,backup; | ||
78 | for (backup = 0; !backup ; backup = 1) | ||
79 | { | ||
80 | if ((error = __fat_get_bpb_sector (volume->partition_start,bpb_lba,bpb_sector)) > 0) | ||
81 | { | ||
82 | bytes_per_sector = peekHI (bpb_sector->bytes_per_sector ); | ||
83 | sectors_per_cluster = peekQI (bpb_sector->sectors_per_cluster); | ||
84 | sectors_per_fat = peekSI (bpb_sector->sectors_per_fat ); | ||
85 | sectors = peekQI (bpb_sector->number_of_fats ) * sectors_per_fat; | ||
86 | reserved_sectors = peekHI (bpb_sector->reserved_sectors ); | ||
87 | total_sectors = peekSI (bpb_sector->total_sectors ); | ||
88 | first_cluster_of_root = peekSI (bpb_sector->root_cluster ); | ||
89 | first_sector_of_fat = reserved_sectors + volume->partition_start; | ||
90 | first_sector_of_data = first_sector_of_fat + sectors; | ||
91 | clusters_per_fat = (total_sectors - first_sector_of_data) / sectors_per_cluster; | ||
92 | |||
93 | if (!bpb_lba) | ||
94 | { | ||
95 | bpb_lba = peekHI(bpb_sector->backup_bpb); | ||
96 | if (bpb_lba == -1) | ||
97 | bpb_lba = 0; | ||
98 | } | ||
99 | |||
100 | if ((bpb_lba >= reserved_sectors) || | ||
101 | (bpb_sector->signature != 0x000055AA) || | ||
102 | (clusters_per_fat < 65525) || | ||
103 | (bytes_per_sector != 512) || | ||
104 | (!bit_in_range (sectors_per_cluster,1,128)) || | ||
105 | (bytes_per_sector * sectors_per_cluster >= 32 KB) || | ||
106 | (peekHI (bpb_sector->total_sectors_16)) || | ||
107 | (peekHI (bpb_sector->sectors_per_fat_16)) || | ||
108 | (peekHI (bpb_sector->number_of_root_entries)) || | ||
109 | ((bpb_sector->media[0] != 0xF0) && (bpb_sector->media[0] < 0xF8))) | ||
110 | { | ||
111 | error = FAT_RETURN_BAD_BPB; | ||
112 | if (bpb_lba) // try with backup BPB sector ? | ||
113 | continue; | ||
114 | return error; | ||
115 | } | ||
116 | if ((signed char)bpb_sector->flags[0] >= 0) | ||
117 | { | ||
118 | bpb_sector->flags[0] = 0x80; | ||
119 | if (!backup && (error = __fat_put_bpb_sector (volume->partition_start,0,bpb_sector)) <= 0) | ||
120 | return error; | ||
121 | if ((error = __fat_put_bpb_sector (volume->partition_start,bpb_lba,bpb_sector)) <= 0) | ||
122 | return error; | ||
123 | } | ||
124 | |||
125 | volume->sectors_per_cluster = sectors_per_cluster; | ||
126 | volume->sectors_per_fat = sectors_per_fat; | ||
127 | volume->first_cluster_of_root = first_cluster_of_root; | ||
128 | volume->first_sector_of_fat = first_sector_of_fat; | ||
129 | volume->first_sector_of_data = first_sector_of_data; | ||
130 | volume->clusters_per_fat = clusters_per_fat; | ||
131 | |||
132 | fsi_lba = ((long)peekHI(bpb_sector->filesystem_info)); | ||
133 | if (fsi_lba == -1) | ||
134 | fsi_lba = 0; | ||
135 | else if (fsi_lba >= reserved_sectors) | ||
136 | { | ||
137 | error = FAT_RETURN_BAD_FSI; | ||
138 | if (bpb_lba) // try with backup BPB sector ? | ||
139 | continue; | ||
140 | return error; | ||
141 | } | ||
142 | |||
143 | if (((error = __fat_check_fsi_sector (volume,fsi_sector,fsi_lba + (backup ? 0 : bpb_lba))) <= 0) && bpb_lba) | ||
144 | continue; | ||
145 | |||
146 | if (backup) | ||
147 | { | ||
148 | error = __fat_put_bpb_sector (volume,0,bpb_sector)) <= 0); | ||
149 | if (!error) | ||
150 | error = __fat_put_fsi_sector (volume,fsi_lba,fsi_sector)) <= 0); | ||
151 | } | ||
152 | |||
153 | break; | ||
154 | } | ||
155 | } | ||
156 | return error; | ||
157 | } | ||
158 | |||
159 | static inline int __fat_compare_volume_name (char const *name,struct fat_volume *volume) | ||
160 | { | ||
161 | return !name ? -1 : strncpy (name,volume->name,11); | ||
162 | } | ||
163 | |||
164 | static struct fat_volume *__fat_splay_volume (struct fat_volume *root,char const *name) | ||
165 | { | ||
166 | struct fat_volume *down; | ||
167 | struct fat_volume *less; | ||
168 | struct fat_volume *more; | ||
169 | struct fat_volume *head[2]; | ||
170 | ((struct fat_volume *)head)->less = | ||
171 | ((struct fat_volume *)head)->more = 0; | ||
172 | less = | ||
173 | more = head; | ||
174 | while (1) | ||
175 | { | ||
176 | int sign = __fat_compare_volume_name (name,root); | ||
177 | if (sign < 0) | ||
178 | { | ||
179 | if ((down = root->less)) | ||
180 | { | ||
181 | sign = __fat_compare_volume_name (name,down); | ||
182 | if (sign < 0) | ||
183 | { | ||
184 | root->less = down->more; | ||
185 | down->more = root; | ||
186 | root = down; | ||
187 | if (!root->less) | ||
188 | break; | ||
189 | } | ||
190 | more->less = root; | ||
191 | more = root; | ||
192 | root = root->less; | ||
193 | continue; | ||
194 | } | ||
195 | break; | ||
196 | } | ||
197 | if (0 < sign) | ||
198 | { | ||
199 | if ((down = root->more)) | ||
200 | { | ||
201 | sign = __fat_compare_volume_name (name,down); | ||
202 | if (0 < sign) | ||
203 | { | ||
204 | root->more = down->less; | ||
205 | down->less = root; | ||
206 | root = down; | ||
207 | if (!root->more) | ||
208 | break; | ||
209 | } | ||
210 | less->more = root; | ||
211 | less = root; | ||
212 | root = root->more; | ||
213 | continue; | ||
214 | } | ||
215 | } | ||
216 | break; | ||
217 | } | ||
218 | less->more = root->less; | ||
219 | more->less = root->more; | ||
220 | root->less = ((struct fat_volume *)head)->more; | ||
221 | root->more = ((struct fat_volume *)head)->less; | ||
222 | return root; | ||
223 | } | ||
224 | |||
225 | static inline struct fat_volume *__fat_insert_volume (struct fat_volume *root,struct fat_volume *node) | ||
226 | { | ||
227 | if (!root) | ||
228 | { | ||
229 | node->less = | ||
230 | node->more = 0; | ||
231 | } | ||
232 | else if (node < (root = __fat_splay_volume (root,node->name))) | ||
233 | { | ||
234 | node->less = root->less; | ||
235 | node->more = root; | ||
236 | root->less = 0; | ||
237 | } | ||
238 | else if | ||
239 | { | ||
240 | node->less = root; | ||
241 | node->more = root->more; | ||
242 | node->more = 0; | ||
243 | } | ||
244 | return node; | ||
245 | } | ||
246 | |||
247 | #if 0 | ||
248 | static inline struct fat_volume *__fat_remove_volume (struct fat_volume *root,struct memory_free_page *node) | ||
249 | { | ||
250 | root = __fat_splay_volume (root,node->name); | ||
251 | if (root->less) | ||
252 | { | ||
253 | node = __fat_splay_volume (root->less,node->name); | ||
254 | node->more = root->more; | ||
255 | } | ||
256 | else | ||
257 | node = root->more; | ||
258 | return node; | ||
259 | } | ||
260 | #endif | ||
261 | |||
262 | static inline struct fat_volume *__fat_lookup_volume (struct fat_volume *root,char const *name) | ||
263 | { | ||
264 | return __fat_splay_volume (root,0); | ||
265 | } | ||
266 | |||
267 | static struct fat_volume *__fat_first_volume (struct fat_volume *root) | ||
268 | { | ||
269 | struct fat_volume *down; | ||
270 | struct fat_volume *less; | ||
271 | struct fat_volume *more; | ||
272 | struct fat_volume *head[2]; | ||
273 | ((struct fat_volume *)head)->less = | ||
274 | ((struct fat_volume *)head)->more = 0; | ||
275 | less = | ||
276 | more = &head; | ||
277 | if (root) | ||
278 | while (1) | ||
279 | { | ||
280 | if ((down = root->less)) | ||
281 | { | ||
282 | root->less = down->more; | ||
283 | down->more = root; | ||
284 | root = down; | ||
285 | if (!root->less) | ||
286 | break; | ||
287 | more->less = root; | ||
288 | more = root; | ||
289 | root = root->less; | ||
290 | continue; | ||
291 | } | ||
292 | break; | ||
293 | } | ||
294 | less->more = root->less; | ||
295 | more->less = root->more; | ||
296 | root->less = ((struct fat_volume *)head)->more; | ||
297 | root->more = ((struct fat_volume *)head)->less; | ||
298 | return root; | ||
299 | } | ||
300 | |||
301 | static inline struct fat_volume *__fat_scan_volume (struct fat_volume *root,int next) | ||
302 | { | ||
303 | return __fat_first_volume (next ? root->more : root,0); | ||
304 | } | ||
305 | |||
306 | static int __fat_build_volume_tree (struct fat_volume *root) | ||
307 | { | ||
308 | struct fat_volume *volume; | ||
309 | int number = 4; | ||
310 | struct __fat_partition_info *partition_info; | ||
311 | struct __fat_mbr_sector mbr_sector; | ||
312 | struct __fat_bpb_sector bpb_sector; | ||
313 | struct __fat_fsi_sector fsi_sector; | ||
314 | if (__fat_get_mbr_sector (&mbr_sector) <= 0) | ||
315 | return 0; | ||
316 | partition_info = mbr_sector.partition_table; | ||
317 | for (;number-- > 0; ++partition_info) | ||
318 | { | ||
319 | switch (partition_info->filesystem_type) | ||
320 | { | ||
321 | case 0x05: // extended partition - handle it as well | ||
322 | { | ||
323 | if (!__fat_build_volume_list (list)) | ||
324 | return 0; | ||
325 | break; | ||
326 | } | ||
327 | case 0x0B: // FAT32 partitions | ||
328 | case 0x0C: | ||
329 | { | ||
330 | if (!(volume = memory_allocate_page (0))) | ||
331 | return 0; | ||
332 | volume->next = 0; | ||
333 | volume->partition_start = partition_info->start; | ||
334 | volume->partition_sectors = partition_info->sectors; | ||
335 | if (__fat_check_bpb_sector (volume,&mbr_sector,&fsi_sector) > 0) | ||
336 | { | ||
337 | dump_volume (volume); | ||
338 | *root = volume; | ||
339 | list = &volume->next; | ||
340 | break; | ||
341 | } | ||
342 | else | ||
343 | memory_release_page (volume,0); | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | return 1; | ||
348 | } | ||
349 | |||
350 | static struct fat_volume *__fat_volume_root; | ||
351 | |||
352 | void fat_setup (void) | ||
353 | { | ||
354 | //build_volume_list (&root); | ||
355 | } | ||
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 @@ | |||
23 | #define __LIBRARY_FAT_INLINES_H__ | 23 | #define __LIBRARY_FAT_INLINES_H__ |
24 | 24 | ||
25 | 25 | ||
26 | |||
26 | #endif \ No newline at end of file | 27 | #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 @@ | |||
1 | ############################################################################# | 1 | ############################################################################## |
2 | ## __________ __ ___. | 2 | ## __________ __ ___. |
3 | ## Open \______ \ ____ ____ | | _\_ |__ _______ ___ | 3 | ## Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
4 | ## Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | 4 | ## Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
5 | ## Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | 5 | ## Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
6 | ## Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | 6 | ## Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
7 | ## \/ \/ \/ \/ \/ | 7 | ## \/ \/ \/ \/ \/ |
8 | ## Copyright Alan Korr, 2002. All rights reserved. | 8 | ## $Id: |
9 | ## | 9 | ## |
10 | ## Permission to use, copy, modify, and distribute this software for any | 10 | ## Copyright (C) 2002 by Alan Korr |
11 | ## purpose is hereby granted without fee, provided that this copyright and | ||
12 | ## permissions notice appear in all copies and derivatives, and that no | ||
13 | ## charge may be made for the software and its documentation except to cover | ||
14 | ## cost of distribution. | ||
15 | ## | 11 | ## |
16 | ## This software is provided "as is" without express or implied warranty. | 12 | ## All files in this archive are subject to the GNU General Public License. |
17 | ############################################################################# | 13 | ## See the file COPYING in the source tree root for full license agreement. |
14 | ## | ||
15 | ## This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | ## KIND, either express or implied. | ||
17 | ## | ||
18 | ############################################################################## | ||
18 | ARCH = test | 19 | ARCH = test |
19 | PACKAGE = fat | 20 | PACKAGE = fat |
20 | VERSION = 0.0.0 | 21 | 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 @@ | |||
21 | #endif | 21 | #endif |
22 | #ifndef __LIBRARY_FAT_RETURN_VALUES_H__ | 22 | #ifndef __LIBRARY_FAT_RETURN_VALUES_H__ |
23 | # define __LIBRARY_FAT_RETURN_VALUES_H__ | 23 | # define __LIBRARY_FAT_RETURN_VALUES_H__ |
24 | |||
25 | enum | ||
26 | { | ||
27 | FAT_RETURN_SUCCESS = 1, | ||
28 | FAT_RETURN_FAILURE = 0 | ||
29 | }; | ||
30 | |||
24 | #endif \ No newline at end of file | 31 | #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 @@ | |||
21 | #endif | 21 | #endif |
22 | #ifndef __LIBRARY_FAT_TYPES_H__ | 22 | #ifndef __LIBRARY_FAT_TYPES_H__ |
23 | # define __LIBRARY_FAT_TYPES_H__ | 23 | # define __LIBRARY_FAT_TYPES_H__ |
24 | |||
25 | // [Alan]: | ||
26 | // I would like to draw your attention about the fact that SH1 | ||
27 | // cannot use misaligned address access so you must be very cautious | ||
28 | // with structures stored in FAT32 partition because they come from | ||
29 | // PC world where misaligned address accesses are usual and not | ||
30 | // problematic. To avoid such a trouble, I decide to use special | ||
31 | // structures where fields are moved in such a way they can be | ||
32 | // accessed by SH1. It is possible thanks to the callback mechanism | ||
33 | // I use for reading or writing from/to an ATA device in ata.h/c. | ||
34 | // So don't be puzzled if those structures seem odd compared | ||
35 | // with the usual ones from PC world. I use this mechanism for structures | ||
36 | // 'partition_info', 'mbr_sector' and 'fsi_sector' for instance, but | ||
37 | // not for structure 'bpb_sector' which is too much complex to handle | ||
38 | // that way, I think. | ||
39 | // By the way, SH1 is big endian, not little endian as PC is. | ||
40 | |||
41 | |||
42 | |||
24 | #endif \ No newline at end of file | 43 | #endif \ No newline at end of file |