diff options
author | Stephen Warren | 2012-10-22 01:43:51 -0500 |
---|---|---|
committer | Tom Rini | 2012-10-29 16:21:20 -0500 |
commit | 045fa1e1142552799ad3203e9e0bc22a11e866ea (patch) | |
tree | 038b783c8efac14c0caffa128f37b77a48c9f407 /fs | |
parent | 03e2ecf6b83e43803f7eed9547d0973b7eb1c8fc (diff) | |
download | u-boot-045fa1e1142552799ad3203e9e0bc22a11e866ea.tar.gz u-boot-045fa1e1142552799ad3203e9e0bc22a11e866ea.tar.xz u-boot-045fa1e1142552799ad3203e9e0bc22a11e866ea.zip |
fs: add filesystem switch libary, implement ls and fsload commands
Implement "ls" and "fsload" commands that act like {fat,ext2}{ls,load},
and transparently handle either file-system. This scheme could easily be
extended to other filesystem types; I only didn't do it for zfs because
I don't have any filesystems of that type to test with.
Replace the implementation of {fat,ext[24]}{ls,load} with this new code
too.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Makefile | 47 | ||||
-rw-r--r-- | fs/fs.c | 308 |
2 files changed, 355 insertions, 0 deletions
diff --git a/fs/Makefile b/fs/Makefile new file mode 100644 index 0000000000..d0ab3aec56 --- /dev/null +++ b/fs/Makefile | |||
@@ -0,0 +1,47 @@ | |||
1 | # | ||
2 | # (C) Copyright 2000-2006 | ||
3 | # Wolfgang Denk, DENX Software Engineering, wd@denx.de. | ||
4 | # Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
5 | # | ||
6 | # See file CREDITS for list of people who contributed to this | ||
7 | # project. | ||
8 | # | ||
9 | # This program is free software; you can redistribute it and/or | ||
10 | # modify it under the terms of the GNU General Public License as | ||
11 | # published by the Free Software Foundation; either version 2 of | ||
12 | # the License, or (at your option) any later version. | ||
13 | # | ||
14 | # This program is distributed in the hope that it will be useful, | ||
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | # GNU General Public License for more details. | ||
18 | # | ||
19 | # You should have received a copy of the GNU General Public License | ||
20 | # along with this program; if not, write to the Free Software | ||
21 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
22 | # MA 02111-1307 USA | ||
23 | # | ||
24 | |||
25 | include $(TOPDIR)/config.mk | ||
26 | |||
27 | LIB = $(obj)libfs.o | ||
28 | |||
29 | COBJS-y += fs.o | ||
30 | |||
31 | COBJS := $(COBJS-y) | ||
32 | SRCS := $(COBJS:.o=.c) | ||
33 | OBJS := $(addprefix $(obj),$(COBJS)) | ||
34 | |||
35 | all: $(LIB) | ||
36 | |||
37 | $(LIB): $(obj).depend $(OBJS) | ||
38 | $(call cmd_link_o_target, $(OBJS)) | ||
39 | |||
40 | ######################################################################### | ||
41 | |||
42 | # defines $(obj).depend target | ||
43 | include $(SRCTREE)/rules.mk | ||
44 | |||
45 | sinclude $(obj).depend | ||
46 | |||
47 | ######################################################################### | ||
diff --git a/fs/fs.c b/fs/fs.c new file mode 100644 index 0000000000..23ffa25f0d --- /dev/null +++ b/fs/fs.c | |||
@@ -0,0 +1,308 @@ | |||
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 | } | ||