#!/bin/ash
## Testing the NAND flash: MT29F4G16 (x16)
## 
##	This test first try the different partitions by writing/reading random blocks
##	Then it format & mount a JFFS2 partition to write/read random size files.
##
## 
## Page	 = 1056 words = (1K + 32) words 
## Block = 64 x pages = (64K + 2K) words  =>  (0x0002.0000 + 0x0000.1000) bytes 
## Total =  4096 blocks = 262144 pages = 512 MBytes = 4.224Mbits
##		 = (0x2000.0000 + 0x0100.0000) bytes
##
## Layout: 
##   		0x0000.0000 - 0x0004.0000	//Empty (two first blocks)
##			0x0004.0000 - 0x0008.0000	//Barebox env
##			0x0008.0000 - 0x0010.0000	//Empty (up to 1MB position)
##			0x0010.0000 - 0x0090.0000	//Kernel (size of 8MB)
##			0x0090.0000 - 0x0400.0000 	//Empty (up to the end of /dev/mtd1)
##			0x0400.0000 - 0x0c00.0000	//Filesystem space, jffs2
##			0x0c00.0000 - 0x2000.0000	//Available
## 
## Linux devices: 
##		wrs# cat /proc/mtd
##		dev:    size   erasesize  name
##		mtd0: 00800000 00020000 "Kernel"
##		mtd1: 08000000 00020000 "Filesystem"
##		mtd2: 00040000 00020000 "Barebox Environment"
##		mtd3: 14000000 00020000 "Available"
##		mtd4: 00840000 00000420 "spi0.0-AT45DB642x"
##
##
## Authors: ##	
##	- Benoit Rat (Seven Solutions, www.sevensols.com)
##
## GNU Lesser General Public License Usage
## This file may be used under the terms of the GNU Lesser
## General Public License version 2.1 as published by the Free Software
## Foundation and appearing in the file LICENSE.LGPL included in the
## packaging of this file.  Please review the following information to
## ensure the GNU Lesser General Public License version 2.1 requirements
## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
#######################################################################################################

printf "======: $0\n"
. 000-functions.sh

	  	
displayErr() {
	if [ "$md5w" != "$md5r" ]; then
		echo "ERROR @ $testdev W:$md5w, R:$md5r"
		cmp -l /testing/at91bootstrap.bin /tmp/nand-at91 > /tmp/cmprw
		head -n 1 /tmp/cmprw
		tail -n 1 /tmp/cmprw
		hexdump -n 500 -v /tmp/nand-at91 
	else 
		echo "OK @ $testnand R/W" 
	fi  
}

askToSkip()
{
	ret="1"
	echo "execute $1?"
	read -t 5 -p "Press any key to skip it (5s): " ret; 
}

###
# This tool works properly but doesn't tell the % of failure of NAND.
# A block should be mark as corrupted if it can read the same as wrote 
# input: 
#	- device is the name of the device in linux i.e. /dev/mtd0
#	- ntest: Is the number of pass of the test (minimal recommand is 3 to be sure)
#
testtool()
{
	## Parse the arguments
	device=$1
	ntest=$2
	xtrarg="$3"
	
	nOK=0;
	itest=0;
	
	while [ $itest -lt $ntest ]; do	
		itest=$(expr $itest + 1)  		
		nandtest --markbad ${xtrarg} ${device}
		if [ "$?" == "0" ]; then
			nOK=$(expr ${nOK} + 1)
			printf ">> external pass %d successfully (%02d %%) \n" $itest $(expr $(expr $itest \* 100 ) / $ntest)
		 else
			printf "ERROR (%02d %%) \n" $(expr $(expr $itest \* 100 ) / $ntest)
		fi
	done
		
	echo "Result NAND testing ($device): OK=${nOK}/${ntest}"
	errpercent ${nOK} ${ntest}		
}


###
# This function is not used because it doesn't handle correctly when the file has a problem. 
testblocks() 
{
	## Parse the arguments
	device=$1
	ntest=$2

	#Obtain the range in which we jump between two block addresses	
	if [ -n $ntest ] && [ $nblock -gt ${ntest} ]; then
		range=$(expr $(expr $nblock / $ntest) \* 2 ) #((nblock/ntest) + 1)*2 
		echo "range $range"
	else
		ntest=$nblock
		range=1
	fi
	
	## Erase the flash
	flash_eraseall -j ${device} #It is better to clear the flash with -j option to avoid bad oob errors 
	
	##Init params
	f2w=/tmp/w128k.bin
	f2r=/tmp/r128k.bin
	sizeblock=131072
	okTxt=""
	itest=0
	iblock=0
	nOK=0
	nKO=0
	ddopt="bs=128k count=1"
	
	
	while [ $itest -lt $ntest ]; do
	
		startaddr=$(expr $iblock \* ${sizeblock})
		
		printf "> Checking Block: %04d @ 0x%08X " $iblock $startaddr
	
		dd $ddopt if=/dev/urandom of=${f2w} 		  2> /dev/null
		printf "..."
		#mtd_debug erase ${device} ${startaddr} ${sizeblock} &> /dev/null ##Don't erase with mtd_debug because it crash on BB
		printf "..."
		mtd_debug write ${device} ${startaddr} ${sizeblock} ${f2w} &> /dev/null
		printf "..."
		mtd_debug read ${device} ${startaddr} ${sizeblock} ${f2r} &> /dev/null
		printf "..."
	
		md5w=`md5sum ${f2w} | cut -f1 -d" "`
		md5r=`md5sum ${f2r} | cut -f1 -d" "`
	
		if [ "$md5w" != "$md5r" ]; then
			nKO=$(expr ${nKO} + 1)		
			printf "ERROR (%02d %%) \n" $(expr $(expr $itest \* 100 ) / $ntest)
		else
			nOK=$(expr ${nOK} + 1) 
			printf " %02d %% \\r" $(expr $(expr $itest \* 100 ) / $ntest)
		fi
	
		tmp=$RANDOM #Improve RANDOM generation
		iblock=$(expr $(expr $iblock + $(expr $(expr $RANDOM % $range ) + 1 )) % $nblock) 
		itest=$(expr $itest + 1)           
	

	done

	echo ""
	echo "Result NAND testing ($device): OK=${nOK}/${ntest} (nblocks=$nblock)"
	errpercent ${nOK} ${ntest}
}





testFiles()
{
	## Parse the arguments
	device=$1
	mtdblock=$2
	ntest=$3
	
	##Try to umount /mnt
	umount /mnt
	
	#format as JFFS2
	flash_erase -j ${device} 0 0
	
	#mount as JFFS2
	mount -t jffs2 ${mtdblock} /mnt

	#Init value
	tcount=0
	ddopt="bs=1k"
	nOK=0
	nKO=0
	itest=0
	f2w=/tmp/w-rand.bin

		
	while [ $itest -lt $ntest ]; do
		
		tmp=$RANDOM
		count=$(expr 128 + $(expr $RANDOM % 1920 )) #Mean file size is 1M 
		tcount=$(expr $tcount + $count )
		f2r=/mnt/file-$itest.bin
		
		printf "> Checking File: %04d (%04d KiB)" $itest $count
	
		##generate random
		dd $ddopt count=$count if=/dev/urandom of=${f2w} 2> /dev/null
		printf "..."
		## write
		dd $ddopt count=$count if=${f2w} of=${f2r} 2> /dev/null
		printf "..."
		
		
		md5w=`md5sum ${f2w} | cut -f1 -d" "` 2> /dev/null
		md5r=`md5sum ${f2r} | cut -f1 -d" "` 2> /dev/null
		printf "..."
	
		if [ "$md5w" != "$md5r" ]; then
			nKO=$(expr ${nKO} + 1)		
			printf "ERROR (%02d %%) \\n" $(expr $(expr $itest \* 100 ) / $ntest)
		else
			nOK=$(expr ${nOK} + 1)
			printf " %02d %% \\r" $(expr $(expr $itest \* 100 ) / $ntest)
		fi
			
		itest=$(expr $itest + 1)        
	done
	echo ""
	echo "Result NAND testing (${mtdblock}): OK=${nOK}/${ntest} (total $(expr $tcount / 1024 ) MB)"
	
	 
	#umount /mnt
	errpercent ${nOK} ${ntest}
	return $?
}

echo "This test will last about 8m"
ret=""
errmsg=""

## Partion mtd0 (Kernel)
echo "testing NAND mtd0 (Kernel)"
device=/dev/mtd0

askToSkip "erase and test ${device}";
if [ x${ret} != "x" ]; then	
	testtool ${device} 3
	ret0=$?
fi
date +%s

## Partion mtd1 (FileSystem)
echo "testing NAND mtd1 (FileSystem)"
device=/dev/mtd1

askToSkip "erase and test ${device}";
if [ x${ret} != "x" ]; then
	testtool ${device} 1	
	ret1=$?
fi
date +%s

## Partion mtd2 (Barebox)
echo "testing NAND mtd2 (Barebox)"
device=/dev/mtd2

askToSkip "erase and test ${device}";
if [ x${ret} != "x" ]; then
	testtool ${device} 3 --keep 	
	ret2=$?
fi
date +%s

## Partion mtd1 (Available)
echo "testing NAND mtd3 (Available)"
device=/dev/mtd3

askToSkip "erase and test ${device}";
if [ x${ret} != "x" ]; then
	testtool ${device} 1	
	ret3=$?
fi
date +%s

## Finaly mount some files of different size and try read and write.
mtdbname=mtdblock0
echo "testing NAND ${mtdbname} (Kernel)"
askToSkip "erase and test ${mtdbname}";
if [ x${ret} != "x" ]; then
	testFiles /dev/mtd0 /dev/${mtdbname} 5
	ret4=$?
fi
date +%s

mtdbname=mtdblock1
echo "testing NAND ${mtdbname} (Filesystem)"
askToSkip "erase and test ${mtdbname}";
if [ x${ret} != "x" ]; then
	testFiles /dev/mtd1 /dev/${mtdbname} 10
	ret5=$?
fi
date +%s

mtdbname=mtdblock3
echo "testing NAND ${mtdbname} (Available)"
askToSkip "erase and test ${mtdbname}";
if [ x${ret} != "x" ]; then
	testFiles /dev/mtd3 /dev/${mtdbname} 20
	ret6=$?
fi
date +%s

### Produce output message
exit_multierr $ret0 $ret1 $ret2 $ret3 $ret4 $ret5 $ret6


