2 * ext2 filesystem for onenand device.
4 * Copyright(C) 2009 Samsung Electronics
5 * InKi Dae <inki.dae@samsung.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 #include <linux/types.h>
31 #include <asm/global_data.h>
33 #include <onenand_ext2.h>
35 #define IMAGE_BASE (0x380000)
36 #define IMAGE_SIZE (8 * 1024 * 1024)
37 #define ONENAND_READ_SIZE (4 * 1024)
38 #define FRAMEBUFFER_SIZE (480 * 800 * 4)
40 #define EXT2_BLOCK_UNIT (1024)
41 #define DATA_BLOCK_UNIT (512)
42 #define INODE_TABLE_ENTRY_SIZE (128)
44 extern vidinfo_t panel_info;
45 extern int onenand_read(ulong off, char *buf, unsigned int *out_size);
47 static char *ext2_buf = NULL;
49 /* it indicates block size of ext2 filesystem formatted. */
50 unsigned int block_size_of_fs = 0;
52 unsigned int inode_block_size = 0;
54 struct ext2_dirent g_dirent;
56 /* set system memory region stored with onenand region. */
57 static unsigned int allocate_ext2_buf(void)
60 unsigned int fb_size = 0;
62 addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE -1);
63 fb_size = panel_info.vl_col * panel_info.vl_row *
64 panel_info.vl_bpix / 8;
65 addr -= IMAGE_SIZE + fb_size;
70 /* load onenand region into system memory. */
71 static void onenand_read_to_ram(void)
73 unsigned int i, out_size;
76 ext2_buf = (char *) allocate_ext2_buf();
77 buf = malloc(ONENAND_READ_SIZE);
79 for (i = 0; i < IMAGE_SIZE ; i+=ONENAND_READ_SIZE) {
80 onenand_read(IMAGE_BASE + i, buf, &out_size);
81 memcpy(ext2_buf + i, buf, ONENAND_READ_SIZE);
88 static char *get_sblock(struct ext2_sblock *sblock)
90 char *buf_sblock = NULL;
92 if (ext2_buf == NULL) {
93 printf("ext2_buf is NULL.\n");
97 buf_sblock = ext2_buf + EXT2_BLOCK_UNIT;
99 /* get super block. */
100 memcpy(sblock, buf_sblock, sizeof(struct ext2_sblock));
102 printf("total_inodes = %d, block_size = %d\n", sblock->total_inodes,
103 sblock->log2_block_size);
108 static char *get_group_dec(struct ext2_block_group *group)
110 char *buf_group = NULL;
112 if (ext2_buf == NULL) {
113 printf("ext2_buf is NULL.\n");
117 /* get group descriptor. */
118 buf_group = ext2_buf + EXT2_BLOCK_UNIT * 2;
119 memcpy(group, buf_group, sizeof(struct ext2_block_group));
121 printf("block_id = %d, inode_id = %d, inode_table_id = %d\n",
122 group->block_id, group->inode_id, group->inode_table_id);
127 static char *get_root_inode_entry(struct ext2_inode *inode,
128 struct ext2_block_group *group)
130 char *buf_root_dir = NULL;
131 unsigned int inode_table_location;
133 if (ext2_buf == NULL) {
134 printf("ext2_buf is NULL.\n");
139 printf("group is NULL.\n");
143 /* get location of inode table. */
144 inode_table_location = group->inode_table_id * EXT2_BLOCK_UNIT;
146 printf("inode table location = %d\n", inode_table_location);
149 * get inode entry of root directory.
151 * inode table has 128byte unit per entry and
152 * root inode is placed in second entry.
154 buf_root_dir = ext2_buf + inode_table_location + INODE_TABLE_ENTRY_SIZE;
155 memcpy(inode, buf_root_dir, sizeof(struct ext2_inode));
157 /* get inode block size and used to find the end of directory entry. */
158 inode_block_size = inode->blockcnt * DATA_BLOCK_UNIT;
160 printf("dir_blocks = %x, size = %d, blockcnt = %d\n", inode->b.blocks.dir_blocks[0],
161 inode->size, inode->blockcnt);
166 static char *get_root_dir_entry(struct ext2_dirent *dirent, struct ext2_inode *inode)
168 char *buf_root_dir = NULL;
170 if (ext2_buf == NULL) {
171 printf("ext2_buf is NULL.\n");
176 printf("inode is NULL.\n");
180 /* get block number stored with data of inode. */
181 buf_root_dir = ext2_buf + inode->b.blocks.dir_blocks[0] * EXT2_BLOCK_UNIT;
182 memcpy(dirent, buf_root_dir, sizeof(struct ext2_dirent));
184 printf("first entry name of root directory is name = %s\n",
190 /* initialize ext2 filesystem and return pointer of root directory entry. */
191 static char *mount_ext2fs(void)
193 struct ext2_sblock sblock;
194 struct ext2_block_group group;
195 struct ext2_inode inode;
196 struct ext2_dirent dirent;
198 unsigned int need_block = 0;
201 buf = get_sblock(&sblock);
203 printf("sblock is NULL.\n");
207 /* in case that log2_block_size is 0, block_size is 1024 and 2048 for 1. */
208 block_size_of_fs = (sblock.log2_block_size + 1) * EXT2_BLOCK_UNIT;
209 printf("block size of filesystem = %d\n", block_size_of_fs);
211 /* get block size for inode table. */
212 need_block = sblock.total_inodes * INODE_TABLE_ENTRY_SIZE /
215 printf("need_block for inode table = %d\n", need_block);
217 buf = get_group_dec(&group);
219 printf("group_dec is NULL.\n");
223 buf = get_root_inode_entry(&inode, &group);
225 printf("root_inode_entry is NULL.\n");
229 buf = get_root_dir_entry(&dirent, &inode);
231 printf("root_dir_entry is NULL.\n");
237 /* get data block. */
238 //block_addr = inode_table_location + EXT2_BLOCK_UNIT * need_block;
239 //printf("data block location = %d\n", block_addr);
240 //buf_data_block = ext2_buf + block_addr;
243 static int get_dir_entry(unsigned int *inode, struct ext2_dirent *dirent)
245 static unsigned int tmp_pt = NULL;
246 static unsigned first = 1;
253 if ((*inode - tmp_pt) >= inode_block_size)
256 memcpy(dirent, (char *) *inode, sizeof(struct ext2_dirent));
257 *inode += dirent->direntlen;
262 static void ls_ext2(unsigned int inode)
264 struct ext2_dirent dirent;
267 ret = get_dir_entry(&inode, &dirent);
269 printf("failed to get directory entry.\n");
273 printf("inode = %d, name = %s\n", dirent.inode, dirent.name);
276 ret = get_dir_entry(&inode, &dirent);
277 printf("inode = %d, name = %s\n", dirent.inode, dirent.name);
281 void test_onenand_ext2(void)
285 onenand_read_to_ram();
287 inode = (unsigned int) mount_ext2fs();