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

Last change on this file since 259 was 259, checked in by devigne, 11 years ago

giet_fat32/fat32.c :
Added _fat_write function. At the moment it does not support the creation of a
new file (the writing must exist in the disk image) and does not support the
allocation of additional cluster from the original file.

create_dmg :
Bug fix for support Linux (The tree files were not consistent with the
pathnames in boot.c).

giet_libs/stdlib.c and stdlib.h :
Added stdlib file. At the moment they only contain the atoi function.

giet_libs/stdio.h :
Bug fix in SYSCALL DEFINE. SYSCALL_FAT_READ, WRITE, CLOSE, LSEEK had the same
value.

Makefile :
Added compilation line for stdlib.o

  • Property svn:executable set to *
File size: 48.6 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] First Partition 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 required (first user _fat_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_KERNEL_MODE );  // we use KERNEL_MODE, because
874                                       // we need to write into FAT cache
875    }
876 
877    // Scan the sub-directories, starting from the root directory (cluster 2)
878    // - The get_name_from_path() function extracts (successively)
879    //   each directory name from the pathname, and store it in name[] buffer
880    // - The scan_directory() function scan one (or several) cluster(s) containing
881    //   a directory looking for name[], and return the cluster index
882    //   corresponding to the directory/file found.
883    nb_read     = 0;
884    cluster     = 2;
885    last_name   = 0;
886    while ( get_name_from_path( pathname, name, &nb_read) )
887    {
888
889#if GIET_DEBUG_FAT
890_tty_get_lock( 0 );
891_puts("\n[FAT DEBUG] _fat_open : search dir/file : ");
892_puts( name );
893_puts("\n");
894_tty_release_lock( 0 );
895#endif
896        // test if we reach the last name (file name)
897        if( pathname[nb_read] == 0 ) 
898        {
899            last_name   = 1;
900            dir_cluster = cluster;
901        }
902
903        // scan current directory
904        cluster  = scan_directory( mode, cluster, name, &file_size );
905
906        if( cluster == END_OF_CHAIN_CLUSTER && last_name && creat )
907        {
908            cluster = fat_create( name, 1, dir_cluster );
909        }
910        else if ( cluster == END_OF_CHAIN_CLUSTER )
911        {
912            _tty_get_lock( 0 );
913            _puts("\n[FAT ERROR] in _fat_open() for file ");
914            _puts( pathname );
915            _puts(" : cannot found name ");
916            _puts( name );
917            _puts("\n");
918            _tty_release_lock( 0 );
919            return -1;
920        }
921    }
922
923#if GIET_DEBUG_FAT
924_tty_get_lock( 0 );
925_puts("\n[FAT DEBUG] File ");
926_puts( pathname );
927_puts(" found\n");
928_tty_release_lock( 0 );
929#endif
930
931    // check the next value for cluster index found
932    unsigned next = get_next_cluster_id( mode, cluster );
933
934    if ( (next != BAD_CLUSTER) && (next != FREE_CLUSTER) )
935    {
936        // Search an empty slot scanning open file descriptors array
937        fd_id = 0;
938        while ( fat.fd[fd_id].used != 0 && fd_id < GIET_OPEN_FILES_MAX )
939        {
940            fd_id++;
941        }
942
943        // set file descriptor if found empty slot
944        if ( fd_id < GIET_OPEN_FILES_MAX )
945        {
946            fat.fd[fd_id].used          = 1;
947            fat.fd[fd_id].first_cluster = cluster;
948            fat.fd[fd_id].file_size     = file_size;
949            _strcpy( fat.fd[fd_id].name, pathname );
950
951#if GIET_DEBUG_FAT
952_tty_get_lock( 0 );
953_puts("\n[FAT DEBUG] file  ");
954_puts( pathname );
955_puts(" open with fd_id = ");
956_putd( fd_id );
957_puts("\n");
958_tty_release_lock( 0 );
959#endif
960
961            return fd_id;
962        }
963        else
964        {
965            _tty_get_lock( 0 );
966            _puts("\n[FAT ERROR] in _fat_open() for file ");
967            _puts( pathname );
968            _puts(" : file descriptor array full\n ");
969            _tty_release_lock( 0 );
970            return -1;
971        }
972    }
973    else
974    {
975        _tty_get_lock( 0 );
976        _puts("\n[FAT ERROR] in _fat_open() for file ");
977        _puts( pathname );
978        _puts(" : file found, but bad cluster\n");
979        _tty_release_lock( 0 );
980        return -1;
981    }
982} // end _fat_open()
983
984///////////////////////////////////////////////////////////////////////////////
985// For an open file, identified by the file descriptor index, transfer
986// an integer number of sectors from block device to a memory buffer.
987// If the number of requested sectors exceeds the file size, it is reduced.
988///////////////////////////////////////////////////////////////////////////////
989// Returns number of sectors transfered if success, < 0 if error.
990///////////////////////////////////////////////////////////////////////////////
991int _fat_read( unsigned int mode,       // mode for IOC driver
992               unsigned int fd_id,      // file descriptor
993               void*        buffer,     // target buffer base address
994               unsigned int count,      // number of sector to read
995               unsigned int offset )    // nuber of sectors to skip in file
996{
997
998#if GIET_DEBUG_FAT
999_tty_get_lock( 0 );
1000_puts("\n[FAT DEBUG] Enter _fat_read() for file ");
1001_puts( fat.fd[fd_id].name );
1002_puts("\n - buffer base     = ");
1003_putx( (unsigned int)buffer );
1004_puts("\n - skipped sectors = ");
1005_putd( offset );
1006_puts("\n - read sectors    = "); 
1007_putd( count );
1008_tty_release_lock( 0 );
1009#endif
1010
1011    unsigned int spc = fat.sectors_per_cluster;
1012
1013    unsigned int file_size;         // number of bytes in file
1014    unsigned int file_sectors;      // number of sectors in file
1015    unsigned int total_sectors;     // actual number of sectors to be transfered
1016    unsigned int cluster;           // cluster index
1017    unsigned int clusters_to_skip;  // number of clusters to skip because offset
1018    unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
1019
1020    // compute file size as a number of sectors
1021    file_size    = fat.fd[fd_id].file_size;
1022    if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
1023    else                     file_sectors = (file_size >> 9); 
1024
1025    // arguments checking
1026    if ( fd_id >= GIET_OPEN_FILES_MAX )
1027    { 
1028        _tty_get_lock( 0 );
1029        _puts("\n[FAT ERROR] in _fat_read() : illegal file descriptor index\n");
1030        _tty_release_lock( 0 );
1031        return -1;
1032    }
1033    if ( fat.fd[fd_id].used != 1 )
1034    {
1035        _tty_get_lock( 0 );
1036        _puts("\n[FAT ERROR] in _fat_read() : file not open\n");
1037        _tty_release_lock( 0 );
1038        return -1;
1039    }
1040    if ( ((unsigned int)buffer & 0x1FF) != 0 )
1041    {
1042        _tty_get_lock( 0 );
1043        _puts("\n[FAT ERROR] in _fat_read() : memory buffer not sector aligned\n");
1044        _tty_release_lock( 0 );
1045        return -1;
1046    }
1047    if ( offset >= file_sectors )
1048    {
1049        _tty_get_lock( 0 );
1050        _puts("\n[FAT ERROR] offset larger than number of sectors in file\n");
1051        _puts(" - offset       = ");
1052        _putd( offset );
1053        _puts(" - file_sectors = ");
1054        _putd( file_sectors );
1055        _tty_release_lock( 0 );
1056        return -1;
1057    }
1058
1059    // compute total number of sectors to read
1060    if ( file_sectors < (offset + count) ) total_sectors = file_sectors - offset;
1061    else                                   total_sectors = count;
1062
1063    // compute clusters and sectors to be skipped
1064    clusters_to_skip = offset / spc;
1065    sectors_to_skip  = offset % spc;
1066   
1067    // get first cluster index
1068    cluster = fat.fd[fd_id].first_cluster;
1069
1070#if GIET_DEBUG_FAT
1071_tty_get_lock( 0 );
1072_puts("\n - first cluster   = ");
1073_putd( cluster );   
1074_puts("\n - skiped clusters = ");
1075_putd( clusters_to_skip );   
1076_puts("\n");
1077_tty_release_lock( 0 );
1078#endif
1079
1080    // compute index of first cluster to be loaded
1081    // as we may need to scan the FAT, we use the kernel mode
1082    while ( clusters_to_skip )
1083    {
1084        cluster = get_next_cluster_id( IOC_KERNEL_MODE, cluster );
1085        clusters_to_skip--;
1086    }
1087
1088    // variables used in the loop on clusters
1089    int             todo_sectors;   // number of sectors still to be loaded
1090    unsigned int    lba;            // first sector index on device
1091    unsigned int    iter_sectors;   // number of sectors to load in iteration
1092    char*           dst;            // pointer on target buffer
1093
1094    // initialize these variables for the first iteration
1095    todo_sectors  = total_sectors;
1096    dst           = (char*)buffer;
1097    lba           = cluster_to_lba(cluster) + sectors_to_skip;
1098    if( total_sectors < (spc - sectors_to_skip) ) iter_sectors = total_sectors;
1099    else                                          iter_sectors = spc - sectors_to_skip; 
1100
1101    // loop on the clusters
1102    while ( todo_sectors > 0 )
1103    {
1104
1105#if GIET_DEBUG_FAT
1106_tty_get_lock( 0 );
1107_puts("\n[FAT DEBUG] _fat_read() IOC request : buf = ");
1108_putx( (unsigned int)dst );
1109_puts(" / lba = ");
1110_putd( lba );
1111_puts(" / sectors = "); 
1112_putd( iter_sectors );
1113_puts("\n"); 
1114_tty_release_lock( 0 );
1115#endif
1116
1117        if( _ioc_read( mode,              // mode for IOC driver
1118                       lba,               // first sector index
1119                       dst,               // buffer address
1120                       iter_sectors ) )   // number of sectors
1121        {
1122            _tty_get_lock( 0 );
1123            _puts("\n[FAT ERROR] in _fat_read() cannot load block ");
1124            _putd( lba );
1125            _puts("\n"); 
1126            _tty_release_lock( 0 );
1127            return -1;
1128        }
1129         
1130        // update variables for next iteration
1131        cluster      = get_next_cluster_id( mode, cluster );
1132        todo_sectors = todo_sectors - iter_sectors;
1133        dst          = dst + (iter_sectors << 9);
1134        lba          = cluster_to_lba(cluster);
1135        if ( todo_sectors > spc ) iter_sectors = spc;
1136        else                      iter_sectors = todo_sectors;
1137    }
1138         
1139    // returns number of sectors actually transfered
1140    return total_sectors;
1141
1142}  // end _fat_read()
1143
1144///////////////////////////////////////////////////////////////////////////////
1145// For an open file, identified by the file descriptor index, transfer
1146// an integer number of sectors from a memory buffer to block device.
1147// Allocate new clusters if the offset+count larger than current file size,
1148// but the offset should be smaller than the current file size...
1149// - fat    : pointer on FAT
1150// - mode   : mode for the IOC driver
1151// - fd_id  : open file descriptor index 
1152// - fd_id  : open file descriptor index 
1153// - buffer : base address of the memory buffer (must be sector aligned)
1154// - offset : number of sectors to skip in file
1155// - count  : number of sectors to be written.
1156///////////////////////////////////////////////////////////////////////////////
1157// Returns number of sectors written if success, < 0 if error.
1158///////////////////////////////////////////////////////////////////////////////
1159int _fat_write( unsigned int mode,       // mode for IOC driver
1160                unsigned int fd_id,      // file descriptor
1161                void*        buffer,     // target buffer base address
1162                unsigned int count,      // number of sector to write
1163                unsigned int offset )    // nuber of sectors to skip in file
1164{
1165
1166    unsigned int spc = fat.sectors_per_cluster;
1167
1168    unsigned int file_size;         // number of bytes in file
1169    unsigned int file_sectors;      // number of sectors in file
1170    unsigned int cluster;           // cluster index
1171    unsigned int clusters_to_skip;  // number of clusters to skip because offset
1172    unsigned int sectors_to_skip;   // number of sectors to skip in first iteration
1173    unsigned int allocate;          // need allocate or not
1174
1175    // compute file size as a number of sectors
1176    file_size    = fat.fd[fd_id].file_size;
1177    if ( file_size & 0x1FF ) file_sectors = (file_size >> 9) + 1;
1178    else                     file_sectors = (file_size >> 9); 
1179   
1180    allocate = ( ((count + offset) / spc) > (file_sectors / spc) );
1181
1182#if GIET_DEBUG_FAT
1183_tty_get_lock( 0 );
1184_puts("\n[FAT DEBUG] Enter _fat_write() for file ");
1185_puts( fat.fd[fd_id].name );
1186_puts("\n - buffer base     = ");
1187_putx( (unsigned int)buffer );
1188_puts("\n - skipped sectors = ");
1189_putd( offset );
1190_puts("\n - write sectors    = "); 
1191_putd( count );
1192_puts("\n - file size (sectors)  = "); 
1193_putd( file_sectors );
1194_puts("\n - need allocate = "); 
1195allocate ? _puts( "True" ) : _puts( "False");
1196_tty_release_lock( 0 );
1197#endif
1198
1199    if ( allocate  )
1200    {
1201        _tty_get_lock( 0 );
1202        _puts("\n[FAT ERROR] in _fat_write() : \n");
1203        _puts("we need to allocate more cluster... But this function is not implemented\n");
1204        _tty_release_lock( 0 );
1205        return -1;
1206    }
1207    // arguments checking
1208    if ( fd_id >= GIET_OPEN_FILES_MAX )
1209    { 
1210        _tty_get_lock( 0 );
1211        _puts("\n[FAT ERROR] in _fat_write() : illegal file descriptor index\n");
1212        _tty_release_lock( 0 );
1213        return -1;
1214    }
1215    if ( fat.fd[fd_id].used != 1 )
1216    {
1217        _tty_get_lock( 0 );
1218        _puts("\n[FAT ERROR] in _fat_write() : file not open\n");
1219        _tty_release_lock( 0 );
1220        return -1;
1221    }
1222    if ( ((unsigned int)buffer & 0x1FF) != 0 )
1223    {
1224        _tty_get_lock( 0 );
1225        _puts("\n[FAT ERROR] in _fat_write() : memory buffer not sector aligned\n");
1226        _tty_release_lock( 0 );
1227        return -1;
1228    }
1229
1230    // compute clusters and sectors to be skipped
1231    clusters_to_skip = offset / spc;
1232    sectors_to_skip  = offset % spc;
1233   
1234    // get first cluster index
1235    cluster = fat.fd[fd_id].first_cluster;
1236
1237#if GIET_DEBUG_FAT
1238_tty_get_lock( 0 );
1239_puts("\n - first cluster   = ");
1240_putd( cluster );   
1241_puts("\n - skiped clusters = ");
1242_putd( clusters_to_skip );   
1243_puts("\n");
1244_tty_release_lock( 0 );
1245#endif
1246
1247    // compute index of first cluster to be loaded
1248    // as we may need to scan the FAT, we use the kernel mode
1249    while ( clusters_to_skip )
1250    {
1251        cluster = get_next_cluster_id( IOC_KERNEL_MODE, cluster );
1252        clusters_to_skip--;
1253    }
1254
1255    // variables used in the loop on clusters
1256    int             todo_sectors;   // number of sectors still to be loaded
1257    unsigned int    lba;            // first sector index on device
1258    unsigned int    iter_sectors;   // number of sectors to load in iteration
1259    char*           src;            // pointer on target buffer
1260
1261    // initialize these variables for the first iteration
1262    todo_sectors  = count;
1263    src           = (char*)buffer;
1264    lba           = cluster_to_lba(cluster) + sectors_to_skip;
1265    if( count < (spc - sectors_to_skip) ) iter_sectors = count;
1266    else                                  iter_sectors = spc - sectors_to_skip; 
1267
1268    // loop on the clusters
1269    while ( todo_sectors > 0 )
1270    {
1271
1272#if GIET_DEBUG_FAT
1273_tty_get_lock( 0 );
1274_puts("\n[FAT DEBUG] _fat_write() IOC request : buf = ");
1275_putx( (unsigned int)src );
1276_puts(" / lba = ");
1277_putd( lba );
1278_puts(" / sectors = "); 
1279_putd( iter_sectors );
1280_puts("\n"); 
1281_tty_release_lock( 0 );
1282#endif
1283
1284        if( _ioc_write( mode,              // mode for IOC driver
1285                        lba,               // first sector index
1286                        src,               // buffer address
1287                        iter_sectors ) )   // number of sectors
1288        {
1289            _tty_get_lock( 0 );
1290            _puts("\n[FAT ERROR] in _fat_write() cannot write block ");
1291            _putd( lba );
1292            _puts("\n"); 
1293            _tty_release_lock( 0 );
1294            return -1;
1295        }
1296         
1297        // update variables for next iteration
1298        cluster      = get_next_cluster_id( mode, cluster );
1299        todo_sectors = todo_sectors - iter_sectors;
1300        src          = src + (iter_sectors << 9);
1301        lba          = cluster_to_lba(cluster);
1302        if ( todo_sectors > spc ) iter_sectors = spc;
1303        else                      iter_sectors = todo_sectors;
1304    }
1305         
1306    // returns number of sectors actually transfered
1307    return count;
1308}
1309
1310/////////////////////////////////////////////////////////////////////////////////
1311// Close the file identified by the file_descriptor index.
1312/////////////////////////////////////////////////////////////////////////////////
1313// Returns 0 on success, -1 on failure.
1314/////////////////////////////////////////////////////////////////////////////////
1315int _fat_close( unsigned int fd_id )
1316{
1317    if( (fd_id < GIET_OPEN_FILES_MAX) )
1318    {
1319        fat.fd[fd_id].used = 0;
1320        return 0;
1321    }
1322    else
1323    {
1324        _tty_get_lock( 0 );
1325        _puts("\n[FAT ERROR] in _fat_close() : illegal file descriptor index\n");
1326        _tty_release_lock( 0 );
1327        return -1;
1328    } 
1329} // end fat_close()
1330
1331/////////////////////////////////////////////////////////////////////////////////////
1332// The following function implement the user_level system call.
1333// The flags argument is nor used, as file access modes are not implemented yet.
1334/////////////////////////////////////////////////////////////////////////////////////
1335// Return the file descriptor index if success / return -1 if failure
1336/////////////////////////////////////////////////////////////////////////////////////
1337int _fat_user_open( char*  pathname,         // absolute pathname from root
1338                    unsigned int flags )     // unused: TODO
1339{
1340    return _fat_open( IOC_KERNEL_MODE,       // we KERNEL_MODE, because
1341                      pathname,              // we need to write into FAT cache
1342                      0 );       
1343}
1344
1345/////////////////////////////////////////////////////////////////////////////////////
1346// The following function implement the user_level system call.
1347// This function should be modified to respect the UNIX specification
1348/////////////////////////////////////////////////////////////////////////////////////
1349// Return number of sectors actually transfered if success / return -1 if failure
1350/////////////////////////////////////////////////////////////////////////////////////
1351int _fat_user_read( unsigned int fd,        // file descriptor index
1352                    void*        buffer,    // destination buffer
1353                    unsigned int count,     // number of sectors to read
1354                    unsigned int offset )   // number of sectors to skip
1355{
1356    return _fat_read( IOC_USER_MODE,
1357                      fd,
1358                      buffer, 
1359                      count, 
1360                      offset );
1361}
1362
1363/////////////////////////////////////////////////////////////////////////////////////
1364// The following function implement the user_level system call.
1365// This function should be modified to respect the UNIX specification.
1366/////////////////////////////////////////////////////////////////////////////////////
1367// Return number of sectors actually transfered if success / return -1 if failure
1368/////////////////////////////////////////////////////////////////////////////////////
1369int _fat_user_write( unsigned int fd,       // file descriptor
1370                     void*        buffer,   // source buffer
1371                     unsigned int count,    // number of sectors to write
1372                     unsigned int offset )  // number of sectors to skip on file
1373{
1374    return _fat_write( IOC_USER_MODE,
1375                       fd,
1376                       buffer, 
1377                       count, 
1378                       offset );
1379}
1380
1381/////////////////////////////////////////////////////////////////////////////////////
1382int _fat_user_lseek( unsigned int fd_id,
1383                     unsigned int offset,
1384                     unsigned int whence )
1385{
1386    _tty_get_lock( 0 );
1387    _puts("[GIET ERROR] _fat_user_lseek function not implemented\n");
1388    _tty_release_lock( 0 );
1389    _exit();
1390    return 0;
1391}
1392
1393
1394// Local Variables:
1395// tab-width: 4
1396// c-basic-offset: 4
1397// c-file-offsets:((innamespace . 0)(inline-open . 0))
1398// indent-tabs-mode: nil
1399// End:
1400// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1401
Note: See TracBrowser for help on using the repository browser.