mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-08-31 17:31:11 +02:00
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:
@@ -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);
|
||||||
|
@@ -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:
|
||||||
|
Reference in New Issue
Block a user