summaryrefslogtreecommitdiffstats
path: root/recipes-bsp/u-boot/u-boot/2011.09git/0009-ext4fs-ls-load-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-bsp/u-boot/u-boot/2011.09git/0009-ext4fs-ls-load-support.patch')
-rw-r--r--recipes-bsp/u-boot/u-boot/2011.09git/0009-ext4fs-ls-load-support.patch2362
1 files changed, 2362 insertions, 0 deletions
diff --git a/recipes-bsp/u-boot/u-boot/2011.09git/0009-ext4fs-ls-load-support.patch b/recipes-bsp/u-boot/u-boot/2011.09git/0009-ext4fs-ls-load-support.patch
new file mode 100644
index 00000000..37ef5d4a
--- /dev/null
+++ b/recipes-bsp/u-boot/u-boot/2011.09git/0009-ext4fs-ls-load-support.patch
@@ -0,0 +1,2362 @@
1From 4e2f3f39a37883bddbe92a71045cb90f489e1d5f Mon Sep 17 00:00:00 2001
2From: "uma.shankar" <uma.shankar@samsung.com>
3Date: Mon, 9 Jan 2012 07:54:50 +0000
4Subject: [PATCH 09/10] ext4fs ls load support
5
6Signed-off-by: Uma Shankar <uma.shankar@samsung.com>
7Signed-off-by: Manjunatha C Achar <a.manjunatha@samsung.com>
8Signed-off-by: Iqbal Shareef <iqbal.ams@samsung.com>
9Signed-off-by: Hakgoo Lee <goodguy.lee@samsung.com>
10---
11 Makefile | 2 +-
12 common/Makefile | 1 +
13 common/cmd_ext4.c | 266 +++++++++++++++
14 fs/Makefile | 1 +
15 fs/ext2/dev.c | 1 +
16 fs/ext2/ext2fs.c | 181 ++--------
17 fs/ext4/Makefile | 51 +++
18 fs/ext4/dev.c | 145 ++++++++
19 fs/ext4/ext4_common.c | 875 +++++++++++++++++++++++++++++++++++++++++++++++++
20 fs/ext4/ext4_common.h | 63 ++++
21 fs/ext4/ext4fs.c | 228 +++++++++++++
22 include/ext4fs.h | 132 ++++++++
23 include/ext_common.h | 188 +++++++++++
24 13 files changed, 1977 insertions(+), 157 deletions(-)
25 create mode 100644 common/cmd_ext4.c
26 create mode 100644 fs/ext4/Makefile
27 create mode 100644 fs/ext4/dev.c
28 create mode 100644 fs/ext4/ext4_common.c
29 create mode 100644 fs/ext4/ext4_common.h
30 create mode 100644 fs/ext4/ext4fs.c
31 create mode 100644 include/ext4fs.h
32 create mode 100644 include/ext_common.h
33
34diff --git a/Makefile b/Makefile
35index 99b9278..6a5068d 100644
36--- a/Makefile
37+++ b/Makefile
38@@ -226,7 +226,7 @@ LIBS += arch/arm/cpu/ixp/npe/libnpe.o
39 endif
40 LIBS += arch/$(ARCH)/lib/lib$(ARCH).o
41 LIBS += fs/cramfs/libcramfs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o \
42- fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o fs/yaffs2/libyaffs2.o \
43+ fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o fs/ext4/libext4fs.o fs/yaffs2/libyaffs2.o \
44 fs/ubifs/libubifs.o
45 LIBS += net/libnet.o
46 LIBS += disk/libdisk.o
47diff --git a/common/Makefile b/common/Makefile
48index 838ae25..b9b5c85 100644
49--- a/common/Makefile
50+++ b/common/Makefile
51@@ -87,6 +87,7 @@ COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o
52 COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
53 COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o
54 COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o
55+COBJS-$(CONFIG_CMD_EXT4) += cmd_ext4.o
56 COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o
57 COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o
58 COBJS-$(CONFIG_CMD_FDC)$(CONFIG_CMD_FDOS) += cmd_fdc.o
59diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c
60new file mode 100644
61index 0000000..2c53d2c
62--- /dev/null
63+++ b/common/cmd_ext4.c
64@@ -0,0 +1,266 @@
65+/*
66+ * (C) Copyright 2011 - 2012 Samsung Electronics
67+ * EXT4 filesystem implementation in Uboot by
68+ * Uma Shankar <uma.shankar@samsung.com>
69+ * Manjunatha C Achar <a.manjunatha@samsung.com>
70+ *
71+ * Ext4fs support
72+ * made from existing cmd_ext2.c file of Uboot
73+ *
74+ * (C) Copyright 2004
75+ * esd gmbh <www.esd-electronics.com>
76+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
77+ *
78+ * made from cmd_reiserfs by
79+ *
80+ * (C) Copyright 2003 - 2004
81+ * Sysgo Real-Time Solutions, AG <www.elinos.com>
82+ * Pavel Bartusek <pba@sysgo.com>
83+ *
84+ * This program is free software; you can redistribute it and/or
85+ * modify it under the terms of the GNU General Public License as
86+ * published by the Free Software Foundation; either version 2 of
87+ * the License, or (at your option) any later version.
88+ *
89+ * This program is distributed in the hope that it will be useful,
90+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
91+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92+ * GNU General Public License for more details.
93+ *
94+ * You should have received a copy of the GNU General Public License
95+ * along with this program; if not, write to the Free Software
96+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
97+ * MA 02111-1307 USA
98+ *
99+ */
100+
101+/*
102+ * Changelog:
103+ * 0.1 - Newly created file for ext4fs support. Taken from cmd_ext2.c
104+ * file in uboot. Added ext4fs ls and load support.
105+ */
106+
107+#include <common.h>
108+#include <part.h>
109+#include <config.h>
110+#include <command.h>
111+#include <image.h>
112+#include <linux/ctype.h>
113+#include <asm/byteorder.h>
114+#include <ext_common.h>
115+#include <ext4fs.h>
116+#include <linux/stat.h>
117+#include <malloc.h>
118+
119+#if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE)
120+#include <usb.h>
121+#endif
122+
123+#if !defined(CONFIG_DOS_PARTITION) && !defined(CONFIG_EFI_PARTITION)
124+#error DOS or EFI partition support must be selected
125+#endif
126+
127+uint64_t total_sector;
128+uint64_t part_offset;
129+
130+#define DOS_PART_MAGIC_OFFSET 0x1fe
131+#define DOS_FS_TYPE_OFFSET 0x36
132+#define DOS_FS32_TYPE_OFFSET 0x52
133+
134+static int do_ext4_load(cmd_tbl_t *cmdtp, int flag, int argc,
135+ char *const argv[])
136+{
137+ char *filename = NULL;
138+ char *ep;
139+ int dev;
140+ unsigned long part = 1;
141+ ulong addr = 0;
142+ ulong part_length;
143+ int filelen;
144+ disk_partition_t info;
145+ struct ext_filesystem *fs;
146+ char buf[12];
147+ unsigned long count;
148+ const char *addr_str;
149+
150+ count = 0;
151+ addr = simple_strtoul(argv[3], NULL, 16);
152+ filename = getenv("bootfile");
153+ switch (argc) {
154+ case 3:
155+ addr_str = getenv("loadaddr");
156+ if (addr_str != NULL)
157+ addr = simple_strtoul(addr_str, NULL, 16);
158+ else
159+ addr = CONFIG_SYS_LOAD_ADDR;
160+
161+ break;
162+ case 4:
163+ break;
164+ case 5:
165+ filename = argv[4];
166+ break;
167+ case 6:
168+ filename = argv[4];
169+ count = simple_strtoul(argv[5], NULL, 16);
170+ break;
171+
172+ default:
173+ return cmd_usage(cmdtp);
174+ }
175+
176+ if (!filename) {
177+ puts("** No boot file defined **\n");
178+ return 1;
179+ }
180+
181+ dev = (int)simple_strtoul(argv[2], &ep, 16);
182+ ext4_dev_desc = get_dev(argv[1], dev);
183+ if (ext4_dev_desc == NULL) {
184+ printf("** Block device %s %d not supported\n", argv[1], dev);
185+ return 1;
186+ }
187+ if (init_fs(ext4_dev_desc))
188+ return 1;
189+
190+ fs = get_fs();
191+ if (*ep) {
192+ if (*ep != ':') {
193+ puts("** Invalid boot device, use `dev[:part]' **\n");
194+ return 1;
195+ }
196+ part = simple_strtoul(++ep, NULL, 16);
197+ }
198+
199+ if (part != 0) {
200+ if (get_partition_info(fs->dev_desc, part, &info)) {
201+ printf("** Bad partition %lu **\n", part);
202+ return 1;
203+ }
204+
205+ if (strncmp((char *)info.type, BOOT_PART_TYPE,
206+ strlen(BOOT_PART_TYPE)) != 0) {
207+ printf("** Invalid partition type \"%s\""
208+ " (expect \"" BOOT_PART_TYPE "\")\n", info.type);
209+ return 1;
210+ }
211+ printf("Loading file \"%s\" "
212+ "from %s device %d:%lu %s\n",
213+ filename, argv[1], dev, part, info.name);
214+ } else {
215+ printf("Loading file \"%s\" from %s device %d\n",
216+ filename, argv[1], dev);
217+ }
218+
219+ part_length = ext4fs_set_blk_dev(fs->dev_desc, part);
220+ if (part_length == 0) {
221+ printf("**Bad partition - %s %d:%lu **\n", argv[1], dev, part);
222+ ext4fs_close();
223+ return 1;
224+ }
225+
226+ if (!ext4fs_mount(part_length)) {
227+ printf("** Bad ext2 partition or disk - %s %d:%lu **\n",
228+ argv[1], dev, part);
229+ ext4fs_close();
230+ return 1;
231+ }
232+
233+ filelen = ext4fs_open(filename);
234+ if (filelen < 0) {
235+ printf("** File not found %s\n", filename);
236+ ext4fs_close();
237+ return 1;
238+ }
239+ if ((count < filelen) && (count != 0))
240+ filelen = count;
241+
242+ if (ext4fs_read((char *)addr, filelen) != filelen) {
243+ printf("** Unable to read \"%s\" from %s %d:%lu **\n",
244+ filename, argv[1], dev, part);
245+ ext4fs_close();
246+ return 1;
247+ }
248+
249+ ext4fs_close();
250+ deinit_fs(fs->dev_desc);
251+ /* Loading ok, update default load address */
252+ load_addr = addr;
253+
254+ printf("%d bytes read\n", filelen);
255+ sprintf(buf, "%X", filelen);
256+ setenv("filesize", buf);
257+
258+ return 0;
259+}
260+
261+static int do_ext4_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
262+{
263+ const char *filename = "/";
264+ int dev;
265+ unsigned long part = 1;
266+ char *ep;
267+ struct ext_filesystem *fs;
268+ int part_length;
269+
270+ if (argc < 3)
271+ return cmd_usage(cmdtp);
272+
273+ dev = (int)simple_strtoul(argv[2], &ep, 16);
274+ ext4_dev_desc = get_dev(argv[1], dev);
275+
276+ if (ext4_dev_desc == NULL) {
277+ printf("\n** Block device %s %d not supported\n", argv[1], dev);
278+ return 1;
279+ }
280+
281+ if (init_fs(ext4_dev_desc))
282+ return 1;
283+
284+ fs = get_fs();
285+ if (*ep) {
286+ if (*ep != ':') {
287+ puts("\n** Invalid boot device, use `dev[:part]' **\n");
288+ return 1;
289+ }
290+ part = simple_strtoul(++ep, NULL, 16);
291+ }
292+
293+ if (argc == 4)
294+ filename = argv[3];
295+
296+ part_length = ext4fs_set_blk_dev(fs->dev_desc, part);
297+ if (part_length == 0) {
298+ printf("** Bad partition - %s %d:%lu **\n", argv[1], dev, part);
299+ ext4fs_close();
300+ return 1;
301+ }
302+
303+ if (!ext4fs_mount(part_length)) {
304+ printf("** Bad ext2 partition or disk - %s %d:%lu **\n",
305+ argv[1], dev, part);
306+ ext4fs_close();
307+ return 1;
308+ }
309+ if (ext4fs_ls(filename)) {
310+ printf("** Error ext2fs_ls() **\n");
311+ ext4fs_close();
312+ return 1;
313+ };
314+
315+ ext4fs_close();
316+ deinit_fs(fs->dev_desc);
317+
318+ return 0;
319+}
320+
321+U_BOOT_CMD(ext4ls, 4, 1, do_ext4_ls,
322+ "list files in a directory (default /)",
323+ "<interface> <dev[:part]> [directory]\n"
324+ " - list files from 'dev' on 'interface' in a 'directory'");
325+
326+U_BOOT_CMD(ext4load, 6, 0, do_ext4_load,
327+ "load binary file from a Ext2 filesystem",
328+ "<interface> <dev[:part]> [addr] [filename] [bytes]\n"
329+ " - load binary file 'filename' from 'dev' on 'interface'\n"
330+ " to address 'addr' from ext2 filesystem");
331diff --git a/fs/Makefile b/fs/Makefile
332index 22aad12..00a8f37 100644
333--- a/fs/Makefile
334+++ b/fs/Makefile
335@@ -23,6 +23,7 @@
336 #
337
338 subdirs-$(CONFIG_CMD_CRAMFS) := cramfs
339+subdirs-$(CONFIG_CMD_EXT4) += ext4
340 subdirs-$(CONFIG_CMD_EXT2) += ext2
341 subdirs-$(CONFIG_CMD_FAT) += fat
342 subdirs-$(CONFIG_CMD_FDOS) += fdos
343diff --git a/fs/ext2/dev.c b/fs/ext2/dev.c
344index 78851d0..339a16e 100644
345--- a/fs/ext2/dev.c
346+++ b/fs/ext2/dev.c
347@@ -27,6 +27,7 @@
348 #include <common.h>
349 #include <config.h>
350 #include <ext2fs.h>
351+#include <ext_common.h>
352
353 static block_dev_desc_t *ext2fs_block_dev_desc;
354 static disk_partition_t part_info;
355diff --git a/fs/ext2/ext2fs.c b/fs/ext2/ext2fs.c
356index 8531db5..ea3d98c 100644
357--- a/fs/ext2/ext2fs.c
358+++ b/fs/ext2/ext2fs.c
359@@ -25,152 +25,16 @@
360
361 #include <common.h>
362 #include <ext2fs.h>
363+#include <ext_common.h>
364 #include <malloc.h>
365 #include <asm/byteorder.h>
366
367 extern int ext2fs_devread (int sector, int byte_offset, int byte_len,
368 char *buf);
369
370-/* Magic value used to identify an ext2 filesystem. */
371-#define EXT2_MAGIC 0xEF53
372-/* Amount of indirect blocks in an inode. */
373-#define INDIRECT_BLOCKS 12
374-/* Maximum lenght of a pathname. */
375-#define EXT2_PATH_MAX 4096
376-/* Maximum nesting of symlinks, used to prevent a loop. */
377-#define EXT2_MAX_SYMLINKCNT 8
378-
379-/* Filetype used in directory entry. */
380-#define FILETYPE_UNKNOWN 0
381-#define FILETYPE_REG 1
382-#define FILETYPE_DIRECTORY 2
383-#define FILETYPE_SYMLINK 7
384-
385-/* Filetype information as used in inodes. */
386-#define FILETYPE_INO_MASK 0170000
387-#define FILETYPE_INO_REG 0100000
388-#define FILETYPE_INO_DIRECTORY 0040000
389-#define FILETYPE_INO_SYMLINK 0120000
390-
391-/* Bits used as offset in sector */
392-#define DISK_SECTOR_BITS 9
393-
394-/* Log2 size of ext2 block in 512 blocks. */
395-#define LOG2_EXT2_BLOCK_SIZE(data) (__le32_to_cpu (data->sblock.log2_block_size) + 1)
396-
397-/* Log2 size of ext2 block in bytes. */
398-#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu (data->sblock.log2_block_size) + 10)
399-
400-/* The size of an ext2 block in bytes. */
401-#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
402-
403-/* The ext2 superblock. */
404-struct ext2_sblock {
405- uint32_t total_inodes;
406- uint32_t total_blocks;
407- uint32_t reserved_blocks;
408- uint32_t free_blocks;
409- uint32_t free_inodes;
410- uint32_t first_data_block;
411- uint32_t log2_block_size;
412- uint32_t log2_fragment_size;
413- uint32_t blocks_per_group;
414- uint32_t fragments_per_group;
415- uint32_t inodes_per_group;
416- uint32_t mtime;
417- uint32_t utime;
418- uint16_t mnt_count;
419- uint16_t max_mnt_count;
420- uint16_t magic;
421- uint16_t fs_state;
422- uint16_t error_handling;
423- uint16_t minor_revision_level;
424- uint32_t lastcheck;
425- uint32_t checkinterval;
426- uint32_t creator_os;
427- uint32_t revision_level;
428- uint16_t uid_reserved;
429- uint16_t gid_reserved;
430- uint32_t first_inode;
431- uint16_t inode_size;
432- uint16_t block_group_number;
433- uint32_t feature_compatibility;
434- uint32_t feature_incompat;
435- uint32_t feature_ro_compat;
436- uint32_t unique_id[4];
437- char volume_name[16];
438- char last_mounted_on[64];
439- uint32_t compression_info;
440-};
441-
442-/* The ext2 blockgroup. */
443-struct ext2_block_group {
444- uint32_t block_id;
445- uint32_t inode_id;
446- uint32_t inode_table_id;
447- uint16_t free_blocks;
448- uint16_t free_inodes;
449- uint16_t used_dir_cnt;
450- uint32_t reserved[3];
451-};
452-
453-/* The ext2 inode. */
454-struct ext2_inode {
455- uint16_t mode;
456- uint16_t uid;
457- uint32_t size;
458- uint32_t atime;
459- uint32_t ctime;
460- uint32_t mtime;
461- uint32_t dtime;
462- uint16_t gid;
463- uint16_t nlinks;
464- uint32_t blockcnt; /* Blocks of 512 bytes!! */
465- uint32_t flags;
466- uint32_t osd1;
467- union {
468- struct datablocks {
469- uint32_t dir_blocks[INDIRECT_BLOCKS];
470- uint32_t indir_block;
471- uint32_t double_indir_block;
472- uint32_t tripple_indir_block;
473- } blocks;
474- char symlink[60];
475- } b;
476- uint32_t version;
477- uint32_t acl;
478- uint32_t dir_acl;
479- uint32_t fragment_addr;
480- uint32_t osd2[3];
481-};
482-
483-/* The header of an ext2 directory entry. */
484-struct ext2_dirent {
485- uint32_t inode;
486- uint16_t direntlen;
487- uint8_t namelen;
488- uint8_t filetype;
489-};
490-
491-struct ext2fs_node {
492- struct ext2_data *data;
493- struct ext2_inode inode;
494- int ino;
495- int inode_read;
496-};
497-
498-/* Information about a "mounted" ext2 filesystem. */
499-struct ext2_data {
500- struct ext2_sblock sblock;
501- struct ext2_inode *inode;
502- struct ext2fs_node diropen;
503-};
504-
505-
506-typedef struct ext2fs_node *ext2fs_node_t;
507
508 struct ext2_data *ext2fs_root = NULL;
509-ext2fs_node_t ext2fs_file = NULL;
510+struct ext2fs_node *ext2fs_file;
511 int symlinknest = 0;
512 uint32_t *indir1_block = NULL;
513 int indir1_size = 0;
514@@ -243,14 +107,16 @@ static int ext2fs_read_inode
515 }
516
517
518-void ext2fs_free_node (ext2fs_node_t node, ext2fs_node_t currroot) {
519+void ext2fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot)
520+{
521 if ((node != &ext2fs_root->diropen) && (node != currroot)) {
522 free (node);
523 }
524 }
525
526
527-static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
528+static int ext2fs_read_block(struct ext2fs_node *node, int fileblock)
529+{
530 struct ext2_data *data = node->data;
531 struct ext2_inode *inode = &node->inode;
532 int blknr;
533@@ -390,7 +256,8 @@ static int ext2fs_read_block (ext2fs_node_t node, int fileblock) {
534
535
536 int ext2fs_read_file
537- (ext2fs_node_t node, int pos, unsigned int len, char *buf) {
538+ (struct ext2fs_node *node, int pos, unsigned int len, char *buf)
539+{
540 int i;
541 int blockcnt;
542 int log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data);
543@@ -471,8 +338,8 @@ int ext2fs_read_file
544 return (len);
545 }
546
547-
548-static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fnode, int *ftype)
549+int ext2fs_iterate_dir(struct ext2fs_node *dir, char *name,
550+ struct ext2fs_node **fnode, int *ftype)
551 {
552 unsigned int fpos = 0;
553 int status;
554@@ -501,7 +368,7 @@ static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fn
555 }
556 if (dirent.namelen != 0) {
557 char filename[dirent.namelen + 1];
558- ext2fs_node_t fdiro;
559+ struct ext2fs_node *fdiro;
560 int type = FILETYPE_UNKNOWN;
561
562 status = ext2fs_read_file (diro,
563@@ -603,8 +470,8 @@ static int ext2fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fn
564 return (0);
565 }
566
567-
568-static char *ext2fs_read_symlink (ext2fs_node_t node) {
569+static char *ext2fs_read_symlink(struct ext2fs_node *node)
570+{
571 char *symlink;
572 struct ext2fs_node *diro = node;
573 int status;
574@@ -641,15 +508,16 @@ static char *ext2fs_read_symlink (ext2fs_node_t node) {
575
576
577 int ext2fs_find_file1
578- (const char *currpath,
579- ext2fs_node_t currroot, ext2fs_node_t * currfound, int *foundtype) {
580+ (const char *currpath, struct ext2fs_node *currroot,
581+ struct ext2fs_node **currfound, int *foundtype)
582+{
583 char fpath[strlen (currpath) + 1];
584 char *name = fpath;
585 char *next;
586 int status;
587 int type = FILETYPE_DIRECTORY;
588- ext2fs_node_t currnode = currroot;
589- ext2fs_node_t oldnode = currroot;
590+ struct ext2fs_node *currnode = currroot;
591+ struct ext2fs_node *oldnode = currroot;
592
593 strncpy (fpath, currpath, strlen (currpath) + 1);
594
595@@ -745,8 +613,9 @@ int ext2fs_find_file1
596
597
598 int ext2fs_find_file
599- (const char *path,
600- ext2fs_node_t rootnode, ext2fs_node_t * foundnode, int expecttype) {
601+ (const char *path, struct ext2fs_node *rootnode,
602+ struct ext2fs_node **foundnode, int expecttype)
603+{
604 int status;
605 int foundtype = FILETYPE_DIRECTORY;
606
607@@ -772,7 +641,7 @@ int ext2fs_find_file
608
609
610 int ext2fs_ls (const char *dirname) {
611- ext2fs_node_t dirnode;
612+ struct ext2fs_node *dirnode;
613 int status;
614
615 if (ext2fs_root == NULL) {
616@@ -792,7 +661,7 @@ int ext2fs_ls (const char *dirname) {
617
618
619 int ext2fs_open (const char *filename) {
620- ext2fs_node_t fdiro = NULL;
621+ struct ext2fs_node *fdiro = NULL;
622 int status;
623 int len;
624
625@@ -822,8 +691,8 @@ fail:
626 }
627
628
629-int ext2fs_close (void
630- ) {
631+int ext2fs_close(void)
632+{
633 if ((ext2fs_file != NULL) && (ext2fs_root != NULL)) {
634 ext2fs_free_node (ext2fs_file, &ext2fs_root->diropen);
635 ext2fs_file = NULL;
636diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile
637new file mode 100644
638index 0000000..7add4ab
639--- /dev/null
640+++ b/fs/ext4/Makefile
641@@ -0,0 +1,51 @@
642+#
643+# (C) Copyright 2006
644+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
645+#
646+# (C) Copyright 2003
647+# Pavel Bartusek, Sysgo Real-Time Solutions AG, pba@sysgo.de
648+#
649+#
650+# See file CREDITS for list of people who contributed to this
651+# project.
652+#
653+# This program is free software; you can redistribute it and/or
654+# modify it under the terms of the GNU General Public License as
655+# published by the Free Software Foundation; either version 2 of
656+# the License, or (at your option) any later version.
657+#
658+# This program is distributed in the hope that it will be useful,
659+# but WITHOUT ANY WARRANTY; without even the implied warranty of
660+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
661+# GNU General Public License for more details.
662+#
663+# You should have received a copy of the GNU General Public License
664+# along with this program; if not, write to the Free Software
665+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
666+# MA 02111-1307 USA
667+#
668+
669+include $(TOPDIR)/config.mk
670+
671+LIB = $(obj)libext4fs.o
672+
673+AOBJS =
674+COBJS-$(CONFIG_CMD_EXT4) := ext4fs.o ext4_common.o dev.o
675+
676+SRCS := $(AOBJS:.o=.S) $(COBJS-y:.o=.c)
677+OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS-y))
678+
679+
680+all: $(LIB) $(AOBJS)
681+
682+$(LIB): $(obj).depend $(OBJS)
683+ $(call cmd_link_o_target, $(OBJS))
684+
685+#########################################################################
686+
687+# defines $(obj).depend target
688+include $(SRCTREE)/rules.mk
689+
690+sinclude $(obj).depend
691+
692+#########################################################################
693diff --git a/fs/ext4/dev.c b/fs/ext4/dev.c
694new file mode 100644
695index 0000000..2054be3
696--- /dev/null
697+++ b/fs/ext4/dev.c
698@@ -0,0 +1,145 @@
699+/*
700+ * (C) Copyright 2011 - 2012 Samsung Electronics
701+ * EXT4 filesystem implementation in Uboot by
702+ * Uma Shankar <uma.shankar@samsung.com>
703+ * Manjunatha C Achar <a.manjunatha@samsung.com>
704+ *
705+ * made from existing ext2/dev.c file of Uboot
706+ * (C) Copyright 2004
707+ * esd gmbh <www.esd-electronics.com>
708+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
709+ *
710+ * based on code of fs/reiserfs/dev.c by
711+ *
712+ * (C) Copyright 2003 - 2004
713+ * Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
714+ *
715+ * This program is free software; you can redistribute it and/or modify
716+ * it under the terms of the GNU General Public License as published by
717+ * the Free Software Foundation; either version 2 of the License, or
718+ * (at your option) any later version.
719+ *
720+ * This program is distributed in the hope that it will be useful,
721+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
722+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
723+ * GNU General Public License for more details.
724+ *
725+ * You should have received a copy of the GNU General Public License
726+ * along with this program; if not, write to the Free Software
727+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
728+ *
729+ */
730+
731+/*
732+ * Changelog:
733+ * 0.1 - Newly created file for ext4fs support. Taken from
734+ * fs/ext2/dev.c file in uboot.
735+ */
736+
737+#include <common.h>
738+#include <config.h>
739+#include <ext_common.h>
740+
741+static block_dev_desc_t *ext4fs_block_dev_desc;
742+static disk_partition_t part_info;
743+
744+int ext4fs_set_blk_dev(block_dev_desc_t *rbdd, int part)
745+{
746+ ext4fs_block_dev_desc = rbdd;
747+
748+ if (part == 0) {
749+ /* disk doesn't use partition table */
750+ part_info.start = 0;
751+ part_info.size = rbdd->lba;
752+ part_info.blksz = rbdd->blksz;
753+ } else {
754+ if (get_partition_info(ext4fs_block_dev_desc,
755+ part, &part_info))
756+ return 0;
757+ }
758+ return part_info.size;
759+}
760+
761+int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf)
762+{
763+ char sec_buf[SECTOR_SIZE];
764+ unsigned block_len;
765+
766+ /* Check partition boundaries */
767+ if ((sector < 0)
768+ || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS)) >=
769+ part_info.size)) {
770+ printf("%s read outside partition %d\n", __func__, sector);
771+ return 0;
772+ }
773+
774+ /* Get the read to the beginning of a partition */
775+ sector += byte_offset >> SECTOR_BITS;
776+ byte_offset &= SECTOR_SIZE - 1;
777+
778+ debug(" <%d, %d, %d>\n", sector, byte_offset, byte_len);
779+
780+ if (ext4fs_block_dev_desc == NULL) {
781+ printf("** Invalid Block Device Descriptor (NULL)\n");
782+ return 0;
783+ }
784+
785+ if (byte_offset != 0) {
786+ /* read first part which isn't aligned with start of sector */
787+ if (ext4fs_block_dev_desc->
788+ block_read(ext4fs_block_dev_desc->dev,
789+ part_info.start + sector, 1,
790+ (unsigned long *) sec_buf) != 1) {
791+ printf(" ** ext2fs_devread() read error **\n");
792+ return 0;
793+ }
794+ memcpy(buf, sec_buf + byte_offset,
795+ min(SECTOR_SIZE - byte_offset, byte_len));
796+ buf += min(SECTOR_SIZE - byte_offset, byte_len);
797+ byte_len -= min(SECTOR_SIZE - byte_offset, byte_len);
798+ sector++;
799+ }
800+
801+ if (byte_len == 0)
802+ return 1;
803+
804+ /* read sector aligned part */
805+ block_len = byte_len & ~(SECTOR_SIZE - 1);
806+
807+ if (block_len == 0) {
808+ u8 p[SECTOR_SIZE];
809+
810+ block_len = SECTOR_SIZE;
811+ ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev,
812+ part_info.start + sector,
813+ 1, (unsigned long *)p);
814+ memcpy(buf, p, byte_len);
815+ return 1;
816+ }
817+
818+ if (ext4fs_block_dev_desc->block_read(ext4fs_block_dev_desc->dev,
819+ part_info.start + sector,
820+ block_len / SECTOR_SIZE,
821+ (unsigned long *) buf) !=
822+ block_len / SECTOR_SIZE) {
823+ printf(" ** %s read error - block\n", __func__);
824+ return 0;
825+ }
826+ block_len = byte_len & ~(SECTOR_SIZE - 1);
827+ buf += block_len;
828+ byte_len -= block_len;
829+ sector += block_len / SECTOR_SIZE;
830+
831+ if (byte_len != 0) {
832+ /* read rest of data which are not in whole sector */
833+ if (ext4fs_block_dev_desc->
834+ block_read(ext4fs_block_dev_desc->dev,
835+ part_info.start + sector, 1,
836+ (unsigned long *) sec_buf) != 1) {
837+ printf("* %s read error - last part\n", __func__);
838+ return 0;
839+ }
840+ memcpy(buf, sec_buf, byte_len);
841+ }
842+ return 1;
843+}
844diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
845new file mode 100644
846index 0000000..d9deefe
847--- /dev/null
848+++ b/fs/ext4/ext4_common.c
849@@ -0,0 +1,875 @@
850+/*
851+ * (C) Copyright 2011 - 2012 Samsung Electronics
852+ * EXT4 filesystem implementation in Uboot by
853+ * Uma Shankar <uma.shankar@samsung.com>
854+ * Manjunatha C Achar <a.manjunatha@samsung.com>
855+ *
856+ * ext4ls and ext4load : Based on ext2 ls load support in Uboot.
857+ *
858+ * (C) Copyright 2004
859+ * esd gmbh <www.esd-electronics.com>
860+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
861+ *
862+ * based on code from grub2 fs/ext2.c and fs/fshelp.c by
863+ * GRUB -- GRand Unified Bootloader
864+ * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
865+ *
866+ * This program is free software; you can redistribute it and/or modify
867+ * it under the terms of the GNU General Public License as published by
868+ * the Free Software Foundation; either version 2 of the License, or
869+ * (at your option) any later version.
870+ *
871+ * This program is distributed in the hope that it will be useful,
872+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
873+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
874+ * GNU General Public License for more details.
875+ *
876+ * You should have received a copy of the GNU General Public License
877+ * along with this program; if not, write to the Free Software
878+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
879+ */
880+
881+#include <common.h>
882+#include <ext_common.h>
883+#include <ext4fs.h>
884+#include <malloc.h>
885+#include <stddef.h>
886+#include <linux/stat.h>
887+#include <linux/time.h>
888+#include <asm/byteorder.h>
889+#include "ext4_common.h"
890+
891+struct ext2_data *ext4fs_root;
892+struct ext2fs_node *ext4fs_file;
893+uint32_t *ext4fs_indir1_block;
894+int ext4fs_indir1_size;
895+int ext4fs_indir1_blkno = -1;
896+uint32_t *ext4fs_indir2_block;
897+int ext4fs_indir2_size;
898+int ext4fs_indir2_blkno = -1;
899+
900+uint32_t *ext4fs_indir3_block;
901+int ext4fs_indir3_size;
902+int ext4fs_indir3_blkno = -1;
903+struct ext2_inode *g_parent_inode;
904+static int symlinknest;
905+
906+static struct ext4_extent_header *ext4fs_get_extent_block
907+ (struct ext2_data *data, char *buf,
908+ struct ext4_extent_header *ext_block,
909+ uint32_t fileblock, int log2_blksz)
910+{
911+ struct ext4_extent_idx *index;
912+ unsigned long long block;
913+ struct ext_filesystem *fs = get_fs();
914+ int i;
915+
916+ while (1) {
917+ index = (struct ext4_extent_idx *)(ext_block + 1);
918+
919+ if (le32_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
920+ return 0;
921+
922+ if (ext_block->eh_depth == 0)
923+ return ext_block;
924+ i = -1;
925+ do {
926+ i++;
927+ if (i >= le32_to_cpu(ext_block->eh_entries))
928+ break;
929+ } while (fileblock > le32_to_cpu(index[i].ei_block));
930+
931+ if (--i < 0)
932+ return 0;
933+
934+ block = le32_to_cpu(index[i].ei_leaf_hi);
935+ block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo);
936+
937+ if (ext4fs_devread(block << log2_blksz, 0, fs->blksz, buf))
938+ ext_block = (struct ext4_extent_header *)buf;
939+ else
940+ return 0;
941+ }
942+}
943+
944+static int ext4fs_blockgroup
945+ (struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
946+{
947+ long int blkno;
948+ unsigned int blkoff, desc_per_blk;
949+
950+ desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
951+
952+ blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 +
953+ group / desc_per_blk;
954+ blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
955+
956+ debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
957+ group, blkno, blkoff);
958+
959+ return ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data),
960+ blkoff, sizeof(struct ext2_block_group),
961+ (char *)blkgrp);
962+}
963+
964+int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
965+{
966+ struct ext2_block_group blkgrp;
967+ struct ext2_sblock *sblock = &data->sblock;
968+ struct ext_filesystem *fs = get_fs();
969+ int inodes_per_block, status;
970+ long int blkno;
971+ unsigned int blkoff;
972+
973+ /* It is easier to calculate if the first inode is 0. */
974+ ino--;
975+ status = ext4fs_blockgroup(data, ino / __le32_to_cpu
976+ (sblock->inodes_per_group), &blkgrp);
977+ if (status == 0)
978+ return 0;
979+
980+ inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz;
981+ blkno = __le32_to_cpu(blkgrp.inode_table_id) +
982+ (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
983+ blkoff = (ino % inodes_per_block) * fs->inodesz;
984+ /* Read the inode. */
985+ status = ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), blkoff,
986+ sizeof(struct ext2_inode), (char *)inode);
987+ if (status == 0)
988+ return 0;
989+
990+ return 1;
991+}
992+
993+long int read_allocated_block(struct ext2_inode *inode, int fileblock)
994+{
995+ long int blknr;
996+ int blksz;
997+ int log2_blksz;
998+ int status;
999+ long int rblock;
1000+ long int perblock_parent;
1001+ long int perblock_child;
1002+ unsigned long long start;
1003+ /* get the blocksize of the filesystem */
1004+ blksz = EXT2_BLOCK_SIZE(ext4fs_root);
1005+ log2_blksz = LOG2_EXT2_BLOCK_SIZE(ext4fs_root);
1006+ if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
1007+ char *buf = zalloc(blksz);
1008+ if (!buf)
1009+ return -ENOMEM;
1010+ struct ext4_extent_header *ext_block;
1011+ struct ext4_extent *extent;
1012+ int i = -1;
1013+ ext_block = ext4fs_get_extent_block(ext4fs_root, buf,
1014+ (struct ext4_extent_header
1015+ *)inode->b.
1016+ blocks.dir_blocks,
1017+ fileblock, log2_blksz);
1018+ if (!ext_block) {
1019+ printf("invalid extent block\n");
1020+ free(buf);
1021+ return -EINVAL;
1022+ }
1023+
1024+ extent = (struct ext4_extent *)(ext_block + 1);
1025+
1026+ do {
1027+ i++;
1028+ if (i >= le32_to_cpu(ext_block->eh_entries))
1029+ break;
1030+ } while (fileblock >= le32_to_cpu(extent[i].ee_block));
1031+ if (--i >= 0) {
1032+ fileblock -= le32_to_cpu(extent[i].ee_block);
1033+ if (fileblock >= le32_to_cpu(extent[i].ee_len)) {
1034+ free(buf);
1035+ return 0;
1036+ }
1037+
1038+ start = le32_to_cpu(extent[i].ee_start_hi);
1039+ start = (start << 32) +
1040+ le32_to_cpu(extent[i].ee_start_lo);
1041+ free(buf);
1042+ return fileblock + start;
1043+ }
1044+
1045+ printf("Extent Error\n");
1046+ free(buf);
1047+ return -1;
1048+ }
1049+
1050+ /* Direct blocks. */
1051+ if (fileblock < INDIRECT_BLOCKS)
1052+ blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
1053+
1054+ /* Indirect. */
1055+ else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
1056+ if (ext4fs_indir1_block == NULL) {
1057+ ext4fs_indir1_block = zalloc(blksz);
1058+ if (ext4fs_indir1_block == NULL) {
1059+ printf("** SI ext2fs read block (indir 1)"
1060+ "malloc failed. **\n");
1061+ return -1;
1062+ }
1063+ ext4fs_indir1_size = blksz;
1064+ ext4fs_indir1_blkno = -1;
1065+ }
1066+ if (blksz != ext4fs_indir1_size) {
1067+ free(ext4fs_indir1_block);
1068+ ext4fs_indir1_block = NULL;
1069+ ext4fs_indir1_size = 0;
1070+ ext4fs_indir1_blkno = -1;
1071+ ext4fs_indir1_block = zalloc(blksz);
1072+ if (ext4fs_indir1_block == NULL) {
1073+ printf("** SI ext2fs read block (indir 1):"
1074+ "malloc failed. **\n");
1075+ return -1;
1076+ }
1077+ ext4fs_indir1_size = blksz;
1078+ }
1079+ if ((__le32_to_cpu(inode->b.blocks.indir_block) <<
1080+ log2_blksz) != ext4fs_indir1_blkno) {
1081+ status =
1082+ ext4fs_devread(__le32_to_cpu
1083+ (inode->b.blocks.
1084+ indir_block) << log2_blksz, 0,
1085+ blksz, (char *)ext4fs_indir1_block);
1086+ if (status == 0) {
1087+ printf("** SI ext2fs read block (indir 1)"
1088+ "failed. **\n");
1089+ return 0;
1090+ }
1091+ ext4fs_indir1_blkno =
1092+ __le32_to_cpu(inode->b.blocks.
1093+ indir_block) << log2_blksz;
1094+ }
1095+ blknr = __le32_to_cpu(ext4fs_indir1_block
1096+ [fileblock - INDIRECT_BLOCKS]);
1097+ }
1098+ /* Double indirect. */
1099+ else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 *
1100+ (blksz / 4 + 1)))) {
1101+
1102+ long int perblock = blksz / 4;
1103+ long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
1104+
1105+ if (ext4fs_indir1_block == NULL) {
1106+ ext4fs_indir1_block = zalloc(blksz);
1107+ if (ext4fs_indir1_block == NULL) {
1108+ printf("** DI ext2fs read block (indir 2 1)"
1109+ "malloc failed. **\n");
1110+ return -1;
1111+ }
1112+ ext4fs_indir1_size = blksz;
1113+ ext4fs_indir1_blkno = -1;
1114+ }
1115+ if (blksz != ext4fs_indir1_size) {
1116+ free(ext4fs_indir1_block);
1117+ ext4fs_indir1_block = NULL;
1118+ ext4fs_indir1_size = 0;
1119+ ext4fs_indir1_blkno = -1;
1120+ ext4fs_indir1_block = zalloc(blksz);
1121+ if (ext4fs_indir1_block == NULL) {
1122+ printf("** DI ext2fs read block (indir 2 1)"
1123+ "malloc failed. **\n");
1124+ return -1;
1125+ }
1126+ ext4fs_indir1_size = blksz;
1127+ }
1128+ if ((__le32_to_cpu(inode->b.blocks.double_indir_block) <<
1129+ log2_blksz) != ext4fs_indir1_blkno) {
1130+ status =
1131+ ext4fs_devread(__le32_to_cpu
1132+ (inode->b.blocks.
1133+ double_indir_block) << log2_blksz,
1134+ 0, blksz,
1135+ (char *)ext4fs_indir1_block);
1136+ if (status == 0) {
1137+ printf("** DI ext2fs read block (indir 2 1)"
1138+ "failed. **\n");
1139+ return -1;
1140+ }
1141+ ext4fs_indir1_blkno =
1142+ __le32_to_cpu(inode->b.blocks.double_indir_block) <<
1143+ log2_blksz;
1144+ }
1145+
1146+ if (ext4fs_indir2_block == NULL) {
1147+ ext4fs_indir2_block = zalloc(blksz);
1148+ if (ext4fs_indir2_block == NULL) {
1149+ printf("** DI ext2fs read block (indir 2 2)"
1150+ "malloc failed. **\n");
1151+ return -1;
1152+ }
1153+ ext4fs_indir2_size = blksz;
1154+ ext4fs_indir2_blkno = -1;
1155+ }
1156+ if (blksz != ext4fs_indir2_size) {
1157+ free(ext4fs_indir2_block);
1158+ ext4fs_indir2_block = NULL;
1159+ ext4fs_indir2_size = 0;
1160+ ext4fs_indir2_blkno = -1;
1161+ ext4fs_indir2_block = zalloc(blksz);
1162+ if (ext4fs_indir2_block == NULL) {
1163+ printf("** DI ext2fs read block (indir 2 2)"
1164+ "malloc failed. **\n");
1165+ return -1;
1166+ }
1167+ ext4fs_indir2_size = blksz;
1168+ }
1169+ if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) <<
1170+ log2_blksz) != ext4fs_indir2_blkno) {
1171+ status = ext4fs_devread(__le32_to_cpu
1172+ (ext4fs_indir1_block
1173+ [rblock /
1174+ perblock]) << log2_blksz, 0,
1175+ blksz,
1176+ (char *)ext4fs_indir2_block);
1177+ if (status == 0) {
1178+ printf("** DI ext2fs read block (indir 2 2)"
1179+ "failed. **\n");
1180+ return -1;
1181+ }
1182+ ext4fs_indir2_blkno =
1183+ __le32_to_cpu(ext4fs_indir1_block[rblock
1184+ /
1185+ perblock]) <<
1186+ log2_blksz;
1187+ }
1188+ blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]);
1189+ }
1190+ /* Tripple indirect. */
1191+ else {
1192+ rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 +
1193+ (blksz / 4 * blksz / 4));
1194+ perblock_child = blksz / 4;
1195+ perblock_parent = ((blksz / 4) * (blksz / 4));
1196+
1197+ if (ext4fs_indir1_block == NULL) {
1198+ ext4fs_indir1_block = zalloc(blksz);
1199+ if (ext4fs_indir1_block == NULL) {
1200+ printf("** TI ext2fs read block (indir 2 1)"
1201+ "malloc failed. **\n");
1202+ return -1;
1203+ }
1204+ ext4fs_indir1_size = blksz;
1205+ ext4fs_indir1_blkno = -1;
1206+ }
1207+ if (blksz != ext4fs_indir1_size) {
1208+ free(ext4fs_indir1_block);
1209+ ext4fs_indir1_block = NULL;
1210+ ext4fs_indir1_size = 0;
1211+ ext4fs_indir1_blkno = -1;
1212+ ext4fs_indir1_block = zalloc(blksz);
1213+ if (ext4fs_indir1_block == NULL) {
1214+ printf("** TI ext2fs read block (indir 2 1)"
1215+ "malloc failed. **\n");
1216+ return -1;
1217+ }
1218+ ext4fs_indir1_size = blksz;
1219+ }
1220+ if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) <<
1221+ log2_blksz) != ext4fs_indir1_blkno) {
1222+ status = ext4fs_devread
1223+ (__le32_to_cpu(inode->b.blocks.triple_indir_block)
1224+ << log2_blksz, 0, blksz,
1225+ (char *)ext4fs_indir1_block);
1226+ if (status == 0) {
1227+ printf("** TI ext2fs read block (indir 2 1)"
1228+ "failed. **\n");
1229+ return -1;
1230+ }
1231+ ext4fs_indir1_blkno =
1232+ __le32_to_cpu(inode->b.blocks.triple_indir_block) <<
1233+ log2_blksz;
1234+ }
1235+
1236+ if (ext4fs_indir2_block == NULL) {
1237+ ext4fs_indir2_block = zalloc(blksz);
1238+ if (ext4fs_indir2_block == NULL) {
1239+ printf("** TI ext2fs read block (indir 2 2)"
1240+ "malloc failed. **\n");
1241+ return -1;
1242+ }
1243+ ext4fs_indir2_size = blksz;
1244+ ext4fs_indir2_blkno = -1;
1245+ }
1246+ if (blksz != ext4fs_indir2_size) {
1247+ free(ext4fs_indir2_block);
1248+ ext4fs_indir2_block = NULL;
1249+ ext4fs_indir2_size = 0;
1250+ ext4fs_indir2_blkno = -1;
1251+ ext4fs_indir2_block = zalloc(blksz);
1252+ if (ext4fs_indir2_block == NULL) {
1253+ printf("** TI ext2fs read block (indir 2 2)"
1254+ "malloc failed. **\n");
1255+ return -1;
1256+ }
1257+ ext4fs_indir2_size = blksz;
1258+ }
1259+ if ((__le32_to_cpu(ext4fs_indir1_block[rblock /
1260+ perblock_parent]) <<
1261+ log2_blksz)
1262+ != ext4fs_indir2_blkno) {
1263+ status = ext4fs_devread(__le32_to_cpu
1264+ (ext4fs_indir1_block
1265+ [rblock /
1266+ perblock_parent]) <<
1267+ log2_blksz, 0, blksz,
1268+ (char *)ext4fs_indir2_block);
1269+ if (status == 0) {
1270+ printf("** TI ext2fs read block (indir 2 2)"
1271+ "failed. **\n");
1272+ return -1;
1273+ }
1274+ ext4fs_indir2_blkno =
1275+ __le32_to_cpu(ext4fs_indir1_block[rblock /
1276+ perblock_parent])
1277+ << log2_blksz;
1278+ }
1279+
1280+ if (ext4fs_indir3_block == NULL) {
1281+ ext4fs_indir3_block = zalloc(blksz);
1282+ if (ext4fs_indir3_block == NULL) {
1283+ printf("** TI ext2fs read block (indir 2 2)"
1284+ "malloc failed. **\n");
1285+ return -1;
1286+ }
1287+ ext4fs_indir3_size = blksz;
1288+ ext4fs_indir3_blkno = -1;
1289+ }
1290+ if (blksz != ext4fs_indir3_size) {
1291+ free(ext4fs_indir3_block);
1292+ ext4fs_indir3_block = NULL;
1293+ ext4fs_indir3_size = 0;
1294+ ext4fs_indir3_blkno = -1;
1295+ ext4fs_indir3_block = zalloc(blksz);
1296+ if (ext4fs_indir3_block == NULL) {
1297+ printf("** TI ext2fs read block (indir 2 2)"
1298+ "malloc failed. **\n");
1299+ return -1;
1300+ }
1301+ ext4fs_indir3_size = blksz;
1302+ }
1303+ if ((__le32_to_cpu(ext4fs_indir2_block[rblock
1304+ /
1305+ perblock_child]) <<
1306+ log2_blksz) != ext4fs_indir3_blkno) {
1307+ status =
1308+ ext4fs_devread(__le32_to_cpu
1309+ (ext4fs_indir2_block
1310+ [(rblock / perblock_child)
1311+ % (blksz / 4)]) << log2_blksz, 0,
1312+ blksz, (char *)ext4fs_indir3_block);
1313+ if (status == 0) {
1314+ printf("** TI ext2fs read block (indir 2 2)"
1315+ "failed. **\n");
1316+ return -1;
1317+ }
1318+ ext4fs_indir3_blkno =
1319+ __le32_to_cpu(ext4fs_indir2_block[(rblock /
1320+ perblock_child) %
1321+ (blksz /
1322+ 4)]) <<
1323+ log2_blksz;
1324+ }
1325+
1326+ blknr = __le32_to_cpu(ext4fs_indir3_block
1327+ [rblock % perblock_child]);
1328+ }
1329+ debug("ext4fs_read_block %ld\n", blknr);
1330+
1331+ return blknr;
1332+}
1333+
1334+void ext4fs_close(void)
1335+{
1336+ if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
1337+ ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen);
1338+ ext4fs_file = NULL;
1339+ }
1340+ if (ext4fs_root != NULL) {
1341+ free(ext4fs_root);
1342+ ext4fs_root = NULL;
1343+ }
1344+ if (ext4fs_indir1_block != NULL) {
1345+ free(ext4fs_indir1_block);
1346+ ext4fs_indir1_block = NULL;
1347+ ext4fs_indir1_size = 0;
1348+ ext4fs_indir1_blkno = -1;
1349+ }
1350+ if (ext4fs_indir2_block != NULL) {
1351+ free(ext4fs_indir2_block);
1352+ ext4fs_indir2_block = NULL;
1353+ ext4fs_indir2_size = 0;
1354+ ext4fs_indir2_blkno = -1;
1355+ }
1356+ if (ext4fs_indir3_block != NULL) {
1357+ free(ext4fs_indir3_block);
1358+ ext4fs_indir3_block = NULL;
1359+ ext4fs_indir3_size = 0;
1360+ ext4fs_indir3_blkno = -1;
1361+ }
1362+}
1363+
1364+int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
1365+ struct ext2fs_node **fnode, int *ftype)
1366+{
1367+ unsigned int fpos = 0;
1368+ int status;
1369+ struct ext2fs_node *diro = (struct ext2fs_node *)dir;
1370+
1371+#ifdef DEBUG
1372+ if (name != NULL)
1373+ printf("Iterate dir %s\n", name);
1374+#endif /* of DEBUG */
1375+ if (!diro->inode_read) {
1376+ status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
1377+ if (status == 0)
1378+ return 0;
1379+ }
1380+ /* Search the file. */
1381+ while (fpos < __le32_to_cpu(diro->inode.size)) {
1382+ struct ext2_dirent dirent;
1383+
1384+ status = ext4fs_read_file(diro, fpos,
1385+ sizeof(struct ext2_dirent),
1386+ (char *)&dirent);
1387+ if (status < 1)
1388+ return 0;
1389+
1390+ if (dirent.namelen != 0) {
1391+ char filename[dirent.namelen + 1];
1392+ struct ext2fs_node *fdiro;
1393+ int type = FILETYPE_UNKNOWN;
1394+
1395+ status = ext4fs_read_file(diro,
1396+ fpos +
1397+ sizeof(struct ext2_dirent),
1398+ dirent.namelen, filename);
1399+ if (status < 1)
1400+ return 0;
1401+
1402+ fdiro = zalloc(sizeof(struct ext2fs_node));
1403+ if (!fdiro)
1404+ return 0;
1405+
1406+ fdiro->data = diro->data;
1407+ fdiro->ino = __le32_to_cpu(dirent.inode);
1408+
1409+ filename[dirent.namelen] = '\0';
1410+
1411+ if (dirent.filetype != FILETYPE_UNKNOWN) {
1412+ fdiro->inode_read = 0;
1413+
1414+ if (dirent.filetype == FILETYPE_DIRECTORY)
1415+ type = FILETYPE_DIRECTORY;
1416+ else if (dirent.filetype == FILETYPE_SYMLINK)
1417+ type = FILETYPE_SYMLINK;
1418+ else if (dirent.filetype == FILETYPE_REG)
1419+ type = FILETYPE_REG;
1420+ } else {
1421+ status = ext4fs_read_inode(diro->data,
1422+ __le32_to_cpu
1423+ (dirent.inode),
1424+ &fdiro->inode);
1425+ if (status == 0) {
1426+ free(fdiro);
1427+ return 0;
1428+ }
1429+ fdiro->inode_read = 1;
1430+
1431+ if ((__le16_to_cpu(fdiro->inode.mode) &
1432+ FILETYPE_INO_MASK) ==
1433+ FILETYPE_INO_DIRECTORY) {
1434+ type = FILETYPE_DIRECTORY;
1435+ } else if ((__le16_to_cpu(fdiro->inode.mode)
1436+ & FILETYPE_INO_MASK) ==
1437+ FILETYPE_INO_SYMLINK) {
1438+ type = FILETYPE_SYMLINK;
1439+ } else if ((__le16_to_cpu(fdiro->inode.mode)
1440+ & FILETYPE_INO_MASK) ==
1441+ FILETYPE_INO_REG) {
1442+ type = FILETYPE_REG;
1443+ }
1444+ }
1445+#ifdef DEBUG
1446+ printf("iterate >%s<\n", filename);
1447+#endif /* of DEBUG */
1448+ if ((name != NULL) && (fnode != NULL)
1449+ && (ftype != NULL)) {
1450+ if (strcmp(filename, name) == 0) {
1451+ *ftype = type;
1452+ *fnode = fdiro;
1453+ return 1;
1454+ }
1455+ } else {
1456+ if (fdiro->inode_read == 0) {
1457+ status = ext4fs_read_inode(diro->data,
1458+ __le32_to_cpu(
1459+ dirent.inode),
1460+ &fdiro->inode);
1461+ if (status == 0) {
1462+ free(fdiro);
1463+ return 0;
1464+ }
1465+ fdiro->inode_read = 1;
1466+ }
1467+ switch (type) {
1468+ case FILETYPE_DIRECTORY:
1469+ printf("<DIR> ");
1470+ break;
1471+ case FILETYPE_SYMLINK:
1472+ printf("<SYM> ");
1473+ break;
1474+ case FILETYPE_REG:
1475+ printf(" ");
1476+ break;
1477+ default:
1478+ printf("< ? > ");
1479+ break;
1480+ }
1481+ printf("%10d %s\n",
1482+ __le32_to_cpu(fdiro->inode.size),
1483+ filename);
1484+ }
1485+ free(fdiro);
1486+ }
1487+ fpos += __le16_to_cpu(dirent.direntlen);
1488+ }
1489+ return 0;
1490+}
1491+
1492+static char *ext4fs_read_symlink(struct ext2fs_node *node)
1493+{
1494+ char *symlink;
1495+ struct ext2fs_node *diro = node;
1496+ int status;
1497+
1498+ if (!diro->inode_read) {
1499+ status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
1500+ if (status == 0)
1501+ return 0;
1502+ }
1503+ symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1);
1504+ if (!symlink)
1505+ return 0;
1506+
1507+ if (__le32_to_cpu(diro->inode.size) <= 60) {
1508+ strncpy(symlink, diro->inode.b.symlink,
1509+ __le32_to_cpu(diro->inode.size));
1510+ } else {
1511+ status = ext4fs_read_file(diro, 0,
1512+ __le32_to_cpu(diro->inode.size),
1513+ symlink);
1514+ if (status == 0) {
1515+ free(symlink);
1516+ return 0;
1517+ }
1518+ }
1519+ symlink[__le32_to_cpu(diro->inode.size)] = '\0';
1520+ return symlink;
1521+}
1522+
1523+static int ext4fs_find_file1(const char *currpath,
1524+ struct ext2fs_node *currroot,
1525+ struct ext2fs_node **currfound, int *foundtype)
1526+{
1527+ char fpath[strlen(currpath) + 1];
1528+ char *name = fpath;
1529+ char *next;
1530+ int status;
1531+ int type = FILETYPE_DIRECTORY;
1532+ struct ext2fs_node *currnode = currroot;
1533+ struct ext2fs_node *oldnode = currroot;
1534+
1535+ strncpy(fpath, currpath, strlen(currpath) + 1);
1536+
1537+ /* Remove all leading slashes. */
1538+ while (*name == '/')
1539+ name++;
1540+
1541+ if (!*name) {
1542+ *currfound = currnode;
1543+ return 1;
1544+ }
1545+
1546+ for (;;) {
1547+ int found;
1548+
1549+ /* Extract the actual part from the pathname. */
1550+ next = strchr(name, '/');
1551+ if (next) {
1552+ /* Remove all leading slashes. */
1553+ while (*next == '/')
1554+ *(next++) = '\0';
1555+ }
1556+
1557+ if (type != FILETYPE_DIRECTORY) {
1558+ ext4fs_free_node(currnode, currroot);
1559+ return 0;
1560+ }
1561+
1562+ oldnode = currnode;
1563+
1564+ /* Iterate over the directory. */
1565+ found = ext4fs_iterate_dir(currnode, name, &currnode, &type);
1566+ if (found == 0)
1567+ return 0;
1568+
1569+ if (found == -1)
1570+ break;
1571+
1572+ /* Read in the symlink and follow it. */
1573+ if (type == FILETYPE_SYMLINK) {
1574+ char *symlink;
1575+
1576+ /* Test if the symlink does not loop. */
1577+ if (++symlinknest == 8) {
1578+ ext4fs_free_node(currnode, currroot);
1579+ ext4fs_free_node(oldnode, currroot);
1580+ return 0;
1581+ }
1582+
1583+ symlink = ext4fs_read_symlink(currnode);
1584+ ext4fs_free_node(currnode, currroot);
1585+
1586+ if (!symlink) {
1587+ ext4fs_free_node(oldnode, currroot);
1588+ return 0;
1589+ }
1590+
1591+ debug("Got symlink >%s<\n", symlink);
1592+
1593+ if (symlink[0] == '/') {
1594+ ext4fs_free_node(oldnode, currroot);
1595+ oldnode = &ext4fs_root->diropen;
1596+ }
1597+
1598+ /* Lookup the node the symlink points to. */
1599+ status = ext4fs_find_file1(symlink, oldnode,
1600+ &currnode, &type);
1601+
1602+ free(symlink);
1603+
1604+ if (status == 0) {
1605+ ext4fs_free_node(oldnode, currroot);
1606+ return 0;
1607+ }
1608+ }
1609+
1610+ ext4fs_free_node(oldnode, currroot);
1611+
1612+ /* Found the node! */
1613+ if (!next || *next == '\0') {
1614+ *currfound = currnode;
1615+ *foundtype = type;
1616+ return 1;
1617+ }
1618+ name = next;
1619+ }
1620+ return -1;
1621+}
1622+
1623+int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
1624+ struct ext2fs_node **foundnode, int expecttype)
1625+{
1626+ int status;
1627+ int foundtype = FILETYPE_DIRECTORY;
1628+
1629+ symlinknest = 0;
1630+ if (!path)
1631+ return 0;
1632+
1633+ status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype);
1634+ if (status == 0)
1635+ return 0;
1636+
1637+ /* Check if the node that was found was of the expected type. */
1638+ if ((expecttype == FILETYPE_REG) && (foundtype != expecttype))
1639+ return 0;
1640+ else if ((expecttype == FILETYPE_DIRECTORY)
1641+ && (foundtype != expecttype))
1642+ return 0;
1643+
1644+ return 1;
1645+}
1646+
1647+int ext4fs_open(const char *filename)
1648+{
1649+ struct ext2fs_node *fdiro = NULL;
1650+ int status;
1651+ int len;
1652+
1653+ if (ext4fs_root == NULL)
1654+ return -1;
1655+
1656+ ext4fs_file = NULL;
1657+ status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro,
1658+ FILETYPE_REG);
1659+ if (status == 0)
1660+ goto fail;
1661+
1662+ if (!fdiro->inode_read) {
1663+ status = ext4fs_read_inode(fdiro->data, fdiro->ino,
1664+ &fdiro->inode);
1665+ if (status == 0)
1666+ goto fail;
1667+ }
1668+ len = __le32_to_cpu(fdiro->inode.size);
1669+ ext4fs_file = fdiro;
1670+
1671+ return len;
1672+ fail:
1673+ ext4fs_free_node(fdiro, &ext4fs_root->diropen);
1674+
1675+ return -1;
1676+}
1677+
1678+int ext4fs_mount(unsigned part_length)
1679+{
1680+ struct ext2_data *data;
1681+ int status;
1682+ struct ext_filesystem *fs = get_fs();
1683+ data = zalloc(sizeof(struct ext2_data));
1684+ if (!data)
1685+ return 0;
1686+
1687+ /* Read the superblock. */
1688+ status = ext4fs_devread(1 * 2, 0, sizeof(struct ext2_sblock),
1689+ (char *)&data->sblock);
1690+
1691+ if (status == 0)
1692+ goto fail;
1693+
1694+ /* Make sure this is an ext2 filesystem. */
1695+ if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC)
1696+ goto fail;
1697+
1698+ if (__le32_to_cpu(data->sblock.revision_level == 0))
1699+ fs->inodesz = 128;
1700+ else
1701+ fs->inodesz = __le16_to_cpu(data->sblock.inode_size);
1702+
1703+ debug("EXT2 rev %d, inode_size %d\n",
1704+ __le32_to_cpu(data->sblock.revision_level), fs->inodesz);
1705+
1706+ data->diropen.data = data;
1707+ data->diropen.ino = 2;
1708+ data->diropen.inode_read = 1;
1709+ data->inode = &data->diropen.inode;
1710+
1711+ status = ext4fs_read_inode(data, 2, data->inode);
1712+ if (status == 0)
1713+ goto fail;
1714+
1715+ ext4fs_root = data;
1716+
1717+ return 1;
1718+ fail:
1719+ printf("Failed to mount ext2 filesystem...\n");
1720+ free(data);
1721+ ext4fs_root = NULL;
1722+
1723+ return 0;
1724+}
1725diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h
1726new file mode 100644
1727index 0000000..18e6ad1
1728--- /dev/null
1729+++ b/fs/ext4/ext4_common.h
1730@@ -0,0 +1,63 @@
1731+/*
1732+ * (C) Copyright 2011 - 2012 Samsung Electronics
1733+ * EXT4 filesystem implementation in Uboot by
1734+ * Uma Shankar <uma.shankar@samsung.com>
1735+ * Manjunatha C Achar <a.manjunatha@samsung.com>
1736+ *
1737+ * ext4ls and ext4load : based on ext2 ls load support in Uboot.
1738+ *
1739+ * (C) Copyright 2004
1740+ * esd gmbh <www.esd-electronics.com>
1741+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
1742+ *
1743+ * based on code from grub2 fs/ext2.c and fs/fshelp.c by
1744+ * GRUB -- GRand Unified Bootloader
1745+ * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
1746+ *
1747+ * This program is free software; you can redistribute it and/or modify
1748+ * it under the terms of the GNU General Public License as published by
1749+ * the Free Software Foundation; either version 2 of the License, or
1750+ * (at your option) any later version.
1751+ *
1752+ * This program is distributed in the hope that it will be useful,
1753+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1754+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1755+ * GNU General Public License for more details.
1756+ *
1757+ * You should have received a copy of the GNU General Public License
1758+ * along with this program; if not, write to the Free Software
1759+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1760+ */
1761+
1762+#ifndef __EXT4_COMMON__
1763+#define __EXT4_COMMON__
1764+#include <ext_common.h>
1765+#include <ext4fs.h>
1766+#include <malloc.h>
1767+#include <asm/errno.h>
1768+
1769+#define YES 1
1770+#define NO 0
1771+#define TRUE 1
1772+#define FALSE 0
1773+#define RECOVER 1
1774+#define SCAN 0
1775+
1776+#define S_IFLNK 0120000 /* symbolic link */
1777+#define BLOCK_NO_ONE 1
1778+#define SUPERBLOCK_SECTOR 2
1779+#define SUPERBLOCK_SIZE 1024
1780+#define F_FILE 1
1781+
1782+#define zalloc(size) calloc(1, size)
1783+
1784+extern unsigned long part_offset;
1785+int ext4fs_read_inode(struct ext2_data *data, int ino,
1786+ struct ext2_inode *inode);
1787+int ext4fs_read_file(struct ext2fs_node *node, int pos,
1788+ unsigned int len, char *buf);
1789+int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
1790+ struct ext2fs_node **foundnode, int expecttype);
1791+int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
1792+ struct ext2fs_node **fnode, int *ftype);
1793+#endif
1794diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
1795new file mode 100644
1796index 0000000..7933769
1797--- /dev/null
1798+++ b/fs/ext4/ext4fs.c
1799@@ -0,0 +1,228 @@
1800+/*
1801+ * (C) Copyright 2011 - 2012 Samsung Electronics
1802+ * EXT4 filesystem implementation in Uboot by
1803+ * Uma Shankar <uma.shankar@samsung.com>
1804+ * Manjunatha C Achar <a.manjunatha@samsung.com>
1805+ *
1806+ * ext4ls and ext4load : Based on ext2 ls and load support in Uboot.
1807+ * Ext4 read optimization taken from Open-Moko
1808+ * Qi bootloader
1809+ *
1810+ * (C) Copyright 2004
1811+ * esd gmbh <www.esd-electronics.com>
1812+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
1813+ *
1814+ * based on code from grub2 fs/ext2.c and fs/fshelp.c by
1815+ * GRUB -- GRand Unified Bootloader
1816+ * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
1817+ *
1818+ * This program is free software; you can redistribute it and/or modify
1819+ * it under the terms of the GNU General Public License as published by
1820+ * the Free Software Foundation; either version 2 of the License, or
1821+ * (at your option) any later version.
1822+ *
1823+ * This program is distributed in the hope that it will be useful,
1824+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1825+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1826+ * GNU General Public License for more details.
1827+ *
1828+ * You should have received a copy of the GNU General Public License
1829+ * along with this program; if not, write to the Free Software
1830+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1831+ */
1832+
1833+#include <common.h>
1834+#include <malloc.h>
1835+#include <ext_common.h>
1836+#include <ext4fs.h>
1837+#include <linux/stat.h>
1838+#include <linux/time.h>
1839+#include <asm/byteorder.h>
1840+#include "ext4_common.h"
1841+
1842+int ext4fs_symlinknest;
1843+block_dev_desc_t *ext4_dev_desc;
1844+
1845+struct ext_filesystem *get_fs(void)
1846+{
1847+ if (ext4_dev_desc == NULL || ext4_dev_desc->priv == NULL)
1848+ printf("Invalid Input Arguments %s\n", __func__);
1849+
1850+ return ext4_dev_desc->priv;
1851+}
1852+
1853+int init_fs(block_dev_desc_t *dev_desc)
1854+{
1855+ struct ext_filesystem *fs;
1856+ if (dev_desc == NULL) {
1857+ printf("Invalid Input Arguments %s\n", __func__);
1858+ return -EINVAL;
1859+ }
1860+
1861+ fs = zalloc(sizeof(struct ext_filesystem));
1862+ if (fs == NULL) {
1863+ printf("malloc failed: %s\n", __func__);
1864+ return -ENOMEM;
1865+ }
1866+
1867+ fs->dev_desc = dev_desc;
1868+ dev_desc->priv = fs;
1869+
1870+ return 0;
1871+}
1872+
1873+void deinit_fs(block_dev_desc_t *dev_desc)
1874+{
1875+ if (dev_desc == NULL) {
1876+ printf("Invalid Input Arguments %s\n", __func__);
1877+ return;
1878+ }
1879+ free(dev_desc->priv);
1880+ dev_desc->priv = NULL;
1881+}
1882+
1883+void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot)
1884+{
1885+ if ((node != &ext4fs_root->diropen) && (node != currroot))
1886+ free(node);
1887+}
1888+
1889+/*
1890+ * Taken from openmoko-kernel mailing list: By Andy green
1891+ * Optimized read file API : collects and defers contiguous sector
1892+ * reads into one potentially more efficient larger sequential read action
1893+ */
1894+int ext4fs_read_file(struct ext2fs_node *node, int pos,
1895+ unsigned int len, char *buf)
1896+{
1897+ int i;
1898+ int blockcnt;
1899+ int log2blocksize = LOG2_EXT2_BLOCK_SIZE(node->data);
1900+ int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS);
1901+ unsigned int filesize = __le32_to_cpu(node->inode.size);
1902+ int previous_block_number = -1;
1903+ int delayed_start = 0;
1904+ int delayed_extent = 0;
1905+ int delayed_skipfirst = 0;
1906+ int delayed_next = 0;
1907+ char *delayed_buf = NULL;
1908+ short status;
1909+
1910+ /* Adjust len so it we can't read past the end of the file. */
1911+ if (len > filesize)
1912+ len = filesize;
1913+
1914+ blockcnt = ((len + pos) + blocksize - 1) / blocksize;
1915+
1916+ for (i = pos / blocksize; i < blockcnt; i++) {
1917+ int blknr;
1918+ int blockoff = pos % blocksize;
1919+ int blockend = blocksize;
1920+ int skipfirst = 0;
1921+ blknr = read_allocated_block(&(node->inode), i);
1922+ if (blknr < 0)
1923+ return -1;
1924+
1925+ blknr = blknr << log2blocksize;
1926+
1927+ /* Last block. */
1928+ if (i == blockcnt - 1) {
1929+ blockend = (len + pos) % blocksize;
1930+
1931+ /* The last portion is exactly blocksize. */
1932+ if (!blockend)
1933+ blockend = blocksize;
1934+ }
1935+
1936+ /* First block. */
1937+ if (i == pos / blocksize) {
1938+ skipfirst = blockoff;
1939+ blockend -= skipfirst;
1940+ }
1941+ if (blknr) {
1942+ int status;
1943+
1944+ if (previous_block_number != -1) {
1945+ if (delayed_next == blknr) {
1946+ delayed_extent += blockend;
1947+ delayed_next += blockend >> SECTOR_BITS;
1948+ } else { /* spill */
1949+ status = ext4fs_devread(delayed_start,
1950+ delayed_skipfirst,
1951+ delayed_extent,
1952+ delayed_buf);
1953+ if (status == 0)
1954+ return -1;
1955+ previous_block_number = blknr;
1956+ delayed_start = blknr;
1957+ delayed_extent = blockend;
1958+ delayed_skipfirst = skipfirst;
1959+ delayed_buf = buf;
1960+ delayed_next = blknr +
1961+ (blockend >> SECTOR_BITS);
1962+ }
1963+ } else {
1964+ previous_block_number = blknr;
1965+ delayed_start = blknr;
1966+ delayed_extent = blockend;
1967+ delayed_skipfirst = skipfirst;
1968+ delayed_buf = buf;
1969+ delayed_next = blknr +
1970+ (blockend >> SECTOR_BITS);
1971+ }
1972+ } else {
1973+ if (previous_block_number != -1) {
1974+ /* spill */
1975+ status = ext4fs_devread(delayed_start,
1976+ delayed_skipfirst,
1977+ delayed_extent,
1978+ delayed_buf);
1979+ if (status == 0)
1980+ return -1;
1981+ previous_block_number = -1;
1982+ }
1983+ memset(buf, 0, blocksize - skipfirst);
1984+ }
1985+ buf += blocksize - skipfirst;
1986+ }
1987+ if (previous_block_number != -1) {
1988+ /* spill */
1989+ status = ext4fs_devread(delayed_start,
1990+ delayed_skipfirst, delayed_extent,
1991+ delayed_buf);
1992+ if (status == 0)
1993+ return -1;
1994+ previous_block_number = -1;
1995+ }
1996+
1997+ return len;
1998+}
1999+
2000+int ext4fs_ls(const char *dirname)
2001+{
2002+ struct ext2fs_node *dirnode;
2003+ int status;
2004+
2005+ if (dirname == NULL)
2006+ return 0;
2007+
2008+ status = ext4fs_find_file(dirname, &ext4fs_root->diropen, &dirnode,
2009+ FILETYPE_DIRECTORY);
2010+ if (status != 1) {
2011+ printf("** Can not find directory. **\n");
2012+ return 1;
2013+ }
2014+
2015+ ext4fs_iterate_dir(dirnode, NULL, NULL, NULL);
2016+ ext4fs_free_node(dirnode, &ext4fs_root->diropen);
2017+
2018+ return 0;
2019+}
2020+
2021+int ext4fs_read(char *buf, unsigned len)
2022+{
2023+ if (ext4fs_root == NULL || ext4fs_file == NULL)
2024+ return 0;
2025+
2026+ return ext4fs_read_file(ext4fs_file, 0, len, buf);
2027+}
2028diff --git a/include/ext4fs.h b/include/ext4fs.h
2029new file mode 100644
2030index 0000000..58a6a1d
2031--- /dev/null
2032+++ b/include/ext4fs.h
2033@@ -0,0 +1,132 @@
2034+/*
2035+ * (C) Copyright 2011 - 2012 Samsung Electronics
2036+ * EXT4 filesystem implementation in Uboot by
2037+ * Uma Shankar <uma.shankar@samsung.com>
2038+ * Manjunatha C Achar <a.manjunatha@samsung.com>
2039+ *
2040+ * Ext4 Extent data structures are taken from original ext4 fs code
2041+ * as found in the linux kernel.
2042+ *
2043+ * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com
2044+ * Written by Alex Tomas <alex@clusterfs.com>
2045+ *
2046+ * This program is free software; you can redistribute it and/or modify
2047+ * it under the terms of the GNU General Public License version 2 as
2048+ * published by the Free Software Foundation.
2049+ *
2050+ * This program is distributed in the hope that it will be useful,
2051+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2052+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2053+ * GNU General Public License for more details.
2054+ *
2055+ * You should have received a copy of the GNU General Public License
2056+ * along with this program; if not, write to the Free Software
2057+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2058+ */
2059+
2060+#ifndef __EXT4__
2061+#define __EXT4__
2062+#include <ext_common.h>
2063+
2064+#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
2065+#define EXT4_EXT_MAGIC 0xf30a
2066+#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
2067+#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040
2068+#define EXT4_INDIRECT_BLOCKS 12
2069+
2070+#define EXT4_BG_INODE_UNINIT 0x0001
2071+#define EXT4_BG_BLOCK_UNINIT 0x0002
2072+#define EXT4_BG_INODE_ZEROED 0x0004
2073+
2074+/*
2075+ * ext4_inode has i_block array (60 bytes total).
2076+ * The first 12 bytes store ext4_extent_header;
2077+ * the remainder stores an array of ext4_extent.
2078+ */
2079+
2080+/*
2081+ * This is the extent on-disk structure.
2082+ * It's used at the bottom of the tree.
2083+ */
2084+struct ext4_extent {
2085+ __le32 ee_block; /* first logical block extent covers */
2086+ __le16 ee_len; /* number of blocks covered by extent */
2087+ __le16 ee_start_hi; /* high 16 bits of physical block */
2088+ __le32 ee_start_lo; /* low 32 bits of physical block */
2089+};
2090+
2091+/*
2092+ * This is index on-disk structure.
2093+ * It's used at all the levels except the bottom.
2094+ */
2095+struct ext4_extent_idx {
2096+ __le32 ei_block; /* index covers logical blocks from 'block' */
2097+ __le32 ei_leaf_lo; /* pointer to the physical block of the next *
2098+ * level. leaf or next index could be there */
2099+ __le16 ei_leaf_hi; /* high 16 bits of physical block */
2100+ __u16 ei_unused;
2101+};
2102+
2103+/* Each block (leaves and indexes), even inode-stored has header. */
2104+struct ext4_extent_header {
2105+ __le16 eh_magic; /* probably will support different formats */
2106+ __le16 eh_entries; /* number of valid entries */
2107+ __le16 eh_max; /* capacity of store in entries */
2108+ __le16 eh_depth; /* has tree real underlying blocks? */
2109+ __le32 eh_generation; /* generation of the tree */
2110+};
2111+
2112+struct ext_filesystem {
2113+ /* Total Sector of partition */
2114+ uint64_t total_sect;
2115+ /* Block size of partition */
2116+ uint32_t blksz;
2117+ /* Inode size of partition */
2118+ uint32_t inodesz;
2119+ /* Sectors per Block */
2120+ uint32_t sect_perblk;
2121+ /* Group Descriptor Block Number */
2122+ uint32_t gdtable_blkno;
2123+ /* Total block groups of partition */
2124+ uint32_t no_blkgrp;
2125+ /* No of blocks required for bgdtable */
2126+ uint32_t no_blk_pergdt;
2127+ /* Superblock */
2128+ struct ext2_sblock *sb;
2129+ /* Block group descritpor table */
2130+ struct ext2_block_group *gd;
2131+ char *gdtable;
2132+
2133+ /* Block Bitmap Related */
2134+ unsigned char **blk_bmaps;
2135+ long int curr_blkno;
2136+ uint16_t first_pass_bbmap;
2137+
2138+ /* Inode Bitmap Related */
2139+ unsigned char **inode_bmaps;
2140+ int curr_inode_no;
2141+ uint16_t first_pass_ibmap;
2142+
2143+ /* Journal Related */
2144+
2145+ /* Block Device Descriptor */
2146+ block_dev_desc_t *dev_desc;
2147+};
2148+
2149+extern block_dev_desc_t *ext4_dev_desc;
2150+extern struct ext2_data *ext4fs_root;
2151+extern struct ext2fs_node *ext4fs_file;
2152+
2153+struct ext_filesystem *get_fs(void);
2154+int init_fs(block_dev_desc_t *dev_desc);
2155+void deinit_fs(block_dev_desc_t *dev_desc);
2156+int ext4fs_open(const char *filename);
2157+int ext4fs_read(char *buf, unsigned len);
2158+int ext4fs_mount(unsigned part_length);
2159+void ext4fs_close(void);
2160+int ext4fs_ls(const char *dirname);
2161+void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot);
2162+int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf);
2163+int ext4fs_set_blk_dev(block_dev_desc_t *rbdd, int part);
2164+long int read_allocated_block(struct ext2_inode *inode, int fileblock);
2165+#endif
2166diff --git a/include/ext_common.h b/include/ext_common.h
2167new file mode 100644
2168index 0000000..5d48021
2169--- /dev/null
2170+++ b/include/ext_common.h
2171@@ -0,0 +1,188 @@
2172+/*
2173+ * (C) Copyright 2011 - 2012 Samsung Electronics
2174+ * EXT4 filesystem implementation in Uboot by
2175+ * Uma Shankar <uma.shankar@samsung.com>
2176+ * Manjunatha C Achar <a.manjunatha@samsung.com>
2177+ *
2178+ * Data structures and headers for ext4 support have been taken from
2179+ * ext2 ls load support in Uboot
2180+ *
2181+ * (C) Copyright 2004
2182+ * esd gmbh <www.esd-electronics.com>
2183+ * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
2184+ *
2185+ * based on code from grub2 fs/ext2.c and fs/fshelp.c by
2186+ * GRUB -- GRand Unified Bootloader
2187+ * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
2188+ *
2189+ * This program is free software; you can redistribute it and/or modify
2190+ * it under the terms of the GNU General Public License as published by
2191+ * the Free Software Foundation; either version 2 of the License, or
2192+ * (at your option) any later version.
2193+ *
2194+ * This program is distributed in the hope that it will be useful,
2195+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2196+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2197+ * GNU General Public License for more details.
2198+ *
2199+ * You should have received a copy of the GNU General Public License
2200+ * along with this program; if not, write to the Free Software
2201+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2202+ */
2203+
2204+#ifndef __EXT_COMMON__
2205+#define __EXT_COMMON__
2206+
2207+#define SECTOR_SIZE 0x200
2208+#define SECTOR_BITS 9
2209+
2210+/* Magic value used to identify an ext2 filesystem. */
2211+#define EXT2_MAGIC 0xEF53
2212+/* Amount of indirect blocks in an inode. */
2213+#define INDIRECT_BLOCKS 12
2214+/* Maximum lenght of a pathname. */
2215+#define EXT2_PATH_MAX 4096
2216+/* Maximum nesting of symlinks, used to prevent a loop. */
2217+#define EXT2_MAX_SYMLINKCNT 8
2218+
2219+/* Filetype used in directory entry. */
2220+#define FILETYPE_UNKNOWN 0
2221+#define FILETYPE_REG 1
2222+#define FILETYPE_DIRECTORY 2
2223+#define FILETYPE_SYMLINK 7
2224+
2225+/* Filetype information as used in inodes. */
2226+#define FILETYPE_INO_MASK 0170000
2227+#define FILETYPE_INO_REG 0100000
2228+#define FILETYPE_INO_DIRECTORY 0040000
2229+#define FILETYPE_INO_SYMLINK 0120000
2230+#define EXT2_ROOT_INO 2 /* Root inode */
2231+
2232+/* Bits used as offset in sector */
2233+#define DISK_SECTOR_BITS 9
2234+/* The size of an ext2 block in bytes. */
2235+#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
2236+
2237+/* Log2 size of ext2 block in 512 blocks. */
2238+#define LOG2_EXT2_BLOCK_SIZE(data) (__le32_to_cpu \
2239+ (data->sblock.log2_block_size) + 1)
2240+
2241+/* Log2 size of ext2 block in bytes. */
2242+#define LOG2_BLOCK_SIZE(data) (__le32_to_cpu \
2243+ (data->sblock.log2_block_size) + 10)
2244+#define INODE_SIZE_FILESYSTEM(data) (__le32_to_cpu \
2245+ (data->sblock.inode_size))
2246+
2247+#define EXT2_FT_DIR 2
2248+#define SUCCESS 1
2249+
2250+/* Macro-instructions used to manage several block sizes */
2251+#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */
2252+#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */
2253+#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE)
2254+#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE)
2255+
2256+/* The ext2 superblock. */
2257+struct ext2_sblock {
2258+ uint32_t total_inodes;
2259+ uint32_t total_blocks;
2260+ uint32_t reserved_blocks;
2261+ uint32_t free_blocks;
2262+ uint32_t free_inodes;
2263+ uint32_t first_data_block;
2264+ uint32_t log2_block_size;
2265+ uint32_t log2_fragment_size;
2266+ uint32_t blocks_per_group;
2267+ uint32_t fragments_per_group;
2268+ uint32_t inodes_per_group;
2269+ uint32_t mtime;
2270+ uint32_t utime;
2271+ uint16_t mnt_count;
2272+ uint16_t max_mnt_count;
2273+ uint16_t magic;
2274+ uint16_t fs_state;
2275+ uint16_t error_handling;
2276+ uint16_t minor_revision_level;
2277+ uint32_t lastcheck;
2278+ uint32_t checkinterval;
2279+ uint32_t creator_os;
2280+ uint32_t revision_level;
2281+ uint16_t uid_reserved;
2282+ uint16_t gid_reserved;
2283+ uint32_t first_inode;
2284+ uint16_t inode_size;
2285+ uint16_t block_group_number;
2286+ uint32_t feature_compatibility;
2287+ uint32_t feature_incompat;
2288+ uint32_t feature_ro_compat;
2289+ uint32_t unique_id[4];
2290+ char volume_name[16];
2291+ char last_mounted_on[64];
2292+ uint32_t compression_info;
2293+};
2294+
2295+struct ext2_block_group {
2296+ __u32 block_id; /* Blocks bitmap block */
2297+ __u32 inode_id; /* Inodes bitmap block */
2298+ __u32 inode_table_id; /* Inodes table block */
2299+ __u16 free_blocks; /* Free blocks count */
2300+ __u16 free_inodes; /* Free inodes count */
2301+ __u16 used_dir_cnt; /* Directories count */
2302+ __u16 bg_flags;
2303+ __u32 bg_reserved[2];
2304+ __u16 bg_itable_unused; /* Unused inodes count */
2305+ __u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/
2306+};
2307+
2308+/* The ext2 inode. */
2309+struct ext2_inode {
2310+ uint16_t mode;
2311+ uint16_t uid;
2312+ uint32_t size;
2313+ uint32_t atime;
2314+ uint32_t ctime;
2315+ uint32_t mtime;
2316+ uint32_t dtime;
2317+ uint16_t gid;
2318+ uint16_t nlinks;
2319+ uint32_t blockcnt; /* Blocks of 512 bytes!! */
2320+ uint32_t flags;
2321+ uint32_t osd1;
2322+ union {
2323+ struct datablocks {
2324+ uint32_t dir_blocks[INDIRECT_BLOCKS];
2325+ uint32_t indir_block;
2326+ uint32_t double_indir_block;
2327+ uint32_t triple_indir_block;
2328+ } blocks;
2329+ char symlink[60];
2330+ } b;
2331+ uint32_t version;
2332+ uint32_t acl;
2333+ uint32_t dir_acl;
2334+ uint32_t fragment_addr;
2335+ uint32_t osd2[3];
2336+};
2337+
2338+/* The header of an ext2 directory entry. */
2339+struct ext2_dirent {
2340+ uint32_t inode;
2341+ uint16_t direntlen;
2342+ uint8_t namelen;
2343+ uint8_t filetype;
2344+};
2345+
2346+struct ext2fs_node {
2347+ struct ext2_data *data;
2348+ struct ext2_inode inode;
2349+ int ino;
2350+ int inode_read;
2351+};
2352+
2353+/* Information about a "mounted" ext2 filesystem. */
2354+struct ext2_data {
2355+ struct ext2_sblock sblock;
2356+ struct ext2_inode *inode;
2357+ struct ext2fs_node diropen;
2358+};
2359+#endif
2360--
23611.7.10
2362