diff mbox

[U-Boot,1/2] ext4fs ls load support

Message ID 1323970768-23834-1-git-send-email-uma.shankar@samsung.com
State Changes Requested
Headers show

Commit Message

uma.shankar@samsung.com Dec. 15, 2011, 5:39 p.m. UTC
From: Uma Shankar <uma.shankar@samsung.com>

Signed-off-by: Uma Shankar <uma.shankar@samsung.com>
Signed-off-by: Manjunatha C Achar <a.manjunatha@samsung.com>
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_ext2.c     |    1 +
 common/cmd_ext4.c     |  253 ++++++++++++++++++++++
 fs/Makefile           |    1 +
 fs/ext2/dev.c         |    1 +
 fs/ext2/ext2fs.c      |  340 +++---------------------------
 fs/ext4/Makefile      |   51 +++++
 fs/ext4/ext4_common.c |  573 +++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ext4/ext4_common.h |   44 ++++
 fs/ext4/ext4fs.c      |  215 ++++++++++++++++++
 include/ext2fs.h      |   16 +-
 include/ext4fs.h      |  116 ++++++++++
 include/ext_common.h  |  199 +++++++++++++++++
 14 files changed, 1489 insertions(+), 324 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
 create mode 100644 include/ext_common.h

Comments

Graeme Russ Dec. 15, 2011, 10:48 p.m. UTC | #1
Hi Uma,

On Dec 15, 2011 5:31 PM, <uma.shankar@samsung.com> wrote:
>
> From: Uma Shankar <uma.shankar@samsung.com>
>
> Signed-off-by: Uma Shankar <uma.shankar@samsung.com>
> Signed-off-by: Manjunatha C Achar <a.manjunatha@samsung.com>
> 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_ext2.c     |    1 +
>  common/cmd_ext4.c     |  253 ++++++++++++++++++++++
>  fs/Makefile           |    1 +
>  fs/ext2/dev.c         |    1 +
>  fs/ext2/ext2fs.c      |  340 +++---------------------------
>  fs/ext4/Makefile      |   51 +++++
>  fs/ext4/ext4_common.c |  573
+++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/ext4/ext4_common.h |   44 ++++
>  fs/ext4/ext4fs.c      |  215 ++++++++++++++++++
>  include/ext2fs.h      |   16 +-
>  include/ext4fs.h      |  116 ++++++++++
>  include/ext_common.h  |  199 +++++++++++++++++
>  14 files changed, 1489 insertions(+), 324 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
>  create mode 100644 include/ext_common.h

Please include revision information in the patch title ([PATCH v2 ...]),
change summary below the signed-of-by line (after a line with only ---) and
set the in-reply-to: email header to the previous version of the patch.

Please read:

http://www.denx.de/wiki/U-Boot/Patches

Regards,

Graeme
Mike Frysinger Dec. 16, 2011, 4:30 p.m. UTC | #2
On Thursday 15 December 2011 12:39:28 uma.shankar@samsung.com wrote:
> From: Uma Shankar <uma.shankar@samsung.com>

NAK: please add some sort of description here.  you must document all the 
places you're copying code from for example, and retain all the appropriate 
copyrights.  as it stands, this patch is a mess from that perspective.

>  Makefile              |    2 +-
>  common/Makefile       |    1 +
>  common/cmd_ext2.c     |    1 +
>  common/cmd_ext4.c     |  253 ++++++++++++++++++++++
>  fs/Makefile           |    1 +
>  fs/ext2/dev.c         |    1 +
>  fs/ext2/ext2fs.c      |  340 +++---------------------------
>  fs/ext4/Makefile      |   51 +++++
>  fs/ext4/ext4_common.c |  573
> fs/ext4/ext4_common.h |   44 ++++
>  fs/ext4/ext4fs.c      |  215 ++++++++++++++++++
>  include/ext2fs.h      |   16 +-
>  include/ext4fs.h      |  116 ++++++++++
>  include/ext_common.h  |  199 +++++++++++++++++

when moving code around, you should use the -M/-C flags so git can better 
describe what you did

> --- /dev/null
> +++ b/common/cmd_ext4.c
>
> +int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])

static

> +{
> +	char *filename = NULL;

const

> +	switch (argc) {
> +	case 3:
> +		addr_str = getenv("loadaddr");
> +		if (addr_str != NULL)
> +			strict_strtoul(addr_str, 16, &addr);
> +		else
> +			addr = CONFIG_SYS_LOAD_ADDR;
> +
> +		filename = getenv("bootfile");
> +		count = 0;
> +		break;
> +	case 4:
> +		strict_strtoul(argv[3], 16, &addr);
> +		filename = getenv("bootfile");
> +		count = 0;
> +		break;
> +	case 5:
> +		strict_strtoul(argv[3], 16, &addr);
> +		filename = argv[4];
> +		count = 0;
> +		break;
> +	case 6:
> +		strict_strtoul(argv[3], 16, &addr);
> +		filename = argv[4];
> +		strict_strtoul(argv[5], 16, &count);
> +		break;
> +
> +	default:
> +		return cmd_usage(cmdtp);
> +	}

there's duplicated code here.  simpler to write it as:
	count = 0;
	filename = getenv("bootfile");
	addr_str = getenv("loadaddr");
	switch (argc) {
	case 6:
		strict_strtoul(argv[5], 16, &count);
	case 5:
		filename = argv[4];
	case 4:
		addr_str = argv[3];
	case 3:
		break;
	default:
		return cmd_usage(cmdtp);
	}
	if (addr_str)
		strict_strtoul(addr_str, 16, &addr);
	else
		addr = CONFIG_SYS_LOAD_ADDR;


> +		(int)strict_strtoul(++ep, 16, &part);

that cast doesn't make sense

> +		if (strncmp((char *)info.type, BOOT_PART_TYPE,
> +			    sizeof(info.type)) != 0) {

i don't see how this could possibly work.  info.type is "unsigned char", so 
casting that single byte into an address and then reading a single byte !?

> +			printf("** Invalid partition type \"%.32s\""
> +			       " (expect \"" BOOT_PART_TYPE "\")\n", info.type);

use %s instead of embeddeding a constant string

> +int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])

static

> +{
> +	char *filename = "/";

const

> +		(int)strict_strtoul(++ep, 16, &part);

useless cast

> --- /dev/null
> +++ b/fs/ext4/Makefile
>
> +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)

drop the dead $(AOBJS) logic

> --- /dev/null
> +++ b/fs/ext4/ext4_common.c
>
> +#ifndef offsetof
> +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
> +#endif

NAK: the linux/ headers already provide this

> +void *xmalloc(size_t size)
> +{
> +	void *ptr = malloc(size);
> +	if (ptr == NULL && size != 0)
> +		printf("bb_msg_memory_exhausted\n");
> +	return ptr;
> +}

NAK: this is useless, and clearly you're copying code from busybox.  you 
*must* document that.

> +void *xzalloc(size_t size)
> +{
> +	void *ptr = xmalloc(size);
> +	memset(ptr, 0, size);
> +	return ptr;
> +}

NAK: this doesn't fail (so the "x" doesn't make sense), and the zalloc() 
aspect should be in a common header written as:
	#define zalloc(size) calloc(1, size)

> +int ext4fs_mount(unsigned part_length)
> +{
> ...
> +#ifdef DEBUG
> +	printf("EXT2 rev %d, inode_size %d\n",
> +	       __le32_to_cpu(data->sblock.revision_level), fs->inodesz);
> +#endif

use debug()

> --- /dev/null
> +++ b/fs/ext4/ext4fs.c
>
> +/*
> + *  ext4load - based on code from GRUB2  fs/ext2.c
> +*/

you must retain copyright from the source files in the new files

> +int init_fs(block_dev_desc_t *dev_desc)
> +{
> ...
> +	fs = (struct ext_filesystem *)xzalloc(sizeof(struct ext_filesystem));

useless cast
-mike
diff mbox

Patch

diff --git a/Makefile b/Makefile
index 5de7915..20cb941 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 2d9ae8c..d99cc31 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -87,6 +87,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_ext2.c b/common/cmd_ext2.c
index 35fb361..3ccc47e 100644
--- a/common/cmd_ext2.c
+++ b/common/cmd_ext2.c
@@ -40,6 +40,7 @@ 
 #include <linux/ctype.h>
 #include <asm/byteorder.h>
 #include <ext2fs.h>
+#include <ext_common.h>
 #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
 #include <usb.h>
 #endif
diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c
new file mode 100644
index 0000000..7c2d541
--- /dev/null
+++ b/common/cmd_ext4.c
@@ -0,0 +1,253 @@ 
+/*
+ * (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 <ext_common.h>
+#include <ext4fs.h>
+#include <linux/stat.h>
+#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;
+
+#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;
+	char *ep;
+	int dev;
+	unsigned long part = 1;
+	ulong addr = 0, part_length;
+	int filelen;
+	disk_partition_t info;
+	struct ext_filesystem *fs;
+	char buf[12];
+	unsigned long count;
+	const char *addr_str;
+
+	switch (argc) {
+	case 3:
+		addr_str = getenv("loadaddr");
+		if (addr_str != NULL)
+			strict_strtoul(addr_str, 16, &addr);
+		else
+			addr = CONFIG_SYS_LOAD_ADDR;
+
+		filename = getenv("bootfile");
+		count = 0;
+		break;
+	case 4:
+		strict_strtoul(argv[3], 16, &addr);
+		filename = getenv("bootfile");
+		count = 0;
+		break;
+	case 5:
+		strict_strtoul(argv[3], 16, &addr);
+		filename = argv[4];
+		count = 0;
+		break;
+	case 6:
+		strict_strtoul(argv[3], 16, &addr);
+		filename = argv[4];
+		strict_strtoul(argv[5], 16, &count);
+		break;
+
+	default:
+		return cmd_usage(cmdtp);
+	}
+
+	if (!filename) {
+		puts("** No boot file defined **\n");
+		return 1;
+	}
+
+	dev = (int)simple_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;
+		}
+		(int)strict_strtoul(++ep, 16, &part);
+	}
+
+	if (part != 0) {
+		if (get_partition_info(fs->dev_desc, part, &info)) {
+			printf("** Bad partition %lu **\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:%lu (%.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:%lu **\n", argv[1], dev, part);
+		ext4fs_close();
+		return 1;
+	}
+
+	if (!ext4fs_mount(part_length)) {
+		printf("** Bad ext2 partition or disk - %s %d:%lu **\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:%lu **\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;
+	unsigned long part = 1;
+	char *ep;
+	struct ext_filesystem *fs;
+	int part_length;
+
+	if (argc < 3)
+		return cmd_usage(cmdtp);
+
+	dev = (int)simple_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;
+		}
+		(int)strict_strtoul(++ep, 16, &part);
+	}
+
+	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:%lu **\n", argv[1], dev, part);
+		ext4fs_close();
+		return 1;
+	}
+
+	if (!ext4fs_mount(part_length)) {
+		printf("** Bad ext2 partition or disk - %s %d:%lu **\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/dev.c b/fs/ext2/dev.c
index 874e211..315ff53 100644
--- a/fs/ext2/dev.c
+++ b/fs/ext2/dev.c
@@ -27,6 +27,7 @@ 
 #include <common.h>
 #include <config.h>
 #include <ext2fs.h>
+#include <ext_common.h>
 
 static block_dev_desc_t *ext2fs_block_dev_desc;
 static disk_partition_t part_info;
diff --git a/fs/ext2/ext2fs.c b/fs/ext2/ext2fs.c
index e119e13..df336b9 100644
--- a/fs/ext2/ext2fs.c
+++ b/fs/ext2/ext2fs.c
@@ -25,152 +25,12 @@ 
 
 #include <common.h>
 #include <ext2fs.h>
+#include <ext_common.h>
 #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;
+struct ext2_data *ext2fs_root;
+struct ext2fs_node *ext2fs_file;
 int symlinknest = 0;
 uint32_t *indir1_block = NULL;
 int indir1_size = 0;
@@ -178,8 +38,7 @@  int indir1_blkno = -1;
 uint32_t *indir2_block = NULL;
 int indir2_size = 0;
 int indir2_blkno = -1;
-static unsigned int inode_size;
-
+unsigned int inode_size;
 
 static int ext2fs_blockgroup
 	(struct ext2_data *data, int group, struct ext2_block_group *blkgrp) {
@@ -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,155 +99,16 @@  static int ext2fs_read_inode
 	return (1);
 }
 
-
-void ext2fs_free_node (ext2fs_node_t node, ext2fs_node_t currroot) {
+void ext2fs_free_node(struct ext2fs_node *node, struct ext2fs_node *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) {
+	(struct ext2fs_node *node, int pos, unsigned int len, char *buf)
+{
 	int i;
 	int blockcnt;
 	int log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data);
@@ -409,8 +127,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 +166,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(struct ext2fs_node *dir, char *name,
+					struct ext2fs_node **fnode, int *ftype)
 {
 	unsigned int fpos = 0;
 	int status;
@@ -479,7 +196,7 @@  static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fn
 		}
 		if (dirent.namelen != 0) {
 			char filename[dirent.namelen + 1];
-			ext2fs_node_t fdiro;
+			struct ext2fs_node *fdiro;
 			int type = FILETYPE_UNKNOWN;
 
 			status = ext2fs_read_file (diro,
@@ -581,8 +298,8 @@  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) {
+static char *ext2fs_read_symlink(struct ext2fs_node *node)
+{
 	char *symlink;
 	struct ext2fs_node *diro = node;
 	int status;
@@ -617,17 +334,17 @@  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) {
+	(const char *currpath, struct ext2fs_node *currroot,
+		struct ext2fs_node **currfound, int *foundtype)
+{
 	char fpath[strlen (currpath) + 1];
 	char *name = fpath;
 	char *next;
 	int status;
 	int type = FILETYPE_DIRECTORY;
-	ext2fs_node_t currnode = currroot;
-	ext2fs_node_t oldnode = currroot;
+	struct ext2fs_node *currnode = currroot;
+	struct ext2fs_node *oldnode = currroot;
 
 	strncpy (fpath, currpath, strlen (currpath) + 1);
 
@@ -721,14 +438,13 @@  int ext2fs_find_file1
 	return (-1);
 }
 
-
 int ext2fs_find_file
-	(const char *path,
-	 ext2fs_node_t rootnode, ext2fs_node_t * foundnode, int expecttype) {
+	(const char *path, struct ext2fs_node *rootnode,
+	struct ext2fs_node **foundnode, int expecttype)
+{
 	int status;
 	int foundtype = FILETYPE_DIRECTORY;
 
-
 	symlinknest = 0;
 	if (!path) {
 		return (0);
@@ -748,9 +464,8 @@  int ext2fs_find_file
 	return (1);
 }
 
-
 int ext2fs_ls (const char *dirname) {
-	ext2fs_node_t dirnode;
+	struct ext2fs_node *dirnode;
 	int status;
 
 	if (ext2fs_root == NULL) {
@@ -768,9 +483,8 @@  int ext2fs_ls (const char *dirname) {
 	return (0);
 }
 
-
 int ext2fs_open (const char *filename) {
-	ext2fs_node_t fdiro = NULL;
+	struct ext2fs_node *fdiro = NULL;
 	int status;
 	int len;
 
@@ -799,7 +513,6 @@  fail:
 	return (-1);
 }
 
-
 int ext2fs_close (void
 	) {
 	if ((ext2fs_file != NULL) && (ext2fs_root != NULL)) {
@@ -825,7 +538,6 @@  int ext2fs_close (void
 	return (0);
 }
 
-
 int ext2fs_read (char *buf, unsigned len) {
 	int status;
 
@@ -836,12 +548,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 +590,7 @@  int ext2fs_mount (unsigned part_length) {
 	}
 
 	ext2fs_root = data;
-
+	ext4fs_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@denx.de.
+#
+# (C) Copyright 2003
+# Pavel Bartusek, Sysgo Real-Time Solutions AG, pba@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..6f9351c
--- /dev/null
+++ b/fs/ext4/ext4_common.c
@@ -0,0 +1,573 @@ 
+/*
+ * (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 <ext_common.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;
+struct ext2fs_node *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 ext2_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 ext2_inode *inode)
+{
+	struct ext2_block_group blkgrp;
+	struct ext2_sblock *sblock = &data->sblock;
+	struct ext_filesystem *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 ext2_inode), (char *)inode);
+	if (status == 0)
+		return 0;
+
+	return 1;
+}
+
+long int read_allocated_block(struct ext2_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 %ld\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)
+{
+	struct ext2fs_node *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,
+				&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;
+	struct ext_filesystem *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, data->inode);
+	if (status == 0)
+		goto fail;
+
+	inode_size = fs->inodesz;
+	ext4fs_root = data;
+	ext2fs_root = data;
+	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..73f218d
--- /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 <ext_common.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
+
+extern unsigned long part_offset;
+int ext4fs_read_inode(struct ext2_data *data, int ino,
+		      struct ext2_inode *inode);
+#endif
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
new file mode 100644
index 0000000..d4faa16
--- /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 <ext_common.h>
+#include <ext4fs.h>
+#include "ext4_common.h"
+
+int ext4fs_symlinknest;
+block_dev_desc_t *ext4_dev_desc;
+
+struct ext_filesystem *get_fs(void)
+{
+	if (ext4_dev_desc == NULL || ext4_dev_desc->priv == NULL)
+		printf("Invalid Input Arguments %s\n", __func__);
+	return (struct ext_filesystem *)ext4_dev_desc->priv;
+}
+
+int init_fs(block_dev_desc_t *dev_desc)
+{
+	struct ext_filesystem *fs;
+	if (dev_desc == NULL) {
+		printf("Invalid Input Arguments %s\n", __func__);
+		return -1;
+	}
+
+	fs = (struct ext_filesystem *)xzalloc(sizeof(struct ext_filesystem));
+	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(struct ext2fs_node *node, struct ext2fs_node *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(struct ext2fs_node *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(&(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)
+{
+	struct ext2fs_node *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..7d4834c 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,12 @@  typedef enum
   ERR_DEV_NEED_INIT,
   ERR_NO_DISK_SPACE,
   ERR_NUMBER_OVERFLOW,
-
   MAX_ERR_NUM
 } ext2fs_error_t;
 
-
-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_ls(const char *dirname);
+int ext2fs_open(const char *filename);
+int ext2fs_read(char *buf, unsigned len);
+int ext2fs_close(void);
+int ext2_register_device(block_dev_desc_t *dev_desc, int part_no);
+#endif
diff --git a/include/ext4fs.h b/include/ext4fs.h
new file mode 100644
index 0000000..fd7bd47
--- /dev/null
+++ b/include/ext4fs.h
@@ -0,0 +1,116 @@ 
+/*
+ * (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., 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__
+#include <ext_common.h>
+
+#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
+
+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;
+};
+
+struct ext_filesystem {
+	/*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;
+};
+
+/*############################*/
+extern block_dev_desc_t *ext4_dev_desc;
+/*#########################*/
+
+extern struct ext2_data *ext4fs_root;
+extern struct ext2fs_node *ext4fs_file;
+struct ext_filesystem *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);
+void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot);
+extern int ext2fs_devread(int sector, int byte_offset, int byte_len, char *buf);
+extern void *xzalloc(size_t size);
+#endif
diff --git a/include/ext_common.h b/include/ext_common.h
new file mode 100644
index 0000000..8b0474c
--- /dev/null
+++ b/include/ext_common.h
@@ -0,0 +1,199 @@ 
+/*
+ * (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.
+ */
+
+
+/* Some parts of this code (mainly the structures and defines) are
+ * from the original ext2 fs code, as found in the linux kernel.
+ */
+
+#ifndef __EXT_COMMON__
+#define __EXT_COMMON__
+
+#define SECTOR_SIZE		0x200
+#define SECTOR_BITS		9
+
+/* 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 */
+
+/* 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;
+};
+
+extern unsigned int inode_size;
+extern struct ext2_data *ext2fs_root;
+extern struct ext2_data *ext4fs_root;
+extern int ext2fs_iterate_dir(struct ext2fs_node *dir, char *name,
+			struct ext2fs_node **fnode, int *ftype);
+extern int ext2fs_find_file(const char *path, struct ext2fs_node *rootnode,
+	struct ext2fs_node **foundnode, int expecttype);
+extern int ext2fs_devread(int sector, int byte_offset, int byte_len, char *buf);
+int ext2fs_set_blk_dev(block_dev_desc_t *rbdd, int part);
+uint32_t div_roundup(uint32_t size, uint32_t n);
+long int read_allocated_block(struct ext2_inode *inode, int fileblock);
+int ext2fs_mount(unsigned part_length);
+void *xmalloc(size_t size);
+void *xzalloc(size_t size);
+#endif