Memory Card File System
Detailed Description
File System API can be used only on devices with memory card:
File System has to be compiled in kernel.
Design aspects:
- small files
- name is not unique (name checking could be time and power consuming)
- sort when files are created, not listed (little RAM - loading and sorting once listed could be time and power consuming)
- minimize number of flashing (power consumption)
- optional encryption
- file type - associated filetype callback
- page refresh (DataFlash specific requirement)
It turned out that existing file systems (notably FAT) were unusable for our purpose.
API
- basic - create file/dir, read/modify file, etc.
- utilities - find and move files, detect memory card, change dir, get file length, delete files in directory, delete dir tree
- security - encrypt/decrypt file with 128bit CBC Twofish
- filetype - register and obtain callback function associated to filetype, set and get file type
- lowlevel - read/modify inode, get number of free blocks
- Note:
- Spider provides functionality for filesystem browsing
Basic Filesystem API
Utility Filesystem API
Security Filesystem API
Filetype API
Low level Filesystem API
- Important:
- File or directory name does not have to be unique. The unique pointer is called inode pointer - u32 number determining inode.
- Note:
- The following text is mainly for information and not necessary for development. Skip if you want to.
The DataFlash memory card is organized into pages, which turbo file system devides into 264 bytes blocks. The number of pages and the number of blocks per page depends on the memory card size. Currently Atmel provides DataFlash MMC packaged cards of three sizes - 2, 4 and 8 Mbytes:
- 2MB AT45DB161B has 4096 pages, 2 blocks per page
- 4MB AT45DB321B has 8192 pages, 2 blocks per page
- 8MB AT45DB642B has 8192 pages, 4 blocks per page
Memory Card Organization
The first page (page number 0), so called "INFO_PAGE" contains basic information, such as the magic string used for format detection, label of the card and also the file system root inode.
The next number_of_all_pages/2048 pages are used for block allocation map - bitmap array, where one bit means block.
The remaining pages are free for user files and directories.
File System Structure
Each block is 264 bytes long, the first 256 bytes are usable space and the remaining 8 bytes has some other meaning, depending whether the block is used for file or directory data. Some bytes have different meaning if the block is the first or the last block of the page.
File System Block
In the above page the green block contains number of page (2 bytes), in case it is the first block of the page, or number of page flashings (4 bytes) in case of the last block of the page. The number of page flashings is used for page refreshing procedure (see Atmel DataFlash datasheets).
Both directory and file blocks have pointers Next Block and Previous Block, but its meaning is different. In case of directory the blocks are linked into 2-way cyclic list, while for the file blocks the Prev Block points:
- to the last block in case of the first block;
- for the second+n*FAST_BLOCK_SKIP(=32) next blocks it points to second+(n+1)*FAST_BLOCK_SKIP block or its value is zero if there is no such block - this feature is used for fast seek;
- for the remaining <second+n*FAST_BLOCK_SKIP+1, second+(n+1)*FAST_BLOCK_SKIP-1> blocks it is the "second+n*FAST_BLOCK_SKIP.
The Next Block always points to the next block in file, the last points to the first.
The result is the semi-2-way cyclic list allowing oneway fast seek.
Directory Block
The directory block contains 8 inodes.
Inode
The inode is a structure containing:
- type, i.e. information whether it points to file, (sub)directory, etc.
- parent - pointer to the parent inode in the directory tree
- content - only for directory inode type, pointer on the first inode in directory.
- previous, next - pointers on previous and next inodes of the directory, inodes are linked in 2-way cyclic list (and content pointing on the start)
- first_block - the file and directory first block
- text - the ALPHA coding coded name.
Structure of file block INODE_TYPE_FILE
The above picture shows the first regular file block.
Structure of encrypted file INODE_TYPE_PROTECTED_KEY_DATA block
This picture shows the Data, Key Encrypted file. The file is encrypted with 128bit Twofish cipher in CBC mode. The 8 byte initial vector is twice on positions [16...23] and [24...31]. This scenario allows to check whether given key is OK and decryption operation can be performed.
- Attention:
- While it weakens the protection and simplifies the brute force attack, it is better than decrypt the file with wrong key and damage it.
Structure of encrypted file INODE_TYPE_PROTECTED_DATA_LEN_TYPE
In this paranoid scheme the type and length of file are shifted to position [8...23] and encrypted as well. Attacker can reveal only the name of file and number of blocks - not even the exact length.
Data Structures
Defines
Typedefs
Functions
- void format (void)
- u8 fs_ino_index (u32 fp)
- u16 fs_ino_block (u32 fp)
- u32 fs_ino_p (u16 block, u8 index)
- u32 ino_parent (Inode *ino)
- void get_inode (Inode *ino, u32 fp)
- void set_inode (Inode *ino, u32 fp)
- void cd_i (u32 fp)
- b32 cd (const u8 *path)
- u32 pwd (void)
- u32 root (void)
- b32 create_file (u32 dir, const u8 *name, u8 sort_flag)
- b32 create_dir (u32 dir, const u8 *name, u8 sort_flag)
- u8 mc_file_encrypt (u32 fp, u8 key[16], u8 flag)
- u8 mc_file_decrypt (u32 desc, u8 key[16])
- b16 delete_files (u32 fp)
- b16 delete_inode (u32 fp)
- u8 mc_set_type (u32 fp, const u8 *type)
- u8 mc_get_type (u32 fp, u8 type[3])
- b32 get_len (u32 fp)
- b32 get_len_raw (u32 fp)
- MCFILE * mc_open (u32 fp, u8 flag)
- b16 mc_read (MCFILE *file, u32 pos, u8 *buf, u8 len)
- b16 mc_rewrite (MCFILE *file, u32 pos, u8 *buf, u8 len)
- b16 mc_append (MCFILE *file, u8 *buf, u8 len)
- b16 mc_close (MCFILE *file)
- b16 mc_clear (u32 fp)
- b32 mc_move (u32 what, u32 to, u8 sort_flag)
- b32 mc_find (b32 file, const u8 *name, u8 type)
- u8 mc_detect (void)
- Inode * inode (void)
- void mc_get_label (u8 label[15])
- void mc_set_label (u8 label[15])
- u16 mc_pages (void)
- u8 mc_blocks (void)
- u16 mc_free (void)
- u8 reg_file_type (const u8 *type, t_file_cb *cb)
- t_file_cb * file_type (u32 file_id)
Define Documentation
|
Filetype callback related, use default behaviour |
|
Indicates APPEND operation. |
|
File callback - DELETE action |
|
File callback - DETAIL action |
|
File callback - MOVE action |
|
Indicates READ operation. |
|
File callback - RENAME action |
|
Indicates REWRITE operation. |
|
File callback - SELECT action |
|
Interpret inode name as MSISDN. Name is expected to be MSISDN_ADN, while searched MSISDN type MSISDN_SMS. |
|
Max. name len (including terminal '\0') |
|
Memory Card present but not formatted |
|
Memory Card present and formatted |
Typedef Documentation
|
Inode
|
|
Memory Card FILE structure. Like FILE but spcific for turbo file system (FILE will be based on MCFILE once implemented). |
Function Documentation
b32 cd |
( |
const u8 * |
path |
) |
|
|
|
Change working directory to a given path. - Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
path | Path, can be stored in RAM, EEPROM, PROGMEM. |
- Returns:
- inode pointer of directory if successful, -ERR_FILE_NOT_FOUND if failed.
- Examples:
-
cells.c, and reader.c.
|
|
Change working directory to directory pointed by pointer. - Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
- Examples:
-
cells.c, mc.c, and reader.c.
|
b32 create_dir |
( |
u32 |
dir, |
|
|
const u8 * |
name, |
|
|
u8 |
sort_flag |
|
) |
|
|
|
Create the new dir in a given directory.
u8 PROGMEM t_dir_name[] = "My Directory";
void foo()
{
b32 dir;
dir=create_dir(root(), t_dir_name, SORT);
}
- Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
- Returns:
- inode pointer>0 if successfull, -ERR_NO_RAM, -ERR_NO_SPACE.
- Examples:
-
cells.c.
|
b32 create_file |
( |
u32 |
dir, |
|
|
const u8 * |
name, |
|
|
u8 |
sort_flag |
|
) |
|
|
|
Create the new file in a given directory.
u8 PROGMEM t_dir_name[] = "My Directory";
u8 PROGMEM t_file_name[] = "My File";
u8 PROGMEM t_file_ext[] = "mxt";
void foo()
{
b32 dir;
b32 file;
MCFILE *fd;
cd_i(root());
dir=cd(t_dir_name);
if(dir<0)
{
}
file=create_dir(dir, t_file_name, SORT);
if(file<0)
{
}
mc_set_type (file, t_file_ext);
fd = mc_open (file, FILE_APPEND);
mc_append (fd, some_data, len_of_some_data);
mc_close (fd);
}
- Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
- Returns:
- inode pointer>0 if successfull, -ERR_NO_RAM, -ERR_NO_SPACE.
- Examples:
-
cells.c.
|
|
Delete all files in the directory. - Note:
- Because of memory reasons the number of deleted files is limited to 85. Use the function more times to delete all files.
- Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
fp | Directory inode pointer. |
- Returns:
- NO_ERROR, ERR_BAD_FILE.
|
|
Returns file callback for given file - Parameters:
-
- Returns:
- callback or NULL if none is associated to the type of given file.
- Examples:
-
mc.c.
|
|
Format memory card.
- Attention:
- Only for tfslib, i.e. programmer. Not available for Turbo.
- Warning:
- Internal inode() use - content will be destroyed.
|
|
Returns the block part of inode pointer. - Parameters:
-
- Returns:
- inode block.
|
u8 fs_ino_index |
( |
u32 |
fp |
) |
|
|
|
Returns the index part of inode pointer. - Parameters:
-
- Returns:
- inode index.
|
|
Converts the block and index to the inode pointer. - Parameters:
-
- Returns:
- inode pointer.
|
|
Returns the content of inode. - Parameters:
-
ino | Pointer on Inode structure to be filled with inode. |
fp | Inode pointer. |
- Examples:
-
mc.c, and reader.c.
|
|
Returns inode pointer of parent. - Parameters:
-
- Returns:
- inode pointer.
- Examples:
-
mc.c.
|
|
The inode() function returns pointer to the Inode structure, which is globaly allocated and usable in your code. Saves RAM and code. - Warning:
- This structure can be used by other functions.
- Examples:
-
mc.c, and reader.c.
|
|
Appends len bytes from buf to file . - Parameters:
-
file | |
len | length of data in buffer |
buf | buffer |
- Returns:
- NO_ERROR if OK, -ERR_BAD_FILE if error.
- Examples:
-
cells.c.
|
|
Returns the number of 264bytes long blocks per page. |
|
Truncate file - clear all the content. - Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
- Returns:
- NO_ERROR, -ERR_BAD_FILE.
|
|
Closes file - must be called to flush all content to memory card and to free all memory. - Parameters:
-
- Returns:
- NO_ERROR.
- Examples:
-
cells.c.
|
u8 mc_file_decrypt |
( |
u32 |
desc, |
|
|
u8 |
key[16] |
|
) |
|
|
u8 mc_file_encrypt |
( |
u32 |
fp, |
|
|
u8 |
key[16], |
|
|
u8 |
flag |
|
) |
|
|
|
Encrypt file pointed on by inode pointer with key and twofish 128bit cypher. - Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
- Returns:
- NO_ERROR, #ERR_BAD_PARMS if wrong flag, ERR_BAD_FILE if not file, ERR_NO_RAM if memory problem.
- Examples:
-
mc.c.
|
b32 mc_find |
( |
b32 |
file, |
|
|
const u8 * |
name, |
|
|
u8 |
type |
|
) |
|
|
|
Find inodes of the given name in the current dir. - Example - Find all occurences of "My File" name
u8 PROGMEM t_file_name[] = "My File";
void foo()
{
b32 file = 0;
cd(...);
do
{
file = mc_find (file, t_file_name, FS_FIND_STRING);
if(file>0)
{
}
} while(file>0);
}
- Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
- Returns:
- inode pointer if >0, -ERR_FILE_NOT_FOUND if not found.
|
|
Returns the number of free file system blocks. |
void mc_get_label |
( |
u8 |
label[15] |
) |
|
|
|
Returns label of the Memory Card. - Parameters:
-
label | Pointer on the buffer where the label is returned. |
- Examples:
-
mc.c.
|
u8 mc_get_type |
( |
u32 |
fp, |
|
|
u8 |
type[3] |
|
) |
|
|
|
Returns file type (3 bytes extension/magic). - Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
fp | Inode pointer on file. |
type | Returned type. |
- Returns:
- ERR_BAD_FILE, NO_ERROR.
- Examples:
-
mc.c.
|
|
Move file/dir form one dir to another. - Parameters:
-
what | Inode pointer on what to move. |
to | Inode pointer on target directory. |
sort_flag | Required sorting, SORT_APPEND, SORT_SMS, #SORT_SMS_SKIP, SORT. |
- Returns:
- NO_ERROR, -ERR_NO_RAM.
|
|
Open file for reading or writing (=appending). - Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
- Returns:
- NULL if failed, MCFILE struct if OK.
- Examples:
-
cells.c.
|
|
Returns the number of Memory Card (DataFlash) pages. |
|
Read len bytes into buf at pos from file . - Parameters:
-
file | |
pos | position |
buf | buffer to fill |
len | length of read |
- Returns:
- nr. of bytes read>=0 if OK, -ERR_WRONG_POS, -ERR_BAD_FILE if error.
|
|
Write len bytes in buf at pos in file . Pos has to be <= file_len - len, otherwise only truncated len. - Parameters:
-
file | |
pos | position |
buf | buffer to write |
len | length of data in buffer |
- Returns:
- nr. of bytes rewriten>=0 OK, -ERR_WRONG_POS, -ERR_BAD_FILE if error.
|
void mc_set_label |
( |
u8 |
label[15] |
) |
|
|
|
Set Memory Card label. - Parameters:
-
label | New Memory Card label. |
- Examples:
-
mc.c.
|
u8 mc_set_type |
( |
u32 |
fp, |
|
|
const u8 * |
type |
|
) |
|
|
|
Set file type (3 bytes extension/magic). - Warning:
- Internal inode() use - content will be destroyed.
- Parameters:
-
fp | Inode pointer on file. |
type | Pointer on u8 type[3], can be RAM, EEPROM, PROGMEM. |
- Returns:
- ERR_BAD_FILE, NO_ERROR.
- Examples:
-
cells.c.
|
|
Returns inode pointer of working directory. - Returns:
- inode pointer.
- Examples:
-
mc.c, and reader.c.
|
|
Associate file type, i.e. 3 letter extension/magic with a given file callback function.
Any application can obtain the cb with file_type() and work with the file.
The following extensions are registered by kernel:
- trb - turbo application
- txt - text file
Example scenario.
We have a file containing SMS specific format message, which viewed as text would not be readable. We have one application (e.g. SMSM Archive) that knows how to display such message and the second application (e.g. memory card viewer) viewing the message.
Application that knows the file (e.g. SMS Archive)
Application that wants to view the file
- Parameters:
-
type | pointer on type in PROGMEM |
cb | callback function |
- Returns:
- NO_ERROR, ERR_NO_EEPROM.
- See also:
- file_type()
|
|
Returns inode pointer of root directory. - Returns:
- root inode pointer.
- Examples:
-
mc.c.
|
|
Sets new inode structure. - Parameters:
-
ino | Pointer on Inode structure containing new inode content. |
fp | inode pointer. |
|
Copyright © 2004-2006 BLADOX
| Turbo version 1.2
|