fat_unusual.c

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

Generated on Wed Sep 23 09:17:02 2009 for ATMEL by  doxygen 1.5.3