Author | Sebastien Lelong, Copyright © 2011, all rights reserved. |
Adapted-by | |
Compiler | 2.4o |
Minix v2 implementation Partitions aren't supported, so you have to create a filesystem on the whole available memory. Typically, instead of "mkfs.minix -v /dev/sdX1", you'll have to "mkfs.minix -v /dev/sdX" (and remove sdX1 partition with fdisk) Some useful commands: - fsck.minix -f -v -s /dev/sdX will print Super-Block and some other information about files, dirs, state - hexdump -C /dev/sdX will dump Minix FS content (only changing lines) - hexdump -v -C /dev/sdX will do the same, but dump all lines, even if identical . In order to test your setup, you can untar minix_data.tar.bz2 available at: ... This archive contains directories and files of different size, used to test data zone and helping to understand how Minix filesystem is designed. 1. prepare your device, no partition (replace /dev/sdX with appropriate device): mkfs.minix -v /dev/sdX mount /dev/sdX /mnt/tmp 2. untar test data: cd /mnt/tmp && tar xjfv path/to/minix_data.tar.bz2 cd && umount /mnt/tmp 3. check content: fsck.minix -f -v -s /dev/sdX should report something like (1GB SD-card used here): . Forcing filesystem check on /dev/sdX. 65535 inodes 992000 blocks Firstdatazone=4227 (4227) Zonesize=1024 Maxsize=2147483647 Filesystem state=1 namelen=30 . 20 inodes used (0%) 70858 zones used (7%) . 16 regu 16 regular files 2 directories 0 character device files 0 block device files 1 links 2 symbolic links ------ 21 files . Vocabulary: these are the terms I'm using in this code, may be wrong... * storage: this is the underlying storage layer. Link between MinixFS and storage is done by creating aliases to some spefici proc/funcs. Typically, storage is sd_card.jal library. It could also be hard-disk too. * sector: this is a unit in underlying storage (eg. for SD cards, 512 bytes) * block: this is a unit in minixfs (typically 1024 bytes, that is, 2 * sector's size with SD cards) * zone: same as a block in case of Minix v2 * inode: well, that's an inode, a kind of meta description of a file * file descriptor: a structure composed with an inode and several information to track how file was opened and where we are within a file (well, again, that's a file descriptor)
* I developped this lib and tested it with sd_card storage. It should be possible to use other * storages though not tested nor even tried. * to developpers: this piece of code is tricky... If you plan to modify this lib, take huge care at variables initialization, there are special values I used, mostly to rollover to 0 when first accessed. It could have been simpler but would have used more variables and thus more resources. There are many counters which, when reaching a specific value, trigger actions (like flushing data, going to next zone, allocate a new zone, etc...). Just don't assume it'll work just because you added a small little line, because everything is quite tied together and you could be victim of an (un)expected butterfly effect :) I myself broke features many times with supposedly minor changes, hurting my brain a lot. Being polite...
var word minix_sector_progress = 0
const byte MINIX_ZONE_TRIPLE_INDIRECT = 0b_1000
const word MINIX_SUPER_MAGIC = 0x137F
const word MINIX_SUPER_MAGIC2 = 0x138F
const dword MINIX_MAX_DIRECT_ZONE_SIZE = MINIX_NUM_DIRECT_ZONES * MINIX_BYTES_PER_BLOCK
const byte MINIX_ERR_NONE = 0b_0000_0000
const word MINIX_BOOT_BLOCK_ADDRESS = 0x00
const dword MINIX_NUM_ZONE_BITS_PER_BLOCK = MINIX_BYTES_PER_BLOCK * 8
var byte _minix_last_error = MINIX_ERR_NONE
const word MINIX2_SUPER_MAGIC = 0x2468
const word MINIX_SUPER_BLOCK_ADDRESS = MINIX_BOOT_BLOCK_ADDRESS + MINIX_BYTES_PER_BLOCK
const word MINIX_INODE_ROOT_ID = 1
const byte MINIX_MODE_WRITE = 0b010
const word MINIX_BYTES_PER_INODE = 0x40
const byte MINIX_ERR_NO_SUCH_FILE = 0b_0000_1000
var minix_superblock minix_sb
const byte MINIX_ERR_NOT_DIRECTORY = 0b_0000_0100
const word MINIX_BYTES_PER_BLOCK = 0x400
const word MINIX_MAX_INDIRECT_ZONE_IDX = 0x03FC
const byte MINIX_MAX_FILENANE_LEN = 30
const byte MINIX_NUM_DIRECT_ZONES = 7
const word MINIX2_SUPER_MAGIC2 = 0x2478
const byte MINIX_MODE_APPEND = 0b100
const byte MINIX_ZONE_NONE = 0b_0000
var dword minix_storage_address = 0
const byte MINIX_ZONE_INDIRECT = 0b_0010
const byte MINIX_ZONE_DOUBLE_INDIRECT = 0b_0100
const byte MINIX_ERR_BAD_ADDRESS = 0b_0010_0000
var minix_fd minix_filefd
var dword minix_curzone
var word minix_cwd
const dword MINIX_NUM_INDIRECT_ZONES = 256
const dword MINIX_NUM_DOUBLE_INDIRECT_ZONES = 65536
const dword MINIX_MAX_INDIRECT_ZONE_SIZE = (MINIX_NUM_INDIRECT_ZONES * MINIX_BYTES_PER_BLOCK) + MINIX_MAX_DIRECT_ZONE_SIZE
const word MINIX3_SUPER_MAGIC = 0x4D5A
const byte MINIX_ZONE_DIRECT = 0b_0001
const byte MINIX_MODE_READ = 0b001
const byte MINIX_ERR_END_OF_FILE = 0b_0001_0000
var byte minix_curzonetab[4] at minix_curzone
const byte MINIX_MAX_DIRECT_ZONE_IDX = 6
const word MINIX_MAX_DOUBLE_DIRECT_ZONE_IDX = 0x03FC
const byte MINIX_ERR_BAD_ZONE_LOCATION = 0b_0000_0010
const byte MINIX_ERR_BAD_MAGIC_NUMBER = 0b_0000_0001
minix_read_super_block(bit in check_data_zone)
minix_close()
minix_init(bit in check)
minix_next_zone(bit in create_zone)
minix_open_block_byte(dword in blocknum, word in bytenum)
minix_flush()
minix_storage_write_byte(byte in data)
minix_seek(dword in bytenum)
minix_load_inode(word in inode_num)
minix_cd(byte in dirname[MINIX_MAX_FILENANE_LEN])
minix_storage_flush()
minix_last_error'put(byte in val)
minix_openi(word in inode_num,byte in mode)
minix_cdi(word in inode_num)
minix_write(byte in data)
minix_open_block(dword in num)
minix_open(byte in filename[MINIX_MAX_FILENANE_LEN],byte in mode)
minix_save_inode()
minix_zone_alloc() return dword
minix_find_in_cwd(byte in filename[MINIX_MAX_FILENANE_LEN]) return word
minix_last_error'get() return byte
minix_read() return byte
minix_next_entry'get() return minix_dir_entry
minix_storage_read_byte() return byte
var word minix_sector_progress = 0
track progress while accessing underlying storage sector
const byte MINIX_ZONE_TRIPLE_INDIRECT = 0b_1000
No documentation found
const word MINIX_SUPER_MAGIC = 0x137F
Magic numbers used to idenfity filesystem version
const word MINIX_SUPER_MAGIC2 = 0x138F
minix fs, 30 char names
const dword MINIX_MAX_DIRECT_ZONE_SIZE = MINIX_NUM_DIRECT_ZONES * MINIX_BYTES_PER_BLOCK
No documentation found
const byte MINIX_ERR_NONE = 0b_0000_0000
Error constants. Following "mkfs" convention, errors are added, so minix_last_error can embed several errors
const word MINIX_BOOT_BLOCK_ADDRESS = 0x00
Super Block is one block after boot block
const dword MINIX_NUM_ZONE_BITS_PER_BLOCK = MINIX_BYTES_PER_BLOCK * 8
No documentation found
var byte _minix_last_error = MINIX_ERR_NONE
Auto-resetting variable: errors are added, and when read, reset to 0
const word MINIX2_SUPER_MAGIC = 0x2468
minix V2 fs
const word MINIX_SUPER_BLOCK_ADDRESS = MINIX_BOOT_BLOCK_ADDRESS + MINIX_BYTES_PER_BLOCK
No documentation found
const word MINIX_INODE_ROOT_ID = 1
Inode --
const byte MINIX_MODE_WRITE = 0b010
No documentation found
const word MINIX_BYTES_PER_INODE = 0x40
64B per inode
const byte MINIX_ERR_NO_SUCH_FILE = 0b_0000_1000
try to access invalid/unexisting filename or inode
var minix_superblock minix_sb
super-block
const byte MINIX_ERR_NOT_DIRECTORY = 0b_0000_0100
try to act on a directory, but inode isn't a directory
const word MINIX_BYTES_PER_BLOCK = 0x400
1KB per block
const word MINIX_MAX_INDIRECT_ZONE_IDX = 0x03FC
0x400 - 4 == one block - one location
const byte MINIX_MAX_FILENANE_LEN = 30
max filename size according to minix v2
const byte MINIX_NUM_DIRECT_ZONES = 7
No documentation found
const word MINIX2_SUPER_MAGIC2 = 0x2478
minix V2 fs, 30 char names
const byte MINIX_MODE_APPEND = 0b100
write implied
const byte MINIX_ZONE_NONE = 0b_0000
No documentation found
var dword minix_storage_address = 0
track underlying storage address
const byte MINIX_ZONE_INDIRECT = 0b_0010
No documentation found
const byte MINIX_ZONE_DOUBLE_INDIRECT = 0b_0100
No documentation found
const byte MINIX_ERR_BAD_ADDRESS = 0b_0010_0000
bad block address
var minix_fd minix_filefd
file descriptor currently being accessed (file)
var dword minix_curzone
No documentation found
var word minix_cwd
current working directory (CWD) inode number
const dword MINIX_NUM_INDIRECT_ZONES = 256
No documentation found
const dword MINIX_NUM_DOUBLE_INDIRECT_ZONES = 65536
No documentation found
const dword MINIX_MAX_INDIRECT_ZONE_SIZE = (MINIX_NUM_INDIRECT_ZONES * MINIX_BYTES_PER_BLOCK) + MINIX_MAX_DIRECT_ZONE_SIZE
No documentation found
const word MINIX3_SUPER_MAGIC = 0x4D5A
minix V3 fs
const byte MINIX_ZONE_DIRECT = 0b_0001
No documentation found
const byte MINIX_MODE_READ = 0b001
File descriptor constants
const byte MINIX_ERR_END_OF_FILE = 0b_0001_0000
reached EOF
var byte minix_curzonetab[4] at minix_curzone
No documentation found
const byte MINIX_MAX_DIRECT_ZONE_IDX = 6
No documentation found
const word MINIX_MAX_DOUBLE_DIRECT_ZONE_IDX = 0x03FC
0x400 - 4 == one block - one location
const byte MINIX_ERR_BAD_ZONE_LOCATION = 0b_0000_0010
something is wrong about declared and computed data location
const byte MINIX_ERR_BAD_MAGIC_NUMBER = 0b_0000_0001
magic number unsupported
minix_read_super_block(bit in check_data_zone)
Read Super-Block and fill record
minix_close()
No documentation found
minix_init(bit in check)
No documentation found
minix_next_zone(bit in create_zone)
move to next data zone, being direct, indirect ou double indirect
minix_open_block_byte(dword in blocknum, word in bytenum)
move to block number, then to byte number within the block
minix_flush()
No documentation found
minix_storage_write_byte(byte in data)
"Raw" read one byte from underlying storage.
minix_seek(dword in bytenum)
move to byte bytenum within a file Notes: assuming file was just opened, no data read bytenum must be <= filesize, if greater, expect troubles
minix_load_inode(word in inode_num)
Load inode data, identified by inode_num, into file descriptor's (minix_filefd) inode parameter
minix_cd(byte in dirname[MINIX_MAX_FILENANE_LEN])
No documentation found
minix_storage_flush()
No documentation found
minix_last_error'put(byte in val)
No documentation found
minix_openi(word in inode_num,byte in mode)
No documentation found
minix_cdi(word in inode_num)
No documentation found
minix_write(byte in data)
write a byte to current opened file descriptor
minix_open_block(dword in num)
move to block number and open read access on underlying storage
minix_open(byte in filename[MINIX_MAX_FILENANE_LEN],byte in mode)
No documentation found
minix_save_inode()
Save current file desc's inode (minix_filefd.inode)
minix_zone_alloc() return dword
Walk accross zone bitmap, searching for a free zone number (identified by 0s) and return available zone number. /!\ zone bitmap and file's content obviously aren't located the same. This means when allocating, we're moving in a different place (zone bitmap) than we previously were while writing into the file. It's the caller's responsability to move the correct location once allocation is done. Yes, that's right: it's dirty, as zone_alloc() won't let the system in its previous state. ("why ?" you may ask... because it's simpler like that, and anyway, this procedure is somewhat internal, so it shouldn't be a problem in the end).
minix_find_in_cwd(byte in filename[MINIX_MAX_FILENANE_LEN]) return word
return inode number found for given filename can be a file or a dir name) in current directory
minix_last_error'get() return byte
No documentation found
minix_read() return byte
Read bytes from file descriptor. Walk over memory zones given, returning content byte by byte. firt walk over direct zones, then swith indirect then double indirect zones. Keep track of progress within inode
minix_next_entry'get() return minix_dir_entry
list current working directory (cwd), returning a directory entry each time it's called, until no more entry found.
minix_storage_read_byte() return byte
"Raw" read one byte from underlying storage.
18f27j53 | 18f27j53_sd_card_minix_demo.jal |
18f27j53 | 18f27j53_sd_card_minix_readi.jal |
18f27j53 | 18f27j53_sd_card_minix_read.jal |