aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiu Aleaxander <Aleaxander@gmail.com>2009-05-13 09:14:49 +0800
committerLiu Aleaxander <Aleaxander@gmail.com>2009-05-13 09:14:49 +0800
commitb6985a112b8a0e34d989d4a57555d0d7318c0718 (patch)
treecaddc69b5d23eaeb0e3118bf151775c1247fa9a1
parent52ab97cab14939b665d6c66b00564004c3911e65 (diff)
downloaddevel-b6985a112b8a0e34d989d4a57555d0d7318c0718.tar.gz
devel-b6985a112b8a0e34d989d4a57555d0d7318c0718.tar.xz
devel-b6985a112b8a0e34d989d4a57555d0d7318c0718.zip
Well, this version added ext4 supported
big changes, ext4 supported and fixed some bugs
-rwxr-xr-xa.outbin27056 -> 29385 bytes
-rw-r--r--ext2_fs.h52
-rw-r--r--extlinux.c164
-rw-r--r--types.h2
4 files changed, 181 insertions, 37 deletions
diff --git a/a.out b/a.out
index 6df4cc2..e478b82 100755
--- a/a.out
+++ b/a.out
Binary files differ
diff --git a/ext2_fs.h b/ext2_fs.h
index eb6b61a..5ed938f 100644
--- a/ext2_fs.h
+++ b/ext2_fs.h
@@ -31,6 +31,11 @@
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK+1)
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK+1)
+
+/* for EXT4 extent */
+#define EXT4_EXT_MAGIC 0xf30a
+#define EXT4_EXTENTS_FLAG 0x00080000
+
/*
* File types and file modes
*/
@@ -197,6 +202,53 @@ struct ext2_dir_entry {
+
+
+/*
+ * This is the extent on-disk structure.
+ * It's used at the bottom of the tree.
+ */
+struct ext4_extent {
+ __u32 ee_block; /* first logical block extent covers */
+ __u16 ee_len; /* number of blocks covered by extent */
+ __u16 ee_start_hi; /* high 16 bits of physical block */
+ __u32 ee_start_lo; /* low 32 bits of physical block */
+};
+
+/*
+ * This is index on-disk structure.
+ * It's used at all the levels except the bottom.
+ */
+struct ext4_extent_idx {
+ __u32 ei_block; /* index covers logical blocks from 'block' */
+ __u32 ei_leaf_lo; /* pointer to the physical block of the next *
+ * level. leaf or next index could be there */
+ __u16 ei_leaf_hi; /* high 16 bits of physical block */
+ __u16 ei_unused;
+};
+
+/*
+ * Each block (leaves and indexes), even inode-stored has header.
+ */
+struct ext4_extent_header {
+ __u16 eh_magic; /* probably will support different formats */
+ __u16 eh_entries; /* number of valid entries */
+ __u16 eh_max; /* capacity of store in entries */
+ __u16 eh_depth; /* has tree real underlying blocks? */
+ __u32 eh_generation; /* generation of the tree */
+};
+
+
+
+#define EXT4_FIRST_EXTENT(header) ( (struct ext4_extent *)(header + 1) )
+#define EXT4_FIRST_INDEX(header) ( (struct ext4_extent_idx *) (header + 1) )
+
+
+
+
+
+
+
/* function declartion */
/*******************************************************************************
extern struct open_file_t * ext2_read(char *);
diff --git a/extlinux.c b/extlinux.c
index d876084..ce494f3 100644
--- a/extlinux.c
+++ b/extlinux.c
@@ -257,7 +257,9 @@ void read_inode(__u32 inode_offset,
*offset = inode_offset % InodePerBlock;
cs = get_cache_block(*block);
- inode = (struct ext2_inode *)cs->data + *offset;
+
+ /* well, in EXT4, the inode structure usually be 256 */
+ inode = (struct ext2_inode *)(cs->data + (*offset * (sb.s_inode_size)));
memcpy(dst, inode, EXT2_GOOD_OLD_INODE_SIZE);
/* for file structure */
@@ -336,38 +338,103 @@ void close_file(struct open_file_t *file)
}
+struct ext4_extent_header *
+ext4_find_leaf (struct ext4_extent_header *eh, __u32 block)
+{
+ struct ext4_extent_idx *index;
+ struct cache_struct *cs;
+ __u64 blk;
+ int i;
+ char buf[ClustSize];
+
+ while (1) {
+
+ index = EXT4_FIRST_INDEX(eh);
+
+ if (eh->eh_magic != EXT4_EXT_MAGIC)
+ return NULL;
+
+ if (eh->eh_depth == 0)
+ return eh;
+
+ for ( i = 0; i < eh->eh_entries; i++ ) {
+ if ( block < index[i].ei_block )
+ break;
+ }
+
+ if ( --i < 0 )
+ return NULL;
+
+ blk = index[i].ei_leaf_hi;
+ blk = (blk << 32) + index[i].ei_leaf_lo;
+
+ /* read the blk to memeory */
+ cs = get_cache_block(blk);
+
+ eh = (struct ext4_extent_header *)(cs->data);
+ }
+}
+
+/* handle the ext4 extents to get the phsical block number */
+__u64 linsector_extent(__u32 block, struct ext2_inode *inode)
+{
+ struct ext4_extent_header *leaf;
+ struct ext4_extent *ext;
+ int i;
+ __u64 start;
+
+ leaf = ext4_find_leaf((struct ext4_extent_header*)inode->i_block,block);
+
+ if (! leaf) {
+ printf("ERROR, extent leaf not found\n");
+ return 0;
+ }
+
+
+ ext = EXT4_FIRST_EXTENT(leaf);
+
+ for ( i = 0; i < leaf->eh_entries; i++ ) {
+ if ( block < ext[i].ee_block)
+ break;
+ }
+
+
+ if ( --i < 0 ) {
+ printf("ERROR, not find the right block\n");
+ return 0;
+ }
+
+
+ /* got it */
+ block -= ext[i].ee_block;
+ if ( block >= ext[i].ee_len)
+ return 0;
+
+ start = ext[i].ee_start_hi;
+ start = (start << 32) + ext[i].ee_start_lo;
+
+ return start + block;
+}
+
/**
- * linsector:
- *
- * Convert a linear sector index in a file to linear sector number
- *
- * well, alought this function converts a linear sector number to
- * physic sector number, it uses block cache in the implemention.
+ * linsector_direct:
*
+ * @param: block, the block index
+ * @param: inode, the inode structure
*
- * @param: line_sector, the linear sector number
- * @param: file, the pointer to open_file_t structure
- *
- * @return: the linear sector number, aka, the physic sector number
+ * @return: the physic block number
*/
-__u32 linsector(__u32 lin_sector, struct open_file_t *file)
+__u32 linsector_direct(__u32 block, struct ext2_inode *inode)
{
struct cache_struct *cs;
- struct ext2_inode *inode;
-
- __u32 block = lin_sector >> ClustShift;
__u32 offset;
-
- /* well, this is what I think the variable ThisInode used for */
- inode = &ThisInode;
-
+
/* direct blocks */
- if ( block < EXT2_NDIR_BLOCKS ) {
- block = inode->i_block[block];
- goto to_sector;
- }
+ if ( block < EXT2_NDIR_BLOCKS )
+ return inode->i_block[block];
+
/* indirect blocks */
block -= EXT2_NDIR_BLOCKS;
@@ -377,8 +444,7 @@ __u32 linsector(__u32 lin_sector, struct open_file_t *file)
cs = get_cache_block(ind_block);
- block = ((__u32 *)cs->data)[block];
- goto to_sector;
+ return ((__u32 *)cs->data)[block];
}
@@ -391,9 +457,7 @@ __u32 linsector(__u32 lin_sector, struct open_file_t *file)
dou_block = ( (__u32 *)cs->data )[block / PtrsPerBlock1];
cs = get_cache_block(dou_block);
- block = ( (__u32*)cs->data )[block % PtrsPerBlock1];
-
- goto to_sector;
+ return ( (__u32*)cs->data )[block % PtrsPerBlock1];
}
@@ -409,20 +473,48 @@ __u32 linsector(__u32 lin_sector, struct open_file_t *file)
tri_block = ((__u32*)cs->data)[block % PtrsPerBlock2];
cs = get_cache_block(tri_block);
- block = ((__u32*)cs->data)[block % PtrsPerBlock1];
- goto to_sector;
+ return ((__u32*)cs->data)[block % PtrsPerBlock1];
}
/* File too big, can not handle */
printf("ERROR, file too big\n");
return 0;
-
- to_sector:
- return ( (block << ClustShift) + (lin_sector & ClustMask) );
}
+/**
+ * linsector:
+ *
+ * Convert a linear sector index in a file to linear sector number
+ *
+ * well, alought this function converts a linear sector number to
+ * physic sector number, it uses block cache in the implemention.
+ *
+ * @param: lin_sector, the lineral sector index
+ *
+ * @return: physic sector number
+ */
+__u32 linsector(__u32 lin_sector)
+{
+ __u32 block = lin_sector >> ClustShift;
+ struct ext2_inode *inode;
+ /* well, this is what I think the variable ThisInode used for */
+ inode = &ThisInode;
+
+ if (inode->i_flags & EXT4_EXTENTS_FLAG)
+ block = linsector_extent(block, inode);
+ else
+ block = (__u32)linsector_direct(block, inode);
+
+ if ( !block ) {
+ printf("WARNING: something error happend at linsector..\n");
+ return 0;
+ }
+
+ /* finally convert it to sector */
+ return ( (block << ClustShift) + (lin_sector & ClustMask) );
+}
/**
@@ -459,7 +551,7 @@ int getfssec(char *buf, struct open_file_t *file, int sectors, int *have_more)
/* get the frament */
sector_idx = file->file_sector;
- next_sector = frag_start = linsector(sector_idx, file);
+ next_sector = frag_start = linsector(sector_idx);
con_sec_cnt = 0;
do {
@@ -480,7 +572,7 @@ int getfssec(char *buf, struct open_file_t *file, int sectors, int *have_more)
*/
sector_idx ++;
next_sector ++;
- }while( next_sector == linsector(sector_idx, file) );
+ }while( next_sector == linsector(sectors) );
@@ -753,7 +845,7 @@ void init_fs(struct ext2_super_block *sb)
blk_size = ClustSize;
DescPerBlock = blk_size / ( 1 << ext2_group_desc_lg2size);
- InodePerBlock = blk_size / EXT2_GOOD_OLD_INODE_SIZE;
+ InodePerBlock = blk_size / sb->s_inode_size;
SecPerClust = ClustSize >> SECTOR_SHIFT;
ClustMask = SecPerClust - 1;
diff --git a/types.h b/types.h
index 79de0bd..4cd3902 100644
--- a/types.h
+++ b/types.h
@@ -1,7 +1,7 @@
#ifndef _TYPES_H
#define _TYPES_H
-
+typedef unsigned long long __u64;
typedef unsigned int __u32;
typedef unsigned short __u16;
typedef unsigned char __u8;