⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmd_jffs2.c

📁 u-boot-1.1.6 源码包
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * (C) Copyright 2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * (C) Copyright 2002 * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de> * * (C) Copyright 2003 * Kai-Uwe Bloem, Auerswald GmbH & Co KG, <linux-development@auerswald.de> * * (C) Copyright 2005 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * *   Added support for reading flash partition table from environment. *   Parsing routines are based on driver/mtd/cmdline.c from the linux 2.4 *   kernel tree. * *   $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $ *   Copyright 2002 SYSGO Real-Time Solutions GmbH * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA *//* * Three environment variables are used by the parsing routines: * * 'partition' - keeps current partition identifier * * partition  := <part-id> * <part-id>  := <dev-id>,part_num * * * 'mtdids' - linux kernel mtd device id <-> u-boot device id mapping * * mtdids=<idmap>[,<idmap>,...] * * <idmap>    := <dev-id>=<mtd-id> * <dev-id>   := 'nand'|'nor'<dev-num> * <dev-num>  := mtd device number, 0... * <mtd-id>   := unique device tag used by linux kernel to find mtd device (mtd->name) * * * 'mtdparts' - partition list * * mtdparts=mtdparts=<mtd-def>[;<mtd-def>...] * * <mtd-def>  := <mtd-id>:<part-def>[,<part-def>...] * <mtd-id>   := unique device tag used by linux kernel to find mtd device (mtd->name) * <part-def> := <size>[@<offset>][<name>][<ro-flag>] * <size>     := standard linux memsize OR '-' to denote all remaining space * <offset>   := partition start offset within the device * <name>     := '(' NAME ')' * <ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel) * * Notes: * - each <mtd-id> used in mtdparts must albo exist in 'mtddis' mapping * - if the above variables are not set defaults for a given target are used * * Examples: * * 1 NOR Flash, with 1 single writable partition: * mtdids=nor0=edb7312-nor * mtdparts=mtdparts=edb7312-nor:- * * 1 NOR Flash with 2 partitions, 1 NAND with one * mtdids=nor0=edb7312-nor,nand0=edb7312-nand * mtdparts=mtdparts=edb7312-nor:256k(ARMboot)ro,-(root);edb7312-nand:-(home) * *//* * JFFS2/CRAMFS support */#include <common.h>#include <command.h>#include <malloc.h>#include <jffs2/jffs2.h>#include <linux/list.h>#include <linux/ctype.h>#if (CONFIG_COMMANDS & CFG_CMD_JFFS2)#include <cramfs/cramfs_fs.h>#if (CONFIG_COMMANDS & CFG_CMD_NAND)#ifdef CFG_NAND_LEGACY#include <linux/mtd/nand_legacy.h>#else /* !CFG_NAND_LEGACY */#include <linux/mtd/nand.h>#include <nand.h>#endif /* !CFG_NAND_LEGACY */#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) *//* enable/disable debugging messages */#define	DEBUG_JFFS#undef	DEBUG_JFFS#ifdef  DEBUG_JFFS# define DEBUGF(fmt, args...)	printf(fmt ,##args)#else# define DEBUGF(fmt, args...)#endif/* special size referring to all the remaining space in a partition */#define SIZE_REMAINING		0xFFFFFFFF/* special offset value, it is used when not provided by user * * this value is used temporarily during parsing, later such offests * are recalculated */#define OFFSET_NOT_SPECIFIED	0xFFFFFFFF/* minimum partition size */#define MIN_PART_SIZE		4096/* this flag needs to be set in part_info struct mask_flags * field for read-only partitions */#define MTD_WRITEABLE_CMD		1#ifdef CONFIG_JFFS2_CMDLINE/* default values for mtdids and mtdparts variables */#if defined(MTDIDS_DEFAULT)static const char *const mtdids_default = MTDIDS_DEFAULT;#else#warning "MTDIDS_DEFAULT not defined!"static const char *const mtdids_default = NULL;#endif#if defined(MTDPARTS_DEFAULT)static const char *const mtdparts_default = MTDPARTS_DEFAULT;#else#warning "MTDPARTS_DEFAULT not defined!"static const char *const mtdparts_default = NULL;#endif/* copies of last seen 'mtdids', 'mtdparts' and 'partition' env variables */#define MTDIDS_MAXLEN		128#define MTDPARTS_MAXLEN		512#define PARTITION_MAXLEN	16static char last_ids[MTDIDS_MAXLEN];static char last_parts[MTDPARTS_MAXLEN];static char last_partition[PARTITION_MAXLEN];/* low level jffs2 cache cleaning routine */extern void jffs2_free_cache(struct part_info *part);/* mtdids mapping list, filled by parse_ids() */struct list_head mtdids;/* device/partition list, parse_cmdline() parses into here */struct list_head devices;#endif /* #ifdef CONFIG_JFFS2_CMDLINE *//* current active device and partition number */static struct mtd_device *current_dev = NULL;static u8 current_partnum = 0;extern int cramfs_check (struct part_info *info);extern int cramfs_load (char *loadoffset, struct part_info *info, char *filename);extern int cramfs_ls (struct part_info *info, char *filename);extern int cramfs_info (struct part_info *info);static struct part_info* jffs2_part_info(struct mtd_device *dev, unsigned int part_num);/* command line only routines */#ifdef CONFIG_JFFS2_CMDLINEstatic struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len);static int device_del(struct mtd_device *dev);/** * Parses a string into a number.  The number stored at ptr is * potentially suffixed with K (for kilobytes, or 1024 bytes), * M (for megabytes, or 1048576 bytes), or G (for gigabytes, or * 1073741824).  If the number is suffixed with K, M, or G, then * the return value is the number multiplied by one kilobyte, one * megabyte, or one gigabyte, respectively. * * @param ptr where parse begins * @param retptr output pointer to next char after parse completes (output) * @return resulting unsigned int */static unsigned long memsize_parse (const char *const ptr, const char **retptr){	unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);	switch (**retptr) {		case 'G':		case 'g':			ret <<= 10;		case 'M':		case 'm':			ret <<= 10;		case 'K':		case 'k':			ret <<= 10;			(*retptr)++;		default:			break;	}	return ret;}/** * Format string describing supplied size. This routine does the opposite job * to memsize_parse(). Size in bytes is converted to string and if possible * shortened by using k (kilobytes), m (megabytes) or g (gigabytes) suffix. * * Note, that this routine does not check for buffer overflow, it's the caller * who must assure enough space. * * @param buf output buffer * @param size size to be converted to string */static void memsize_format(char *buf, u32 size){#define SIZE_GB ((u32)1024*1024*1024)#define SIZE_MB ((u32)1024*1024)#define SIZE_KB ((u32)1024)	if ((size % SIZE_GB) == 0)		sprintf(buf, "%lug", size/SIZE_GB);	else if ((size % SIZE_MB) == 0)		sprintf(buf, "%lum", size/SIZE_MB);	else if (size % SIZE_KB == 0)		sprintf(buf, "%luk", size/SIZE_KB);	else		sprintf(buf, "%lu", size);}/** * This routine does global indexing of all partitions. Resulting index for * current partition is saved in 'mtddevnum'. Current partition name in * 'mtddevname'. */static void index_partitions(void){	char buf[16];	u16 mtddevnum;	struct part_info *part;	struct list_head *dentry;	struct mtd_device *dev;	DEBUGF("--- index partitions ---\n");	if (current_dev) {		mtddevnum = 0;		list_for_each(dentry, &devices) {			dev = list_entry(dentry, struct mtd_device, link);			if (dev == current_dev) {				mtddevnum += current_partnum;				sprintf(buf, "%d", mtddevnum);				setenv("mtddevnum", buf);				break;			}			mtddevnum += dev->num_parts;		}		part = jffs2_part_info(current_dev, current_partnum);		setenv("mtddevname", part->name);		DEBUGF("=> mtddevnum %d,\n=> mtddevname %s\n", mtddevnum, part->name);	} else {		setenv("mtddevnum", NULL);		setenv("mtddevname", NULL);		DEBUGF("=> mtddevnum NULL\n=> mtddevname NULL\n");	}}/** * Save current device and partition in environment variable 'partition'. */static void current_save(void){	char buf[16];	DEBUGF("--- current_save ---\n");	if (current_dev) {		sprintf(buf, "%s%d,%d", MTD_DEV_TYPE(current_dev->id->type),					current_dev->id->num, current_partnum);		setenv("partition", buf);		strncpy(last_partition, buf, 16);		DEBUGF("=> partition %s\n", buf);	} else {		setenv("partition", NULL);		last_partition[0] = '\0';		DEBUGF("=> partition NULL\n");	}	index_partitions();}/** * Performs sanity check for supplied NOR flash partition. Table of existing * NOR flash devices is searched and partition device is located. Alignment * with the granularity of NOR flash sectors is verified. * * @param id of the parent device * @param part partition to validate * @return 0 if partition is valid, 1 otherwise */static int part_validate_nor(struct mtdids *id, struct part_info *part){#if (CONFIG_COMMANDS & CFG_CMD_FLASH)	/* info for FLASH chips */	extern flash_info_t flash_info[];	flash_info_t *flash;	int offset_aligned;	u32 end_offset;	int i;	flash = &flash_info[id->num];	offset_aligned = 0;	for (i = 0; i < flash->sector_count; i++) {		if ((flash->start[i] - flash->start[0]) == part->offset) {			offset_aligned = 1;			break;		}	}	if (offset_aligned == 0) {		printf("%s%d: partition (%s) start offset alignment incorrect\n",				MTD_DEV_TYPE(id->type), id->num, part->name);		return 1;	}	end_offset = part->offset + part->size;	for (i = 0; i < flash->sector_count; i++) {		if ((flash->start[i] - flash->start[0]) == end_offset)			return 0;	}	if (flash->size == end_offset)		return 0;	printf("%s%d: partition (%s) size alignment incorrect\n",			MTD_DEV_TYPE(id->type), id->num, part->name);#endif	return 1;}/** * Performs sanity check for supplied NAND flash partition. Table of existing * NAND flash devices is searched and partition device is located. Alignment * with the granularity of nand erasesize is verified. * * @param id of the parent device * @param part partition to validate * @return 0 if partition is valid, 1 otherwise */static int part_validate_nand(struct mtdids *id, struct part_info *part){#if defined(CONFIG_JFFS2_NAND) && (CONFIG_COMMANDS & CFG_CMD_NAND)	/* info for NAND chips */	nand_info_t *nand;	nand = &nand_info[id->num];	if ((unsigned long)(part->offset) % nand->erasesize) {		printf("%s%d: partition (%s) start offset alignment incorrect\n",				MTD_DEV_TYPE(id->type), id->num, part->name);		return 1;	}	if (part->size % nand->erasesize) {		printf("%s%d: partition (%s) size alignment incorrect\n",				MTD_DEV_TYPE(id->type), id->num, part->name);		return 1;	}	return 0;#else	return 1;#endif}/** * Performs sanity check for supplied partition. Offset and size are verified * to be within valid range. Partition type is checked and either * parts_validate_nor() or parts_validate_nand() is called with the argument * of part. * * @param id of the parent device * @param part partition to validate * @return 0 if partition is valid, 1 otherwise */static int part_validate(struct mtdids *id, struct part_info *part){	if (part->size == SIZE_REMAINING)		part->size = id->size - part->offset;	if (part->offset > id->size) {		printf("%s: offset %08lx beyond flash size %08lx\n",				id->mtd_id, part->offset, id->size);		return 1;	}	if ((part->offset + part->size) <= part->offset) {		printf("%s%d: partition (%s) size too big\n",				MTD_DEV_TYPE(id->type), id->num, part->name);		return 1;	}	if (part->offset + part->size > id->size) {		printf("%s: partitioning exceeds flash size\n", id->mtd_id);		return 1;	}	if (id->type == MTD_DEV_TYPE_NAND)		return part_validate_nand(id, part);	else if (id->type == MTD_DEV_TYPE_NOR)		return part_validate_nor(id, part);	else		DEBUGF("part_validate: invalid dev type\n");	return 1;}/** * Delete selected partition from the partion list of the specified device. * * @param dev device to delete partition from * @param part partition to delete * @return 0 on success, 1 otherwise */static int part_del(struct mtd_device *dev, struct part_info *part){	u8 current_save_needed = 0;	/* if there is only one partition, remove whole device */	if (dev->num_parts == 1)		return device_del(dev);	/* otherwise just delete this partition */	if (dev == current_dev) {		/* we are modyfing partitions for the current device,		 * update current */		struct part_info *curr_pi;		curr_pi = jffs2_part_info(current_dev, current_partnum);		if (curr_pi) {			if (curr_pi == part) {				printf("current partition deleted, resetting current to 0\n");				current_partnum = 0;			} else if (part->offset <= curr_pi->offset) {				current_partnum--;			}			current_save_needed = 1;		}	}#ifdef CFG_NAND_LEGACY	jffs2_free_cache(part);#endif	list_del(&part->link);	free(part);	dev->num_parts--;	if (current_save_needed > 0)		current_save();	else		index_partitions();	return 0;}/** * Delete all partitions from parts head list, free memory. * * @param head list of partitions to delete */static void part_delall(struct list_head *head){	struct list_head *entry, *n;	struct part_info *part_tmp;	/* clean tmp_list and free allocated memory */	list_for_each_safe(entry, n, head) {		part_tmp = list_entry(entry, struct part_info, link);#ifdef CFG_NAND_LEGACY		jffs2_free_cache(part_tmp);#endif		list_del(entry);		free(part_tmp);	}}/** * Add new partition to the supplied partition list. Make sure partitions are * sorted by offset in ascending order. * * @param head list this partition is to be added to * @param new partition to be added */static int part_sort_add(struct mtd_device *dev, struct part_info *part){	struct list_head *entry;	struct part_info *new_pi, *curr_pi;	/* link partition to parrent dev */	part->dev = dev;	if (list_empty(&dev->parts)) {		DEBUGF("part_sort_add: list empty\n");		list_add(&part->link, &dev->parts);		dev->num_parts++;		index_partitions();		return 0;	}	new_pi = list_entry(&part->link, struct part_info, link);	/* get current partition info if we are updating current device */	curr_pi = NULL;	if (dev == current_dev)		curr_pi = jffs2_part_info(current_dev, current_partnum);	list_for_each(entry, &dev->parts) {		struct part_info *pi;		pi = list_entry(entry, struct part_info, link);		/* be compliant with kernel cmdline, allow only one partition at offset zero */		if ((new_pi->offset == pi->offset) && (pi->offset == 0)) {			printf("cannot add second partition at offset 0\n");			return 1;		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -