Example #1
0
/* read a page with ECC */
static int nand_read_page(u_char *buf, ulong page_addr)
{
 	u_char ecc_code[6];
	u_char ecc_calc[3];
 	u_char oob_buf[16];
	u_char *p;
	u16 val;
	int cntr;

	NAND_ENABLE_CE();   
	NanD_Command(NAND_CMD_READ0);
	NanD_Address(ADDR_COLUMN_PAGE, page_addr>>1);

	NAND_WAIT_READY();
 	p = buf;
	for (cntr = 0; cntr < 256; cntr++){
		val = READ_NAND(NAND_ADDR);
		*p++ = val & 0xff;
		*p++ = val >> 8;
 	}

	p = oob_buf;
	for (cntr = 0; cntr < 8; cntr++){
 		val = READ_NAND(NAND_ADDR);
		*p++ = val & 0xff;
		*p++ = val >> 8;
 	}
 	NAND_DISABLE_CE();  /* set pin high */

 	/* Pick the ECC bytes out of the oob data */
	for (cntr = 0; cntr < 6; cntr++)
		ecc_code[cntr] =  oob_buf[ecc_pos[cntr]];


	if ((oob_buf[eccvalid_pos] & 0x0f) != 0x0f) {
 		nand_calculate_ecc (buf, &ecc_calc[0]);
		if (nand_correct_data (buf, &ecc_code[0], &ecc_calc[0]) == -1) {
 			printf ("ECC Failed, page 0x%08x\n", page_addr);
  			return 1;
 		}
	}
	
	if ((oob_buf[eccvalid_pos] & 0xf0) != 0xf0) {
 		nand_calculate_ecc (buf + 256, &ecc_calc[0]);
		if (nand_correct_data (buf + 256, &ecc_code[3], &ecc_calc[0]) == -1) {
 			printf ("ECC Failed, page 0x%08x\n", page_addr+0x100);
  			return 1;
 		}
	}

	return 0;
}
Example #2
0
void cmd_nand_ecc(int argc, char** argv) {
	if(argc < 3) {
		bufferPrintf("Usage: %s <data> <ecc>\r\n", argv[0]);
		return;
	}

	uint32_t address = parseNumber(argv[1]);
	uint32_t ecc = parseNumber(argv[2]);

	bufferPrintf("nand_calculate_ecc(%x, %x) = %d\r\n", address, ecc, nand_calculate_ecc((uint8_t*) address, (uint8_t*) ecc));
}
Example #3
0
void ecc_sector(unsigned char *sector, unsigned char *code)
{
	unsigned char *p;
	int ecc = 0;

	ecc = nand_calculate_ecc(sector);

	p = (unsigned char *)&ecc;

	code[0] = p[0];
	code[1] = p[2];
	code[2] = p[1] | (p[3] << 4);
}
Example #4
0
/**
 * @returns If no error occurred, returns number of bytes consumed;
 * otherwise, returns a negative error code.)
 */
int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s)
{
	size_t total_read = 0;
	size_t one_read;

	if (NULL != s->page) {
		fileio_read(&s->fileio, s->page_size, s->page, &one_read);
		if (one_read < s->page_size)
			memset(s->page + one_read, 0xff, s->page_size - one_read);
		total_read += one_read;
	}

	if (s->oob_format & NAND_OOB_SW_ECC) {
		uint8_t ecc[3];
		memset(s->oob, 0xff, s->oob_size);
		for (uint32_t i = 0, j = 0; i < s->page_size; i += 256) {
			nand_calculate_ecc(nand, s->page + i, ecc);
			s->oob[s->eccpos[j++]] = ecc[0];
			s->oob[s->eccpos[j++]] = ecc[1];
			s->oob[s->eccpos[j++]] = ecc[2];
		}
	} else if (s->oob_format & NAND_OOB_SW_ECC_KW)   {
		/*
		 * In this case eccpos is not used as
		 * the ECC data is always stored contigously
		 * at the end of the OOB area.  It consists
		 * of 10 bytes per 512-byte data block.
		 */
		uint8_t *ecc = s->oob + s->oob_size - s->page_size / 512 * 10;
		memset(s->oob, 0xff, s->oob_size);
		for (uint32_t i = 0; i < s->page_size; i += 512) {
			nand_calculate_ecc_kw(nand, s->page + i, ecc);
			ecc += 10;
		}
	} else if (NULL != s->oob)   {
		fileio_read(&s->fileio, s->oob_size, s->oob, &one_read);
		if (one_read < s->oob_size)
			memset(s->oob + one_read, 0xff, s->oob_size - one_read);
		total_read += one_read;
	}
	return total_read;
}
Example #5
0
/*start_address/size does not include oob
  */
int main(int argc, char **argv)
{
	uint8_t *page_data = NULL;
	uint8_t *ecc_data;
	int infd = -1, outfd = -1;
	int ret = 1;
	ssize_t bytes;
	int ch;

	while ((ch = getopt(argc, argv, "e:o:p:")) != -1) {
		switch(ch) {
		case 'p':
			page_size = strtoul(optarg, NULL, 0);
			break;
		case 'o':
			oob_size = strtoul(optarg, NULL, 0);
			break;
		case 'e':
			ecc_offset = strtoul(optarg, NULL, 0);
			break;
		default:
			usage(argv[0]);
		}
	}
	argc -= optind;
	if (argc < 2)
		usage(argv[0]);

	argv += optind;

	infd = open(argv[0], O_RDONLY, 0);
	if (infd < 0) {
		perror("open input file");
		goto out;
	}

	outfd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC, 0644);
	if (outfd < 0) {
		perror("open output file");
		goto out;
	}

	page_data = malloc(page_size + oob_size);

	while ((bytes = read(infd, page_data, page_size)) == page_size) {
		int j;

		ecc_data = page_data + page_size + ecc_offset;
		for (j = 0; j < page_size / 256; j++)
		{
			nand_calculate_ecc(page_data + j * 256, ecc_data);
			ecc_data += 3;
		}
		write(outfd, page_data, page_size + oob_size);
	}

	ret = 0;
out:
	if (infd >= 0)
		close(infd);
	if (outfd >= 0)
		close(outfd);
	if (page_data)
		free(page_data);
	return ret;
}
Example #6
0
/*start_address/size does not include oob
  */
int main(int argc, char **argv)
{
	uint32_t start_address,size;
	char *nand_image;

	uint32_t pagenumber,pages;

	int nand_fd;
	uint32_t i,j;
	
	uint8_t page_data[BB_NAND_PAGE_SIZE+BB_NAND_OOB_SIZE];
	uint8_t ecc_data[3];
	

	if (argc!=4)
	{
		useage();
		exit(1);
	}

	nand_image = argv[1];

	start_address = strtol(argv[2],NULL,0);
	size = strtol(argv[3],NULL,0);

	nand_fd = open(nand_image,O_RDWR);
	if (nand_fd<0)
	{
		printf("Can not open nand image %s \n",nand_image);
		exit(1);
	}

	if (start_address>=BB_NAND_SIZE)
	{
		printf("start_address can no be more than 0x%x \n",BB_NAND_SIZE);
		exit(1);
	}
	if ((start_address%BB_NAND_PAGE_SIZE)!=0)
	{
		printf("start_address should be aligned to page boundary \n");
		exit(1);
	}

	if (size==0)
	{
		printf("size can no be zero \n");
		exit(1);
	}
	if ((size%BB_NAND_PAGE_SIZE)!=0)
	{
		printf("size should be aligned to page boundary \n");
		exit(1);
	}


	pagenumber = start_address/BB_NAND_PAGE_SIZE;
	pages = size/BB_NAND_PAGE_SIZE;

	for (i=0;i<pages;i++)
	{
		lseek(nand_fd,pagenumber*(BB_NAND_PAGE_SIZE+BB_NAND_OOB_SIZE),SEEK_SET);
		read(nand_fd,page_data,BB_NAND_PAGE_SIZE+BB_NAND_OOB_SIZE);
		
		for (j=0;j<BB_NAND_PAGE_SIZE/256;j++)
		{
			nand_calculate_ecc(page_data+j*256,ecc_data);
			memcpy(page_data+BB_NAND_PAGE_SIZE+BB_NAND_ECC_OFFSET+j*3,ecc_data,3);
		}
		lseek(nand_fd,pagenumber*(BB_NAND_PAGE_SIZE+BB_NAND_OOB_SIZE),SEEK_SET);
		write(nand_fd,page_data,BB_NAND_PAGE_SIZE+BB_NAND_OOB_SIZE);
		pagenumber++;
	}

	close(nand_fd);
	return (1);
}