mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-08-30 00:41:09 +02:00
our current experimental Neutrino branch
git-svn-id: file:///home/bas/coolstream_public_svn/THIRDPARTY/applications/neutrino-experimental@27 e54a6e83-5905-42d5-8d5c-058d10e6a962
Origin commit data
------------------
Branch: ni/coolstream
Commit: bc5bd4154e
Author: mrcolor <mrcolor@e54a6e83-5905-42d5-8d5c-058d10e6a962>
Date: 2009-12-08 (Tue, 08 Dec 2009)
------------------
This commit was generated by Migit
This commit is contained in:
538
src/system/flashtool.cpp
Normal file
538
src/system/flashtool.cpp
Normal file
@@ -0,0 +1,538 @@
|
||||
/*
|
||||
Neutrino-GUI - DBoxII-Project
|
||||
|
||||
License: GPL
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <libmd5sum.h>
|
||||
#include <system/flashtool.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/reboot.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 <driver/encoding.h>
|
||||
#include <global.h>
|
||||
|
||||
|
||||
CFlashTool::CFlashTool()
|
||||
{
|
||||
statusViewer = NULL;
|
||||
mtdDevice = "";
|
||||
ErrorMessage = "";
|
||||
}
|
||||
|
||||
CFlashTool::~CFlashTool()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string & CFlashTool::getErrorMessage(void) const
|
||||
{
|
||||
return ErrorMessage;
|
||||
}
|
||||
|
||||
void CFlashTool::setMTDDevice( const std::string & mtddevice )
|
||||
{
|
||||
mtdDevice = mtddevice;
|
||||
printf("flashtool.cpp: set mtd device to %s\n", mtddevice.c_str());
|
||||
}
|
||||
|
||||
void CFlashTool::setStatusViewer( CProgress_StatusViewer* statusview )
|
||||
{
|
||||
statusViewer = statusview;
|
||||
}
|
||||
|
||||
bool CFlashTool::readFromMTD( const std::string & filename, int globalProgressEnd )
|
||||
{
|
||||
int fd1, fd2;
|
||||
long filesize;
|
||||
int globalProgressBegin = 0;
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
statusViewer->showLocalStatus(0);
|
||||
}
|
||||
|
||||
if (mtdDevice.empty())
|
||||
{
|
||||
ErrorMessage = "mtd-device not set";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (fd1 = open( mtdDevice.c_str(), O_RDONLY )) < 0 )
|
||||
{
|
||||
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD);
|
||||
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 )
|
||||
{
|
||||
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENFILE);
|
||||
close(fd1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
globalProgressBegin = statusViewer->getGlobalStatus();
|
||||
}
|
||||
filesize = CMTDInfo::getInstance()->getMTDSize(mtdDevice);
|
||||
|
||||
char buf[1024];
|
||||
long fsize = filesize;
|
||||
while(fsize>0)
|
||||
{
|
||||
long block = fsize;
|
||||
if(block>(long)sizeof(buf))
|
||||
{
|
||||
block = sizeof(buf);
|
||||
}
|
||||
read( fd1, &buf, block);
|
||||
write( fd2, &buf, block);
|
||||
fsize -= block;
|
||||
char prog = char(100-(100./filesize*fsize));
|
||||
if(statusViewer)
|
||||
{
|
||||
statusViewer->showLocalStatus(prog);
|
||||
if(globalProgressEnd!=-1)
|
||||
{
|
||||
int globalProg = globalProgressBegin + int((globalProgressEnd-globalProgressBegin) * prog/100. );
|
||||
statusViewer->showGlobalStatus(globalProg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
statusViewer->showLocalStatus(100);
|
||||
}
|
||||
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFlashTool::program( const std::string & filename, int globalProgressEndErase, int globalProgressEndFlash )
|
||||
{
|
||||
int fd1, fd2;
|
||||
long filesize;
|
||||
int globalProgressBegin = 0;
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
statusViewer->showLocalStatus(0);
|
||||
}
|
||||
|
||||
if (mtdDevice.empty())
|
||||
{
|
||||
ErrorMessage = "mtd-device not set";
|
||||
return false;
|
||||
}
|
||||
|
||||
if( (fd1 = open( filename.c_str(), O_RDONLY )) < 0 )
|
||||
{
|
||||
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENFILE);
|
||||
return false;
|
||||
}
|
||||
|
||||
filesize = lseek( fd1, 0, SEEK_END);
|
||||
lseek( fd1, 0, SEEK_SET);
|
||||
|
||||
if(filesize==0)
|
||||
{
|
||||
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_FILEIS0BYTES);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
statusViewer->showLocalStatus(0);
|
||||
statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_ERASING)); // UTF-8
|
||||
}
|
||||
//g_Zapit->shutdown(); sleep(2);
|
||||
if(!erase(globalProgressEndErase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
if(globalProgressEndErase!=-1)
|
||||
{
|
||||
statusViewer->showGlobalStatus(globalProgressEndErase);
|
||||
}
|
||||
statusViewer->showLocalStatus(0);
|
||||
statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_PROGRAMMINGFLASH)); // UTF-8
|
||||
}
|
||||
|
||||
if( (fd2 = open( mtdDevice.c_str(), O_WRONLY )) < 0 )
|
||||
{
|
||||
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD);
|
||||
close(fd1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
globalProgressBegin = statusViewer->getGlobalStatus();
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
long fsize = filesize;
|
||||
while(fsize>0)
|
||||
{
|
||||
long block = fsize;
|
||||
if(block>(long)sizeof(buf))
|
||||
{
|
||||
block = sizeof(buf);
|
||||
}
|
||||
read( fd1, &buf, block);
|
||||
write( fd2, &buf, block);
|
||||
fsize -= block;
|
||||
char prog = char(100-(100./filesize*fsize));
|
||||
if(statusViewer)
|
||||
{
|
||||
statusViewer->showLocalStatus(prog);
|
||||
if(globalProgressEndFlash!=-1)
|
||||
{
|
||||
int globalProg = globalProgressBegin + int((globalProgressEndFlash-globalProgressBegin) * prog/100. );
|
||||
statusViewer->showGlobalStatus(globalProg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
statusViewer->showLocalStatus(100);
|
||||
}
|
||||
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFlashTool::erase(int globalProgressEnd)
|
||||
{
|
||||
int fd;
|
||||
mtd_info_t meminfo;
|
||||
erase_info_t erase;
|
||||
int globalProgressBegin = 0;
|
||||
|
||||
if( (fd = open( mtdDevice.c_str(), O_RDWR )) < 0 )
|
||||
{
|
||||
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ioctl( fd, MEMGETINFO, &meminfo ) != 0 )
|
||||
{
|
||||
#warning TODO: localize error message
|
||||
ErrorMessage = "can't get mtd-info";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(statusViewer)
|
||||
{
|
||||
globalProgressBegin = statusViewer->getGlobalStatus();
|
||||
}
|
||||
|
||||
erase.length = meminfo.erasesize;
|
||||
for (erase.start = 0; erase.start < meminfo.size;erase.start += meminfo.erasesize)
|
||||
{
|
||||
printf( "Erasing %s erase size %x start %x size %x\n",
|
||||
mtdDevice.c_str(), meminfo.erasesize, erase.start,
|
||||
meminfo.size );
|
||||
printf( "\rErasing %u Kbyte @ %x -- %2u %% complete.",
|
||||
meminfo.erasesize/1024, erase.start,
|
||||
erase.start*100/meminfo.size );
|
||||
if(statusViewer)
|
||||
{
|
||||
int prog = int(erase.start*100./meminfo.size);
|
||||
statusViewer->showLocalStatus(prog);
|
||||
if(globalProgressEnd!=-1)
|
||||
{
|
||||
int globalProg = globalProgressBegin + int((globalProgressEnd-globalProgressBegin) * prog/100. );
|
||||
statusViewer->showGlobalStatus(globalProg);
|
||||
}
|
||||
}
|
||||
|
||||
if(ioctl( fd, MEMERASE, &erase) != 0)
|
||||
{
|
||||
ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_ERASEFAILED);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFlashTool::check_cramfs( const std::string & filename )
|
||||
{
|
||||
int retVal = 0; //cramfs_crc( (char*) filename.c_str() );
|
||||
printf("flashcheck returned: %d\n", retVal);
|
||||
return retVal==1;
|
||||
}
|
||||
#define FROMHEX(c) ((c)>='a' ? (c)-'a'+10 : ((c)>='A' ? (c)-'A'+10 : (c)-'0'))
|
||||
bool CFlashTool::check_md5( const std::string & filename, const std::string & smd5)
|
||||
{
|
||||
unsigned char md5[16];
|
||||
unsigned char omd5[16];
|
||||
|
||||
const char * ptr = smd5.c_str();
|
||||
|
||||
if(strlen(ptr) < 32)
|
||||
return false;
|
||||
//printf("[flashtool] check file %s md5 %s\n", filename.c_str(), ptr);
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
omd5[i] = FROMHEX(ptr[i*2])*16 + FROMHEX(ptr[i*2+1]);
|
||||
|
||||
md5_file(filename.c_str(), 1, md5);
|
||||
if(memcmp(md5, omd5, 16))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CFlashTool::reboot()
|
||||
{
|
||||
::sync();
|
||||
::reboot(RB_AUTOBOOT);
|
||||
::exit(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
CFlashVersionInfo::CFlashVersionInfo(const std::string & versionString)
|
||||
{
|
||||
//SBBBYYYYMMTTHHMM -- formatsting
|
||||
|
||||
// recover type
|
||||
snapshot = versionString[0];
|
||||
|
||||
// recover release cycle version
|
||||
releaseCycle[0] = versionString[1];
|
||||
releaseCycle[1] = '.';
|
||||
/*
|
||||
if (versionString[2] == '0')
|
||||
{
|
||||
releaseCycle[2] = versionString[3];
|
||||
releaseCycle[3] = 0;
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
releaseCycle[2] = versionString[2];
|
||||
releaseCycle[3] = versionString[3];
|
||||
releaseCycle[4] = 0;
|
||||
}
|
||||
|
||||
// recover date
|
||||
date[0] = versionString[10];
|
||||
date[1] = versionString[11];
|
||||
date[2] = '.';
|
||||
date[3] = versionString[8];
|
||||
date[4] = versionString[9];
|
||||
date[5] = '.';
|
||||
date[6] = versionString[4];
|
||||
date[7] = versionString[5];
|
||||
date[8] = versionString[6];
|
||||
date[9] = versionString[7];
|
||||
date[10] = 0;
|
||||
|
||||
// recover time stamp
|
||||
time[0] = versionString[12];
|
||||
time[1] = versionString[13];
|
||||
time[2] = ':';
|
||||
time[3] = versionString[14];
|
||||
time[4] = versionString[15];
|
||||
time[5] = 0;
|
||||
}
|
||||
|
||||
const char * const CFlashVersionInfo::getDate(void) const
|
||||
{
|
||||
return date;
|
||||
}
|
||||
|
||||
const char * const CFlashVersionInfo::getTime(void) const
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
const char * const CFlashVersionInfo::getReleaseCycle(void) const
|
||||
{
|
||||
return releaseCycle;
|
||||
}
|
||||
|
||||
const char * const CFlashVersionInfo::getType(void) const
|
||||
{
|
||||
switch (snapshot)
|
||||
{
|
||||
case '0':
|
||||
return "Release";
|
||||
case '1':
|
||||
return "Beta";
|
||||
case '2':
|
||||
return "Internal";
|
||||
case 'L':
|
||||
return "Locale";
|
||||
case 'S':
|
||||
return "Settings";
|
||||
case 'A':
|
||||
return "Addon";
|
||||
case 'T':
|
||||
return "Text";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
CMTDInfo::CMTDInfo()
|
||||
{
|
||||
getPartitionInfo();
|
||||
}
|
||||
|
||||
CMTDInfo::~CMTDInfo()
|
||||
{
|
||||
for(int x=0;x<getMTDCount();x++)
|
||||
{
|
||||
delete mtdData[x];
|
||||
}
|
||||
mtdData.clear();
|
||||
}
|
||||
|
||||
|
||||
CMTDInfo* CMTDInfo::getInstance()
|
||||
{
|
||||
static CMTDInfo* MTDInfo = NULL;
|
||||
|
||||
if(!MTDInfo)
|
||||
{
|
||||
MTDInfo = new CMTDInfo();
|
||||
}
|
||||
return MTDInfo;
|
||||
}
|
||||
|
||||
void CMTDInfo::getPartitionInfo()
|
||||
{
|
||||
FILE* fd = fopen("/proc/mtd", "r");
|
||||
if(!fd)
|
||||
{
|
||||
perror("cannot read /proc/mtd");
|
||||
return;
|
||||
}
|
||||
char buf[1000];
|
||||
fgets(buf,sizeof(buf),fd);
|
||||
while(!feof(fd))
|
||||
{
|
||||
if(fgets(buf,sizeof(buf),fd)!=NULL)
|
||||
{
|
||||
char mtdname[50]="";
|
||||
int mtdnr=0;
|
||||
int mtdsize=0;
|
||||
int mtderasesize=0;
|
||||
sscanf(buf, "mtd%d: %x %x \"%s\"\n", &mtdnr, &mtdsize, &mtderasesize, mtdname);
|
||||
SMTDPartition* tmp = new SMTDPartition;
|
||||
tmp->size = mtdsize;
|
||||
tmp->erasesize = mtderasesize;
|
||||
std::string tmpstr = buf;
|
||||
tmp->name = tmpstr.substr( tmpstr.find('\"')+1, tmpstr.rfind('\"')-tmpstr.find('\"')-1);
|
||||
sprintf((char*) &buf, "/dev/mtd%d", mtdnr);
|
||||
tmp->filename = buf;
|
||||
mtdData.push_back(tmp);
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
int CMTDInfo::getMTDCount()
|
||||
{
|
||||
return mtdData.size();
|
||||
}
|
||||
|
||||
std::string CMTDInfo::getMTDName(const int pos)
|
||||
{
|
||||
#warning TODO: check /proc/mtd specification to determine mtdname encoding
|
||||
|
||||
return FILESYSTEM_ENCODING_TO_UTF8_STRING(mtdData[pos]->name);
|
||||
}
|
||||
|
||||
std::string CMTDInfo::getMTDFileName(const int pos)
|
||||
{
|
||||
return mtdData[pos]->filename;
|
||||
}
|
||||
|
||||
int CMTDInfo::getMTDSize(const int pos)
|
||||
{
|
||||
return mtdData[pos]->size;
|
||||
}
|
||||
|
||||
int CMTDInfo::getMTDEraseSize(const int pos)
|
||||
{
|
||||
return mtdData[pos]->erasesize;
|
||||
}
|
||||
|
||||
int CMTDInfo::findMTDNumber(const std::string & filename)
|
||||
{
|
||||
for(int x=0;x<getMTDCount();x++)
|
||||
{
|
||||
if(filename == getMTDFileName(x))
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string CMTDInfo::getMTDName(const std::string & filename)
|
||||
{
|
||||
return getMTDName( findMTDNumber(filename) );
|
||||
}
|
||||
|
||||
int CMTDInfo::getMTDSize( const std::string & filename )
|
||||
{
|
||||
return getMTDSize( findMTDNumber(filename) );
|
||||
}
|
||||
|
||||
int CMTDInfo::getMTDEraseSize( const std::string & filename )
|
||||
{
|
||||
return getMTDEraseSize( findMTDNumber(filename) );
|
||||
}
|
Reference in New Issue
Block a user