5 #include <lib/gui/ebutton.h>
6 #include <lib/gui/statusbar.h>
7 #include <lib/gui/emessage.h>
8 #include <lib/gui/eprogress.h>
9 #include <lib/gui/eskin.h>
10 #include <lib/dvb/decoder.h>
11 #include <lib/dvb/edvb.h>
12 #include <lib/system/info.h>
13 #include <lib/gdi/font.h>
14 #include <lib/gdi/epng.h>
15 #include <lib/gdi/gfbdc.h>
16 #include <lib/gdi/fb.h>
17 #include <libmd5sum.h>
21 #include <linux/version.h>
22 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
23 #include <linux/compiler.h>
25 #include <mtd/mtd-user.h>
26 #include <sys/ioctl.h>
27 #include <sys/mount.h>
29 #define TMP_IMAGE "/tmp/root.cramfs"
30 #define TMP_IMAGE_ALT "/tmp/cdk.cramfs"
31 #define TMP_CHANGELOG "/tmp/changelog"
33 class ProgressWindow
: public eWindow
37 ProgressWindow( const char * );
40 ProgressWindow::ProgressWindow( const char *wtext
)
41 :eWindow(0), progress(this)
43 move(ePoint(100,250));
44 cresize(eSize(470,50));
46 progress
.move(ePoint(10,10));
47 progress
.resize(eSize(450,30));
50 static eString
getVersionInfo(const char *info
)
52 FILE *f
=fopen("/.version", "rt");
59 if (!fgets(buffer
, 128, f
))
62 buffer
[strlen(buffer
)-1]=0;
63 if ((!strncmp(buffer
, info
, strlen(info
)) && (buffer
[strlen(info
)]=='=')))
65 int i
= strlen(info
)+1;
66 result
= eString(buffer
).mid(i
, strlen(buffer
)-i
);
74 eListBoxEntryImage::eListBoxEntryImage
75 (eListBox
<eListBoxEntryImage
> *listbox
, eString name
, eString target
, eString url
, eString version
, eString creator
, const unsigned char md5
[16])
76 : eListBoxEntryText((eListBox
<eListBoxEntryText
> *)listbox
, name
),
77 name(name
), target(target
), url(url
), version(version
), creator(creator
)
80 memcpy(this->md5
, md5
, 16);
82 memset(this->md5
, 0, 16);
85 eHTTPDownload::eHTTPDownload(eHTTPConnection
*c
, const char *filename
): eHTTPDataSource(c
), filename(filename
)
87 if (c
->remote_header
.count("Content-Length"))
88 total
=atoi(c
->remote_header
["Content-Length"].c_str());
92 fd
=::creat(filename
, 0777);
93 progress(received
, total
);
96 eHTTPDownload::~eHTTPDownload()
100 if ((total
!= -1) && (total
!= received
))
101 ::unlink(filename
.c_str());
104 void eHTTPDownload::haveData(void *data
, int len
)
109 ::write(fd
, data
, len
);
112 progress(received
, total
);
115 eHTTPDownloadXML::eHTTPDownloadXML(eHTTPConnection
*c
, XMLTreeParser
&parser
): eHTTPDataSource(c
), parser(parser
)
121 void eHTTPDownloadXML::haveData(void *data
, int len
)
123 if ((!error
) && (!parser
.Parse((char*)data
, len
, !data
)))
125 errorstring
.sprintf("XML parse error: %s at line %d",
126 parser
.ErrorString(parser
.GetErrorCode()),
127 parser
.GetCurrentLineNumber());
132 eUpgrade::eUpgrade(bool manual
)
133 :http(0), changelog(0)
135 status
= new eStatusBar(this);
136 status
->setFlags(eStatusBar::flagOwnerDraw
);
138 status
->setName("status");
140 images
=new eListBox
<eListBoxEntryImage
>(this);
141 images
->setName("images");
142 CONNECT(images
->selected
, eUpgrade::imageSelected
);
143 CONNECT(images
->selchanged
, eUpgrade::imageSelchanged
);
145 imagehelp
=new eLabel(this);
146 imagehelp
->setName("imagehelp");
147 imagehelp
->setText(_("Please select the software version to upgrade to:"));
149 progress
=new eProgress(this);
150 progress
->setName("progress");
153 progresstext
=new eLabel(this);
154 progresstext
->setName("progresstext");
155 progresstext
->hide();
157 changes
=new eLabel(this, RS_WRAP
);
158 changes
->setName("changes");
160 abort
=new eButton(this);
161 abort
->setName("abort");
162 CONNECT(abort
->selected
, eUpgrade::abortDownload
);
165 if (eSkin::getActive()->build(this, "eUpgrade"))
166 eFatal("skin load of \"eUpgrade\" failed");
171 mIDStr
=eSystemInfo::getInstance()->getmidStr();
173 eString caturl
=getVersionInfo("catalog");
175 if (caturl
.length() && !manual
)
176 loadCatalog(caturl
.c_str());
178 ourversion
=getVersionInfo("version");
181 if (!stat(TMP_IMAGE_ALT
, &s
))
182 rename(TMP_IMAGE_ALT
, TMP_IMAGE
);
183 if (!stat(TMP_IMAGE
, &s
))
184 new eListBoxEntryImage(images
, _("manual upload"), "", "", "", "", 0);
189 void eUpgrade::loadCatalog(const char *url
)
195 catalog
=new XMLTreeParser("ISO-8859-1");
196 http
=eHTTPConnection::doRequest(url
, eApp
, &error
);
199 catalogTransferDone(error
);
202 setStatus(_("downloading catalog..."));
203 CONNECT(http
->transferDone
, eUpgrade::catalogTransferDone
);
204 CONNECT(http
->createDataSource
, eUpgrade::createCatalogDataSink
);
205 http
->local_header
["User-Agent"]="enigma-upgrade/1.0.0";
210 void eUpgrade::loadChangelog(const char *url
)
216 changelog
=eHTTPConnection::doRequest(url
, eApp
, &error
);
219 changelogTransferDone(error
);
222 setStatus(_("downloading changelog..."));
223 CONNECT(changelog
->transferDone
, eUpgrade::changelogTransferDone
);
224 CONNECT(changelog
->createDataSource
, eUpgrade::createChangelogDataSink
);
225 changelog
->local_header
["User-Agent"]="enigma-upgrade/1.0.0";
230 void eUpgrade::loadImage(const char *url
)
239 progresstext
->show();
241 http
=eHTTPConnection::doRequest(url
, eApp
, &error
);
244 imageTransferDone(error
);
247 setStatus(_("downloading image..."));
248 CONNECT(http
->transferDone
, eUpgrade::imageTransferDone
);
249 CONNECT(http
->createDataSource
, eUpgrade::createImageDataSink
);
250 http
->local_header
["User-Agent"]="enigma-upgrade/1.0.0";
255 void eUpgrade::catalogTransferDone(int err
)
257 if ((!err
) && http
&& (http
->code
== 200) && datacatalog
&& !datacatalog
->error
)
259 XMLTreeNode
*root
=catalog
->RootNode();
260 eString mytarget
=mIDStr
;
261 images
->beginAtomic();
262 for (XMLTreeNode
*r
=root
->GetChild(); r
; r
=r
->GetNext())
264 if (!strcmp(r
->GetType(), "image"))
266 const char *name
=r
->GetAttributeValue("name");
267 const char *url
=r
->GetAttributeValue("url");
268 const char *version
=r
->GetAttributeValue("version");
269 const char *target
=r
->GetAttributeValue("target");
270 const char *creator
=r
->GetAttributeValue("creator");
271 const char *amd5
=r
->GetAttributeValue("md5");
272 unsigned char md5
[16];
274 creator
=_("unknown");
277 for (int i
=0; i
<32; i
+=2)
287 if (sscanf(x
, "%02x", &v
) != 1)
291 if (!(name
&& url
&& version
&& target
))
293 if (!strstr(target
, mytarget
.c_str()))
295 new eListBoxEntryImage(images
, name
, target
, url
, version
, creator
, md5
);
296 } else if (!strcmp(r
->GetType(), "changelog"))
298 const char *changelog
=r
->GetAttributeValue("url");
300 loadChangelog(changelog
);
305 setStatus(_("Please select version to upgrade or LAME! to abort"));
306 if (images
->getCurrent())
307 imageSelchanged(images
->getCurrent());
310 if (err
|| http
->code
!=200)
312 else if (datacatalog
)
314 eDebug("data error.");
315 // setStatus(datacatalog->errorstring);
316 setStatus("XML parse error.");
324 void flashImage(int checkmd5
);
326 void eUpgrade::imageTransferDone(int err
)
329 progresstext
->hide();
331 if (err
|| !http
|| http
->code
!= 200)
340 void eUpgrade::changelogTransferDone(int err
)
342 if (err
|| !changelog
|| changelog
->code
!= 200)
347 FILE *f
=fopen(TMP_CHANGELOG
, "rt");
351 while (fgets(temp
, 1024, f
))
354 temp
[strlen(temp
)-1]=0; // remove trailng \n
356 changelogEntry entry
;
358 entry
.date
=str
.left(12);
359 entry
.priority
=str
[13]-'0';
360 entry
.text
=str
.mid(15);
361 unsigned int in
=entry
.text
.find(' ');
363 if (in
!= eString::npos
)
365 entry
.machines
=entry
.text
.left(in
);
366 entry
.text
=entry
.text
.mid(in
+1);
368 changelogentries
.push_back(entry
);
372 displayChangelog(ourversion
.mid(4), selectedversion
.mid(4), mIDStr
);
377 void eUpgrade::imageSelected(eListBoxEntryImage
*img
)
381 if (img
->url
.length())
383 memcpy(expected_md5
, img
->md5
, 16);
385 loadImage(img
->url
.c_str());
392 void eUpgrade::imageSelchanged(eListBoxEntryImage
*img
)
394 selectedversion
=img
->version
;
395 displayChangelog(ourversion
.mid(4), selectedversion
.mid(4), mIDStr
);
398 void eUpgrade::setStatus(const eString
&string
)
400 status
->setText(string
);
403 void eUpgrade::setError(int err
)
409 if (http
&& http
->code
!= 200)
410 errmsg
="error: server replied " + eString().setNum(http
->code
) + " " + http
->code_descr
;
413 errmsg
="Can't resolve hostname!";
416 errmsg
="Can't connect! (check network settings)";
419 errmsg
.sprintf("unknown error %d", err
);
424 if (current_url
.length())
425 errmsg
+="\n(URL: " + current_url
+ ")";
426 eMessageBox
box(errmsg
, _("Error!"), eMessageBox::btOK
|eMessageBox::iconError
);
433 eHTTPDataSource
*eUpgrade::createCatalogDataSink(eHTTPConnection
*conn
)
435 return datacatalog
=new eHTTPDownloadXML(conn
, *catalog
);
438 eHTTPDataSource
*eUpgrade::createImageDataSink(eHTTPConnection
*conn
)
440 image
=new eHTTPDownload(conn
, TMP_IMAGE
);
442 CONNECT(image
->progress
, eUpgrade::downloadProgress
);
446 eHTTPDataSource
*eUpgrade::createChangelogDataSink(eHTTPConnection
*conn
)
448 changelogdownload
=new eHTTPDownload(conn
, TMP_CHANGELOG
);
450 CONNECT(changelogdownload
->progress
, eUpgrade::downloadProgress
);
451 return changelogdownload
;
454 void eUpgrade::downloadProgress(int received
, int total
)
456 if ((time(0) == lasttime
) && (received
!= total
))
462 int perc
=received
*100/total
;
463 pt
.sprintf("%d/%d kb (%d%%)", received
/1024, total
/1024, perc
);
464 progress
->setPerc(perc
);
465 progresstext
->setText(pt
);
469 pt
.sprintf("%d kb", received
/1024);
470 progress
->setPerc(0);
471 progresstext
->setText(pt
);
475 void eUpgrade::abortDownload()
482 setStatus(_("Download aborted."));
484 progresstext
->hide();
490 bool erase(char mtd
[30], const char *titleText
);
492 #ifdef USE_EXTERNAL_FLASHTOOL
493 static int flashext
=1;
495 static int flashext
=0;
497 // when you will use the external flashtool you must set this here to 1
499 void eUpgrade::flashImage(int checkmd5
)
501 setStatus(_("checking consistency of file..."));
502 unsigned char md5
[16];
503 if (checkmd5
&& md5_file (TMP_IMAGE
, 1, (unsigned char*) &md5
))
505 setStatus(_("write error while downloading..."));
507 _("write error while downloading..."),
509 eMessageBox::btOK
|eMessageBox::iconError
);
517 if (checkmd5
&& memcmp(md5
, expected_md5
, 16))
519 setStatus(_("Data error. The checksum didn't match."));
521 _("Data error. The checksum didn't match."),
523 eMessageBox::btOK
|eMessageBox::iconError
);
531 setStatus(_("Checksum OK. Ready to upgrade."));
533 _("Are you sure you want to upgrade to this new version?"),
534 _("Ready to upgrade"),
535 eMessageBox::btYes
|eMessageBox::btNo
|eMessageBox::iconQuestion
);
541 if (res
== eMessageBox::btYes
)
546 int mID
= atoi(mIDStr
.c_str());
552 strcpy(mtd
,"/dev/mtd/2");
559 strcpy(mtd
,"/dev/mtd/0");
563 strcpy(mtd
,"/dev/null");
568 if( (fd1
= open( TMP_IMAGE
, O_RDONLY
)) < 0 )
570 eMessageBox
box(_("Can't read flashimage.img!"), _("Flash"), eMessageBox::iconInfo
|eMessageBox::btOK
);
578 int filesize
= lseek( fd1
, 0, SEEK_END
);
579 lseek( fd1
, 0, SEEK_SET
);
583 eMessageBox
box(_("flashimage.img has filesize of 0byte!"), _("Flash"), eMessageBox::iconInfo
|eMessageBox::btOK
);
601 pixmap
.clut
.colors
=256;
602 pixmap
.clut
.data
=gFBDC::getInstance()->getPixmap().clut
.data
;
603 gPixmapDC
outputDC(&pixmap
);
605 virtualRoot
.move(ePoint(0, 0));
606 virtualRoot
.resize(eSize(720, 576));
607 virtualRoot
.setTarget(&outputDC
);
608 virtualRoot
.makeRoot();
609 virtualRoot
.setBackgroundColor(gColor(0));
613 _("Please wait... do NOT switch off the receiver!"),
614 _("upgrade in progress"), eMessageBox::iconInfo
);
617 ProgressWindow
wnd(_("Erasing Flash..."));
619 while(gRC::getInstance().mustDraw())
621 // if ( !savePNG("/tmp/update1.png", &pixmap) )
622 // eDebug("saved update pic 1");
623 int fd
= open("/tmp/update1.raw", O_CREAT
|O_WRONLY
|O_TRUNC
);
626 ePoint pos
= wnd
.progress
.getAbsolutePosition();
627 int x
= 2+pos
.x(); // borderwidth+xpos..
628 int y
= 2+pos
.y(); // borderwidth+ypos..
629 int fillColor
= eSkin::getActive()->queryScheme("eProgress.left").color
;
630 int width
= wnd
.progress
.getSize().width()-4;
631 int height
= wnd
.progress
.getSize().height()-4;
632 write(fd
, &x
, sizeof(x
));
633 write(fd
, &y
, sizeof(y
));
634 write(fd
, &width
, sizeof(width
));
635 write(fd
, &height
, sizeof(height
));
636 write(fd
, &fillColor
, sizeof(fillColor
));
637 write(fd
, pixmap
.data
, 720*576*pixmap
.bpp
/8);
642 ProgressWindow
wnd(_("Writing Software to Flash..."));
644 while(gRC::getInstance().mustDraw())
646 // if ( !savePNG("/tmp/update2.png", &pixmap) )
647 // eDebug("saved update pic 2");
648 int fd
= open("/tmp/update2.raw", O_CREAT
|O_WRONLY
|O_TRUNC
);
651 ePoint pos
= wnd
.progress
.getAbsolutePosition();
652 int x
= 2+pos
.x(); // borderwidth+xpos..
653 int y
= 2+pos
.y(); // borderwidth+ypos..
654 int fillColor
= eSkin::getActive()->queryScheme("eProgress.left").color
;
655 int width
= wnd
.progress
.getSize().width()-4;
656 int height
= wnd
.progress
.getSize().height()-4;
657 write(fd
, &x
, sizeof(x
));
658 write(fd
, &y
, sizeof(y
));
659 write(fd
, &width
, sizeof(width
));
660 write(fd
, &height
, sizeof(height
));
661 write(fd
, &fillColor
, sizeof(fillColor
));
662 write(fd
, pixmap
.data
, 720*576*pixmap
.bpp
/8);
668 int fd
= open("/tmp/mtd.txt", O_WRONLY
|O_CREAT
|O_TRUNC
);
671 write(fd
, mtd
, strlen(mtd
));
674 struct fb_cmap
* cmap
= fbClass::getInstance()->CMAP();
675 fd
= open("/tmp/cmap", O_WRONLY
|O_CREAT
|O_TRUNC
);
678 write(fd
, &cmap
->start
, sizeof(cmap
->start
));
679 write(fd
, &cmap
->len
, sizeof(cmap
->len
));
680 write(fd
, cmap
->red
, cmap
->len
*sizeof(__u16
));
681 write(fd
, cmap
->green
, cmap
->len
*sizeof(__u16
));
682 write(fd
, cmap
->blue
, cmap
->len
*sizeof(__u16
));
683 write(fd
, cmap
->transp
, cmap
->len
*sizeof(__u16
));
686 eZap::getInstance()->getDesktop(eZap::desktopFB
)->makeRoot();
687 fbClass::getInstance()->lock();
692 _("Please wait... do NOT switch off the receiver!"),
693 _("upgrade in progress"), eMessageBox::iconInfo
);
696 // without this nice we have not enough priority for
697 // file operations... then the update ist very slow on the
700 eEPGCache::getInstance()->messages
.send(eEPGCache::Message(eEPGCache::Message::pause
));
702 system("cp /sbin/rebootSE /tmp/reboot");
704 if(!erase(mtd
,_("Erasing Flash...")))
707 eMessageBox
box(_("Erase error!"), _("Flash"), eMessageBox::iconInfo
|eMessageBox::btOK
);
715 if( (fd2
= open(mtd
, O_RDWR
)) < 0 )
718 eMessageBox
box(_("Can't open mtd!"), _("Flash"), eMessageBox::iconInfo
|eMessageBox::btOK
);
727 if( ioctl( fd2
, MEMGETINFO
, &meminfo
) != 0 )
733 ProgressWindow
wnd(_("Writing Software to Flash..."));
736 char buf
[meminfo
.erasesize
];
740 eDebug("flashing now...");
743 while( ( rbytes
= read( fd1
, buf
, sizeof(buf
) ) ) )
745 fsize
-= write( fd2
, buf
, rbytes
);
746 wnd
.progress
.setPerc( ((filesize
-fsize
)*100)/filesize
);
757 _("upgrade successful!\nrestarting..."),
759 eMessageBox::btOK
|eMessageBox::iconInfo
);
764 eZap::getInstance()->quit(3);
765 // system("/sbin/reboot");
766 // system("/bin/reboot");
774 bool erase(char mtd
[30], const char *titleText
)
780 if( (fd
= open( mtd
, O_RDWR
)) < 0 )
783 if( ioctl( fd
, MEMGETINFO
, &meminfo
) != 0 )
786 ProgressWindow
wnd(titleText
);
789 erase
.length
= meminfo
.erasesize
;
790 for (erase
.start
= 0; erase
.start
< meminfo
.size
; erase
.start
+= meminfo
.erasesize
)
792 eDebugNoNewLine("\rErasing %u Kibyte @ %x -- %2u %% complete",
793 meminfo
.erasesize
/1024, erase
.start
,
794 erase
.start
*100/meminfo
.size
);
796 wnd
.progress
.setPerc( erase
.start
*100/meminfo
.size
);
798 if(ioctl( fd
, MEMERASE
, &erase
) != 0)
812 void eUpgrade::displayChangelog(eString oldversion
, eString newversion
, eString mid
)
815 if (newversion
.empty())
818 } else if (oldversion
== newversion
)
820 changetext
=_("This is the currently installed release.");
821 } else if (oldversion
> newversion
)
823 changetext
=_("This is an older release.");
824 } else if (changelogentries
.empty())
826 changetext
=_("No changelog data available.");
829 // build list of changetext
831 std::multimap
<int,eString
> pchanges
;
832 for (std::list
<changelogEntry
>::const_iterator
i(changelogentries
.begin());
833 i
!= changelogentries
.end(); ++i
)
835 // check if change is new for this version
836 if ((i
->date
> oldversion
) && (i
->date
<= newversion
) && ((i
->machines
=="*") || (i
->machines
.find(mid
) != eString::npos
)))
837 pchanges
.insert(std::pair
<int,eString
>(i
->priority
, i
->text
));
839 if (pchanges
.empty())
840 changetext
=_("No new features were added in this release.");
843 changetext
=_("The following new features were added in this release:\n");
844 for (std::map
<int,eString
>::const_iterator
i(pchanges
.begin());
845 i
!= pchanges
.end(); ++i
)
846 changetext
+=" * " + i
->second
+ "\n";
849 changes
->setText(changetext
);
852 eUpgrade::~eUpgrade()