]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Plugson/src/Lib/fat_io_lib/fat_table.c
1.1.07 release
[Ventoy.git] / Plugson / src / Lib / fat_io_lib / fat_table.c
1 //-----------------------------------------------------------------------------
2 //-----------------------------------------------------------------------------
3 // FAT16/32 File IO Library
4 // V2.6
5 // Ultra-Embedded.com
6 // Copyright 2003 - 2012
7 //
8 // Email: admin@ultra-embedded.com
9 //
10 // License: GPL
11 // If you would like a version with a more permissive license for use in
12 // closed source commercial applications please contact me for details.
13 //-----------------------------------------------------------------------------
14 //
15 // This file is part of FAT File IO Library.
16 //
17 // FAT File IO Library is free software; you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation; either version 2 of the License, or
20 // (at your option) any later version.
21 //
22 // FAT File IO Library is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 // GNU General Public License for more details.
26 //
27 // You should have received a copy of the GNU General Public License
28 // along with FAT File IO Library; if not, write to the Free Software
29 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 //-----------------------------------------------------------------------------
31 //-----------------------------------------------------------------------------
32 #include <string.h>
33 #include "fat_defs.h"
34 #include "fat_access.h"
35 #include "fat_table.h"
36
37 #ifndef FAT_BUFFERS
38 #define FAT_BUFFERS 1
39 #endif
40
41 #ifndef FAT_BUFFER_SECTORS
42 #define FAT_BUFFER_SECTORS 1
43 #endif
44
45 #if FAT_BUFFERS < 1 || FAT_BUFFER_SECTORS < 1
46 #error "FAT_BUFFERS & FAT_BUFFER_SECTORS must be at least 1"
47 #endif
48
49 //-----------------------------------------------------------------------------
50 // FAT Sector Buffer
51 //-----------------------------------------------------------------------------
52 #define FAT32_GET_32BIT_WORD(pbuf, location) ( GET_32BIT_WORD(pbuf->ptr, location) )
53 #define FAT32_SET_32BIT_WORD(pbuf, location, value) { SET_32BIT_WORD(pbuf->ptr, location, value); pbuf->dirty = 1; }
54 #define FAT16_GET_16BIT_WORD(pbuf, location) ( GET_16BIT_WORD(pbuf->ptr, location) )
55 #define FAT16_SET_16BIT_WORD(pbuf, location, value) { SET_16BIT_WORD(pbuf->ptr, location, value); pbuf->dirty = 1; }
56
57 //-----------------------------------------------------------------------------
58 // fatfs_fat_init:
59 //-----------------------------------------------------------------------------
60 void fatfs_fat_init(struct fatfs *fs)
61 {
62 int i;
63
64 // FAT buffer chain head
65 fs->fat_buffer_head = NULL;
66
67 for (i=0;i<FAT_BUFFERS;i++)
68 {
69 // Initialise buffers to invalid
70 fs->fat_buffers[i].address = FAT32_INVALID_CLUSTER;
71 fs->fat_buffers[i].dirty = 0;
72 memset(fs->fat_buffers[i].sector, 0x00, sizeof(fs->fat_buffers[i].sector));
73 fs->fat_buffers[i].ptr = NULL;
74
75 // Add to head of queue
76 fs->fat_buffers[i].next = fs->fat_buffer_head;
77 fs->fat_buffer_head = &fs->fat_buffers[i];
78 }
79 }
80 //-----------------------------------------------------------------------------
81 // fatfs_fat_writeback: Writeback 'dirty' FAT sectors to disk
82 //-----------------------------------------------------------------------------
83 static int fatfs_fat_writeback(struct fatfs *fs, struct fat_buffer *pcur)
84 {
85 if (pcur)
86 {
87 // Writeback sector if changed
88 if (pcur->dirty)
89 {
90 if (fs->disk_io.write_media)
91 {
92 uint32 sectors = FAT_BUFFER_SECTORS;
93 uint32 offset = pcur->address - fs->fat_begin_lba;
94
95 // Limit to sectors used for the FAT
96 if ((offset + FAT_BUFFER_SECTORS) <= fs->fat_sectors)
97 sectors = FAT_BUFFER_SECTORS;
98 else
99 sectors = fs->fat_sectors - offset;
100
101 if (!fs->disk_io.write_media(pcur->address, pcur->sector, sectors))
102 return 0;
103 }
104
105 pcur->dirty = 0;
106 }
107
108 return 1;
109 }
110 else
111 return 0;
112 }
113 //-----------------------------------------------------------------------------
114 // fatfs_fat_read_sector: Read a FAT sector
115 //-----------------------------------------------------------------------------
116 static struct fat_buffer *fatfs_fat_read_sector(struct fatfs *fs, uint32 sector)
117 {
118 struct fat_buffer *last = NULL;
119 struct fat_buffer *pcur = fs->fat_buffer_head;
120
121 // Itterate through sector buffer list
122 while (pcur)
123 {
124 // Sector within this buffer?
125 if ((sector >= pcur->address) && (sector < (pcur->address + FAT_BUFFER_SECTORS)))
126 break;
127
128 // End of list?
129 if (pcur->next == NULL)
130 {
131 // Remove buffer from list
132 if (last)
133 last->next = NULL;
134 // We the first and last buffer in the chain?
135 else
136 fs->fat_buffer_head = NULL;
137 }
138
139 last = pcur;
140 pcur = pcur->next;
141 }
142
143 // We found the sector already in FAT buffer chain
144 if (pcur)
145 {
146 pcur->ptr = (uint8 *)(pcur->sector + ((sector - pcur->address) * FAT_SECTOR_SIZE));
147 return pcur;
148 }
149
150 // Else, we removed the last item from the list
151 pcur = last;
152
153 // Add to start of sector buffer list (now newest sector)
154 pcur->next = fs->fat_buffer_head;
155 fs->fat_buffer_head = pcur;
156
157 // Writeback sector if changed
158 if (pcur->dirty)
159 if (!fatfs_fat_writeback(fs, pcur))
160 return 0;
161
162 // Address is now new sector
163 pcur->address = sector;
164
165 // Read next sector
166 if (!fs->disk_io.read_media(pcur->address, pcur->sector, FAT_BUFFER_SECTORS))
167 {
168 // Read failed, invalidate buffer address
169 pcur->address = FAT32_INVALID_CLUSTER;
170 return NULL;
171 }
172
173 pcur->ptr = pcur->sector;
174 return pcur;
175 }
176 //-----------------------------------------------------------------------------
177 // fatfs_fat_purge: Purge 'dirty' FAT sectors to disk
178 //-----------------------------------------------------------------------------
179 int fatfs_fat_purge(struct fatfs *fs)
180 {
181 struct fat_buffer *pcur = fs->fat_buffer_head;
182
183 // Itterate through sector buffer list
184 while (pcur)
185 {
186 // Writeback sector if changed
187 if (pcur->dirty)
188 if (!fatfs_fat_writeback(fs, pcur))
189 return 0;
190
191 pcur = pcur->next;
192 }
193
194 return 1;
195 }
196
197 //-----------------------------------------------------------------------------
198 // General FAT Table Operations
199 //-----------------------------------------------------------------------------
200
201 //-----------------------------------------------------------------------------
202 // fatfs_find_next_cluster: Return cluster number of next cluster in chain by
203 // reading FAT table and traversing it. Return 0xffffffff for end of chain.
204 //-----------------------------------------------------------------------------
205 uint32 fatfs_find_next_cluster(struct fatfs *fs, uint32 current_cluster)
206 {
207 uint32 fat_sector_offset, position;
208 uint32 nextcluster;
209 struct fat_buffer *pbuf;
210
211 // Why is '..' labelled with cluster 0 when it should be 2 ??
212 if (current_cluster == 0)
213 current_cluster = 2;
214
215 // Find which sector of FAT table to read
216 if (fs->fat_type == FAT_TYPE_16)
217 fat_sector_offset = current_cluster / 256;
218 else
219 fat_sector_offset = current_cluster / 128;
220
221 // Read FAT sector into buffer
222 pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
223 if (!pbuf)
224 return (FAT32_LAST_CLUSTER);
225
226 if (fs->fat_type == FAT_TYPE_16)
227 {
228 // Find 32 bit entry of current sector relating to cluster number
229 position = (current_cluster - (fat_sector_offset * 256)) * 2;
230
231 // Read Next Clusters value from Sector Buffer
232 nextcluster = FAT16_GET_16BIT_WORD(pbuf, (uint16)position);
233
234 // If end of chain found
235 if (nextcluster >= 0xFFF8 && nextcluster <= 0xFFFF)
236 return (FAT32_LAST_CLUSTER);
237 }
238 else
239 {
240 // Find 32 bit entry of current sector relating to cluster number
241 position = (current_cluster - (fat_sector_offset * 128)) * 4;
242
243 // Read Next Clusters value from Sector Buffer
244 nextcluster = FAT32_GET_32BIT_WORD(pbuf, (uint16)position);
245
246 // Mask out MS 4 bits (its 28bit addressing)
247 nextcluster = nextcluster & 0x0FFFFFFF;
248
249 // If end of chain found
250 if (nextcluster >= 0x0FFFFFF8 && nextcluster <= 0x0FFFFFFF)
251 return (FAT32_LAST_CLUSTER);
252 }
253
254 // Else return next cluster
255 return (nextcluster);
256 }
257 //-----------------------------------------------------------------------------
258 // fatfs_set_fs_info_next_free_cluster: Write the next free cluster to the FSINFO table
259 //-----------------------------------------------------------------------------
260 void fatfs_set_fs_info_next_free_cluster(struct fatfs *fs, uint32 newValue)
261 {
262 if (fs->fat_type == FAT_TYPE_16)
263 ;
264 else
265 {
266 // Load sector to change it
267 struct fat_buffer *pbuf = fatfs_fat_read_sector(fs, fs->lba_begin+fs->fs_info_sector);
268 if (!pbuf)
269 return ;
270
271 // Change
272 FAT32_SET_32BIT_WORD(pbuf, 492, newValue);
273 fs->next_free_cluster = newValue;
274
275 // Write back FSINFO sector to disk
276 if (fs->disk_io.write_media)
277 fs->disk_io.write_media(pbuf->address, pbuf->sector, 1);
278
279 // Invalidate cache entry
280 pbuf->address = FAT32_INVALID_CLUSTER;
281 pbuf->dirty = 0;
282 }
283 }
284 //-----------------------------------------------------------------------------
285 // fatfs_find_blank_cluster: Find a free cluster entry by reading the FAT
286 //-----------------------------------------------------------------------------
287 #if FATFS_INC_WRITE_SUPPORT
288 int fatfs_find_blank_cluster(struct fatfs *fs, uint32 start_cluster, uint32 *free_cluster)
289 {
290 uint32 fat_sector_offset, position;
291 uint32 nextcluster;
292 uint32 current_cluster = start_cluster;
293 struct fat_buffer *pbuf;
294
295 do
296 {
297 // Find which sector of FAT table to read
298 if (fs->fat_type == FAT_TYPE_16)
299 fat_sector_offset = current_cluster / 256;
300 else
301 fat_sector_offset = current_cluster / 128;
302
303 if ( fat_sector_offset < fs->fat_sectors)
304 {
305 // Read FAT sector into buffer
306 pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
307 if (!pbuf)
308 return 0;
309
310 if (fs->fat_type == FAT_TYPE_16)
311 {
312 // Find 32 bit entry of current sector relating to cluster number
313 position = (current_cluster - (fat_sector_offset * 256)) * 2;
314
315 // Read Next Clusters value from Sector Buffer
316 nextcluster = FAT16_GET_16BIT_WORD(pbuf, (uint16)position);
317 }
318 else
319 {
320 // Find 32 bit entry of current sector relating to cluster number
321 position = (current_cluster - (fat_sector_offset * 128)) * 4;
322
323 // Read Next Clusters value from Sector Buffer
324 nextcluster = FAT32_GET_32BIT_WORD(pbuf, (uint16)position);
325
326 // Mask out MS 4 bits (its 28bit addressing)
327 nextcluster = nextcluster & 0x0FFFFFFF;
328 }
329
330 if (nextcluster !=0 )
331 current_cluster++;
332 }
333 else
334 // Otherwise, run out of FAT sectors to check...
335 return 0;
336 }
337 while (nextcluster != 0x0);
338
339 // Found blank entry
340 *free_cluster = current_cluster;
341 return 1;
342 }
343 #endif
344 //-----------------------------------------------------------------------------
345 // fatfs_fat_set_cluster: Set a cluster link in the chain. NOTE: Immediate
346 // write (slow).
347 //-----------------------------------------------------------------------------
348 #if FATFS_INC_WRITE_SUPPORT
349 int fatfs_fat_set_cluster(struct fatfs *fs, uint32 cluster, uint32 next_cluster)
350 {
351 struct fat_buffer *pbuf;
352 uint32 fat_sector_offset, position;
353
354 // Find which sector of FAT table to read
355 if (fs->fat_type == FAT_TYPE_16)
356 fat_sector_offset = cluster / 256;
357 else
358 fat_sector_offset = cluster / 128;
359
360 // Read FAT sector into buffer
361 pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
362 if (!pbuf)
363 return 0;
364
365 if (fs->fat_type == FAT_TYPE_16)
366 {
367 // Find 16 bit entry of current sector relating to cluster number
368 position = (cluster - (fat_sector_offset * 256)) * 2;
369
370 // Write Next Clusters value to Sector Buffer
371 FAT16_SET_16BIT_WORD(pbuf, (uint16)position, ((uint16)next_cluster));
372 }
373 else
374 {
375 // Find 32 bit entry of current sector relating to cluster number
376 position = (cluster - (fat_sector_offset * 128)) * 4;
377
378 // Write Next Clusters value to Sector Buffer
379 FAT32_SET_32BIT_WORD(pbuf, (uint16)position, next_cluster);
380 }
381
382 return 1;
383 }
384 #endif
385 //-----------------------------------------------------------------------------
386 // fatfs_free_cluster_chain: Follow a chain marking each element as free
387 //-----------------------------------------------------------------------------
388 #if FATFS_INC_WRITE_SUPPORT
389 int fatfs_free_cluster_chain(struct fatfs *fs, uint32 start_cluster)
390 {
391 uint32 last_cluster;
392 uint32 next_cluster = start_cluster;
393
394 // Loop until end of chain
395 while ( (next_cluster != FAT32_LAST_CLUSTER) && (next_cluster != 0x00000000) )
396 {
397 last_cluster = next_cluster;
398
399 // Find next link
400 next_cluster = fatfs_find_next_cluster(fs, next_cluster);
401
402 // Clear last link
403 fatfs_fat_set_cluster(fs, last_cluster, 0x00000000);
404 }
405
406 return 1;
407 }
408 #endif
409 //-----------------------------------------------------------------------------
410 // fatfs_fat_add_cluster_to_chain: Follow a chain marking and then add a new entry
411 // to the current tail.
412 //-----------------------------------------------------------------------------
413 #if FATFS_INC_WRITE_SUPPORT
414 int fatfs_fat_add_cluster_to_chain(struct fatfs *fs, uint32 start_cluster, uint32 newEntry)
415 {
416 uint32 last_cluster = FAT32_LAST_CLUSTER;
417 uint32 next_cluster = start_cluster;
418
419 if (start_cluster == FAT32_LAST_CLUSTER)
420 return 0;
421
422 // Loop until end of chain
423 while ( next_cluster != FAT32_LAST_CLUSTER )
424 {
425 last_cluster = next_cluster;
426
427 // Find next link
428 next_cluster = fatfs_find_next_cluster(fs, next_cluster);
429 if (!next_cluster)
430 return 0;
431 }
432
433 // Add link in for new cluster
434 fatfs_fat_set_cluster(fs, last_cluster, newEntry);
435
436 // Mark new cluster as end of chain
437 fatfs_fat_set_cluster(fs, newEntry, FAT32_LAST_CLUSTER);
438
439 return 1;
440 }
441 #endif
442 //-----------------------------------------------------------------------------
443 // fatfs_count_free_clusters:
444 //-----------------------------------------------------------------------------
445 uint32 fatfs_count_free_clusters(struct fatfs *fs)
446 {
447 uint32 i,j;
448 uint32 count = 0;
449 struct fat_buffer *pbuf;
450
451 for (i = 0; i < fs->fat_sectors; i++)
452 {
453 // Read FAT sector into buffer
454 pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba + i);
455 if (!pbuf)
456 break;
457
458 for (j = 0; j < FAT_SECTOR_SIZE; )
459 {
460 if (fs->fat_type == FAT_TYPE_16)
461 {
462 if (FAT16_GET_16BIT_WORD(pbuf, (uint16)j) == 0)
463 count++;
464
465 j += 2;
466 }
467 else
468 {
469 if (FAT32_GET_32BIT_WORD(pbuf, (uint16)j) == 0)
470 count++;
471
472 j += 4;
473 }
474 }
475 }
476
477 return count;
478 }