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

📄 fw_env.c

📁 最新版的u-boot,2008-10-18发布
💻 C
📖 第 1 页 / 共 2 页
字号:
		blockstart += blocklen;	}	return processed;}/* * Write count bytes at offset, but stay within ENVSETCORS (dev) sectors of * DEVOFFSET (dev). Similar to the read case above, on NOR we erase and write * the whole data at once. */static int flash_write_buf (int dev, int fd, void *buf, size_t count,			    off_t offset, uint8_t mtd_type){	void *data;	struct erase_info_user erase;	size_t blocklen;	/* length of NAND block / NOR erase sector */	size_t erase_len;	/* whole area that can be erased - may include				   bad blocks */	size_t erasesize;	/* erase / write length - one block on NAND,				   whole area on NOR */	size_t processed = 0;	/* progress counter */	size_t write_total;	/* total size to actually write - excludinig				   bad blocks */	off_t erase_offset;	/* offset to the first erase block (aligned)				   below offset */	off_t block_seek;	/* offset inside the erase block to the start				   of the data */	off_t top_of_range;	/* end of the last block we may use */	loff_t blockstart;	/* running start of the current block -				   MEMGETBADBLOCK needs 64 bits */	int rc;	blocklen = DEVESIZE (dev);	/* Erase sector size is always a power of 2 */	top_of_range = (DEVOFFSET (dev) & ~(blocklen - 1)) +		ENVSECTORS (dev) * blocklen;	erase_offset = offset & ~(blocklen - 1);	/* Maximum area we may use */	erase_len = top_of_range - erase_offset;	blockstart = erase_offset;	/* Offset inside a block */	block_seek = offset - erase_offset;	/*	 * Data size we actually have to write: from the start of the block	 * to the start of the data, then count bytes of data, and to the	 * end of the block	 */	write_total = (block_seek + count + blocklen - 1) & ~(blocklen - 1);	/*	 * Support data anywhere within erase sectors: read out the complete	 * area to be erased, replace the environment image, write the whole	 * block back again.	 */	if (write_total > count) {		data = malloc (erase_len);		if (!data) {			fprintf (stderr,				 "Cannot malloc %u bytes: %s\n",				 erase_len, strerror (errno));			return -1;		}		rc = flash_read_buf (dev, fd, data, write_total, erase_offset,				     mtd_type);		if (write_total != rc)			return -1;		/* Overwrite the old environment */		memcpy (data + block_seek, buf, count);	} else {		/*		 * We get here, iff offset is block-aligned and count is a		 * multiple of blocklen - see write_total calculation above		 */		data = buf;	}	if (mtd_type == MTD_NANDFLASH) {		/*		 * NAND: calculate which blocks we are writing. We have		 * to write one block at a time to skip bad blocks.		 */		erasesize = blocklen;	} else {		erasesize = erase_len;	}	erase.length = erasesize;	/* This only runs once on NOR flash */	while (processed < write_total) {		rc = flash_bad_block (fd, mtd_type, &blockstart);		if (rc < 0)		/* block test failed */			return rc;		if (blockstart + erasesize > top_of_range) {			fprintf (stderr, "End of range reached, aborting\n");			return -1;		}		if (rc) {		/* block is bad */			blockstart += blocklen;			continue;		}		erase.start = blockstart;		ioctl (fd, MEMUNLOCK, &erase);		if (ioctl (fd, MEMERASE, &erase) != 0) {			fprintf (stderr, "MTD erase error on %s: %s\n",				 DEVNAME (dev),				 strerror (errno));			return -1;		}		if (lseek (fd, blockstart, SEEK_SET) == -1) {			fprintf (stderr,				 "Seek error on %s: %s\n",				 DEVNAME (dev), strerror (errno));			return -1;		}#ifdef DEBUG		printf ("Write 0x%x bytes at 0x%llx\n", erasesize, blockstart);#endif		if (write (fd, data + processed, erasesize) != erasesize) {			fprintf (stderr, "Write error on %s: %s\n",				 DEVNAME (dev), strerror (errno));			return -1;		}		ioctl (fd, MEMLOCK, &erase);		processed  += blocklen;		block_seek = 0;		blockstart += blocklen;	}	if (write_total > count)		free (data);	return processed;}/* * Set obsolete flag at offset - NOR flash only */static int flash_flag_obsolete (int dev, int fd, off_t offset){	int rc;	/* This relies on the fact, that obsolete_flag == 0 */	rc = lseek (fd, offset, SEEK_SET);	if (rc < 0) {		fprintf (stderr, "Cannot seek to set the flag on %s \n",			 DEVNAME (dev));		return rc;	}	rc = write (fd, &obsolete_flag, sizeof (obsolete_flag));	if (rc < 0)		perror ("Could not set obsolete flag");	return rc;}static int flash_write (int fd_current, int fd_target, int dev_target){	int rc;	switch (environment.flag_scheme) {	case FLAG_NONE:		break;	case FLAG_INCREMENTAL:		(*environment.flags)++;		break;	case FLAG_BOOLEAN:		*environment.flags = active_flag;		break;	default:		fprintf (stderr, "Unimplemented flash scheme %u \n",			 environment.flag_scheme);		return -1;	}#ifdef DEBUG	printf ("Writing new environment at 0x%lx on %s\n",		DEVOFFSET (dev_target), DEVNAME (dev_target));#endif	rc = flash_write_buf (dev_target, fd_target, environment.image,			      CONFIG_ENV_SIZE, DEVOFFSET (dev_target),			      DEVTYPE(dev_target));	if (rc < 0)		return rc;	if (environment.flag_scheme == FLAG_BOOLEAN) {		/* Have to set obsolete flag */		off_t offset = DEVOFFSET (dev_current) +			offsetof (struct env_image_redundant, flags);#ifdef DEBUG		printf ("Setting obsolete flag in environment at 0x%lx on %s\n",			DEVOFFSET (dev_current), DEVNAME (dev_current));#endif		flash_flag_obsolete (dev_current, fd_current, offset);	}	return 0;}static int flash_read (int fd){	struct mtd_info_user mtdinfo;	int rc;	rc = ioctl (fd, MEMGETINFO, &mtdinfo);	if (rc < 0) {		perror ("Cannot get MTD information");		return -1;	}	if (mtdinfo.type != MTD_NORFLASH && mtdinfo.type != MTD_NANDFLASH) {		fprintf (stderr, "Unsupported flash type %u\n", mtdinfo.type);		return -1;	}	DEVTYPE(dev_current) = mtdinfo.type;	rc = flash_read_buf (dev_current, fd, environment.image, CONFIG_ENV_SIZE,			     DEVOFFSET (dev_current), mtdinfo.type);	return (rc != CONFIG_ENV_SIZE) ? -1 : 0;}static int flash_io (int mode){	int fd_current, fd_target, rc, dev_target;	/* dev_current: fd_current, erase_current */	fd_current = open (DEVNAME (dev_current), mode);	if (fd_current < 0) {		fprintf (stderr,			 "Can't open %s: %s\n",			 DEVNAME (dev_current), strerror (errno));		return -1;	}	if (mode == O_RDWR) {		if (HaveRedundEnv) {			/* switch to next partition for writing */			dev_target = !dev_current;			/* dev_target: fd_target, erase_target */			fd_target = open (DEVNAME (dev_target), mode);			if (fd_target < 0) {				fprintf (stderr,					 "Can't open %s: %s\n",					 DEVNAME (dev_target),					 strerror (errno));				rc = -1;				goto exit;			}		} else {			dev_target = dev_current;			fd_target = fd_current;		}		rc = flash_write (fd_current, fd_target, dev_target);		if (HaveRedundEnv) {			if (close (fd_target)) {				fprintf (stderr,					"I/O error on %s: %s\n",					DEVNAME (dev_target),					strerror (errno));				rc = -1;			}		}	} else {		rc = flash_read (fd_current);	}exit:	if (close (fd_current)) {		fprintf (stderr,			 "I/O error on %s: %s\n",			 DEVNAME (dev_current), strerror (errno));		return -1;	}	return rc;}/* * s1 is either a simple 'name', or a 'name=value' pair. * s2 is a 'name=value' pair. * If the names match, return the value of s2, else NULL. */static char *envmatch (char * s1, char * s2){	while (*s1 == *s2++)		if (*s1++ == '=')			return s2;	if (*s1 == '\0' && *(s2 - 1) == '=')		return s2;	return NULL;}/* * Prevent confusion if running from erased flash memory */static int env_init (void){	int crc0, crc0_ok;	char flag0;	void *addr0;	int crc1, crc1_ok;	char flag1;	void *addr1;	struct env_image_single *single;	struct env_image_redundant *redundant;	if (parse_config ())		/* should fill envdevices */		return -1;	addr0 = calloc (1, CONFIG_ENV_SIZE);	if (addr0 == NULL) {		fprintf (stderr,			"Not enough memory for environment (%ld bytes)\n",			CONFIG_ENV_SIZE);		return -1;	}	/* read environment from FLASH to local buffer */	environment.image = addr0;	if (HaveRedundEnv) {		redundant = addr0;		environment.crc		= &redundant->crc;		environment.flags	= &redundant->flags;		environment.data	= redundant->data;	} else {		single = addr0;		environment.crc		= &single->crc;		environment.flags	= NULL;		environment.data	= single->data;	}	dev_current = 0;	if (flash_io (O_RDONLY))		return -1;	crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE);	crc0_ok = (crc0 == *environment.crc);	if (!HaveRedundEnv) {		if (!crc0_ok) {			fprintf (stderr,				"Warning: Bad CRC, using default environment\n");			memcpy(environment.data, default_environment, sizeof default_environment);		}	} else {		flag0 = *environment.flags;		dev_current = 1;		addr1 = calloc (1, CONFIG_ENV_SIZE);		if (addr1 == NULL) {			fprintf (stderr,				"Not enough memory for environment (%ld bytes)\n",				CONFIG_ENV_SIZE);			return -1;		}		redundant = addr1;		/*		 * have to set environment.image for flash_read(), careful -		 * other pointers in environment still point inside addr0		 */		environment.image = addr1;		if (flash_io (O_RDONLY))			return -1;		/* Check flag scheme compatibility */		if (DEVTYPE(dev_current) == MTD_NORFLASH &&		    DEVTYPE(!dev_current) == MTD_NORFLASH) {			environment.flag_scheme = FLAG_BOOLEAN;		} else if (DEVTYPE(dev_current) == MTD_NANDFLASH &&			   DEVTYPE(!dev_current) == MTD_NANDFLASH) {			environment.flag_scheme = FLAG_INCREMENTAL;		} else {			fprintf (stderr, "Incompatible flash types!\n");			return -1;		}		crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE);		crc1_ok = (crc1 == redundant->crc);		flag1 = redundant->flags;		if (crc0_ok && !crc1_ok) {			dev_current = 0;		} else if (!crc0_ok && crc1_ok) {			dev_current = 1;		} else if (!crc0_ok && !crc1_ok) {			fprintf (stderr,				"Warning: Bad CRC, using default environment\n");			memcpy (environment.data, default_environment,				sizeof default_environment);			dev_current = 0;		} else {			switch (environment.flag_scheme) {			case FLAG_BOOLEAN:				if (flag0 == active_flag &&				    flag1 == obsolete_flag) {					dev_current = 0;				} else if (flag0 == obsolete_flag &&					   flag1 == active_flag) {					dev_current = 1;				} else if (flag0 == flag1) {					dev_current = 0;				} else if (flag0 == 0xFF) {					dev_current = 0;				} else if (flag1 == 0xFF) {					dev_current = 1;				} else {					dev_current = 0;				}				break;			case FLAG_INCREMENTAL:				if ((flag0 == 255 && flag1 == 0) ||				    flag1 > flag0)					dev_current = 1;				else if ((flag1 == 255 && flag0 == 0) ||					 flag0 > flag1)					dev_current = 0;				else /* flags are equal - almost impossible */					dev_current = 0;				break;			default:				fprintf (stderr, "Unknown flag scheme %u \n",					 environment.flag_scheme);				return -1;			}		}		/*		 * If we are reading, we don't need the flag and the CRC any		 * more, if we are writing, we will re-calculate CRC and update		 * flags before writing out		 */		if (dev_current) {			environment.image	= addr1;			environment.crc		= &redundant->crc;			environment.flags	= &redundant->flags;			environment.data	= redundant->data;			free (addr0);		} else {			environment.image	= addr0;			/* Other pointers are already set */			free (addr1);		}	}	return 0;}static int parse_config (){	struct stat st;#if defined(CONFIG_FILE)	/* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */	if (get_config (CONFIG_FILE)) {		fprintf (stderr,			"Cannot parse config file: %s\n", strerror (errno));		return -1;	}#else	strcpy (DEVNAME (0), DEVICE1_NAME);	DEVOFFSET (0) = DEVICE1_OFFSET;	ENVSIZE (0) = ENV1_SIZE;	DEVESIZE (0) = DEVICE1_ESIZE;	ENVSECTORS (0) = DEVICE1_ENVSECTORS;#ifdef HAVE_REDUND	strcpy (DEVNAME (1), DEVICE2_NAME);	DEVOFFSET (1) = DEVICE2_OFFSET;	ENVSIZE (1) = ENV2_SIZE;	DEVESIZE (1) = DEVICE2_ESIZE;	ENVSECTORS (1) = DEVICE2_ENVSECTORS;	HaveRedundEnv = 1;#endif#endif	if (stat (DEVNAME (0), &st)) {		fprintf (stderr,			"Cannot access MTD device %s: %s\n",			DEVNAME (0), strerror (errno));		return -1;	}	if (HaveRedundEnv && stat (DEVNAME (1), &st)) {		fprintf (stderr,			"Cannot access MTD device %s: %s\n",			DEVNAME (1), strerror (errno));		return -1;	}	return 0;}#if defined(CONFIG_FILE)static int get_config (char *fname){	FILE *fp;	int i = 0;	int rc;	char dump[128];	fp = fopen (fname, "r");	if (fp == NULL)		return -1;	while (i < 2 && fgets (dump, sizeof (dump), fp)) {		/* Skip incomplete conversions and comment strings */		if (dump[0] == '#')			continue;		rc = sscanf (dump, "%s %lx %lx %lx %lx",			     DEVNAME (i),			     &DEVOFFSET (i),			     &ENVSIZE (i),			     &DEVESIZE (i),			     &ENVSECTORS (i));		if (rc < 4)			continue;		if (rc < 5)			/* Default - 1 sector */			ENVSECTORS (i) = 1;		i++;	}	fclose (fp);	HaveRedundEnv = i - 1;	if (!i) {			/* No valid entries found */		errno = EINVAL;		return -1;	} else		return 0;}#endif

⌨️ 快捷键说明

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