From: Graeme Russ <graeme.russ@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] Subject: [PATCH 1/2] ext4fs ls load support
Date: Mon, 12 Dec 2011 23:12:30 +1100 [thread overview]
Message-ID: <4EE5EFAE.1040708@gmail.com> (raw)
In-Reply-To: <8DCC78758C8A458F900F9F5885BA589A@sisodomain.com>
Hi Uma,
On 12/12/11 21:45, uma.shankar at samsung.com wrote:
> From: Uma Shankar <uma.shankar@samsung.com>
> Date: Mon, 12 Dec 2011 12:01:22 +0530
> Subject: [PATCH 1/2] ext4fs ls load support
>
> Signed-off-by: Uma Shankar <uma.shankar@samsung.com>, Manjunatha C Achar
> <a.manjunatha@samsung.com>
I think all SoBs belong on their own line
> Signed-off-by: Iqbal Shareef <iqbal.ams@samsung.com>
> Signed-off-by: Hakgoo Lee <goodguy.lee@samsung.com>
> ---
> Makefile | 2 +-
> common/Makefile | 1 +
> common/cmd_ext4.c | 255 ++++++++++++++++++++++
> fs/Makefile | 1 +
> fs/ext2/ext2fs.c | 303 +--------------------------
> fs/ext4/Makefile | 51 +++++
> fs/ext4/ext4_common.c | 572 +++++++++++++++++++++++++++++++++++++++++++++++++
> fs/ext4/ext4_common.h | 44 ++++
> fs/ext4/ext4fs.c | 215 ++++++++++++++++++
> include/ext2fs.h | 177 +++++++++++++++-
> include/ext4fs.h | 164 ++++++++++++++
> 11 files changed, 1478 insertions(+), 307 deletions(-)
> create mode 100644 common/cmd_ext4.c
> create mode 100644 fs/ext4/Makefile
> create mode 100644 fs/ext4/ext4_common.c
> create mode 100644 fs/ext4/ext4_common.h
> create mode 100644 fs/ext4/ext4fs.c
> create mode 100644 include/ext4fs.h
>
> diff --git a/Makefile b/Makefile
> index fb658f4..5f29812 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -235,7 +235,7 @@ LIBS += dts/libdts.o
> endif
> LIBS += arch/$(ARCH)/lib/lib$(ARCH).o
> LIBS += fs/cramfs/libcramfs.o fs/fat/libfat.o fs/fdos/libfdos.o
> fs/jffs2/libjffs2.o \
> - fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o fs/yaffs2/libyaffs2.o \
> + fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o fs/ext4/libext4fs.o
> fs/yaffs2/libyaffs2.o \
> fs/ubifs/libubifs.o
> LIBS += net/libnet.o
> LIBS += disk/libdisk.o
> diff --git a/common/Makefile b/common/Makefile
> index 1b672ad..d7fd4a8 100644
> --- a/common/Makefile
> +++ b/common/Makefile
> @@ -90,6 +90,7 @@ COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
> COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o
> COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o
> COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o
> +COBJS-$(CONFIG_CMD_EXT4) += cmd_ext4.o
> COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o
> COBJS-$(CONFIG_CMD_FDC)$(CONFIG_CMD_FDOS) += cmd_fdc.o
> COBJS-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o
> diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c
> new file mode 100644
> index 0000000..b223443
> --- /dev/null
> +++ b/common/cmd_ext4.c
> @@ -0,0 +1,255 @@
> +/*
> + * (C) Copyright 2011 Samsung Electronics
> + * EXT4 filesystem implementation in Uboot by
> + * Uma Shankar <uma.shankar@samsung.com>
> + * Manjunatha C Achar <a.manjunatha@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + *
> + */
> +
> +/*
> + * Ext4fs support
> + * made from existing cmd_ext2.c file of Uboot
> + */
> +#include <common.h>
> +#include <part.h>
> +#include <config.h>
> +#include <command.h>
> +#include <image.h>
> +#include <linux/ctype.h>
> +#include <asm/byteorder.h>
> +#include <ext2fs.h>
> +#include <ext4fs.h>
> +#include <linux/stat.h>
> +#include "../disk/part_dos.h"
Don't use relative include paths
> +#include <malloc.h>
> +
> +#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
> +#include <usb.h>
> +#endif
> +
> +#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION)
> +#error DOS or EFI partition support must be selected
> +#endif
> +
> +uint64_t total_sector;
> +uint64_t part_offset;
> +static uint64_t part_size;
> +static uint16_t cur_part = 1;
> +
> +#define DOS_PART_MAGIC_OFFSET 0x1fe
> +#define DOS_FS_TYPE_OFFSET 0x36
> +#define DOS_FS32_TYPE_OFFSET 0x52
> +
> +int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
> +{
> + char *filename = NULL;
Wrong indent style - use tabs
> + char *ep;
> + int dev, part = 1;
> + ulong addr = 0, part_length;
I've never been a fan of multiple declarations on the same line (especially
if some are assigned a value and some not) - I'll defer to others for an
'official' position on this
> + int filelen;
> + disk_partition_t info;
> + ExtFileSystem *fs;
No camel case
> + char buf[12];
> + unsigned long count;
> + char *addr_str;
> +
> + switch (argc) {
> + case 3:
> + addr_str = getenv("loadaddr");
> + if (addr_str != NULL)
> + addr = strict_strtoul(addr_str, NULL, 16);
> + else
> + addr = CONFIG_SYS_LOAD_ADDR;
> +
> + filename = getenv("bootfile");
> + count = 0;
> + break;
> + case 4:
> + addr = strict_strtoul(argv[3], NULL, 16);
> + filename = getenv("bootfile");
> + count = 0;
> + break;
> + case 5:
> + addr = strict_strtoul(argv[3], NULL, 16);
> + filename = argv[4];
> + count = 0;
> + break;
> + case 6:
> + addr = strict_strtoul(argv[3], NULL, 16);
> + filename = argv[4];
> + count = strict_strtoul(argv[5], NULL, 16);
> + break;
> +
> + default:
> + return cmd_usage(cmdtp);
> + }
> +
> + if (!filename) {
> + puts("** No boot file defined **\n");
Nice to see you used puts() instead of printf() - One day we'll tidy this
up globally :)
> + return 1;
> + }
> +
> + dev = (int)strict_strtoul(argv[2], &ep, 16);
> + ext4_dev_desc = get_dev(argv[1], dev);
> + if (ext4_dev_desc == NULL) {
> + printf("** Block device %s %d not supported\n", argv[1], dev);
> + return 1;
> + }
> + if (init_fs(ext4_dev_desc))
> + return 1;
> +
> + fs = get_fs();
> + if (*ep) {
> + if (*ep != ':') {
> + puts("** Invalid boot device, use `dev[:part]' **\n");
> + return 1;
> + }
> + part = (int)strict_strtoul(++ep, NULL, 16);
> + }
> +
> + if (part != 0) {
> + if (get_partition_info(fs->dev_desc, part, &info)) {
> + printf("** Bad partition %d **\n", part);
> + return 1;
> + }
> +
> + if (strncmp((char *)info.type, BOOT_PART_TYPE,
> + sizeof(info.type)) != 0) {
> + printf("** Invalid partition type \"%.32s\""
> + " (expect \"" BOOT_PART_TYPE "\")\n", info.type);
> + return 1;
> + }
> + printf("Loading file \"%s\" "
> + "from %s device %d:%d (%.32s)\n",
> + filename, argv[1], dev, part, info.name);
> + } else {
> + printf("Loading file \"%s\" from %s device %d\n",
> + filename, argv[1], dev);
> + }
> +
> + part_length = ext2fs_set_blk_dev(fs->dev_desc, part);
> + if (part_length == 0) {
> + printf("**Bad partition - %s %d:%d **\n", argv[1], dev, part);
> + ext4fs_close();
> + return 1;
> + }
> +
> + if (!ext4fs_mount(part_length)) {
> + printf("** Bad ext2 partition or disk - %s %d:%d **\n",
> + argv[1], dev, part);
> + ext4fs_close();
> + return 1;
> + }
> +
> + filelen = ext4fs_open(filename);
> + if (filelen < 0) {
> + printf("** File not found %s\n", filename);
> + ext4fs_close();
> + return 1;
> + }
> + if ((count < filelen) && (count != 0))
> + filelen = count;
> +
> + if (ext4fs_read((char *)addr, filelen) != filelen) {
> + printf("** Unable to read \"%s\" from %s %d:%d **\n",
> + filename, argv[1], dev, part);
> + ext4fs_close();
> + return 1;
> + }
> +
> + ext4fs_close();
> + deinit_fs(fs->dev_desc);
> + /* Loading ok, update default load address */
> + load_addr = addr;
> +
> + printf("%d bytes read\n", filelen);
> + sprintf(buf, "%X", filelen);
> + setenv("filesize", buf);
> +
> + return 0;
> +}
> +
> +int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
> +{
> + char *filename = "/";
> + int dev = 0;
> + int part = 1;
> + char *ep;
> + ExtFileSystem *fs;
> + int part_length;
> +
> + if (argc < 3)
> + return cmd_usage(cmdtp);
> +
> + dev = (int)strict_strtoul(argv[2], &ep, 16);
> + ext4_dev_desc = get_dev(argv[1], dev);
> +
> + if (ext4_dev_desc == NULL) {
> + printf("\n** Block device %s %d not supported\n", argv[1], dev);
> + return 1;
> + }
> +
> + if (init_fs(ext4_dev_desc))
> + return 1;
> +
> + fs = get_fs();
> + if (*ep) {
> + if (*ep != ':') {
> + puts("\n** Invalid boot device, use `dev[:part]' **\n");
> + return 1;
> + }
> + part = (int)strict_strtoul(++ep, NULL, 16);
> + }
> +
> + if (argc == 4)
> + filename = argv[3];
> +
> + part_length = ext2fs_set_blk_dev(fs->dev_desc, part);
> + if (part_length == 0) {
> + printf("** Bad partition - %s %d:%d **\n", argv[1], dev, part);
> + ext4fs_close();
> + return 1;
> + }
> +
> + if (!ext4fs_mount(part_length)) {
> + printf("** Bad ext2 partition or disk - %s %d:%d **\n",
> + argv[1], dev, part);
> + ext4fs_close();
> + return 1;
> + }
> + if (ext4fs_ls(filename)) {
> + printf("** Error ext2fs_ls() **\n");
> + ext4fs_close();
> + return 1;
> + };
> +
> + ext4fs_close();
> + deinit_fs(fs->dev_desc);
> + return 0;
> +}
> +
> +U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls,
> + "list files in a directory (default /)",
> + "<interface> <dev[:part]> [directory]\n"
> + " - list files from 'dev' on 'interface' in a 'directory'");
> +
> +U_BOOT_CMD(ext4load, 6, 0, do_ext4_load,
> + "load binary file from a Ext2 filesystem",
> + "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
> + " - load binary file 'filename' from 'dev' on 'interface'\n"
> + " to address 'addr' from ext2 filesystem");
> diff --git a/fs/Makefile b/fs/Makefile
> index 22aad12..27330d4 100644
> --- a/fs/Makefile
> +++ b/fs/Makefile
> @@ -24,6 +24,7 @@
>
> subdirs-$(CONFIG_CMD_CRAMFS) := cramfs
> subdirs-$(CONFIG_CMD_EXT2) += ext2
> +subdirs-$(CONFIG_CMD_EXT4) += ext4
> subdirs-$(CONFIG_CMD_FAT) += fat
> subdirs-$(CONFIG_CMD_FDOS) += fdos
> subdirs-$(CONFIG_CMD_JFFS2) += jffs2
> diff --git a/fs/ext2/ext2fs.c b/fs/ext2/ext2fs.c
> index e119e13..058b650 100644
> --- a/fs/ext2/ext2fs.c
> +++ b/fs/ext2/ext2fs.c
> @@ -25,150 +25,10 @@
>
> #include <common.h>
> #include <ext2fs.h>
> +#include <ext4fs.h>
Hmm, seems odd to include an ext4fs include in ext2fs - I understand what
you are doing, but should there be an extfs_common.h which holds the common
defines?
> #include <malloc.h>
> #include <asm/byteorder.h>
>
> -extern int ext2fs_devread (int sector, int byte_offset, int byte_len,
> - char *buf);
> -
> -/* Magic value used to identify an ext2 filesystem. */
> -#define EXT2_MAGIC 0xEF53
> -/* Amount of indirect blocks in an inode. */
> -#define INDIRECT_BLOCKS 12
> -/* Maximum lenght of a pathname. */
> -#define EXT2_PATH_MAX 4096
> -/* Maximum nesting of symlinks, used to prevent a loop. */
> -#define EXT2_MAX_SYMLINKCNT 8
> -
> -/* Filetype used in directory entry. */
> -#define FILETYPE_UNKNOWN 0
> -#define FILETYPE_REG 1
> -#define FILETYPE_DIRECTORY 2
> -#define FILETYPE_SYMLINK 7
> -
> -/* Filetype information as used in inodes. */
> -#define FILETYPE_INO_MASK 0170000
> -#define FILETYPE_INO_REG 0100000
> -#define FILETYPE_INO_DIRECTORY 0040000
> -#define FILETYPE_INO_SYMLINK 0120000
> -
> -/* Bits used as offset in sector */
> -#define DISK_SECTOR_BITS 9
> -
> -/* Log2 size of ext2 block in 512 blocks. */
> -#define LOG2_EXT2_BLOCK_SIZE(data) (__le32_to_cpu
> (data->sblock.log2_block_size) + 1)
> -
> -/* Log2 size of ext2 block in bytes. */
> -#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu
> (data->sblock.log2_block_size) + 10)
> -
> -/* The size of an ext2 block in bytes. */
> -#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
> -
> -/* The ext2 superblock. */
> -struct ext2_sblock {
> - uint32_t total_inodes;
> - uint32_t total_blocks;
> - uint32_t reserved_blocks;
> - uint32_t free_blocks;
> - uint32_t free_inodes;
> - uint32_t first_data_block;
> - uint32_t log2_block_size;
> - uint32_t log2_fragment_size;
> - uint32_t blocks_per_group;
> - uint32_t fragments_per_group;
> - uint32_t inodes_per_group;
> - uint32_t mtime;
> - uint32_t utime;
> - uint16_t mnt_count;
> - uint16_t max_mnt_count;
> - uint16_t magic;
> - uint16_t fs_state;
> - uint16_t error_handling;
> - uint16_t minor_revision_level;
> - uint32_t lastcheck;
> - uint32_t checkinterval;
> - uint32_t creator_os;
> - uint32_t revision_level;
> - uint16_t uid_reserved;
> - uint16_t gid_reserved;
> - uint32_t first_inode;
> - uint16_t inode_size;
> - uint16_t block_group_number;
> - uint32_t feature_compatibility;
> - uint32_t feature_incompat;
> - uint32_t feature_ro_compat;
> - uint32_t unique_id[4];
> - char volume_name[16];
> - char last_mounted_on[64];
> - uint32_t compression_info;
> -};
> -
> -/* The ext2 blockgroup. */
> -struct ext2_block_group {
> - uint32_t block_id;
> - uint32_t inode_id;
> - uint32_t inode_table_id;
> - uint16_t free_blocks;
> - uint16_t free_inodes;
> - uint16_t used_dir_cnt;
> - uint32_t reserved[3];
> -};
> -
> -/* The ext2 inode. */
> -struct ext2_inode {
> - uint16_t mode;
> - uint16_t uid;
> - uint32_t size;
> - uint32_t atime;
> - uint32_t ctime;
> - uint32_t mtime;
> - uint32_t dtime;
> - uint16_t gid;
> - uint16_t nlinks;
> - uint32_t blockcnt; /* Blocks of 512 bytes!! */
> - uint32_t flags;
> - uint32_t osd1;
> - union {
> - struct datablocks {
> - uint32_t dir_blocks[INDIRECT_BLOCKS];
> - uint32_t indir_block;
> - uint32_t double_indir_block;
> - uint32_t tripple_indir_block;
> - } blocks;
> - char symlink[60];
> - } b;
> - uint32_t version;
> - uint32_t acl;
> - uint32_t dir_acl;
> - uint32_t fragment_addr;
> - uint32_t osd2[3];
> -};
> -
> -/* The header of an ext2 directory entry. */
> -struct ext2_dirent {
> - uint32_t inode;
> - uint16_t direntlen;
> - uint8_t namelen;
> - uint8_t filetype;
> -};
> -
> -struct ext2fs_node {
> - struct ext2_data *data;
> - struct ext2_inode inode;
> - int ino;
> - int inode_read;
> -};
> -
> -/* Information about a "mounted" ext2 filesystem. */
> -struct ext2_data {
> - struct ext2_sblock sblock;
> - struct ext2_inode *inode;
> - struct ext2fs_node diropen;
> -};
> -
> -
> -typedef struct ext2fs_node *ext2fs_node_t;
> -
> struct ext2_data *ext2fs_root = NULL;
> ext2fs_node_t ext2fs_file = NULL;
> int symlinknest = 0;
> @@ -180,7 +40,6 @@ int indir2_size = 0;
> int indir2_blkno = -1;
> static unsigned int inode_size;
>
> -
> static int ext2fs_blockgroup
> (struct ext2_data *data, int group, struct ext2_block_group *blkgrp) {
> unsigned int blkno;
> @@ -198,10 +57,8 @@ static int ext2fs_blockgroup
> #endif
> return (ext2fs_devread (blkno << LOG2_EXT2_BLOCK_SIZE(data),
> blkoff, sizeof(struct ext2_block_group), (char *)blkgrp));
> -
> }
>
> -
> static int ext2fs_read_inode
> (struct ext2_data *data, int ino, struct ext2_inode *inode) {
> struct ext2_block_group blkgrp;
> @@ -242,153 +99,12 @@ static int ext2fs_read_inode
> return (1);
> }
>
> -
> void ext2fs_free_node (ext2fs_node_t node, ext2fs_node_t currroot) {
> if ((node != &ext2fs_root->diropen) && (node != currroot)) {
> free (node);
> }
> }
>
> -
> -static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
> - struct ext2_data *data = node->data;
> - struct ext2_inode *inode = &node->inode;
> - int blknr;
> - int blksz = EXT2_BLOCK_SIZE (data);
> - int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
> - int status;
> -
> - /* Direct blocks. */
> - if (fileblock < INDIRECT_BLOCKS) {
> - blknr = __le32_to_cpu (inode->b.blocks.dir_blocks[fileblock]);
> - }
> - /* Indirect. */
> - else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
> - if (indir1_block == NULL) {
> - indir1_block = (uint32_t *) malloc (blksz);
> - if (indir1_block == NULL) {
> - printf ("** ext2fs read block (indir 1) malloc failed. **\n");
> - return (-1);
> - }
> - indir1_size = blksz;
> - indir1_blkno = -1;
> - }
> - if (blksz != indir1_size) {
> - free (indir1_block);
> - indir1_block = NULL;
> - indir1_size = 0;
> - indir1_blkno = -1;
> - indir1_block = (uint32_t *) malloc (blksz);
> - if (indir1_block == NULL) {
> - printf ("** ext2fs read block (indir 1) malloc failed. **\n");
> - return (-1);
> - }
> - indir1_size = blksz;
> - }
> - if ((__le32_to_cpu (inode->b.blocks.indir_block) <<
> - log2_blksz) != indir1_blkno) {
> - status = ext2fs_devread (__le32_to_cpu(inode->b.blocks.indir_block) <<
> log2_blksz,
> - 0, blksz,
> - (char *) indir1_block);
> - if (status == 0) {
> - printf ("** ext2fs read block (indir 1) failed. **\n");
> - return (0);
> - }
> - indir1_blkno =
> - __le32_to_cpu (inode->b.blocks.
> - indir_block) << log2_blksz;
> - }
> - blknr = __le32_to_cpu (indir1_block
> - [fileblock - INDIRECT_BLOCKS]);
> - }
> - /* Double indirect. */
> - else if (fileblock <
> - (INDIRECT_BLOCKS + (blksz / 4 * (blksz / 4 + 1)))) {
> - unsigned int perblock = blksz / 4;
> - unsigned int rblock = fileblock - (INDIRECT_BLOCKS
> - + blksz / 4);
> -
> - if (indir1_block == NULL) {
> - indir1_block = (uint32_t *) malloc (blksz);
> - if (indir1_block == NULL) {
> - printf ("** ext2fs read block (indir 2 1) malloc failed. **\n");
> - return (-1);
> - }
> - indir1_size = blksz;
> - indir1_blkno = -1;
> - }
> - if (blksz != indir1_size) {
> - free (indir1_block);
> - indir1_block = NULL;
> - indir1_size = 0;
> - indir1_blkno = -1;
> - indir1_block = (uint32_t *) malloc (blksz);
> - if (indir1_block == NULL) {
> - printf ("** ext2fs read block (indir 2 1) malloc failed. **\n");
> - return (-1);
> - }
> - indir1_size = blksz;
> - }
> - if ((__le32_to_cpu (inode->b.blocks.double_indir_block) <<
> - log2_blksz) != indir1_blkno) {
> - status = ext2fs_devread
> (__le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz,
> - 0, blksz,
> - (char *) indir1_block);
> - if (status == 0) {
> - printf ("** ext2fs read block (indir 2 1) failed. **\n");
> - return (-1);
> - }
> - indir1_blkno =
> - __le32_to_cpu (inode->b.blocks.double_indir_block) << log2_blksz;
> - }
> -
> - if (indir2_block == NULL) {
> - indir2_block = (uint32_t *) malloc (blksz);
> - if (indir2_block == NULL) {
> - printf ("** ext2fs read block (indir 2 2) malloc failed. **\n");
> - return (-1);
> - }
> - indir2_size = blksz;
> - indir2_blkno = -1;
> - }
> - if (blksz != indir2_size) {
> - free (indir2_block);
> - indir2_block = NULL;
> - indir2_size = 0;
> - indir2_blkno = -1;
> - indir2_block = (uint32_t *) malloc (blksz);
> - if (indir2_block == NULL) {
> - printf ("** ext2fs read block (indir 2 2) malloc failed. **\n");
> - return (-1);
> - }
> - indir2_size = blksz;
> - }
> - if ((__le32_to_cpu (indir1_block[rblock / perblock]) <<
> - log2_blksz) != indir2_blkno) {
> - status = ext2fs_devread (__le32_to_cpu(indir1_block[rblock / perblock])
> << log2_blksz,
> - 0, blksz,
> - (char *) indir2_block);
> - if (status == 0) {
> - printf ("** ext2fs read block (indir 2 2) failed. **\n");
> - return (-1);
> - }
> - indir2_blkno =
> - __le32_to_cpu (indir1_block[rblock / perblock]) << log2_blksz;
> - }
> - blknr = __le32_to_cpu (indir2_block[rblock % perblock]);
> - }
> - /* Tripple indirect. */
> - else {
> - printf ("** ext2fs doesn't support tripple indirect blocks. **\n");
> - return (-1);
> - }
> -#ifdef DEBUG
> - printf ("ext2fs_read_block %08x\n", blknr);
> -#endif
> - return (blknr);
> -}
> -
> -
> int ext2fs_read_file
> (ext2fs_node_t node, int pos, unsigned int len, char *buf) {
> int i;
> @@ -409,8 +125,7 @@ int ext2fs_read_file
> int blockend = blocksize;
>
> int skipfirst = 0;
> -
> - blknr = ext2fs_read_block (node, i);
> + blknr = read_allocated_block(&(node->inode), i);
> if (blknr < 0) {
> return (-1);
> }
> @@ -449,8 +164,8 @@ int ext2fs_read_file
> return (len);
> }
>
> -
> -static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name,
> ext2fs_node_t * fnode, int *ftype)
> +int ext2fs_iterate_dir(ext2fs_node_t dir, char *name,
> + ext2fs_node_t *fnode, int *ftype)
> {
> unsigned int fpos = 0;
> int status;
> @@ -581,7 +296,6 @@ static int ext2fs_iterate_dir (ext2fs_node_t dir, char
> *name, ext2fs_node_t * fn
> return (0);
> }
>
> -
> static char *ext2fs_read_symlink (ext2fs_node_t node) {
> char *symlink;
> struct ext2fs_node *diro = node;
> @@ -617,7 +331,6 @@ static char *ext2fs_read_symlink (ext2fs_node_t node) {
> return (symlink);
> }
>
> -
> int ext2fs_find_file1
> (const char *currpath,
> ext2fs_node_t currroot, ext2fs_node_t * currfound, int *foundtype) {
> @@ -721,7 +434,6 @@ int ext2fs_find_file1
> return (-1);
> }
>
> -
> int ext2fs_find_file
> (const char *path,
> ext2fs_node_t rootnode, ext2fs_node_t * foundnode, int expecttype) {
> @@ -748,7 +460,6 @@ int ext2fs_find_file
> return (1);
> }
>
> -
> int ext2fs_ls (const char *dirname) {
> ext2fs_node_t dirnode;
> int status;
> @@ -768,7 +479,6 @@ int ext2fs_ls (const char *dirname) {
> return (0);
> }
>
> -
> int ext2fs_open (const char *filename) {
> ext2fs_node_t fdiro = NULL;
> int status;
> @@ -799,7 +509,6 @@ fail:
> return (-1);
> }
>
> -
> int ext2fs_close (void
> ) {
> if ((ext2fs_file != NULL) && (ext2fs_root != NULL)) {
> @@ -825,7 +534,6 @@ int ext2fs_close (void
> return (0);
> }
>
> -
> int ext2fs_read (char *buf, unsigned len) {
> int status;
>
> @@ -836,12 +544,10 @@ int ext2fs_read (char *buf, unsigned len) {
> if (ext2fs_file == NULL) {
> return (0);
> }
> -
> status = ext2fs_read_file (ext2fs_file, 0, len, buf);
> return (status);
> }
>
> -
> int ext2fs_mount (unsigned part_length) {
> struct ext2_data *data;
> int status;
> @@ -880,7 +586,6 @@ int ext2fs_mount (unsigned part_length) {
> }
>
> ext2fs_root = data;
> -
> return (1);
>
> fail:
> diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
> new file mode 100644
> index 0000000..850f821
> --- /dev/null
> +++ b/fs/ext4/Makefile
> @@ -0,0 +1,51 @@
> +#
> +# (C) Copyright 2006
> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> +#
> +# (C) Copyright 2003
> +# Pavel Bartusek, Sysgo Real-Time Solutions AG, pba at sysgo.de
> +#
> +#
> +# See file CREDITS for list of people who contributed to this
> +# project.
> +#
> +# This program is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU General Public License as
> +# published by the Free Software Foundation; either version 2 of
> +# the License, or (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> +# MA 02111-1307 USA
> +#
> +
> +include $(TOPDIR)/config.mk
> +
> +LIB = $(obj)libext4fs.o
> +
> +AOBJS =
> +COBJS-$(CONFIG_CMD_EXT4) := ext4fs.o ext4_common.o
> +
> +SRCS := $(AOBJS:.o=.S) $(COBJS-y:.o=.c)
> +OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS-y))
> +
> +
> +all: $(LIB) $(AOBJS)
> +
> +$(LIB): $(obj).depend $(OBJS)
> + $(call cmd_link_o_target, $(OBJS))
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
> new file mode 100644
> index 0000000..39321f6
> --- /dev/null
> +++ b/fs/ext4/ext4_common.c
> @@ -0,0 +1,572 @@
> +/*
> + * (C) Copyright 2011 Samsung Electronics
> + * EXT4 filesystem implementation in Uboot by
> + * Uma Shankar <uma.shankar@samsung.com>
> + * Manjunatha C Achar <a.manjunatha@samsung.com>
> + *
> + * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +/*
> + * ext4load - based on code from GRUB2 fs/ext2.c
> +*/
'*' should all be aligned
I'm concerned about the licensing here - GRUB is currently GPLv3+, U-Boot
is GPLv2+...
> +#include <common.h>
> +#include <ext2fs.h>
> +#include <ext4fs.h>
> +#include <malloc.h>
> +#include <asm/byteorder.h>
> +#include <linux/stat.h>
> +#include <linux/time.h>
> +#include "ext4_common.h"
> +
> +struct ext2_data *ext4fs_root;
> +ext2fs_node_t ext4fs_file;
> +uint32_t *ext4fs_indir1_block;
> +int ext4fs_indir1_size;
> +int ext4fs_indir1_blkno = -1;
> +uint32_t *ext4fs_indir2_block;
> +int ext4fs_indir2_size;
> +int ext4fs_indir2_blkno = -1;
> +
> +uint32_t *ext4fs_indir3_block;
> +int ext4fs_indir3_size;
> +int ext4fs_indir3_blkno = -1;
> +struct ext4_inode *g_parent_inode;
> +
> +#ifndef offsetof
> +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
> +#endif
> +
> +void *xmalloc(size_t size)
> +{
> + void *ptr = malloc(size);
> + if (ptr == NULL && size != 0)
> + printf("bb_msg_memory_exhausted\n");
> + return ptr;
> +}
> +
> +void *xzalloc(size_t size)
> +{
> + void *ptr = xmalloc(size);
> + memset(ptr, 0, size);
> + return ptr;
> +}
> +
> +static struct ext4_extent_header *ext4fs_find_leaf(struct ext2_data *data,
> + char *buf, struct ext4_extent_header *ext_block, uint32_t fileblock)
> +{
> + struct ext4_extent_idx *index;
> + unsigned long long block;
> + int i;
> +
> + while (1) {
> + index = (struct ext4_extent_idx *)(ext_block + 1);
> +
> + if (le32_to_cpu(ext_block->magic) != EXT4_EXT_MAGIC)
> + return 0;
> +
> + if (ext_block->depth == 0)
> + return ext_block;
> +
> + for (i = 0; i < le32_to_cpu(ext_block->entries); i++) {
> + if (fileblock < le32_to_cpu(index[i].block))
> + break;
> + }
> +
> + if (--i < 0)
> + return 0;
> +
> + block = le32_to_cpu(index[i].leaf_hi);
> + block = (block << 32) + le32_to_cpu(index[i].leaf);
> +
> + if (ext2fs_devread(block << LOG2_EXT2_BLOCK_SIZE(data),
> + 0, EXT2_BLOCK_SIZE(data), buf)) {
> + ext_block = (struct ext4_extent_header *)buf;
> + return ext_block;
> + } else
> + return 0;
> + }
> +}
> +
> +static int ext4fs_blockgroup
> + (struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
> +{
> + long int blkno;
> + unsigned int blkoff, desc_per_blk;
> +
> + desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
> +
> + blkno = __le32_to_cpu(data->sblock.first_data_block) + 1
> + + group / desc_per_blk;
> + blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
> +
> + debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
> + group, blkno, blkoff);
> +
> + return ext2fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data),
> + blkoff, sizeof(struct ext2_block_group), (char *)blkgrp);
> +}
> +
> +int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext4_inode
> *inode)
> +{
> + struct ext2_block_group blkgrp;
> + struct ext2_sblock *sblock = &data->sblock;
> + ExtFileSystem *fs = get_fs();
> + int inodes_per_block, status;
> + long int blkno;
> + unsigned int blkoff;
> +
> + /* It is easier to calculate if the first inode is 0. */
> + ino--;
> + status = ext4fs_blockgroup(data, ino / __le32_to_cpu
> + (sblock->inodes_per_group), &blkgrp);
> +
> + if (status == 0)
> + return 0;
> +
> + inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz;
> +
> + blkno = __le32_to_cpu(blkgrp.inode_table_id) +
> + (ino % __le32_to_cpu(sblock->inodes_per_group))
> + / inodes_per_block;
> + blkoff = (ino % inodes_per_block) * fs->inodesz;
> + /* Read the inode. */
> + status = ext2fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), blkoff,
> + sizeof(struct ext4_inode), (char *)inode);
> + if (status == 0)
> + return 0;
> +
> + return 1;
> +}
> +
> +long int read_allocated_block(struct ext4_inode *inode, int fileblock)
> +{
> + long int blknr;
> + int blksz;
> + int log2_blksz;
> + int status;
> + long int rblock;
> + long int perblock_parent;
> + long int perblock_child;
> + unsigned long long start;
> + /*get the blocksize of the filesystem */
> + blksz = EXT2_BLOCK_SIZE(ext4fs_root);
> + log2_blksz = LOG2_EXT2_BLOCK_SIZE(ext4fs_root);
> +
> + if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FLAG) {
> + char buf[EXT2_BLOCK_SIZE(ext4fs_root)];
> + struct ext4_extent_header *leaf;
> + struct ext4_extent *ext;
> + int i;
> +
> + leaf = ext4fs_find_leaf(ext4fs_root, buf,
> + (struct ext4_extent_header *)inode->
> + b.blocks.dir_blocks, fileblock);
> + if (!leaf) {
> + printf("invalid extent\n");
> + return -1;
> + }
> +
> + ext = (struct ext4_extent *)(leaf + 1);
> +
> + for (i = 0; i < le32_to_cpu(leaf->entries); i++) {
> + if (fileblock < le32_to_cpu(ext[i].block))
> + break;
> + }
> +
> + if (--i >= 0) {
> + fileblock -= le32_to_cpu(ext[i].block);
> + if (fileblock >= le32_to_cpu(ext[i].len)) {
> + return 0;
> + } else {
> + start = le32_to_cpu(ext[i].start_hi);
> + start = (start << 32) +
> + le32_to_cpu(ext[i].start);
> + return fileblock + start;
> + }
> + } else {
> + printf("something wrong with extent\n");
> + return -1;
> + }
> + }
> +
> + /* Direct blocks. */
> + if (fileblock < INDIRECT_BLOCKS)
> + blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
> +
> + /* Indirect. */
> + else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
> + if (ext4fs_indir1_block == NULL) {
> + ext4fs_indir1_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir1_block == NULL) {
> + printf("** SI ext2fs read block (indir 1) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir1_size = blksz;
> + ext4fs_indir1_blkno = -1;
> + }
> + if (blksz != ext4fs_indir1_size) {
> + free(ext4fs_indir1_block);
> + ext4fs_indir1_block = NULL;
> + ext4fs_indir1_size = 0;
> + ext4fs_indir1_blkno = -1;
> + ext4fs_indir1_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir1_block == NULL) {
> + printf("** SI ext2fs read block (indir 1) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir1_size = blksz;
> + }
> + if ((__le32_to_cpu(inode->b.blocks.indir_block) <<
> + log2_blksz) != ext4fs_indir1_blkno) {
> + status = ext2fs_devread(__le32_to_cpu(inode->b.blocks.
> + indir_block) << log2_blksz, 0, blksz,
> + (char *) ext4fs_indir1_block);
> + if (status == 0) {
> + printf("** SI ext2fs read block (indir 1) \
> + failed. **\n");
> + return 0;
> + }
> + ext4fs_indir1_blkno =
> + __le32_to_cpu(inode->b.blocks.
> + indir_block) << log2_blksz;
> + }
> + blknr = __le32_to_cpu(ext4fs_indir1_block
> + [fileblock - INDIRECT_BLOCKS]);
> + }
> + /* Double indirect. */
> + else if (fileblock <
> + (INDIRECT_BLOCKS + (blksz / 4 * (blksz / 4 + 1)))) {
> +
> + long int perblock = blksz / 4;
> + long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
> +
> + if (ext4fs_indir1_block == NULL) {
> + ext4fs_indir1_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir1_block == NULL) {
> + printf("** DI ext2fs read block (indir 2 1) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir1_size = blksz;
> + ext4fs_indir1_blkno = -1;
> + }
> + if (blksz != ext4fs_indir1_size) {
> + free(ext4fs_indir1_block);
> + ext4fs_indir1_block = NULL;
> + ext4fs_indir1_size = 0;
> + ext4fs_indir1_blkno = -1;
> + ext4fs_indir1_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir1_block == NULL) {
> + printf("** DI ext2fs read block (indir 2 1) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir1_size = blksz;
> + }
> + if ((__le32_to_cpu(inode->b.blocks.double_indir_block) <<
> + log2_blksz) != ext4fs_indir1_blkno) {
> + status = ext2fs_devread(__le32_to_cpu(inode->b.blocks.
> + double_indir_block) << log2_blksz, 0, blksz,
> + (char *) ext4fs_indir1_block);
> + if (status == 0) {
> + printf("** DI ext2fs read block (indir 2 1) \
> + failed. **\n");
> + return -1;
> + }
> + ext4fs_indir1_blkno =
> + __le32_to_cpu(inode->b.blocks.
> + double_indir_block) << log2_blksz;
> + }
> +
> + if (ext4fs_indir2_block == NULL) {
> + ext4fs_indir2_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir2_block == NULL) {
> + printf("** DI ext2fs read block (indir 2 2) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir2_size = blksz;
> + ext4fs_indir2_blkno = -1;
> + }
> + if (blksz != ext4fs_indir2_size) {
> + free(ext4fs_indir2_block);
> + ext4fs_indir2_block = NULL;
> + ext4fs_indir2_size = 0;
> + ext4fs_indir2_blkno = -1;
> + ext4fs_indir2_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir2_block == NULL) {
> + printf("** DI ext2fs read block (indir 2 2) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir2_size = blksz;
> + }
> + if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) <<
> + log2_blksz) != ext4fs_indir2_blkno) {
> + status = ext2fs_devread(__le32_to_cpu
> + (ext4fs_indir1_block
> + [rblock / perblock]) << log2_blksz,
> + 0, blksz, (char *) ext4fs_indir2_block);
> + if (status == 0) {
> + printf("** DI ext2fs read block (indir 2 2) \
> + failed. **\n");
> + return -1;
> + }
> + ext4fs_indir2_blkno =
> + __le32_to_cpu(ext4fs_indir1_block[rblock
> + / perblock]) << log2_blksz;
> + }
> + blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]);
> + }
> + /* Tripple indirect. */
> + else {
> + rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 +
> + (blksz / 4 * blksz / 4));
> + perblock_child = blksz / 4;
> + perblock_parent = ((blksz / 4) * (blksz / 4));
> +
> + if (ext4fs_indir1_block == NULL) {
> + ext4fs_indir1_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir1_block == NULL) {
> + printf("** TI ext2fs read block (indir 2 1) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir1_size = blksz;
> + ext4fs_indir1_blkno = -1;
> + }
> + if (blksz != ext4fs_indir1_size) {
> + free(ext4fs_indir1_block);
> + ext4fs_indir1_block = NULL;
> + ext4fs_indir1_size = 0;
> + ext4fs_indir1_blkno = -1;
> + ext4fs_indir1_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir1_block == NULL) {
> + printf("** TI ext2fs read block (indir 2 1) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir1_size = blksz;
> + }
> + if ((__le32_to_cpu(inode->b.blocks.tripple_indir_block) <<
> + log2_blksz) != ext4fs_indir1_blkno) {
> + status = ext2fs_devread
> + (__le32_to_cpu(inode->b.blocks.
> + tripple_indir_block) << log2_blksz,
> + 0, blksz, (char *) ext4fs_indir1_block);
> + if (status == 0) {
> + printf("** TI ext2fs read block (indir 2 1) \
> + failed. **\n");
> + return -1;
> + }
> + ext4fs_indir1_blkno =
> + __le32_to_cpu(inode->b.blocks.
> + tripple_indir_block) << log2_blksz;
> + }
> +
> + if (ext4fs_indir2_block == NULL) {
> + ext4fs_indir2_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir2_block == NULL) {
> + printf("** TI ext2fs read block (indir 2 2) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir2_size = blksz;
> + ext4fs_indir2_blkno = -1;
> + }
> + if (blksz != ext4fs_indir2_size) {
> + free(ext4fs_indir2_block);
> + ext4fs_indir2_block = NULL;
> + ext4fs_indir2_size = 0;
> + ext4fs_indir2_blkno = -1;
> + ext4fs_indir2_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir2_block == NULL) {
> + printf("** TI ext2fs read block (indir 2 2) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir2_size = blksz;
> + }
> + if ((__le32_to_cpu(ext4fs_indir1_block[rblock /
> + perblock_parent]) << log2_blksz)
> + != ext4fs_indir2_blkno) {
> + status = ext2fs_devread(__le32_to_cpu
> + (ext4fs_indir1_block
> + [rblock / perblock_parent]) << log2_blksz,
> + 0, blksz, (char *) ext4fs_indir2_block);
> + if (status == 0) {
> + printf("** TI ext2fs read block (indir 2 2) \
> + failed. **\n");
> + return -1;
> + }
> + ext4fs_indir2_blkno =
> + __le32_to_cpu(ext4fs_indir1_block[rblock /
> + perblock_parent]) << log2_blksz;
> + }
> +
> + if (ext4fs_indir3_block == NULL) {
> + ext4fs_indir3_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir3_block == NULL) {
> + printf("** TI ext2fs read block (indir 2 2) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir3_size = blksz;
> + ext4fs_indir3_blkno = -1;
> + }
> + if (blksz != ext4fs_indir3_size) {
> + free(ext4fs_indir3_block);
> + ext4fs_indir3_block = NULL;
> + ext4fs_indir3_size = 0;
> + ext4fs_indir3_blkno = -1;
> + ext4fs_indir3_block = (uint32_t *) malloc(blksz);
> + if (ext4fs_indir3_block == NULL) {
> + printf("** TI ext2fs read block (indir 2 2) \
> + malloc failed. **\n");
> + return -1;
> + }
> + ext4fs_indir3_size = blksz;
> + }
> + if ((__le32_to_cpu(ext4fs_indir2_block[rblock
> + / perblock_child]) << log2_blksz) != ext4fs_indir3_blkno){
> + status = ext2fs_devread(__le32_to_cpu
> + (ext4fs_indir2_block[(rblock / perblock_child)
> + % (blksz / 4)]) << log2_blksz,
> + 0, blksz, (char *) ext4fs_indir3_block);
> + if (status == 0) {
> + printf("** TI ext2fs read block (indir 2 2) \
> + failed. **\n");
> + return -1;
> + }
> + ext4fs_indir3_blkno =
> + __le32_to_cpu(ext4fs_indir2_block[(rblock /
> + perblock_child) % (blksz / 4)]) << log2_blksz;
> + }
> +
> + blknr = __le32_to_cpu(ext4fs_indir3_block
> + [rblock % perblock_child]);
> + }
> + debug("ext4fs_read_block %08x\n", blknr);
> + return blknr;
> +}
> +
> +int ext4fs_close(void)
> +{
> + if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
> + ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen);
> + ext4fs_file = NULL;
> + }
> + if (ext4fs_root != NULL) {
> + free(ext4fs_root);
> + ext4fs_root = NULL;
> + }
> + if (ext4fs_indir1_block != NULL) {
> + free(ext4fs_indir1_block);
> + ext4fs_indir1_block = NULL;
> + ext4fs_indir1_size = 0;
> + ext4fs_indir1_blkno = -1;
> + }
> + if (ext4fs_indir2_block != NULL) {
> + free(ext4fs_indir2_block);
> + ext4fs_indir2_block = NULL;
> + ext4fs_indir2_size = 0;
> + ext4fs_indir2_blkno = -1;
> + }
> + return 0;
> +}
> +
> +int ext4fs_open(const char *filename)
> +{
> + ext2fs_node_t fdiro = NULL;
> + int status;
> + int len;
> +
> + if (ext4fs_root == NULL)
> + return -1;
> +
> + ext4fs_file = NULL;
> + status = ext2fs_find_file(filename, &ext4fs_root->diropen, &fdiro,
> + FILETYPE_REG);
> + if (status == 0)
> + goto fail;
> +
> + if (!fdiro->inode_read) {
> + status = ext4fs_read_inode(fdiro->data, fdiro->ino,
> + (struct ext4_inode *)&fdiro->inode);
> + if (status == 0)
> + goto fail;
> + }
> + len = __le32_to_cpu(fdiro->inode.size);
> + ext4fs_file = fdiro;
> + return len;
> +
> +fail:
> + ext4fs_free_node(fdiro, &ext4fs_root->diropen);
> + return -1;
> +}
> +
> +int ext4fs_mount(unsigned part_length)
> +{
> + struct ext2_data *data;
> + int status;
> + ExtFileSystem *fs = get_fs();
> + data = malloc(sizeof(struct ext2_data));
> + if (!data)
> + return 0;
> +
> + /* Read the superblock. */
> + status = ext2fs_devread(1 * 2, 0, sizeof(struct ext2_sblock),
> + (char *)&data->sblock);
> +
> + if (status == 0)
> + goto fail;
> +
> + /* Make sure this is an ext2 filesystem. */
> + if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC)
> + goto fail;
> +
> + if (__le32_to_cpu(data->sblock.revision_level == 0))
> + fs->inodesz = 128;
> + else
> + fs->inodesz = __le16_to_cpu(data->sblock.inode_size);
> +
> +#ifdef DEBUG
> + printf("EXT2 rev %d, inode_size %d\n",
> + __le32_to_cpu(data->sblock.revision_level), fs->inodesz);
> +#endif
> + data->diropen.data = data;
> + data->diropen.ino = 2;
> + data->diropen.inode_read = 1;
> + data->inode = &data->diropen.inode;
> +
> + status = ext4fs_read_inode(data, 2, (struct ext4_inode *)data->inode);
> + if (status == 0)
> + goto fail;
> +
> + ext4fs_root = data;
> + ext2fs_mount(part_length);
> + return 1;
> +
> +fail:
> + printf("Failed to mount ext2 filesystem...\n");
> + free(data);
> +
> + ext4fs_root = NULL;
> + return 0;
> +}
> diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h
> new file mode 100644
> index 0000000..2014298
> --- /dev/null
> +++ b/fs/ext4/ext4_common.h
> @@ -0,0 +1,44 @@
> +/*
> + * (C) Copyright 2011 Samsung Electronics
> + * EXT4 filesystem implementation in Uboot by
> + * Uma Shankar <uma.shankar@samsung.com>
> + * Manjunatha C Achar <a.manjunatha@samsung.com>
> + *
> + * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#ifndef __EXT4_COMMON__
> +#define __EXT4_COMMON__
> +#include <ext2fs.h>
> +#include <ext4fs.h>
> +
> +#define YES 1
> +#define NO 0
> +#define TRUE 1
> +#define FALSE 0
> +#define RECOVER 1
> +#define SCAN 0
> +
> +#define S_IFLNK 0120000 /* symbolic link */
> +#define BLOCK_NO_ONE 1
> +#define SUPERBLOCK_SECTOR 2
> +#define SUPERBLOCK_SIZE 1024
> +#define F_FILE 1
Can you fix the alignments so the defines are all nicely aligned (using tabs)
> +
> +extern unsigned long part_offset;
> +int ext4fs_read_inode(struct ext2_data *data, int ino,
> + struct ext4_inode *inode);
> +#endif
> diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
> new file mode 100644
> index 0000000..890aaf3
> --- /dev/null
> +++ b/fs/ext4/ext4fs.c
> @@ -0,0 +1,215 @@
> +/*
> + * (C) Copyright 2011 Samsung Electronics
> + * EXT4 filesystem implementation in Uboot by
> + * Uma Shankar <uma.shankar@samsung.com>
> + * Manjunatha C Achar <a.manjunatha@samsung.com>
> + *
> + * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +/*
> + * ext4load - based on code from GRUB2 fs/ext2.c
> +*/
> +#include <common.h>
> +#include <malloc.h>
> +#include <asm/byteorder.h>
> +#include <linux/stat.h>
> +#include <linux/time.h>
> +#include <ext2fs.h>
> +#include <ext4fs.h>
> +#include "ext4_common.h"
> +
> +int ext4fs_symlinknest;
> +block_dev_desc_t *ext4_dev_desc;
> +
> +ExtFileSystem *get_fs(void)
Again, no camel case please
> +{
> + if (ext4_dev_desc == NULL || ext4_dev_desc->priv == NULL)
> + printf("Invalid Input Arguments %s\n", __func__);
> + return (ExtFileSystem *)ext4_dev_desc->priv;
> +}
> +
> +int init_fs(block_dev_desc_t *dev_desc)
> +{
> + ExtFileSystem *fs;
> + if (dev_desc == NULL) {
> + printf("Invalid Input Arguments %s\n", __func__);
> + return -1;
> + }
> +
> + fs = (ExtFileSystem *)xzalloc(sizeof(ExtFileSystem));
> + if (fs == NULL) {
> + printf("malloc failed: %s\n", __func__);
> + return -1;
> + }
> +
> + fs->dev_desc = dev_desc;
> + dev_desc->priv = fs;
> + return 0;
> +}
> +
> +void deinit_fs(block_dev_desc_t *dev_desc)
> +{
> + if (dev_desc == NULL) {
> + printf("Invalid Input Arguments %s\n", __func__);
> + return;
> + }
> + if (dev_desc->priv)
> + free(dev_desc->priv);
> + return;
> +}
> +
> +void ext4fs_free_node(ext2fs_node_t node, ext2fs_node_t currroot)
> +{
> + if ((node != &ext4fs_root->diropen) && (node != currroot))
> + free(node);
> +}
> +
> +/* Taken from openmoko-kernel mailing list: By Andy green
> +* Optimized read file API : collects and defers contiguous sector
> +* reads into one potentially more efficient larger sequential read action
> +*/
> +int ext4fs_read_file(ext2fs_node_t node, int pos, unsigned int len, char
> *buf)
> +{
> + int i;
> + int blockcnt;
> + int log2blocksize = LOG2_EXT2_BLOCK_SIZE(node->data);
> + int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS);
> + unsigned int filesize = __le32_to_cpu(node->inode.size);
> + int previous_block_number = -1;
> + int delayed_start = 0;
> + int delayed_extent = 0;
> + int delayed_skipfirst = 0;
> + int delayed_next = 0;
> + char *delayed_buf = NULL;
> + short status;
> +
> + /* Adjust len so it we can't read past the end of the file. */
> + if (len > filesize)
> + len = filesize;
> +
> + blockcnt = ((len + pos) + blocksize - 1) / blocksize;
> +
> + for (i = pos / blocksize; i < blockcnt; i++) {
> + int blknr;
> + int blockoff = pos % blocksize;
> + int blockend = blocksize;
> + int skipfirst = 0;
> + blknr = read_allocated_block((struct ext4_inode *)
> + &(node->inode), i);
> + if (blknr < 0)
> + return -1;
> +
> + blknr = blknr << log2blocksize;
> +
> + /* Last block. */
> + if (i == blockcnt - 1) {
> + blockend = (len + pos) % blocksize;
> +
> + /* The last portion is exactly blocksize. */
> + if (!blockend)
> + blockend = blocksize;
> + }
> +
> + /* First block. */
> + if (i == pos / blocksize) {
> + skipfirst = blockoff;
> + blockend -= skipfirst;
> + }
> + if (blknr) {
> + int status;
> +
> + if (previous_block_number != -1) {
> + if (delayed_next == blknr) {
> + delayed_extent += blockend;
> + delayed_next += blockend >> SECTOR_BITS;
> + } else { /* spill */
> + status = ext2fs_devread(delayed_start,
> + delayed_skipfirst,
> + delayed_extent,
> + delayed_buf);
> + if (status == 0)
> + return -1;
> + previous_block_number = blknr;
> + delayed_start = blknr;
> + delayed_extent = blockend;
> + delayed_skipfirst = skipfirst;
> + delayed_buf = buf;
> + delayed_next = blknr +
> + (blockend >> SECTOR_BITS);
> + }
> + } else {
> + previous_block_number = blknr;
> + delayed_start = blknr;
> + delayed_extent = blockend;
> + delayed_skipfirst = skipfirst;
> + delayed_buf = buf;
> + delayed_next = blknr +
> + (blockend >> SECTOR_BITS);
> + }
> + } else {
> + if (previous_block_number != -1) {
> + /* spill */
> + status = ext2fs_devread(delayed_start,
> + delayed_skipfirst,
> + delayed_extent,
> + delayed_buf);
> + if (status == 0)
> + return -1;
> + previous_block_number = -1;
> + }
> + memset(buf, 0, blocksize - skipfirst);
> + }
> + buf += blocksize - skipfirst;
> + }
> + if (previous_block_number != -1) {
> + /* spill */
> + status = ext2fs_devread(delayed_start,
> + delayed_skipfirst, delayed_extent,
> + delayed_buf);
> + if (status == 0)
> + return -1;
> + previous_block_number = -1;
> + }
> + return len;
> +}
> +
> +int ext4fs_ls(const char *dirname)
> +{
> + ext2fs_node_t dirnode;
> + int status;
> +
> + if (dirname == NULL)
> + return 0;
> +
> + status = ext2fs_find_file(dirname, &ext4fs_root->diropen, &dirnode,
> + FILETYPE_DIRECTORY);
> + if (status != 1) {
> + printf("** Can not find directory. **\n");
> + return 1;
> + }
> +
> + ext2fs_iterate_dir(dirnode, NULL, NULL, NULL);
> + ext4fs_free_node(dirnode, &ext4fs_root->diropen);
> + return 0;
> +}
> +
> +int ext4fs_read(char *buf, unsigned len)
> +{
> + if (ext4fs_root == NULL || ext4fs_file == NULL)
> + return 0;
> + return ext4fs_read_file(ext4fs_file, 0, len, buf);
> +}
> diff --git a/include/ext2fs.h b/include/ext2fs.h
> index 163a9bb..de58d0a 100644
> --- a/include/ext2fs.h
> +++ b/include/ext2fs.h
> @@ -25,6 +25,8 @@
> * from the original ext2 fs code, as found in the linux kernel.
> */
>
> +#ifndef __EXT2__
> +#define __EXT2__
>
> #define SECTOR_SIZE 0x200
> #define SECTOR_BITS 9
> @@ -68,14 +70,175 @@ typedef enum
> ERR_DEV_NEED_INIT,
> ERR_NO_DISK_SPACE,
> ERR_NUMBER_OVERFLOW,
> -
> MAX_ERR_NUM
> } ext2fs_error_t;
>
> +/* Magic value used to identify an ext2 filesystem. */
> +#define EXT2_MAGIC 0xEF53
> +/* Amount of indirect blocks in an inode. */
> +#define INDIRECT_BLOCKS 12
> +/* Maximum lenght of a pathname. */
> +#define EXT2_PATH_MAX 4096
> +/* Maximum nesting of symlinks, used to prevent a loop. */
> +#define EXT2_MAX_SYMLINKCNT 8
> +
> +/* Filetype used in directory entry. */
> +#define FILETYPE_UNKNOWN 0
> +#define FILETYPE_REG 1
> +#define FILETYPE_DIRECTORY 2
> +#define FILETYPE_SYMLINK 7
> +
> +/* Filetype information as used in inodes. */
> +#define FILETYPE_INO_MASK 0170000
> +#define FILETYPE_INO_REG 0100000
> +#define FILETYPE_INO_DIRECTORY 0040000
> +#define FILETYPE_INO_SYMLINK 0120000
> +#define EXT2_ROOT_INO 2 /* Root inode */
Again, make defines are all nicely aligned (using tabs)
> +
> +/* Bits used as offset in sector */
> +#define DISK_SECTOR_BITS 9
> +/* The size of an ext2 block in bytes. */
> +#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
> +
> +/* Log2 size of ext2 block in 512 blocks. */
> +#define LOG2_EXT2_BLOCK_SIZE(data) (__le32_to_cpu \
> + (data->sblock.log2_block_size) + 1)
> +
> +/* Log2 size of ext2 block in bytes. */
> +#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu \
> + (data->sblock.log2_block_size) + 10)
> +#define INODE_SIZE_FILESYSTEM(data) (__le32_to_cpu \
> + (data->sblock.inode_size))
> +
> +#define EXT2_FT_DIR 2
> +#define SUCCESS 1
> +/*
> + * Macro-instructions used to manage several block sizes
> + */
> +#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
> +#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
> +#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
> +#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
> +
> +/* The ext2 superblock. */
> +struct ext2_sblock {
> + uint32_t total_inodes;
> + uint32_t total_blocks;
> + uint32_t reserved_blocks;
> + uint32_t free_blocks;
> + uint32_t free_inodes;
> + uint32_t first_data_block;
> + uint32_t log2_block_size;
> + uint32_t log2_fragment_size;
> + uint32_t blocks_per_group;
> + uint32_t fragments_per_group;
> + uint32_t inodes_per_group;
> + uint32_t mtime;
> + uint32_t utime;
> + uint16_t mnt_count;
> + uint16_t max_mnt_count;
> + uint16_t magic;
> + uint16_t fs_state;
> + uint16_t error_handling;
> + uint16_t minor_revision_level;
> + uint32_t lastcheck;
> + uint32_t checkinterval;
> + uint32_t creator_os;
> + uint32_t revision_level;
> + uint16_t uid_reserved;
> + uint16_t gid_reserved;
> + uint32_t first_inode;
> + uint16_t inode_size;
> + uint16_t block_group_number;
> + uint32_t feature_compatibility;
> + uint32_t feature_incompat;
> + uint32_t feature_ro_compat;
> + uint32_t unique_id[4];
> + char volume_name[16];
> + char last_mounted_on[64];
> + uint32_t compression_info;
> +};
> +
> +struct ext2_block_group {
> + __u32 block_id; /* Blocks bitmap block */
> + __u32 inode_id; /* Inodes bitmap block */
> + __u32 inode_table_id; /* Inodes table block */
> + __u16 free_blocks; /* Free blocks count */
> + __u16 free_inodes; /* Free inodes count */
> + __u16 used_dir_cnt; /* Directories count */
> + __u16 bg_flags;
> + __u32 bg_reserved[2];
> + __u16 bg_itable_unused; /* Unused inodes count */
> + __u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/
> +};
> +
> +/* The ext2 inode. */
> +struct ext2_inode {
> + uint16_t mode;
> + uint16_t uid;
> + uint32_t size;
> + uint32_t atime;
> + uint32_t ctime;
> + uint32_t mtime;
> + uint32_t dtime;
> + uint16_t gid;
> + uint16_t nlinks;
> + uint32_t blockcnt; /* Blocks of 512 bytes!! */
> + uint32_t flags;
> + uint32_t osd1;
> + union {
> + struct datablocks {
> + uint32_t dir_blocks[INDIRECT_BLOCKS];
> + uint32_t indir_block;
> + uint32_t double_indir_block;
> + uint32_t tripple_indir_block;
> + } blocks;
> + char symlink[60];
> + } b;
> + uint32_t version;
> + uint32_t acl;
> + uint32_t dir_acl;
> + uint32_t fragment_addr;
> + uint32_t osd2[3];
> +};
> +
> +/* The header of an ext2 directory entry. */
> +struct ext2_dirent {
> + uint32_t inode;
> + uint16_t direntlen;
> + uint8_t namelen;
> + uint8_t filetype;
> +};
> +
> +struct ext2fs_node {
> + struct ext2_data *data;
> + struct ext2_inode inode;
> + int ino;
> + int inode_read;
> +};
> +
> +/* Information about a "mounted" ext2 filesystem. */
> +struct ext2_data {
> + struct ext2_sblock sblock;
> + struct ext2_inode *inode;
> + struct ext2fs_node diropen;
> +};
> +
> +typedef struct ext2fs_node *ext2fs_node_t;
> +extern int ext2fs_iterate_dir(ext2fs_node_t dir, char *name,
> + ext2fs_node_t *fnode, int *ftype);
> +extern int ext2fs_find_file(const char *path,
> + ext2fs_node_t rootnode, ext2fs_node_t *foundnode, int expecttype);
>
> -extern int ext2fs_set_blk_dev(block_dev_desc_t *rbdd, int part);
> -extern int ext2fs_ls (const char *dirname);
> -extern int ext2fs_open (const char *filename);
> -extern int ext2fs_read (char *buf, unsigned len);
> -extern int ext2fs_mount (unsigned part_length);
> -extern int ext2fs_close(void);
> +int ext2fs_set_blk_dev(block_dev_desc_t *rbdd, int part);
> +int ext2fs_ls(const char *dirname);
> +int ext2fs_open(const char *filename);
> +int ext2fs_read(char *buf, unsigned len);
> +int ext2fs_mount(unsigned part_length);
> +int ext2fs_close(void);
> +int ext2_register_device(block_dev_desc_t *dev_desc, int part_no);
> +extern int ext2fs_devread(int sector, int byte_offset, int byte_len, char
> *buf);
> +uint32_t div_roundup(uint32_t size, uint32_t n);
> +void *xmalloc(size_t size);
> +void *xzalloc(size_t size);
> +#endif
> diff --git a/include/ext4fs.h b/include/ext4fs.h
> new file mode 100644
> index 0000000..168acba
> --- /dev/null
> +++ b/include/ext4fs.h
> @@ -0,0 +1,164 @@
> +/*
> + * (C) Copyright 2011 Samsung Electronics
> + * EXT4 filesystem implementation in Uboot by
> + * Uma Shankar <uma.shankar@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + * Some parts of this code (mainly the structures and defines) are
> + * from the original ext4 fs code, as found in the linux kernel.
> + * Reference for ext4load and ls features have ben taken from GRUB
> + */
> +
> +#ifndef __EXT4__
> +#define __EXT4__
> +
> +#define EXT4_EXTENTS_FLAG 0x80000
> +#define EXT4_EXT_MAGIC 0xf30a
> +#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
> +#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040
> +#define EXT4_INDIRECT_BLOCKS 12
> +
> +#define EXT4_BG_INODE_UNINIT 0x0001
> +#define EXT4_BG_BLOCK_UNINIT 0x0002
> +#define EXT4_BG_INODE_ZEROED 0x0004
> +
> +/* The ext4 inode. */
> +struct ext4_inode {
> + uint16_t mode;
> + uint16_t uid;
> + uint32_t size;
> + uint32_t atime;
> + uint32_t ctime;
> + uint32_t mtime;
> + uint32_t dtime;
> + uint16_t gid;
> + uint16_t nlinks;
> + uint32_t blockcnt; /* Blocks of 512 bytes!! */
> + uint32_t flags;
> + uint32_t osd1;
> + union {
> + struct data_blocks {
> + uint32_t dir_blocks[EXT4_INDIRECT_BLOCKS];
> + uint32_t indir_block;
> + uint32_t double_indir_block;
> + uint32_t tripple_indir_block;
> + } blocks;
> + char symlink[60];
> + } b;
> + uint32_t version;
> + uint32_t acl;
> + uint32_t dir_acl;
> + uint32_t fragment_addr;
> + uint32_t osd2[3];
> +};
> +
> +/* All fields are little-endian */
> +struct ext4_dir {
> + uint32_t inode1;
> + uint16_t rec_len1;
> + uint8_t name_len1;
> + uint8_t file_type1;
> + char name1[4];
> + uint32_t inode2;
> + uint16_t rec_len2;
> + uint8_t name_len2;
> + uint8_t file_type2;
> + char name2[4];
> + uint32_t inode3;
> + uint16_t rec_len3;
> + uint8_t name_len3;
> + uint8_t file_type3;
> + char name3[12];
> +};
> +
> +struct ext4_extent_header {
> + uint16_t magic;
> + uint16_t entries;
> + uint16_t max;
> + uint16_t depth;
> + uint32_t generation;
> +};
> +
> +struct ext4_extent {
> + uint32_t block;
> + uint16_t len;
> + uint16_t start_hi;
> + uint32_t start;
> +};
> +
> +struct ext4_extent_idx {
> + uint32_t block;
> + uint32_t leaf;
> + uint16_t leaf_hi;
> + uint16_t unused;
> +};
> +
> +typedef struct _ExtFileSystem {
> + /*Total Sector of partition */
> + uint64_t total_sect;
> + /*Block size of partition */
> + uint32_t blksz;
> + /*Inode size of partition */
> + uint32_t inodesz;
> + /*Sectors per Block */
> + uint32_t sect_perblk;
> + /*Group Descriptor Block Number */
> + uint32_t gdtable_blkno;
> + /*Total block groups of partition */
> + uint32_t no_blkgrp;
> + /*No of blocks required for bgdtable */
> + uint32_t no_blk_pergdt;
> + /*superblock */
> + struct ext2_sblock *sb;
> + /*block group descritpor table */
> + struct ext2_block_group *gd;
> + char *gdtable;
> +
> + /*Block Bitmap Related */
> + unsigned char **blk_bmaps;
> + long int curr_blkno;
> + uint16_t first_pass_bbmap;
> +
> + /*Inode Bitmap Related */
> + unsigned char **inode_bmaps;
> + int curr_inode_no;
> + uint16_t first_pass_ibmap;
> +
> + /*Journal Related */
> +
> + /*Block Device Descriptor */
> + block_dev_desc_t *dev_desc;
> +} ExtFileSystem;
> +
> +/*############################*/
> +extern block_dev_desc_t *ext4_dev_desc;
> +/*#########################*/
> +
> +extern struct ext2_data *ext4fs_root;
> +extern ext2fs_node_t ext4fs_file;
> +ExtFileSystem *get_fs(void);
> +int init_fs(block_dev_desc_t *);
> +void deinit_fs(block_dev_desc_t *);
> +int ext4fs_open(const char *filename);
> +int ext4fs_read(char *buf, unsigned len);
> +int ext4fs_mount(unsigned part_length);
> +int ext4fs_close(void);
> +int ext4fs_ls(const char *dirname);
> +long int read_allocated_block(struct ext4_inode *inode, int fileblock);
> +void ext4fs_free_node(ext2fs_node_t node, ext2fs_node_t currroot);
> +extern int ext2fs_devread(int sector, int byte_offset, int byte_len, char
> *buf);
> +extern void *xzalloc(size_t size);
> +#endif
Regards,
Graeme
prev parent reply other threads:[~2011-12-12 12:12 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-12 10:45 [U-Boot] Subject: [PATCH 1/2] ext4fs ls load support uma.shankar at samsung.com
2011-12-12 12:12 ` Graeme Russ [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4EE5EFAE.1040708@gmail.com \
--to=graeme.russ@gmail.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.