diff options
author | Alan Korr <alkorr@rockbox.org> | 2002-04-19 12:16:19 +0000 |
---|---|---|
committer | Alan Korr <alkorr@rockbox.org> | 2002-04-19 12:16:19 +0000 |
commit | 6dd637f44c0523958012f3c28068c631a73b0569 (patch) | |
tree | 73f926f81d05617869da14a40f9613909e7f2dee /firmware/test/fat/fat-volume.c | |
parent | b41596560eed4f805d19931eec3d37b3bad06e61 (diff) | |
download | rockbox-6dd637f44c0523958012f3c28068c631a73b0569.tar.gz rockbox-6dd637f44c0523958012f3c28068c631a73b0569.zip |
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
Diffstat (limited to 'firmware/test/fat/fat-volume.c')
-rw-r--r-- | firmware/test/fat/fat-volume.c | 355 |
1 files changed, 355 insertions, 0 deletions
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 | } | ||