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

# fat_unusual.c

Go to the documentation of this file.

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