1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2002
3*4882a593Smuzhiyun * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * (C) Copyright 2002
6*4882a593Smuzhiyun * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * (C) Copyright 2003
9*4882a593Smuzhiyun * Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de>
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * (C) Copyright 2005
12*4882a593Smuzhiyun * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * Added support for reading flash partition table from environment.
15*4882a593Smuzhiyun * Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4
16*4882a593Smuzhiyun * kernel tree.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
19*4882a593Smuzhiyun * Copyright 2002 SYSGO Real-Time Solutions GmbH
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun * Three environment variables are used by the parsing routines:
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun * 'partition' - keeps current partition identifier
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * partition := <part-id>
30*4882a593Smuzhiyun * <part-id> := <dev-id>,part_num
31*4882a593Smuzhiyun *
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * mtdids=<idmap>[,<idmap>,...]
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun * <idmap> := <dev-id>=<mtd-id>
38*4882a593Smuzhiyun * <dev-id> := 'nand'|'nor'|'onenand'<dev-num>
39*4882a593Smuzhiyun * <dev-num> := mtd device number, 0...
40*4882a593Smuzhiyun * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)
41*4882a593Smuzhiyun *
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun * 'mtdparts' - partition list
44*4882a593Smuzhiyun *
45*4882a593Smuzhiyun * mtdparts=mtdparts=<mtd-def>[;<mtd-def>...]
46*4882a593Smuzhiyun *
47*4882a593Smuzhiyun * <mtd-def> := <mtd-id>:<part-def>[,<part-def>...]
48*4882a593Smuzhiyun * <mtd-id> := unique device tag used by linux kernel to find mtd device (mtd->name)
49*4882a593Smuzhiyun * <part-def> := <size>[@<offset>][<name>][<ro-flag>]
50*4882a593Smuzhiyun * <size> := standard linux memsize OR '-' to denote all remaining space
51*4882a593Smuzhiyun * <offset> := partition start offset within the device
52*4882a593Smuzhiyun * <name> := '(' NAME ')'
53*4882a593Smuzhiyun * <ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)
54*4882a593Smuzhiyun *
55*4882a593Smuzhiyun * Notes:
56*4882a593Smuzhiyun * - each <mtd-id> used in mtdparts must albo exist in 'mtddis' mapping
57*4882a593Smuzhiyun * - if the above variables are not set defaults for a given target are used
58*4882a593Smuzhiyun *
59*4882a593Smuzhiyun * Examples:
60*4882a593Smuzhiyun *
61*4882a593Smuzhiyun * 1 NOR Flash, with 1 single writable partition:
62*4882a593Smuzhiyun * mtdids=nor0=edb7312-nor
63*4882a593Smuzhiyun * mtdparts=mtdparts=edb7312-nor:-
64*4882a593Smuzhiyun *
65*4882a593Smuzhiyun * 1 NOR Flash with 2 partitions, 1 NAND with one
66*4882a593Smuzhiyun * mtdids=nor0=edb7312-nor,nand0=edb7312-nand
67*4882a593Smuzhiyun * mtdparts=mtdparts=edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home)
68*4882a593Smuzhiyun *
69*4882a593Smuzhiyun */
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /*
72*4882a593Smuzhiyun * JFFS2/CRAMFS support
73*4882a593Smuzhiyun */
74*4882a593Smuzhiyun #include <common.h>
75*4882a593Smuzhiyun #include <command.h>
76*4882a593Smuzhiyun #include <malloc.h>
77*4882a593Smuzhiyun #include <jffs2/jffs2.h>
78*4882a593Smuzhiyun #include <linux/list.h>
79*4882a593Smuzhiyun #include <linux/ctype.h>
80*4882a593Smuzhiyun #include <cramfs/cramfs_fs.h>
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun #if defined(CONFIG_CMD_NAND)
83*4882a593Smuzhiyun #include <linux/mtd/rawnand.h>
84*4882a593Smuzhiyun #include <nand.h>
85*4882a593Smuzhiyun #endif
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun #if defined(CONFIG_CMD_ONENAND)
88*4882a593Smuzhiyun #include <linux/mtd/mtd.h>
89*4882a593Smuzhiyun #include <linux/mtd/onenand.h>
90*4882a593Smuzhiyun #include <onenand_uboot.h>
91*4882a593Smuzhiyun #endif
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /* enable/disable debugging messages */
94*4882a593Smuzhiyun #define DEBUG_JFFS
95*4882a593Smuzhiyun #undef DEBUG_JFFS
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun #ifdef DEBUG_JFFS
98*4882a593Smuzhiyun # define DEBUGF(fmt, args...) printf(fmt ,##args)
99*4882a593Smuzhiyun #else
100*4882a593Smuzhiyun # define DEBUGF(fmt, args...)
101*4882a593Smuzhiyun #endif
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun /* special size referring to all the remaining space in a partition */
104*4882a593Smuzhiyun #define SIZE_REMAINING 0xFFFFFFFF
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* special offset value, it is used when not provided by user
107*4882a593Smuzhiyun *
108*4882a593Smuzhiyun * this value is used temporarily during parsing, later such offests
109*4882a593Smuzhiyun * are recalculated */
110*4882a593Smuzhiyun #define OFFSET_NOT_SPECIFIED 0xFFFFFFFF
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /* minimum partition size */
113*4882a593Smuzhiyun #define MIN_PART_SIZE 4096
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* this flag needs to be set in part_info struct mask_flags
116*4882a593Smuzhiyun * field for read-only partitions */
117*4882a593Smuzhiyun #define MTD_WRITEABLE_CMD 1
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* current active device and partition number */
120*4882a593Smuzhiyun #ifdef CONFIG_CMD_MTDPARTS
121*4882a593Smuzhiyun /* Use the ones declared in cmd_mtdparts.c */
122*4882a593Smuzhiyun extern struct mtd_device *current_mtd_dev;
123*4882a593Smuzhiyun extern u8 current_mtd_partnum;
124*4882a593Smuzhiyun #else
125*4882a593Smuzhiyun /* Use local ones */
126*4882a593Smuzhiyun struct mtd_device *current_mtd_dev = NULL;
127*4882a593Smuzhiyun u8 current_mtd_partnum = 0;
128*4882a593Smuzhiyun #endif
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun #if defined(CONFIG_CMD_CRAMFS)
131*4882a593Smuzhiyun extern int cramfs_check (struct part_info *info);
132*4882a593Smuzhiyun extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename);
133*4882a593Smuzhiyun extern int cramfs_ls (struct part_info *info, char *filename);
134*4882a593Smuzhiyun extern int cramfs_info (struct part_info *info);
135*4882a593Smuzhiyun #else
136*4882a593Smuzhiyun /* defining empty macros for function names is ugly but avoids ifdef clutter
137*4882a593Smuzhiyun * all over the code */
138*4882a593Smuzhiyun #define cramfs_check(x) (0)
139*4882a593Smuzhiyun #define cramfs_load(x,y,z) (-1)
140*4882a593Smuzhiyun #define cramfs_ls(x,y) (0)
141*4882a593Smuzhiyun #define cramfs_info(x) (0)
142*4882a593Smuzhiyun #endif
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun #ifndef CONFIG_CMD_MTDPARTS
145*4882a593Smuzhiyun /**
146*4882a593Smuzhiyun * Check device number to be within valid range for given device type.
147*4882a593Smuzhiyun *
148*4882a593Smuzhiyun * @param dev device to validate
149*4882a593Smuzhiyun * @return 0 if device is valid, 1 otherwise
150*4882a593Smuzhiyun */
mtd_device_validate(u8 type,u8 num,u32 * size)151*4882a593Smuzhiyun static int mtd_device_validate(u8 type, u8 num, u32 *size)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun if (type == MTD_DEV_TYPE_NOR) {
154*4882a593Smuzhiyun #if defined(CONFIG_CMD_FLASH)
155*4882a593Smuzhiyun if (num < CONFIG_SYS_MAX_FLASH_BANKS) {
156*4882a593Smuzhiyun extern flash_info_t flash_info[];
157*4882a593Smuzhiyun *size = flash_info[num].size;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun return 0;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun printf("no such FLASH device: %s%d (valid range 0 ... %d\n",
163*4882a593Smuzhiyun MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_FLASH_BANKS - 1);
164*4882a593Smuzhiyun #else
165*4882a593Smuzhiyun printf("support for FLASH devices not present\n");
166*4882a593Smuzhiyun #endif
167*4882a593Smuzhiyun } else if (type == MTD_DEV_TYPE_NAND) {
168*4882a593Smuzhiyun #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
169*4882a593Smuzhiyun struct mtd_info *mtd = get_nand_dev_by_index(num);
170*4882a593Smuzhiyun if (mtd) {
171*4882a593Smuzhiyun *size = mtd->size;
172*4882a593Smuzhiyun return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun printf("no such NAND device: %s%d (valid range 0 ... %d)\n",
176*4882a593Smuzhiyun MTD_DEV_TYPE(type), num, CONFIG_SYS_MAX_NAND_DEVICE - 1);
177*4882a593Smuzhiyun #else
178*4882a593Smuzhiyun printf("support for NAND devices not present\n");
179*4882a593Smuzhiyun #endif
180*4882a593Smuzhiyun } else if (type == MTD_DEV_TYPE_ONENAND) {
181*4882a593Smuzhiyun #if defined(CONFIG_CMD_ONENAND)
182*4882a593Smuzhiyun *size = onenand_mtd.size;
183*4882a593Smuzhiyun return 0;
184*4882a593Smuzhiyun #else
185*4882a593Smuzhiyun printf("support for OneNAND devices not present\n");
186*4882a593Smuzhiyun #endif
187*4882a593Smuzhiyun } else
188*4882a593Smuzhiyun printf("Unknown defice type %d\n", type);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return 1;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /**
194*4882a593Smuzhiyun * Parse device id string <dev-id> := 'nand'|'nor'|'onenand'<dev-num>,
195*4882a593Smuzhiyun * return device type and number.
196*4882a593Smuzhiyun *
197*4882a593Smuzhiyun * @param id string describing device id
198*4882a593Smuzhiyun * @param ret_id output pointer to next char after parse completes (output)
199*4882a593Smuzhiyun * @param dev_type parsed device type (output)
200*4882a593Smuzhiyun * @param dev_num parsed device number (output)
201*4882a593Smuzhiyun * @return 0 on success, 1 otherwise
202*4882a593Smuzhiyun */
mtd_id_parse(const char * id,const char ** ret_id,u8 * dev_type,u8 * dev_num)203*4882a593Smuzhiyun static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun const char *p = id;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun *dev_type = 0;
208*4882a593Smuzhiyun if (strncmp(p, "nand", 4) == 0) {
209*4882a593Smuzhiyun *dev_type = MTD_DEV_TYPE_NAND;
210*4882a593Smuzhiyun p += 4;
211*4882a593Smuzhiyun } else if (strncmp(p, "nor", 3) == 0) {
212*4882a593Smuzhiyun *dev_type = MTD_DEV_TYPE_NOR;
213*4882a593Smuzhiyun p += 3;
214*4882a593Smuzhiyun } else if (strncmp(p, "onenand", 7) == 0) {
215*4882a593Smuzhiyun *dev_type = MTD_DEV_TYPE_ONENAND;
216*4882a593Smuzhiyun p += 7;
217*4882a593Smuzhiyun } else {
218*4882a593Smuzhiyun printf("incorrect device type in %s\n", id);
219*4882a593Smuzhiyun return 1;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (!isdigit(*p)) {
223*4882a593Smuzhiyun printf("incorrect device number in %s\n", id);
224*4882a593Smuzhiyun return 1;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun *dev_num = simple_strtoul(p, (char **)&p, 0);
228*4882a593Smuzhiyun if (ret_id)
229*4882a593Smuzhiyun *ret_id = p;
230*4882a593Smuzhiyun return 0;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /*
234*4882a593Smuzhiyun * 'Static' version of command line mtdparts_init() routine. Single partition on
235*4882a593Smuzhiyun * a single device configuration.
236*4882a593Smuzhiyun */
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun /**
239*4882a593Smuzhiyun * Calculate sector size.
240*4882a593Smuzhiyun *
241*4882a593Smuzhiyun * @return sector size
242*4882a593Smuzhiyun */
get_part_sector_size_nand(struct mtdids * id)243*4882a593Smuzhiyun static inline u32 get_part_sector_size_nand(struct mtdids *id)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun #if defined(CONFIG_JFFS2_NAND) && defined(CONFIG_CMD_NAND)
246*4882a593Smuzhiyun struct mtd_info *mtd;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun mtd = get_nand_dev_by_index(id->num);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun return mtd->erasesize;
251*4882a593Smuzhiyun #else
252*4882a593Smuzhiyun BUG();
253*4882a593Smuzhiyun return 0;
254*4882a593Smuzhiyun #endif
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
get_part_sector_size_nor(struct mtdids * id,struct part_info * part)257*4882a593Smuzhiyun static inline u32 get_part_sector_size_nor(struct mtdids *id, struct part_info *part)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun #if defined(CONFIG_CMD_FLASH)
260*4882a593Smuzhiyun extern flash_info_t flash_info[];
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun u32 end_phys, start_phys, sector_size = 0, size = 0;
263*4882a593Smuzhiyun int i;
264*4882a593Smuzhiyun flash_info_t *flash;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun flash = &flash_info[id->num];
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun start_phys = flash->start[0] + part->offset;
269*4882a593Smuzhiyun end_phys = start_phys + part->size - 1;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun for (i = 0; i < flash->sector_count; i++) {
272*4882a593Smuzhiyun if (flash->start[i] >= end_phys)
273*4882a593Smuzhiyun break;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun if (flash->start[i] >= start_phys) {
276*4882a593Smuzhiyun if (i == flash->sector_count - 1) {
277*4882a593Smuzhiyun size = flash->start[0] + flash->size - flash->start[i];
278*4882a593Smuzhiyun } else {
279*4882a593Smuzhiyun size = flash->start[i+1] - flash->start[i];
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun if (sector_size < size)
283*4882a593Smuzhiyun sector_size = size;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun return sector_size;
288*4882a593Smuzhiyun #else
289*4882a593Smuzhiyun BUG();
290*4882a593Smuzhiyun return 0;
291*4882a593Smuzhiyun #endif
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
get_part_sector_size_onenand(void)294*4882a593Smuzhiyun static inline u32 get_part_sector_size_onenand(void)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun #if defined(CONFIG_CMD_ONENAND)
297*4882a593Smuzhiyun struct mtd_info *mtd;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun mtd = &onenand_mtd;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun return mtd->erasesize;
302*4882a593Smuzhiyun #else
303*4882a593Smuzhiyun BUG();
304*4882a593Smuzhiyun return 0;
305*4882a593Smuzhiyun #endif
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
get_part_sector_size(struct mtdids * id,struct part_info * part)308*4882a593Smuzhiyun static inline u32 get_part_sector_size(struct mtdids *id, struct part_info *part)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun if (id->type == MTD_DEV_TYPE_NAND)
311*4882a593Smuzhiyun return get_part_sector_size_nand(id);
312*4882a593Smuzhiyun else if (id->type == MTD_DEV_TYPE_NOR)
313*4882a593Smuzhiyun return get_part_sector_size_nor(id, part);
314*4882a593Smuzhiyun else if (id->type == MTD_DEV_TYPE_ONENAND)
315*4882a593Smuzhiyun return get_part_sector_size_onenand();
316*4882a593Smuzhiyun else
317*4882a593Smuzhiyun DEBUGF("Error: Unknown device type.\n");
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun return 0;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun /**
323*4882a593Smuzhiyun * Parse and initialize global mtdids mapping and create global
324*4882a593Smuzhiyun * device/partition list.
325*4882a593Smuzhiyun *
326*4882a593Smuzhiyun * 'Static' version of command line mtdparts_init() routine. Single partition on
327*4882a593Smuzhiyun * a single device configuration.
328*4882a593Smuzhiyun *
329*4882a593Smuzhiyun * @return 0 on success, 1 otherwise
330*4882a593Smuzhiyun */
mtdparts_init(void)331*4882a593Smuzhiyun int mtdparts_init(void)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun static int initialized = 0;
334*4882a593Smuzhiyun u32 size;
335*4882a593Smuzhiyun char *dev_name;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun DEBUGF("\n---mtdparts_init---\n");
338*4882a593Smuzhiyun if (!initialized) {
339*4882a593Smuzhiyun struct mtdids *id;
340*4882a593Smuzhiyun struct part_info *part;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun initialized = 1;
343*4882a593Smuzhiyun current_mtd_dev = (struct mtd_device *)
344*4882a593Smuzhiyun malloc(sizeof(struct mtd_device) +
345*4882a593Smuzhiyun sizeof(struct part_info) +
346*4882a593Smuzhiyun sizeof(struct mtdids));
347*4882a593Smuzhiyun if (!current_mtd_dev) {
348*4882a593Smuzhiyun printf("out of memory\n");
349*4882a593Smuzhiyun return 1;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun memset(current_mtd_dev, 0, sizeof(struct mtd_device) +
352*4882a593Smuzhiyun sizeof(struct part_info) + sizeof(struct mtdids));
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun id = (struct mtdids *)(current_mtd_dev + 1);
355*4882a593Smuzhiyun part = (struct part_info *)(id + 1);
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun /* id */
358*4882a593Smuzhiyun id->mtd_id = "single part";
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun #if defined(CONFIG_JFFS2_DEV)
361*4882a593Smuzhiyun dev_name = CONFIG_JFFS2_DEV;
362*4882a593Smuzhiyun #else
363*4882a593Smuzhiyun dev_name = "nor0";
364*4882a593Smuzhiyun #endif
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun if ((mtd_id_parse(dev_name, NULL, &id->type, &id->num) != 0) ||
367*4882a593Smuzhiyun (mtd_device_validate(id->type, id->num, &size) != 0)) {
368*4882a593Smuzhiyun printf("incorrect device: %s%d\n", MTD_DEV_TYPE(id->type), id->num);
369*4882a593Smuzhiyun free(current_mtd_dev);
370*4882a593Smuzhiyun return 1;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun id->size = size;
373*4882a593Smuzhiyun INIT_LIST_HEAD(&id->link);
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun DEBUGF("dev id: type = %d, num = %d, size = 0x%08lx, mtd_id = %s\n",
376*4882a593Smuzhiyun id->type, id->num, id->size, id->mtd_id);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun /* partition */
379*4882a593Smuzhiyun part->name = "static";
380*4882a593Smuzhiyun part->auto_name = 0;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun #if defined(CONFIG_JFFS2_PART_SIZE)
383*4882a593Smuzhiyun part->size = CONFIG_JFFS2_PART_SIZE;
384*4882a593Smuzhiyun #else
385*4882a593Smuzhiyun part->size = SIZE_REMAINING;
386*4882a593Smuzhiyun #endif
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun #if defined(CONFIG_JFFS2_PART_OFFSET)
389*4882a593Smuzhiyun part->offset = CONFIG_JFFS2_PART_OFFSET;
390*4882a593Smuzhiyun #else
391*4882a593Smuzhiyun part->offset = 0x00000000;
392*4882a593Smuzhiyun #endif
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun part->dev = current_mtd_dev;
395*4882a593Smuzhiyun INIT_LIST_HEAD(&part->link);
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun /* recalculate size if needed */
398*4882a593Smuzhiyun if (part->size == SIZE_REMAINING)
399*4882a593Smuzhiyun part->size = id->size - part->offset;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun part->sector_size = get_part_sector_size(id, part);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun DEBUGF("part : name = %s, size = 0x%08lx, offset = 0x%08lx\n",
404*4882a593Smuzhiyun part->name, part->size, part->offset);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun /* device */
407*4882a593Smuzhiyun current_mtd_dev->id = id;
408*4882a593Smuzhiyun INIT_LIST_HEAD(¤t_mtd_dev->link);
409*4882a593Smuzhiyun current_mtd_dev->num_parts = 1;
410*4882a593Smuzhiyun INIT_LIST_HEAD(¤t_mtd_dev->parts);
411*4882a593Smuzhiyun list_add(&part->link, ¤t_mtd_dev->parts);
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun return 0;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun #endif /* #ifndef CONFIG_CMD_MTDPARTS */
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun /**
419*4882a593Smuzhiyun * Return pointer to the partition of a requested number from a requested
420*4882a593Smuzhiyun * device.
421*4882a593Smuzhiyun *
422*4882a593Smuzhiyun * @param dev device that is to be searched for a partition
423*4882a593Smuzhiyun * @param part_num requested partition number
424*4882a593Smuzhiyun * @return pointer to the part_info, NULL otherwise
425*4882a593Smuzhiyun */
jffs2_part_info(struct mtd_device * dev,unsigned int part_num)426*4882a593Smuzhiyun static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun struct list_head *entry;
429*4882a593Smuzhiyun struct part_info *part;
430*4882a593Smuzhiyun int num;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun if (!dev)
433*4882a593Smuzhiyun return NULL;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun DEBUGF("\n--- jffs2_part_info: partition number %d for device %s%d (%s)\n",
436*4882a593Smuzhiyun part_num, MTD_DEV_TYPE(dev->id->type),
437*4882a593Smuzhiyun dev->id->num, dev->id->mtd_id);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun if (part_num >= dev->num_parts) {
440*4882a593Smuzhiyun printf("invalid partition number %d for device %s%d (%s)\n",
441*4882a593Smuzhiyun part_num, MTD_DEV_TYPE(dev->id->type),
442*4882a593Smuzhiyun dev->id->num, dev->id->mtd_id);
443*4882a593Smuzhiyun return NULL;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun /* locate partition number, return it */
447*4882a593Smuzhiyun num = 0;
448*4882a593Smuzhiyun list_for_each(entry, &dev->parts) {
449*4882a593Smuzhiyun part = list_entry(entry, struct part_info, link);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun if (part_num == num++) {
452*4882a593Smuzhiyun return part;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun return NULL;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun /***************************************************/
460*4882a593Smuzhiyun /* U-Boot commands */
461*4882a593Smuzhiyun /***************************************************/
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun /**
464*4882a593Smuzhiyun * Routine implementing fsload u-boot command. This routine tries to load
465*4882a593Smuzhiyun * a requested file from jffs2/cramfs filesystem on a current partition.
466*4882a593Smuzhiyun *
467*4882a593Smuzhiyun * @param cmdtp command internal data
468*4882a593Smuzhiyun * @param flag command flag
469*4882a593Smuzhiyun * @param argc number of arguments supplied to the command
470*4882a593Smuzhiyun * @param argv arguments list
471*4882a593Smuzhiyun * @return 0 on success, 1 otherwise
472*4882a593Smuzhiyun */
do_jffs2_fsload(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])473*4882a593Smuzhiyun int do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun char *fsname;
476*4882a593Smuzhiyun char *filename;
477*4882a593Smuzhiyun int size;
478*4882a593Smuzhiyun struct part_info *part;
479*4882a593Smuzhiyun ulong offset = load_addr;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun /* pre-set Boot file name */
482*4882a593Smuzhiyun filename = env_get("bootfile");
483*4882a593Smuzhiyun if (!filename)
484*4882a593Smuzhiyun filename = "uImage";
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun if (argc == 2) {
487*4882a593Smuzhiyun filename = argv[1];
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun if (argc == 3) {
490*4882a593Smuzhiyun offset = simple_strtoul(argv[1], NULL, 16);
491*4882a593Smuzhiyun load_addr = offset;
492*4882a593Smuzhiyun filename = argv[2];
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun /* make sure we are in sync with env variables */
496*4882a593Smuzhiyun if (mtdparts_init() !=0)
497*4882a593Smuzhiyun return 1;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun /* check partition type for cramfs */
502*4882a593Smuzhiyun fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2");
503*4882a593Smuzhiyun printf("### %s loading '%s' to 0x%lx\n", fsname, filename, offset);
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun if (cramfs_check(part)) {
506*4882a593Smuzhiyun size = cramfs_load ((char *) offset, part, filename);
507*4882a593Smuzhiyun } else {
508*4882a593Smuzhiyun /* if this is not cramfs assume jffs2 */
509*4882a593Smuzhiyun size = jffs2_1pass_load((char *)offset, part, filename);
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun if (size > 0) {
513*4882a593Smuzhiyun printf("### %s load complete: %d bytes loaded to 0x%lx\n",
514*4882a593Smuzhiyun fsname, size, offset);
515*4882a593Smuzhiyun env_set_hex("filesize", size);
516*4882a593Smuzhiyun } else {
517*4882a593Smuzhiyun printf("### %s LOAD ERROR<%x> for %s!\n", fsname, size, filename);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun return !(size > 0);
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun return 1;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun /**
526*4882a593Smuzhiyun * Routine implementing u-boot ls command which lists content of a given
527*4882a593Smuzhiyun * directory on a current partition.
528*4882a593Smuzhiyun *
529*4882a593Smuzhiyun * @param cmdtp command internal data
530*4882a593Smuzhiyun * @param flag command flag
531*4882a593Smuzhiyun * @param argc number of arguments supplied to the command
532*4882a593Smuzhiyun * @param argv arguments list
533*4882a593Smuzhiyun * @return 0 on success, 1 otherwise
534*4882a593Smuzhiyun */
do_jffs2_ls(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])535*4882a593Smuzhiyun int do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun char *filename = "/";
538*4882a593Smuzhiyun int ret;
539*4882a593Smuzhiyun struct part_info *part;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun if (argc == 2)
542*4882a593Smuzhiyun filename = argv[1];
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun /* make sure we are in sync with env variables */
545*4882a593Smuzhiyun if (mtdparts_init() !=0)
546*4882a593Smuzhiyun return 1;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /* check partition type for cramfs */
551*4882a593Smuzhiyun if (cramfs_check(part)) {
552*4882a593Smuzhiyun ret = cramfs_ls (part, filename);
553*4882a593Smuzhiyun } else {
554*4882a593Smuzhiyun /* if this is not cramfs assume jffs2 */
555*4882a593Smuzhiyun ret = jffs2_1pass_ls(part, filename);
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun return ret ? 0 : 1;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun return 1;
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun /**
564*4882a593Smuzhiyun * Routine implementing u-boot fsinfo command. This routine prints out
565*4882a593Smuzhiyun * miscellaneous filesystem informations/statistics.
566*4882a593Smuzhiyun *
567*4882a593Smuzhiyun * @param cmdtp command internal data
568*4882a593Smuzhiyun * @param flag command flag
569*4882a593Smuzhiyun * @param argc number of arguments supplied to the command
570*4882a593Smuzhiyun * @param argv arguments list
571*4882a593Smuzhiyun * @return 0 on success, 1 otherwise
572*4882a593Smuzhiyun */
do_jffs2_fsinfo(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])573*4882a593Smuzhiyun int do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun struct part_info *part;
576*4882a593Smuzhiyun char *fsname;
577*4882a593Smuzhiyun int ret;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun /* make sure we are in sync with env variables */
580*4882a593Smuzhiyun if (mtdparts_init() !=0)
581*4882a593Smuzhiyun return 1;
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun if ((part = jffs2_part_info(current_mtd_dev, current_mtd_partnum))){
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /* check partition type for cramfs */
586*4882a593Smuzhiyun fsname = (cramfs_check(part) ? "CRAMFS" : "JFFS2");
587*4882a593Smuzhiyun printf("### filesystem type is %s\n", fsname);
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun if (cramfs_check(part)) {
590*4882a593Smuzhiyun ret = cramfs_info (part);
591*4882a593Smuzhiyun } else {
592*4882a593Smuzhiyun /* if this is not cramfs assume jffs2 */
593*4882a593Smuzhiyun ret = jffs2_1pass_info(part);
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun return ret ? 0 : 1;
597*4882a593Smuzhiyun }
598*4882a593Smuzhiyun return 1;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun /***************************************************/
602*4882a593Smuzhiyun U_BOOT_CMD(
603*4882a593Smuzhiyun fsload, 3, 0, do_jffs2_fsload,
604*4882a593Smuzhiyun "load binary file from a filesystem image",
605*4882a593Smuzhiyun "[ off ] [ filename ]\n"
606*4882a593Smuzhiyun " - load binary file from flash bank\n"
607*4882a593Smuzhiyun " with offset 'off'"
608*4882a593Smuzhiyun );
609*4882a593Smuzhiyun U_BOOT_CMD(
610*4882a593Smuzhiyun fsls, 2, 1, do_jffs2_ls,
611*4882a593Smuzhiyun "list files in a directory (default /)",
612*4882a593Smuzhiyun "[ directory ]"
613*4882a593Smuzhiyun );
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun U_BOOT_CMD(
616*4882a593Smuzhiyun fsinfo, 1, 1, do_jffs2_fsinfo,
617*4882a593Smuzhiyun "print information about filesystems",
618*4882a593Smuzhiyun ""
619*4882a593Smuzhiyun );
620*4882a593Smuzhiyun /***************************************************/
621