source: soft/giet_vm/giet_fat32/fat32.c @ 271

Last change on this file since 271 was 263, checked in by alain, 11 years ago

Introducing support for TSAR fixed format cluster index (cluster_xy)
We have now 4 parameters defined in map.xml:

  • X_WIDTH, Y_WIDTH define the fixed format (typically X_WIDTH = 4 / Y_WIDTH = 4)
  • X_SIZE, Y_SIZE define the actual TSAR 2D mesh variable size (from 1 to 16)
  • Property svn:executable set to *
File size: 49.5 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : fat32.c
3// Date     : 01/09/2013
4// Authors  : Marco Jankovic, Cesar Fuguet & Alain Greiner
5// Copyright (c) UPMC-LIP6
6//////////////////////////////////////////////////////////////////////////////////
7// The fat32.h and fat32.c files define a library of access functions
8// to a FAT32 partition on a block device. It is intended to be used
9// by the GIET_VM nano-kernel for both the boot code and the kernel code.
10// This code uses functions defined in the utils.c and drivers.c files.
11//////////////////////////////////////////////////////////////////////////////////
12// Implementation notes:
13// 1. the "lba" (Logical Block Address) is the physical sector index on
14//    the block device. The physical sector size is supposed to be 512 bytes.
15// 2. the "cluster" variable is actually a cluster index. A cluster contains
16//    typically 8 sectors (4K bytes) and the cluster index is a 32 bits word.
17// 2. This FAT32 library uses a FAT cache whose storage capacity is one
18//    sector (512 bytes, or 128 cluster indexes in FAT)
19// 3. This FAT32 library can be used in three modes: BOOT/KERNEL/USER
20//    defining three different behaviours for the IOC driver.
21//////////////////////////////////////////////////////////////////////////////////
22
23#include <giet_config.h>
24#include <fat32.h>
25#include <tty_driver.h>
26#include <ioc_driver.h>
27#include <utils.h>
28
29//////////////////////////////////////////////////////////////////////////////////
30//      Global variable used by all FAT access functions
31//////////////////////////////////////////////////////////////////////////////////
32
33__attribute__((section (".kdata"))) 
34fat32_fs_t fat __attribute__((aligned(64)));
35
36//////////////////////////////////////////////////////////////////////////////////
37// This function displays the content of the FAT cache
38//////////////////////////////////////////////////////////////////////////////////
39#if GIET_DEBUG_FAT
40void display_fat_cache()
41{
42    unsigned int line;
43    unsigned int word;
44    unsigned int temp[9];
45
46    temp[8] = 0;
47
48    _tty_get_lock( 0 );
49    _puts("\n*********************** fat_cache_lba = ");
50    _putx( fat.cache_lba );
51    _puts(" **************************\n");
52
53    for ( line=0 ; line<16 ; line++ )
54    {
55        // display address
56        _putx( (fat.cache_lba<<9) + (line<<5) );
57        _puts(" : ");
58
59        // display data hexa
60        for ( word=0 ; word<8 ; word++ )
61        {
62            unsigned int byte  = (line<<5) + (word<<2);
63            unsigned int hexa  = (fat.fat_cache[byte  ]<<24) |
64                                 (fat.fat_cache[byte+1]<<16) |
65                                 (fat.fat_cache[byte+2]<< 8) |
66                                 (fat.fat_cache[byte+3]);
67            _putx( hexa );
68            _puts(" | ");
69
70            // prepare display ascii
71            temp[word] = fat.fat_cache[byte]         |
72                         (fat.fat_cache[byte+1]<<8)  |
73                         (fat.fat_cache[byte+2]<<16) |
74                         (fat.fat_cache[byte+3]<<24) ;
75        }
76       
77        // display data ascii
78        _puts( (char*)temp );
79        _puts("\n");
80    }
81    _puts("***************************************************************************\n");
82    _tty_release_lock( 0 );
83} // end display_fat_cache() 
84#endif
85 
86//////////////////////////////////////////////////////////////////////////////////
87// This function returns the length of a FAT field. This field is identified
88// man by an (offset,length) mnemonic defined in fat32.h file.
89//////////////////////////////////////////////////////////////////////////////////
90static inline int get_length( int offset, 
91                              int length)
92{
93    return length;
94}
95
96//////////////////////////////////////////////////////////////////////////////
97// Read one 32 bits word in a char[] buffer, taking endianness into account.
98// This field is defined by the offset and size arguments.
99//////////////////////////////////////////////////////////////////////////////
100static unsigned int read_entry( unsigned int   offset,
101                                unsigned int   size,
102                                char*          buffer,
103                                unsigned int   little_indian )
104{
105    unsigned int turn;
106    unsigned int res  = 0;
107    unsigned int mask = 0x000000ff;
108
109    if( little_indian )
110    {
111        turn = size;
112        while( turn != 1 )
113        {
114            res = res | (buffer[offset + (turn-1)] & mask);
115            res = res << 8;
116            turn--;
117        }
118        res = (buffer[offset + (turn-1)] & mask) | res;
119    }
120    else
121    {
122        turn = 0;
123        while( turn != size - 1 )
124        {
125
126            res = res  | (buffer[ offset + turn ] & mask );
127            res = res << 8;
128            turn++;
129        }
130        res = res | (buffer[offset + turn] & mask);
131    }
132    return res;
133}
134
135//////////////////////////////////////////////////////////////////////////////////
136// This function retuns the cluster index from the lba of a DATA sector.
137// The lba must be larger than the lba of the first DATA sector.
138// The DATA region indexing starts a cluster 2.
139//////////////////////////////////////////////////////////////////////////////////
140static inline unsigned int lba_to_cluster( unsigned int lba )                   
141{
142   if (lba < fat.data_lba ) return 0;
143
144   return ( (lba - fat.data_lba) / fat.sectors_per_cluster) + 2; 
145}
146
147//////////////////////////////////////////////////////////////////////////////////
148// This function retuns the lba of first sector in DATA region
149// from the cluster index. The cluster index must be larger than 2.
150//////////////////////////////////////////////////////////////////////////////////
151static inline unsigned int cluster_to_lba( unsigned int cluster )       
152{
153   if ( cluster < 2 ) return 0; 
154
155   return  (fat.sectors_per_cluster * (cluster - 2)) + fat.data_lba;
156}
157
158/////////////////////////////////////////////////////////////////////////////////
159// This function search the FAT (using the FAT cache), and returns
160// the next cluster index from the curent cluster index in the FAT.
161// remark: a sector of FAT contains 128 cluster indexes.
162/////////////////////////////////////////////////////////////////////////////////
163static unsigned int get_next_cluster_id( unsigned int mode,
164                                         unsigned int cluster )
165{
166    // compute lba of the sector containing the cluster index
167    unsigned int lba = fat.partition_lba + 32 + (cluster / 128);
168
169    if ( lba == fat.cache_lba )      // hit in cache
170    {
171        return read_entry( ((cluster % 128) * 4), 
172                           4, 
173                           fat.fat_cache,
174                           1 );
175    }
176    else                                  // miss in cache
177    {
178        // we cannot access fat in user mode
179        if( mode == IOC_USER_MODE ) mode = IOC_KERNEL_MODE;
180       
181        // access fat
182        if( _ioc_read( mode,              // mode for IOC driver
183                       lba,               // sector index
184                       fat.fat_cache,     // fat cache
185                       1 ) )              // one sector
186        {
187            _tty_get_lock( 0 );
188            _puts("[FAT_ERROR] in get_next cluster_id() cannot read block ");
189            _putd( lba );
190            _puts("\n");
191            _tty_release_lock( 0 );
192            return 1;
193        }
194        fat.cache_lba = lba;
195
196        return read_entry( ((cluster % 128) * 4), 
197                           4, 
198                           fat.fat_cache,
199                           1 );
200    }
201}
202
203///////////////////////////////////////////////////////////////////////////////
204// This function returns the cluster index from a (32 bytes) directory entry
205///////////////////////////////////////////////////////////////////////////////
206static inline unsigned int read_cluster( char* buf )                 
207{
208   unsigned int cluster = read_entry( DIR_FST_CLUS_HI, buf, 1 ) << 16;
209   cluster = cluster | read_entry( DIR_FST_CLUS_LO, buf, 1 );
210   return cluster;
211} 
212
213//////////////////////////////////////////////////////
214static inline unsigned char to_upper(unsigned char c)
215{
216   if (c >= 'a' && c <= 'z') return (c & ~(0x20));
217   else                      return c;
218}
219
220////////////////////////////////////////////////////////////////
221// This function is a filter:
222// Return the c character if c is a legal short name character
223// Return the '_' character if c is illegal
224////////////////////////////////////////////////////////////////
225static unsigned char illegal_short(unsigned char c)
226{
227   const unsigned char illegal_char [] =";+=[]’,\"*\\<>/?:|\0";
228   short i = 0;
229   while (illegal_char[i]!='\0')
230   {
231      if (c == illegal_char[i])
232         return '_';
233      i++;
234   }
235   return c;
236}
237
238/////////////////////////////////////////////////////////////////////////////////
239// This function test if the string argument is a legal SFN (Short File Name)
240// and copies this name (removing the .) in the sfn_string argument.
241// Criteria for a Short File Name are:
242// - separator is '.' (extension is not mandatory)
243// - 1 <= name length <= 8
244// - 0 <= extension length <= 3
245// - no illegal character (see illega_short() function)
246// Return 1 if it string is a legal SFN
247// Return 0 if not legal SFN
248/////////////////////////////////////////////////////////////////////////////////
249static int is_short( char* string, 
250                     char* sfn_string)
251{
252    int s_size   = 0;
253    int dot_ext  = 0;       // dot offset in the filename
254    int name_len = 0;       // length of file name
255    int ext_len  = 0;       // length of extension
256    int i        = 0;
257    int sc_i     = 0;
258    char ch;
259
260#if GIET_DEBUG_FAT
261_tty_get_lock( 0 );
262_puts("\n[FAT DEBUG] filename ");
263_puts( string );
264_tty_release_lock( 0 );
265#endif
266
267    if(string[0] == '.' && string[1] == '\0')
268    {
269        sfn_string[0] = '.';
270
271#if GIET_DEBUG_FAT
272_tty_get_lock( 0 );
273_puts(" converted to 8.3 SFN format : ");
274_puts( sfn_string );
275_puts("\n");
276_tty_release_lock( 0 );
277#endif
278
279      return 1;
280   }
281
282   if(string[0] == '.' && string[1] == '.' && string[2] == '\0')
283   {
284      sfn_string[0] = '.';
285      sfn_string[1] = '.';
286
287#if GIET_DEBUG_FAT
288_tty_get_lock( 0 );
289_puts(" converted to 8.3 SFN format : ");
290_puts( string );
291_puts("\n");
292_tty_release_lock( 0 );
293#endif
294
295      return 1;
296   }
297
298   sfn_string[11] = '\0';
299
300   while (string[s_size] != '\0')
301   {
302      if (string[s_size] == '.')
303      {
304         dot_ext = s_size;
305         ext_len = -1;
306      }
307      ext_len++;
308      s_size++;
309   }
310
311   if (dot_ext != 0)
312   {
313      name_len = s_size - ext_len - 1;
314   }
315   else
316   {
317      name_len = s_size;
318      ext_len = 0;
319   }
320
321   if ( ext_len > 3 || ( name_len > 8))
322   {
323      return 0;
324   }
325
326   if (dot_ext != 0)
327   {
328      while (i != ext_len)
329      {
330         ch = to_upper(string[dot_ext + 1 + i]);
331         ch = illegal_short(ch);
332         sfn_string[8+i] = ch;
333         i++;
334      } 
335   }
336   i = 0;
337   sc_i = 0;
338   while (i!= name_len)
339   {
340      ch = to_upper(string[i]);
341      ch = illegal_short(ch);
342      if (ch != '.')
343         sfn_string[sc_i++] = ch;
344      i++;
345   }
346
347#if GIET_DEBUG_FAT
348_tty_get_lock( 0 );
349_puts(" converted to 8.3 SFN format : ");
350_puts( sfn_string );
351_puts("\n");
352_tty_release_lock( 0 );
353#endif
354
355   return 1;
356}
357
358////////////////////////////////////////////////////////////////////////////////
359static int get_name_from_short( char* dir_entry,     // input:  SFN dir_entry
360                                char* entry_name )   // output: name
361{
362    unsigned int i   = 0;
363    unsigned int length = get_length(DIR_NAME);
364
365    while ( i < length )
366    {
367        entry_name[i] = dir_entry[i];
368        i++;
369    }
370    entry_name[i] = '\0';
371
372    return i;
373}
374///////////////////////////////////////////////////////////////////////////////
375static int get_name_from_long( char *dir_entry,    // input : LFN dir_entry
376                               char *entry_name)   // output : name
377{
378    unsigned int   entry_name_offset   = 0;
379    unsigned int   dir_entry_offset    = get_length(LDIR_ORD);
380    unsigned int   l_name_1            = get_length(LDIR_NAME_1);
381    unsigned int   l_name_2            = get_length(LDIR_NAME_2);
382    unsigned int   l_name_3            = get_length(LDIR_NAME_3);
383    unsigned int   l_attr              = get_length(LDIR_ATTR);
384    unsigned int   l_type              = get_length(LDIR_TYPE);
385    unsigned int   l_chksum            = get_length(LDIR_CHKSUM);
386    unsigned int   l_rsvd              = get_length(LDIR_RSVD);
387
388    unsigned int j            = 0;
389    unsigned int eof          = 0;
390
391    while ( (dir_entry_offset != DIR_ENTRY_SIZE)  && (!eof) )
392    {
393        while (j != l_name_1 && !eof )
394        {
395            if ( (dir_entry[dir_entry_offset] == 0x00) || 
396                 (dir_entry[dir_entry_offset] == 0xFF) )
397            {
398                eof = 1;
399                continue;
400            }
401            entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
402            dir_entry_offset += 2;
403            j += 2;
404            entry_name_offset++;
405        }
406
407        dir_entry_offset += (l_attr + l_type + l_chksum);
408        j = 0;
409
410        while (j != l_name_2 && !eof )
411        {
412            if ( (dir_entry[dir_entry_offset] == 0x00) || 
413                 (dir_entry[dir_entry_offset] == 0xFF) )
414            {
415                eof = 1;
416                continue;
417            }
418            entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
419            dir_entry_offset += 2;
420            j += 2;
421            entry_name_offset++;
422        }
423
424        dir_entry_offset += l_rsvd;
425        j = 0;
426
427        while (j != l_name_3 && !eof )
428        {
429            if ( (dir_entry[dir_entry_offset] == 0x00) || 
430                 (dir_entry[dir_entry_offset] == 0xFF) )
431            {
432                eof = 1;
433                continue;
434            }
435            entry_name[entry_name_offset] = dir_entry[dir_entry_offset];
436            dir_entry_offset += 2;
437            j += 2;
438            entry_name_offset++;
439        }
440    }
441    entry_name[entry_name_offset] = '\0';
442
443    return entry_name_offset;
444} // end get_name_from_long()
445
446////////////////////////////////////////////////////////////////////////////////////////
447// This function read the blocks defined by the cluster index argument, in a data
448// region containing a directory to search the name of a file/firectory,
449// and returns the cluster index of the file/directory when the name has been found.
450// Return cluster index if name found / Return -1 if not found,
451////////////////////////////////////////////////////////////////////////////////////////
452static int scan_directory( unsigned int   mode,        // mode for IOC driver
453                           unsigned int   cluster,     // cluster containing dir_entry
454                           char*          file_name,   // searched file/directory name
455                           unsigned int*  file_size )  // file size
456{
457
458#if GIET_DEBUG_FAT
459_tty_get_lock( 0 );
460_puts("\n[FAT DEBUG] enter _scan_directory() searching dir/file : ");
461_puts( file_name );
462_puts("\n");
463_tty_release_lock( 0 );
464#endif
465
466    char dir_entry[32];   // buffer to store a full directory_entry
467    char name_entry[14];  // buffer to store a 13 characters (partial) name
468
469    char sfn[12]            = {[0 ... 10] = ' ', '\0'};   // buffer for a Short File Name
470    unsigned int  is_sfn    = is_short(file_name, sfn);   // if file_name is short, sfn = 1     
471    unsigned int  offset    = 0;                          // byte offset in block
472    unsigned int  block_id  = fat.sectors_per_cluster;   // sector index initialisation       
473    unsigned int  lba       = cluster_to_lba(cluster);   
474    unsigned int  attr      = 0;                          // directory entry attribute
475    unsigned int  ord       = 0;                          // directory entry sequence
476    unsigned int  found     = 0;                          // name found
477    unsigned int  i;
478
479    for( i = 0 ; i < 32 ; i++ ) dir_entry[i]  = 0;
480    for( i = 0 ; i < 14 ; i++ ) name_entry[i] = 0;
481
482    // load first cluster sector from DATA region into FAT cache
483    // other sectors will be loaded inside loop as required
484    if( _ioc_read( mode,            // mode for IOC driver
485                   lba,             // sector index
486                   fat.fat_cache,   // buffer address
487                   1 ) )            // one sector
488    {
489        _tty_get_lock( 0 );
490        _puts("[FAT ERROR] in scan directory() cannot read sector ");
491        _putd( lba );
492        _puts("\n");
493        _tty_release_lock( 0 );
494        return -1;
495    }
496
497    fat.cache_lba = lba;
498
499    #if GIET_DEBUG_FAT
500    display_fat_cache();
501    #endif
502
503    // in this loop we scan all names in directory identified by cluster:
504    // - the offset increment is an integer number of directory entry (32 bytes)
505    // - the exit condition is success (name found) or failure (end of directory)
506    while( 1 )
507    {
508        // load a new sector if required
509        if (offset >= 512)             
510        {
511            if ( block_id )           // not a new cluster
512            {
513                lba += 1;
514                block_id --;
515            }
516            else                                          // get next cluster
517            {
518                cluster = get_next_cluster_id( mode, cluster );
519
520                if ( cluster >= END_OF_CHAIN_CLUSTER  ) return END_OF_CHAIN_CLUSTER;
521
522                lba      = cluster_to_lba(cluster);
523                block_id = fat.sectors_per_cluster;
524            }
525            if( _ioc_read( mode,             // mode for IOC driver
526                           lba,              // sector index
527                           fat.fat_cache,   // buffer address
528                           1 ) )             // one sector
529            {
530                _tty_get_lock( 0 );
531                _puts("[FAT ERROR] in scan directory() cannot read sector ");
532                _putd( lba );
533                _puts("\n");
534                _tty_release_lock( 0 );
535                return -1;
536            }
537            fat.cache_lba = lba;
538            block_id--;
539            offset = offset % 512;
540        }
541
542        // analyse a directory entry (pointed by fat.fat_cache + offset)
543        if ( !found )
544        { 
545            attr = read_entry( DIR_ATTR, fat.fat_cache + offset, 0);   
546            ord  = read_entry( LDIR_ORD, fat.fat_cache + offset, 0);
547
548            if ( is_sfn == 1 )                            // searched name is short
549            {
550                if      ( (ord != FREE_ENTRY ) &&
551                          (ord != NO_MORE_ENTRY) &&
552                          (attr == ATTR_LONG_NAME_MASK) )    // LFN entry : skipped
553                {
554                                        offset     = offset + ((ord & 0xF) * DIR_ENTRY_SIZE);
555                    continue;
556                }
557                else if ( (attr != ATTR_LONG_NAME_MASK) && 
558                          (ord  != FREE_ENTRY) && 
559                          (ord  != NO_MORE_ENTRY ) )         // SFN entry : checked
560                {
561                    _memcpy( dir_entry, fat.fat_cache + offset, DIR_ENTRY_SIZE );   
562                    offset = offset + DIR_ENTRY_SIZE;
563                }
564                else if (ord == NO_MORE_ENTRY )              // end of directory : return
565                {
566                    return END_OF_CHAIN_CLUSTER;
567                }
568                else                                                                         // free entry : skipped
569                {
570                    offset = offset + DIR_ENTRY_SIZE;
571                    continue;
572                }
573            }
574            else                                      // searched name is long
575            {
576                if( (attr == ATTR_LONG_NAME_MASK) && 
577                    (ord != FREE_ENTRY) &&
578                    (ord != NO_MORE_ENTRY) )                 // LFN entry : checked
579                {
580                    _memcpy( dir_entry, fat.fat_cache + offset, DIR_ENTRY_SIZE );   
581                    offset = offset + DIR_ENTRY_SIZE;
582                }
583                else if( (attr != ATTR_LONG_NAME_MASK) && 
584                         (ord  != FREE_ENTRY) && 
585                         (ord  != NO_MORE_ENTRY))                        // SFN entry : skipped
586                {
587                    offset = offset + DIR_ENTRY_SIZE;
588                    continue;
589                }
590                else if (ord == NO_MORE_ENTRY )                          // end of director : return
591                {
592                    return END_OF_CHAIN_CLUSTER;
593                }
594                else                                           // free entry : skipped
595                {
596                    offset = offset + DIR_ENTRY_SIZE;
597                    continue;
598                }
599            }
600
601            // testing the name extracted from dir entry
602            if ( is_sfn == 1 )                            // searched name is short
603            {
604                get_name_from_short( dir_entry, name_entry );
605
606                if ( _strncmp( (char*)sfn, (char*)name_entry, 13 ) == 0 )
607                {
608                    *file_size = read_entry( DIR_FILE_SIZE , dir_entry, 1 );
609                    return read_cluster( dir_entry );
610                }
611            }
612            else                                         // searched name is long
613            {
614                get_name_from_long( dir_entry, name_entry );
615
616                unsigned shift = ((ord & 0xf) - 1) * 13;
617                if ( _strncmp( (char*)(file_name + shift), (char*)name_entry, 13 ) == 0 )
618                {
619                    if( (ord & 0xf) == 1 )  found = 1;
620                    continue;
621                }
622                else                                                                 // no matching : skip
623                {
624                    offset = offset + ((ord & 0xf) * DIR_ENTRY_SIZE);
625                }
626            }
627        } 
628        else    // file found
629        {
630            _memcpy( dir_entry, fat.fat_cache + offset, DIR_ENTRY_SIZE );   
631            offset     = offset + DIR_ENTRY_SIZE;
632            *file_size = read_entry( DIR_FILE_SIZE, dir_entry, 1 );
633
634#if GIET_DEBUG_FAT
635_tty_get_lock( 0 );
636_puts("\n[FAT DEBUG] FILE FOUND\n");
637_tty_release_lock( 0 );
638#endif
639            return read_cluster( dir_entry );
640        }
641    }
642    return -1;
643} // end scan_directory()
644
645///////////////////////////////////////////////////////////////////////
646// This function analyses the pathname argument, from the character
647// defined by the *nb_read argument.
648// It copies the found name (between '/') in the name[] buffer,
649// and updates the nb_read argument.
650// Return 1 if name found, Return 0 if NUL character found,
651///////////////////////////////////////////////////////////////////////
652static int get_name_from_path( char*          pathname,
653                               char*          name,
654                               unsigned int*  nb_read ) 
655{
656    if ( pathname[*nb_read] == 0 ) return 0;
657
658    int i = (pathname[*nb_read] == '/')? (*nb_read) + 1 : *nb_read;
659    int j = 0;
660   
661    while(pathname[i] != '/' && pathname[i] != '\0')
662    {
663        name[j] = pathname[i];   
664        j++;
665        i++;
666    }
667    name[j] = 0;
668
669    if ( pathname[i] == '/' ) *nb_read += j+1;
670    else                      *nb_read += j;
671
672    return 1;
673}
674
675//////////////////////////////////////////////////////////////////////
676// This function create a new entry in a directory identified
677// by "dir_cluster". The name is defined by "name".
678// The type (dir/file) is defined by "is_file".
679// Returns cluster index if success, Returns -1 if error.
680//////////////////////////////////////////////////////////////////////
681static int fat_create( char*           name,
682                       unsigned int    is_file,
683                       unsigned int    dir_cluster )
684{
685    _tty_get_lock( 0 );
686    _puts("\n[FAT ERROR] _fat_create() not implemented\n");
687    _tty_release_lock( 0 );
688    return 0;
689}  //end _fat_create()
690
691
692
693////////////// Extern functions //////////////////////////////////////////
694
695//////////////////////////////////////////////////////////////////////////
696// This function initializes the FAT structure, including the
697// files descriptors array, from informations found in the boot record.
698//////////////////////////////////////////////////////////////////////////
699// Return 0 if success, Return -1 if failure
700//////////////////////////////////////////////////////////////////////////
701int _fat_init( unsigned int mode )   // mode for IOC driver
702{
703    unsigned int   n;
704
705#if GIET_DEBUG_FAT
706_tty_get_lock( 0 );
707_puts("\n[FAT DEBUG] Enter _fat_init() / fat_cache_base = ");
708_putx( (unsigned int)fat.fat_cache );
709_puts("\n");
710_tty_release_lock( 0 );
711#endif
712
713    // load Master Boot Record (sector 0) into fat cache
714    if ( _ioc_read( mode,             // mode for IOC driver
715                    0,                // sector index
716                    fat.fat_cache,    // buffer address
717                    1 ) )             // one sector
718    { 
719        _tty_get_lock( 0 );
720        _puts("\n[FAT ERROR] in _fat_init() cannot load Boot Sector\n"); 
721        _tty_release_lock( 0 );
722        return -1;
723    }
724    fat.cache_lba = 0;
725   
726    // checking Boot sector integrity
727    if( MBR_SIGNATURE_VALUE != read_entry( MBR_SIGNATURE_POSITION, fat.fat_cache, 1))
728    {
729        _tty_get_lock( 0 );
730        _puts("\n[FAT ERROR] Boot sector not recognized or corrupt \n"); 
731        _tty_release_lock( 0 );
732        return -1; 
733    }
734
735#if GIET_DEBUG_FAT
736_tty_get_lock( 0 );
737_puts("\n[FAT DEBUG] Boot Sector Loaded\n");
738_tty_release_lock( 0 );
739#endif
740
741    // initialise fat descriptor from Boot sector
742    fat.partition_lba     = read_entry( FIRST_PARTITION_BEGIN_LBA, fat.fat_cache, 1 );
743    fat.partition_sectors = read_entry( FIRST_PARTITION_SIZE,      fat.fat_cache, 1 );
744
745    // load Partition Boot Record (first partition sector) into fat cache
746    if ( _ioc_read( mode,                 // mode for IOC driver
747                    fat.partition_lba,   // sector index
748                    fat.fat_cache,       // buffer address
749                    1 ) )                 // one sector
750    {
751        _tty_get_lock( 0 );
752        _puts("\n[FAT ERROR] in _fat_init() cannot load block ");
753        _putd( fat.partition_lba );
754        _puts("\n"); 
755        _tty_release_lock( 0 );
756        return -1;
757    }
758    fat.cache_lba = fat.partition_lba;
759
760#if GIET_DEBUG_FAT
761_tty_get_lock( 0 );
762_puts("\n[FAT DEBUG] Partition First Sector Loaded\n");
763_tty_release_lock( 0 );
764#endif
765
766
767    // checking various FAT32 assuptions from boot sector
768    if( read_entry( BPB_BYTSPERSEC, fat.fat_cache, 1 ) != 512 )
769    {
770        _tty_get_lock( 0 );
771        _puts("\n[FAT ERROR] The sector size must be 512 bytes\n");
772        _tty_release_lock( 0 );
773        return -1; 
774    }
775    if( read_entry( BPB_RSVDSECCNT, fat.fat_cache, 1 ) != 32 ) 
776    {
777        _tty_get_lock( 0 );
778        _puts("\n[FAT ERROR] The RSVD region in FAT32 must be 32 sectors\n");
779        _tty_release_lock( 0 );
780        return -1; 
781    }
782    if( read_entry( BPB_NUMFATS, fat.fat_cache, 1 ) != 1 )
783    {
784        _tty_get_lock( 0 );
785        _puts("\n[FAT ERROR] The number of FAT copies in FAT region must be 1\n");
786        _tty_release_lock( 0 );
787        return -1; 
788    }
789    if( (read_entry( BPB_FAT32_FATSZ32, fat.fat_cache, 1 ) & 0xF) != 0 )
790    {
791        _tty_get_lock( 0 );
792        _puts("\n[FAT ERROR] The FAT region in FAT32 must be multiple of 32 sectors\n");
793        _tty_release_lock( 0 );
794        return -1; 
795    }
796
797    if( read_entry( BPB_FAT32_ROOTCLUS, fat.fat_cache, 1 ) != 2 )
798    {
799        _tty_get_lock( 0 );
800        _puts("\n[FAT ERROR] The first cluster index must be 2\n");
801        _tty_release_lock( 0 );
802        return -1; 
803    }
804
805    // initialise fat descriptor from partition first sector
806    fat.sectors_per_cluster = read_entry( BPB_SECPERCLUS, fat.fat_cache, 1 );
807    fat.sector_size         = read_entry( BPB_BYTSPERSEC, fat.fat_cache, 1 );
808    fat.cluster_size        = fat.sectors_per_cluster * 512;
809    fat.fat_sectors         = read_entry( BPB_FAT32_FATSZ32, fat.fat_cache, 1 );
810    fat.data_lba            = 32 + fat.fat_sectors + fat.partition_lba;
811    fat.initialised         = FAT_INITIALISED;
812
813    // initialise file descriptor array
814    for( n = 0 ; n < GIET_OPEN_FILES_MAX ; n++ ) fat.fd[n].used = 0;
815
816#if (GIET_DEBUG_FAT == 1)
817_tty_get_lock( 0 );
818_puts("\n[FAT DEBUG] Exit _fat_init()\n");
819_tty_release_lock( 0 );
820#endif
821
822    return 0;
823}  // end _fat_init()
824
825/////////////////
826void _fat_print()
827{
828    _puts("\n################################ FAT32 ###############################"); 
829    _puts("\nFAT initialised                "); _putx( fat.initialised );
830    _puts("\nSector Size  (bytes)           "); _putx( fat.sector_size );
831    _puts("\nSectors per cluster            "); _putx( fat.sectors_per_cluster );
832    _puts("\nPartition size (sectors)       "); _putx( fat.partition_sectors );
833    _puts("\nPartition first lba            "); _putx( fat.partition_lba ); 
834    _puts("\nData region first lba          "); _putx( fat.data_lba );
835    _puts("\nNumber of sectors for one FAT  "); _putx( fat.fat_sectors );
836    _puts("\n######################################################################\n");
837}
838
839///////////////////////////////////////////////////////////////////////////////
840// This function checks that the kernel FAT structure has been initialised,
841// and makes the FAT initialisation if it is the first user open request.
842// This function searches a file identified by the "pathname" argument.
843// It starts from root (cluster 2) to scan successively each subdirectory.
844// When the file is not found, but the path is found, and "creat" is set,
845// a new file is created and introduced in the directory.
846// Finally, it sets a new open file in the file descriptors array.
847///////////////////////////////////////////////////////////////////////////////
848// Returns file descriptor index if success, returns -1 if error.
849///////////////////////////////////////////////////////////////////////////////
850int _fat_open( unsigned     mode,
851               char*        pathname,
852               unsigned int creat )
853{
854    char                 name[256];    // buffer for one name in pathname
855    unsigned int         nb_read;          // number of characters written in name[]
856    unsigned int         cluster;      // current cluster index when scanning FAT
857    unsigned int         dir_cluster;  // previous cluster index when scanning FAT
858    unsigned int         fd_id;        // index when scanning file descriptors array
859    unsigned int         file_size;    // number of bytes
860    unsigned int         last_name;    // directory containing file name is reached
861   
862#if GIET_DEBUG_FAT
863_tty_get_lock( 0 );
864_puts("\n[FAT DEBUG] enter _fat_open() for file ");
865_puts( pathname );
866_puts("\n");
867_tty_release_lock( 0 );
868#endif
869
870    // check FAT initialised
871    if( fat.initialised != FAT_INITIALISED )
872    {
873        _fat_init( IOC_BOOT_VA_MODE );
874    }
875 
876    // Scan the directories, starting from the root directory (cluster 2)
877    // - The get_name_from_path() function extracts (successively)
878    //   each directory name from the pathname, and store it in name[] buffer
879    // - The scan_directory() function scan one (or several) cluster(s) containing
880    //   a directory looking for name[], and return the cluster index
881    //   corresponding to the directory/file found.
882    nb_read     = 0;
883    cluster     = 2;
884    last_name   = 0;
885    while ( get_name_from_path( pathname, name, &nb_read) )
886    {
887
888#if GIET_DEBUG_FAT
889_tty_get_lock( 0 );
890_puts("\n[FAT DEBUG] _fat_open : search dir/file : ");
891_puts( name );
892_puts("\n");
893_tty_release_lock( 0 );
894#endif
895        // test if we reach the last name (file name)
896        if( pathname[nb_read] == 0 ) 
897        {
898            last_name   = 1;
899            dir_cluster = cluster;
900        }
901
902        // scan current directory
903        cluster  = scan_directory( mode, cluster, name, &file_size );
904
905        if( cluster == END_OF_CHAIN_CLUSTER && last_name && creat )
906        {
907            cluster = fat_create( name, 1, dir_cluster );
908        }
909        else if ( cluster == END_OF_CHAIN_CLUSTER )
910        {
911            _tty_get_lock( 0 );
912            _puts("\n[FAT ERROR] in _fat_open() for file ");
913            _puts( pathname );
914            _puts(" : cannot found name ");
915            _puts( name );
916            _puts("\n");
917            _tty_release_lock( 0 );
918            return -1;
919        }
920    }
921
922#if GIET_DEBUG_FAT
923_tty_get_lock( 0 );
924_puts("\n[FAT DEBUG] File ");
925_puts( pathname );
926_puts(" found\n");
927_tty_release_lock( 0 );
928#endif
929
930    // check the next value for cluster index found
931    unsigned next = get_next_cluster_id( mode, cluster );
932
933    if ( (next != BAD_CLUSTER) && (next != FREE_CLUSTER) )
934    {
935        // Search an empty slot scanning open file descriptors array
936        fd_id = 0;
937        while ( fat.fd[fd_id].used != 0 && fd_id < GIET_OPEN_FILES_MAX )
938        {
939            fd_id++;
940        }
941
942        // set file descriptor if found empty slot
943        if ( fd_id < GIET_OPEN_FILES_MAX )
944        {
945            fat.fd[fd_id].used          = 1;
946            fat.fd[fd_id].first_cluster = cluster;
947            fat.fd[fd_id].file_size     = file_size;
948            _strcpy( fat.fd[fd_id].name, pathname );
949
950#if GIET_DEBUG_FAT
951_tty_get_lock( 0 );
952_puts("\n[FAT DEBUG] file  ");
953_puts( pathname );
954_puts(" open with fd_id = ");
955_putd( fd_id );
956_puts("\n");
957_tty_release_lock( 0 );
958#endif
959
960            return fd_id;
961        }
962        else
963        {
964            _tty_get_lock( 0 );
965            _puts("\n[FAT ERROR] in _fat_open() for file ");
966            _puts( pathname );
967            _puts(" : file descriptor array full\n ");
968            _tty_release_lock( 0 );
969            return -1;
970        }
971    }
972    else
973    {
974        _tty_get_lock( 0 );
975        _puts("\n[FAT ERROR] in _fat_open() for file ");
976        _puts( pathname );
977        _puts(" : file found, but bad cluster\n");
978        _tty_release_lock( 0 );
979        return -1;
980    }
981} // end _fat_open()
982
983///////////////////////////////////////////////////////////////////////////////
984// For an open file, identified by the file descriptor index, transfer
985// an integer number of sectors from block device to a memory buffer.
986// If the number of requested sectors exceeds the file size, it is reduced.
987///////////////////////////////////////////////////////////////////////////////
988// Returns number of sectors transfered if success, < 0 if error.
989///////////////////////////////////////////////////////////////////////////////
990int _fat_read( unsigned int mode,       // mode for IOC driver
991               unsigned int fd_id,      // file descriptor
992               void*        buffer,     // target buffer base address
993               unsigned int count,      // number of sector to read
994               unsigned int offset )    // nuber of sectors to skip in file
995{
996
997#if GIET_DEBUG_FAT
998_tty_get_lock( 0 );
999_puts("\n[FAT DEBUG] Enter _fat_read() for file ");
1000_puts( fat.fd[fd_id].name );
1001_puts("\n - buffer base     = ");
1002_putx( (unsigned int)buffer );
1003_puts("\n - skipped sectors = ");
1004_putd( offset );
1005_puts("\n - read sectors    = "); 
1006_putd( count );
1007_tty_release_lock( 0 );
1008#endif
1009
1010    unsigned int spc = fat.sectors_per_cluster;
1011
1012    unsigned int file_size;         // number of bytes in file
1013    unsigned int file_sectors;      // number of sectors in file
1014    unsigned int total_sectors;     // actual number of sectors to be transfered
1015    unsigned int cluster;           // cluster index
1016    unsigned int clusters_to_skip;  // number of clusters to skip because offset
1017    unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
1018
1019    // compute file size as a number of sectors
1020    file_size    = fat.fd[fd_id].file_size;
1021    if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
1022    else                     file_sectors = (file_size >> 9); 
1023
1024    // arguments checking
1025    if ( fd_id >= GIET_OPEN_FILES_MAX )
1026    { 
1027        _tty_get_lock( 0 );
1028        _puts("\n[FAT ERROR] in _fat_read() : illegal file descriptor index\n");
1029        _tty_release_lock( 0 );
1030        return -1;
1031    }
1032    if ( fat.fd[fd_id].used != 1 )
1033    {
1034        _tty_get_lock( 0 );
1035        _puts("\n[FAT ERROR] in _fat_read() : file not open\n");
1036        _tty_release_lock( 0 );
1037        return -1;
1038    }
1039    if ( ((unsigned int)buffer & 0x1FF) != 0 )
1040    {
1041        _tty_get_lock( 0 );
1042        _puts("\n[FAT ERROR] in _fat_read() : memory buffer not sector aligned\n");
1043        _tty_release_lock( 0 );
1044        return -1;
1045    }
1046    if ( offset >= file_sectors )
1047    {
1048        _tty_get_lock( 0 );
1049        _puts("\n[FAT ERROR] offset larger than number of sectors in file\n");
1050        _puts(" - offset       = ");
1051        _putd( offset );
1052        _puts(" - file_sectors = ");
1053        _putd( file_sectors );
1054        _tty_release_lock( 0 );
1055        return -1;
1056    }
1057
1058    // compute total number of sectors to read
1059    if ( file_sectors < (offset + count) ) total_sectors = file_sectors - offset;
1060    else                                   total_sectors = count;
1061
1062    // compute clusters and sectors to be skipped
1063    clusters_to_skip = offset / spc;
1064    sectors_to_skip  = offset % spc;
1065   
1066    // get first cluster index
1067    cluster = fat.fd[fd_id].first_cluster;
1068
1069#if GIET_DEBUG_FAT
1070_tty_get_lock( 0 );
1071_puts("\n - first cluster   = ");
1072_putd( cluster );   
1073_puts("\n - skiped clusters = ");
1074_putd( clusters_to_skip );   
1075_puts("\n");
1076_tty_release_lock( 0 );
1077#endif
1078
1079    // compute index of first cluster to be loaded
1080    // as we may need to scan the FAT, we use the kernel mode
1081    while ( clusters_to_skip )
1082    {
1083        cluster = get_next_cluster_id( IOC_KERNEL_MODE, cluster );
1084        clusters_to_skip--;
1085    }
1086
1087    // variables used in the loop on clusters
1088    int             todo_sectors;   // number of sectors still to be loaded
1089    unsigned int    lba;            // first sector index on device
1090    unsigned int    iter_sectors;   // number of sectors to load in iteration
1091    char*           dst;            // pointer on target buffer
1092
1093    // initialize these variables for the first iteration
1094    todo_sectors  = total_sectors;
1095    dst           = (char*)buffer;
1096    lba           = cluster_to_lba(cluster) + sectors_to_skip;
1097    if( total_sectors < (spc - sectors_to_skip) ) iter_sectors = total_sectors;
1098    else                                          iter_sectors = spc - sectors_to_skip; 
1099
1100    // loop on the clusters
1101    while ( todo_sectors > 0 )
1102    {
1103
1104#if GIET_DEBUG_FAT
1105_tty_get_lock( 0 );
1106_puts("\n[FAT DEBUG] _fat_read() IOC request : buf = ");
1107_putx( (unsigned int)dst );
1108_puts(" / lba = ");
1109_putd( lba );
1110_puts(" / sectors = "); 
1111_putd( iter_sectors );
1112_puts("\n"); 
1113_tty_release_lock( 0 );
1114#endif
1115
1116        if( _ioc_read( mode,              // mode for IOC driver
1117                       lba,               // first sector index
1118                       dst,               // buffer address
1119                       iter_sectors ) )   // number of sectors
1120        {
1121            _tty_get_lock( 0 );
1122            _puts("\n[FAT ERROR] in _fat_read() cannot load block ");
1123            _putd( lba );
1124            _puts("\n"); 
1125            _tty_release_lock( 0 );
1126            return -1;
1127        }
1128         
1129        // update variables for next iteration
1130        cluster      = get_next_cluster_id( mode, cluster );
1131        todo_sectors = todo_sectors - iter_sectors;
1132        dst          = dst + (iter_sectors << 9);
1133        lba          = cluster_to_lba(cluster);
1134        if ( todo_sectors > spc ) iter_sectors = spc;
1135        else                      iter_sectors = todo_sectors;
1136    }
1137         
1138    // returns number of sectors actually transfered
1139    return total_sectors;
1140
1141}  // end _fat_read()
1142
1143///////////////////////////////////////////////////////////////////////////////
1144// For an open file, identified by the file descriptor index, transfer
1145// an integer number of sectors from a memory buffer to block device.
1146// Allocate new clusters if the offset+count larger than current file size,
1147// but the offset should be smaller than the current file size...
1148// - fat    : pointer on FAT
1149// - mode   : mode for the IOC driver
1150// - fd_id  : open file descriptor index 
1151// - fd_id  : open file descriptor index 
1152// - buffer : base address of the memory buffer (must be sector aligned)
1153// - offset : number of sectors to skip in file
1154// - count  : number of sectors to be written.
1155///////////////////////////////////////////////////////////////////////////////
1156// Returns number of sectors written if success, < 0 if error.
1157///////////////////////////////////////////////////////////////////////////////
1158int _fat_write( unsigned int mode,       // mode for IOC driver
1159                unsigned int fd_id,      // file descriptor
1160                void*        buffer,     // target buffer base address
1161                unsigned int count,      // number of sector to write
1162                unsigned int offset )    // nuber of sectors to skip in file
1163{
1164
1165    unsigned int spc = fat.sectors_per_cluster;
1166
1167    unsigned int file_size;         // number of bytes in file
1168    unsigned int file_sectors;      // number of sectors in file
1169    unsigned int cluster;           // cluster index
1170    unsigned int clusters_to_skip;  // number of clusters to skip because offset
1171    unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
1172    unsigned int allocate;          // need allocate or not
1173
1174    // compute file size as a number of sectors
1175    file_size    = fat.fd[fd_id].file_size;
1176    if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
1177    else                     file_sectors = (file_size >> 9); 
1178   
1179    allocate = ( ((count + offset) / spc) > (file_sectors / spc) );
1180
1181#if GIET_DEBUG_FAT
1182_tty_get_lock( 0 );
1183_puts("\n[FAT DEBUG] Enter _fat_write() for file ");
1184_puts( fat.fd[fd_id].name );
1185_puts("\n - buffer base     = ");
1186_putx( (unsigned int)buffer );
1187_puts("\n - skipped sectors = ");
1188_putd( offset );
1189_puts("\n - write sectors    = "); 
1190_putd( count );
1191_puts("\n - file size (sectors)  = "); 
1192_putd( file_sectors );
1193_puts("\n - need allocate = "); 
1194allocate ? _puts( "True" ) : _puts( "False");
1195_tty_release_lock( 0 );
1196#endif
1197
1198    if ( allocate  )
1199    {
1200        _tty_get_lock( 0 );
1201        _puts("\n[FAT ERROR] in _fat_write() : \n");
1202        _puts("we need to allocate more cluster... But this function is not implemented\n");
1203        _tty_release_lock( 0 );
1204        return -1;
1205    }
1206    // arguments checking
1207    if ( fd_id >= GIET_OPEN_FILES_MAX )
1208    { 
1209        _tty_get_lock( 0 );
1210        _puts("\n[FAT ERROR] in _fat_write() : illegal file descriptor index\n");
1211        _tty_release_lock( 0 );
1212        return -1;
1213    }
1214    if ( fat.fd[fd_id].used != 1 )
1215    {
1216        _tty_get_lock( 0 );
1217        _puts("\n[FAT ERROR] in _fat_write() : file not open\n");
1218        _tty_release_lock( 0 );
1219        return -1;
1220    }
1221    if ( ((unsigned int)buffer & 0x1FF) != 0 )
1222    {
1223        _tty_get_lock( 0 );
1224        _puts("\n[FAT ERROR] in _fat_write() : memory buffer not sector aligned\n");
1225        _tty_release_lock( 0 );
1226        return -1;
1227    }
1228
1229    // compute clusters and sectors to be skipped
1230    clusters_to_skip = offset / spc;
1231    sectors_to_skip  = offset % spc;
1232   
1233    // get first cluster index
1234    cluster = fat.fd[fd_id].first_cluster;
1235
1236#if GIET_DEBUG_FAT
1237_tty_get_lock( 0 );
1238_puts("\n - first cluster   = ");
1239_putd( cluster );   
1240_puts("\n - skiped clusters = ");
1241_putd( clusters_to_skip );   
1242_puts("\n");
1243_tty_release_lock( 0 );
1244#endif
1245
1246    // compute index of first cluster to be loaded
1247    // as we may need to scan the FAT, we use the kernel mode
1248    while ( clusters_to_skip )
1249    {
1250        cluster = get_next_cluster_id( IOC_KERNEL_MODE, cluster );
1251        clusters_to_skip--;
1252    }
1253
1254    // variables used in the loop on clusters
1255    int             todo_sectors;   // number of sectors still to be loaded
1256    unsigned int    lba;            // first sector index on device
1257    unsigned int    iter_sectors;   // number of sectors to load in iteration
1258    char*           src;            // pointer on target buffer
1259
1260    // initialize these variables for the first iteration
1261    todo_sectors  = count;
1262    src           = (char*)buffer;
1263    lba           = cluster_to_lba(cluster) + sectors_to_skip;
1264    if( count < (spc - sectors_to_skip) ) iter_sectors = count;
1265    else                                  iter_sectors = spc - sectors_to_skip; 
1266
1267    // loop on the clusters
1268    while ( todo_sectors > 0 )
1269    {
1270
1271#if GIET_DEBUG_FAT
1272_tty_get_lock( 0 );
1273_puts("\n[FAT DEBUG] _fat_write() IOC request : buf = ");
1274_putx( (unsigned int)src );
1275_puts(" / lba = ");
1276_putd( lba );
1277_puts(" / sectors = "); 
1278_putd( iter_sectors );
1279_puts("\n"); 
1280_tty_release_lock( 0 );
1281#endif
1282
1283        if( _ioc_write( mode,              // mode for IOC driver
1284                        lba,               // first sector index
1285                        src,               // buffer address
1286                        iter_sectors ) )   // number of sectors
1287        {
1288            _tty_get_lock( 0 );
1289            _puts("\n[FAT ERROR] in _fat_write() cannot write block ");
1290            _putd( lba );
1291            _puts("\n"); 
1292            _tty_release_lock( 0 );
1293            return -1;
1294        }
1295         
1296        // update variables for next iteration
1297        cluster      = get_next_cluster_id( mode, cluster );
1298        todo_sectors = todo_sectors - iter_sectors;
1299        src          = src + (iter_sectors << 9);
1300        lba          = cluster_to_lba(cluster);
1301        if ( todo_sectors > spc ) iter_sectors = spc;
1302        else                      iter_sectors = todo_sectors;
1303    }
1304         
1305    // returns number of sectors actually transfered
1306    return count;
1307}
1308
1309/////////////////////////////////////////////////////////////////////////////////
1310// Return stats of a file identified by "fd".
1311// (Only the file_size in sectors for this moment)
1312/////////////////////////////////////////////////////////////////////////////////
1313// Returns file size (on sectors) on success, -1 on failure.
1314/////////////////////////////////////////////////////////////////////////////////
1315int _fat_fstat( unsigned int fd_id )
1316{
1317    unsigned int file_size    = 0;
1318    unsigned int file_sectors = 0;
1319
1320    if( (fd_id < GIET_OPEN_FILES_MAX) )
1321    {
1322        file_size = fat.fd[fd_id].file_size;
1323
1324        if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
1325        else                     file_sectors = (file_size >> 9); 
1326
1327        return file_sectors;
1328    }
1329    else
1330    {
1331        _tty_get_lock( 0 );
1332        _puts("\n[FAT ERROR] in _fat_fstat() : illegal file descriptor index\n");
1333        _tty_release_lock( 0 );
1334        return -1;
1335    } 
1336} // end _fat_fstat()
1337
1338/////////////////////////////////////////////////////////////////////////////////
1339// Close the file identified by the file_descriptor index.
1340/////////////////////////////////////////////////////////////////////////////////
1341// Returns 0 on success, -1 on failure.
1342/////////////////////////////////////////////////////////////////////////////////
1343int _fat_close( unsigned int fd_id )
1344{
1345    if( (fd_id < GIET_OPEN_FILES_MAX) )
1346    {
1347        fat.fd[fd_id].used = 0;
1348        return 0;
1349    }
1350    else
1351    {
1352        _tty_get_lock( 0 );
1353        _puts("\n[FAT ERROR] in _fat_close() : illegal file descriptor index\n");
1354        _tty_release_lock( 0 );
1355        return -1;
1356    } 
1357} // end fat_close()
1358
1359/////////////////////////////////////////////////////////////////////////////////////
1360// The following function implement the user_level system call.
1361// The flags argument is nor used, as file access modes are not implemented yet.
1362/////////////////////////////////////////////////////////////////////////////////////
1363// Return the file descriptor index if success / return -1 if failure
1364/////////////////////////////////////////////////////////////////////////////////////
1365int _fat_user_open( char*  pathname,         // absolute pathname from root
1366                    unsigned int flags )     // unused: TODO
1367{
1368    return _fat_open( IOC_KERNEL_MODE,       // we KERNEL_MODE, because
1369                      pathname,              // we need to write into FAT cache
1370                      0 );       
1371}
1372
1373/////////////////////////////////////////////////////////////////////////////////////
1374// The following function implement the user_level system call.
1375// This function should be modified to respect the UNIX specification
1376/////////////////////////////////////////////////////////////////////////////////////
1377// Return number of sectors actually transfered if success / return -1 if failure
1378/////////////////////////////////////////////////////////////////////////////////////
1379int _fat_user_read( unsigned int fd,        // file descriptor index
1380                    void*        buffer,    // destination buffer
1381                    unsigned int count,     // number of sectors to read
1382                    unsigned int offset )   // number of sectors to skip
1383{
1384    return _fat_read( IOC_USER_MODE,
1385                      fd,
1386                      buffer, 
1387                      count, 
1388                      offset );
1389}
1390
1391/////////////////////////////////////////////////////////////////////////////////////
1392// The following function implement the user_level system call.
1393// This function should be modified to respect the UNIX specification.
1394/////////////////////////////////////////////////////////////////////////////////////
1395// Return number of sectors actually transfered if success / return -1 if failure
1396/////////////////////////////////////////////////////////////////////////////////////
1397int _fat_user_write( unsigned int fd,       // file descriptor
1398                     void*        buffer,   // source buffer
1399                     unsigned int count,    // number of sectors to write
1400                     unsigned int offset )  // number of sectors to skip on file
1401{
1402    return _fat_write( IOC_USER_MODE,
1403                       fd,
1404                       buffer, 
1405                       count, 
1406                       offset );
1407}
1408
1409/////////////////////////////////////////////////////////////////////////////////////
1410int _fat_user_lseek( unsigned int fd_id,
1411                     unsigned int offset,
1412                     unsigned int whence )
1413{
1414    _tty_get_lock( 0 );
1415    _puts("[GIET ERROR] _fat_user_lseek function not implemented\n");
1416    _tty_release_lock( 0 );
1417    _exit();
1418    return 0;
1419}
1420
1421
1422// Local Variables:
1423// tab-width: 4
1424// c-basic-offset: 4
1425// c-file-offsets:((innamespace . 0)(inline-open . 0))
1426// indent-tabs-mode: nil
1427// End:
1428// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1429
Note: See TracBrowser for help on using the repository browser.