UbixOS  2.0
fat_table.c
Go to the documentation of this file.
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
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 //-----------------------------------------------------------------------------
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 //-----------------------------------------------------------------------------
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
438 
439  return 1;
440 }
441 #endif
442 //-----------------------------------------------------------------------------
443 // fatfs_count_free_clusters:
444 //-----------------------------------------------------------------------------
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 }
fatfs_fat_add_cluster_to_chain
int fatfs_fat_add_cluster_to_chain(struct fatfs *fs, uint32 start_cluster, uint32 newEntry)
Definition: fat_table.c:414
fat_buffer
Definition: fat_access.h:40
fat_access.h
fat_table.h
FAT32_SET_32BIT_WORD
#define FAT32_SET_32BIT_WORD(pbuf, location, value)
Definition: fat_table.c:53
uint8
unsigned char uint8
Definition: fat_types.h:15
FAT32_GET_32BIT_WORD
#define FAT32_GET_32BIT_WORD(pbuf, location)
Definition: fat_table.c:52
FAT32_LAST_CLUSTER
#define FAT32_LAST_CLUSTER
Definition: fat_defs.h:108
string.h
fat_buffer::dirty
int dirty
Definition: fat_access.h:44
fatfs_find_next_cluster
uint32 fatfs_find_next_cluster(struct fatfs *fs, uint32 current_cluster)
Definition: fat_table.c:205
fatfs_set_fs_info_next_free_cluster
void fatfs_set_fs_info_next_free_cluster(struct fatfs *fs, uint32 newValue)
Definition: fat_table.c:260
FAT16_SET_16BIT_WORD
#define FAT16_SET_16BIT_WORD(pbuf, location, value)
Definition: fat_table.c:55
fat_defs.h
fatfs_find_blank_cluster
int fatfs_find_blank_cluster(struct fatfs *fs, uint32 start_cluster, uint32 *free_cluster)
Definition: fat_table.c:288
fs
Definition: fs.h:260
FAT_SECTOR_SIZE
#define FAT_SECTOR_SIZE
Definition: fat_opts.h:70
fatfs_free_cluster_chain
int fatfs_free_cluster_chain(struct fatfs *fs, uint32 start_cluster)
Definition: fat_table.c:389
FAT_BUFFERS
#define FAT_BUFFERS
Definition: fat_opts.h:35
FAT32_INVALID_CLUSTER
#define FAT32_INVALID_CLUSTER
Definition: fat_defs.h:109
fatfs_count_free_clusters
uint32 fatfs_count_free_clusters(struct fatfs *fs)
Definition: fat_table.c:445
FAT16_GET_16BIT_WORD
#define FAT16_GET_16BIT_WORD(pbuf, location)
Definition: fat_table.c:54
memset
void * memset(void *dst, int c, size_t length)
uint16
unsigned short uint16
Definition: fat_types.h:16
FAT_BUFFER_SECTORS
#define FAT_BUFFER_SECTORS
Definition: fat_opts.h:29
fat_buffer::sector
uint8 sector[512 *1]
Definition: fat_access.h:42
fatfs_fat_set_cluster
int fatfs_fat_set_cluster(struct fatfs *fs, uint32 cluster, uint32 next_cluster)
Definition: fat_table.c:349
fatfs_fat_init
void fatfs_fat_init(struct fatfs *fs)
Definition: fat_table.c:60
uint32
unsigned long uint32
Definition: fat_types.h:23
fat_buffer::next
struct fat_buffer * next
Definition: fat_access.h:48
fatfs_fat_purge
int fatfs_fat_purge(struct fatfs *fs)
Definition: fat_table.c:179
fat_buffer::ptr
uint8 * ptr
Definition: fat_access.h:45
pbuf
Definition: pbuf.h:142
FAT_TYPE_16
Definition: fat_access.h:53
fat_buffer::address
uint32 address
Definition: fat_access.h:43
fatfs
Definition: fat_access.h:57
NULL
#define NULL
Definition: fat_string.h:17