]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Plugson/src/Lib/fat_io_lib/fat_table.c
1 //-----------------------------------------------------------------------------
2 //-----------------------------------------------------------------------------
3 // FAT16/32 File IO Library
6 // Copyright 2003 - 2012
8 // Email: admin@ultra-embedded.com
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 //-----------------------------------------------------------------------------
15 // This file is part of FAT File IO Library.
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.
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.
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 //-----------------------------------------------------------------------------
34 #include "fat_access.h"
35 #include "fat_table.h"
41 #ifndef FAT_BUFFER_SECTORS
42 #define FAT_BUFFER_SECTORS 1
45 #if FAT_BUFFERS < 1 || FAT_BUFFER_SECTORS < 1
46 #error "FAT_BUFFERS & FAT_BUFFER_SECTORS must be at least 1"
49 //-----------------------------------------------------------------------------
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; }
57 //-----------------------------------------------------------------------------
59 //-----------------------------------------------------------------------------
60 void fatfs_fat_init(struct fatfs
*fs
)
64 // FAT buffer chain head
65 fs
->fat_buffer_head
= NULL
;
67 for (i
=0;i
<FAT_BUFFERS
;i
++)
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
;
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
];
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
)
87 // Writeback sector if changed
90 if (fs
->disk_io
.write_media
)
92 uint32 sectors
= FAT_BUFFER_SECTORS
;
93 uint32 offset
= pcur
->address
- fs
->fat_begin_lba
;
95 // Limit to sectors used for the FAT
96 if ((offset
+ FAT_BUFFER_SECTORS
) <= fs
->fat_sectors
)
97 sectors
= FAT_BUFFER_SECTORS
;
99 sectors
= fs
->fat_sectors
- offset
;
101 if (!fs
->disk_io
.write_media(pcur
->address
, pcur
->sector
, sectors
))
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
)
118 struct fat_buffer
*last
= NULL
;
119 struct fat_buffer
*pcur
= fs
->fat_buffer_head
;
121 // Itterate through sector buffer list
124 // Sector within this buffer?
125 if ((sector
>= pcur
->address
) && (sector
< (pcur
->address
+ FAT_BUFFER_SECTORS
)))
129 if (pcur
->next
== NULL
)
131 // Remove buffer from list
134 // We the first and last buffer in the chain?
136 fs
->fat_buffer_head
= NULL
;
143 // We found the sector already in FAT buffer chain
146 pcur
->ptr
= (uint8
*)(pcur
->sector
+ ((sector
- pcur
->address
) * FAT_SECTOR_SIZE
));
150 // Else, we removed the last item from the list
153 // Add to start of sector buffer list (now newest sector)
154 pcur
->next
= fs
->fat_buffer_head
;
155 fs
->fat_buffer_head
= pcur
;
157 // Writeback sector if changed
159 if (!fatfs_fat_writeback(fs
, pcur
))
162 // Address is now new sector
163 pcur
->address
= sector
;
166 if (!fs
->disk_io
.read_media(pcur
->address
, pcur
->sector
, FAT_BUFFER_SECTORS
))
168 // Read failed, invalidate buffer address
169 pcur
->address
= FAT32_INVALID_CLUSTER
;
173 pcur
->ptr
= pcur
->sector
;
176 //-----------------------------------------------------------------------------
177 // fatfs_fat_purge: Purge 'dirty' FAT sectors to disk
178 //-----------------------------------------------------------------------------
179 int fatfs_fat_purge(struct fatfs
*fs
)
181 struct fat_buffer
*pcur
= fs
->fat_buffer_head
;
183 // Itterate through sector buffer list
186 // Writeback sector if changed
188 if (!fatfs_fat_writeback(fs
, pcur
))
197 //-----------------------------------------------------------------------------
198 // General FAT Table Operations
199 //-----------------------------------------------------------------------------
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
)
207 uint32 fat_sector_offset
, position
;
209 struct fat_buffer
*pbuf
;
211 // Why is '..' labelled with cluster 0 when it should be 2 ??
212 if (current_cluster
== 0)
215 // Find which sector of FAT table to read
216 if (fs
->fat_type
== FAT_TYPE_16
)
217 fat_sector_offset
= current_cluster
/ 256;
219 fat_sector_offset
= current_cluster
/ 128;
221 // Read FAT sector into buffer
222 pbuf
= fatfs_fat_read_sector(fs
, fs
->fat_begin_lba
+fat_sector_offset
);
224 return (FAT32_LAST_CLUSTER
);
226 if (fs
->fat_type
== FAT_TYPE_16
)
228 // Find 32 bit entry of current sector relating to cluster number
229 position
= (current_cluster
- (fat_sector_offset
* 256)) * 2;
231 // Read Next Clusters value from Sector Buffer
232 nextcluster
= FAT16_GET_16BIT_WORD(pbuf
, (uint16
)position
);
234 // If end of chain found
235 if (nextcluster
>= 0xFFF8 && nextcluster
<= 0xFFFF)
236 return (FAT32_LAST_CLUSTER
);
240 // Find 32 bit entry of current sector relating to cluster number
241 position
= (current_cluster
- (fat_sector_offset
* 128)) * 4;
243 // Read Next Clusters value from Sector Buffer
244 nextcluster
= FAT32_GET_32BIT_WORD(pbuf
, (uint16
)position
);
246 // Mask out MS 4 bits (its 28bit addressing)
247 nextcluster
= nextcluster
& 0x0FFFFFFF;
249 // If end of chain found
250 if (nextcluster
>= 0x0FFFFFF8 && nextcluster
<= 0x0FFFFFFF)
251 return (FAT32_LAST_CLUSTER
);
254 // Else return next cluster
255 return (nextcluster
);
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
)
262 if (fs
->fat_type
== FAT_TYPE_16
)
266 // Load sector to change it
267 struct fat_buffer
*pbuf
= fatfs_fat_read_sector(fs
, fs
->lba_begin
+fs
->fs_info_sector
);
272 FAT32_SET_32BIT_WORD(pbuf
, 492, newValue
);
273 fs
->next_free_cluster
= newValue
;
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);
279 // Invalidate cache entry
280 pbuf
->address
= FAT32_INVALID_CLUSTER
;
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
)
290 uint32 fat_sector_offset
, position
;
292 uint32 current_cluster
= start_cluster
;
293 struct fat_buffer
*pbuf
;
297 // Find which sector of FAT table to read
298 if (fs
->fat_type
== FAT_TYPE_16
)
299 fat_sector_offset
= current_cluster
/ 256;
301 fat_sector_offset
= current_cluster
/ 128;
303 if ( fat_sector_offset
< fs
->fat_sectors
)
305 // Read FAT sector into buffer
306 pbuf
= fatfs_fat_read_sector(fs
, fs
->fat_begin_lba
+fat_sector_offset
);
310 if (fs
->fat_type
== FAT_TYPE_16
)
312 // Find 32 bit entry of current sector relating to cluster number
313 position
= (current_cluster
- (fat_sector_offset
* 256)) * 2;
315 // Read Next Clusters value from Sector Buffer
316 nextcluster
= FAT16_GET_16BIT_WORD(pbuf
, (uint16
)position
);
320 // Find 32 bit entry of current sector relating to cluster number
321 position
= (current_cluster
- (fat_sector_offset
* 128)) * 4;
323 // Read Next Clusters value from Sector Buffer
324 nextcluster
= FAT32_GET_32BIT_WORD(pbuf
, (uint16
)position
);
326 // Mask out MS 4 bits (its 28bit addressing)
327 nextcluster
= nextcluster
& 0x0FFFFFFF;
330 if (nextcluster
!=0 )
334 // Otherwise, run out of FAT sectors to check...
337 while (nextcluster
!= 0x0);
340 *free_cluster
= current_cluster
;
344 //-----------------------------------------------------------------------------
345 // fatfs_fat_set_cluster: Set a cluster link in the chain. NOTE: Immediate
347 //-----------------------------------------------------------------------------
348 #if FATFS_INC_WRITE_SUPPORT
349 int fatfs_fat_set_cluster(struct fatfs
*fs
, uint32 cluster
, uint32 next_cluster
)
351 struct fat_buffer
*pbuf
;
352 uint32 fat_sector_offset
, position
;
354 // Find which sector of FAT table to read
355 if (fs
->fat_type
== FAT_TYPE_16
)
356 fat_sector_offset
= cluster
/ 256;
358 fat_sector_offset
= cluster
/ 128;
360 // Read FAT sector into buffer
361 pbuf
= fatfs_fat_read_sector(fs
, fs
->fat_begin_lba
+fat_sector_offset
);
365 if (fs
->fat_type
== FAT_TYPE_16
)
367 // Find 16 bit entry of current sector relating to cluster number
368 position
= (cluster
- (fat_sector_offset
* 256)) * 2;
370 // Write Next Clusters value to Sector Buffer
371 FAT16_SET_16BIT_WORD(pbuf
, (uint16
)position
, ((uint16
)next_cluster
));
375 // Find 32 bit entry of current sector relating to cluster number
376 position
= (cluster
- (fat_sector_offset
* 128)) * 4;
378 // Write Next Clusters value to Sector Buffer
379 FAT32_SET_32BIT_WORD(pbuf
, (uint16
)position
, next_cluster
);
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
)
392 uint32 next_cluster
= start_cluster
;
394 // Loop until end of chain
395 while ( (next_cluster
!= FAT32_LAST_CLUSTER
) && (next_cluster
!= 0x00000000) )
397 last_cluster
= next_cluster
;
400 next_cluster
= fatfs_find_next_cluster(fs
, next_cluster
);
403 fatfs_fat_set_cluster(fs
, last_cluster
, 0x00000000);
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
)
416 uint32 last_cluster
= FAT32_LAST_CLUSTER
;
417 uint32 next_cluster
= start_cluster
;
419 if (start_cluster
== FAT32_LAST_CLUSTER
)
422 // Loop until end of chain
423 while ( next_cluster
!= FAT32_LAST_CLUSTER
)
425 last_cluster
= next_cluster
;
428 next_cluster
= fatfs_find_next_cluster(fs
, next_cluster
);
433 // Add link in for new cluster
434 fatfs_fat_set_cluster(fs
, last_cluster
, newEntry
);
436 // Mark new cluster as end of chain
437 fatfs_fat_set_cluster(fs
, newEntry
, FAT32_LAST_CLUSTER
);
442 //-----------------------------------------------------------------------------
443 // fatfs_count_free_clusters:
444 //-----------------------------------------------------------------------------
445 uint32
fatfs_count_free_clusters(struct fatfs
*fs
)
449 struct fat_buffer
*pbuf
;
451 for (i
= 0; i
< fs
->fat_sectors
; i
++)
453 // Read FAT sector into buffer
454 pbuf
= fatfs_fat_read_sector(fs
, fs
->fat_begin_lba
+ i
);
458 for (j
= 0; j
< FAT_SECTOR_SIZE
; )
460 if (fs
->fat_type
== FAT_TYPE_16
)
462 if (FAT16_GET_16BIT_WORD(pbuf
, (uint16
)j
) == 0)
469 if (FAT32_GET_32BIT_WORD(pbuf
, (uint16
)j
) == 0)