aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Kardashevskiy <aik@ozlabs.ru>2019-12-30 14:01:24 +1100
committerAlexey Kardashevskiy <aik@ozlabs.ru>2020-02-21 14:03:07 +1100
commitefb21312a4a8290f45acd04460f862a88cc9a75a (patch)
tree01ad45e3a345a718fa8c4b9c165917a04ac124bb
parent9b8e6ab2a41119f6e8d21bbc207c53834bce31ae (diff)
downloadSLOF-efb21312a4a8290f45acd04460f862a88cc9a75a.zip
SLOF-efb21312a4a8290f45acd04460f862a88cc9a75a.tar.gz
SLOF-efb21312a4a8290f45acd04460f862a88cc9a75a.tar.bz2
ext2/4: Add basic extent tree support
This allows booting from ext4 filesystems when EXT4_EXTENTS_FL is set in inode. Based on: https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
-rw-r--r--slof/fs/packages/ext2-files.fs56
1 files changed, 56 insertions, 0 deletions
diff --git a/slof/fs/packages/ext2-files.fs b/slof/fs/packages/ext2-files.fs
index fbfdeeb..7169137 100644
--- a/slof/fs/packages/ext2-files.fs
+++ b/slof/fs/packages/ext2-files.fs
@@ -75,6 +75,61 @@ INSTANCE VARIABLE #blocks-left
;
: inode-i-block ( inode -- block ) 28 + ;
+80000 CONSTANT EXT4_EXTENTS_FL
+: inode-i-flags ( inode -- i_flags ) 20 + l@-le ;
+F30A CONSTANT EXT4_EH_MAGIC
+: extent-tree-entries ( iblock -- entries ) C + ;
+
+STRUCT
+ 2 field ext4-eh>magic
+ 2 field ext4-eh>entries
+ 2 field ext4-eh>max
+ 2 field ext4-eh>depth
+ 4 field ext4-eh>generation
+CONSTANT /ext4-eh
+
+STRUCT
+ 4 field ext4-ee>block
+ 2 field ext4-ee>len
+ 2 field ext4-ee>start_hi
+ 4 field ext4-ee>start_lo
+CONSTANT /ext4-ee
+
+: ext4-ee-start ( entries -- ee-start )
+ dup ext4-ee>start_hi w@-le 32 lshift
+ swap
+ ext4-ee>start_lo l@-le or
+;
+
+: expand-blocks ( start len -- )
+ bounds
+ ?DO
+ i ^blocks @ l!-le
+ 1 blocks-read
+ 1 +LOOP
+;
+
+\ [0x28..0x34] ext4_extent_header
+\ [0x34..0x64] ext4_extent_idx[eh_entries if eh_depth > 0] (not supported)
+\ ext4_extent[eh_entries if eh_depth == 0]
+: read-extent-tree ( inode -- )
+ inode-i-block
+ dup ext4-eh>magic w@-le EXT4_EH_MAGIC <> IF ." BAD extent tree magic" cr EXIT THEN
+ dup ext4-eh>depth w@-le 0 <> IF ." Root inode is not lead, not supported" cr EXIT THEN
+ \ depth=0 means it is a leaf and entries are ext4_extent[eh_entries]
+ dup ext4-eh>entries w@-le
+ >r
+ /ext4-eh +
+ r>
+ 0
+ DO
+ dup ext4-ee-start
+ over ext4-ee>len w@-le ( ext4_extent^ start len )
+ expand-blocks
+ /ext4-ee +
+ LOOP
+ drop
+;
\ Reads block numbers into blocks
: read-block#s ( -- )
@@ -83,6 +138,7 @@ INSTANCE VARIABLE #blocks-left
file-len @ block-size @ // #blocks ! \ *#blocks = roundup(file-len/block-size)
#blocks @ 4 * alloc-mem blocks ! \ *blocks = allocmem(*#blocks)
blocks @ ^blocks ! #blocks @ #blocks-left !
+ inode @ inode-i-flags EXT4_EXTENTS_FL and IF inode @ read-extent-tree EXIT THEN
#blocks-left @ c min \ # direct blocks
inode @ inode-i-block over 4 * ^blocks @ swap move blocks-read
#blocks-left @ IF inode @ 58 + l@-le read-indirect-blocks THEN