ATMEL: fat_unusual.c Source File

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# fat_unusual.c

Go to the documentation of this file.

    00001 /*This file is prepared for Doxygen automatic documentation generation.*/
    00014 /* Copyright (C) 2006-2008, Atmel Corporation All rights reserved.
    00015  *
    00016  * Redistribution and use in source and binary forms, with or without
    00017  * modification, are permitted provided that the following conditions are met:
    00018  *
    00019  * 1. Redistributions of source code must retain the above copyright notice,
    00020  * this list of conditions and the following disclaimer.
    00021  *
    00022  * 2. Redistributions in binary form must reproduce the above copyright notice,
    00023  * this list of conditions and the following disclaimer in the documentation
    00024  * and/or other materials provided with the distribution.
    00025  *
    00026  * 3. The name of Atmel may not be used to endorse or promote products derived
    00027  * from this software without specific prior written permission.
    00028  *
    00029  * 4. This software may only be redistributed and used in connection with an Atmel
    00030  * AVR product.
    00031  *
    00032  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
    00033  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00034  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
    00035  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00036  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00037  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00038  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00039  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00040  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00041  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00042  */
    00043
    00044 //_____  I N C L U D E S ___________________________________________________
    00045 #include "conf_explorer.h"
    00046 #include "fs_com.h"
    00047 #include "fat.h"
    00048 #include LIB_MEM
    00049 #include LIB_CTRLACCESS
    00050
    00051
    00052 //_____ D E F I N I T I O N S ______________________________________________
    00053
    00054
    00055
    00056
    00057 //_____ D E C L A R A T I O N S ____________________________________________
    00058
    00059 Bool  fat_select_filesystem               ( U8 u8_fat_type , Bool b_MBR );
    00060 Bool  fat_write_MBR                       ( void );
    00061 Bool  fat_write_PBR                       ( Bool b_MBR );
    00062 Bool  fat_clean_zone                      ( Bool b_MBR );
    00063 Bool  fat_initialize_fat                  ( void );
    00064
    00065
    00068 void  fat_translatedate_number_to_ascii   ( FS_STRING sz_date , PTR_CACHE ptr_date , Bool enable_ms );
    00069 void  fat_translate_number_to_ascii       ( FS_STRING sz_ascii_number, U8 u8_size_number_ascii, U8 u8_nb_increment );
    00070 void  fat_translatedate_ascii_to_number   ( const FS_STRING sz_date , PTR_CACHE ptr_date , Bool enable_ms );
    00071 U16   fat_translate_ascii_to_number       ( const FS_STRING sz_ascii_number, U8 u8_size_number_ascii  );
    00073
    00076 void  fat_create_long_name_entry          ( FS_STRING sz_name , U8 u8_crc , U8 u8_id  );
    00077 U8    fat_create_short_entry_name         ( FS_STRING sz_name , FS_STRING short_name , U8 nb , Bool mode  );
    00078 U8    fat_find_short_entry_name           ( FS_STRING sz_name  );
    00079 Bool  fat_entry_shortname_compare         ( FS_STRING short_name );
    00080 U8    fat_check_name                      ( FS_STRING sz_name  );
    00081 U8    fat_translate_char_shortname        ( U8 character );
    00082 Bool  fat_alloc_entry_free                ( U8 u8_nb_entry );
    00083 Bool  fat_garbage_collector_entry         ( void );
    00085
    00086
    00087
    00088
    00105 Bool  fat_mount( void )
    00106 {
    00107    U8  u8_sector_size;
    00108    U8  u8_tmp;
    00109    U16 u16_tmp;
    00110    U32 u32_tmp;
    00111
    00112    // Select the root directory
    00113    fs_g_nav.u32_cluster_sel_dir   = 0;
    00114    // No selected file
    00115    fat_clear_entry_info_and_ptr();
    00116
    00117    fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_UNM;
    00118    fs_gu32_addrsector = 0;    // Start read at the beginning of memory
    00119
    00120    // Check if the drive is availabled
    00121    if( !fat_check_device() )
    00122       return FALSE;
    00123
    00124    while( 1 )  // Search a valid partition
    00125    {
    00126       // Read one sector
    00127       if( !fat_cache_read_sector( TRUE ))
    00128          return FALSE;
    00129
    00130       // Check PBR/MBR signature
    00131       if ( (fs_g_sector[510] != FS_BR_SIGNATURE_LOW  )
    00132       &&   (fs_g_sector[511] != FS_BR_SIGNATURE_HIGH ) )
    00133       {
    00134          fs_g_status = FS_ERR_NO_FORMAT;
    00135          return FALSE;
    00136       }
    00137
    00138       if ( 0 == fs_gu32_addrsector )
    00139       {
    00140          //** first sector then check a MBR structure
    00141          // Search the first partition supported
    00142 #if (FS_MULTI_PARTITION == ENABLED)
    00143          u16_tmp=0;  // Init to "no valid partition found"
    00144 #endif
    00145          for( u8_tmp=0 ; u8_tmp!=4 ; u8_tmp++ )
    00146          {
    00147             // The first sector must be a MBR, then check the partition entry in the MBR
    00148             if ( ((fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+0] == FS_PART_BOOTABLE             )||
    00149                   (fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+0] == FS_PART_NO_BOOTABLE          )  )
    00150             &&   ((fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+4] == FS_PART_TYPE_FAT12           )||
    00151                   (fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+4] == FS_PART_TYPE_FAT16_INF32M    )||
    00152                   (fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+4] == FS_PART_TYPE_FAT16_SUP32M    )||
    00153                   (fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+4] == FS_PART_TYPE_FAT16_SUP32M_BIS)||
    00154                   (fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+4] == FS_PART_TYPE_FAT32           )||
    00155                   (fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+4] == FS_PART_TYPE_FAT32_BIS       )) )
    00156             {
    00157                // A valid partition is found
    00158 #if (FS_MULTI_PARTITION == ENABLED)
    00159                if( u16_tmp == fs_g_nav.u8_partition )
    00160                   break;   // The selected partition is valid
    00161                u16_tmp++;
    00162 #else
    00163                break;
    00164 #endif
    00165             }
    00166          }
    00167          if( u8_tmp != 4 )
    00168          {
    00169             // Partition found -> Get partition position (unit sector) at offset 8
    00170             LSB0(fs_gu32_addrsector) = fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+8];
    00171             LSB1(fs_gu32_addrsector) = fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+9];
    00172             LSB2(fs_gu32_addrsector) = fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+10];
    00173             LSB3(fs_gu32_addrsector) = fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(u8_tmp)+11];
    00174             fs_gu32_addrsector *= mem_sector_size( fs_g_nav.u8_lun );
    00175             continue;   // Go to check PBR of partition
    00176          }
    00177
    00178          // No MBR found then check PBR
    00179 #if (FS_MULTI_PARTITION == ENABLED)
    00180          // The device don't have mutli partition, but only one
    00181          if ( 0 != fs_g_nav.u8_partition )
    00182          {
    00183             fs_g_status = FS_ERR_NO_PART;
    00184             return FALSE;
    00185          }
    00186 #endif
    00187       }
    00188
    00189       //** Check a PBR structure
    00190       if ( (fs_g_sector[0] == 0xEB) &&          // PBR Byte 0
    00191            (fs_g_sector[2] == 0x90) &&          // PBR Byte 2
    00192            ((fs_g_sector[21] & 0xF0) == 0xF0) ) // PBR Byte 21 : Media byte
    00193       {
    00194          break;   // valid PBR found
    00195       }
    00196       // PBR not found
    00197       fs_g_status = FS_ERR_NO_PART;
    00198       return FALSE;
    00199    }
    00200
    00201    fs_g_status = FS_ERR_NO_SUPPORT_PART;  // by default partition no supported
    00202
    00203    // Get sector size of File System (unit 512B)
    00204    // To translate from sector disk unit to sector 512B unit
    00205    u8_sector_size = HIGH_16_BPB_BytsPerSec/2;
    00206
    00207    // Read BPB_SecPerClus (unit sector)
    00208    fs_g_nav.u8_BPB_SecPerClus = U8_BPB_SecPerClus * u8_sector_size;
    00209
    00210    //** FAT Type determination (algorithm of "Hardware White Paper FAT")
    00211    // Get FAT size (unit sector)
    00212    LSB( u16_tmp ) = LOW_16_BPB_FATSz16;
    00213    MSB( u16_tmp ) = HIGH_16_BPB_FATSz16;
    00214    if ( 0==u16_tmp )
    00215    {
    00216       LSB( u16_tmp ) = LOW0_32_BPB_FATSz32;
    00217       MSB( u16_tmp ) = LOW1_32_BPB_FATSz32;
    00218       // a large FAT32 isn't supported by this file system
    00219       if( (0 != LOW2_32_BPB_FATSz32 )
    00220       ||  (0 != LOW3_32_BPB_FATSz32 ) )
    00221       {
    00222          return FALSE;
    00223       }
    00224    }
    00225    fs_g_nav.u16_fat_size = u16_tmp * u8_sector_size;
    00226
    00227    // Get total count of sectors in partition
    00228    if ( (0==LOW_16_BPB_TotSec16) && (0==HIGH_16_BPB_TotSec16) )
    00229    {
    00230       LSB0( u32_tmp ) = LOW0_32_BPB_TotSec32;
    00231       LSB1( u32_tmp ) = LOW1_32_BPB_TotSec32;
    00232       LSB2( u32_tmp ) = LOW2_32_BPB_TotSec32;
    00233       LSB3( u32_tmp ) = LOW3_32_BPB_TotSec32;
    00234    }
    00235    else
    00236    {
    00237       LSB0( u32_tmp ) = LOW_16_BPB_TotSec16;
    00238       LSB1( u32_tmp ) = HIGH_16_BPB_TotSec16;
    00239       LSB2( u32_tmp ) = 0;
    00240       LSB3( u32_tmp ) = 0;
    00241    }
    00242    u32_tmp *= u8_sector_size;   // Translate from sector disk unit to sector 512B unit
    00243
    00244    // Compute the offset (unit 512B) between the end of FAT (beginning of root dir in FAT1x) and the beginning of PBR
    00245    fs_g_nav.rootdir.seg.u16_pos = FS_NB_FAT * fs_g_nav.u16_fat_size;
    00246
    00247    // Compute the root directory size (unit sector), for FAT32 is always 0
    00248    LSB( u16_tmp ) = LOW_16_BPB_RootEntCnt;
    00249    MSB( u16_tmp ) = HIGH_16_BPB_RootEntCnt;
    00250    fs_g_nav.rootdir.seg.u16_size = ((u16_tmp * FS_SIZE_FILE_ENTRY) + ((FS_512B*u8_sector_size)-1)) / (FS_512B*u8_sector_size);
    00251    fs_g_nav.rootdir.seg.u16_size *= u8_sector_size;
    00252
    00253    // Get number of reserved sector
    00254    LSB( u16_tmp ) = LOW_16_BPB_ResvSecCnt;
    00255    MSB( u16_tmp ) = HIGH_16_BPB_ResvSecCnt;
    00256    // Get FSInfo position
    00257    fs_g_nav.u16_offset_FSInfo = (u16_tmp-LOW_16_BPB_FSInfo)*u8_sector_size;
    00258    u16_tmp *= u8_sector_size; // number of reserved sector translated in unit 512B
    00259
    00260    // Compute the FAT address (unit 512B)
    00261    fs_g_nav.u32_ptr_fat = fs_gu32_addrsector + u16_tmp;
    00262
    00263    // Compute the offset (unit 512B) between the first data cluster and the FAT beginning
    00264    fs_g_nav.u32_offset_data = (FS_NB_FAT * (U32)fs_g_nav.u16_fat_size) + (U32)fs_g_nav.rootdir.seg.u16_size;
    00265
    00266    // Compute the data region (clusters space = Total - Sector used) size (unit 512B)
    00267    u32_tmp -= ((U32)u16_tmp + fs_g_nav.u32_offset_data);
    00268
    00269    // Compute the count of CLUSTER in the data region
    00270    // !!!Optimization -> u32_CountofCluster (unit 512B)/ fs_g_nav.u8_BPB_SecPerClus (unit 512B & power of 2)
    00271    if (!fs_g_nav.u8_BPB_SecPerClus)
    00272      return FALSE;
    00273    for( u8_tmp = fs_g_nav.u8_BPB_SecPerClus; u8_tmp!=1 ; u8_tmp >>= 1 )
    00274    {
    00275      u32_tmp  >>= 1;   // This computation round down
    00276    }
    00277    fs_g_nav.u32_CountofCluster = u32_tmp+2; // The total of cluster include the two reserved clusters
    00278
    00279    // Determine the FAT type
    00280    if (u32_tmp < FS_FAT12_MAX_CLUSTERS)
    00281    {
    00282       // Is FAT 12
    00283 #if (FS_FAT_12 == DISABLED)
    00284       return FALSE;
    00285 #endif
    00286       fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_12;
    00287    } else {
    00288    if (u32_tmp < FS_FAT16_MAX_CLUSTERS)
    00289    {
    00290       // Is FAT 16
    00291 #if (FS_FAT_16 == DISABLED)
    00292       return FS_NO_SUPPORT_PART;
    00293 #endif
    00294       fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_16;
    00295    } else {
    00296       // Is FAT 32
    00297 #if (FS_FAT_32 == DISABLED)
    00298       return FALSE;
    00299 #endif
    00300       fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_32;
    00301       // In FAT32, the root dir is like another directory, this one have a cluster list
    00302       // Get the first cluster number of root
    00303       LSB0( fs_g_nav.rootdir.u32_cluster ) = LOW0_32_BPB_RootClus;
    00304       LSB1( fs_g_nav.rootdir.u32_cluster ) = LOW1_32_BPB_RootClus;
    00305       LSB2( fs_g_nav.rootdir.u32_cluster ) = LOW2_32_BPB_RootClus;
    00306       LSB3( fs_g_nav.rootdir.u32_cluster ) = LOW3_32_BPB_RootClus;
    00307    }
    00308    }
    00309
    00310    return TRUE;
    00311 }
    00312
    00313
    00314
    00315 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET) )
    00316
    00318 _MEM_TYPE_SLOW_   U32 fs_s_u32_size_partition;
    00319
    00340 Bool  fat_format( U8 u8_fat_type )
    00341 {
    00342    Bool b_MBR;
    00343 #if (FS_MULTI_PARTITION == ENABLED)
    00344 #error NOT SUPPORTED
    00345    fs_g_nav.u8_partition = 0;
    00346 #endif
    00347
    00348
    00349    // Get drive capacity (= last LBA)
    00350    mem_read_capacity( fs_g_nav.u8_lun , &fs_s_u32_size_partition );
    00351
    00352    if( u8_fat_type & FS_FORMAT_NOMBR_FLAG )
    00353    {
    00354       b_MBR = FALSE;
    00355       u8_fat_type &= ~FS_FORMAT_NOMBR_FLAG;
    00356       // partition size = disk size = last LBA + 1
    00357       fs_s_u32_size_partition++;
    00358    }else{
    00359       b_MBR = TRUE;
    00360       // partition size = size disk -1 = last LBA
    00361    }
    00362
    00363    // Compute the FAT type for the device
    00364    if( !fat_select_filesystem( u8_fat_type , b_MBR ))
    00365       return FALSE;
    00366
    00367    // Write the MBR sector (first sector)
    00368    if( b_MBR )
    00369       if( !fat_write_MBR())
    00370          return FALSE;
    00371
    00372    // Write the PBR sector
    00373    if( !fat_write_PBR( b_MBR ))
    00374       return FALSE;
    00375
    00376    // Clear reserved zone, FAT zone, and Root dir zone
    00377    // Remark: the reserved zone of FAT32 isn't initialized, because BPB_FSInfo is equal to 0
    00378    if( !fat_clean_zone( b_MBR ))
    00379       return FALSE;
    00380
    00381    // Initialization of the FAT 1 and 2
    00382    if( !fat_initialize_fat())
    00383       return FALSE;
    00384
    00385    return fat_cache_flush();
    00386 }
    00387
    00388
    00389
    00391 typedef struct st_fs_format_table {
    00392    U32   u32_disk_size;
    00393    U8    u8_SecPerClusVal;
    00394 } Fs_format_table;
    00395
    00396
    00398 _CONST_TYPE_ Fs_format_table TableFAT12[] = {
    00399    {  4096, 1},      // disks up to 2 MB, 512 bytes cluster
    00400    {  8192, 2},      // disks up to 4 MB, 1k cluster
    00401    { 16384, 4},      // disks up to 8 MB, 2k cluster
    00402    { 32680, 8},      // disks up to 16 MB, 4k cluster
    00403 };
    00404 /*
    00405 NOTE: that this table includes
    00406 entries for disk sizes larger than 16 MB even though typically
    00407 only the entries for disks < 16 MB in size are used.
    00408 The way this table is accessed is to look for the first entry
    00409 in the table for which the disk size is less than or equal
    00410 to the DiskSize field in that table entry. For this table to
    00411 work properly BPB_RsvdSecCnt must be 1, BPB_NumFATs
    00412 must be 2, and BPB_RootEntCnt must be 512.
    00413 */
    00414
    00415
    00417 _CONST_TYPE_ Fs_format_table TableFAT16[] = {
    00418    { 8400, 0},       // disks up to 4.1 MB, the 0 value for SecPerClusVal trips an error
    00419    { 32680, 2},      // disks up to 16 MB, 1k cluster
    00420    { 262144, 4},     // disks up to 128 MB, 2k cluster
    00421    { 524288, 8},     // disks up to 256 MB, 4k cluster
    00422    { 1048576, 16},   // disks up to 512 MB, 8k cluster
    00423    // The entries after this point are not used unless FAT16 is forced
    00424    { 2097152, 32},   // disks up to 1 GB, 16k cluster
    00425    { 4194304, 64},   // disks up to 2 GB, 32k cluster
    00426    { 0xFFFFFFFF, 0}  // any disk greater than 2GB, 0 value for SecPerClusVal trips an error
    00427 };
    00428 /*
    00429 NOTE: that this table includes
    00430 entries for disk sizes larger than 512 MB even though typically
    00431 only the entries for disks < 512 MB in size are used.
    00432 The way this table is accessed is to look for the first entry
    00433 in the table for which the disk size is less than or equal
    00434 to the DiskSize field in that table entry. For this table to
    00435 work properly BPB_RsvdSecCnt must be 1, BPB_NumFATs
    00436 must be 2, and BPB_RootEntCnt must be 512. Any of these values
    00437 being different may require the first table entries DiskSize value
    00438 to be changed otherwise the cluster count may be to low for FAT16.
    00439 */
    00440
    00441
    00443 _CONST_TYPE_ Fs_format_table TableFAT32[] = {
    00444    { 66600, 0},      // disks up to 32.5 MB, the 0 value for SecPerClusVal trips an error
    00445    { 532480, 1},     // disks up to 260 MB, .5k cluster
    00446    { 16777216, 8},   // disks up to 8 GB, 4k cluster
    00447    { 33554432, 16},  // disks up to 16 GB, 8k cluster
    00448    { 67108864, 32},  // disks up to 32 GB, 16k cluster
    00449    { 0xFFFFFFFF, 64} // disks greater than 32GB, 32k cluster
    00450 };
    00451 /*
    00452 NOTE: that this table includes
    00453 entries for disk sizes smaller than 512 MB even though typically
    00454 only the entries for disks >= 512 MB in size are used.
    00455 The way this table is accessed is to look for the first entry
    00456 in the table for which the disk size is less than or equal
    00457 to the DiskSize field in that table entry. For this table to
    00458 work properly BPB_RsvdSecCnt must be 32, and BPB_NumFATs
    00459 must be 2. Any of these values being different may require the first
    00460 table entries DiskSize value to be changed otherwise the cluster count
    00461 may be to low for FAT32.
    00462 */
    00463
    00464
    00467
    00483 Bool  fat_select_filesystem( U8 u8_fat_type , Bool b_MBR )
    00484 {
    00485    U8 u8_i;
    00486    U8 u8_tmp = 0;
    00487    U16  u16_tmp, u16_tmp2;
    00488    Fs_format_table _CONST_TYPE_ *ptr_table;
    00489
    00490    if( (FS_FORMAT_FAT   != u8_fat_type )
    00491    &&  (FS_FORMAT_FAT32 != u8_fat_type ) )
    00492    {
    00493       // Default format then select the better FAT type
    00494       if( (((U32)512*1024*1024)/FS_512B) >= fs_s_u32_size_partition  )
    00495       {
    00496          u8_fat_type = FS_FORMAT_FAT;
    00497       } else {
    00498          u8_fat_type = FS_FORMAT_FAT32;
    00499       }
    00500    }
    00501
    00502    //** Verify the FAT type choosed
    00503    if(FS_FORMAT_FAT == u8_fat_type )
    00504    {
    00505       if( (((U32)2*1024*1024)/FS_512B) >= fs_s_u32_size_partition  )
    00506       {
    00507          fs_g_status = FS_ERR_DEVICE_TOO_SMALL;    // The disk size is not supported
    00508          return FALSE;
    00509       }
    00510       if( (((U32)15*1024*1024)/FS_512B) >= fs_s_u32_size_partition  )
    00511       {
    00512          // FAT 12 format
    00513          fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_12;
    00514          u8_i = sizeof(TableFAT12);
    00515          ptr_table = TableFAT12;
    00516       }else{
    00517          // FAT 16 format
    00518          fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_16;
    00519          u8_i = sizeof(TableFAT16);
    00520          ptr_table = TableFAT16;
    00521       }
    00522    }
    00523    else
    00524    {  // FAT 32 format
    00525       fs_g_nav_fast.u8_type_fat = FS_TYPE_FAT_32;
    00526       u8_i = sizeof(TableFAT32);
    00527       ptr_table = TableFAT32;
    00528    }
    00529    for(  ; u8_i!=0 ; u8_i-- )
    00530    {
    00531       if( fs_s_u32_size_partition <= ptr_table->u32_disk_size )
    00532       {
    00533          // Get cluster size (unit sector)
    00534          fs_g_nav.u8_BPB_SecPerClus = ptr_table->u8_SecPerClusVal;
    00535          break;
    00536       }
    00537       ptr_table++;
    00538    }
    00539    if(0 == fs_g_nav.u8_BPB_SecPerClus)
    00540    {
    00541       fs_g_status = FS_ERR_BAD_SIZE_FAT;    // The disk size is not supported by selected FAT type
    00542       return FALSE;
    00543    }
    00544
    00545    //** Compute fat size
    00546    // Compute PBR address
    00547    if( b_MBR )
    00548       fs_g_nav.u32_ptr_fat = 1;  // MBR exist
    00549    else
    00550       fs_g_nav.u32_ptr_fat = 0;  // no MBR
    00551
    00552    if( Is_fat12 )
    00553    {  // FAT 12
    00554       fs_g_nav.u32_ptr_fat += 1;  // FAT address = PBR address + 1
    00555       // Try all possibility of FAT12 size
    00556       fs_g_nav.u16_fat_size=1;
    00557       while(1)
    00558       {
    00559          if( 12 < fs_g_nav.u16_fat_size)        // Max FAT size in FAT12 mode (unit sector) (=0xFFE*1.5/FS_512B)
    00560          {
    00561             fs_g_status = FS_ERR_BAD_SIZE_FAT;  // The disk size is not supported by file system selected
    00562             return FALSE;
    00563          }
    00564          // Check if the number of cluster corresponding at data zone size
    00565          // Note: -1 to not compute PBR sector
    00566          u16_tmp  = ((fs_s_u32_size_partition -1 - (fs_g_nav.u16_fat_size *2)) / fs_g_nav.u8_BPB_SecPerClus)+2;
    00567          u16_tmp2 = (fs_g_nav.u16_fat_size *FS_512B *2) / 3;
    00568          if( u16_tmp <= u16_tmp2 )
    00569             break;   // FAT size OK
    00570
    00571          fs_g_nav.u16_fat_size++;
    00572       }
    00573    }
    00574    else
    00575    {
    00576       if( Is_fat32 )
    00577       {  // FAT 32
    00578          fs_g_nav.u32_ptr_fat += 32;  // FAT address = PBR address + BPB_ResvSecCnt
    00579          // RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec;
    00580          //                = (FS_512B-1) / FS_512B = 0
    00581          // TmpVal1        = DskSize – (BPB_ResvdSecCnt + RootDirSectors);
    00582          //                = fs_s_u32_size_partition - (32 + 0)
    00583          //                = fs_s_u32_size_partition - u8_tmp
    00584          u8_tmp = 32;
    00585          // TmpVal2        = ((256 * BPB_SecPerClus) + BPB_NumFATs )/2;
    00586          //                = ((((U16)fs_g_nav.u8_BPB_SecPerClus)<<8) + 2) >> 1;
    00587          //                = (((U16)fs_g_nav.u8_BPB_SecPerClus)<<7) + 1;
    00588          //                = u16_tmp
    00589          u16_tmp = (((U16)fs_g_nav.u8_BPB_SecPerClus)<<7) + 1;
    00590          // BPB_FATSz16    = 0;
    00591          // BPB_FATSz32    = FATSz;
    00592       }
    00593       if( Is_fat16 )
    00594       {  // FAT 16
    00595          fs_g_nav.u32_ptr_fat += 1;  // FAT address = PBR address + BPB_ResvSecCnt
    00596          // RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1))  / BPB_BytsPerSec
    00597          //                = ((512            * 32) + (FS_512B-1)) / FS_512B
    00598          //                = 32
    00599          // TmpVal1        = DskSize – (BPB_ResvdSecCnt + RootDirSectors);
    00600          //                = fs_s_u32_size_partition - (1 + 32)
    00601          //                = fs_s_u32_size_partition - u8_tmp
    00602          u8_tmp = 33;
    00603          // TmpVal2        = ((256 * BPB_SecPerClus) + BPB_NumFATs )/2;
    00604          //                = (((U16)fs_g_nav.u8_BPB_SecPerClus)<<8) + 2;
    00605          //                = u16_tmp
    00606          MSB(u16_tmp) = fs_g_nav.u8_BPB_SecPerClus;
    00607          LSB(u16_tmp) = 2;
    00608       }
    00609       // FATSz          = (TMPVal1 + TmpVal2 – 1) / TmpVal2;
    00610       fs_g_nav.u16_fat_size = (fs_s_u32_size_partition -u8_tmp +u16_tmp -1) / u16_tmp;
    00611    }
    00612
    00613    return TRUE;
    00614 }
    00615
    00616
    00622 Bool  fat_write_MBR( void )
    00623 {
    00624    U8 u8_i = 0;
    00625
    00626    // Init and reset the internal cache at the beginning of memory
    00627    fs_gu32_addrsector = 0;
    00628    if( !fat_cache_read_sector( FALSE ))
    00629       return FALSE;
    00630    fat_cache_mark_sector_as_dirty();
    00631    fat_cache_clear();
    00632
    00633    // MBR signature
    00634    fs_g_sector[510] = FS_BR_SIGNATURE_LOW;
    00635    fs_g_sector[511] = FS_BR_SIGNATURE_HIGH;
    00636
    00637    // Write the partition entry in the MBR
    00638    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0) +0] = FS_PART_NO_BOOTABLE;   // Active partition
    00639    // Remark: cylinder and header start to 0, and sector value start to 1
    00640    //fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0) +1] = 0;                   // The head (0) where the partition starts
    00641    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0) +2] = 2;                     // The sector (2=next to MBR) and the cylinder (0) where the partition starts
    00642    //fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0) +3] = 0;
    00643
    00644    // Write patition type
    00645    if( Is_fat32 )
    00646    {  // FAT 32
    00647       u8_i = FS_PART_TYPE_FAT32;
    00648    }
    00649    if( Is_fat16 )
    00650    {  // FAT 16
    00651       if( fs_s_u32_size_partition < (32L*1024*(1024/FS_512B)) )
    00652       {  // Disk < 32MB
    00653          u8_i = FS_PART_TYPE_FAT16_INF32M;
    00654       }else{
    00655          u8_i = FS_PART_TYPE_FAT16_SUP32M;
    00656       }
    00657    }
    00658    if( Is_fat12 )
    00659    {  // FAT 12
    00660       u8_i = FS_PART_TYPE_FAT12;
    00661    }
    00662
    00663    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0) +4] = u8_i;
    00664
    00665    // The head where the partitions ends
    00666    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0) +5] = (LSB1(fs_s_u32_size_partition)<<2) + (LSB0(fs_s_u32_size_partition)>>6);
    00667    // The sector and the cylinder where the partition ends
    00668    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0) +6] = (LSB1(fs_s_u32_size_partition)&0xC0) + (LSB0(fs_s_u32_size_partition)&0x3F);
    00669    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0) +7] = LSB2(fs_s_u32_size_partition);
    00670
    00671    // Write partition position (in sectors) at offset 8
    00672    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0)+ 8] = 0x01;
    00673    //fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0)+ 9] = 0x00;
    00674    //fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0)+10] = 0x00;
    00675    //fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0)+11] = 0x00;
    00676    // Write the number of sector in partition (= size - one sector MBR = last LBA, return by read_capacity)
    00677    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0)+12] = LSB0(fs_s_u32_size_partition);
    00678    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0)+13] = LSB1(fs_s_u32_size_partition);
    00679    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0)+14] = LSB2(fs_s_u32_size_partition);
    00680    fs_g_sector[FS_MBR_OFFSET_PART_ENTRY(0)+15] = LSB3(fs_s_u32_size_partition);
    00681
    00682    return TRUE;
    00683 }
    00684
    00686 _CONST_TYPE_ U8 const_header_pbr[] = {
    00687    0xEB,0,0x90,                                       // offset 00-02, Add jump boot flag
    00688    'M','S','W','I','N','4','.','1',                   // offset 03-11, No add OEM name
    00689    FS_512B & 0xFF, FS_512B >>8,                       // offset 11-12, Add byte per sector
    00690    0,                                                 // offset 13-13, Add sector by cluster
    00691    0,0,                                               // offset 14-15, Add Number of reserved sector (see next step for optimization test)
    00692    2,                                                 // offset 16-16, Add Number of FAT
    00693    0,0,                                               // offset 17-18, Add Number of root entry (FAT32 = 0 entry, FAT16 = 512 entrys)
    00694    0,0,
    00695    FS_PART_NO_REMOVE_MEDIA,                           // offset 21-21, Media byte
    00696    0,0,
    00697    0x3F,0,                                            // offset 24-25, Sector per track (must be egal to MBR information, also maximum sector per head = 0x3F = 6bits)
    00698    0,0,                                               // offset 26-27, Number of header
    00699    1                                                  // offset 28-31, Number of hidden setors
    00700    };
    00701 _CONST_TYPE_ U8 const_tail_pbr[] = {           // offset 36 on FAT 16, offset 64 on FAT 32
    00702    FS_PART_HARD_DISK,                                 // Driver number
    00703    0,                                                 // Reserved (used by Windows NT)
    00704    FS_BOOT_SIGN,                                      // Extended boot signature
    00705    0,0,0,0,                                           // volume ID
    00706    'N','O',' ','N','A','M','E',' ',' ',' ',' ',       // volume label (11 characters);
    00707    'F','A','T',' ',' ',' ',' ',' ',                   // FAT type in ASCII (8 characters);
    00708    };
    00709
    00710
    00713 _CONST_TYPE_ U8 const_FSI_LeadSig[] = {
    00714    0x52,0x52,0x61,0x41
    00715 };
    00716 _CONST_TYPE_ U8 const_FSI_StrucSig[] = {
    00717    0x72,0x72,0x41,0x61
    00718 };
    00720
    00721
    00729 Bool  fat_write_PBR( Bool b_MBR )
    00730 {
    00731    U16 u16_tmp;
    00732
    00733    //** Init the cache sector with PBR
    00734    if( b_MBR )
    00735       fs_gu32_addrsector = 1;
    00736    else
    00737       fs_gu32_addrsector = 0;
    00738
    00739    if( !fat_cache_read_sector( FALSE ))
    00740       return FALSE;
    00741    fat_cache_mark_sector_as_dirty();
    00742    fat_cache_clear();
    00743
    00744    //** WRITE CONSTANTE & VARIABLE FOR FAT and FAT32
    00745    memcpy_code2ram( fs_g_sector, const_header_pbr , sizeof(const_header_pbr) );
    00746    // PBR signature
    00747    fs_g_sector[510] = FS_BR_SIGNATURE_LOW;
    00748    fs_g_sector[511] = FS_BR_SIGNATURE_HIGH;
    00749
    00750    // offset 13-13, Add sector by cluster
    00751    fs_g_sector[13] = fs_g_nav.u8_BPB_SecPerClus;
    00752    // offset 26-27, Number of header
    00753    fs_g_sector[26] = (LSB1(fs_s_u32_size_partition)<<2) + (LSB0(fs_s_u32_size_partition)>>6);
    00754
    00755    //** WRITE CONSTANTE & VARIABLE DEPENDING OF FAT16 and FAT32
    00756    // Since offset 36, there are a different structure space for FAT16 and FAT32
    00757    // offset 39-42 or 67-70, Volume ID not used
    00758    // offset 43-53 or 71-81, Volume Label
    00759    // offset 54-61 or 82-89, File system type
    00760    if( Is_fat32 )
    00761    {
    00762       memcpy_code2ram( &fs_g_sector[64], const_tail_pbr, sizeof(const_tail_pbr) );
    00763    }else{
    00764       memcpy_code2ram( &fs_g_sector[36], const_tail_pbr, sizeof(const_tail_pbr) );
    00765    }
    00766
    00767    u16_tmp = fs_g_nav.u16_fat_size;    // save value in fast data space to optimize code
    00768    if( Is_fat32 )
    00769    {
    00770       // offset 14-15, Add Number of reserved sector, FAT32 = 32 sectors
    00771       fs_g_sector[14] = 32;
    00772       // offset 17-18, Add Number of root entry, FAT32 = 0 entry
    00773       // offset 36-39, Fat size 32bits
    00774       LOW0_32_BPB_FATSz32 = LSB(u16_tmp);
    00775       LOW1_32_BPB_FATSz32 = MSB(u16_tmp);
    00776       // offset 40-41, Ext flags (all FAT are enabled = 0)
    00777       // offset 42-43, Fs version (version0:0 = 0)
    00778       // offset 44-47, Root Cluster (first free cluster = 2)
    00779       fs_g_sector[44]= 2;
    00780       // offset 48-49, Fs Info (usualy 1)
    00781       fs_g_sector[48]= 1;
    00782       // offset 50-51, Backup Boot Sector (usualy 6)
    00783       // fs_g_sector[50]= 0;
    00784       // offset 52-63, reserved space
    00785       // offset 54-61, File system type
    00786       fs_g_sector[85]='3';
    00787       fs_g_sector[86]='2';
    00788       // Update FSInfo position
    00789       fs_g_nav.u16_offset_FSInfo = (32-1);
    00790    }
    00791    else
    00792    {
    00793       // FAT 12 or 16
    00794       // offset 14-15, Add Number of reserved sector, FAT = 1 sector
    00795       fs_g_sector[14] = 1;
    00796       // offset 17-18, Add Number of root entry, FAT = 512 entrys
    00797       //fs_g_sector[17] = 512&0xFF;
    00798       fs_g_sector[18] = 512>>8;
    00799
    00800       // offset 22-23, Fat size 16bits
    00801       LOW_16_BPB_FATSz16  = LSB(u16_tmp);
    00802       HIGH_16_BPB_FATSz16 = MSB(u16_tmp);
    00803       // offset 54-61, File system type
    00804       fs_g_sector[57]='1';
    00805       if( Is_fat12 )
    00806       {
    00807          fs_g_sector[58]='2';
    00808       }else{
    00809          fs_g_sector[58]='6';
    00810       }
    00811    }
    00812
    00813    // Write the number of sector in partition (= size - one sector MBR = last LBA, return by read_capacity)
    00814    if( ( Is_fat32 )
    00815    ||  ((0x10000-1) <= fs_s_u32_size_partition) )
    00816    {
    00817       // FAT32 or disk > 32MB
    00818       // offset 32-35, Number of sector in partition (value 32 bits)
    00819       fs_g_sector[32] = LSB0(fs_s_u32_size_partition);
    00820       fs_g_sector[33] = LSB1(fs_s_u32_size_partition);
    00821       fs_g_sector[34] = LSB2(fs_s_u32_size_partition);
    00822       fs_g_sector[35] = LSB3(fs_s_u32_size_partition);
    00823    }
    00824    else
    00825    {
    00826       // offset 19-20, Number of sector in partition (value 16 bits)
    00827       fs_g_sector[19] = LSB0(fs_s_u32_size_partition);
    00828       fs_g_sector[20] = LSB1(fs_s_u32_size_partition);
    00829    }
    00830
    00831    if( Is_fat32 )
    00832    {
    00833       // Init the FAT32 FSInfo Sector
    00834       if( !fat_write_fat32_FSInfo( 0xFFFFFFFF ))
    00835          return FALSE;
    00836    }
    00837    return TRUE;
    00838 }
    00840
    00841 #ifdef  FS_FAT_32
    00852 Bool  fat_write_fat32_FSInfo( U32 u32_nb_free_cluster )
    00853 {
    00854    // Init sector
    00855    fs_gu32_addrsector = fs_g_nav.u32_ptr_fat - fs_g_nav.u16_offset_FSInfo;
    00856
    00857    if( !fat_cache_read_sector( FALSE ))
    00858       return FALSE;
    00859    fat_cache_mark_sector_as_dirty();
    00860    fat_cache_clear();
    00861
    00862    // Fill sector
    00863    // offset 00-04, This lead signature
    00864    memcpy_code2ram( &fs_g_sector[0], const_FSI_LeadSig, sizeof(const_FSI_LeadSig) );
    00865    // offset 004-483, reserved (fill with 0)
    00866    // offset 484-487, signature
    00867    memcpy_code2ram( &fs_g_sector[484], const_FSI_StrucSig, sizeof(const_FSI_StrucSig) );
    00868    // offset 488-491, free cluster count (by default NO value)
    00869    fs_g_sector[488] = LSB0(u32_nb_free_cluster);
    00870    fs_g_sector[489] = LSB1(u32_nb_free_cluster);
    00871    fs_g_sector[490] = LSB2(u32_nb_free_cluster);
    00872    fs_g_sector[491] = LSB3(u32_nb_free_cluster);
    00873    // offset 492-495, indicates the cluster number at which the driver should start looking for free clusters (by default NO value)
    00874    memset( &fs_g_sector[492] , 0xFF , 4 );
    00875    // offset 496-509, reserved (fill with 0)
    00876    // offset 510-511, Signature
    00877    fs_g_sector[510] = FS_BR_SIGNATURE_LOW;
    00878    fs_g_sector[511] = FS_BR_SIGNATURE_HIGH;
    00879    return TRUE;
    00880 }
    00881
    00882
    00887 U32   fat_read_fat32_FSInfo( void )
    00888 {
    00889    U32 u32_nb_free_cluster;
    00890
    00891    // Read FAT32 FSInfo Sector
    00892    fs_gu32_addrsector = fs_g_nav.u32_ptr_fat - fs_g_nav.u16_offset_FSInfo;
    00893    if( !fat_cache_read_sector( TRUE ))
    00894       return 0xFFFFFFFF;
    00895
    00896    //* Check signature
    00897    // offset 510-511, Signature
    00898    if( fs_g_sector[510] != FS_BR_SIGNATURE_LOW )
    00899       return 0xFFFFFFFF;
    00900    if( fs_g_sector[511] != FS_BR_SIGNATURE_HIGH)
    00901       return 0xFFFFFFFF;
    00902    // offset 00-04, This lead signature
    00903    if( 0 != memcmp_code2ram( &fs_g_sector[0], const_FSI_LeadSig, sizeof(const_FSI_LeadSig) ))
    00904       return 0xFFFFFFFF;
    00905    // offset 004-483, reserved (fill with 0)
    00906    // offset 484-487, signature
    00907    if( 0 != memcmp_code2ram( &fs_g_sector[484], const_FSI_StrucSig, sizeof(const_FSI_StrucSig)) )
    00908       return 0xFFFFFFFF;
    00909
    00910    //* Read value
    00911    // offset 488-491, free cluster count
    00912    LSB0(u32_nb_free_cluster) = fs_g_sector[488];
    00913    LSB1(u32_nb_free_cluster) = fs_g_sector[489];
    00914    LSB2(u32_nb_free_cluster) = fs_g_sector[490];
    00915    LSB3(u32_nb_free_cluster) = fs_g_sector[491];
    00916    return u32_nb_free_cluster;
    00917 }
    00918 #endif  // FS_FAT_32
    00919
    00920
    00928 Bool  fat_clean_zone( Bool b_MBR )
    00929 {
    00930    U16 u16_nb_sector_clean, u16_i;
    00931    _MEM_TYPE_SLOW_   U8 *ptr;
    00932
    00933    // Flush the internal cache before clear the cache
    00934    if( !fat_cache_flush())
    00935       return FALSE;
    00936    fat_cache_clear();
    00937
    00938    // remark: these zones are stored after the PBR and are continues
    00939    // Start after PBR
    00940    if( b_MBR )
    00941    {
    00942       fs_gu32_addrsector = 2; // Jump MBR and PBR
    00943    }else{
    00944       fs_gu32_addrsector = 1; // Jump only a PBR (no MBR create)
    00945    }
    00946
    00947    // Compute reserved zone size and root size
    00948    if( Is_fat32 )
    00949    {  // FAT 32
    00950       fs_gu32_addrsector++;   // Jump FAT32 FSInfo Sector
    00951       // root size = cluster size AND reserved zone = 32 - 2 (2 = PBR + FSInfo)
    00952       u16_nb_sector_clean = fs_g_nav.u8_BPB_SecPerClus + 30;
    00953    }
    00954    else
    00955    {  // FAT 12 or 16
    00956       // root size = 512 entrys = 32 sectors AND reserved zone = 1 - 1(PBR)
    00957       u16_nb_sector_clean = 32;
    00958    }
    00959    u16_nb_sector_clean += (fs_g_nav.u16_fat_size*2);  // Add FAT size
    00960
    00961    // loop to clean
    00962    for( ; u16_nb_sector_clean!=0; u16_nb_sector_clean-- )
    00963    {
    00964       // To improve the format time
    00965       // We check if the sector is clean (0x00) instead of write a clean sector.
    00966       if( !fat_cache_read_sector( TRUE ))
    00967          return FALSE;
    00968       ptr = fs_g_sector;
    00969       for( u16_i=0; u16_i<FS_CACHE_SIZE; u16_i++,ptr++ )
    00970       {
    00971          if( 0x00 != *ptr )
    00972          {
    00973             // Sector not clean then erase it
    00974             fat_cache_clear();
    00975             fat_cache_mark_sector_as_dirty();
    00976             break;
    00977          }
    00978       }
    00979       fs_gu32_addrsector++;
    00980    }
    00981    return TRUE;
    00982 }
    00983
    00984
    00987 _CONST_TYPE_ U8 const_header_fat12[] = {
    00988    0xF8,0xFF,0xFF                            // reserved clusters 0 & 1
    00989    };
    00990 _CONST_TYPE_ U8 const_header_fat16[] = {
    00991    0xF8,0xFF,0xFF,0xFF                       // reserved clusters 0 & 1
    00992    };
    00993 _CONST_TYPE_ U8 const_header_fat32[] = {
    00994    0xF8,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0x0F   // reserved clusters 0 & 1
    00995   ,0xFF,0xFF,0xFF,0x0F                       // reserved clusters 2 for root directory
    00996    };
    00998
    00999
    01005 Bool  fat_initialize_fat( void )
    01006 {
    01007    // Init and reset the internal cache at the memory beginning
    01008    fs_gu32_addrsector = fs_g_nav.u32_ptr_fat;
    01009    if( !fat_cache_read_sector( FALSE ))
    01010       return FALSE;
    01011    fat_cache_mark_sector_as_dirty();
    01012
    01013    if( Is_fat32 )
    01014    {
    01015       memcpy_code2ram( fs_g_sector, const_header_fat32, sizeof(const_header_fat32) );
    01016    }
    01017    if( Is_fat16 )
    01018    {
    01019       memcpy_code2ram( fs_g_sector, const_header_fat16, sizeof(const_header_fat16) );
    01020    }
    01021    if( Is_fat12 )
    01022    {
    01023       memcpy_code2ram( fs_g_sector, const_header_fat12, sizeof(const_header_fat12) );
    01024    }
    01025
    01026    // Copy the first sector of FAT 1 in the first sector of FAT 2
    01027    fs_gu32_addrsector = fs_g_nav.u32_ptr_fat + fs_g_nav.u16_fat_size;
    01028    if( !fat_cache_read_sector( FALSE ))
    01029       return FALSE;
    01030    fat_cache_mark_sector_as_dirty();
    01031    return TRUE;
    01032 }
    01033
    01034
    01043 Bool  fat_serialnumber( Bool b_action , U8 _MEM_TYPE_SLOW_ *a_u8_sn )
    01044 {
    01045    // Compute PBR address
    01046    if ( Is_fat12 || Is_fat16 )
    01047    {  // FAT 12 & 16 (BPB_ResvSecCnt must be ega to 1)
    01048       fs_gu32_addrsector = fs_g_nav.u32_ptr_fat-1;
    01049    }
    01050    else
    01051    {  // FAT 32 (BPB_ResvSecCnt must be ega to 32)
    01052       fs_gu32_addrsector = fs_g_nav.u32_ptr_fat-32;
    01053    }
    01054    // Read PBR
    01055    if( !fat_cache_read_sector( TRUE ))
    01056       return FALSE;
    01057
    01058    // The serial is storaged at invert
    01059    if( b_action == FS_SN_READ )
    01060    {
    01061       // Read serial number
    01062       a_u8_sn[0] = fs_g_sector[42];
    01063       a_u8_sn[1] = fs_g_sector[41];
    01064       a_u8_sn[2] = fs_g_sector[40];
    01065       a_u8_sn[3] = fs_g_sector[39];
    01066       return TRUE;
    01067    }else{
    01068       // Write serial number
    01069       fs_g_sector[42] = a_u8_sn[0];
    01070       fs_g_sector[41] = a_u8_sn[1];
    01071       fs_g_sector[40] = a_u8_sn[2];
    01072       fs_g_sector[39] = a_u8_sn[3];
    01073       fat_cache_mark_sector_as_dirty();
    01074       return fat_cache_flush();
    01075    }
    01076 }
    01077
    01078
    01087 Bool  fat_entry_label( Bool b_action , FS_STRING sz_label )
    01088 {
    01089    PTR_CACHE ptr_entry;
    01090    U8 u8_pos_name;
    01091    U8 u8_char;
    01092
    01093    ptr_entry = fat_get_ptr_entry();
    01094
    01095    if( FS_LABEL_READ == b_action)
    01096    {
    01097       if( FS_ENTRY_END == ptr_entry[0] )           // end of directory
    01098       {
    01099          fs_g_status = FS_ERR_ENTRY_EMPTY;
    01100          return FALSE;
    01101       }
    01102       if( FS_ATTR_VOLUME_ID != ptr_entry[11])      // no system label
    01103       {
    01104          fs_g_status = FS_ERR_ENTRY_BAD;
    01105          return FALSE;
    01106       }
    01107       if( NULL == sz_label )
    01108          return TRUE;
    01109       for( u8_pos_name=0; u8_pos_name<11; u8_pos_name++ )
    01110       {
    01111          u8_char = *ptr_entry;
    01112          if( 0x20 == u8_char )
    01113             u8_char = 0;
    01114          *sz_label = u8_char;
    01115          if( 0 == u8_char )
    01116             return TRUE;                           // Label readed
    01117          ptr_entry++;
    01118          sz_label++;
    01119       }
    01120       *sz_label = 0;
    01121       return TRUE;
    01122    }
    01123
    01124    if( FS_LABEL_WRITE == b_action)
    01125    {
    01126       // Autorize to write the label only on an empty entry or the system label entry
    01127       if( FS_ENTRY_END != ptr_entry[0] )           // end of directory
    01128       {
    01129          if( FS_ATTR_VOLUME_ID != ptr_entry[11])   // no system label
    01130          {
    01131             fs_g_status = FS_ERR_ENTRY_BAD;
    01132             return FALSE;
    01133          }
    01134       }
    01135       if( 0 == *sz_label )
    01136       {
    01137          fs_g_status = FS_ERR_NAME_INCORRECT;
    01138          return FALSE;
    01139       }
    01140       ptr_entry[11] = FS_ATTR_VOLUME_ID;
    01141       for( u8_pos_name=0; u8_pos_name<11; u8_pos_name++ )
    01142       {
    01143          u8_char = *sz_label;
    01144          if( ('a'<=u8_char) && (u8_char<='z') )
    01145          {
    01146             u8_char -= ('a'-'A');                  // Change to upper case
    01147          }
    01148          if( 0 == u8_char )
    01149          {
    01150             u8_char = 0x20;
    01151          }
    01152          *ptr_entry = u8_char;
    01153          ptr_entry++;
    01154          if( 0x20 == u8_char )
    01155             continue;
    01156          sz_label++;
    01157       }
    01158       fat_cache_mark_sector_as_dirty();
    01159       return fat_cache_flush();
    01160    }
    01161    return FALSE;                                   // To delete the compilation warning
    01162 }
    01163 #endif  // FS_LEVEL_FEATURES
    01164
    01165
    01166 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    01180 Bool  fat_initialize_dir( void )
    01181 {
    01182    U8 u8_i;
    01183
    01184    // Clear the cluster corresponding at directory
    01185    if( !fat_clear_cluster())
    01186       return FALSE;
    01187    fat_cache_mark_sector_as_dirty();
    01188    // here, the internal cache is the first sector of the cluster
    01189
    01190    // Create the dot "." entry, this one is a directory that points to itself
    01191    fs_g_sector[0]='.';
    01192    for( u8_i=1 ; u8_i<11 ; u8_i++ )
    01193       fs_g_sector[u8_i]=' ';
    01194    fs_g_sector[11]=FS_ATTR_DIRECTORY;
    01195    fs_g_sector[26]= LSB0( fs_g_nav_entry.u32_cluster );
    01196    fs_g_sector[27]= LSB1( fs_g_nav_entry.u32_cluster );
    01197    fs_g_sector[20]= LSB2( fs_g_nav_entry.u32_cluster );
    01198    fs_g_sector[21]= LSB3( fs_g_nav_entry.u32_cluster );
    01199    // Create the dotdot ".." entry, this one points to the starting cluster of the parent directory
    01200    fs_g_sector[FS_SIZE_FILE_ENTRY+0]='.';
    01201    fs_g_sector[FS_SIZE_FILE_ENTRY+1]='.';
    01202    for( u8_i=2 ; u8_i<11 ; u8_i++ )
    01203       fs_g_sector[FS_SIZE_FILE_ENTRY+u8_i]=' ';
    01204    fs_g_sector[FS_SIZE_FILE_ENTRY+11]=FS_ATTR_DIRECTORY;
    01205    fs_g_sector[FS_SIZE_FILE_ENTRY+26]= LSB0( fs_g_nav.u32_cluster_sel_dir );
    01206    fs_g_sector[FS_SIZE_FILE_ENTRY+27]= LSB1( fs_g_nav.u32_cluster_sel_dir );
    01207    fs_g_sector[FS_SIZE_FILE_ENTRY+20]= LSB2( fs_g_nav.u32_cluster_sel_dir );
    01208    fs_g_sector[FS_SIZE_FILE_ENTRY+21]= LSB3( fs_g_nav.u32_cluster_sel_dir );
    01209
    01210    return TRUE;
    01211 }
    01212 #endif  // FS_LEVEL_FEATURES
    01213
    01214
    01221 void  fat_get_date( FS_STRING sz_date , Bool type_date )
    01222 {
    01223    PTR_CACHE ptr_entry;
    01224
    01225    ptr_entry = fat_get_ptr_entry();
    01226    if( FS_DATE_LAST_WRITE == type_date )
    01227    {
    01228       fat_translatedate_number_to_ascii( sz_date , &ptr_entry[22] , FALSE );
    01229    }
    01230    else
    01231    {
    01232       fat_translatedate_number_to_ascii( sz_date , &ptr_entry[13] , TRUE );
    01233    }
    01234 }
    01235
    01236
    01244 void  fat_translatedate_number_to_ascii( FS_STRING sz_date , PTR_CACHE ptr_date , Bool enable_ms )
    01245 {
    01246    FS_STRING ptr_string_date;
    01247    U8 u8_i;
    01248    U8 msb_date, lsb_date, msb_time, lsb_time, u8_ms = 0;
    01249
    01250    // Read entry value of date and time
    01251    if( enable_ms )
    01252    {
    01253       u8_ms = *ptr_date;
    01254       ptr_date++;
    01255    }
    01256    lsb_time = *ptr_date;
    01257    ptr_date++;
    01258    msb_time = *ptr_date;
    01259    ptr_date++;
    01260    lsb_date = *ptr_date;
    01261    ptr_date++;
    01262    msb_date = *ptr_date;
    01263
    01264    // Initialise the string with "1980000000000000" (Year = 1980 and other at 0)
    01265    ptr_string_date = sz_date;
    01266    *ptr_string_date = '1';
    01267    ptr_string_date++;
    01268    *ptr_string_date = '9';
    01269    ptr_string_date++;
    01270    *ptr_string_date = '8';
    01271    ptr_string_date++;
    01272    for( u8_i=(15-2) ; u8_i!=0 ; u8_i-- )
    01273    {
    01274       *ptr_string_date = '0';
    01275       ptr_string_date++;
    01276    }
    01277
    01278    // Get the year
    01279    fat_translate_number_to_ascii( sz_date, 4 , msb_date>>1 );
    01280
    01281    // Get the month
    01282    fat_translate_number_to_ascii( &sz_date[4] , 2 , ((msb_date & 0x01)<<3) + (lsb_date>>5) );
    01283
    01284    // Get the day
    01285    fat_translate_number_to_ascii( &sz_date[6] , 2 , lsb_date & 0x1F );
    01286
    01287    // Get the hour
    01288    fat_translate_number_to_ascii( &sz_date[8] , 2 , msb_time >> (11-8) );
    01289
    01290    // Get the minute
    01291    fat_translate_number_to_ascii( &sz_date[10] , 2 , ((msb_time & 0x07)<<3) + (lsb_time>>5) );
    01292
    01293    // Get the seconde
    01294    fat_translate_number_to_ascii( &sz_date[12] , 2 , (lsb_time & 0x1F)<<1 );
    01295    if( 99 < u8_ms )
    01296    {
    01297      // Add one seconde
    01298      fat_translate_number_to_ascii( &sz_date[12] , 2 , 1 );
    01299      u8_ms -= 100;
    01300    }
    01301
    01302    // Get the miliseconde
    01303    fat_translate_number_to_ascii( &sz_date[14] , 2 , u8_ms );
    01304 }
    01305
    01306
    01317 void  fat_translate_number_to_ascii( FS_STRING sz_ascii_number, U8 u8_size_number_ascii, U8 u8_nb_increment )
    01318 {
    01319    FS_STRING ptr_sz_ascii_number;
    01320
    01321    u8_size_number_ascii--;
    01322
    01323    for( ; u8_nb_increment != 0 ; u8_nb_increment-- )
    01324    {
    01325       ptr_sz_ascii_number = sz_ascii_number + u8_size_number_ascii;
    01326       ptr_sz_ascii_number[0]++;
    01327       while( ('9'+1) == *ptr_sz_ascii_number )
    01328       {
    01329          *ptr_sz_ascii_number = '0';
    01330          ptr_sz_ascii_number--;
    01331          ptr_sz_ascii_number[0]++;
    01332       }
    01333    }
    01334 }
    01335
    01336
    01337 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET))
    01348 void  fat_set_date( const FS_STRING sz_date , Bool type_date )
    01349 {
    01350    PTR_CACHE ptr_entry;
    01351
    01352    fat_cache_mark_sector_as_dirty();
    01353    ptr_entry = fat_get_ptr_entry();
    01354
    01355    if( FS_DATE_LAST_WRITE == type_date )
    01356    {
    01357       fat_translatedate_ascii_to_number( sz_date , &ptr_entry[22] , FALSE );
    01358    }
    01359    else
    01360    {
    01361       fat_translatedate_ascii_to_number( sz_date , &ptr_entry[13] , TRUE );
    01362    }
    01363 }
    01364
    01365
    01377 void  fat_translatedate_ascii_to_number( const FS_STRING sz_date , PTR_CACHE ptr_date , Bool enable_ms )
    01378 {
    01379    U8 u8_tmp;
    01380    U8 msb_date, lsb_date, msb_time, lsb_time;
    01381
    01382    // Set the year
    01383    msb_date  = ((U8)(fat_translate_ascii_to_number( sz_date , 4 )-1980))<<1;
    01384
    01385    // Set the month
    01386    u8_tmp    = (U8)fat_translate_ascii_to_number( &sz_date[4] , 2 );
    01387    msb_date |= (u8_tmp >> 3);
    01388    lsb_date  = (u8_tmp << 5);
    01389
    01390    // Set the day
    01391    lsb_date |= (U8)fat_translate_ascii_to_number( &sz_date[6] , 2 );
    01392
    01393    // Set the hour
    01394    msb_time  = ((U8)fat_translate_ascii_to_number( &sz_date[8] , 2 )) << (11-8);
    01395
    01396    // Set the minute
    01397    u8_tmp    = (U8)fat_translate_ascii_to_number( &sz_date[10] , 2 );
    01398    msb_time |= (u8_tmp >> 3);
    01399    lsb_time  = (u8_tmp << 5);
    01400
    01401    // Set the seconde
    01402    u8_tmp    = (U8)fat_translate_ascii_to_number( &sz_date[12] , 2 );
    01403    lsb_time |= (u8_tmp >> 1);
    01404
    01405    // Set the miliseconde
    01406    if( enable_ms )
    01407    {
    01408       // check if the seconde time is %2
    01409       if( u8_tmp & 0x01 )
    01410       {  // it isn't %2
    01411          u8_tmp = 100;  // add one seconde
    01412       }
    01413       else
    01414       {
    01415          u8_tmp = 0;    // no more seconde
    01416       }
    01417       *ptr_date = u8_tmp + (U8)fat_translate_ascii_to_number( &sz_date[14] , 2 );
    01418       ptr_date++;
    01419    }
    01420
    01421    // Record value
    01422    ptr_date[0] = lsb_time;
    01423    ptr_date[1] = msb_time;
    01424    ptr_date[2] = lsb_date;
    01425    ptr_date[3] = msb_date;
    01426 }
    01427
    01428
    01440 U16   fat_translate_ascii_to_number( const FS_STRING sz_ascii_number, U8 u8_size_number_ascii  )
    01441 {
    01442    U8 sz_ascii_number_copy[4];
    01443    U8 _MEM_TYPE_FAST_ *ptr_sz_ascii_number;
    01444    U8 u8_i;
    01445    U16 u16_number;
    01446
    01447    for( u8_i=0; u8_i < u8_size_number_ascii; u8_i++ )
    01448    {
    01449       sz_ascii_number_copy[u8_i] = sz_ascii_number[u8_i];
    01450    }
    01451
    01452    u16_number=0;
    01453
    01454    while( 1 )
    01455    {
    01456       // Check if it is the end of ascii number (= "0...0")
    01457       ptr_sz_ascii_number = sz_ascii_number_copy;
    01458       for( u8_i = u8_size_number_ascii; u8_i !=0; u8_i-- )
    01459       {
    01460          if( '0' != *ptr_sz_ascii_number )
    01461          {
    01462             break;
    01463          }
    01464          ptr_sz_ascii_number++;
    01465       }
    01466       if( 0 == u8_i)
    01467          return u16_number;
    01468
    01469       // Decrement the number
    01470       ptr_sz_ascii_number = sz_ascii_number_copy + u8_size_number_ascii -1;
    01471       u16_number++;
    01472       ptr_sz_ascii_number[0]--;
    01473       while( ('0'-1) == ptr_sz_ascii_number[0] )
    01474       {
    01475          *ptr_sz_ascii_number = '9';
    01476          ptr_sz_ascii_number--;
    01477          ptr_sz_ascii_number[0]--;
    01478       }
    01479    }
    01480 }
    01481 #endif  // FS_LEVEL_FEATURES
    01482
    01483
    01484
    01485 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    01499 Bool  fat_create_entry_file_name( FS_STRING sz_name )
    01500 {
    01501    U8 u8_i, u8_nb;
    01502    U8 u8_crc, u8_nb_entry;
    01503
    01504    // Compute the number of entry for this name
    01505    u8_nb_entry = fat_check_name( sz_name  );
    01506    if( 0 == u8_nb_entry )
    01507       return FALSE;
    01508
    01509    // Search a unik short entry
    01510    u8_nb = fat_find_short_entry_name( sz_name  );
    01511    if( 0 == u8_nb )
    01512    {
    01513       fs_g_status = FS_ERR_FILE_EXIST;
    01514       return FALSE;  // All short name exist
    01515    }
    01516
    01517    // Alloc a space for entrys
    01518    if( !fat_alloc_entry_free( u8_nb_entry ))
    01519       return FALSE;
    01520    // Remark: here the pointer of entry is on the last free entry of new space allocated
    01521
    01522    // Add short name entry
    01523    u8_crc = fat_create_short_entry_name( sz_name , 0 , u8_nb, FALSE  );
    01524    u8_nb_entry--;
    01525
    01526    // For each long name entry
    01527    for( u8_i=1 ; u8_i<=u8_nb_entry ; u8_i++ )
    01528    {
    01529       // Go to previous entry
    01530       fs_g_nav_fast.u16_entry_pos_sel_file--;
    01531       if( !fat_read_dir())
    01532          return FALSE;
    01533       // Write a long name entry
    01534       if( u8_i == u8_nb_entry )
    01535       {
    01536          u8_i += FS_ENTRY_LFN_LAST;
    01537       }
    01538       fat_create_long_name_entry( sz_name , u8_crc , u8_i );
    01539       sz_name += FS_SIZE_LFN_ENTRY*(Is_unicode? 2 : 1 );
    01540   }
    01541   // Go back to the short name entry
    01542   fs_g_nav_fast.u16_entry_pos_sel_file += u8_nb_entry;
    01543   return TRUE;
    01544 }
    01545
    01546
    01557 void  fat_create_long_name_entry( FS_STRING sz_name , U8 u8_crc , U8 u8_id  )
    01558 {
    01559    PTR_CACHE ptr_entry;
    01560    Bool b_end_of_name = FALSE;
    01561
    01562    fat_cache_mark_sector_as_dirty();
    01563    ptr_entry = fat_get_ptr_entry();
    01564    *ptr_entry = u8_id;
    01565    ptr_entry++;   // The long name start at offset 1 of the entry file
    01566
    01567    for( u8_id=1; u8_id<FS_SIZE_FILE_ENTRY ; u8_id++ , ptr_entry++ )
    01568    {
    01569       // fields with no character
    01570       if( 11 == u8_id)
    01571       {
    01572          *ptr_entry = FS_ATTR_LFN_ENTRY;  // attribut field
    01573          continue;
    01574       }
    01575       if( (12 == u8_id)
    01576       ||  (26 == u8_id)
    01577       ||  (27 == u8_id) )
    01578       {
    01579          // Reserved field
    01580          // *ptr_entry = 0x00;            // No necessary because the cache must be clean
    01581          continue;
    01582       }
    01583       if( 13 == u8_id)
    01584       {
    01585          *ptr_entry = u8_crc;             // CRC field
    01586          continue;
    01587       }
    01588
    01589       // fields with a character
    01590       if( !b_end_of_name )
    01591       {
    01592          U16 u16_tmp;
    01593          if( Is_unicode )
    01594          {
    01595             u16_tmp = ((FS_STR_UNICODE)sz_name)[0];
    01596          }else{
    01597             u16_tmp = sz_name[0];
    01598          }
    01599          if(('\\' == u16_tmp )
    01600          || ('/'  == u16_tmp ) )
    01601          {  // end of name
    01602             u16_tmp = 0;                  // Set a end of name flag
    01603          }
    01604          if( 0 == u16_tmp )
    01605          {
    01606             b_end_of_name = TRUE;
    01607          }
    01608          *ptr_entry = LSB(u16_tmp);
    01609          ptr_entry++;
    01610          *ptr_entry = MSB(u16_tmp);
    01611          u8_id++;
    01612          sz_name += (Is_unicode? 2 : 1 );
    01613       }
    01614       else
    01615       {  // end of name
    01616          *ptr_entry = 0xFF;               // Padding mandatory
    01617       }
    01618    } // end of loop
    01619 }
    01620
    01621
    01632 U8    fat_create_short_entry_name( FS_STRING sz_name , FS_STRING short_name , U8 nb , Bool mode  )
    01633 {
    01634    PTR_CACHE ptr_entry = 0;
    01635    U8 u8_i, u8_step, character;
    01636    U8 crc;
    01637    U8 nb_digit;
    01638
    01639    if( !mode )
    01640    {
    01641       // Modify internal cache to create short name entry in the current entry
    01642       fat_cache_mark_sector_as_dirty();
    01643       // Get pointer on current entry
    01644       ptr_entry = fat_get_ptr_entry();
    01645    }
    01646
    01647    // Compute the digit number
    01648    if( nb < 10 )        nb_digit = 1;
    01649    else if( nb < 100 )  nb_digit = 2;
    01650    else                 nb_digit = 3;
    01651
    01652    crc = u8_i = 0;
    01653    u8_step = 1;
    01654    while( 1 )
    01655    {
    01656       if( Is_unicode )
    01657       {
    01658          character = ((FS_STR_UNICODE)sz_name)[0];
    01659       }else{
    01660          character = sz_name[0];
    01661       }
    01662
    01663       if( 1 == u8_step )
    01664       {  // step 1 = translate the name
    01665          if( ((FS_SIZE_SFNAME_WITHOUT_EXT-(1+nb_digit)) == u8_i)    // name field is full (-2 for "~1")
    01666          ||  ('.'    == character)                       // is the end of name without extension
    01667          ||  fat_check_eof_name(character)            )  // is the end of name
    01668          {
    01669             u8_step++;                                   // go to next step
    01670             continue;
    01671          }
    01672       }
    01673       if( 8 == u8_step )
    01674       {  // step 8 = translate the extension
    01675          if( (u8_i == FS_SIZE_SFNAME)                    // name field is full
    01676          ||  fat_check_eof_name(character)            )  // is the end of name
    01677          {
    01678             u8_step++;                                   // go to next step
    01679             continue;
    01680          }
    01681       }
    01682       if( (1==u8_step) || (8==u8_step) )
    01683       {  // steps to translate name
    01684          character = fat_translate_char_shortname( character );
    01685          sz_name += (Is_unicode? 2 : 1 );
    01686          if( 0 == character )
    01687          {
    01688             continue;                                    // Bad character, ignore this one
    01689          }
    01690       }
    01691       if( 7 == u8_step )
    01692       {  // step 5 = find character '.'
    01693          if( ('.'    == character)                       // is the end of name without extension
    01694          ||  fat_check_eof_name(character)            )  // is the end of name
    01695          {
    01696             u8_step++;                                   // go to next step
    01697          } else {
    01698             sz_name += (Is_unicode? 2 : 1 );
    01699          }
    01700          continue;                                       // this step don't add a character in the short name
    01701       }
    01702       if( 6 == u8_step )
    01703       {  // step 4 = add padding
    01704          if( u8_i == FS_SIZE_SFNAME_WITHOUT_EXT )        // end of field name without extension
    01705          {
    01706             u8_step++;                                   // go to next step
    01707             continue;
    01708          }
    01709          character = ' ';
    01710       }
    01711       if( 9 == u8_step )
    01712       {  // step 7 = add padding in extension name
    01713          if( u8_i == FS_SIZE_SFNAME )                    // end of field name with extension
    01714          {
    01715             break;                                       // end of loop while(1)
    01716          }
    01717          character = ' ';
    01718       }
    01719       if( 5 == u8_step )
    01720       {  // step 4 = add unit 1 of number
    01721          character = '0'+(nb%10);
    01722          u8_step++;                                      // go to next step
    01723       }
    01724       if( 4 == u8_step )
    01725       {  // step 3 = add unit 10 of number
    01726          character = '0'+((nb%100)/10);
    01727          u8_step++;                                      // go to next step
    01728       }
    01729       if( 3 == u8_step )
    01730       {  // step 2 = add unit 100 of number
    01731          character = '0'+(nb/100);
    01732          u8_step++;                                      // go to next step
    01733       }
    01734       if( 2 == u8_step )
    01735       {  // step 2 = add character '~'
    01736          character = '~';
    01737          u8_step+=(4-nb_digit);                          // go to next step
    01738       }
    01739
    01740       if( mode )
    01741       {
    01742          // Record the short name in buffer
    01743          *short_name = character;
    01744          short_name++;
    01745       }else{
    01746          // Record the character in short entry file
    01747          *ptr_entry = character;
    01748          ptr_entry++;
    01749       }
    01750       u8_i++;
    01751
    01752       // Compute the CRC of the short name
    01753       crc = (crc >> 1) + ((crc & 1) << 7);               // rotate
    01754       crc += character;                                  // add next char
    01755    } // End of loop while
    01756    return crc;
    01757 }
    01758
    01759
    01767 U8    fat_find_short_entry_name( FS_STRING sz_name  )
    01768 {
    01769    char _MEM_TYPE_SLOW_ short_name[11];
    01770    U8 u8_nb;
    01771
    01772    u8_nb = 0;
    01773    while(1)
    01774    {
    01775       if( 0xFF == u8_nb )
    01776          return 0;                                       // All short name exist
    01777
    01778       u8_nb++;                                           // Try next short name
    01779       fat_create_short_entry_name( sz_name , short_name , u8_nb , TRUE  ); // Compute the short name
    01780       fs_g_nav_fast.u16_entry_pos_sel_file = 0;          // Go to beginning of directory
    01781       // Scan directory to find a short entry
    01782       while(1)
    01783       {
    01784          if ( !fat_read_dir())                           // Read directory
    01785          {
    01786             if( FS_ERR_OUT_LIST == fs_g_status )
    01787                return u8_nb;                             // short name don't exist, then good number
    01788             return 0;                                    // System or Disk Error
    01789          }
    01790          if( fat_entry_shortname_compare( short_name ) ) // Check entry
    01791             break;                                       // Short name exist
    01792          if( FS_ERR_ENTRY_EMPTY == fs_g_status )
    01793             return u8_nb;                                // Short name don't exist, then good number
    01794          fs_g_nav_fast.u16_entry_pos_sel_file++;         // Go to next entry
    01795       }
    01796    }
    01797 }
    01798
    01799
    01807 Bool  fat_entry_shortname_compare( FS_STRING short_name )
    01808 {
    01809    PTR_CACHE ptr_entry;
    01810
    01811    ptr_entry = fat_get_ptr_entry();
    01812    if( FS_ENTRY_END == *ptr_entry )             // end of directory
    01813    {
    01814       fs_g_status = FS_ERR_ENTRY_EMPTY;
    01815       return FALSE;
    01816    }
    01817    if( (FS_ENTRY_DEL == *ptr_entry )            // deleted entry
    01818    ||  (FS_ATTR_LFN_ENTRY == ptr_entry[11]) )   // long file name
    01819    {
    01820       fs_g_status = FS_ERR_ENTRY_BAD;
    01821       return FALSE;
    01822    }
    01823    fs_g_status = FS_ERR_ENTRY_BAD;              // by default this entry is different then bad
    01824    return (0==memcmp_ram2ram(ptr_entry , short_name , 8+3 ));
    01825 }
    01826
    01828 _CONST_TYPE_ U8 fs_s_tab_incorrect_char[]={':','*','?','"','<','>','|'};
    01829
    01837 U8    fat_check_name( FS_STRING sz_name  )
    01838 {
    01839    U8 u8_nb_entry, u8_i, u8_j;
    01840    U16 u16_character;
    01841
    01842    u8_nb_entry = 2;        // a short entry + one long name entry minimum
    01843    u8_i = FS_SIZE_LFN_ENTRY;
    01844    while( 1 )
    01845    {
    01846       if( Is_unicode )
    01847       {
    01848          u16_character = ((FS_STR_UNICODE)sz_name)[0];
    01849       }else{
    01850          u16_character = sz_name[0];
    01851       }
    01852       if( fat_check_eof_name( u16_character ) )
    01853          break;
    01854
    01855       for( u8_j = 0 ; u8_j < sizeof(fs_s_tab_incorrect_char) ; u8_j++ )
    01856       {
    01857          if( u16_character == fs_s_tab_incorrect_char[u8_j] )
    01858          {
    01859             fs_g_status = FS_ERR_INCORRECT_NAME;
    01860             return 0;      // incorrect character
    01861          }
    01862       }
    01863       if( 0 == u8_i )
    01864       {
    01865          u8_nb_entry++;
    01866          u8_i = FS_SIZE_LFN_ENTRY;
    01867       }
    01868       u8_i--;
    01869       sz_name += (Is_unicode? 2 : 1 );
    01870    }
    01871    if( 0x14 < u8_nb_entry )
    01872    {
    01873       fs_g_status = FS_ERR_NAME_TOO_LARGE;
    01874       return 0;            // Name too large
    01875    }
    01876    return u8_nb_entry;
    01877 }
    01878
    01879
    01881 _CONST_TYPE_ U8 fs_s_execption_char[]={'+',',','.',';','=','[',']'};
    01882
    01890 U8    fat_translate_char_shortname( U8 character )
    01891 {
    01892    U8 u8_j;
    01893
    01894    if( (character<=' ') || ('~'<character) )
    01895       return 0;
    01896    if( ('a'<=character) && (character<='z') )
    01897    {
    01898       return (character - ('a'-'A'));  // Change to upper case
    01899    }
    01900    for( u8_j = 0 ; u8_j < sizeof(fs_s_execption_char) ; u8_j++ )
    01901    {
    01902       if( character == fs_s_execption_char[u8_j] )
    01903          return 0;
    01904    }
    01905    return character;
    01906 }
    01907
    01908
    01920 Bool  fat_alloc_entry_free( U8 u8_nb_entry )
    01921 {
    01922    PTR_CACHE ptr_entry;
    01923    Bool b_garbage_collector_used = FALSE;
    01924    U8 u8_nb_entry_save;
    01925
    01926    u8_nb_entry_save = u8_nb_entry;
    01927
    01928    // Start at the beginning of dir
    01929    fs_g_nav_fast.u16_entry_pos_sel_file=0;
    01930    // Loop in directory
    01931    while( 1 )
    01932    {
    01933       // Fill internal cache with a sector from directory
    01934       if( !fat_read_dir() )
    01935       {
    01936          if( FS_ERR_OUT_LIST != fs_g_status )
    01937             return FALSE;
    01938
    01939          // The position is outside the cluster list
    01940          // then alloc a new sector (= new cluster)
    01941          // Remark: The fs_g_seg.u32_addr contains the last cluster value of a directory list to link with the new list
    01942          fs_g_seg.u32_size_or_pos = 1;
    01943          if( !fat_allocfreespace())
    01944          {
    01945             // Garbage collector on entry file
    01946             if( b_garbage_collector_used )
    01947                return FALSE;
    01948             if( !fat_garbage_collector_entry())
    01949                return FALSE;
    01950             b_garbage_collector_used = TRUE;
    01951             fs_g_nav_fast.u16_entry_pos_sel_file=0;
    01952             u8_nb_entry = u8_nb_entry_save;
    01953             continue;
    01954          }
    01955
    01956          // Clean this new cluster
    01957          // Remark: The fs_g_seg.u32_addr contains the new cluster value
    01958          if( !fat_clear_cluster())
    01959             return FALSE;
    01960
    01961          continue;  // Rescan the directory list to find the new allocated sector
    01962       }
    01963
    01964       // Check entry
    01965       ptr_entry = fat_get_ptr_entry();
    01966       if ( FS_ENTRY_END == *ptr_entry )
    01967       {  // The entry is free
    01968          u8_nb_entry--;
    01969          if( 0 == u8_nb_entry )
    01970          {
    01971             return TRUE;  // All free entry is found
    01972          }
    01973       }
    01974
    01975       // go to next entry
    01976       fs_g_nav_fast.u16_entry_pos_sel_file++;
    01977       if( 0 == fs_g_nav_fast.u16_entry_pos_sel_file )
    01978       {
    01979          // Here, the directory have the maximum size
    01980          // Garbage collector on entry file
    01981          if( b_garbage_collector_used )
    01982          {
    01983             // Directory full (FAT Norm limit directory to 65535 entrys)
    01984             fs_g_status = FS_ERR_NO_FREE_SPACE;
    01985             return FALSE;
    01986          }
    01987          if( !fat_garbage_collector_entry())
    01988             return FALSE;
    01989          b_garbage_collector_used = TRUE;
    01990          fs_g_nav_fast.u16_entry_pos_sel_file=0;
    01991          u8_nb_entry = u8_nb_entry_save;
    01992          continue;
    01993       }
    01994    }  // end of while(1)
    01995 }
    01996
    01997
    02003 Bool fat_garbage_collector_entry( void )
    02004 {
    02005    _MEM_TYPE_SLOW_   U8 entry[ FS_SIZE_FILE_ENTRY ];
    02006    PTR_CACHE ptr_entry;
    02007    U16 u16_pos_old = 0;
    02008    U16 u16_pos_new = 0;
    02009
    02010    // Loop in directory
    02011    while( 1 )
    02012    {
    02013       // Go to old entry list
    02014       fs_g_nav_fast.u16_entry_pos_sel_file=u16_pos_old;
    02015       // Fill internal cache with a sector from directory
    02016       if( !fat_read_dir() )
    02017       {
    02018          if( FS_ERR_OUT_LIST != fs_g_status )
    02019             return FALSE;
    02020          goto fat_garbage_collector_entry_endofdir;
    02021       }
    02022
    02023       // Check entry
    02024       ptr_entry = fat_get_ptr_entry();
    02025
    02026       if ( FS_ENTRY_END == *ptr_entry )
    02027       {
    02028          // The entry is free, then it is the end of entry list
    02029 fat_garbage_collector_entry_endofdir:
    02030          // Fill empty entry in old list
    02031          fs_g_nav_fast.u16_entry_pos_sel_file=u16_pos_new;
    02032          while( fs_g_nav_fast.u16_entry_pos_sel_file != u16_pos_old )
    02033          {
    02034             // Fill internal cache with a sector from directory
    02035             if( !fat_read_dir() )
    02036                return FALSE;
    02037             memset( fat_get_ptr_entry() , 0 , 32 );
    02038             fat_cache_mark_sector_as_dirty();
    02039             fs_g_nav_fast.u16_entry_pos_sel_file++;
    02040          }
    02041          return TRUE;  // End of garbage
    02042       }
    02043
    02044       if ( FS_ENTRY_DEL != *ptr_entry )
    02045       {
    02046          // entry valid
    02047          if( u16_pos_old != u16_pos_new )
    02048          {
    02049             // A free space exist then move entry
    02050             memcpy_ram2ram( entry, ptr_entry, FS_SIZE_FILE_ENTRY );
    02051             fs_g_nav_fast.u16_entry_pos_sel_file=u16_pos_new;
    02052             // Fill internal cache with a sector from directory
    02053             if( !fat_read_dir() )
    02054                return FALSE;
    02055             memcpy_ram2ram( fat_get_ptr_entry(), entry, FS_SIZE_FILE_ENTRY );
    02056             fat_cache_mark_sector_as_dirty();
    02057          }
    02058          u16_pos_new++;
    02059       }
    02060       u16_pos_old++;
    02061    }  // end of while(1)
    02062 }
    02063
    02064
    02073 Bool  fat_delete_file( Bool b_cluster_list )
    02074 {
    02075    PTR_CACHE ptr_entry;
    02076    U8 u8_tmp;
    02077    Bool b_short_del = FALSE;
    02078
    02079    // loop in directory
    02080    while( 1 )
    02081    {
    02082       // Fill internal cache with a sector from directory
    02083       if( !fat_read_dir() )
    02084          return FALSE;
    02085
    02086       // Get pointer on the current entry
    02087       ptr_entry = fat_get_ptr_entry();
    02088       u8_tmp = ptr_entry[0];
    02089
    02090       if( (FS_ATTR_LFN_ENTRY != ptr_entry[11])
    02091       &&  (b_short_del) )
    02092       {
    02093          // no long entry exist, then only a short entry to delete
    02094          break;   // Go to delete cluster list
    02095       }
    02096
    02097       // Delete entry
    02098       b_short_del = TRUE;
    02099       ptr_entry[0] = FS_ENTRY_DEL;
    02100       fat_cache_mark_sector_as_dirty();
    02101
    02102       if( (FS_ATTR_LFN_ENTRY == ptr_entry[11])
    02103       &&  ( 0 != (FS_ENTRY_LFN_LAST & u8_tmp)) )
    02104       {
    02105          // It is the last entry of long name
    02106          break;   // Go to delete cluster list
    02107       }
    02108
    02109       // Go to previous entry
    02110       fs_g_nav_fast.u16_entry_pos_sel_file--;
    02111    }  // end of while(1)
    02112
    02113    if( b_cluster_list )
    02114    {
    02115       // Delete cluster list
    02116       fs_g_nav_entry.u32_pos_in_file=0;      // Delete ALL list (start at begining)
    02117       if( !fat_read_file( FS_CLUST_ACT_CLR ))
    02118          return FALSE;
    02119    }
    02120
    02121    return TRUE;
    02122 }
    02123 #endif  // FS_LEVEL_FEATURES
    02124
    02125
    02126
    02132 U32   fat_getfreespace( void )
    02133 {
    02134    U32 u32_nb_free_cluster = 0;
    02135
    02136    // Read ALL FAT1
    02137    fs_g_cluster.u32_pos = 2;
    02138
    02139    if( Is_fat12 )
    02140    {  // FAT12 only
    02141       for(
    02142       ;     fs_g_cluster.u32_pos < fs_g_nav.u32_CountofCluster
    02143       ;     fs_g_cluster.u32_pos++ )
    02144       {
    02145          // Get the value of the cluster
    02146          if ( !fat_cluster_val( FS_CLUST_VAL_READ ) )
    02147             return 0;
    02148
    02149          if ( 0 == fs_g_cluster.u32_val )
    02150             u32_nb_free_cluster++;
    02151       }
    02152    }
    02153    else
    02154    {
    02155       if( Is_fat32 )
    02156       {
    02157          u32_nb_free_cluster = fat_read_fat32_FSInfo();
    02158          if( 0xFFFFFFFF != u32_nb_free_cluster )
    02159             goto endof_fat_getfreespace;
    02160          u32_nb_free_cluster = 0;
    02161       }
    02162       // Speed optimization only for FAT16 and FAT32
    02163       // init first value used by fat_cluster_readnext()
    02164       if( !fat_cluster_val( FS_CLUST_VAL_READ ))
    02165          return FALSE;
    02166       for(
    02167       ;     fs_g_cluster.u32_pos < fs_g_nav.u32_CountofCluster
    02168       ;     fs_g_cluster.u32_pos++ )
    02169       {
    02170          if ( 0 == fs_g_cluster.u32_val )
    02171             u32_nb_free_cluster++;
    02172          if( !fat_cluster_readnext() )
    02173             return FALSE;
    02174       }
    02175 #if (FSFEATURE_WRITE_COMPLET == (FS_LEVEL_FEATURES & FSFEATURE_WRITE_COMPLET) )
    02176       if( Is_fat32 )
    02177       {
    02178          // Save value for the future call
    02179          fat_write_fat32_FSInfo( u32_nb_free_cluster );
    02180       }
    02181 #endif
    02182    }
    02183 endof_fat_getfreespace:
    02184    return (u32_nb_free_cluster * fs_g_nav.u8_BPB_SecPerClus);
    02185 }
    02186
    02187
    02197 U8    fat_getfreespace_percent( void )
    02198 {
    02199    U32 u32_nb_free_cluster = 0;
    02200    U16 u16_tmp, u16_pos;
    02201
    02202    if( Is_fat12 )
    02203    {  // No speed optimization necessary on FAT12
    02204       return (((fat_getfreespace()/fs_g_nav.u8_BPB_SecPerClus)*100) / fs_g_nav.u32_CountofCluster);
    02205    }
    02206
    02207
    02208    fs_g_cluster.u32_pos = 2;
    02209    // Init first value used by fat_cluster_readnext()
    02210    if( !fat_cluster_val( FS_CLUST_VAL_READ ))
    02211       return FALSE;
    02212
    02213    // The optimization is to
    02214    // - read only the LSB byte of cluster
    02215    // - read only 1 cluster for 2 clusters
    02216    if( Is_fat32 )
    02217    {
    02218       u32_nb_free_cluster = fat_read_fat32_FSInfo();
    02219       if( 0xFFFFFFFF != u32_nb_free_cluster )
    02220          goto endof_fat_getfreespace_percent;
    02221       u32_nb_free_cluster = 0;
    02222
    02223       u16_pos = 2*4;
    02224       for(  u16_tmp = fs_g_nav.u16_fat_size
    02225       ;     u16_tmp!=0
    02226       ;     u16_tmp-- )
    02227       {
    02228          for( ; u16_pos < 512 ; u16_pos += (2*4) )
    02229          {
    02230             if( 0 == fs_g_sector[u16_pos] )
    02231                u32_nb_free_cluster+=2;
    02232          }
    02233          // Read next sector in FAT
    02234          u16_pos = 0;
    02235          fs_gu32_addrsector++;
    02236          if( !fat_cache_read_sector( TRUE ))
    02237             return 0;
    02238       }
    02239    }
    02240
    02241    if ( Is_fat16 )
    02242    {
    02243       u16_pos = 2*2;
    02244
    02245       for(  u16_tmp = fs_g_nav.u16_fat_size
    02246       ;     u16_tmp!=0
    02247       ;     u16_tmp-- )
    02248       {
    02249          for( ; u16_pos < 512 ; u16_pos += (2*2) )
    02250          {
    02251             if( 0 == fs_g_sector[u16_pos] )
    02252                u32_nb_free_cluster+=2;
    02253          }
    02254          // Read next sector in FAT
    02255          u16_pos = 0;
    02256          fs_gu32_addrsector++;
    02257          if( !fat_cache_read_sector( TRUE ))
    02258             return 0;
    02259       }
    02260    }
    02261
    02262    // Compute percent
    02263    if( u32_nb_free_cluster > fs_g_nav.u32_CountofCluster )
    02264       return 100;
    02265    if( u32_nb_free_cluster > ((fs_g_nav.u32_CountofCluster-u32_nb_free_cluster)/256) )
    02266    {
    02267       // Compute and add a delta error
    02268       u32_nb_free_cluster -= ((fs_g_nav.u32_CountofCluster-u32_nb_free_cluster)/256);
    02269    }
    02270 endof_fat_getfreespace_percent:
    02271    return ((u32_nb_free_cluster * 100) / fs_g_nav.u32_CountofCluster);
    02272 }
    02273
    02274
    02275
    02276 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    02293 Bool  fat_allocfreespace( void )
    02294 {
    02295    // Flag to signal the first step which search the first free cluster of the new list
    02296    Bool first_cluster_free_is_found = FALSE;
    02297    // If TRUE then use a quick procedure but don't scan all FAT else use a slow proceudre but scan all FAT
    02298    Bool b_quick_find = TRUE;
    02299
    02300    if( Is_fat32 )
    02301    {
    02302       // Clear info about free space
    02303       if( !fat_write_fat32_FSInfo( 0xFFFFFFFF ))
    02304          return FALSE;
    02305    }
    02306
    02307    if( 0xFF == MSB0(fs_g_seg.u32_addr) )
    02308    {
    02309 fat_allocfreespace_start:
    02310       // New cluster list, then research at the beginning of FAT
    02311       fs_g_cluster.u32_pos = 2;
    02312    }else{
    02313       // Continue the cluster list then start after the end of the cluster list
    02314       fs_g_cluster.u32_pos = fs_g_seg.u32_addr+1;
    02315    }
    02316
    02317    fat_clear_info_fat_mod();
    02318
    02319    // Read ALL FAT1
    02320    for(
    02321    ;     fs_g_cluster.u32_pos < fs_g_nav.u32_CountofCluster
    02322    ;     fs_g_cluster.u32_pos++ )
    02323    {
    02324       // Get the value of the cluster
    02325       if ( !fat_cluster_val( FS_CLUST_VAL_READ ) )
    02326          return FALSE;
    02327
    02328       if ( 0 == fs_g_cluster.u32_val )
    02329       {
    02330          // A free cluster is found
    02331          fs_g_cluster.u32_val = fs_g_cluster.u32_pos;    // value of the cluster is the new free cluster
    02332          if( TRUE == first_cluster_free_is_found )
    02333          {
    02334             // Link the new cluster with previous cluster
    02335             fs_g_cluster.u32_pos--;                      // select the previous cluster
    02336             if ( !fat_cluster_val( FS_CLUST_VAL_WRITE ) )
    02337                return FALSE;
    02338          }
    02339          else
    02340          {
    02341             // It is the first cluster of the new list
    02342             first_cluster_free_is_found = TRUE;
    02343
    02344             if( 0xFF != MSB0(fs_g_seg.u32_addr) )
    02345             {
    02346                // Link this new cluster with the current cluster list
    02347                // Select the last cluster of the current list
    02348                if( 0 == fs_g_seg.u32_addr )
    02349                {  // The current cluster list is the cluster list of root directory
    02350                   if( FS_TYPE_FAT_32 != fs_g_nav_fast.u8_type_fat )
    02351                   {
    02352                      // Impossible to increment ROOT DIR size of FAT12 or FAT16
    02353                      fs_g_status = FS_ERR_NO_FREE_SPACE;
    02354                      return FALSE;
    02355                   }
    02356                   fs_g_cluster.u32_pos = fs_g_nav.rootdir.u32_cluster;
    02357                }
    02358                else
    02359                {
    02360                   fs_g_cluster.u32_pos = fs_g_seg.u32_addr;
    02361                }
    02362                if ( !fat_cluster_val( FS_CLUST_VAL_WRITE ) )
    02363                   return FALSE;
    02364             }  // else no writing the first cluster value in FAT because no current cluster list
    02365             fs_g_seg.u32_addr = fs_g_cluster.u32_val;    // save the first cluster value
    02366          }
    02367
    02368          // At the new cluster position, set the flag end of list
    02369          fs_g_cluster.u32_pos = fs_g_cluster.u32_val;    // Select the new cluster
    02370          fs_g_cluster.u32_val = FS_CLUST_VAL_EOL;        // Cluster value is the flag end of list
    02371          if ( !fat_cluster_val( FS_CLUST_VAL_WRITE ) )
    02372             return FALSE;
    02373
    02374          // Compute the remaining sectors
    02375          if ( fs_g_seg.u32_size_or_pos <= fs_g_nav.u8_BPB_SecPerClus )
    02376          {
    02377             fs_g_seg.u32_size_or_pos = 0; // All space found
    02378             break;                        // Stop loop
    02379          }
    02380          fs_g_seg.u32_size_or_pos -= fs_g_nav.u8_BPB_SecPerClus;
    02381       }
    02382       else
    02383       {
    02384          // The next cluster is not free
    02385          if( TRUE == first_cluster_free_is_found )
    02386          {
    02387             // To have a segment memory continue, the cluster list must be continue
    02388             // then stop allocation
    02389             break;
    02390          }
    02391          else
    02392          {
    02393             // It is the first step to search the first free cluster
    02394             // then ignore this cluster no free and continue search
    02395             if( b_quick_find )
    02396             {
    02397                fs_g_cluster.u32_pos += 500;
    02398             }
    02399          }
    02400       }
    02401    }
    02402
    02403    // End of alloc
    02404    if( FALSE == first_cluster_free_is_found )
    02405    {
    02406       if( b_quick_find )
    02407       {
    02408          // Retry in normal mode to scann all FAT (= no quick mode)
    02409          b_quick_find = FALSE;
    02410          goto fat_allocfreespace_start;
    02411       }
    02412       fs_g_status = FS_ERR_NO_FREE_SPACE; // NO FREE CLUSTER FIND
    02413       return FALSE;
    02414    }
    02415
    02416    return fat_update_fat2();
    02417 }
    02418 #endif  // FS_LEVEL_FEATURES
    02419
    02420
    02421 #if (FS_LEVEL_FEATURES > FSFEATURE_READ)
    02424 void  fat_clear_info_fat_mod( void )
    02425 {
    02426    fs_g_u16_first_mod_fat = 0xFFFF;
    02427    fs_g_u16_last_mod_fat = 0;
    02428 }
    02429 #endif  // FS_LEVEL_FEATURES
    02430
    02431
    02432 #if (FS_LEVEL_FEATURES > FSFEATURE_READ)
    02438 Bool  fat_update_fat2( void )
    02439 {
    02440   while( fs_g_u16_first_mod_fat <= fs_g_u16_last_mod_fat )
    02441   {
    02442      // Compute the modification position of FAT 1
    02443      fs_gu32_addrsector = fs_g_nav.u32_ptr_fat + fs_g_u16_first_mod_fat;
    02444      // Read FAT1
    02445       if( !fat_cache_read_sector( TRUE ))
    02446          return FALSE;
    02447      // Compute the modification position of FAT 2
    02448      fs_gu32_addrsector = fs_g_nav.u32_ptr_fat + ((U32)fs_g_u16_first_mod_fat + fs_g_nav.u16_fat_size);
    02449      // Init the sector FAT2 with the previous sector of the FAT1
    02450      if( !fat_cache_read_sector( FALSE ))
    02451          return FALSE;
    02452      // Flag the sector FAT2 like modify
    02453      fat_cache_mark_sector_as_dirty();
    02454      fs_g_u16_first_mod_fat++;
    02455   }
    02456   return TRUE;
    02457 }
    02458 #endif  // FS_LEVEL_FEATURES
    02459
    02460
    02461 #if (FSFEATURE_WRITE == (FS_LEVEL_FEATURES & FSFEATURE_WRITE))
    02473 Bool  fat_clear_cluster( void )
    02474 {
    02475    U8 u8_loop;
    02476
    02477    // Compute the cluster sector address
    02478    fs_g_seg.u32_size_or_pos  = 0;   // Select the beginning of cluster
    02479    if( !fat_cluster_list( FS_CLUST_ACT_ONE, FALSE ))
    02480       return FALSE;
    02481
    02482    // Loop in the cluster (start at the end of cluster)
    02483    fs_gu32_addrsector = fs_g_seg.u32_addr + (fs_g_nav.u8_BPB_SecPerClus -1);
    02484    for(  u8_loop = 0
    02485    ;     fs_g_nav.u8_BPB_SecPerClus != u8_loop
    02486    ;     u8_loop++ )
    02487    {
    02488       // Update internal cache with cluster sector inforamtion but don't read data from memory
    02489       if( !fat_cache_read_sector( FALSE ))
    02490          return FALSE;
    02491
    02492       if(0 == u8_loop)
    02493       {  // Clean internal cache (just for the sector)
    02494          fat_cache_clear();
    02495       }
    02496       fat_cache_mark_sector_as_dirty();
    02497       fs_gu32_addrsector--;         // go to previous sector
    02498    }
    02499    return TRUE;
    02500 }
    02501 #endif  // FS_LEVEL_FEATURES