source: trunk/kernel/fs/fatfs.h @ 623

Last change on this file since 623 was 623, checked in by alain, 5 years ago

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

File size: 28.1 KB
Line 
1/*
2 * fatfs.h - FATFS file system API definition.
3 *
4 * Author    Mohamed Lamine Karaoui (2014,2015)
5 *           Alain Greiner (2016,2017,2018)
6 *
7 * Copyright (c) UPMC Sorbonne Universites
8 *
9 * This file is part of ALMOS-MKH.
10 *
11 * ALMOS-MKH is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2.0 of the License.
14 *
15 * ALMOS-MKH is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#ifndef _FATFS_H_
26#define _FATFS_H_
27
28#include <hal_kernel_types.h>
29#include <remote_queuelock.h>
30#include <vfs.h>
31#include <dev_ioc.h>
32
33
34///////////////////////////////////////////////////////////////////////////////////////////
35// The FATFS File System implements a FAT32 read/write file system.
36//
37// The FATFS extensions to the generic VFS are the following:
38//
39// 1) The vfs_ctx_t "extend" field is a void* pointing on the fatfs_ctx_t structure.
40//    This structure contains various general informations such as the total
41//    number of sectors in FAT region, the number of bytes per sector, the number
42//    of sectors per cluster, the lba of FAT region, the lba of data region, or the
43//    cluster index for the root directory. It contains also an extended pointer
44//    on the FAT mapper.
45//
46// 2) The vfs_inode_t "extend" contains, for each inode,
47//    the first FAT cluster index (after cast to intptr).
48//
49// 3) The vfs_dentry_t "extend" field contains, for each dentry, the entry index
50//    in the FATFS directory (32 bytes per FATFS entry).
51///////////////////////////////////////////////////////////////////////////////////////////
52
53/*************** Partition Boot Sector Format **********************************/
54//                                     offset |  length
55#define BS_JMPBOOT                          0 ,  3
56#define BS_OEMNAME                          3 ,  8
57#define BPB_BYTSPERSEC                     11 ,  2
58#define BPB_SECPERCLUS                     13 ,  1
59#define BPB_RSVDSECCNT                     14 ,  2
60#define BPB_NUMFATS                        16 ,  1
61#define BPB_ROOTENTCNT                     17 ,  2
62#define BPB_TOTSEC16                       19 ,  2
63#define BPB_MEDIA                          21 ,  1
64#define BPB_FATSZ16                        22 ,  2
65#define BPB_SECPERTRK                      24 ,  2
66#define BPB_NUMHEADS                       26 ,  2
67#define BPB_HIDDSEC                        28 ,  4
68#define BPB_TOTSEC32                       32 ,  4
69#define BPB_PARTITION_TABLE               446 , 64
70
71// FAT 32
72#define BPB_FAT32_FATSZ32                  36 ,  4
73#define BPB_FAT32_EXTFLAGS                 40 ,  2
74#define BPB_FAT32_FSVER                    42 ,  2
75#define BPB_FAT32_ROOTCLUS                 44 ,  4
76#define BPB_FAT32_FSINFO                   48 ,  2
77#define BPB_FAT32_BKBOOTSEC                50 ,  2
78#define BS_FAT32_DRVNUM                    64 ,  1
79#define BS_FAT32_BOOTSIG                   66 ,  1
80#define BS_FAT32_VOLID                     67 ,  4
81#define BS_FAT32_VOLLAB                    71 , 11
82#define BS_FAT32_FILSYSTYPE                82 ,  8
83
84// Partitions
85#define FIRST_PARTITION_ACTIVE            446 ,  8
86#define FIRST_PARTITION_BEGIN_LBA         454 ,  4
87#define FIRST_PARTITION_SIZE              458 ,  4
88#define SECOND_PARTITION_ACTIVE           462 ,  8
89#define SECOND_PARTITION_BEGIN_LBA        470 ,  4
90#define SECOND_PARTITION_SIZE             474 ,  4
91#define THIRD_PARTITION_ACTIVE            478 ,  8
92#define THIRD_PARTITION_BEGIN_LBA         486 ,  4
93#define THIRD_PARTITION_SIZE              490 ,  4
94#define FOURTH_PARTITION_ACTIVE           494 ,  8
95#define FOURTH_PARTITION_BEGIN_LBA        502 ,  4
96#define FOURTH_PARTITION_SIZE             506 ,  4   
97/*******************************************************************************/
98
99#define MBR_SIGNATURE_POSITION            510 , 2
100#define MBR_SIGNATURE_VALUE               0xAA55 
101
102/************** FAT_FS_INFO SECTOR  ********************************************/
103#define FS_SIGNATURE_VALUE_1              0x52526141
104#define FS_SIGNATURE_VALUE_2              0x72724161
105#define FS_SIGNATURE_VALUE_3              0x000055AA 
106#define FS_SIGNATURE_POSITION_1           0   , 4 
107#define FS_SIGNATURE_POSITION_2           484 , 4
108#define FS_SIGNATURE_POSITION_3           508 , 4 
109#define FS_FREE_CLUSTERS                  488 , 4
110#define FS_FREE_CLUSTER_HINT              492 , 4
111/*******************************************************************************/
112
113#define DIR_ENTRY_SIZE          32
114                   
115#define NAME_MAX_SIZE           31
116
117/******* SFN Directory Entry Structure (32 bytes) ******************************/
118//                            offset | length
119#define DIR_NAME                   0 , 11   // dir_entry name
120#define DIR_ATTR                  11 ,  1   // attributes
121#define DIR_NTRES                 12 ,  1   // reserved for the OS       
122#define DIR_CRT_TIMES_TENTH       13 ,  1
123#define DIR_FST_CLUS_HI           20 ,  2   // cluster index 16 MSB bits
124#define DIR_WRT_TIME              22 ,  2   // time of last write
125#define DIR_WRT_DATE              24 ,  2   // date of last write
126#define DIR_FST_CLUS_LO           26 ,  2   // cluster index 16 LSB bit
127#define DIR_FILE_SIZE             28 ,  4   // dir_entry size (up to 4 Gbytes)
128/*******************************************************************************/
129
130/******* LFN Directory Entry Structure  (32 bytes) *****************************/
131//                            offset | length
132#define LDIR_ORD                   0 ,  1   // Sequence number (from 0x01 to 0x0f)   
133#define LDIR_NAME_1                1 , 10   // name broken into 3 parts
134#define LDIR_ATTR                 11 ,  1   // attributes (must be 0x0F)
135#define LDIR_TYPE                 12 ,  1   // directory type (must be 0x00)
136#define LDIR_CHKSUM               13 ,  1   // checksum of name in short dir 
137#define LDIR_NAME_2               14 , 12
138#define LDIR_RSVD                 26 ,  2   // artifact of previous fat (must be 0)
139#define LDIR_NAME_3               28 ,  4   
140/*******************************************************************************/
141
142/***********************  DIR_ATTR values  (attributes) ************************/
143#define ATTR_READ_ONLY            0x01
144#define ATTR_HIDDEN               0x02
145#define ATTR_SYSTEM               0x04
146#define ATTR_VOLUME_ID            0x08
147#define ATTR_DIRECTORY            0x10
148#define ATTR_ARCHIVE              0x20
149#define ATTR_LONG_NAME_MASK       0x0f      // READ_ONLY|HIDDEN|SYSTEM|VOLUME_ID
150/*******************************************************************************/
151
152/********************* DIR_ORD special values **********************************/
153#define FREE_ENTRY                0xE5     // this entry is free in the directory
154#define NO_MORE_ENTRY             0x00     // no more entry in the directory
155/*******************************************************************************/
156
157/******************** CLuster Index Special Values *****************************/
158#define FREE_CLUSTER              0x00000000
159#define RESERVED_CLUSTER          0x00000001
160#define BAD_CLUSTER               0x0FFFFFF7
161#define END_OF_CHAIN_CLUSTER_MIN  0x0ffffff8
162#define END_OF_CHAIN_CLUSTER_MAX  0x0fffffff
163/*******************************************************************************/
164
165/****  Forward declarations  ****/
166
167struct mapper_s;
168struct page_s;
169struct vfs_ctx_s;
170struct vfs_inode_s;
171struct vfs_dentry_s;
172
173/*****************************************************************************************
174 * This structure defines a FATFS specific context (extension to VFS context).
175 * This extension is replicated in all clusters.
176 *
177 * WARNING : Almost all fields are constant values, but the <free_cluster_hint> and
178 * <free_clusters> are shared variables. All kernel instances use the variables
179 * in cluster 0, using the <free_lock> remote busy_lock for exclusive access.
180 ****************************************************************************************/
181
182typedef struct fatfs_ctx_s
183{
184    uint32_t            fat_sectors_count;     /*! number of sectors in FAT region      */
185    uint32_t            bytes_per_sector;      /*! number of bytes per sector           */
186    uint32_t            sectors_per_cluster;   /*! number of sectors per cluster        */
187    uint32_t            fat_begin_lba;         /*! lba of FAT region                    */
188    uint32_t            cluster_begin_lba;     /*! lba of data region                   */
189    uint32_t            fs_info_lba;           /*! lba of FS_INFO sector                */
190    uint32_t            root_dir_cluster;      /*! cluster index for  root directory    */
191    xptr_t              fat_mapper_xp;         /*! extended pointer on FAT mapper       */
192    uint32_t            free_cluster_hint;     /*! start point to search free cluster   */
193    uint32_t            free_clusters;         /*! free clusters number                 */
194    remote_queuelock_t  free_lock;             /*! exclusive access to hint & number    */
195}
196fatfs_ctx_t;
197
198//////////////////////////////////////////////////////////////////////////////////////////
199//              FATFS specific extern functions 
200//////////////////////////////////////////////////////////////////////////////////////////
201
202/*****************************************************************************************
203 * This function access the FAT (File Allocation Table), stored in the FAT mapper, and
204 * returns in <searched_cluster> the FATFS cluster index for a given page of a given
205 * inode identified by the <first_cluster> and <page_id> arguments.
206 * It can be called by a thread running in any cluster, as it uses remote access
207 * primitives when the FAT mapper is remote.
208 * The FAT is actually an array of uint32_t slots. Each slot in this array contains the
209 * index of another slot in this array, to form one linked list for each file stored on
210 * device in the FATFS file system. This index in the FAT array is also the index of the
211 * FATFS cluster on the device. One FATFS cluster is supposed to contain one PPM page.
212 * For a given file, the entry point in the FAT is simply the index of the FATFS cluster
213 * containing the first page of the file. The FAT mapper being a cache, this function
214 * updates the FAT mapper from informations stored on IOC device in case of miss.
215 *****************************************************************************************
216 * @ first_cluster       : [in]  index of first FATFS cluster allocated to the file.
217 * @ page_id             : [in]  index of searched page in file.
218 * @ searched_cluster    : [out] found FATFS cluster index.
219 * @ return 0 if success / return -1 if a FAT mapper miss cannot be solved.
220 ****************************************************************************************/
221error_t fatfs_get_cluster( uint32_t   first_cluster,
222                           uint32_t   page_id,
223                           uint32_t * searched_cluster );
224
225/*****************************************************************************************
226 * This function display the content of the FATFS context.
227 ****************************************************************************************/
228void fatfs_ctx_display( void );
229
230/*****************************************************************************************
231 * This function displays the content of a part of the File Allocation Table.
232 * It loads the requested page fom device to mapper if required.
233 *****************************************************************************************
234 * @ page_id   : page index in FAT mapper (one page is 4 Kbytes).
235 * @ nentries  : number of entries (one entry is 4 bytes).
236 ****************************************************************************************/
237void fatfs_display_fat( uint32_t  page_id,
238                        uint32_t  nentries );
239
240
241//////////////////////////////////////////////////////////////////////////////////////////
242// Generic API: These functions are called by the kernel VFS,
243//              and must be implemented by all File Systems.
244//////////////////////////////////////////////////////////////////////////////////////////
245
246/*****************************************************************************************
247 * This fuction allocates memory from local cluster for a FATFS context descriptor.
248 *****************************************************************************************
249 * @ return a pointer on the created context / return NULL if failure.
250 ****************************************************************************************/
251fatfs_ctx_t * fatfs_ctx_alloc( void );
252
253/*****************************************************************************************
254 * This function access the boot device, and initialises the local FATFS context
255 * from informations contained in the boot record.
256 *****************************************************************************************
257 * @ vfs_ctx   : local pointer on VFS context for FATFS.
258 ****************************************************************************************/
259void fatfs_ctx_init( fatfs_ctx_t * fatfs_ctx );
260
261/*****************************************************************************************
262 * This function releases memory dynamically allocated for the FATFS context extension.
263 *****************************************************************************************
264 * @ vfs_ctx   : local pointer on VFS context.
265 ****************************************************************************************/
266void fatfs_ctx_destroy( fatfs_ctx_t * fatfs_ctx );
267
268/*****************************************************************************************
269 * This function implements the generic vfs_fs_add_dentry() function for the FATFS.
270 *****************************************************************************************
271 * This function updates a directory identified by the <inode> argument
272 * to add a new directory entry identified by the <dentry> argument.
273 * All modified pages in directory mapper are synchronously updated on IOC device.
274 * It must be called by a thread running in the cluster containing the inode.
275 *
276 * Implementation note : this function works in two steps:
277 * - It scan the set of 32 bytes FATFS directry entries, using two embedded loops 
278 *   to find the end of directory (NO_MORE_ENTRY marker).
279 * - Then it writes 3, 4, or 5 directory entries (depending on the name length), using
280 *   a 5 steps FSM (one state per entry to be written), updates on IOC device the
281 *   modified pages, and updates the dentry extension field, that must contain
282 *   the dentry index in FATFS directory.
283 *****************************************************************************************
284 * @ inode    : local pointer on directory inode.
285 * @ dentry   : local pointer on dentry.
286 * @ return 0 if success / return ENOENT if not found, or EIO if no access to IOC device.
287 ****************************************************************************************/
288error_t fatfs_add_dentry( struct vfs_inode_s  * inode,
289                          struct vfs_dentry_s * dentry );
290
291/*****************************************************************************************
292 * This function implements the generic vfs_fs_remove_dentry() function for the FATFS.
293 *****************************************************************************************
294 * This function updates a directory identified by the <inode> argument
295 * to remove a directory entry identified by the <dentry> argument.
296 * All modified pages in directory mapper are synchronously updated on IOC device.
297 * It must be called by a thread running in the cluster containing the inode.
298 *
299 * Implementation note: this function uses the dentry extension to directly access
300 * the NORMAL directory entry and invalidate all involved LFN entries. Then it
301 * updates the modified pages on IOC device.
302 *****************************************************************************************
303 * @ inode    : local pointer on directory inode.
304 * @ dentry   : local pointer on dentry.
305 * @ return 0 if success / return ENOENT if not found, or EIO if no access to IOC device.
306 ****************************************************************************************/
307error_t fatfs_remove_dentry( struct vfs_inode_s  * inode,
308                             struct vfs_dentry_s * dentry );
309
310/*****************************************************************************************
311 * This function implements the generic vfs_fs_new_dentry() function for the FATFS.
312 *****************************************************************************************
313 * It initializes a new inode/dentry couple in Inode Tree, attached to the directory
314 * identified by the <parent_inode> argument. The new directory entry is identified
315 * by the <name> argument. The child inode descriptor identified by the <child_inode_xp>
316 * argument, and the dentry descriptor must have been previously allocated.
317 * It scan the parent mapper to find the <name> argument.
318 * It set the "type", "size", and "extend" fields in inode descriptor.
319 * It set the " extend" field in dentry descriptor.
320 * It must be called by a thread running in the cluster containing the parent inode.
321 *****************************************************************************************
322 * @ parent_inode    : local pointer on parent inode (directory).
323 * @ name            : child name.
324 * @ child_inode_xp  : extended pointer on remote child inode (file or directory).
325 * @ return 0 if success / return ENOENT if child not found.
326 ****************************************************************************************/
327error_t fatfs_new_dentry( struct vfs_inode_s * parent_inode,
328                          char               * name,
329                          xptr_t               child_inode_xp );
330
331/*****************************************************************************************
332 * This function implements the generic vfs_fs_update_dentry() function for the FATFS.
333 *****************************************************************************************
334 * It update the size of a directory entry identified by the <dentry> argument in
335 * the mapper of a directory identified by the <inode> argument, as defined by the <size>
336 * argument.
337 * It scan the mapper to find the entry identified by the dentry "name" field.
338 * It set the "size" field in the in the directory mapper AND marks the page as DIRTY.
339 * It must be called by a thread running in the cluster containing the directory inode.
340 *****************************************************************************************
341 * @ inode        : local pointer on inode (directory).
342 * @ dentry       : local pointer on dentry (for name).
343 * @ size         : new size value.
344 * @ return 0 if success / return ENOENT if child not found.
345 ****************************************************************************************/
346error_t fatfs_update_dentry( struct vfs_inode_s  * inode,
347                             struct vfs_dentry_s * dentry,
348                             uint32_t              size );
349
350/*****************************************************************************************
351 * This function implements the generic vfs_fs_get_user_dir() function for the FATFS.
352 *****************************************************************************************
353 * It is called by the remote_dir_create() function to scan the mapper of a directory
354 * identified by the <inode> argument, and copy up to <max_dirent> valid dentries to a
355 * local dirent array, defined by the <array> argument. The <min_dentry> argument defines
356 * the index of the first dentry to be copied to the target dirent array.
357 * This function returns in the <entries> buffer the number of dentries actually written,
358 * and signals in the <done> buffer when the last valid entry has been found.
359 * If the <detailed> argument is true, a dentry/inode couple that does not exist in
360 * the Inode Tree is dynamically created, and all dirent fields are documented in the
361 * dirent array. Otherwise, only the dentry name is documented.
362 * It must be called by a thread running in the cluster containing the directory inode.
363 *****************************************************************************************
364 * @ inode      : [in]  local pointer on directory inode.
365 * @ array      : [in]  local pointer on array of dirents.
366 * @ max_dirent : [in]  max number of slots in dirent array.
367 * @ min_dentry : [in]  index of first dentry to be copied into array.
368 * @ detailed   : [in]  dynamic inode creation if true.
369 * @ entries    : [out] number of dentries actually copied into array.
370 * @ done       : [out] Boolean true when last entry found.
371 * @ return 0 if success / return -1 if failure.
372 ****************************************************************************************/
373error_t fatfs_get_user_dir( struct vfs_inode_s * inode,
374                            struct dirent      * array, 
375                            uint32_t             max_dirent,
376                            uint32_t             min_dentry,
377                            bool_t               detailed,
378                            uint32_t           * entries,
379                            bool_t             * done );
380
381/*****************************************************************************************
382 * This function implements the generic vfs_fs_sync_inode() function for the FATFS.
383 *****************************************************************************************
384 * It updates the FATFS on the IOC device for a given inode identified by
385 * the <inode> argument. It scan all pages registered in the associated mapper,
386 * and copies from mapper to device each page marked as dirty.
387 * WARNING : The target <inode> cannot be a directory, because all modifications in a
388 * directory are synchronously done on the IOC device by the two fatfs_add_dentry()
389 * and fatfs_remove_dentry() functions.
390 *****************************************************************************************
391 * @ inode   : local pointer on inode.
392 * @ return 0 if success / return EIO if failure during device access.
393 ****************************************************************************************/
394error_t fatfs_sync_inode( struct vfs_inode_s * inode );
395
396/*****************************************************************************************
397 * This function implements the generic vfs_fs_sync_fat() function for the FATFS.
398 *****************************************************************************************
399 * It updates the FATFS on the IOC device for the FAT itself.
400 * It scan all clusters registered in the FAT mapper, and copies from mapper to device
401 * each page marked as dirty.
402 *
403 * TODO : the current implementation check ALL pages in the FAT region, even if most
404 * pages are empty, and not copied in mapper. It is sub-optimal.
405 * - A first solution is to maintain in the FAT context two "dirty_min" and "dirty_max"
406 *  variables defining the smallest/largest dirty page index in FAT mapper...
407 *****************************************************************************************
408 * @ return 0 if success / return EIO if failure during device access.
409 ****************************************************************************************/
410error_t fatfs_sync_fat( void );
411
412/*****************************************************************************************
413 * This function implements the generic vfs_fs_sync_fsinfo() function for the FATFS.
414 *****************************************************************************************
415 * It updates the FS_INFO sector on the IOC device.
416 * It copies the <free_cluster_hint> and <free_clusters> variables from
417 * the FATFS context in cluster 0 to the FS_INFO sector on device.
418 *****************************************************************************************
419 * @ return 0 if success / return EIO if failure during device access.
420 ****************************************************************************************/
421error_t fatfs_sync_free_info( void );
422
423/*****************************************************************************************
424 * This function implements the generic vfs_fs_cluster_alloc() function for the FATFS.
425 *****************************************************************************************
426 * It access the FAT (File allocation table), stored in the FAT mapper, and returns
427 * in <searched_cluster> the FATFS cluster index of a free cluster.
428 * It can be called by a thread running in any cluster, as it uses remote access
429 * primitives when the FAT mapper is remote. It takes the "free_lock" stored in the
430 * FATFS context located in the same cluster as the FAT mapper itself, to get exclusive
431 * access to the FAT. It uses (and updates) the <free_cluster_hint> and <free_clusters>
432 * shared variables in this FATFS context.
433 * It updates the FAT mapper, and synchronously updates the FAT region on IOC device.
434 * The FAT mapper being a cache, this function updates the FAT mapper from informations
435 * stored on IOC device in case of miss.
436 *****************************************************************************************
437 * @ searched_cluster    : [out] found FATFS cluster index.
438 * @ return 0 if success / return -1 if no more free clusters on IOC device.
439 ****************************************************************************************/
440error_t fatfs_cluster_alloc( uint32_t * searched_cluster );
441
442/*****************************************************************************************
443 * This function implements the generic vfs_fs_release_inode() function for the FATFS.
444 *****************************************************************************************
445 * It releases all clusters allocated to a file/directory identified by the <inode_xp>
446 * argument. All released clusters are marked FREE_CLUSTER in the FAT mapper.
447 * This function calls the recursive function fatfs_cluster_release() to release
448 * the clusters in reverse order of the linked list (from last to first).
449 * When the FAT mapper has been updated, it calls the fatfs_sync_fat() function to
450 * synchronously update all dirty pages in the FAT mapper to the IOC device.
451 * Finally the FS-INFO sector on the IOC device is updated.
452 *****************************************************************************************
453 * @ inode_xp   : extended pointer on inode.
454 * @ return 0 if success / return EIO if failure during device access.
455 ****************************************************************************************/
456error_t fatfs_release_inode( xptr_t inode_xp );
457
458/*****************************************************************************************
459 * This function implements the generic vfs_fs_move_page() function for the FATFS.
460 *****************************************************************************************
461 * This function moves a page from/to the mapper to/from the FATFS file system on device.
462 * The page must have been previously allocated and registered in the mapper.   
463 * The page - and the mapper - can be located in another cluster than the calling thread.
464 * The pointer on the mapper and the page index in file are found in the page descriptor.
465 * It is used for both a regular file/directory mapper, and the FAT mapper.
466 * For the FAT mapper, it access the FATFS to get the location on IOC device.
467 * For a regular file, it access the FAT mapper to get the cluster index on IOC device.
468 * It can be called by any thread running in any cluster.
469 *
470 * WARNING : For the FAT mapper, the inode field in the mapper MUST be NULL, as this
471 * is used to indicate that the corresponding mapper is the FAT mapper.
472 *****************************************************************************************
473 * @ page_xp   : extended pointer on page descriptor.
474 * @ cmd_type  : IOC_READ / IOC_WRITE / IOC_SYNC_READ / IOC_SYNC_WRITE
475 * @ return 0 if success / return EIO if error during device access.
476 ****************************************************************************************/
477error_t fatfs_move_page( xptr_t      page_xp,
478                         cmd_type_t  cmd_type );
479
480
481
482
483
484
485#endif  /* _FATFS_H_ */
Note: See TracBrowser for help on using the repository browser.