system/flashtool.cpp: add bad block skip for read/write/erase in case of NAND

Origin commit data
------------------
Branch: ni/coolstream
Commit: e739868e7c
Author: [CST] Focus <focus.cst@gmail.com>
Date: 2013-01-29 (Tue, 29 Jan 2013)


------------------
No further description and justification available within origin commit message!

------------------
This commit was generated by Migit
This commit is contained in:
[CST] Focus
2013-01-29 14:23:50 +04:00
parent 7f9de3998d
commit a916394176
2 changed files with 151 additions and 100 deletions

View File

@@ -36,16 +36,6 @@
#include <linux/version.h> #include <linux/version.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7)
//#include <linux/compiler.h>
#include <mtd/mtd-user.h>
#else
#include <mtd/mtd-user.h>
//#include <linux/mtd/mtd.h>
#endif
//#include <libcramfs.h>
#include <global.h> #include <global.h>
@@ -78,58 +68,78 @@ void CFlashTool::setStatusViewer( CProgress_StatusViewer* statusview )
bool CFlashTool::readFromMTD( const std::string & filename, int globalProgressEnd ) bool CFlashTool::readFromMTD( const std::string & filename, int globalProgressEnd )
{ {
int fd1, fd2; int fd1;
long filesize; long filesize;
int globalProgressBegin = 0; int globalProgressBegin = 0;
if(statusViewer) if(statusViewer)
{
statusViewer->showLocalStatus(0); statusViewer->showLocalStatus(0);
}
if (mtdDevice.empty()) if (mtdDevice.empty()) {
{
ErrorMessage = "mtd-device not set"; ErrorMessage = "mtd-device not set";
return false; return false;
} }
if( (fd1 = open( mtdDevice.c_str(), O_RDONLY )) < 0 ) if( (fd = open( mtdDevice.c_str(), O_RDONLY )) < 0 ) {
{
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD); ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD);
return false; return false;
} }
if (!getInfo()) {
close(fd);
return false;
}
if( (fd2 = open( filename.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0 ) if( (fd1 = open( filename.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0 ) {
{
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENFILE); ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENFILE);
close(fd1); close(fd);
return false; return false;
} }
if(statusViewer) if(statusViewer)
{
globalProgressBegin = statusViewer->getGlobalStatus(); globalProgressBegin = statusViewer->getGlobalStatus();
}
filesize = CMTDInfo::getInstance()->getMTDSize(mtdDevice); filesize = CMTDInfo::getInstance()->getMTDSize(mtdDevice);
char buf[1024]; unsigned char * buf = new unsigned char[meminfo.writesize];
long fsize = filesize; if (buf == NULL) {
while(fsize>0) printf("CFlashTool::program: mem alloc failed\n");
{ close(fd);
long block = fsize; close(fd1);
if(block>(long)sizeof(buf)) return false;
{
block = sizeof(buf);
} }
read( fd1, &buf, block); unsigned mtdoffset = 0;
write( fd2, &buf, block); long fsize = filesize;
while(fsize > 0) {
unsigned block = meminfo.writesize;
if (isnand) {
unsigned blockstart = mtdoffset & ~(meminfo.erasesize - 1);
if (blockstart == mtdoffset) {
while (mtdoffset < meminfo.size) {
printf("CFlashTool::readFromMTD: read block at %x\n", mtdoffset);
loff_t offset = mtdoffset;
int ret = ioctl(fd, MEMGETBADBLOCK, &offset);
if (ret == 0)
break;
printf("CFlashTool::readFromMTD: bad block at %x, skipping..\n", mtdoffset);
mtdoffset += meminfo.erasesize;
fsize -= meminfo.erasesize;
lseek(fd, mtdoffset, SEEK_SET);
continue;
}
if (mtdoffset >= meminfo.size) {
printf("CFlashTool::readFromMTD: end of device...\n");
break;
}
}
}
read(fd, buf, block);
write(fd1, buf, block);
fsize -= block; fsize -= block;
mtdoffset += meminfo.writesize;
char prog = char(100-(100./filesize*fsize)); char prog = char(100-(100./filesize*fsize));
if(statusViewer) if(statusViewer) {
{
statusViewer->showLocalStatus(prog); statusViewer->showLocalStatus(prog);
if(globalProgressEnd!=-1) if(globalProgressEnd!=-1) {
{
int globalProg = globalProgressBegin + int((globalProgressEnd-globalProgressBegin) * prog/100. ); int globalProg = globalProgressBegin + int((globalProgressEnd-globalProgressBegin) * prog/100. );
statusViewer->showGlobalStatus(globalProg); statusViewer->showGlobalStatus(globalProg);
} }
@@ -137,34 +147,29 @@ bool CFlashTool::readFromMTD( const std::string & filename, int globalProgressEn
} }
if(statusViewer) if(statusViewer)
{
statusViewer->showLocalStatus(100); statusViewer->showLocalStatus(100);
}
delete[] buf;
close(fd);
close(fd1); close(fd1);
close(fd2);
return true; return true;
} }
bool CFlashTool::program( const std::string & filename, int globalProgressEndErase, int globalProgressEndFlash ) bool CFlashTool::program( const std::string & filename, int globalProgressEndErase, int globalProgressEndFlash )
{ {
int fd1, fd2; int fd1;
long filesize; ssize_t filesize;
int globalProgressBegin = 0; int globalProgressBegin = 0;
if(statusViewer) if(statusViewer)
{
statusViewer->showLocalStatus(0); statusViewer->showLocalStatus(0);
}
if (mtdDevice.empty()) if (mtdDevice.empty()) {
{
ErrorMessage = "mtd-device not set"; ErrorMessage = "mtd-device not set";
return false; return false;
} }
if( (fd1 = open( filename.c_str(), O_RDONLY )) < 0 ) if( (fd1 = open( filename.c_str(), O_RDONLY )) < 0 ) {
{
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENFILE); ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENFILE);
return false; return false;
} }
@@ -172,65 +177,89 @@ bool CFlashTool::program( const std::string & filename, int globalProgressEndEra
filesize = lseek( fd1, 0, SEEK_END); filesize = lseek( fd1, 0, SEEK_END);
lseek( fd1, 0, SEEK_SET); lseek( fd1, 0, SEEK_SET);
if(filesize==0) if(filesize==0) {
{
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_FILEIS0BYTES); ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_FILEIS0BYTES);
close(fd1); close(fd1);
return false; return false;
} }
if(statusViewer) if(statusViewer) {
{
statusViewer->showLocalStatus(0); statusViewer->showLocalStatus(0);
statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_ERASING)); // UTF-8 statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_ERASING)); // UTF-8
} }
//g_Zapit->shutdown(); sleep(2);
if(!erase(globalProgressEndErase)) if(!erase(globalProgressEndErase)) {
{
close(fd1); close(fd1);
return false; return false;
} }
if(statusViewer) if(statusViewer) {
{
if(globalProgressEndErase!=-1) if(globalProgressEndErase!=-1)
{
statusViewer->showGlobalStatus(globalProgressEndErase); statusViewer->showGlobalStatus(globalProgressEndErase);
}
statusViewer->showLocalStatus(0); statusViewer->showLocalStatus(0);
statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_PROGRAMMINGFLASH)); // UTF-8 statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_PROGRAMMINGFLASH)); // UTF-8
} }
if( (fd2 = open( mtdDevice.c_str(), O_WRONLY )) < 0 ) if( (fd = open( mtdDevice.c_str(), O_WRONLY )) < 0 ) {
{
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD); ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD);
close(fd1); close(fd1);
return false; return false;
} }
if(statusViewer) if(statusViewer)
{
globalProgressBegin = statusViewer->getGlobalStatus(); globalProgressBegin = statusViewer->getGlobalStatus();
}
char buf[1024]; unsigned char * buf = new unsigned char[meminfo.writesize];
long fsize = filesize; if (buf == NULL) {
while(fsize>0) printf("CFlashTool::program: mem alloc failed\n");
{ close(fd);
long block = fsize; close(fd1);
if(block>(long)sizeof(buf)) return false;
{
block = sizeof(buf);
} }
read( fd1, &buf, block); unsigned mtdoffset = 0;
write( fd2, &buf, block); unsigned fsize = filesize;
printf("CFlashTool::program: file %s write size %d, erase size %d\n", filename.c_str(), meminfo.writesize, meminfo.erasesize);
while(fsize > 0) {
unsigned block = meminfo.writesize;
if (block > fsize)
block = fsize;
unsigned res = read(fd1, buf, block);
if (res != block) {
printf("CFlashTool::program: read from %s failed: %d from %d\n", filename.c_str(), res, block);
}
if (isnand) {
if (block < (unsigned) meminfo.writesize) {
printf("CFlashTool::program: padding at %x\n", mtdoffset);
memset(buf + res, 0, meminfo.writesize - res);
}
unsigned blockstart = mtdoffset & ~(meminfo.erasesize - 1);
if (blockstart == mtdoffset) {
while (mtdoffset < meminfo.size) {
printf("CFlashTool::program: write block at %x\n", mtdoffset);
loff_t offset = mtdoffset;
int ret = ioctl(fd, MEMGETBADBLOCK, &offset);
if (ret == 0)
break;
printf("CFlashTool::program: bad block at %x, skipping..\n", mtdoffset);
mtdoffset += meminfo.erasesize;
lseek(fd, mtdoffset, SEEK_SET);
continue;
}
if (mtdoffset >= meminfo.size) {
printf("CFlashTool::program: not enough space to write, left: %d\n", fsize);
break;
}
}
}
write(fd, buf, meminfo.writesize);
fsize -= block; fsize -= block;
mtdoffset += meminfo.writesize;
if(statusViewer) {
char prog = char(100-(100./filesize*fsize)); char prog = char(100-(100./filesize*fsize));
if(statusViewer)
{
statusViewer->showLocalStatus(prog); statusViewer->showLocalStatus(prog);
if(globalProgressEndFlash!=-1) if(globalProgressEndFlash!=-1) {
{
int globalProg = globalProgressBegin + int((globalProgressEndFlash-globalProgressBegin) * prog/100. ); int globalProg = globalProgressBegin + int((globalProgressEndFlash-globalProgressBegin) * prog/100. );
statusViewer->showGlobalStatus(globalProg); statusViewer->showGlobalStatus(globalProg);
} }
@@ -238,53 +267,59 @@ bool CFlashTool::program( const std::string & filename, int globalProgressEndEra
} }
if(statusViewer) if(statusViewer)
{
statusViewer->showLocalStatus(100); statusViewer->showLocalStatus(100);
}
delete[] buf;
close(fd1); close(fd1);
close(fd2); close(fd);
// FIXME error message
if (fsize)
return false;
return true;
}
bool CFlashTool::getInfo()
{
if (ioctl( fd, MEMGETINFO, &meminfo ) != 0 ) {
// TODO: localize error message
ErrorMessage = "can't get mtd-info";
return false;
}
isnand = (meminfo.type == MTD_NANDFLASH);
printf("CFlashTool::getInfo: NAND: %s\n", isnand ? "yes" : "no");
return true; return true;
} }
bool CFlashTool::erase(int globalProgressEnd) bool CFlashTool::erase(int globalProgressEnd)
{ {
int fd;
mtd_info_t meminfo;
erase_info_t lerase; erase_info_t lerase;
int globalProgressBegin = 0; int globalProgressBegin = 0;
if( (fd = open( mtdDevice.c_str(), O_RDWR )) < 0 ) if( (fd = open( mtdDevice.c_str(), O_RDWR )) < 0 )
{ {
printf("CFlashTool::erase: cant open %s\n", mtdDevice.c_str());
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD); ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD);
return false; return false;
} }
if( ioctl( fd, MEMGETINFO, &meminfo ) != 0 ) if (!getInfo()) {
{
// TODO: localize error message
ErrorMessage = "can't get mtd-info";
close(fd); close(fd);
return false; return false;
} }
if(statusViewer) if(statusViewer)
{
globalProgressBegin = statusViewer->getGlobalStatus(); globalProgressBegin = statusViewer->getGlobalStatus();
}
lerase.length = meminfo.erasesize; lerase.length = meminfo.erasesize;
for (lerase.start = 0; lerase.start < meminfo.size;lerase.start += meminfo.erasesize)
for (lerase.start = 0; lerase.start < meminfo.size; lerase.start += meminfo.erasesize)
{ {
printf( "Erasing %s erase size %x start %x size %x\n", /* printf( "Erasing %s erase size %x start %x size %x\n",
mtdDevice.c_str(), meminfo.erasesize, lerase.start, mtdDevice.c_str(), meminfo.erasesize, lerase.start,
meminfo.size ); meminfo.size ); */
printf( "\rErasing %u Kbyte @ %x -- %2u %% complete.", int prog = int(lerase.start*100./meminfo.size);
meminfo.erasesize/1024, lerase.start,
lerase.start*100/meminfo.size );
if(statusViewer) if(statusViewer)
{ {
int prog = int(lerase.start*100./meminfo.size);
statusViewer->showLocalStatus(prog); statusViewer->showLocalStatus(prog);
if(globalProgressEnd!=-1) if(globalProgressEnd!=-1)
{ {
@@ -292,6 +327,14 @@ bool CFlashTool::erase(int globalProgressEnd)
statusViewer->showGlobalStatus(globalProg); statusViewer->showGlobalStatus(globalProg);
} }
} }
if (isnand) {
loff_t offset = lerase.start;
int ret = ioctl(fd, MEMGETBADBLOCK, &offset);
if (ret > 0) {
printf("Erasing: bad block at %x, skipping..\n", lerase.start);
continue;
}
}
if(ioctl( fd, MEMERASE, &lerase) != 0) if(ioctl( fd, MEMERASE, &lerase) != 0)
{ {
@@ -299,6 +342,9 @@ bool CFlashTool::erase(int globalProgressEnd)
close(fd); close(fd);
return false; return false;
} }
printf( "Erasing %u Kbyte @ %x -- %2u %% complete.\n",
meminfo.erasesize/1024, lerase.start,
prog /* lerase.start*100/meminfo.size */);
} }
close(fd); close(fd);

View File

@@ -37,7 +37,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <mtd/mtd-user.h>
class CFlashTool class CFlashTool
{ {
@@ -47,6 +47,11 @@ class CFlashTool
std::string mtdDevice; std::string mtdDevice;
std::string ErrorMessage; std::string ErrorMessage;
int fd;
mtd_info_t meminfo;
bool isnand;
bool getInfo();
bool erase(int globalProgressEnd=-1); bool erase(int globalProgressEnd=-1);
public: public: