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

Generated on Fri May 15 15:41:36 2009 for ATMEL by  doxygen 1.5.3