Code Search for Developers
 
 
  

update.c from openap at Krugle


Show update.c syntax highlighted

 /*  
     update.c - userspace front-end to flash device.

     Copyright (C) 2001-2001 Instant 802 Networks, All Rights Reserved.
        
*/

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <string.h>

#include <linux/mtd/mtd.h>

#ifndef DEBUG
/* 0 - no messages, 1 - only error messages, 2 - all messages */
#define DEBUG 1
#endif

#if DEBUG < 2
#define printf(arg, ...) ;
#endif

#if DEBUG < 1
#define fprintf(arg, ...) ;
#define perror(arg) ;
#endif

// returns if the offset is on a block boundary or not
int boundary_check(region_info_t *regioninfo, unsigned int region_count,
		   unsigned int offset, 
		   unsigned int *ret_region, unsigned int *ret_block) {
	region_info_t *r = NULL;
	unsigned int region_start = 0;
	unsigned int region_end = 0;
	unsigned int region_blocksize = 0;
	int i = 0;
	
	for (i=0; i<region_count; i++) {
		r = &regioninfo[i];
		region_start = r->offset;
		region_end   = r->offset + (r->numblocks * r->erasesize);
		region_blocksize = r->erasesize;

		// we need a special case if the offset is at the very end of the flash
		if ( (offset == region_end) && (i == region_count-1) ) {
			if (ret_region) 
				*ret_region = i;
			if (ret_block)
				*ret_block = r->numblocks;
			goto success;
		}
		// if offset is at the beginning or within this current region
		else if( (offset >= region_start) && (offset < region_end) )
		{
			// and if offset lands on a block boundary
			if ( ((region_end - offset) % region_blocksize) == 0) {
				if (ret_region) 
					*ret_region = i;
				if (ret_block)
					*ret_block = (offset - region_start) / region_blocksize;
				goto success;
			}
		}

	}
//fail:
	printf("boundary check for offset %d(0x%x) failed\n",
	       offset, offset);
	return 0; // fail

 success:
	//printf("boundary check for offset %d(0x%x) returning region %d block %d\n",
	//     offset, offset, i, (offset - region_start) / region_blocksize);
	return 1; // success

}



int region_erase(int fd, int start, int length)
{
	region_info_t *regioninfo = NULL;
	region_info_t *r = NULL;
	int region_count = 0;
	int i = 0;

	// find the region count
	if (ioctl(fd,MEMGETREGIONCOUNT, &region_count)) {
		printf("there are no regions in this mtd device\n");
		return 1;
	}
	printf("%d regions found in this mtd device\n", region_count);

	
	// allocate and clear the regioninfo
	regioninfo = malloc(sizeof(region_info_t)*region_count);
//	memset(regioninfo, 0, sizeof(region_info_t)*region_count);


	// get the info for each region
	for (i=0; i<region_count; i++) {
		r = &regioninfo[i];

		// read in the region info
		r->regionindex = i;
		if (ioctl(fd, MEMGETREGIONINFO, r) != 0) {
			printf("failed printing out region summaries\n");
			free(regioninfo);
			return 1;
		}
		// print out the region info
		printf("region %d is at %d(0x%x) of %d sectors "
		       "with sector size %d(0x%x)\n", 
		       i, r->offset, r->offset, 
		       r->numblocks,
		       r->erasesize, r->erasesize);
	}


	// safety checks
	if (!boundary_check(regioninfo, region_count, start, NULL, NULL)) {
 		printf("start %d(0x%x)is not on a boundary\n", 
		       start, start);
		return 1;
	}
	if (!boundary_check(regioninfo, region_count, start+length, NULL, NULL)) {
		printf("start+length %d(0x%x)is not on a boundary\n", 
		       start+length, start+length);
		return 1;
	}


	// do the erasing
	{
//		region_info_t * r = NULL;
		erase_info_t erase;
		u_int32_t region_num = 0;
		u_int32_t block_num  = 0;
		u_int32_t offset = start; // increment as we go

		while (offset < start+length)
		{
//			memset(&erase, 0, sizeof(erase_info_t));
			if (!boundary_check(regioninfo, region_count, offset,
					    &region_num, &block_num)) 
			{
				printf("could not find region in middle of erase\n");
				printf("we are fucked!\n");
				close(fd);
				return 1;
			}

			printf("boundary check for offset %d(0x%x) returning region %d block %d\n",
			       offset, offset, region_num, block_num);


			erase.start = offset;
			erase.length = regioninfo[region_num].erasesize;

			printf("erasing region %d block %d at offset %d(0x%x) length %d(0x%x)\n",
			       region_num, block_num,
			       erase.start, erase.start,
			       erase.length, erase.length);
			
			if( ioctl(fd, MEMERASE, &erase) ) 
			{
				perror("region block erase failure\n");
				close(fd);
				return 1;
			}
			
			offset += erase.length;
		}
	}
 	return 0;
}



int copy(int to, int from, int start)
{
	char buf[1024];
	off_t of;
	ssize_t s, w;

	of = lseek(to, 0, SEEK_SET);
	if (of != start) return 2;

	for(;;) {
		s = read(from, buf, sizeof(buf));
		if (s == -1) return 3;
		if (s == 0) break;
		w = write(to, buf, s);
		if (s != w) return 4;
	}
	return 0;
}


void usage() {
	printf("update <device> <start> <length> { - | <filename> }\n"
	       "Erases the bytes specified in the mtd device, and optionally\n"
	       "writes new data from a file or stdin. Start and length must\n"
	       "be on sector boundries\n");
}

int main(int argc,char *argv[])
{
	int fd       = 0;
	int fd2      = -1;
	int start    = 0;
	int length    = 0;
	int res      = 0; 

	if (argc < 4) {
		usage();
		return 1;
	}
	
	start  = strtol(argv[2], NULL, 0);
	length = strtol(argv[3], NULL, 0);

	// open the device
	if ((fd = open(argv[1],O_RDWR)) < 0) {
		perror("device open error");
		return 1;
	}
	// open the file
	if (argc == 5) {
		if (strcmp(argv[4],"-") == 0)
			fd2 = 0;
		else {
			fd2 = open(argv[4],O_RDONLY);
			if (fd2 < 0) {
				perror("file open error");
				return 1;
			}
		}
	}
	printf("MTD start erase\n");
	res = region_erase(fd, start, length);
	printf("MTD finish erase\n");
	if (res) return res;

	if (fd2 >= 0) {
		int ret = 0;
		printf("MTD start write\n");
		ret = copy(fd, fd2, start);
		printf("MTD finish write\n");
		if (ret) return ret;
	}

	if (length == 1048576 ) {
		printf("rebooting: killing init\n");
		return(kill(1, SIGTERM));
	}

	return 0;

}




See more files for this project here

openap

OpenAP is the complete distribution of open-source software that is required to produce a fully 802.11b compliant wireless access point. OpenAP is also a platform on which developers and hobbyists may realize their ideas. Since the build environment and s

Project homepage: http://savannah.nongnu.org/projects/openap
Programming language(s): Assembly,C
License: gpl2

  facility/
    rules
  Makefile
  update.c