diff --git a/lwext4/ext4_mkfs.c b/lwext4/ext4_mkfs.c index 64bbea7..23271ad 100644 --- a/lwext4/ext4_mkfs.c +++ b/lwext4/ext4_mkfs.c @@ -38,8 +38,13 @@ #include "ext4_super.h" #include "ext4_mkfs.h" +#include +#include -static int ext4_mkfs_sb2info(struct ext4_sblock *sb, struct ext4_mkfs_info *info) +#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y)) +#define EXT4_ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y))) + +static int sb2info(struct ext4_sblock *sb, struct ext4_mkfs_info *info) { if (to_le16(sb->magic) != EXT4_SUPERBLOCK_MAGIC) @@ -64,6 +69,40 @@ static int ext4_mkfs_sb2info(struct ext4_sblock *sb, struct ext4_mkfs_info *info return EOK; } +static int info2sb(struct ext4_mkfs_info *info, struct ext4_sblock *sb) +{ + (void)info; + memset(sb, 0, sizeof(struct ext4_sblock)); + /*TODO: Fill superblock with proper values*/ + + return EOK; +} + +static uint32_t compute_blocks_per_group(struct ext4_mkfs_info *info) +{ + return info->block_size * 8; +} + +static uint32_t compute_inodes(struct ext4_mkfs_info *info) +{ + return DIV_ROUND_UP(info->len, info->block_size) / 4; +} + +static uint32_t compute_inodes_per_group(struct ext4_mkfs_info *info) +{ + uint32_t blocks = DIV_ROUND_UP(info->len, info->block_size); + uint32_t block_groups = DIV_ROUND_UP(blocks, info->blocks_per_group); + uint32_t inodes = DIV_ROUND_UP(info->inodes, block_groups); + inodes = EXT4_ALIGN(inodes, (info->block_size / info->inode_size)); + + /* After properly rounding up the number of inodes/group, + * make sure to update the total inodes field in the info struct. + */ + info->inodes = inodes * block_groups; + + return inodes; +} + int ext4_mkfs_read_info(struct ext4_blockdev *bd, struct ext4_mkfs_info *info) { @@ -82,7 +121,7 @@ int ext4_mkfs_read_info(struct ext4_blockdev *bd, struct ext4_mkfs_info *info) if (r != EOK) goto Finish; - r = ext4_mkfs_sb2info(sb, info); + r = sb2info(sb, info); Finish: if (sb) @@ -93,9 +132,53 @@ Finish: int ext4_mkfs(struct ext4_blockdev *bd, struct ext4_mkfs_info *info) { - (void)bd; - (void)info; - return EOK; + int r; + struct ext4_sblock *sb = NULL; + r = ext4_block_init(bd); + if (r != EOK) + return r; + + sb = malloc(sizeof(struct ext4_sblock)); + if (!sb) + goto Finish; + + if (info->block_size == 0) + info->block_size = 4096; /*Set block size to default value*/ + + /* Round down the filesystem length to be a multiple of the block size */ + info->len &= ~((uint64_t)info->block_size - 1); + + + if (info->blocks_per_group == 0) + info->blocks_per_group = compute_blocks_per_group(info); + + if (info->inodes == 0) + info->inodes = compute_inodes(info); + + if (info->inode_size == 0) + info->inode_size = 256; + + if (info->label == NULL) + info->label = ""; + + info->inodes_per_group = compute_inodes_per_group(info); + + info->feat_compat = CONFIG_FEATURE_COMPAT_SUPP; + info->feat_ro_compat = CONFIG_FEATURE_RO_COMPAT_SUPP; + info->feat_incompat = CONFIG_FEATURE_INCOMPAT_SUPP; + + + r = info2sb(info, sb); + if (r != EOK) + return r; + + /*TODO: write fisesystem metadata*/ + + Finish: + if (sb) + free(sb); + ext4_block_fini(bd); + return r; } /**