xref: /rk3399_rockchip-uboot/fs/fs.c (revision 045fa1e1142552799ad3203e9e0bc22a11e866ea)
1 /*
2  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <config.h>
18 #include <common.h>
19 #include <part.h>
20 #include <ext4fs.h>
21 #include <fat.h>
22 #include <fs.h>
23 
24 static block_dev_desc_t *fs_dev_desc;
25 static disk_partition_t fs_partition;
26 static int fs_type = FS_TYPE_ANY;
27 
28 static inline int fs_ls_unsupported(const char *dirname)
29 {
30 	printf("** Unrecognized filesystem type **\n");
31 	return -1;
32 }
33 
34 static inline int fs_read_unsupported(const char *filename, ulong addr,
35 				      int offset, int len)
36 {
37 	printf("** Unrecognized filesystem type **\n");
38 	return -1;
39 }
40 
41 #ifdef CONFIG_FS_FAT
42 static int fs_probe_fat(void)
43 {
44 	return fat_set_blk_dev(fs_dev_desc, &fs_partition);
45 }
46 
47 static void fs_close_fat(void)
48 {
49 }
50 
51 #define fs_ls_fat file_fat_ls
52 
53 static int fs_read_fat(const char *filename, ulong addr, int offset, int len)
54 {
55 	int len_read;
56 
57 	len_read = file_fat_read_at(filename, offset,
58 				    (unsigned char *)addr, len);
59 	if (len_read == -1) {
60 		printf("** Unable to read file %s **\n", filename);
61 		return -1;
62 	}
63 
64 	return len_read;
65 }
66 #else
67 static inline int fs_probe_fat(void)
68 {
69 	return -1;
70 }
71 
72 static inline void fs_close_fat(void)
73 {
74 }
75 
76 #define fs_ls_fat fs_ls_unsupported
77 #define fs_read_fat fs_read_unsupported
78 #endif
79 
80 #ifdef CONFIG_FS_EXT4
81 static int fs_probe_ext(void)
82 {
83 	ext4fs_set_blk_dev(fs_dev_desc, &fs_partition);
84 
85 	if (!ext4fs_mount(fs_partition.size)) {
86 		ext4fs_close();
87 		return -1;
88 	}
89 
90 	return 0;
91 }
92 
93 static void fs_close_ext(void)
94 {
95 	ext4fs_close();
96 }
97 
98 #define fs_ls_ext ext4fs_ls
99 
100 static int fs_read_ext(const char *filename, ulong addr, int offset, int len)
101 {
102 	int file_len;
103 	int len_read;
104 
105 	if (offset != 0) {
106 		printf("** Cannot support non-zero offset **\n");
107 		return -1;
108 	}
109 
110 	file_len = ext4fs_open(filename);
111 	if (file_len < 0) {
112 		printf("** File not found %s **\n", filename);
113 		ext4fs_close();
114 		return -1;
115 	}
116 
117 	if (len == 0)
118 		len = file_len;
119 
120 	len_read = ext4fs_read((char *)addr, len);
121 	ext4fs_close();
122 
123 	if (len_read != len) {
124 		printf("** Unable to read file %s **\n", filename);
125 		return -1;
126 	}
127 
128 	return len_read;
129 }
130 #else
131 static inline int fs_probe_ext(void)
132 {
133 	return -1;
134 }
135 
136 static inline void fs_close_ext(void)
137 {
138 }
139 
140 #define fs_ls_ext fs_ls_unsupported
141 #define fs_read_ext fs_read_unsupported
142 #endif
143 
144 static const struct {
145 	int fstype;
146 	int (*probe)(void);
147 } fstypes[] = {
148 	{
149 		.fstype = FS_TYPE_FAT,
150 		.probe = fs_probe_fat,
151 	},
152 	{
153 		.fstype = FS_TYPE_EXT,
154 		.probe = fs_probe_ext,
155 	},
156 };
157 
158 int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
159 {
160 	int part, i;
161 
162 	part = get_device_and_partition(ifname, dev_part_str, &fs_dev_desc,
163 					&fs_partition, 1);
164 	if (part < 0)
165 		return -1;
166 
167 	for (i = 0; i < ARRAY_SIZE(fstypes); i++) {
168 		if ((fstype != FS_TYPE_ANY) && (fstype != fstypes[i].fstype))
169 			continue;
170 
171 		if (!fstypes[i].probe()) {
172 			fs_type = fstypes[i].fstype;
173 			return 0;
174 		}
175 	}
176 
177 	printf("** Unrecognized filesystem type **\n");
178 	return -1;
179 }
180 
181 static void fs_close(void)
182 {
183 	switch (fs_type) {
184 	case FS_TYPE_FAT:
185 		fs_close_fat();
186 		break;
187 	case FS_TYPE_EXT:
188 		fs_close_ext();
189 		break;
190 	default:
191 		break;
192 	}
193 
194 	fs_type = FS_TYPE_ANY;
195 }
196 
197 int fs_ls(const char *dirname)
198 {
199 	int ret;
200 
201 	switch (fs_type) {
202 	case FS_TYPE_FAT:
203 		ret = fs_ls_fat(dirname);
204 		break;
205 	case FS_TYPE_EXT:
206 		ret = fs_ls_ext(dirname);
207 		break;
208 	default:
209 		ret = fs_ls_unsupported(dirname);
210 		break;
211 	}
212 
213 	fs_close();
214 
215 	return ret;
216 }
217 
218 int fs_read(const char *filename, ulong addr, int offset, int len)
219 {
220 	int ret;
221 
222 	switch (fs_type) {
223 	case FS_TYPE_FAT:
224 		ret = fs_read_fat(filename, addr, offset, len);
225 		break;
226 	case FS_TYPE_EXT:
227 		ret = fs_read_ext(filename, addr, offset, len);
228 		break;
229 	default:
230 		ret = fs_read_unsupported(filename, addr, offset, len);
231 		break;
232 	}
233 
234 	fs_close();
235 
236 	return ret;
237 }
238 
239 int do_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
240 		int fstype)
241 {
242 	unsigned long addr;
243 	const char *addr_str;
244 	const char *filename;
245 	unsigned long bytes;
246 	unsigned long pos;
247 	int len_read;
248 	char buf[12];
249 
250 	if (argc < 5)
251 		return CMD_RET_USAGE;
252 
253 	if (fs_set_blk_dev(argv[1], argv[2], fstype))
254 		return 1;
255 
256 	if (argc >= 4) {
257 		addr = simple_strtoul(argv[3], NULL, 0);
258 	} else {
259 		addr_str = getenv("loadaddr");
260 		if (addr_str != NULL)
261 			addr = simple_strtoul(addr_str, NULL, 16);
262 		else
263 			addr = CONFIG_SYS_LOAD_ADDR;
264 	}
265 	if (argc >= 5) {
266 		filename = argv[4];
267 	} else {
268 		filename = getenv("bootfile");
269 		if (!filename) {
270 			puts("** No boot file defined **\n");
271 			return 1;
272 		}
273 	}
274 	if (argc >= 6)
275 		bytes = simple_strtoul(argv[5], NULL, 0);
276 	else
277 		bytes = 0;
278 	if (argc >= 7)
279 		pos = simple_strtoul(argv[6], NULL, 0);
280 	else
281 		pos = 0;
282 
283 	len_read = fs_read(filename, addr, pos, bytes);
284 	if (len_read <= 0)
285 		return 1;
286 
287 	printf("%d bytes read\n", len_read);
288 
289 	sprintf(buf, "0x%x", len_read);
290 	setenv("filesize", buf);
291 
292 	return 0;
293 }
294 
295 int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
296 	int fstype)
297 {
298 	if (argc < 2)
299 		return CMD_RET_USAGE;
300 
301 	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
302 		return 1;
303 
304 	if (fs_ls(argc == 4 ? argv[3] : "/"))
305 		return 1;
306 
307 	return 0;
308 }
309