diff options
author | Koen Kooi <koen@dominion.thruhere.net> | 2012-05-01 21:06:52 +0200 |
---|---|---|
committer | Denys Dmytriyenko <denys@ti.com> | 2012-05-03 19:09:25 -0400 |
commit | 07913cca6cfd7f35a9bb5d6b2cca41c6b5f07ec3 (patch) | |
tree | 5a0d8be401a0c7c7eab66ef19081f02e77d6c85d /recipes-bsp | |
parent | f0e2305c7e1395066b4303b4a891bfb2a066602b (diff) | |
download | meta-ti-07913cca6cfd7f35a9bb5d6b2cca41c6b5f07ec3.tar.gz |
u-boot 2011.12: switch beagleboard to ext4 to match beaglebone
Also add patch to increase ext2 read speed.
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
Acked-by: Tom Rini <trini@ti.com>
Signed-off-by: Denys Dmytriyenko <denys@ti.com>
Diffstat (limited to 'recipes-bsp')
4 files changed, 2483 insertions, 1 deletions
diff --git a/recipes-bsp/u-boot/u-boot/2011.12/0011-ext2load-increase-read-speed.patch b/recipes-bsp/u-boot/u-boot/2011.12/0011-ext2load-increase-read-speed.patch new file mode 100644 index 00000000..2adb1db9 --- /dev/null +++ b/recipes-bsp/u-boot/u-boot/2011.12/0011-ext2load-increase-read-speed.patch | |||
@@ -0,0 +1,74 @@ | |||
1 | From e4181abd88a932bc38054af05d39a633656caefa Mon Sep 17 00:00:00 2001 | ||
2 | From: "u-boot@lakedaemon.net" <u-boot@lakedaemon.net> | ||
3 | Date: Wed, 28 Mar 2012 04:37:11 +0000 | ||
4 | Subject: [PATCH 11/13] ext2load: increase read speed | ||
5 | |||
6 | This patch dramatically drops the amount of time u-boot needs to read a | ||
7 | file from an ext2 partition. On a typical 2 to 5 MB file (kernels and | ||
8 | initrds) it goes from tens of seconds to a couple seconds. | ||
9 | |||
10 | All we are doing here is grouping contiguous blocks into one read. | ||
11 | |||
12 | Boot tested on Globalscale Technologies Dreamplug (Kirkwood ARM SoC) | ||
13 | with three different files. sha1sums were calculated in Linux | ||
14 | userspace, and then confirmed after ext2load. | ||
15 | |||
16 | Signed-off-by: Jason Cooper <u-boot@lakedaemon.net> | ||
17 | --- | ||
18 | fs/ext2/ext2fs.c | 26 ++++++++++++++++++++++++-- | ||
19 | 1 file changed, 24 insertions(+), 2 deletions(-) | ||
20 | |||
21 | diff --git a/fs/ext2/ext2fs.c b/fs/ext2/ext2fs.c | ||
22 | index e119e13..8531db5 100644 | ||
23 | --- a/fs/ext2/ext2fs.c | ||
24 | +++ b/fs/ext2/ext2fs.c | ||
25 | @@ -414,7 +414,6 @@ int ext2fs_read_file | ||
26 | if (blknr < 0) { | ||
27 | return (-1); | ||
28 | } | ||
29 | - blknr = blknr << log2blocksize; | ||
30 | |||
31 | /* Last block. */ | ||
32 | if (i == blockcnt - 1) { | ||
33 | @@ -432,6 +431,29 @@ int ext2fs_read_file | ||
34 | blockend -= skipfirst; | ||
35 | } | ||
36 | |||
37 | + /* grab middle blocks in one go */ | ||
38 | + if (i != pos / blocksize && i != blockcnt - 1 && blockcnt > 3) { | ||
39 | + int oldblk = blknr; | ||
40 | + int blocknxt; | ||
41 | + while (i < blockcnt - 1) { | ||
42 | + blocknxt = ext2fs_read_block(node, i + 1); | ||
43 | + if (blocknxt == (oldblk + 1)) { | ||
44 | + oldblk = blocknxt; | ||
45 | + i++; | ||
46 | + } else { | ||
47 | + blocknxt = ext2fs_read_block(node, i); | ||
48 | + break; | ||
49 | + } | ||
50 | + } | ||
51 | + | ||
52 | + if (oldblk == blknr) | ||
53 | + blockend = blocksize; | ||
54 | + else | ||
55 | + blockend = (1 + blocknxt - blknr) * blocksize; | ||
56 | + } | ||
57 | + | ||
58 | + blknr = blknr << log2blocksize; | ||
59 | + | ||
60 | /* If the block number is 0 this block is not stored on disk but | ||
61 | is zero filled instead. */ | ||
62 | if (blknr) { | ||
63 | @@ -444,7 +466,7 @@ int ext2fs_read_file | ||
64 | } else { | ||
65 | memset (buf, 0, blocksize - skipfirst); | ||
66 | } | ||
67 | - buf += blocksize - skipfirst; | ||
68 | + buf += blockend - skipfirst; | ||
69 | } | ||
70 | return (len); | ||
71 | } | ||
72 | -- | ||
73 | 1.7.10 | ||
74 | |||
diff --git a/recipes-bsp/u-boot/u-boot/2011.12/0012-ext4fs-ls-load-support.patch b/recipes-bsp/u-boot/u-boot/2011.12/0012-ext4fs-ls-load-support.patch new file mode 100644 index 00000000..c16a2d8c --- /dev/null +++ b/recipes-bsp/u-boot/u-boot/2011.12/0012-ext4fs-ls-load-support.patch | |||
@@ -0,0 +1,2362 @@ | |||
1 | From 04a6b1d60a4fec316992b11837d6347117cbb670 Mon Sep 17 00:00:00 2001 | ||
2 | From: "uma.shankar" <uma.shankar@samsung.com> | ||
3 | Date: Mon, 9 Jan 2012 07:54:50 +0000 | ||
4 | Subject: [PATCH 12/13] ext4fs ls load support | ||
5 | |||
6 | Signed-off-by: Uma Shankar <uma.shankar@samsung.com> | ||
7 | Signed-off-by: Manjunatha C Achar <a.manjunatha@samsung.com> | ||
8 | Signed-off-by: Iqbal Shareef <iqbal.ams@samsung.com> | ||
9 | Signed-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 | |||
34 | diff --git a/Makefile b/Makefile | ||
35 | index 0438f1e..51cc8c8 100644 | ||
36 | --- a/Makefile | ||
37 | +++ b/Makefile | ||
38 | @@ -235,7 +235,7 @@ LIBS += dts/libdts.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 | ||
47 | diff --git a/common/Makefile b/common/Makefile | ||
48 | index 2d9ae8c..f5243f6 100644 | ||
49 | --- a/common/Makefile | ||
50 | +++ b/common/Makefile | ||
51 | @@ -86,6 +86,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 | ||
59 | diff --git a/common/cmd_ext4.c b/common/cmd_ext4.c | ||
60 | new file mode 100644 | ||
61 | index 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"); | ||
331 | diff --git a/fs/Makefile b/fs/Makefile | ||
332 | index 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 | ||
343 | diff --git a/fs/ext2/dev.c b/fs/ext2/dev.c | ||
344 | index 874e211..315ff53 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; | ||
355 | diff --git a/fs/ext2/ext2fs.c b/fs/ext2/ext2fs.c | ||
356 | index 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; | ||
636 | diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile | ||
637 | new file mode 100644 | ||
638 | index 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 | +######################################################################### | ||
693 | diff --git a/fs/ext4/dev.c b/fs/ext4/dev.c | ||
694 | new file mode 100644 | ||
695 | index 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 | +} | ||
844 | diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c | ||
845 | new file mode 100644 | ||
846 | index 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 | +} | ||
1725 | diff --git a/fs/ext4/ext4_common.h b/fs/ext4/ext4_common.h | ||
1726 | new file mode 100644 | ||
1727 | index 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 | ||
1794 | diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c | ||
1795 | new file mode 100644 | ||
1796 | index 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 | +} | ||
2028 | diff --git a/include/ext4fs.h b/include/ext4fs.h | ||
2029 | new file mode 100644 | ||
2030 | index 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 | ||
2166 | diff --git a/include/ext_common.h b/include/ext_common.h | ||
2167 | new file mode 100644 | ||
2168 | index 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 | -- | ||
2361 | 1.7.10 | ||
2362 | |||
diff --git a/recipes-bsp/u-boot/u-boot/2011.12/0013-beagleboard-switch-mmcroots-to-ext4.patch b/recipes-bsp/u-boot/u-boot/2011.12/0013-beagleboard-switch-mmcroots-to-ext4.patch new file mode 100644 index 00000000..c80dfc2b --- /dev/null +++ b/recipes-bsp/u-boot/u-boot/2011.12/0013-beagleboard-switch-mmcroots-to-ext4.patch | |||
@@ -0,0 +1,43 @@ | |||
1 | From f5b19d6609a540a9eafa60dad902e7416df57771 Mon Sep 17 00:00:00 2001 | ||
2 | From: Koen Kooi <koen@dominion.thruhere.net> | ||
3 | Date: Mon, 30 Apr 2012 11:10:07 +0200 | ||
4 | Subject: [PATCH 13/13] beagleboard: switch mmcroots to ext4 | ||
5 | |||
6 | Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> | ||
7 | --- | ||
8 | include/configs/omap3_beagle.h | 5 +++-- | ||
9 | 1 file changed, 3 insertions(+), 2 deletions(-) | ||
10 | |||
11 | diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h | ||
12 | index 65ab8ee..3157d47 100644 | ||
13 | --- a/include/configs/omap3_beagle.h | ||
14 | +++ b/include/configs/omap3_beagle.h | ||
15 | @@ -140,6 +140,7 @@ | ||
16 | |||
17 | #define CONFIG_CMD_CACHE | ||
18 | #define CONFIG_CMD_EXT2 /* EXT2 Support */ | ||
19 | +#define CONFIG_CMD_EXT4 | ||
20 | #define CONFIG_CMD_FAT /* FAT support */ | ||
21 | #define CONFIG_CMD_JFFS2 /* JFFS2 Support */ | ||
22 | #define CONFIG_CMD_MTDPARTS /* Enable MTD parts commands */ | ||
23 | @@ -222,7 +223,7 @@ | ||
24 | "defaultdisplay=dvi\0" \ | ||
25 | "mmcdev=0\0" \ | ||
26 | "mmcroot=/dev/mmcblk0p2 ro\0" \ | ||
27 | - "mmcrootfstype=ext3 rootwait\0" \ | ||
28 | + "mmcrootfstype=ext4 rootwait\0" \ | ||
29 | "nandroot=ubi0:rootfs ubi.mtd=4\0" \ | ||
30 | "nandrootfstype=ubifs\0" \ | ||
31 | "ramroot=/dev/ram0 rw ramdisk_size=65536 initrd=0x81000000,64M\0" \ | ||
32 | @@ -265,7 +266,7 @@ | ||
33 | "rootfstype=${ramrootfstype}\0" \ | ||
34 | "loadramdisk=fatload mmc ${mmcdev} ${rdaddr} ramdisk.gz\0" \ | ||
35 | "loaduimagefat=fatload mmc ${mmcdev} ${loadaddr} uImage\0" \ | ||
36 | - "loaduimage=ext2load mmc ${mmcdev}:2 ${loadaddr} /boot/uImage\0" \ | ||
37 | + "loaduimage=ext4load mmc ${mmcdev}:2 ${loadaddr} /boot/uImage\0" \ | ||
38 | "mmcboot=echo Booting from mmc ...; " \ | ||
39 | "run mmcargs; " \ | ||
40 | "bootm ${loadaddr}\0" \ | ||
41 | -- | ||
42 | 1.7.10 | ||
43 | |||
diff --git a/recipes-bsp/u-boot/u-boot_2011.12.bb b/recipes-bsp/u-boot/u-boot_2011.12.bb index 9616a053..45c64a68 100644 --- a/recipes-bsp/u-boot/u-boot_2011.12.bb +++ b/recipes-bsp/u-boot/u-boot_2011.12.bb | |||
@@ -6,7 +6,7 @@ UBOOT_IMAGE = "u-boot-${MACHINE}-${PV}-${PR}.img" | |||
6 | UBOOT_SYMLINK = "u-boot-${MACHINE}.img" | 6 | UBOOT_SYMLINK = "u-boot-${MACHINE}.img" |
7 | 7 | ||
8 | PV = "2011.12" | 8 | PV = "2011.12" |
9 | PR = "r7" | 9 | PR = "r8" |
10 | 10 | ||
11 | # No patches for other machines yet | 11 | # No patches for other machines yet |
12 | COMPATIBLE_MACHINE = "(beagleboard|pandaboard|hawkboard|am3517-evm|am37x-evm|omap3evm)" | 12 | COMPATIBLE_MACHINE = "(beagleboard|pandaboard|hawkboard|am3517-evm|am37x-evm|omap3evm)" |
@@ -30,6 +30,9 @@ SRC_URI = "git://www.denx.de/git/u-boot.git;protocol=git \ | |||
30 | ${CACHEFIX} \ | 30 | ${CACHEFIX} \ |
31 | file://2011.12/0009-Beagleboard-Correct-memory-size-on-rev-C4.patch \ | 31 | file://2011.12/0009-Beagleboard-Correct-memory-size-on-rev-C4.patch \ |
32 | file://2011.12/0010-OMAP3-Correct-get_sdr_cs_offset-mask.patch \ | 32 | file://2011.12/0010-OMAP3-Correct-get_sdr_cs_offset-mask.patch \ |
33 | file://2011.12/0011-ext2load-increase-read-speed.patch \ | ||
34 | file://2011.12/0012-ext4fs-ls-load-support.patch \ | ||
35 | file://2011.12/0013-beagleboard-switch-mmcroots-to-ext4.patch \ | ||
33 | ${FWENV} \ | 36 | ${FWENV} \ |
34 | " | 37 | " |
35 | 38 | ||