Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f898ac4411 | ||
|
|
c6ee6a8e68 | ||
|
|
1096c8b426 | ||
|
|
97eb4484d9 | ||
|
|
d247e9bdc8 | ||
|
|
c5d3897e77 | ||
|
|
3b68eaf303 | ||
|
|
62e26a81aa | ||
|
|
75abff061a | ||
|
|
17dd99f368 | ||
|
|
89bc4a10a3 | ||
|
|
61a23aff66 | ||
|
|
9b68e43ac1 | ||
|
|
de32a6140a | ||
|
|
55bfee79a2 | ||
|
|
287cb10250 | ||
|
|
08e53f404d | ||
|
|
f3870fd788 | ||
|
|
1b393d1e41 | ||
|
|
1c1bfb9c78 | ||
|
|
0cd7a0c2cc | ||
|
|
79832d9289 | ||
|
|
796dc3a677 | ||
|
|
1c20e5ff5f | ||
|
|
fbd23222b1 | ||
|
|
47bdc71eea | ||
|
|
d9e43ef41c | ||
|
|
3d914ce22b | ||
|
|
2b80f8e620 | ||
|
|
0df9ca3e59 | ||
|
|
3637723661 | ||
|
|
a02caaac15 | ||
|
|
a1febdd2ea | ||
|
|
848e3fe06c | ||
|
|
eb97fad2a7 | ||
|
|
7de5d7fd92 | ||
|
|
032538ec5a | ||
|
|
2c34ec70d2 | ||
|
|
5a6965afef | ||
|
|
acf7e1cad7 | ||
|
|
37844a6b9a | ||
|
|
5c90f39f6e | ||
|
|
5ca1e0c899 | ||
|
|
b997951f97 | ||
|
|
6dae516af2 | ||
|
|
f5a9d273ce | ||
|
|
22f71b0f25 | ||
|
|
f96a530392 | ||
|
|
3e17c94722 | ||
|
|
1eef797e29 | ||
|
|
62bb8e4e28 | ||
|
|
2f7bab98bf | ||
|
|
3480526cde | ||
|
|
7dd8fdb560 | ||
|
|
1bcaf8f79c | ||
|
|
e362f3cab9 | ||
|
|
9ea9bea096 | ||
|
|
1e84b07b39 | ||
|
|
e205b47789 | ||
|
|
1edbc5e52e | ||
|
|
0629204d39 | ||
|
|
a01de09ca5 | ||
|
|
355fe9dc62 | ||
|
|
857123e9e4 | ||
|
|
edb4793863 | ||
|
|
880a3e0846 | ||
|
|
9833f94dad | ||
|
|
cffeb329c4 | ||
|
|
4f6eb6e936 | ||
|
|
1776315097 | ||
|
|
def1d49ab4 | ||
|
|
3e863759d3 | ||
|
|
87202c38a0 | ||
|
|
246394d25b | ||
|
|
6ecc3e2a80 | ||
|
|
9164f331a3 | ||
|
|
d5ff815e72 | ||
|
|
8c624670cc | ||
|
|
51072eb40a | ||
|
|
bd54b19bbf | ||
|
|
69b5278710 | ||
|
|
2e78262c10 | ||
|
|
c03e01879e | ||
|
|
9087b564ba | ||
|
|
8084f68b50 | ||
|
|
1ebc2b8308 | ||
|
|
ae03494a73 | ||
|
|
6665ba9917 | ||
|
|
75df75b4e9 | ||
|
|
82dd535429 | ||
|
|
288726981a | ||
|
|
8635ea66a7 | ||
|
|
cbffb8f924 | ||
|
|
7b5d36bd4c | ||
|
|
067c84ea2c | ||
|
|
29c2b60670 | ||
|
|
09b6b377fe | ||
|
|
a6ec2b36c4 | ||
|
|
2cbeb4d0fe | ||
|
|
116e77bef7 | ||
|
|
2746da7a03 | ||
|
|
3d7b15e30b | ||
|
|
912ec5210e | ||
|
|
6a6a6348f5 | ||
|
|
01ec9928f9 | ||
|
|
bd141d2739 | ||
|
|
463dc3c6dd | ||
|
|
3f96851407 | ||
|
|
10217cd331 | ||
|
|
886b40e4b5 | ||
|
|
99294e1b74 | ||
|
|
5f0b6bb328 | ||
|
|
aa366ea133 | ||
|
|
4ef49e123a | ||
|
|
64505e1b73 | ||
|
|
a9c0daab68 | ||
|
|
420482c6b7 | ||
|
|
09a6405501 | ||
|
|
cc8cca84ef | ||
|
|
e98891e52d | ||
|
|
e66d87fde0 | ||
|
|
e4f7cf7bc5 | ||
|
|
cd9b51ad80 | ||
|
|
2189eebaf0 | ||
|
|
08adc52c78 | ||
|
|
95571860d0 | ||
|
|
f35c4048fe | ||
|
|
d76b5a2b44 | ||
|
|
d8c6a03147 | ||
|
|
fc51f45195 | ||
|
|
26c1c2914e | ||
|
|
230d45c9e3 | ||
|
|
f059663164 | ||
|
|
d9e6d47f1b | ||
|
|
b2bd1d90c7 | ||
|
|
863cf8134a | ||
|
|
6c220a45fd | ||
|
|
ada683ed9b | ||
|
|
5efa0d96b8 | ||
|
|
a321f275ef | ||
|
|
7868ad0c71 | ||
|
|
c0e490cc30 | ||
|
|
15b05dce75 | ||
|
|
e4b4d211c1 | ||
|
|
b0130e52d6 | ||
|
|
6d69da6cd1 | ||
|
|
3666e285dc | ||
|
|
ddb3406855 | ||
|
|
11410296a7 | ||
|
|
d636ef78dd | ||
|
|
0d6b32c371 | ||
|
|
66966a242d | ||
|
|
d1bb1b6094 | ||
|
|
28ca666c6e | ||
|
|
f8ad95ee4d | ||
|
|
f6c9450319 | ||
|
|
2127e08052 | ||
|
|
a072a2cf83 | ||
|
|
3a83d99f9a | ||
|
|
1a89112c25 | ||
|
|
10a2bc6319 | ||
|
|
55c158fc34 | ||
|
|
e41cf5236a | ||
|
|
54ddeb6407 | ||
|
|
8167e841ce | ||
|
|
ad7bab8df8 | ||
|
|
805bafacef | ||
|
|
40cd74c506 | ||
|
|
c92df79829 | ||
|
|
62aa414dc0 | ||
|
|
36aff5fca4 | ||
|
|
d9aeffa1d0 | ||
|
|
d0d249c738 | ||
|
|
db546a17b8 | ||
|
|
d35d6142ca | ||
|
|
2d52d8c3c6 | ||
|
|
1ba42ce46f | ||
|
|
1736afae69 | ||
|
|
0f5f96149f | ||
|
|
e084cdaabe | ||
|
|
89e70ea88c | ||
|
|
2544d42ee2 | ||
|
|
0d1d64bbfe | ||
|
|
26099e9536 | ||
|
|
17c6aefdcb | ||
|
|
ab07fec919 | ||
|
|
0e687beed3 | ||
|
|
131e8bbe1f | ||
|
|
0809303feb | ||
|
|
33d00aa714 | ||
|
|
24a12b2e72 | ||
|
|
6062a736d2 | ||
|
|
6cd01df098 | ||
|
|
8a21acc9cc | ||
|
|
8c1cfe3a6e | ||
|
|
8e2c830433 | ||
|
|
868bee0413 | ||
|
|
d6ad749515 | ||
|
|
83bcb7358c | ||
|
|
67d3e4de70 | ||
|
|
8c5590d150 | ||
|
|
cb25a8bd3e | ||
|
|
3c4c0088f0 | ||
|
|
e75b963d3a | ||
|
|
378dfe3162 | ||
|
|
dddf92646d | ||
|
|
791f805fa0 | ||
|
|
5325bfdfd1 | ||
|
|
3d42ebaf73 | ||
|
|
4ab76a5112 | ||
|
|
f4b0e9b6f3 | ||
|
|
6cf03a9e28 | ||
|
|
ded123141c | ||
|
|
8ea3ba3771 | ||
|
|
0e0844b78b | ||
|
|
a1d95afbf7 | ||
|
|
dc8844f112 | ||
|
|
a67a16479c | ||
|
|
24f34d2f55 | ||
|
|
19a8d76e0c | ||
|
|
aa89ef8dad | ||
|
|
ff7a89b781 | ||
|
|
8eb58ad08c | ||
|
|
32f2e53304 | ||
|
|
f79b653523 | ||
|
|
cc6e2dcfcd | ||
|
|
adbe2dabad | ||
|
|
4b7769a67d | ||
|
|
27acbb09a5 | ||
|
|
b142205f1c | ||
|
|
e4858deccd | ||
|
|
3ce8ca13f1 | ||
|
|
ad68e324c6 | ||
|
|
34b55a222e | ||
|
|
bc9441ddd6 | ||
|
|
6e0941a3c4 | ||
|
|
603a64757d | ||
|
|
2002ba27a2 | ||
|
|
01a7da1d95 | ||
|
|
70c09fb5b7 | ||
|
|
29084d4acf | ||
|
|
0d76941600 | ||
|
|
5dc162bc4a | ||
|
|
564b0715f1 | ||
|
|
6e710dcac9 | ||
|
|
b2883167d5 | ||
|
|
1b99ad115a | ||
|
|
9baad78435 | ||
|
|
d2ce7052ec | ||
|
|
d29c63cac9 | ||
|
|
f597e28a87 | ||
|
|
a0eff48f30 | ||
|
|
5310efb16c | ||
|
|
01239ea839 | ||
|
|
b4cbab6774 | ||
|
|
366680af1b | ||
|
|
4de49acb49 | ||
|
|
238f92ab25 | ||
|
|
71b63c29d3 | ||
|
|
e7de4ffe34 | ||
|
|
b581c7f25d | ||
|
|
d10814e808 | ||
|
|
b582869208 | ||
|
|
dd2c6b7f18 | ||
|
|
5b17b8e398 | ||
|
|
d96a54994e | ||
|
|
b80dfdc657 | ||
|
|
d06e88ce39 | ||
|
|
df9fae0c0e | ||
|
|
3fed685e79 | ||
|
|
ef4a506905 | ||
|
|
1a7d30cebf | ||
|
|
ea52c0509a | ||
|
|
01726cddc5 | ||
|
|
cd52b36d38 | ||
|
|
7ab41812ea | ||
|
|
2cab7a9c80 | ||
|
|
3ead19bdea | ||
|
|
03eeca994d | ||
|
|
b596e97926 | ||
|
|
589443a356 | ||
|
|
869a872897 | ||
|
|
48fc14c913 | ||
|
|
37f5d06973 | ||
|
|
f8d3fa0ecd | ||
|
|
f62628bf29 | ||
|
|
8301455a5b | ||
|
|
860d71d18a | ||
|
|
48384d4e47 | ||
|
|
ce177a9588 | ||
|
|
2421b9f6c2 | ||
|
|
eac07b18d9 | ||
|
|
418f3cfd4b | ||
|
|
3f0d6f85d3 | ||
|
|
027a6d9a18 | ||
|
|
58c0dbe275 | ||
|
|
2110196958 | ||
|
|
9195f3c7da | ||
|
|
4f92794cdf | ||
|
|
535561efbf | ||
|
|
5da30a5bc5 | ||
|
|
8fdba437af | ||
|
|
583cc8a963 | ||
|
|
491f06015b | ||
|
|
1aca3bef85 | ||
|
|
b4575a40fc | ||
|
|
8bc521f3e5 | ||
|
|
b1cfc3181b | ||
|
|
1ddf269c69 | ||
|
|
dc910a5317 | ||
|
|
34c8fb057d | ||
|
|
04f9369ace | ||
|
|
b0f69c8b6b | ||
|
|
dc4fd72133 | ||
|
|
20eed53d8c | ||
|
|
e2aaa2cb40 | ||
|
|
4d7899fa40 | ||
|
|
3f975a93b3 | ||
|
|
5f4476566d | ||
|
|
b7206abf11 | ||
|
|
034b17cef4 | ||
|
|
3a1053b29e | ||
|
|
fc3a613276 | ||
|
|
5a96158322 | ||
|
|
3d427bfd77 | ||
|
|
edac98d26e | ||
|
|
83c25d7eb2 | ||
|
|
2ddb2923c6 | ||
|
|
32a59f4279 | ||
|
|
fc6bacdb94 | ||
|
|
680fd91de8 | ||
|
|
288cad1c2e | ||
|
|
4115aab13d | ||
|
|
fbdac811fc | ||
|
|
d15412a788 | ||
|
|
85fdbfb354 | ||
|
|
11e32133b0 | ||
|
|
1f3c790d87 | ||
|
|
6521a8e9d1 | ||
|
|
3728cdea31 | ||
|
|
c1d909c415 | ||
|
|
579dbe9837 | ||
|
|
ed3cb1d3f8 | ||
|
|
ea97ac427e | ||
|
|
a3af55acb4 | ||
|
|
83b41f9371 | ||
|
|
c46961d511 | ||
|
|
ec71146727 | ||
|
|
43d8d45919 | ||
|
|
f299486ef9 | ||
|
|
1515b7c7c1 | ||
|
|
ed37b5ee62 | ||
|
|
d0f9d78335 | ||
|
|
3e13254858 | ||
|
|
5e3de1ba06 | ||
|
|
5b5425e0d0 | ||
|
|
60f2337927 | ||
|
|
196f1f7abb | ||
|
|
300635ad8f |
No files matched your search
@@ -0,0 +1,2 @@
|
|||||||
|
Copyright (C) 2007-2010 pancake <pancake@youterm.com>
|
||||||
|
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
Installation instructions:
|
||||||
|
==========================
|
||||||
|
|
||||||
|
To build the flasher you will need gcc, make and libusb. For crosscompiling
|
||||||
|
to arm you can use scratchbox. But you will probably need the libusb.so of
|
||||||
|
the scratchbox environment to the device.
|
||||||
|
|
||||||
|
Just type:
|
||||||
|
|
||||||
|
$ make
|
||||||
|
|
||||||
|
The most interesting targets for make are:
|
||||||
|
|
||||||
|
all normal build
|
||||||
|
install installs into /usr/local by default
|
||||||
|
uninstall remove installed files
|
||||||
|
clean clean compilation objects and generated binaries
|
||||||
|
|
||||||
|
|
||||||
|
The installation procedure is quite simple and you can define a new PREFIX
|
||||||
|
manually from the command line:
|
||||||
|
|
||||||
|
$ sudo make install PREFIX=/usr
|
||||||
|
|
||||||
|
The default one is /usr/local (not very userfriendly but standards are
|
||||||
|
standards :P hehe)
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
------. ,---------.--.--.
|
------. ,---------.--.--.
|
||||||
/ | ___ | | | \\------------ -- .
|
/ | ___ | | | \\------------ -- .
|
||||||
| .__ / \/ . ____/ _/ _/ The 0pen
|
| .__ / \/ . ____/ _/ _/ The 0pen
|
||||||
@@ -11,21 +10,40 @@
|
|||||||
_/ ___|_.|__|
|
_/ ___|_.|__|
|
||||||
'`
|
'`
|
||||||
|
|
||||||
The 'Free Fiasco Firmware Flasher' aka 0xFFFF utility tries to implement
|
0xFFFF is Open Free Fiasco Firmware Flasher for Maemo devices. It support
|
||||||
a free (GPL'd) userspace handler for the NOLO bootloader.
|
generating and unpacking FIASCO images on local computer. Useful for editing
|
||||||
|
Maemo firmware package for future flash. It support via USB flashing any image
|
||||||
|
type to Maemo device and also \"cold\" flashing which means flashing dead device
|
||||||
|
with erased bootloader. There is support for booting kernel via USB without
|
||||||
|
flashing to NAND and also changing configuration of Maemo device (enable/disable
|
||||||
|
R&D mode, changing HW revision strings, ...).
|
||||||
|
|
||||||
|
0xFFFF is alternative tool to proprietary Nokia flasher-3.5 and fiasco-gen.
|
||||||
|
0xFFFF generate compatible FIASCO images and also accept FIASCO images generated
|
||||||
|
by Nokia fiasco-gen.
|
||||||
|
|
||||||
Use it with CARE. This is an experimental tool and it can brick your device.
|
Use it with CARE. This is an experimental tool and it can brick your device.
|
||||||
It's not suposed to be stable, so nokia will probably release incompatible
|
It's not suposed to be stable, so nokia will probably release incompatible
|
||||||
bootloaders to break this tool. USE IT AT YOUR OWN RISK.
|
bootloaders to break this tool. USE IT AT YOUR OWN RISK.
|
||||||
|
|
||||||
This tool has been designed and tested on n770. The n800 flash should work
|
|
||||||
but it's not tested and is known to use different request codes.
|
|
||||||
|
|
||||||
PLEASE. Read carefully all the documentation inside doc/* for more information
|
PLEASE. Read carefully all the documentation inside doc/* for more information
|
||||||
before building or using the flasher to avoid questions, problems or so.
|
before building or using the flasher to avoid questions, problems or so.
|
||||||
|
|
||||||
|
Feel free to join to the mailing list and visit the homepage for more info:
|
||||||
|
|
||||||
|
0xffff@lists.nopcode.org
|
||||||
|
http://www.nopcode.org/0xFFFF
|
||||||
|
|
||||||
|
-----------8<---------------------------------------------------------------
|
||||||
|
|
||||||
|
Build:
|
||||||
|
$ make
|
||||||
|
|
||||||
|
To install: (by default is /usr/local)
|
||||||
|
$ make install PREFIX=/usr DESTDIR=/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Have phun!
|
Have phun!
|
||||||
|
|
||||||
|
|
||||||
--pancake
|
--pancake
|
||||||
|
--Pali
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
cal:
|
||||||
|
* Write support
|
||||||
|
|
||||||
|
cold-flash:
|
||||||
|
* Detect device from asic id
|
||||||
|
|
||||||
|
device:
|
||||||
|
* Support for Nokia N950 and Nokia N9
|
||||||
|
|
||||||
|
disk:
|
||||||
|
* Everything (work with eMMC images in USB Mass storage mode)
|
||||||
|
|
||||||
|
fiasco:
|
||||||
|
* Support for Harmattan images
|
||||||
|
|
||||||
|
image:
|
||||||
|
* Support for Harmattan images
|
||||||
|
|
||||||
|
local:
|
||||||
|
* Support for flashing (on device)
|
||||||
|
|
||||||
|
mkii:
|
||||||
|
* Everything (flashing protocol for eMMC images)
|
||||||
|
|
||||||
|
nolo:
|
||||||
|
* Support for dumping images (it is possible?)
|
||||||
|
* Implement functions for setting nolo, kernel, initfs and content versions (it is possible?)
|
||||||
|
|
||||||
|
operations:
|
||||||
|
* Enable FLASH_DISK protocol when implemented
|
||||||
|
|
||||||
|
usb-device:
|
||||||
|
* Autodetect devices from product string
|
||||||
|
* Enable FLASH_DISK and FLASH_MKII protocols when implemented
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
VERSION = 0.6
|
||||||
|
PREFIX = /usr/local
|
||||||
|
|
||||||
|
# NetBSD stuff
|
||||||
|
#CPPFLAGS += -I/usr/pkg/include
|
||||||
|
#LDFLAGS += -L/usr/pkg/lib -Wl,-R/usr/pkg/lib
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
0xffff (0.6-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* This is new rewritten version of original 0xFFFF 0.5 tool
|
||||||
|
|
||||||
|
-- Pali Rohár <pali.rohar@gmail.com> Sun, 07 Apr 2013 15:01:50 +0200
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
7
|
||||||
Vendored
+25
@@ -0,0 +1,25 @@
|
|||||||
|
Source: 0xffff
|
||||||
|
Section: utils
|
||||||
|
Priority: extra
|
||||||
|
Maintainer: Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
Build-Depends: debhelper (>= 7), libusb-dev
|
||||||
|
Standards-Version: 3.9.3
|
||||||
|
|
||||||
|
Package: 0xffff
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||||
|
Description: Open Free Fiasco Firmware Flasher
|
||||||
|
0xFFFF is Open Free Fiasco Firmware Flasher for Maemo devices. It support
|
||||||
|
generating and unpacking FIASCO images on local computer. Useful for editing
|
||||||
|
Maemo firmware package for future flash. It support via USB flashing any image
|
||||||
|
type to Maemo device and also "cold" flashing which means flashing dead
|
||||||
|
device with erased bootloader. There is support for booting kernel via USB
|
||||||
|
without flashing to NAND and also changing configuration of Maemo device
|
||||||
|
(enable/disable R&D mode, changing HW revision strings, ...).
|
||||||
|
.
|
||||||
|
0xFFFF is alternative tool to proprietary Nokia flasher-3.5 and fiasco-gen.
|
||||||
|
0xFFFF generate compatible FIASCO images and also accept FIASCO images
|
||||||
|
generated by Nokia fiasco-gen.
|
||||||
|
.
|
||||||
|
Supported Maemo devices:
|
||||||
|
Nokia 770, Nokia N800, Nokia N810, Nokia N810 WiMAX, Nokia N900
|
||||||
Vendored
+29
@@ -0,0 +1,29 @@
|
|||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: 0xffff
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2007-2012 pancake <pancake@youterm.com>
|
||||||
|
2011 Michael Buesch <mb@bu3sch.de>
|
||||||
|
2011-2013 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
License: GPL-3.0+
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2013 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
License: GPL-3.0+
|
||||||
|
|
||||||
|
License: GPL-3.0+
|
||||||
|
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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
.
|
||||||
|
This package 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
|
||||||
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
README
|
||||||
|
doc/*
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
# -*- makefile -*-
|
||||||
|
|
||||||
|
# Uncomment this to turn on verbose mode.
|
||||||
|
#export DH_VERBOSE=1
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@
|
||||||
|
|
||||||
|
override_dh_auto_install:
|
||||||
|
dh_auto_install -- PREFIX=/usr
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
3.0 (quilt)
|
||||||
+54
-28
@@ -1,36 +1,16 @@
|
|||||||
<b>Dumping the firmware</b>
|
Dumping the firmware:
|
||||||
|
|
||||||
This technique consists on reconstructing a firmware image dumping
|
This technique consists on reconstructing a firmware image dumping
|
||||||
pieces at certains offsets of the device internal memory.
|
pieces at certain offsets of the device internal memory.
|
||||||
|
|
||||||
|
Technical details:
|
||||||
|
|
||||||
<b>End user details:</b>
|
* The internal flash memory is exposed to the system as MTD devices.
|
||||||
|
* Is possible to dump the individual sections of a flashed firmware.
|
||||||
* Extract the firmware pieces from a running device
|
|
||||||
*
|
*
|
||||||
* This functionality is useful to extract backups of your system
|
* READ src/local.c for detailed information.
|
||||||
* firmware. This is really useful when you're on a desert island
|
|
||||||
* without an internet connection.
|
|
||||||
*
|
|
||||||
* This tool needs more testing, so take care and don't blame me if
|
|
||||||
* it breaks your system. It *is* to your responsability, use at
|
|
||||||
* your own risk
|
|
||||||
*
|
|
||||||
* NOTE: It's theorically possible to flash the device on the fly from
|
|
||||||
* the running OS, but this has not yet been tested. Keep tuned for
|
|
||||||
* updates and newz.
|
|
||||||
*
|
|
||||||
* Have fun!
|
|
||||||
|
|
||||||
|
mtd0 - contains xloader and secondary pieces of the bootloaders
|
||||||
<b>Technical details:</b>
|
|
||||||
|
|
||||||
* The internal flash memory is exposed to the system as MTD devices. So it's
|
|
||||||
* possible to dump the individual sections of a flashed firmware.
|
|
||||||
*
|
|
||||||
* READ src/dump.c for detailed information.
|
|
||||||
|
|
||||||
mtd0 - contains xloader and sencodary pieces of the bootloaders
|
|
||||||
0x00000 - xloader.bin (size is 0x03600)
|
0x00000 - xloader.bin (size is 0x03600)
|
||||||
0x04000 - secondary.bin (size is 0x15400)
|
0x04000 - secondary.bin (size is 0x15400)
|
||||||
0x1FFFF - eof
|
0x1FFFF - eof
|
||||||
@@ -40,6 +20,52 @@ pieces at certains offsets of the device internal memory.
|
|||||||
mtd2 - starts with NOLO img\x5c\x13 and \x00 padding
|
mtd2 - starts with NOLO img\x5c\x13 and \x00 padding
|
||||||
0x00800 - zImage
|
0x00800 - zImage
|
||||||
|
|
||||||
mtd3 - rootfs.jffs2 (20M) aka 0x200000 vs 0x3900000
|
> NOLO is a four byte marker, next four bytes
|
||||||
|
> can vary since it is kernel image size
|
||||||
|
|
||||||
|
mtd3 - initfs.jffs2 (2M) aka 0x200000 vs 0x3900000
|
||||||
|
|
||||||
mtd4 - rootfs.jffs2 (a fucking copy of the above rootfs?)
|
mtd4 - rootfs.jffs2 (a fucking copy of the above rootfs?)
|
||||||
|
|
||||||
|
For dumping mtd partition is used tool nanddump. Here is example how to dump
|
||||||
|
kernel image without padding to file zImage:
|
||||||
|
|
||||||
|
$ nanddump -i -o -b -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2
|
||||||
|
|
||||||
|
Params means:
|
||||||
|
-i - "Ignore errors"
|
||||||
|
-o - "Omit oob data"
|
||||||
|
-b - "Omit bad blocks"
|
||||||
|
-s - "Start address"
|
||||||
|
-l - "Length"
|
||||||
|
-f - "Output file"
|
||||||
|
|
||||||
|
Please note that some new versions of nanddump have some options removed and
|
||||||
|
some are enabled by default. Before using check params of your nanddump version.
|
||||||
|
|
||||||
|
|
||||||
|
// Extra notes //
|
||||||
|
|
||||||
|
[MTD] NAND Consolidate oobinfo handling
|
||||||
|
|
||||||
|
The info structure for out of band data was copied into
|
||||||
|
the mtd structure. Make it a pointer and remove the ability
|
||||||
|
to set it from userspace. The position of ecc bytes is
|
||||||
|
defined by the hardware and should not be changed by software.
|
||||||
|
|
||||||
|
// The oob stuff
|
||||||
|
|
||||||
|
In mtd3 the OOB data is 64 bytes aka 0x40, and this oob stuff
|
||||||
|
appears every 2KB aka 0x800 bytes.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obsolete legacy interface. Keep it in order not to break userspace
|
||||||
|
* interfaces
|
||||||
|
*/
|
||||||
|
struct nand_oobinfo {
|
||||||
|
uint32_t useecc;
|
||||||
|
uint32_t eccbytes;
|
||||||
|
uint32_t oobfree[8][2];
|
||||||
|
uint32_t eccpos[32];
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
Via USB:
|
||||||
|
|
||||||
|
Identify device:
|
||||||
|
$ 0xFFFF -I
|
||||||
|
|
||||||
|
Load kernel & initfs and boot it with cmdline:
|
||||||
|
$ 0xFFFF -m initfs:<file> -m kernel:<file> -l -b "<cmdline>"
|
||||||
|
|
||||||
|
Flash kernel and reboot:
|
||||||
|
$ 0xFFFF -m kernel:<file> -f -r
|
||||||
|
|
||||||
|
Flash FIASCO image and reboot:
|
||||||
|
$ 0xFFFF -M <file> -f -r
|
||||||
|
|
||||||
|
Flash only kernel from FIASCO image and reboot:
|
||||||
|
$ 0xFFFF -M <file> -t kernel -f -r
|
||||||
|
|
||||||
|
Cold-Flash 2nd and secondary bootloaders:
|
||||||
|
$ 0xFFFF -m 2nd:<file> -m secondary:<file> -c
|
||||||
|
|
||||||
|
|
||||||
|
On device (need nanddump from mtd-utils):
|
||||||
|
|
||||||
|
Dump all images to current directory:
|
||||||
|
$ 0xFFFF -e
|
||||||
|
|
||||||
|
Dump all images to one FIASCO file:
|
||||||
|
$ 0xFFFF -E <file>
|
||||||
|
|
||||||
|
|
||||||
|
FIASCO packaging:
|
||||||
|
|
||||||
|
Show FIASCO image content:
|
||||||
|
$ 0xFFFF -M <file> -i
|
||||||
|
|
||||||
|
Unpack FIASCO image to current directory:
|
||||||
|
$ 0xFFFF -M <file> -u
|
||||||
|
|
||||||
|
Generate new FIASCO image image.fiasco from files xloader.bin, nolo.bin, zImage, rootfs and append device&version information (xloader for RX-51 hw revision: 2101 and 2102, version 1.0)
|
||||||
|
$ 0xFFFF -m RX-51:2101,2102:1.0:xloader:xloader.bin -m RX-51:2101,2102:1.0:secondary:nolo.bin -m 2.6.28:kernel:zImage -m rootfs -g image.fiasco
|
||||||
@@ -1,70 +1,35 @@
|
|||||||
<b>FAQ</b>
|
FAQ:
|
||||||
|
|
||||||
This file tries to collect a bunch of common questions/answers about flashing
|
*) How can I set my Internet Tablet into RD mode with 0xFFFF?
|
||||||
|
|
||||||
<b>*) Why implement a free software flasher?</b>
|
Just type '0xFFFF -R 1' as root
|
||||||
|
|
||||||
The Nokia Internet Tablets are based on Free Software (software libre), but
|
|
||||||
not everything included *is* free software, for instance, the firmware flasher
|
|
||||||
tool.
|
|
||||||
|
|
||||||
The 0xFFFF project aims to feed the minds of those who really want to
|
|
||||||
understand how these gadgets work internally, free the knowledge to
|
|
||||||
avoid the restrictions and fill the lack of information on the most
|
|
||||||
important part of the system.
|
|
||||||
|
|
||||||
That's it, now you can build and run this flasher on *BSD, w32, MacOSX on ARM,
|
|
||||||
powerpc, x86, mips, etc...
|
|
||||||
|
|
||||||
|
|
||||||
<b>*) Can I brick my device?</b>
|
*) How can I unpack a FIASCO firmware?
|
||||||
|
|
||||||
Of course! You're free to do what you want with your device :)
|
Just type '0xFFFF -M FiascoFirmware.bin -u'
|
||||||
|
|
||||||
Seriously. Flashing a device is not a safe thing, so I give no warranty
|
|
||||||
of what will happen to your device when using this tool.
|
|
||||||
|
|
||||||
BTW, after a huge number of tests I can say that these devices are hard
|
|
||||||
to brick, but if you are scared about bricking your device you should
|
|
||||||
use the flasher provided by Nokia, it's better for your heart's health.
|
|
||||||
|
|
||||||
|
|
||||||
<b>*) What can I do with 0xFFFF?</b>
|
*) How can I flash a new rootfs?
|
||||||
|
|
||||||
Actually 0xFFFF allows you to:
|
# 0xFFFF -m rootfs.jffs2 -f
|
||||||
|
|
||||||
- flash separated pieces of the firmware.
|
|
||||||
- retrieve information about the device
|
|
||||||
- reboot de mother board
|
|
||||||
- extract the current firmware pieces from the device (reverse flash)
|
|
||||||
- set the USB host/slave mode
|
|
||||||
- set the R&R mode
|
|
||||||
- identify firmware pieces
|
|
||||||
|
|
||||||
|
|
||||||
<b>*) What is NOLO?</b>
|
*) How can I flash a full FIASCO image?
|
||||||
|
|
||||||
NOLO is the 'server-side' part of the flasher from Nokia. NOLO means
|
# 0xFFFF -M FiascoFirmware.fiasco -f
|
||||||
NOkia LOader and it's composed by two pieces of the firmware that are
|
|
||||||
flashed together.
|
|
||||||
|
|
||||||
On the n800 firmwares, these two pieces are distributed in a single
|
|
||||||
file, but when flashing a n770, NOLO requires to provide the xloader
|
|
||||||
(without commiting) and then the secondary piece.
|
|
||||||
|
|
||||||
This piece of software is closed source and is the responsable of
|
|
||||||
handling the requests from the client-side flasher. It provides a
|
|
||||||
query-like interface via usb control messages for doing different
|
|
||||||
actions on the device.
|
|
||||||
|
|
||||||
|
|
||||||
<b>*) How can I identify my device?</b>
|
Advanced commands:
|
||||||
|
|
||||||
Theorically n770 and n800 have different USB device ID, but this is not
|
*) How to extract the firmware pieces from a running device?
|
||||||
true at all. The first series of the n800 comes with the same usb-id
|
|
||||||
than n770. That's weird!
|
|
||||||
|
|
||||||
So, the only way to identify the device is by asking nolo for the version
|
It is possible to dump the firmware pieces from the internal MTD to reconstruct a FIASCO image.
|
||||||
information of different pieces of the firmware. This can be faked, because
|
To do this recompile the flasher for ARM and run this command in the device:
|
||||||
you can flash n770 stuff on n800 and viceversa, but it's not recommended
|
|
||||||
because it wouldn't work :)
|
# mkdir /media/mmc1/backup
|
||||||
|
# 0xFFFF -e /media/mmc1/backup
|
||||||
|
|
||||||
|
To dump directly into FIASCO image run:
|
||||||
|
|
||||||
|
# 0xFFFF -E /media/mmc1/backup.fiasco
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
FAQ2:
|
||||||
|
|
||||||
|
This file tries to collect a bunch of common questions/answers about flashing
|
||||||
|
|
||||||
|
|
||||||
|
*) Why implement a free software flasher?
|
||||||
|
|
||||||
|
The Nokia Internet Tablets are based on Free Software (software libre), but
|
||||||
|
not everything included *is* free software, for instance, the firmware flasher
|
||||||
|
tool.
|
||||||
|
|
||||||
|
The 0xFFFF project aims to feed the minds of those who really want to
|
||||||
|
understand how these gadgets work internally, free the knowledge to
|
||||||
|
avoid the restrictions and fill the lack of information on the most
|
||||||
|
important part of the system.
|
||||||
|
|
||||||
|
That's it, now you can build and run this flasher on *BSD, w32, MacOSX on ARM,
|
||||||
|
powerpc, x86, mips, etc...
|
||||||
|
|
||||||
|
|
||||||
|
*) Can I brick my device?
|
||||||
|
|
||||||
|
Of course! You're free to do what you want with your device :)
|
||||||
|
|
||||||
|
Seriously. Flashing a device is not a safe thing, so I give no warranty
|
||||||
|
of what will happen to your device when using this tool.
|
||||||
|
|
||||||
|
BTW, after a huge number of tests I can say that these devices are hard
|
||||||
|
to brick, but if you are scared about bricking your device you should
|
||||||
|
use the flasher provided by Nokia, it's better for your heart's health.
|
||||||
|
|
||||||
|
|
||||||
|
*) What can I do with 0xFFFF?
|
||||||
|
|
||||||
|
Actually 0xFFFF allows you to:
|
||||||
|
|
||||||
|
- flash separated pieces of the firmware
|
||||||
|
- flash full FIASCO image
|
||||||
|
- load kernel & initfs without flashing
|
||||||
|
- cold-flash bricked device (without NOLO)
|
||||||
|
- retrieve information about the device
|
||||||
|
- reboot de mother board
|
||||||
|
- extract the current firmware pieces from the device (dump)
|
||||||
|
- set the USB host/slave mode
|
||||||
|
- set the R&R mode and flags
|
||||||
|
- pack/unpack FIASCO firmwares
|
||||||
|
- automatic piece identifier
|
||||||
|
|
||||||
|
|
||||||
|
*) What is NOLO?
|
||||||
|
|
||||||
|
NOLO is the 'server-side' part of the flasher from Nokia. NOLO means
|
||||||
|
NOkia LOader and it's composed by two pieces of the firmware that are
|
||||||
|
flashed together.
|
||||||
|
|
||||||
|
On the n800 firmwares, these two pieces are distributed in a single
|
||||||
|
file, but when flashing a 770, NOLO requires to provide the xloader
|
||||||
|
(without committing) and then the secondary piece.
|
||||||
|
|
||||||
|
This piece of software is closed source and is the responsible of
|
||||||
|
handling the requests from the client-side flasher. It provides a
|
||||||
|
query-like interface via usb control messages for doing different
|
||||||
|
actions on the device.
|
||||||
|
|
||||||
|
|
||||||
|
*) How can I identify my device?
|
||||||
|
|
||||||
|
Theoretically 770 and n800 have different USB device ID, but this is not
|
||||||
|
true at all. The first series of the n800 comes with the same usb-id
|
||||||
|
than 770. That's weird!
|
||||||
|
|
||||||
|
So, the only way to identify the device is by asking nolo for the version
|
||||||
|
information of different pieces of the firmware. This can be faked, because
|
||||||
|
you can flash 770 stuff on n800 and viceversa, but it's not recommended
|
||||||
|
because it wouldn't work :)
|
||||||
|
|
||||||
|
|
||||||
|
*) Can I unpack FIASCO blobs?
|
||||||
|
|
||||||
|
Yes, last version of 0xFFFF has full support of FIASCO images.
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
Copyright (C) 2007-2011 pancake <pancake@youterm.com>
|
||||||
|
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
SPECS FOR THE FIASCO FIRMWARE FILE FORMAT ffff!
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
This is final working version of FIASCO format. FIASCO image which
|
||||||
|
is generated by this spec is acceptable by Nokia flasher-3.5 and
|
||||||
|
unpack data same as FIASCO image generated by Nokia fiasco-gen. This
|
||||||
|
format is implemented in 0xFFFF and every image which I tested
|
||||||
|
(generated by 0xFFFF and fiasco-gen) was properly unpacked under
|
||||||
|
0xFFFF and flasher-3.5 with same result. Small difference is that
|
||||||
|
fiasco-gen add some unknown subsection block to image header
|
||||||
|
(type '4' or '/') which contains some messy characters... But if
|
||||||
|
these sections missing, flasher-3.5 working fine too. And old FIASCO
|
||||||
|
images (for N8x0) does not have these subsection...
|
||||||
|
|
||||||
|
|
||||||
|
FILE HEADER
|
||||||
|
|
||||||
|
1 byte = 0xb4 -- signature
|
||||||
|
4 bytes -- FW header length (big endian)
|
||||||
|
|
||||||
|
|
||||||
|
FW HEADER
|
||||||
|
|
||||||
|
4 bytes -- number of FW header blocks (big endian)
|
||||||
|
block {
|
||||||
|
1 byte -- type of block
|
||||||
|
0xE8 - Fiasco name
|
||||||
|
0x31 - FW name
|
||||||
|
1 byte -- length of block data
|
||||||
|
N bytes -- block data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IMAGE
|
||||||
|
|
||||||
|
1 byte = 0x54 -- signature
|
||||||
|
1 byte -- number of subsection blocks + 1
|
||||||
|
5 bytes -- unknown (always 0x2e 0x19 0x01 0x01 0x00)
|
||||||
|
2 bytes -- checksum for the image contents (xorpair) (big endian)
|
||||||
|
12 bytes -- image name type (first byte is FF if is the last image)
|
||||||
|
4 bytes -- length of image data (big endian)
|
||||||
|
4 bytes -- unknown (always 0x00 0x00 0x00 0x00)
|
||||||
|
block {
|
||||||
|
1 byte -- type of subsection block
|
||||||
|
'1' - version
|
||||||
|
'2' - device & hw revisions (size of device is 16, hw revision 8)
|
||||||
|
'3' - layout
|
||||||
|
'4' - unknown
|
||||||
|
'/' - unknown
|
||||||
|
1 byte -- length of subsection block
|
||||||
|
N bytes -- subsection block data
|
||||||
|
}
|
||||||
|
1 byte -- unknown (0x00 is accepted, maybe end of subsections?)
|
||||||
|
N bytes -- image data
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
It is possible to flash directly from the device, so this brings the possibility
|
||||||
|
to completely replace the bootloader flasher by a userland one with extended
|
||||||
|
features for backuping and recovering data.
|
||||||
|
|
||||||
|
The way to flash is using mtd-utils:
|
||||||
|
|
||||||
|
$ flash_eraseall -j /dev/mtd3
|
||||||
|
$ nandwrite -a -p /dev/mtd3 initfs.jffs2
|
||||||
|
|
||||||
|
This is an specific example plagied from initfs_flasher of bootmenu.
|
||||||
|
|
||||||
|
The '-j' flag says that this is a jffs2 partition. Theoretically this
|
||||||
|
flag is not required for zImage, and the bootloader pieces.
|
||||||
|
|
||||||
|
The '-a' creates the OOB data automatically, and the '-p' flag pads
|
||||||
|
the data to fill the block.
|
||||||
|
|
||||||
|
These flags are only fine for initfs, so this will be probably wrong
|
||||||
|
for other pieces. Using the dump functionality you can check if you
|
||||||
|
have flashed properly every piece inside the device, but keep in mind
|
||||||
|
that it is dangerous and you can brick your device.
|
||||||
|
|
||||||
|
But feel free to send feedback to provide a full support for local
|
||||||
|
flashing on 770 and n800.
|
||||||
|
|
||||||
|
|
||||||
|
Nokia N900 using ubi layout on top of /dev/mtd5 rootfs partition. Therefor
|
||||||
|
formatting rootfs should be done via ubiformat tool which preserve erase counters.
|
||||||
|
|
||||||
|
Erasing N900 rootfs:
|
||||||
|
|
||||||
|
$ ubiformat /dev/mtd5
|
||||||
|
|
||||||
|
Flashing new ubi image to N900 rootfs:
|
||||||
|
|
||||||
|
$ ubiformat /dev/mtd5 -s 512 -O 512 -f image.ubi
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
Mk II protocol is the only protocol which can be used to flash eMMC images.
|
||||||
|
NOLO does not support eMMC, so flashing eMMC is done in Maemo system. NOLO
|
||||||
|
will boot device into "update" mode and Maemo will start only softupd daemon
|
||||||
|
(which is responsible for flashing from Maemo system) and load kernel driver
|
||||||
|
g_softupd which handle USB communication to user space daemon. When device
|
||||||
|
is in PC Suite mode Maemo system start softupd daemon and load kernel driver
|
||||||
|
g_nokia which can also handle communication via Mk II protocol.
|
||||||
|
|
||||||
|
Default Maemo flasher (v2.5.2 (Oct 21 2009)) support only some basic functions
|
||||||
|
via Mk II protocol - it can send eMMC image to softupd server which flash it.
|
||||||
|
But there is unofficial Maemo flasher (flasher v2.8.2 (Jan 8 2010)) distributed
|
||||||
|
with omap aes kernel driver for Nokia RX-51 under name "flasher.rover" which
|
||||||
|
support more functions. So "flasher.rover" is better for RE this protocol.
|
||||||
|
|
||||||
|
Via Mk II protocol over usb with softupd daemon in device it is possible to
|
||||||
|
flash any type of image except rootfs (xloader, secondary, kernel, mmc,
|
||||||
|
cmt-2nd, cmt-algo, cmt-mcusw). Maemo system using same Mk II protocol over
|
||||||
|
local TCP socket (server also provided by softupd) to update/flash system.
|
||||||
|
|
||||||
|
Over usb are used only these functions for communication:
|
||||||
|
|
||||||
|
usb_claim_interface (interface=1)
|
||||||
|
usb_set_altinterface (alternate=1)
|
||||||
|
|
||||||
|
usb_bulk_write (ep=1, timeout=5000)
|
||||||
|
usb_bulk_read (ep=129, timeout=5000)
|
||||||
|
|
||||||
|
For every (request) message which is send by host, server send back response.
|
||||||
|
Format of message every message is same. It has 6 bytes header and (at least)
|
||||||
|
4 bytes body.
|
||||||
|
|
||||||
|
HEADER
|
||||||
|
|
||||||
|
4 bytes -- type of header
|
||||||
|
0x8810001B - out (sent by host: usb_bulk_write)
|
||||||
|
0x8800101B - in (received by host: usb_bulk_read)
|
||||||
|
2 bytes -- size of body (big endian)
|
||||||
|
|
||||||
|
BODY
|
||||||
|
|
||||||
|
4 bytes -- type of message
|
||||||
|
N bytes -- data
|
||||||
|
|
||||||
|
Reply message data always starts with char 0x00 (except pong response).
|
||||||
|
|
||||||
|
Here are some sniffed messages from Nokia RX-51. First two messages seems to
|
||||||
|
must be always protocol version exchange (first host ask for protocol version of
|
||||||
|
server and then host send its protocol version). On RX-51 is used version "2".
|
||||||
|
|
||||||
|
Ping:
|
||||||
|
req_type = 0x00000000
|
||||||
|
res_type = 0x20000000
|
||||||
|
|
||||||
|
Get protocol version:
|
||||||
|
req_type = 0x01010000
|
||||||
|
req_data = "/update/protocol_version"
|
||||||
|
res_type = 0x21010000
|
||||||
|
res_data = 0x00 "2"
|
||||||
|
|
||||||
|
Tell our protocol version:
|
||||||
|
req_type = 0x02020000
|
||||||
|
req_data = "/update/host_protocol_version" 0x00 "2"
|
||||||
|
res_type = 0x22020000
|
||||||
|
res_data = 0x00
|
||||||
|
|
||||||
|
Get device:
|
||||||
|
req_type = 0x01030000
|
||||||
|
req_data = "/device/product_code"
|
||||||
|
res_type = 0x21030000
|
||||||
|
res_data = 0x00 "RX-51"
|
||||||
|
|
||||||
|
Get hwrev:
|
||||||
|
req_type = 0x01040000
|
||||||
|
req_data = "/device/hw_build"
|
||||||
|
res_type = 0x21040000
|
||||||
|
res_data = 0x00 "2101"
|
||||||
|
|
||||||
|
Get image types:
|
||||||
|
req_type = 0x01050000
|
||||||
|
req_data = "/update/supported_images"
|
||||||
|
res_type = 0x21050000
|
||||||
|
res_data = 0x00 "xloader,secondary,kernel,mmc,cmt-2nd,cmt-algo,cmt-mcusw"
|
||||||
|
|
||||||
|
Reboot device:
|
||||||
|
req_type = 0x0C060000
|
||||||
|
req_data = "reboot"
|
||||||
|
res_type = 0x2C060000
|
||||||
|
res_data = 0x00
|
||||||
+12
-19
@@ -1,4 +1,4 @@
|
|||||||
<b>Nokia tips</b>
|
Nokia tips:
|
||||||
|
|
||||||
When developing this tool I've found some bugs and misfeatures that
|
When developing this tool I've found some bugs and misfeatures that
|
||||||
should be fixed to make flashing safer and cleaner.
|
should be fixed to make flashing safer and cleaner.
|
||||||
@@ -9,7 +9,7 @@ it's really hard to break the device and it works pretty nice. BTW I
|
|||||||
think that there are some things that should be fixed.
|
think that there are some things that should be fixed.
|
||||||
|
|
||||||
|
|
||||||
<b>*) Flashing at low battery level</b>
|
*) Flashing at low battery level
|
||||||
|
|
||||||
When the device is under a certain limit of battery it will not start,
|
When the device is under a certain limit of battery it will not start,
|
||||||
this is done by initfs, without any warning message or so, this really
|
this is done by initfs, without any warning message or so, this really
|
||||||
@@ -20,7 +20,7 @@ think that there are some things that should be fixed.
|
|||||||
This is *really* dangerous and not very user friendly.
|
This is *really* dangerous and not very user friendly.
|
||||||
|
|
||||||
|
|
||||||
<b>*) Internal nolo state not reset'd</b>
|
*) Internal nolo state not reset'd
|
||||||
|
|
||||||
It's possible to get nolo on a strange state that always returns error
|
It's possible to get nolo on a strange state that always returns error
|
||||||
when flashing pieces, it's mandatory to reboot the device to recover
|
when flashing pieces, it's mandatory to reboot the device to recover
|
||||||
@@ -29,7 +29,7 @@ think that there are some things that should be fixed.
|
|||||||
This is an strange and not very clear to me.
|
This is an strange and not very clear to me.
|
||||||
|
|
||||||
|
|
||||||
<b>*) Buffer overflows</b>
|
*) Buffer overflows
|
||||||
|
|
||||||
The original nokia flasher has some buffer overflow bugs that should
|
The original nokia flasher has some buffer overflow bugs that should
|
||||||
be fixed. They're safe for 99.9% of cases, but bofs on critical programs
|
be fixed. They're safe for 99.9% of cases, but bofs on critical programs
|
||||||
@@ -40,31 +40,24 @@ think that there are some things that should be fixed.
|
|||||||
than this one.
|
than this one.
|
||||||
|
|
||||||
|
|
||||||
<b>*) Missing stuff</b>
|
*) Weird firmware format
|
||||||
|
|
||||||
There are some flashing options that are not working like passing arguments
|
|
||||||
to the kernel, set the hw revision or do a cold flash (the most critical
|
|
||||||
part is undocumented).
|
|
||||||
|
|
||||||
|
|
||||||
<b>*) Weird firmware format</b>
|
|
||||||
|
|
||||||
The (new and old) FIASCO firmware format is not a very clean format, it
|
The (new and old) FIASCO firmware format is not a very clean format, it
|
||||||
doesn't provide any checksumming facility to ensure that the contents of
|
doesn't provide any checksumming facility to ensure that the contents of
|
||||||
the firmware have been modified or incorrect, so i'll rather encourage
|
the firmware have been modified or incorrect, so I'll rather encourage
|
||||||
to design and create a standard firmware format for embedded devices with
|
to design and create a standard firmware format for embedded devices with
|
||||||
checksumming, signatures, handling libraries, documentation and so.
|
checksumming, signatures, handling libraries, documentation and so.
|
||||||
|
|
||||||
I'll happilly collaborate on the design of this open firmware format, and
|
I'll happily collaborate on the design of this open firmware format, and
|
||||||
it would be used on all the open source-based devices to aim interoperability
|
it would be used on all the open source-based devices to aim interoperability
|
||||||
between devices and flashers, providing a more standard and reliable way of
|
between devices and flashers, providing a more standard and reliable way of
|
||||||
flashing devices.
|
flashing devices.
|
||||||
|
|
||||||
This will ease the development on new devices, so the information and the
|
This will ease the development on new devices, so the information and the
|
||||||
code could be revised and enhaced by zillions of eyes.
|
code could be revised and enhanced by zillions of eyes.
|
||||||
|
|
||||||
|
|
||||||
<b>*) Poor checksumming</b>
|
*) Poor checksumming
|
||||||
|
|
||||||
The only checksum is a 16 bit xor of the whole firmware piece and it's only
|
The only checksum is a 16 bit xor of the whole firmware piece and it's only
|
||||||
checked after sending the piece to the device.
|
checked after sending the piece to the device.
|
||||||
@@ -73,7 +66,7 @@ think that there are some things that should be fixed.
|
|||||||
algorithm. It currently performs a unique check at the end, it could be
|
algorithm. It currently performs a unique check at the end, it could be
|
||||||
better to check each data block to avoid errors or invalid flashing, isn't it ?
|
better to check each data block to avoid errors or invalid flashing, isn't it ?
|
||||||
|
|
||||||
<b>*) No validation of pieces before flashing</b>
|
*) No validation of pieces before flashing
|
||||||
|
|
||||||
I've implemented a minimal check of the pieces to avoid flashing invalid
|
I've implemented a minimal check of the pieces to avoid flashing invalid
|
||||||
pieces on the wrong place. This is done in fpid.c (firmware piece identifier).
|
pieces on the wrong place. This is done in fpid.c (firmware piece identifier).
|
||||||
@@ -82,7 +75,7 @@ think that there are some things that should be fixed.
|
|||||||
that can (pseudo)brick the device.
|
that can (pseudo)brick the device.
|
||||||
|
|
||||||
|
|
||||||
<b>*) Reverse flashing</b>
|
*) Reverse flashing
|
||||||
|
|
||||||
If you want to test a new firmware, but you don't want to loose all the
|
If you want to test a new firmware, but you don't want to loose all the
|
||||||
contents of your device. The only way to do that (afaik) is from the
|
contents of your device. The only way to do that (afaik) is from the
|
||||||
@@ -94,7 +87,7 @@ think that there are some things that should be fixed.
|
|||||||
case of a wrong checksumming (for example)
|
case of a wrong checksumming (for example)
|
||||||
|
|
||||||
|
|
||||||
<b>*) Documentation</b>
|
*) Documentation
|
||||||
|
|
||||||
The nokia flasher comes as is, without documentation. This is not good
|
The nokia flasher comes as is, without documentation. This is not good
|
||||||
to anybody, because the lack of information is always the root of problems,
|
to anybody, because the lack of information is always the root of problems,
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
Consequences of a weird flashing :)<br />
|
|
||||||
<img src="img/n770bars.jpg">
|
|
||||||
+31
@@ -4,3 +4,34 @@ Fiasco firmware pieces
|
|||||||
The firmware for the maemo devices is composed by a set of pieces containing
|
The firmware for the maemo devices is composed by a set of pieces containing
|
||||||
the required parts to update the whole system following a partition layout
|
the required parts to update the whole system following a partition layout
|
||||||
defined by NOLO on the internal flash memory.
|
defined by NOLO on the internal flash memory.
|
||||||
|
|
||||||
|
Nokia provides a blob packed with a proprietary format called 'FIASCO'. This
|
||||||
|
blob contains the following pieces:
|
||||||
|
|
||||||
|
- 2nd - for Cold Flashing
|
||||||
|
- xloader - first part of nolo
|
||||||
|
- secondary - second part of nolo (usb support and launches kernel)
|
||||||
|
- kernel - the kernel
|
||||||
|
- initfs - initial system that initializes everything and runs rootfs
|
||||||
|
- rootfs - the whole system image
|
||||||
|
|
||||||
|
Some of these pieces are versioned to match board specific features
|
||||||
|
(mostly xloader and secondary ones).
|
||||||
|
|
||||||
|
To flash an initfs partition and reboot:
|
||||||
|
|
||||||
|
$ 0xFFFF -m initfs:initfs.jffs2 -f -r
|
||||||
|
|
||||||
|
The format of the argument is [[[device:[hw-revision:]]verion:]piece-type:]file-name[%layout-file-name]
|
||||||
|
|
||||||
|
Pieces can be automatically identified by using the '-i' flag:
|
||||||
|
|
||||||
|
$ 0xFFFF -m initfs.jffs2 -i
|
||||||
|
|
||||||
|
You can dump these pieces from the internal memory of the internet
|
||||||
|
tablet by using the mtd-utils over /dev/mtd* or just running:
|
||||||
|
|
||||||
|
770$ 0xFFFF -e /media/mmc1
|
||||||
|
|
||||||
|
There is another way for dumping pieces with extra parameters and options,
|
||||||
|
read doc/dumping for more information.
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
<b>Usage guide</b>
|
|
||||||
|
|
||||||
0xFFFF is a free software implementation of the flasher for the Nokia Internet
|
|
||||||
Tablets (n770 and n800).
|
|
||||||
<pre>
|
|
||||||
- flash separated pieces of the firmware.
|
|
||||||
- retrieve information about the device
|
|
||||||
- reboot de mother board
|
|
||||||
- extract the current firmware pieces from the device (dump)
|
|
||||||
- set the USB host/slave mode
|
|
||||||
- set the R&R mode
|
|
||||||
- identify firmware pieces
|
|
||||||
</pre>
|
|
||||||
This is the help message of the tool:
|
|
||||||
<pre>
|
|
||||||
<b>~$ 0xFFFF -h</b>
|
|
||||||
0xFFFF v0.1 - The Open Free Fiasco Firmware Flasher
|
|
||||||
-b [arg] boots the kernel with arguments
|
|
||||||
-e [path] dump the firmware pieces into the path
|
|
||||||
-p [[p:]file] piece-of-firmware : file-where-this-piece-is
|
|
||||||
-r [0|1] disable/enable R&D mode
|
|
||||||
-u [fiasco] unpack target fiasco image
|
|
||||||
-U [0|1] disable/enable the usb host mode
|
|
||||||
-h show this help message
|
|
||||||
-i show device information (let standby mode)
|
|
||||||
-I [piece] identify a firmware piece
|
|
||||||
-l list supported usb device ids
|
|
||||||
-d [vid:pid] injects a usb device into the supported list
|
|
||||||
-R reboot the omap board
|
|
||||||
-v be verbose and noisy
|
|
||||||
-V show 0xFFFF version information
|
|
||||||
Pieces are: xloader secondary kernel initfs rootfs omap-nand
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
Before anything we can execute failsafe queries like getting device information:
|
|
||||||
<pre> <b>~$ 0xFFFF -i</b></pre>
|
|
||||||
This command will put the bootloader in standby mode, so you can now send other
|
|
||||||
commands without having to reboot the tablet manually. To reboot the mother
|
|
||||||
board via USB type:
|
|
||||||
<pre> <b>~$ 0xFFFF -R</b></pre>
|
|
||||||
You can run 'offline' commands to identify the type of the firmware pieces:
|
|
||||||
<pre> <b>~$ 0xFFFF -I zImage -I xloader.bin -I initfs.jffs2.orig</b>
|
|
||||||
kernel: zImage
|
|
||||||
xloader: xloader.bin
|
|
||||||
initfs: initfs.jffs2.orig</pre>
|
|
||||||
If you want to backup your device firmware you can crosscompile the 0xFFFF
|
|
||||||
utility and type this on the terminal:
|
|
||||||
<pre> <b>~$ sudo gainroot</b>
|
|
||||||
~# mkdir /media/mmc1/firmware
|
|
||||||
~# ./0xFFFF -e /media/mmc1/firmware</pre>
|
|
||||||
Now is time to flash something :) By default the flasher identifies the type
|
|
||||||
of the piece automatically, but you can force't prefixing the filename with
|
|
||||||
the piece-type name. To do this is just as simple as typing:
|
|
||||||
<pre> <b>~$ 0xFFFF -p zImage</b></pre>
|
|
||||||
+48
-8
@@ -1,11 +1,51 @@
|
|||||||
VERSION=0.1
|
include ../config.mk
|
||||||
OBJ=main.o fiasco.o hexdump.o dump.o flash.o
|
|
||||||
OBJ+=hash.o fpid.o query.o pieces.o utils.o
|
|
||||||
BIN=0xFFFF
|
|
||||||
CFLAGS+=-DVERSION=\"${VERSION}\" -Wall -g
|
|
||||||
|
|
||||||
main: ${OBJ}
|
PREFIX ?= /usr/local
|
||||||
${CC} ${LDFLAGS} -o ${BIN} ${OBJ} -lusb
|
INSTALL ?= install
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
CROSS_CC = $(CROSS_COMPILE)$(CC)
|
||||||
|
HOST_CC = $(HOST_COMPILE)$(CC)
|
||||||
|
|
||||||
|
CPPFLAGS += -DVERSION=\"$(VERSION)\" -D_GNU_SOURCE
|
||||||
|
CFLAGS += -W -Wall -O2 -pedantic -std=c99
|
||||||
|
LIBS += -lusb
|
||||||
|
|
||||||
|
DEPENDS = Makefile ../config.mk
|
||||||
|
|
||||||
|
OBJS = main.o nolo.o printf-utils.o image.o fiasco.o device.o usb-device.o cold-flash.o operations.o local.o mkii.o disk.o cal.o
|
||||||
|
BIN = 0xFFFF
|
||||||
|
MANGEN = mangen
|
||||||
|
|
||||||
|
all: $(BIN) $(BIN).1
|
||||||
|
|
||||||
|
$(BIN): $(OBJS) $(DEPENDS)
|
||||||
|
$(CROSS_CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) $(OBJS) $(LIBS)
|
||||||
|
|
||||||
|
$(MANGEN): $(MANGEN).c $(DEPENDS)
|
||||||
|
$(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$(BIN).1: $(BIN) $(MANGEN) $(DEPENDS) ../doc/examples
|
||||||
|
./$(MANGEN) > $@.tmp
|
||||||
|
(printf '.SH EXAMPLES\n.\n.PP\n.B\n'; cat ../doc/examples) | sed 's/^$$/.fi\n.\n.PP\n.B/' | sed '/^\.PP$$/N;/\.B/N;/\.fi/N;s/^\.PP\n\.B\n\.fi\n//' | sed '/^\.B/N;s/\n/ /;/^\.B/s/$$/\n.nf/' | sed '/^\.nf/N;/^\.fi/N;s/^\.nf\n.fi/./' >> $@.tmp
|
||||||
|
mv $@.tmp $@
|
||||||
|
|
||||||
|
libusb-sniff-32.so: libusb-sniff.c $(DEPENDS)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -fPIC -ldl -shared -m32 -o $@ $<
|
||||||
|
|
||||||
|
libusb-sniff-64.so: libusb-sniff.c $(DEPENDS)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -fPIC -ldl -shared -m64 -o $@ $<
|
||||||
|
|
||||||
|
%.o: %.c $(DEPENDS)
|
||||||
|
$(CROSS_CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
install: $(BIN) $(BIN).1
|
||||||
|
$(INSTALL) -D -m 755 $(BIN) $(DESTDIR)$(PREFIX)/bin/$(BIN)
|
||||||
|
$(INSTALL) -D -m 644 $(BIN).1 $(DESTDIR)$(PREFIX)/share/man/man1/$(BIN).1
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
$(RM) $(DESTDIR)$(PREFIX)/bin/$(BIN)
|
||||||
|
$(RM) $(DESTDIR)$(PREFIX)/share/man/man1/$(BIN).1
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm -f ${OBJ} ${BIN}
|
-$(RM) $(OBJS) $(BIN) $(MANGEN) $(BIN).1 $(BIN).1.tmp libusb-sniff-32.so libusb-sniff-64.so
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (c) 2011 Michael Buesch <mb@bu3sch.de>
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This is simple CAL parser form Calvaria */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <mtd/mtd-user.h>
|
||||||
|
|
||||||
|
#include "cal.h"
|
||||||
|
|
||||||
|
#define MAX_SIZE 393216
|
||||||
|
#define INDEX_LAST (0xFF + 1)
|
||||||
|
#define HDR_MAGIC "ConF"
|
||||||
|
|
||||||
|
struct cal {
|
||||||
|
int fd;
|
||||||
|
ssize_t size;
|
||||||
|
void * mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct header {
|
||||||
|
char magic[4]; /* Magic sequence */
|
||||||
|
uint8_t type; /* Type number */
|
||||||
|
uint8_t index; /* Index number */
|
||||||
|
uint16_t flags; /* Flags */
|
||||||
|
char name[16]; /* Human readable section name */
|
||||||
|
uint32_t length; /* Payload length */
|
||||||
|
uint32_t datasum; /* Data CRC32 checksum */
|
||||||
|
uint32_t hdrsum; /* Header CRC32 checksum */
|
||||||
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
|
||||||
|
int cal_init_file(const char * file, struct cal ** cal_out) {
|
||||||
|
|
||||||
|
int fd = -1;
|
||||||
|
uint64_t blksize = 0;
|
||||||
|
ssize_t size = 0;
|
||||||
|
void * mem = NULL;
|
||||||
|
struct cal * cal = NULL;
|
||||||
|
struct stat st;
|
||||||
|
mtd_info_t mtd_info;
|
||||||
|
|
||||||
|
if ( stat(file, &st) != 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fd = open(file, O_RDONLY);
|
||||||
|
|
||||||
|
if ( fd < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ( S_ISREG(st.st_mode) )
|
||||||
|
size = st.st_size;
|
||||||
|
else if ( S_ISBLK(st.st_mode) ) {
|
||||||
|
if ( ioctl(fd, BLKGETSIZE64, &blksize) != 0 )
|
||||||
|
goto err;
|
||||||
|
if ( blksize > SSIZE_MAX )
|
||||||
|
goto err;
|
||||||
|
size = blksize;
|
||||||
|
} else if ( S_ISCHR(st.st_mode) && major(st.st_rdev) == 90 ) {
|
||||||
|
if ( ioctl(fd, MEMGETINFO, &mtd_info) != 0 )
|
||||||
|
goto err;
|
||||||
|
size = mtd_info.size;
|
||||||
|
} else {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( size == 0 || size > MAX_SIZE )
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
mem = malloc(size);
|
||||||
|
|
||||||
|
if ( ! mem )
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if ( read(fd, mem, size) != size )
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cal = malloc(sizeof(struct cal));
|
||||||
|
|
||||||
|
if ( ! cal )
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cal->fd = fd;
|
||||||
|
cal->mem = mem;
|
||||||
|
cal->size = size;
|
||||||
|
|
||||||
|
*cal_out = cal;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
close(fd);
|
||||||
|
free(mem);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int cal_init(struct cal ** cal_out) {
|
||||||
|
|
||||||
|
return cal_init_file("/dev/mtd1ro", cal_out);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void cal_finish(struct cal * cal) {
|
||||||
|
|
||||||
|
if ( cal ) {
|
||||||
|
free(cal->mem);
|
||||||
|
free(cal);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t crc32(uint32_t crc, const void * _data, size_t size) {
|
||||||
|
|
||||||
|
const uint8_t * data = _data;
|
||||||
|
uint8_t value;
|
||||||
|
unsigned int bit;
|
||||||
|
size_t i;
|
||||||
|
const uint32_t poly = 0xEDB88320;
|
||||||
|
|
||||||
|
for ( i = 0; i < size; i++ ) {
|
||||||
|
value = data[i];
|
||||||
|
for ( bit = 8; bit; bit-- ) {
|
||||||
|
if ( (crc & 1) != (value & 1) )
|
||||||
|
crc = (crc >> 1) ^ poly;
|
||||||
|
else
|
||||||
|
crc >>= 1;
|
||||||
|
value >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_header(void *data, size_t size) {
|
||||||
|
|
||||||
|
struct header * hdr = data;
|
||||||
|
|
||||||
|
if ( size < sizeof(struct header) )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ( memcmp(hdr->magic, HDR_MAGIC, sizeof(hdr->magic)) != 0 )
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t find_section(void *start, uint64_t count, int want_index, const char *want_name) {
|
||||||
|
|
||||||
|
int64_t offset = 0, found_offset = -1;
|
||||||
|
uint8_t * data = start;
|
||||||
|
struct header *hdr;
|
||||||
|
char sectname[sizeof(hdr->name) + 1] = { 0, };
|
||||||
|
uint32_t payload_len;
|
||||||
|
int previous_index = -1;
|
||||||
|
|
||||||
|
while ( 1 ) {
|
||||||
|
|
||||||
|
/* Find header start */
|
||||||
|
if ( count < sizeof(struct header) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( ! is_header(data + offset, count) ) {
|
||||||
|
count--;
|
||||||
|
offset++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr = (struct header *)(data + offset);
|
||||||
|
payload_len = hdr->length;
|
||||||
|
|
||||||
|
if ( count - sizeof(struct header) < payload_len )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(sectname, hdr->name, sizeof(hdr->name));
|
||||||
|
|
||||||
|
if ( want_index == INDEX_LAST ) {
|
||||||
|
if ((int)hdr->index <= previous_index)
|
||||||
|
goto next;
|
||||||
|
} else {
|
||||||
|
if (want_index >= 0 && want_index != hdr->index)
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( want_name && strcmp(sectname, want_name) != 0 )
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
/* Found it */
|
||||||
|
found_offset = offset;
|
||||||
|
if ( want_index == INDEX_LAST )
|
||||||
|
previous_index = hdr->index;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
next:
|
||||||
|
count -= sizeof(struct header) + payload_len;
|
||||||
|
offset += sizeof(struct header) + payload_len;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_offset;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int cal_read_block(struct cal * cal, const char * name, void ** ptr, unsigned long * len, unsigned long flags) {
|
||||||
|
|
||||||
|
int64_t find_offset;
|
||||||
|
uint64_t filelen = cal->size;
|
||||||
|
uint8_t * data = cal->mem;
|
||||||
|
struct header * hdr;
|
||||||
|
|
||||||
|
find_offset = find_section(data, filelen, INDEX_LAST, name);
|
||||||
|
if ( find_offset < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
hdr = (struct header *)(data + find_offset);
|
||||||
|
|
||||||
|
if ( flags && hdr->flags != flags )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ( crc32(0, hdr, sizeof(*hdr) - 4) != hdr->hdrsum )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*ptr = data + find_offset + sizeof(struct header);
|
||||||
|
*len = hdr->length;
|
||||||
|
|
||||||
|
if ( crc32(0, *ptr, *len) != hdr->datasum )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (c) 2011 Michael Buesch <mb@bu3sch.de>
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAL_H
|
||||||
|
#define CAL_H
|
||||||
|
|
||||||
|
#define CAL_MAX_NAME_LEN 16
|
||||||
|
#define CAL_FLAG_USER 0x0001
|
||||||
|
#define CAL_FLAG_WRITE_ONCE 0x0002
|
||||||
|
|
||||||
|
struct cal;
|
||||||
|
|
||||||
|
int cal_init(struct cal ** cal_out);
|
||||||
|
int cal_init_file(const char * file, struct cal ** cal_out);
|
||||||
|
void cal_finish(struct cal * cal);
|
||||||
|
int cal_read_block(struct cal * cal, const char * name, void ** ptr, unsigned long * len, unsigned long flags);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,415 @@
|
|||||||
|
/*
|
||||||
|
cold-flash.c - Cold flashing
|
||||||
|
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <usb.h>
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
#include "cold-flash.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
#include "printf-utils.h"
|
||||||
|
|
||||||
|
#define READ_DEV 0x81
|
||||||
|
#define WRITE_DEV 0x01
|
||||||
|
#define READ_TIMEOUT 500
|
||||||
|
#define WRITE_TIMEOUT 3000
|
||||||
|
|
||||||
|
static uint32_t tab[256];
|
||||||
|
|
||||||
|
static void crc32_gentab(void) {
|
||||||
|
|
||||||
|
int i, j;
|
||||||
|
uint32_t crc;
|
||||||
|
uint32_t poly = 0xEDB88320L;
|
||||||
|
|
||||||
|
for ( i = 0; i < 256; i++) {
|
||||||
|
|
||||||
|
crc = i;
|
||||||
|
|
||||||
|
for ( j = 8; j > 0; j-- ) {
|
||||||
|
|
||||||
|
if (crc & 1)
|
||||||
|
crc = (crc >> 1) ^ poly;
|
||||||
|
else
|
||||||
|
crc >>= 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tab[i] = crc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t crc32(unsigned char * bytes, size_t size, uint32_t crc) {
|
||||||
|
|
||||||
|
static int gen = 0;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if ( ! gen ) {
|
||||||
|
crc32_gentab();
|
||||||
|
gen = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; i < size; ++i )
|
||||||
|
crc = (crc >> 8) ^ tab[(crc ^ bytes[i]) & 0xff];
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Omap Boot Messages */
|
||||||
|
/* See spruf98v.pdf (page 3444): OMAP35x Technical Reference Manual - 25.4.5 Peripheral Booting */
|
||||||
|
|
||||||
|
/* Omap Peripheral boot message */
|
||||||
|
static const uint32_t omap_peripheral_msg = 0xF0030002;
|
||||||
|
|
||||||
|
/* Omap Void (no device) boot message */
|
||||||
|
static const uint32_t omap_void_msg = 0xF0030006;
|
||||||
|
|
||||||
|
/* Omap XIP memory boot message */
|
||||||
|
static const uint32_t omap_xip_msg = 0xF0030106;
|
||||||
|
|
||||||
|
/* Omap Nand boot message */
|
||||||
|
static const uint32_t omap_nand_msg = 0xF0030206;
|
||||||
|
|
||||||
|
/* Omap OneNAND boot message */
|
||||||
|
static const uint32_t omap_onenand_msg = 0xF0030306;
|
||||||
|
|
||||||
|
/* Omap DOC boot message */
|
||||||
|
static const uint32_t omap_doc_msg = 0xF0030406;
|
||||||
|
|
||||||
|
/* Omap MMC/SD2 boot message */
|
||||||
|
static const uint32_t omap_mmc2_msg = 0xF0030506;
|
||||||
|
|
||||||
|
/* Omap MMC/SD1 boot message */
|
||||||
|
static const uint32_t omap_mmc1_msg = 0xF0030606;
|
||||||
|
|
||||||
|
/* Omap XIP memory with wait monitoring boot message */
|
||||||
|
static const uint32_t omap_xipwait_msg = 0xF0030706;
|
||||||
|
|
||||||
|
/* Omap UART boot message */
|
||||||
|
static const uint32_t omap_uart_msg = 0xF0031006;
|
||||||
|
|
||||||
|
/* Omap HS USB boot message */
|
||||||
|
static const uint32_t omap_hsusb_msg = 0xF0031106;
|
||||||
|
|
||||||
|
/* Omap next device boot message */
|
||||||
|
static const uint32_t omap_next_msg = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
/* Omap memory boot message */
|
||||||
|
static const uint32_t omap_memory_msg = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* Nokia X-Loader messages */
|
||||||
|
|
||||||
|
/* Structure of X-Loader message */
|
||||||
|
struct xloader_msg {
|
||||||
|
uint32_t type; /* 4 bytes - type of message */
|
||||||
|
uint32_t size; /* 4 bytes - size of file */
|
||||||
|
uint32_t crc1; /* 4 bytes - crc32 of file */
|
||||||
|
uint32_t crc2; /* 4 bytes - crc32 of first 12 bytes of message */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define XLOADER_MSG_TYPE_PING 0x6301326E
|
||||||
|
#define XLOADER_MSG_TYPE_SEND 0x6302326E
|
||||||
|
|
||||||
|
struct xloader_msg xloader_msg_create(uint32_t type, struct image * image) {
|
||||||
|
|
||||||
|
struct xloader_msg msg;
|
||||||
|
uint32_t need, readed;
|
||||||
|
int ret;
|
||||||
|
uint8_t buffer[1024];
|
||||||
|
|
||||||
|
msg.type = type;
|
||||||
|
msg.size = 0;
|
||||||
|
msg.crc1 = 0;
|
||||||
|
|
||||||
|
if ( image ) {
|
||||||
|
msg.size = image->size;
|
||||||
|
image_seek(image, 0);
|
||||||
|
readed = 0;
|
||||||
|
while ( readed < image->size ) {
|
||||||
|
need = image->size - readed;
|
||||||
|
if ( need > sizeof(buffer) )
|
||||||
|
need = sizeof(buffer);
|
||||||
|
ret = image_read(image, buffer, need);
|
||||||
|
if ( ret == 0 )
|
||||||
|
break;
|
||||||
|
msg.crc1 = crc32(buffer, ret, msg.crc1);
|
||||||
|
readed += ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.crc2 = crc32((unsigned char *)&msg, 12, 0);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_asic(usb_dev_handle * udev, uint8_t * asic_buffer, int size, int asic_size) {
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
printf("Waiting for ASIC ID...\n");
|
||||||
|
ret = usb_bulk_read(udev, READ_DEV, (char *)asic_buffer, size, READ_TIMEOUT);
|
||||||
|
if ( ret != asic_size )
|
||||||
|
ERROR_RETURN("Invalid size of ASIC ID", -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_2nd(usb_dev_handle * udev, struct image * image) {
|
||||||
|
|
||||||
|
uint8_t buffer[1024];
|
||||||
|
uint32_t need, readed;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
printf("Sending OMAP peripheral boot message...\n");
|
||||||
|
ret = usb_bulk_write(udev, WRITE_DEV, (char *)&omap_peripheral_msg, sizeof(omap_peripheral_msg), WRITE_TIMEOUT);
|
||||||
|
usleep(5000);
|
||||||
|
if ( ret != sizeof(omap_peripheral_msg) )
|
||||||
|
ERROR_RETURN("Sending OMAP peripheral boot message failed", -1);
|
||||||
|
|
||||||
|
printf("Sending 2nd X-Loader image size...\n");
|
||||||
|
ret = usb_bulk_write(udev, WRITE_DEV, (char *)&image->size, 4, WRITE_TIMEOUT);
|
||||||
|
usleep(5000);
|
||||||
|
if ( ret != 4 )
|
||||||
|
ERROR_RETURN("Sending 2nd X-Loader image size failed", -1);
|
||||||
|
|
||||||
|
printf("Sending 2nd X-Loader image...\n");
|
||||||
|
printf_progressbar(0, image->size);
|
||||||
|
image_seek(image, 0);
|
||||||
|
readed = 0;
|
||||||
|
while ( readed < image->size ) {
|
||||||
|
need = image->size - readed;
|
||||||
|
if ( need > sizeof(buffer) )
|
||||||
|
need = sizeof(buffer);
|
||||||
|
ret = image_read(image, buffer, need);
|
||||||
|
if ( ret == 0 )
|
||||||
|
break;
|
||||||
|
if ( usb_bulk_write(udev, WRITE_DEV, (char *)buffer, ret, WRITE_TIMEOUT) != ret )
|
||||||
|
PRINTF_ERROR_RETURN("Sending 2nd X-Loader image failed", -1);
|
||||||
|
readed += ret;
|
||||||
|
printf_progressbar(readed, image->size);
|
||||||
|
}
|
||||||
|
usleep(50000);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_secondary(usb_dev_handle * udev, struct image * image) {
|
||||||
|
|
||||||
|
struct xloader_msg init_msg;
|
||||||
|
uint8_t buffer[1024];
|
||||||
|
uint32_t need, readed;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
init_msg = xloader_msg_create(XLOADER_MSG_TYPE_SEND, image);
|
||||||
|
|
||||||
|
printf("Sending X-Loader init message...\n");
|
||||||
|
ret = usb_bulk_write(udev, WRITE_DEV, (char *)&init_msg, sizeof(init_msg), WRITE_TIMEOUT);
|
||||||
|
usleep(5000);
|
||||||
|
if ( ret != sizeof(init_msg) )
|
||||||
|
ERROR_RETURN("Sending X-Loader init message failed", -1);
|
||||||
|
|
||||||
|
printf("Waiting for X-Loader response...\n");
|
||||||
|
ret = usb_bulk_read(udev, READ_DEV, (char *)&buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
|
||||||
|
if ( ret != 4 )
|
||||||
|
ERROR_RETURN("No response", -1);
|
||||||
|
|
||||||
|
printf("Sending Secondary image...\n");
|
||||||
|
printf_progressbar(0, image->size);
|
||||||
|
image_seek(image, 0);
|
||||||
|
readed = 0;
|
||||||
|
while ( readed < image->size ) {
|
||||||
|
need = image->size - readed;
|
||||||
|
if ( need > sizeof(buffer) )
|
||||||
|
need = sizeof(buffer);
|
||||||
|
ret = image_read(image, buffer, need);
|
||||||
|
if ( ret == 0 )
|
||||||
|
break;
|
||||||
|
if ( usb_bulk_write(udev, WRITE_DEV, (char *)buffer, ret, WRITE_TIMEOUT) != ret )
|
||||||
|
PRINTF_ERROR_RETURN("Sending Secondary image failed", -1);
|
||||||
|
readed += ret;
|
||||||
|
printf_progressbar(readed, image->size);
|
||||||
|
}
|
||||||
|
usleep(5000);
|
||||||
|
|
||||||
|
printf("Waiting for X-Loader response...\n");
|
||||||
|
ret = usb_bulk_read(udev, READ_DEV, (char *)&buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
|
||||||
|
if ( ret != 4 )
|
||||||
|
ERROR_RETURN("No response", -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ping_timeout(usb_dev_handle * udev) {
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
int pong = 0;
|
||||||
|
int try_ping = 10;
|
||||||
|
|
||||||
|
while ( try_ping > 0 ) {
|
||||||
|
|
||||||
|
struct xloader_msg ping_msg = xloader_msg_create(XLOADER_MSG_TYPE_PING, NULL);
|
||||||
|
int try_read = 4;
|
||||||
|
|
||||||
|
printf("Sending X-Loader ping message\n");
|
||||||
|
ret = usb_bulk_write(udev, WRITE_DEV, (char *)&ping_msg, sizeof(ping_msg), WRITE_TIMEOUT);
|
||||||
|
if ( ret != sizeof(ping_msg) )
|
||||||
|
ERROR_RETURN("Sending X-Loader ping message failed", -1);
|
||||||
|
|
||||||
|
printf("Waiting for X-Loader pong response...\n");
|
||||||
|
while ( try_read > 0 ) {
|
||||||
|
|
||||||
|
uint32_t ping_read;
|
||||||
|
ret = usb_bulk_read(udev, READ_DEV, (char *)&ping_read, sizeof(ping_read), READ_TIMEOUT);
|
||||||
|
if ( ret == sizeof(ping_read) ) {
|
||||||
|
printf("Got it\n");
|
||||||
|
pong = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(5000);
|
||||||
|
--try_read;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pong )
|
||||||
|
break;
|
||||||
|
|
||||||
|
printf("Response timeout\n");
|
||||||
|
--try_ping;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pong)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int init_cold_flash(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
uint8_t asic_buffer[127];
|
||||||
|
int asic_size = 69;
|
||||||
|
const char * chip = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( dev->flash_device->protocol != FLASH_COLD )
|
||||||
|
ERROR_RETURN("Device is not in Cold Flash mode", -1);
|
||||||
|
|
||||||
|
if ( read_asic(dev->udev, asic_buffer, sizeof(asic_buffer), asic_size) != 0 )
|
||||||
|
ERROR_RETURN("Reading ASIC ID failed", -1);
|
||||||
|
|
||||||
|
if ( verbose ) {
|
||||||
|
printf("Got ASIC ID:");
|
||||||
|
for ( i = 0; i < asic_size; ++i )
|
||||||
|
printf(" 0x%.2X", (unsigned int)asic_buffer[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Detect device from asic id */
|
||||||
|
|
||||||
|
/* ASIC ID specification: http://processors.wiki.ti.com/index.php/OMAP35x_and_AM/DM37x_Initialization#UART.2FUSB_Booting */
|
||||||
|
|
||||||
|
/* Number of subblocks */
|
||||||
|
if ( asic_buffer[0] != 0x05 )
|
||||||
|
ERROR_RETURN("Invalid ASIC ID", -1);
|
||||||
|
|
||||||
|
/* ID Subblock - header */
|
||||||
|
if ( memcmp(asic_buffer+1, "\x01\x05\x01", 3) != 0 )
|
||||||
|
ERROR_RETURN("Invalid ASIC ID", -1);
|
||||||
|
|
||||||
|
/* ID Subblock - OMAP chip version (check for OMAP3430 or 3630) */
|
||||||
|
if ( memcmp(asic_buffer+4, "\x34\x30\x07", 3) == 0 )
|
||||||
|
chip = "OMAP3430";
|
||||||
|
else if ( memcmp(asic_buffer+4, "\x36\x30\x07", 3) == 0 )
|
||||||
|
chip = "OMAP3630";
|
||||||
|
else
|
||||||
|
ERROR_RETURN("Invalid ASIC ID", -1);
|
||||||
|
|
||||||
|
/* Reserved1 - header */
|
||||||
|
if ( memcmp(asic_buffer+8, "\x13\x02\x01", 3) != 0 )
|
||||||
|
ERROR_RETURN("Invalid ASIC ID", -1);
|
||||||
|
|
||||||
|
/* 2nd ID Subblock - header */
|
||||||
|
if ( memcmp(asic_buffer+12, "\x12\x15\x01", 3) != 0 )
|
||||||
|
ERROR_RETURN("Invalid ASIC ID", -1);
|
||||||
|
|
||||||
|
/* Reserved2 - header */
|
||||||
|
if ( memcmp(asic_buffer+35, "\x14\x15\x01", 3) != 0 )
|
||||||
|
ERROR_RETURN("Invalid ASIC ID", -1);
|
||||||
|
|
||||||
|
/* Checksum subblock - header */
|
||||||
|
if ( memcmp(asic_buffer+58, "\x15\x09\x01", 3) != 0 )
|
||||||
|
ERROR_RETURN("Invalid ASIC ID", -1);
|
||||||
|
|
||||||
|
printf("Detected %s chip\n", chip);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int cold_flash(struct usb_device_info * dev, struct image * x2nd, struct image * secondary) {
|
||||||
|
|
||||||
|
if ( x2nd->type != IMAGE_2ND )
|
||||||
|
ERROR_RETURN("Image type is not 2nd X-Loader", -1);
|
||||||
|
|
||||||
|
if ( secondary->type != IMAGE_SECONDARY )
|
||||||
|
ERROR_RETURN("Image type is not Secondary", -1);
|
||||||
|
|
||||||
|
if ( send_2nd(dev->udev, x2nd) != 0 )
|
||||||
|
ERROR_RETURN("Sending 2nd X-Loader image failed", -1);
|
||||||
|
|
||||||
|
if ( ping_timeout(dev->udev) != 0 )
|
||||||
|
ERROR_RETURN("Sending X-Loader ping message failed", -1);
|
||||||
|
|
||||||
|
if ( send_secondary(dev->udev, secondary) != 0 )
|
||||||
|
ERROR_RETURN("Sending Secondary image failed", -1);
|
||||||
|
|
||||||
|
printf("Done\n");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int leave_cold_flash(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
printf("Sending OMAP memory boot message...\n");
|
||||||
|
ret = usb_bulk_write(dev->udev, WRITE_DEV, (char *)&omap_memory_msg, sizeof(omap_memory_msg), WRITE_TIMEOUT);
|
||||||
|
usleep(5000);
|
||||||
|
if ( ret != sizeof(omap_memory_msg) )
|
||||||
|
ERROR_RETURN("Sending OMAP memory boot message failed", -1);
|
||||||
|
|
||||||
|
usleep(250000);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
cold-flash.h - Cold flashing
|
||||||
|
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COLD_FLASH_H
|
||||||
|
#define COLD_FLASH_H
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
|
||||||
|
/* Initialize Cold Flash mde */
|
||||||
|
int init_cold_flash(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
/* Flash 2nd and secondary image in Cold Flash mode. After flashing device will boot secondary image */
|
||||||
|
int cold_flash(struct usb_device_info * dev, struct image * x2nd, struct image * secondary);
|
||||||
|
|
||||||
|
/* Leave Cold Flashing mode and continue booting */
|
||||||
|
int leave_cold_flash(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
#endif
|
||||||
+328
@@ -0,0 +1,328 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
static const char * devices[] = {
|
||||||
|
[DEVICE_SU_18] = "SU-18",
|
||||||
|
[DEVICE_RX_34] = "RX-34",
|
||||||
|
[DEVICE_RX_44] = "RX-44",
|
||||||
|
[DEVICE_RX_48] = "RX-48",
|
||||||
|
[DEVICE_RX_51] = "RX-51",
|
||||||
|
};
|
||||||
|
|
||||||
|
enum device device_from_string(const char * device) {
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if ( ! device || ! device[0] )
|
||||||
|
return DEVICE_ANY;
|
||||||
|
|
||||||
|
for ( i = 0; i < sizeof(devices)/sizeof(devices[0]); ++i )
|
||||||
|
if ( devices[i] && strcmp(devices[i], device) == 0 )
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return DEVICE_UNKNOWN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * device_to_string(enum device device) {
|
||||||
|
|
||||||
|
if ( device >= sizeof(devices)/sizeof(devices[0]) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return devices[device];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * long_devices[] = {
|
||||||
|
[DEVICE_SU_18] = "Nokia 770",
|
||||||
|
[DEVICE_RX_34] = "Nokia N800",
|
||||||
|
[DEVICE_RX_44] = "Nokia N810",
|
||||||
|
[DEVICE_RX_48] = "Nokia N810 Wimax",
|
||||||
|
[DEVICE_RX_51] = "Nokia N900",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char * device_to_long_string(enum device device) {
|
||||||
|
|
||||||
|
if ( device >= sizeof(long_devices)/sizeof(long_devices[0]) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return long_devices[device];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwrev_is_valid(const int16_t * hwrevs, int16_t hwrev) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* hwrevs not specified, valid for any hwrev */
|
||||||
|
if ( ! hwrevs )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for ( i = 0; hwrevs[i] != -1; ++i )
|
||||||
|
if ( hwrev == hwrevs[i] )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t * hwrevs_alloc_from_string(const char * str) {
|
||||||
|
|
||||||
|
const char * ptr = str;
|
||||||
|
const char * oldptr = ptr;
|
||||||
|
int count = 2;
|
||||||
|
int16_t * ret;
|
||||||
|
int16_t tmp;
|
||||||
|
int i;
|
||||||
|
char buf[5];
|
||||||
|
|
||||||
|
if ( ! str )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while ( (ptr = strchr(ptr, ',')) ) {
|
||||||
|
++count;
|
||||||
|
++ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = calloc(count, sizeof(int16_t));
|
||||||
|
if ( ! ret )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
ptr = str;
|
||||||
|
while ( (ptr = strchr(ptr, ',')) ) {
|
||||||
|
strncpy(buf, oldptr, ptr-oldptr);
|
||||||
|
buf[4] = 0;
|
||||||
|
tmp = atoi(buf);
|
||||||
|
if ( tmp >= 0 )
|
||||||
|
ret[i++] = tmp;
|
||||||
|
++ptr;
|
||||||
|
oldptr = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = atoi(oldptr);
|
||||||
|
if ( tmp >= 0 )
|
||||||
|
ret[i++] = tmp;
|
||||||
|
|
||||||
|
ret[i++] = -1;
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char * hwrevs_alloc_to_string(const int16_t * hwrevs) {
|
||||||
|
|
||||||
|
char * ret;
|
||||||
|
char * ptr;
|
||||||
|
int i;
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
for ( i = 0; hwrevs[i] != -1; ++i )
|
||||||
|
len += 7;
|
||||||
|
|
||||||
|
ret = calloc(1, len+1);
|
||||||
|
if ( ! ret )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ptr = ret;
|
||||||
|
for ( i = 0; hwrevs[i] != -1; ++i )
|
||||||
|
ptr += sprintf(ptr, "%d,", hwrevs[i]);
|
||||||
|
|
||||||
|
*(ptr-1) = 0;
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_HWREVS 29
|
||||||
|
|
||||||
|
char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
int size = 0;
|
||||||
|
const char * device;
|
||||||
|
const struct device_list * device_first;
|
||||||
|
char ** ret;
|
||||||
|
char * last_ptr;
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
device_first = device_list;
|
||||||
|
|
||||||
|
while ( device_first ) {
|
||||||
|
|
||||||
|
int local = 0;
|
||||||
|
|
||||||
|
if ( ! device_to_string(device_first->device) ) {
|
||||||
|
device_first = device_first->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( i = 0; device_first->hwrevs[i] != -1; ++i )
|
||||||
|
if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 )
|
||||||
|
++local;
|
||||||
|
|
||||||
|
size += (1+16+(MAX_HWREVS+1)*8)*(local/MAX_HWREVS+1);
|
||||||
|
count += local/MAX_HWREVS;
|
||||||
|
if ( local%MAX_HWREVS != 0 || local == 0 )
|
||||||
|
++count;
|
||||||
|
|
||||||
|
device_first = device_first->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = calloc(1, (count+1)*sizeof(char *) + size);
|
||||||
|
if ( ! ret )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
last_ptr = (char *)ret + (count+1)*sizeof(char *);
|
||||||
|
device_first = device_list;
|
||||||
|
|
||||||
|
while ( device_first ) {
|
||||||
|
|
||||||
|
i = -1;
|
||||||
|
|
||||||
|
device = device_to_string(device_first->device);
|
||||||
|
if ( ! device ) {
|
||||||
|
device_first = device_first->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( device_first->hwrevs[i+1] != -1 ) {
|
||||||
|
|
||||||
|
uint8_t len = 0;
|
||||||
|
ret[j] = ++last_ptr;
|
||||||
|
|
||||||
|
strncpy(ret[j]+1, device, 16);
|
||||||
|
last_ptr += 16;
|
||||||
|
len += 16;
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
|
||||||
|
for ( k = 0; k < MAX_HWREVS; ++k ) {
|
||||||
|
|
||||||
|
if ( device_first->hwrevs[i+1] == -1 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if ( device_first->hwrevs[i] < 0 || device_first->hwrevs[i] > 9999 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(ret[j]+1+16+k*8, 8, "%d", device_first->hwrevs[i]);
|
||||||
|
last_ptr += 8;
|
||||||
|
len += 8;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
((uint8_t*)ret[j])[0] = len;
|
||||||
|
|
||||||
|
++j;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
device_first = device_first->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ret[j] = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device_list * device_list_alloc_from_buf(const char * buf, size_t size) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int len;
|
||||||
|
int count;
|
||||||
|
char str[17];
|
||||||
|
const char * ptr1;
|
||||||
|
const char * ptr;
|
||||||
|
struct device_list * ret;
|
||||||
|
|
||||||
|
ret = calloc(1, sizeof(struct device_list));
|
||||||
|
if ( ! ret )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = strnlen(buf, size);
|
||||||
|
if ( len > 16 )
|
||||||
|
len = 16;
|
||||||
|
|
||||||
|
memset(str, 0, sizeof(str));
|
||||||
|
memcpy(str, buf, len);
|
||||||
|
ptr1 = buf + len;
|
||||||
|
|
||||||
|
ret->device = device_from_string(str);
|
||||||
|
|
||||||
|
ptr = ptr1;
|
||||||
|
count = 1;
|
||||||
|
while ( ptr < buf + size ) {
|
||||||
|
|
||||||
|
while ( ptr < buf + size && *ptr < 32 )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( ptr >= buf + size )
|
||||||
|
break;
|
||||||
|
|
||||||
|
len = strnlen(ptr, buf + size - ptr);
|
||||||
|
if ( len > 8 )
|
||||||
|
len = 8;
|
||||||
|
|
||||||
|
ptr += len + 1;
|
||||||
|
++count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->hwrevs = calloc(count, sizeof(int16_t));
|
||||||
|
if ( ! ret->hwrevs )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ptr = ptr1;
|
||||||
|
i = 0;
|
||||||
|
while ( ptr < buf + size ) {
|
||||||
|
|
||||||
|
while ( ptr < buf + size && *ptr < 32 )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( ptr >= buf + size )
|
||||||
|
break;
|
||||||
|
|
||||||
|
len = strnlen(ptr, buf + size - ptr);
|
||||||
|
if ( len > 8 )
|
||||||
|
len = 8;
|
||||||
|
|
||||||
|
memset(str, 0, sizeof(str));
|
||||||
|
memcpy(str, ptr, len);
|
||||||
|
ptr += len + 1;
|
||||||
|
ret->hwrevs[i++] = atoi(str);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->hwrevs[i] = -1;
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEVICE_H
|
||||||
|
#define DEVICE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum device {
|
||||||
|
DEVICE_UNKNOWN = 0,
|
||||||
|
DEVICE_ANY, /* Unspecified / Any device */
|
||||||
|
DEVICE_SU_18, /* Nokia 770 */
|
||||||
|
DEVICE_RX_34, /* Nokia N800 */
|
||||||
|
DEVICE_RX_44, /* Nokia N810 */
|
||||||
|
DEVICE_RX_48, /* Nokia N810 WiMax */
|
||||||
|
DEVICE_RX_51, /* Nokia N900 */
|
||||||
|
DEVICE_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
hwrevs - array of int16_t
|
||||||
|
- terminated by -1
|
||||||
|
- valid numbers: 0-9999
|
||||||
|
*/
|
||||||
|
struct device_list {
|
||||||
|
enum device device;
|
||||||
|
int16_t * hwrevs;
|
||||||
|
struct device_list * next;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum device device_from_string(const char * device);
|
||||||
|
const char * device_to_string(enum device device);
|
||||||
|
const char * device_to_long_string(enum device device);
|
||||||
|
|
||||||
|
int hwrev_is_valid(const int16_t * hwrevs, int16_t hwrev);
|
||||||
|
|
||||||
|
int16_t * hwrevs_alloc_from_string(const char * str);
|
||||||
|
char * hwrevs_alloc_to_string(const int16_t * hwrevs);
|
||||||
|
|
||||||
|
char ** device_list_alloc_to_bufs(const struct device_list * device_list);
|
||||||
|
struct device_list * device_list_alloc_from_buf(const char * buf, size_t size);
|
||||||
|
|
||||||
|
#endif
|
||||||
+188
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
|
#include <linux/fs.h>
|
||||||
|
|
||||||
|
#include "disk.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
#include "printf-utils.h"
|
||||||
|
|
||||||
|
static char global_buf[1 << 22]; /* 4MB */
|
||||||
|
|
||||||
|
int disk_init(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("RAW mode is not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum device disk_get_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return DEVICE_UNKNOWN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int disk_flash_raw(const char * blkdev, const char * file) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)blkdev;
|
||||||
|
(void)file;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int disk_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)image;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int disk_dump_raw(const char * blkdev, const char * file) {
|
||||||
|
|
||||||
|
int fd1, fd2;
|
||||||
|
int ret;
|
||||||
|
char * path;
|
||||||
|
uint64_t blksize;
|
||||||
|
size_t need, readed;
|
||||||
|
ssize_t size;
|
||||||
|
struct stat st;
|
||||||
|
struct statvfs buf;
|
||||||
|
|
||||||
|
printf("Dump block device %s to file %s...\n", blkdev, file);
|
||||||
|
|
||||||
|
if ( stat(blkdev, &st) != 0 ) {
|
||||||
|
ERROR_INFO("Cannot stat block device %s", blkdev);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! S_ISBLK(st.st_mode) ) {
|
||||||
|
ERROR("Invalid block device %s", blkdev);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd1 = open(blkdev, O_RDONLY);
|
||||||
|
|
||||||
|
if ( fd1 < 0 ) {
|
||||||
|
ERROR_INFO("Cannot open block device %s", blkdev);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ioctl(fd1, BLKGETSIZE64, &blksize) != 0 ) {
|
||||||
|
ERROR_INFO("Cannot get size of block device %s", blkdev);
|
||||||
|
close(fd1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( blksize > ULLONG_MAX ) {
|
||||||
|
ERROR("Block device %s is too big", blkdev);
|
||||||
|
close(fd1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( blksize == 0 ) {
|
||||||
|
ERROR("Block device %s has zero size", blkdev);
|
||||||
|
close(fd1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = strdup(file);
|
||||||
|
if ( ! path ) {
|
||||||
|
ALLOC_ERROR();
|
||||||
|
close(fd1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = statvfs(dirname(path), &buf);
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
if ( ret == 0 && buf.f_bsize * buf.f_bfree < blksize ) {
|
||||||
|
ERROR("Not enough free space (have: %llu, need: %llu)", (unsigned long long int)(buf.f_bsize) * buf.f_bfree, (unsigned long long int)blksize);
|
||||||
|
close(fd1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
|
|
||||||
|
if ( fd2 < 0 ) {
|
||||||
|
ERROR_INFO("Cannot create file %s", file);
|
||||||
|
close(fd1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
readed = 0;
|
||||||
|
printf_progressbar(0, blksize);
|
||||||
|
|
||||||
|
while ( readed < blksize ) {
|
||||||
|
need = blksize - readed;
|
||||||
|
if ( need > sizeof(global_buf) )
|
||||||
|
need = sizeof(global_buf);
|
||||||
|
size = read(fd1, global_buf, need);
|
||||||
|
if ( size == 0 )
|
||||||
|
break;
|
||||||
|
if ( write(fd2, global_buf, size) != size ) {
|
||||||
|
PRINTF_ERROR("Dumping image failed");
|
||||||
|
close(fd1);
|
||||||
|
close(fd2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
readed += size;
|
||||||
|
printf_progressbar(readed, blksize);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd1);
|
||||||
|
close(fd2);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)image;
|
||||||
|
(void)file;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int disk_check_badblocks(struct usb_device_info * dev, const char * device) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)device;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DISK_H
|
||||||
|
#define DISK_H
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
|
||||||
|
int disk_init(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
enum device disk_get_device(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
int disk_flash_raw(const char * blkdev, const char * file);
|
||||||
|
int disk_dump_raw(const char * blkdev, const char * file);
|
||||||
|
|
||||||
|
int disk_flash_image(struct usb_device_info * dev, struct image * image);
|
||||||
|
int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file);
|
||||||
|
int disk_check_badblocks(struct usb_device_info * dev, const char * device);
|
||||||
|
|
||||||
|
#endif
|
||||||
-145
@@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007
|
|
||||||
* pancake <pancake@youterm.com>
|
|
||||||
*
|
|
||||||
* 0xFFFF 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.
|
|
||||||
*
|
|
||||||
* 0xFFFF 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 0xFFFF; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include <usb.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
int rf_extract(char *dev, off_t from, off_t to, char *file)
|
|
||||||
{
|
|
||||||
off_t i, blk = 0xfffff;
|
|
||||||
char buf[0xfffff];
|
|
||||||
FILE *fs = fopen(dev, "rb");
|
|
||||||
FILE *fd = fopen(file, "wb+");
|
|
||||||
|
|
||||||
if (from>to) {
|
|
||||||
printf("Bad range %lld - %lld for %s\n", from, to, file);
|
|
||||||
goto __rf_extract_exit;
|
|
||||||
}
|
|
||||||
if (fs == NULL) { perror(dev); goto __rf_extract_exit; }
|
|
||||||
if (fd == NULL) { perror(file); goto __rf_extract_exit; }
|
|
||||||
|
|
||||||
printf("%s: extracting...", file);
|
|
||||||
fflush(stdout);
|
|
||||||
fseek(fs, from, SEEK_SET);
|
|
||||||
|
|
||||||
for(i=from;i<to;i+=blk) {
|
|
||||||
int ret;
|
|
||||||
if (i+blk>to) blk = to-i;
|
|
||||||
ret = fread(buf, blk, 1, fs);
|
|
||||||
if (feof(fs)) break;
|
|
||||||
fwrite(buf, blk, 1, fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\r%s: %lld bytes dumped from %s\n",
|
|
||||||
file, to-from, dev);
|
|
||||||
|
|
||||||
__rf_extract_exit:
|
|
||||||
if (fs) fclose(fs);
|
|
||||||
if (fd) fclose(fd);
|
|
||||||
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rf_strip(char *file)
|
|
||||||
{
|
|
||||||
FILE *fd = fopen(file, "rw");
|
|
||||||
unsigned char buf[4096];
|
|
||||||
int ret;
|
|
||||||
off_t eof = 0;
|
|
||||||
|
|
||||||
if (!fd) {
|
|
||||||
fprintf(stderr, "Weird! can't open %s???\n", file);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
printf("Stripping padding from %s... ", file);
|
|
||||||
fflush(stdout);
|
|
||||||
fseek(fd, 0, SEEK_END);
|
|
||||||
|
|
||||||
do {
|
|
||||||
fseek(fd, -4096, SEEK_CUR);
|
|
||||||
ret = fread(buf, 1, 4096, fd);
|
|
||||||
fseek(fd, -4096, SEEK_CUR);
|
|
||||||
for(ret--;ret>0;ret--)
|
|
||||||
if (buf[ret]!=0xff) {
|
|
||||||
fseek(fd, ret+1, SEEK_CUR);
|
|
||||||
eof = ftell(fd);
|
|
||||||
goto __done;
|
|
||||||
}
|
|
||||||
} while(1);
|
|
||||||
|
|
||||||
__done:
|
|
||||||
fclose(fd);
|
|
||||||
if (eof) truncate(file, eof);
|
|
||||||
printf("done at %d\n", (int)eof);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_n800()
|
|
||||||
{
|
|
||||||
int n800 = 0;
|
|
||||||
unsigned char buf[4];
|
|
||||||
FILE *fd = fopen("/dev/mtd0", "rb");
|
|
||||||
|
|
||||||
if (!fd) {
|
|
||||||
fprintf(stderr, "Cannot open /dev/mtd0.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
fread(buf, 4, 1,fd);
|
|
||||||
if (!memcmp("\xff\xff\xff\xff", buf, 4))
|
|
||||||
n800 = 1;
|
|
||||||
|
|
||||||
fclose(fd);
|
|
||||||
|
|
||||||
return n800;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int reverse_extract_pieces(char *dir)
|
|
||||||
{
|
|
||||||
char reply;
|
|
||||||
chdir(dir);
|
|
||||||
|
|
||||||
rf_extract("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin");
|
|
||||||
rf_extract("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin");
|
|
||||||
rf_extract("/dev/mtd2", 0x000800, 0x200000, "zImage");
|
|
||||||
rf_extract("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2");
|
|
||||||
printf("\nWARNING: the rootfs extraction on n800 is known to be buggy! feedback is welcome.\n\n");
|
|
||||||
printf("Extract rootfs? (Y/n): "); fflush(stdout);
|
|
||||||
read(0, &reply, 1);
|
|
||||||
if (reply=='y'||reply=='Y')
|
|
||||||
rf_extract("/dev/mtd4", 0x000000, 0xffffff, "rootfs.jffs2");
|
|
||||||
else printf("*** Ignoring rootfs\n");
|
|
||||||
rf_strip("xloader.bin");
|
|
||||||
rf_strip("secondary.bin");
|
|
||||||
rf_strip("zImage");
|
|
||||||
rf_strip("initfs.jffs2");
|
|
||||||
printf("Identifying extracted files...\n");
|
|
||||||
printf("%s: xloader\n", fpid_file("xloader.bin"));
|
|
||||||
printf("%s: secondary.bin\n", fpid_file("secondary.bin"));
|
|
||||||
printf("%s: zImage\n", fpid_file("zImage"));
|
|
||||||
printf("%s: initfs.jffs2\n", fpid_file("initfs.jffs2"));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
+541
-105
@@ -1,136 +1,572 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2007
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
* pancake <pancake@youterm.com>
|
Copyright (C) 2007-2011 pancake <pancake@youterm.com>
|
||||||
*
|
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
* 0xFFFF is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
This program is free software: you can redistribute it and/or modify
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
it under the terms of the GNU General Public License as published by
|
||||||
* (at your option) any later version.
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
*
|
(at your option) any later version.
|
||||||
* 0xFFFF is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
This program is distributed in the hope that it will be useful,
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* GNU General Public License for more details.
|
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 0xFFFF; if not, write to the Free Software
|
You should have received a copy of the GNU General Public License
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#warning The FIASCO format is not yet fully implemented.
|
#include "global.h"
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "fiasco.h"
|
||||||
|
|
||||||
|
#define FIASCO_READ_ERROR(fiasco, ...) do { ERROR_INFO(__VA_ARGS__); fiasco_free(fiasco); return NULL; } while (0)
|
||||||
|
#define FIASCO_WRITE_ERROR(file, fd, ...) do { ERROR_INFO_STR(file, __VA_ARGS__); if ( fd >= 0 ) close(fd); return -1; } while (0)
|
||||||
|
#define READ_OR_FAIL(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) { FIASCO_READ_ERROR(fiasco, "Cannot read %d bytes", size); } } while (0)
|
||||||
|
#define READ_OR_RETURN(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; } while (0)
|
||||||
|
#define WRITE_OR_FAIL(file, fd, buf, size) do { if ( ! simulate ) { if ( write(fd, buf, size) != (ssize_t)size ) { FIASCO_WRITE_ERROR(file, fd, "Cannot write %d bytes", size); } } } while (0)
|
||||||
|
|
||||||
|
struct fiasco * fiasco_alloc_empty(void) {
|
||||||
|
|
||||||
|
struct fiasco * fiasco = calloc(1, sizeof(struct fiasco));
|
||||||
|
if ( ! fiasco )
|
||||||
|
ALLOC_ERROR_RETURN(NULL);
|
||||||
|
|
||||||
|
fiasco->fd = -1;
|
||||||
|
return fiasco;
|
||||||
|
|
||||||
off_t piece_header_to_size(unsigned char *header)
|
|
||||||
{
|
|
||||||
off_t sz = 0;
|
|
||||||
sz += header[0x15+3];
|
|
||||||
sz += header[0x15+2] << 8;
|
|
||||||
sz += header[0x15+1] << 16;
|
|
||||||
sz += header[0x15+0] << 24;
|
|
||||||
return sz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int piece_header_is_valid(unsigned char *header)
|
struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||||
{
|
|
||||||
if (header[0]=='T' && header[1]=='\x02')
|
uint8_t byte;
|
||||||
return 1;
|
uint32_t length;
|
||||||
return 0;
|
uint32_t count;
|
||||||
|
uint8_t length8;
|
||||||
|
uint8_t count8;
|
||||||
|
|
||||||
|
char type[13];
|
||||||
|
char device[17];
|
||||||
|
char hwrevs[1024];
|
||||||
|
char version[257];
|
||||||
|
char layout[257];
|
||||||
|
uint16_t hash;
|
||||||
|
off_t offset;
|
||||||
|
struct image * image;
|
||||||
|
|
||||||
|
char hwrev[9];
|
||||||
|
unsigned char buf[512];
|
||||||
|
unsigned char *pbuf;
|
||||||
|
|
||||||
|
struct fiasco * fiasco = fiasco_alloc_empty();
|
||||||
|
if ( ! fiasco )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fiasco->fd = open(file, O_RDONLY);
|
||||||
|
if ( fiasco->fd < 0 ) {
|
||||||
|
ERROR_INFO("Cannot open file");
|
||||||
|
fiasco_free(fiasco);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fiasco->orig_filename = strdup(file);
|
||||||
|
|
||||||
|
READ_OR_FAIL(fiasco, &byte, 1);
|
||||||
|
if ( byte != 0xb4 )
|
||||||
|
FIASCO_READ_ERROR(fiasco, "Invalid fiasco signature");
|
||||||
|
|
||||||
|
READ_OR_FAIL(fiasco, &length, 4);
|
||||||
|
length = ntohl(length);
|
||||||
|
|
||||||
|
READ_OR_FAIL(fiasco, &count, 4);
|
||||||
|
count = ntohl(count);
|
||||||
|
|
||||||
|
VERBOSE("Number of header blocks: %d\n", count);
|
||||||
|
|
||||||
|
while ( count > 0 ) {
|
||||||
|
READ_OR_FAIL(fiasco, &byte, 1);
|
||||||
|
READ_OR_FAIL(fiasco, &length8, 1);
|
||||||
|
READ_OR_FAIL(fiasco, buf, length8);
|
||||||
|
if ( byte == 0xe8 ) {
|
||||||
|
memset(fiasco->name, 0, sizeof(fiasco->name));
|
||||||
|
strncpy(fiasco->name, (char *)buf, length8);
|
||||||
|
VERBOSE("Fiasco name: %s\n", fiasco->name);
|
||||||
|
} else if ( byte == 0x31 ) {
|
||||||
|
memset(fiasco->swver, 0, sizeof(fiasco->swver));
|
||||||
|
strncpy(fiasco->swver, (char *)buf, length8);
|
||||||
|
VERBOSE("SW version: %s\n", fiasco->swver);
|
||||||
|
} else {
|
||||||
|
VERBOSE("Unknown header %#x\n", byte);
|
||||||
|
}
|
||||||
|
--count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* walk the tree */
|
||||||
|
while ( 1 ) {
|
||||||
|
|
||||||
|
/* If end of file, return fiasco image */
|
||||||
|
READ_OR_RETURN(fiasco, buf, 7);
|
||||||
|
|
||||||
|
/* Header of next image */
|
||||||
|
if ( ! buf[0] == 0x54 && buf[2] == 0x2E && buf[3] == 0x19 && buf[4] == 0x01 && buf[5] == 0x01 && buf[6] == 0x00 ) {
|
||||||
|
ERROR("Invalid next image header");
|
||||||
|
return fiasco;
|
||||||
|
}
|
||||||
|
|
||||||
|
count8 = buf[1];
|
||||||
|
if ( count8 > 0 )
|
||||||
|
--count8;
|
||||||
|
|
||||||
|
READ_OR_RETURN(fiasco, &hash, 2);
|
||||||
|
hash = ntohs(hash);
|
||||||
|
|
||||||
|
memset(type, 0, sizeof(type));
|
||||||
|
READ_OR_RETURN(fiasco, type, 12);
|
||||||
|
|
||||||
|
byte = type[0];
|
||||||
|
if ( byte == 0xFF )
|
||||||
|
return fiasco;
|
||||||
|
|
||||||
|
VERBOSE(" %s\n", type);
|
||||||
|
|
||||||
|
READ_OR_RETURN(fiasco, &length, 4);
|
||||||
|
length = ntohl(length);
|
||||||
|
|
||||||
|
/* unknown */
|
||||||
|
READ_OR_RETURN(fiasco, buf, 4);
|
||||||
|
|
||||||
|
VERBOSE(" size: %d bytes\n", length);
|
||||||
|
VERBOSE(" hash: %#04x\n", hash);
|
||||||
|
VERBOSE(" subsections: %d\n", count8);
|
||||||
|
|
||||||
|
memset(device, 0, sizeof(device));
|
||||||
|
memset(hwrevs, 0, sizeof(hwrevs));
|
||||||
|
memset(version, 0, sizeof(version));
|
||||||
|
memset(layout, 0, sizeof(layout));
|
||||||
|
|
||||||
|
while ( count8 > 0 ) {
|
||||||
|
|
||||||
|
READ_OR_RETURN(fiasco, &byte, 1);
|
||||||
|
READ_OR_RETURN(fiasco, &length8, 1);
|
||||||
|
READ_OR_RETURN(fiasco, buf, length8);
|
||||||
|
|
||||||
|
VERBOSE(" subinfo\n");
|
||||||
|
VERBOSE(" length: %d\n", length8);
|
||||||
|
VERBOSE(" type: ");
|
||||||
|
|
||||||
|
if ( byte == '1' ) {
|
||||||
|
memset(version, 0, sizeof(version));
|
||||||
|
strncpy(version, (char *)buf, length8);
|
||||||
|
VERBOSE("version string\n");
|
||||||
|
VERBOSE(" version: %s\n", version);
|
||||||
|
} else if ( byte == '2' ) {
|
||||||
|
int tmp = length8;
|
||||||
|
if ( tmp > 16 ) tmp = 16;
|
||||||
|
memset(device, 0, sizeof(device));
|
||||||
|
strncpy(device, (char *)buf, tmp);
|
||||||
|
VERBOSE("hw revision\n");
|
||||||
|
VERBOSE(" device: %s\n", device);
|
||||||
|
pbuf = buf + strlen(device) + 1;
|
||||||
|
while ( pbuf < buf + length8 ) {
|
||||||
|
while ( pbuf < buf + length8 && *pbuf < 32 )
|
||||||
|
++pbuf;
|
||||||
|
if ( pbuf >= buf + length8 ) break;
|
||||||
|
tmp = buf + length8 - pbuf;
|
||||||
|
if ( tmp > 8 ) tmp = 8;
|
||||||
|
memset(hwrev, 0, sizeof(hwrev));
|
||||||
|
strncpy(hwrev, (char *)pbuf, tmp);
|
||||||
|
if ( ! hwrevs[0] )
|
||||||
|
strcpy(hwrevs, hwrev);
|
||||||
|
else {
|
||||||
|
/* TODO: check if hwrevs has enough size */
|
||||||
|
strcat(hwrevs, ",");
|
||||||
|
strcat(hwrevs, hwrev);
|
||||||
|
}
|
||||||
|
VERBOSE(" hw revision: %s\n", hwrev);
|
||||||
|
pbuf += strlen(hwrev) + 1;
|
||||||
|
}
|
||||||
|
} else if ( byte == '3' ) {
|
||||||
|
memset(layout, 0, sizeof(layout));
|
||||||
|
strncpy(layout, (char *)buf, length8);
|
||||||
|
VERBOSE("layout\n");
|
||||||
|
} else {
|
||||||
|
VERBOSE("unknown ('%c':%#x)\n", byte, byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
--count8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* unknown */
|
||||||
|
READ_OR_RETURN(fiasco, buf, 1);
|
||||||
|
|
||||||
|
offset = lseek(fiasco->fd, 0, SEEK_CUR);
|
||||||
|
|
||||||
|
VERBOSE(" version: %s\n", version);
|
||||||
|
VERBOSE(" device: %s\n", device);
|
||||||
|
VERBOSE(" hwrevs: %s\n", hwrevs);
|
||||||
|
VERBOSE(" data at: %#08x\n", (unsigned int)offset);
|
||||||
|
|
||||||
|
image = image_alloc_from_shared_fd(fiasco->fd, length, offset, hash, type, device, hwrevs, version, layout);
|
||||||
|
|
||||||
|
if ( ! image )
|
||||||
|
FIASCO_READ_ERROR(fiasco, "Cannot allocate image");
|
||||||
|
|
||||||
|
fiasco_add_image(fiasco, image);
|
||||||
|
|
||||||
|
lseek(fiasco->fd, offset+length, SEEK_SET);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return fiasco;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define piece_header_to_name(x) x+0x9;
|
void fiasco_free(struct fiasco * fiasco) {
|
||||||
|
|
||||||
/*
|
struct image_list * list = fiasco->first;
|
||||||
* Teh Fiasco firmware parser lives here!
|
|
||||||
*/
|
|
||||||
int fiasco_read_image(char *file)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
unsigned char header[5];
|
|
||||||
unsigned char version[55];
|
|
||||||
char *version2;
|
|
||||||
|
|
||||||
fd = open(file, O_RDONLY);
|
while ( list ) {
|
||||||
|
struct image_list * next = list->next;
|
||||||
|
image_list_del(list);
|
||||||
|
list = next;
|
||||||
|
}
|
||||||
|
|
||||||
printf("WARNING: Fiasco firmware is not yet fully supported. Don't relay on it ATM.\n");
|
if ( fiasco->fd >= 0 )
|
||||||
|
close(fiasco->fd);
|
||||||
|
|
||||||
if (fd == -1) {
|
free(fiasco->orig_filename);
|
||||||
printf("Cannot open fiasco image.\n");
|
|
||||||
|
free(fiasco);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void fiasco_add_image(struct fiasco * fiasco, struct image * image) {
|
||||||
|
|
||||||
|
image_list_add(&fiasco->first, image);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
|
||||||
|
|
||||||
|
int fd = -1;
|
||||||
|
int i;
|
||||||
|
int device_count;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t length;
|
||||||
|
uint16_t hash;
|
||||||
|
uint8_t length8;
|
||||||
|
char ** device_hwrevs_bufs;
|
||||||
|
const char * str;
|
||||||
|
const char * type;
|
||||||
|
struct image_list * image_list;
|
||||||
|
struct image * image;
|
||||||
|
unsigned char buf[4096];
|
||||||
|
|
||||||
|
if ( ! fiasco )
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
// b4 00 00 00 00 36
|
printf("Generating Fiasco image %s...\n", file);
|
||||||
if (read(fd, header, 5) != 5) {
|
|
||||||
printf("Error reading fiasco header\n");
|
|
||||||
goto __fiasco_read_image_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header[0] != 0xb4) {
|
if ( ! fiasco->first )
|
||||||
printf("Invalid fiasco signature.\n");
|
FIASCO_WRITE_ERROR(file, fd, "Nothing to write");
|
||||||
goto __fiasco_read_image_end;
|
|
||||||
}
|
|
||||||
// skip 6 bytes
|
|
||||||
read(fd, version, 6);
|
|
||||||
|
|
||||||
// print version header
|
if ( fiasco->name && strlen(fiasco->name)+1 > UINT8_MAX )
|
||||||
if (read(fd, version, 55) != 55) {
|
FIASCO_WRITE_ERROR(file, fd, "Fiasco name string is too long");
|
||||||
printf("Error reading fiasco version.\n");
|
|
||||||
goto __fiasco_read_image_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("# Fiasco header information:\n");
|
if ( fiasco->swver && strlen(fiasco->swver)+1 > UINT8_MAX )
|
||||||
printf("# ==========================\n");
|
FIASCO_WRITE_ERROR(file, fd, "SW version string is too long");
|
||||||
printf("# firmware type: %s\n", version);
|
|
||||||
version2 = version+strlen((char *)version)+3;
|
|
||||||
if (*version2=='.')
|
|
||||||
printf("firmware version: (null) (old firmware? no version string found?)\n");
|
|
||||||
else printf("firmware version: %s\n", version2);
|
|
||||||
|
|
||||||
// pieces:
|
if ( ! simulate ) {
|
||||||
// after the version2 string starts the header-body loop love
|
fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0644);
|
||||||
lseek(fd, 0xf + strlen(version2) + strlen(version), SEEK_SET);
|
if ( fd < 0 ) {
|
||||||
do {
|
ERROR_INFO("Cannot create file");
|
||||||
char piece_header[30];
|
return -1;
|
||||||
char description[256];
|
|
||||||
unsigned char desc_len;
|
|
||||||
char *name;
|
|
||||||
off_t size;
|
|
||||||
off_t tmp = lseek(fd, 0, SEEK_CUR);
|
|
||||||
|
|
||||||
size = read(fd, piece_header, 30);
|
|
||||||
if (size != 30) {
|
|
||||||
fprintf(stderr, "Unexpected end of file\n");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
dump_bytes(piece_header,30);
|
}
|
||||||
if (!piece_header_is_valid(piece_header)) {
|
|
||||||
fprintf(stderr, "Oops. Invalid piece header.\n");
|
printf("Writing Fiasco header...\n");
|
||||||
break;
|
|
||||||
|
WRITE_OR_FAIL(file, fd, "\xb4", 1); /* signature */
|
||||||
|
|
||||||
|
if ( fiasco->name[0] )
|
||||||
|
str = fiasco->name;
|
||||||
|
else
|
||||||
|
str = "OSSO UART+USB";
|
||||||
|
|
||||||
|
length = 4 + strlen(str) + 3;
|
||||||
|
if ( fiasco->swver[0] )
|
||||||
|
length += strlen(fiasco->swver) + 3;
|
||||||
|
length = htonl(length);
|
||||||
|
WRITE_OR_FAIL(file, fd, &length, 4); /* FW header length */
|
||||||
|
|
||||||
|
if ( fiasco->swver[0] )
|
||||||
|
length = htonl(2);
|
||||||
|
else
|
||||||
|
length = htonl(1);
|
||||||
|
WRITE_OR_FAIL(file, fd, &length, 4); /* FW header blocks count */
|
||||||
|
|
||||||
|
/* Fiasco name */
|
||||||
|
length8 = strlen(str)+1;
|
||||||
|
WRITE_OR_FAIL(file, fd, "\xe8", 1);
|
||||||
|
WRITE_OR_FAIL(file, fd, &length8, 1);
|
||||||
|
WRITE_OR_FAIL(file, fd, str, length8);
|
||||||
|
|
||||||
|
/* SW version */
|
||||||
|
if ( fiasco->swver[0] ) {
|
||||||
|
printf("Writing SW version: %s\n", fiasco->swver);
|
||||||
|
length8 = strlen(fiasco->swver)+1;
|
||||||
|
WRITE_OR_FAIL(file, fd, "\x31", 1);
|
||||||
|
WRITE_OR_FAIL(file, fd, &length8, 1);
|
||||||
|
WRITE_OR_FAIL(file, fd, fiasco->swver, length8);
|
||||||
|
};
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
image_list = fiasco->first;
|
||||||
|
|
||||||
|
while ( image_list ) {
|
||||||
|
|
||||||
|
image = image_list->image;
|
||||||
|
|
||||||
|
if ( ! image )
|
||||||
|
FIASCO_WRITE_ERROR(file, fd, "Empty image");
|
||||||
|
|
||||||
|
printf("Writing image...\n");
|
||||||
|
image_print_info(image);
|
||||||
|
|
||||||
|
type = image_type_to_string(image->type);
|
||||||
|
|
||||||
|
device_hwrevs_bufs = device_list_alloc_to_bufs(image->devices);
|
||||||
|
|
||||||
|
device_count = 0;
|
||||||
|
if ( device_hwrevs_bufs && device_hwrevs_bufs[0] )
|
||||||
|
for ( ; device_hwrevs_bufs[device_count]; ++device_count );
|
||||||
|
|
||||||
|
if ( ! type )
|
||||||
|
FIASCO_WRITE_ERROR(file, fd, "Unknown image type");
|
||||||
|
|
||||||
|
if ( image->version && strlen(image->version) > UINT8_MAX )
|
||||||
|
FIASCO_WRITE_ERROR(file, fd, "Image version string is too long");
|
||||||
|
|
||||||
|
if ( image->layout && strlen(image->layout) > UINT8_MAX )
|
||||||
|
FIASCO_WRITE_ERROR(file, fd, "Image layout is too long");
|
||||||
|
|
||||||
|
printf("Writing image header...\n");
|
||||||
|
|
||||||
|
/* signature */
|
||||||
|
WRITE_OR_FAIL(file, fd, "T", 1);
|
||||||
|
|
||||||
|
/* number of subsections */
|
||||||
|
length8 = device_count+1;
|
||||||
|
if ( image->version )
|
||||||
|
++length8;
|
||||||
|
if ( image->layout )
|
||||||
|
++length8;
|
||||||
|
WRITE_OR_FAIL(file, fd, &length8, 1);
|
||||||
|
|
||||||
|
/* unknown */
|
||||||
|
WRITE_OR_FAIL(file, fd, "\x2e\x19\x01\x01\x00", 5);
|
||||||
|
|
||||||
|
/* checksum */
|
||||||
|
hash = htons(image->hash);
|
||||||
|
WRITE_OR_FAIL(file, fd, &hash, 2);
|
||||||
|
|
||||||
|
/* image type name */
|
||||||
|
memset(buf, 0, 12);
|
||||||
|
strncpy((char *)buf, type, 12);
|
||||||
|
WRITE_OR_FAIL(file, fd, buf, 12);
|
||||||
|
|
||||||
|
/* image size */
|
||||||
|
size = htonl(image->size);
|
||||||
|
WRITE_OR_FAIL(file, fd, &size, 4);
|
||||||
|
|
||||||
|
/* unknown */
|
||||||
|
WRITE_OR_FAIL(file, fd, "\x00\x00\x00\x00", 4);
|
||||||
|
|
||||||
|
/* append version subsection */
|
||||||
|
if ( image->version ) {
|
||||||
|
WRITE_OR_FAIL(file, fd, "1", 1); /* 1 - version */
|
||||||
|
length8 = strlen(image->version)+1;
|
||||||
|
WRITE_OR_FAIL(file, fd, &length8, 1);
|
||||||
|
WRITE_OR_FAIL(file, fd, image->version, length8);
|
||||||
}
|
}
|
||||||
size = piece_header_to_size(piece_header);
|
|
||||||
name = piece_header_to_name(piece_header);
|
|
||||||
printf("# %s is %lld bytes\n", name, size);
|
|
||||||
|
|
||||||
read(fd, description, 255);
|
/* append device & hwrevs subsection */
|
||||||
printf("# version: %s\n", description);
|
for ( i = 0; i < device_count; ++i ) {
|
||||||
/* lseek foreach subimage */
|
WRITE_OR_FAIL(file, fd, "2", 1); /* 2 - device & hwrevs */
|
||||||
lseek(fd, tmp, SEEK_SET);
|
WRITE_OR_FAIL(file, fd, &device_hwrevs_bufs[i][0], 1);
|
||||||
lseek(fd, strlen(description) + 0x20, SEEK_CUR);
|
WRITE_OR_FAIL(file, fd, device_hwrevs_bufs[i]+1, ((uint8_t *)(device_hwrevs_bufs[i]))[0]);
|
||||||
printf("rsc '%s' %lld '%s.bin' 0 %lld\n", file, lseek(fd,0,SEEK_CUR), name, size);
|
}
|
||||||
lseek(fd, size, SEEK_CUR);
|
free(device_hwrevs_bufs);
|
||||||
} while(1);
|
|
||||||
|
|
||||||
//printf("Image '%s', size %d bytes.\n", image, size);
|
/* append layout subsection */
|
||||||
|
if ( image->layout ) {
|
||||||
|
length8 = strlen(image->layout);
|
||||||
|
WRITE_OR_FAIL(file, fd, "3", 1); /* 3 - layout */
|
||||||
|
WRITE_OR_FAIL(file, fd, &length8, 1);
|
||||||
|
WRITE_OR_FAIL(file, fd, image->layout, length8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dummy byte - end of all subsections */
|
||||||
|
WRITE_OR_FAIL(file, fd, "\x00", 1);
|
||||||
|
|
||||||
|
printf("Writing image data...\n");
|
||||||
|
|
||||||
|
image_seek(image, 0);
|
||||||
|
while ( 1 ) {
|
||||||
|
size = image_read(image, buf, sizeof(buf));
|
||||||
|
if ( size == 0 )
|
||||||
|
break;
|
||||||
|
WRITE_OR_FAIL(file, fd, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
image_list = image_list->next;
|
||||||
|
|
||||||
|
if ( image_list )
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
__fiasco_read_image_end:
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
printf("\nDone\n\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
|
||||||
|
|
||||||
|
int fd = -1;
|
||||||
|
char * name = NULL;
|
||||||
|
char * layout_name = NULL;
|
||||||
|
struct image * image;
|
||||||
|
struct image_list * image_list;
|
||||||
|
uint32_t size;
|
||||||
|
char cwd[256];
|
||||||
|
unsigned char buf[4096];
|
||||||
|
|
||||||
|
if ( dir ) {
|
||||||
|
|
||||||
|
memset(cwd, 0, sizeof(cwd));
|
||||||
|
|
||||||
|
if ( ! getcwd(cwd, sizeof(cwd)) ) {
|
||||||
|
ERROR_INFO("Cannot store current directory");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( chdir(dir) < 0 ) {
|
||||||
|
ERROR_INFO("Cannot change current directory to %s", dir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fiasco_print_info(fiasco);
|
||||||
|
|
||||||
|
image_list = fiasco->first;
|
||||||
|
|
||||||
|
while ( image_list ) {
|
||||||
|
|
||||||
|
image = image_list->image;
|
||||||
|
|
||||||
|
name = image_name_alloc_from_values(image);
|
||||||
|
if ( ! name )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
printf("Unpacking image...\n");
|
||||||
|
image_print_info(image);
|
||||||
|
|
||||||
|
if ( image->layout ) {
|
||||||
|
|
||||||
|
layout_name = calloc(1, strlen(name) + strlen(".layout") + 1);
|
||||||
|
if ( ! layout_name )
|
||||||
|
ALLOC_ERROR_RETURN(-1);
|
||||||
|
|
||||||
|
sprintf(layout_name, "%s.layout", name);
|
||||||
|
|
||||||
|
printf(" Layout file: %s\n", layout_name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" Output file: %s\n", name);
|
||||||
|
|
||||||
|
if ( ! simulate ) {
|
||||||
|
fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644);
|
||||||
|
if ( fd < 0 ) {
|
||||||
|
ERROR_INFO("Cannot create output file %s", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
image_seek(image, 0);
|
||||||
|
while ( 1 ) {
|
||||||
|
size = image_read(image, buf, sizeof(buf));
|
||||||
|
if ( size == 0 )
|
||||||
|
break;
|
||||||
|
WRITE_OR_FAIL(name, fd, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if ( image->layout ) {
|
||||||
|
|
||||||
|
if ( ! simulate ) {
|
||||||
|
fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644);
|
||||||
|
if ( fd < 0 ) {
|
||||||
|
ERROR_INFO("Cannot create layout file %s", layout_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(layout_name);
|
||||||
|
|
||||||
|
WRITE_OR_FAIL(layout_name, fd, image->layout, (int)strlen(image->layout));
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
image_list = image_list->next;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dir ) {
|
||||||
|
if ( chdir(cwd) < 0 ) {
|
||||||
|
ERROR_INFO("Cannot change current directory back to %s", cwd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nDone\n\n");
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void fiasco_print_info(struct fiasco * fiasco) {
|
||||||
|
|
||||||
|
if ( fiasco->orig_filename )
|
||||||
|
printf("File: %s\n", fiasco->orig_filename);
|
||||||
|
|
||||||
|
if ( fiasco->name[0] )
|
||||||
|
printf(" Fiasco Name: %s\n", fiasco->name);
|
||||||
|
|
||||||
|
if ( fiasco->swver[0] )
|
||||||
|
printf(" Fiasco Software release version: %s\n", fiasco->swver);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2007-2011 pancake <pancake@youterm.com>
|
||||||
|
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FIASCO_H
|
||||||
|
#define FIASCO_H
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
struct fiasco {
|
||||||
|
char name[257];
|
||||||
|
char swver[257];
|
||||||
|
int fd;
|
||||||
|
char * orig_filename;
|
||||||
|
struct image_list * first;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fiasco * fiasco_alloc_empty(void);
|
||||||
|
struct fiasco * fiasco_alloc_from_file(const char * file);
|
||||||
|
void fiasco_free(struct fiasco * fiasco);
|
||||||
|
void fiasco_add_image(struct fiasco * fiasco, struct image * image);
|
||||||
|
int fiasco_write_to_file(struct fiasco * fiasco, const char * file);
|
||||||
|
int fiasco_unpack(struct fiasco * fiasco, const char * dir);
|
||||||
|
void fiasco_print_info(struct fiasco * fiasco);
|
||||||
|
|
||||||
|
#endif
|
||||||
-167
@@ -1,167 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007
|
|
||||||
* pancake <pancake@youterm.com>
|
|
||||||
*
|
|
||||||
* 0xFFFF 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.
|
|
||||||
*
|
|
||||||
* 0xFFFF 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 0xFFFF; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "hash.h"
|
|
||||||
#include <usb.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void check_nolo_order_failed()
|
|
||||||
{
|
|
||||||
fprintf(stderr, "\nERROR: Provide xloader before the secondary. NOLO disagrees anything else.\n");
|
|
||||||
fprintf(stderr, "Use: -p xloader.bin -p secondary.bin\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void check_nolo_order()
|
|
||||||
{
|
|
||||||
int i, xlo = 0;
|
|
||||||
|
|
||||||
for(i=0;i<pcs_n;i++) {
|
|
||||||
if (!strcmp(pcs[i].type, "xloader")) {
|
|
||||||
if (!xlo && ++i<pcs_n) {
|
|
||||||
printf("CHK%s\n", pcs[i].type);
|
|
||||||
xlo++;
|
|
||||||
if (!strcmp(pcs[i].type, "secondary")) {
|
|
||||||
xlo = 0x11;
|
|
||||||
break;
|
|
||||||
} else check_nolo_order_failed();
|
|
||||||
} check_nolo_order_failed();
|
|
||||||
} else
|
|
||||||
if (!strcmp(pcs[i].type, "secondary"))
|
|
||||||
check_nolo_order_failed();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xlo && xlo != 0x11)
|
|
||||||
check_nolo_order_failed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void flash_image(char *filename, char *piece, char *version)
|
|
||||||
{
|
|
||||||
FILE *fd;
|
|
||||||
int vlen = 0;
|
|
||||||
int request;
|
|
||||||
/*/ n800 flash queries have a variable size */
|
|
||||||
unsigned char fquery[256]; /* flash query */
|
|
||||||
unsigned long long size, off;
|
|
||||||
unsigned char bsize[4], tmp;
|
|
||||||
unsigned char nolofiller[128];
|
|
||||||
ushort hash = do_hash_file(filename);
|
|
||||||
|
|
||||||
if (version)
|
|
||||||
vlen = strlen(version)+1;
|
|
||||||
|
|
||||||
fd = fopen(filename, "rb");
|
|
||||||
if (fd == NULL) {
|
|
||||||
printf("Cannot open file\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* cook flash query */
|
|
||||||
memset(fquery, '\x00', 27); // reset buffer
|
|
||||||
memcpy(fquery, "\x2e\x19\x01\x01", 4); // header
|
|
||||||
//memcpy(fquery+5, "\xbf\x6b", 2); // some magic (modified crc16???)
|
|
||||||
memcpy(fquery+5, &hash, 2);
|
|
||||||
tmp = fquery[5]; fquery[5] = fquery[6]; fquery[6] = tmp;
|
|
||||||
memcpy(fquery+7, piece, strlen(piece)); // XXX ??!??
|
|
||||||
|
|
||||||
printf("| hash: 0x%hhx%hhx ", fquery[5], fquery[6]);
|
|
||||||
size = get_file_size(filename);
|
|
||||||
bsize[0] = (size & 0xff000000) >> 24;
|
|
||||||
bsize[1] = (size & 0x00ff0000) >> 16;
|
|
||||||
bsize[2] = (size & 0x0000ff00) >> 8;
|
|
||||||
bsize[3] = (size & 0x000000ff);
|
|
||||||
printf("size: %lld (%02x %02x %02x %02x)\n",
|
|
||||||
size, bsize[0], bsize[1], bsize[2], bsize[3]);
|
|
||||||
memcpy(fquery+0x13, &bsize, 4);
|
|
||||||
if (vlen) memcpy(fquery+27, version, vlen);
|
|
||||||
|
|
||||||
if (!strcmp(piece, "rootfs"))
|
|
||||||
request = 85;
|
|
||||||
else request = 68;
|
|
||||||
|
|
||||||
//dump_bytes(fquery, 27+vlen);
|
|
||||||
if (usb_control_msg(dev, CMD_WRITE, request, 0, 0, (char *)fquery, 27+vlen, 2000) <0) {
|
|
||||||
perror("flash_image.header");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*/ cook and bulk nollo filler */
|
|
||||||
memset(&nolofiller, '\xff', 128);
|
|
||||||
memcpy(nolofiller+0x00, "NOLO filler", 11);
|
|
||||||
memcpy(nolofiller+0x40, "NOLO filler", 11);
|
|
||||||
usb_bulk_write(dev, 2, (char *)nolofiller, 128, 5000);
|
|
||||||
usb_bulk_write(dev, 2, (char *)nolofiller, 0, 5000);
|
|
||||||
|
|
||||||
/*/ bulk write image here */
|
|
||||||
printf("[=] Bulkwriting the %s piece...\n", piece);
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
for(off = 0; off<size; off += BSIZE) {
|
|
||||||
char buf[BSIZE];
|
|
||||||
int bread, bsize = size-off;
|
|
||||||
if (bsize>BSIZE) bsize = BSIZE;
|
|
||||||
bread = fread(buf, bsize, 1, fd);
|
|
||||||
if (bread != 1)
|
|
||||||
printf("WARNING: Oops wrong read %d vs %d \n", bread, bsize);
|
|
||||||
bread = usb_bulk_write(dev, 2, buf, bsize, 5000);
|
|
||||||
progressbar(off, size);
|
|
||||||
if (bread<0) perror(" -ee- ");
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
fclose(fd);
|
|
||||||
/*/ EOF */
|
|
||||||
usb_bulk_write(dev, 2, (char *)nolofiller, 0, 1000);
|
|
||||||
progressbar(1, 1);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
// index = 4????
|
|
||||||
if (!strcmp(piece, "rootfs")) {
|
|
||||||
if (usb_control_msg(dev, CMD_WRITE, 82, 0, 0, (char *)fquery, 0, 30000)<0) {
|
|
||||||
fprintf(stderr, "Oops. Invalid checksum?\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int t = 0;
|
|
||||||
if (!strcmp(piece, "secondary"))
|
|
||||||
t = 1;
|
|
||||||
else
|
|
||||||
if (!strcmp(piece, "kernel"))
|
|
||||||
t = 3;
|
|
||||||
else
|
|
||||||
if (!strcmp(piece, "initfs"))
|
|
||||||
t = 4;
|
|
||||||
if (!strcmp(piece, "xloader"))
|
|
||||||
printf("xloader flashed not commiting until secondary arrives...\n");
|
|
||||||
else
|
|
||||||
if (usb_control_msg(dev, CMD_WRITE, 80, 0, t, (char *)fquery, 0, 10000)<0) {
|
|
||||||
fprintf(stderr, "Oops. Invalid checksum?\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// unknown query !! :""
|
|
||||||
if (usb_control_msg(dev, CMD_WRITE, 67, 0, 0, (char *)fquery, 0, 2000)<0) {
|
|
||||||
fprintf(stderr, "Oops, the flash was denied or so :/\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
printf("Flash done succesfully.\n");
|
|
||||||
}
|
|
||||||
-75
@@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007
|
|
||||||
* pancake <pancake@youterm.com>
|
|
||||||
*
|
|
||||||
* 0xFFFF 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.
|
|
||||||
*
|
|
||||||
* 0xFFFF 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 0xFFFF; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
char *fpid_file(char *filename)
|
|
||||||
{
|
|
||||||
FILE *fd;
|
|
||||||
char buf[512];
|
|
||||||
unsigned char *b = (unsigned char *)&buf;
|
|
||||||
char *piece = NULL;
|
|
||||||
long size;
|
|
||||||
|
|
||||||
// 2nd : +0x34 = 2NDAPE
|
|
||||||
// secondary: +0x04 = NOLOScnd
|
|
||||||
// x-loader : +0x14 = X-LOADER
|
|
||||||
// xloader8 : +0x0c = NOLOXldr
|
|
||||||
// kernel : +0x00 = 0000 a0e1 0000 a0e1
|
|
||||||
// initfs : <2M...be sure with 3M 0x300000
|
|
||||||
|
|
||||||
fd = fopen(filename, "r");
|
|
||||||
if (fd == NULL) {
|
|
||||||
printf("Cannot open file '%s'\n", filename);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
fread(buf, 512, 1, fd);
|
|
||||||
fseek(fd, 0, SEEK_END);
|
|
||||||
size = ftell(fd);
|
|
||||||
fclose(fd);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (!memcmp(b+0x34, "2NDAPE", 6))
|
|
||||||
return PIECE_2ND;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (!memcmp(b+0x04, "NOLOScnd", 8))
|
|
||||||
return pieces[PIECE_SECONDARY];
|
|
||||||
else
|
|
||||||
if (!memcmp(b+0x14, "X-LOADER", 8))
|
|
||||||
return pieces[PIECE_XLOADER];
|
|
||||||
else
|
|
||||||
if (!memcmp(b+0x0c, "NOLOXldr", 8)) // TODO: this is xloader800, not valid on 770?
|
|
||||||
return pieces[PIECE_XLOADER];
|
|
||||||
else
|
|
||||||
if (!memcmp(b+0x00, "\x00\x00\xa0\xe1\x00\x00\xa0\xe1", 8))
|
|
||||||
return pieces[PIECE_KERNEL];
|
|
||||||
else
|
|
||||||
if (!memcmp(b+0x00, "\x85\x19\x01\xe0", 4)) {
|
|
||||||
/*/ is jffs2 */
|
|
||||||
if (size < 0x300000)
|
|
||||||
return pieces[PIECE_INITFS];
|
|
||||||
return pieces[PIECE_ROOTFS];
|
|
||||||
}
|
|
||||||
|
|
||||||
return piece;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
#ifndef GLOBAL_H
|
||||||
|
#define GLOBAL_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
extern int simulate;
|
||||||
|
extern int noverify;
|
||||||
|
extern int verbose;
|
||||||
|
|
||||||
|
#define VERBOSE(...) do { if ( verbose ) { fprintf(stderr, __VA_ARGS__); } } while (0)
|
||||||
|
#define WARNING(...) do { fprintf(stderr, "Warning: "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); } while (0)
|
||||||
|
#define ERROR_INFO_STR(str, ...) do { if ( str[0] ) fprintf(stderr, "Error: %s: ", str); else fprintf(stderr, "Error: "); fprintf(stderr, __VA_ARGS__); if ( errno ) fprintf(stderr, ": %s\n", strerror(errno)); else fprintf(stderr, "\n"); } while (0)
|
||||||
|
#define ERROR_STR(str, ...) do { errno = 0; ERROR_INFO_STR(str, __VA_ARGS__); } while (0)
|
||||||
|
#define ERROR_INFO(...) do { ERROR_INFO_STR("", __VA_ARGS__); } while (0)
|
||||||
|
#define ERROR(...) do { ERROR_STR("", __VA_ARGS__); } while (0)
|
||||||
|
#define ERROR_RETURN(str, ...) do { ERROR("%s", str); return __VA_ARGS__; } while (0)
|
||||||
|
|
||||||
|
#define ALLOC_ERROR() do { ERROR("Cannot allocate memory"); } while (0)
|
||||||
|
#define ALLOC_ERROR_RETURN(...) do { ALLOC_ERROR(); return __VA_ARGS__; } while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
-62
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007
|
|
||||||
* pancake <pancake@youterm.com>
|
|
||||||
*
|
|
||||||
* 0xFFFF 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.
|
|
||||||
*
|
|
||||||
* 0xFFFF 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 0xFFFF; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "hash.h"
|
|
||||||
|
|
||||||
usho do_hash(usho *b, int len)
|
|
||||||
{
|
|
||||||
usho result = 0;
|
|
||||||
for(len>>=1;len--;b=b+1)
|
|
||||||
result^=b[0];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
usho do_hash_file(char *filename)
|
|
||||||
{
|
|
||||||
unsigned char buf[BSIZE];
|
|
||||||
FILE *fd = fopen(filename, "r");
|
|
||||||
usho hash = 0;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (fd == NULL) {
|
|
||||||
fprintf(stderr, "ERROR: File '%s' not found.\n", filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
do { ret = fread(&buf, 1, BSIZE, fd);
|
|
||||||
if (ret == -1)
|
|
||||||
return 0;
|
|
||||||
hash ^= do_hash((usho *)&buf, ret);
|
|
||||||
} while(ret);
|
|
||||||
|
|
||||||
fclose(fd);
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
main()
|
|
||||||
{
|
|
||||||
usho us = do_hash_file("zImage");
|
|
||||||
unsigned char *h= (unsigned char *)&us;
|
|
||||||
printf("%x %x\n",h[0],h[1]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
#ifndef _INCLUDE_HASH_H_
|
|
||||||
#define _INCLUDE_HASH_H_
|
|
||||||
|
|
||||||
#define usho unsigned short
|
|
||||||
#define BSIZE 0x20000
|
|
||||||
|
|
||||||
usho do_hash(usho *b, int len);
|
|
||||||
usho do_hash_file(char *filename);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2006-2007
|
|
||||||
* pancake <pancake@youterm.com>
|
|
||||||
*
|
|
||||||
* radare 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.
|
|
||||||
*
|
|
||||||
* radare 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 radare; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "hexdump.h"
|
|
||||||
|
|
||||||
char getprintablechar(char a)
|
|
||||||
{
|
|
||||||
if (a>=' '&&a<='~')
|
|
||||||
return a;
|
|
||||||
return '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_printable (int c)
|
|
||||||
{
|
|
||||||
if (c<' '||c>'~') return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper function
|
|
||||||
*/
|
|
||||||
void dump_bytes(unsigned char *buf, int len)
|
|
||||||
{
|
|
||||||
int i,j,seek = 0;
|
|
||||||
int inc = 16;
|
|
||||||
|
|
||||||
for(i=0; i<len; i+=inc) {
|
|
||||||
fprintf(stderr, "0x%08x | ", seek+i);
|
|
||||||
for(j=i;j<i+inc;j++) {
|
|
||||||
if (j>=len) {
|
|
||||||
fprintf(stderr, " ");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fprintf(stderr, "%02x ", buf[j]);
|
|
||||||
}
|
|
||||||
fprintf(stderr, " ");
|
|
||||||
for(j=i; j<i+inc; j++) {
|
|
||||||
if (j >= len)
|
|
||||||
fprintf(stderr, " ");
|
|
||||||
else
|
|
||||||
if ( is_printable(buf[j]) )
|
|
||||||
fprintf(stderr, "%c", buf[j]);
|
|
||||||
else fprintf(stderr, ".");
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
char getprintablechar(char a);
|
|
||||||
int is_printable (int c);
|
|
||||||
void dump_bytes(unsigned char *buf, int len);
|
|
||||||
+611
@@ -0,0 +1,611 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
#define IMAGE_STORE_CUR(image) do { if ( image->is_shared_fd ) { image->cur = lseek(image->fd, 0, SEEK_CUR) - image->offset; if ( image->cur > image->size ) image->cur = image->size; } } while (0)
|
||||||
|
#define IMAGE_RESTORE_CUR(image) do { if ( image->is_shared_fd ) { if ( image->cur <= image->size ) lseek(image->fd, image->offset + image->cur, SEEK_SET); else lseek(image->fd, image->offset + image->size, SEEK_SET); } } while (0)
|
||||||
|
|
||||||
|
/* format: type-device:hwrevs_version */
|
||||||
|
static void image_missing_values_from_name(struct image * image, const char * name) {
|
||||||
|
|
||||||
|
char * str;
|
||||||
|
char * ptr;
|
||||||
|
char * ptr2;
|
||||||
|
char * type = NULL;
|
||||||
|
char * device = NULL;
|
||||||
|
char * hwrevs = NULL;
|
||||||
|
char * version = NULL;
|
||||||
|
enum device new_device;
|
||||||
|
|
||||||
|
str = strdup(name);
|
||||||
|
if ( ! str )
|
||||||
|
return;
|
||||||
|
|
||||||
|
ptr = strchr(str, '_');
|
||||||
|
if ( ptr ) {
|
||||||
|
*ptr = 0;
|
||||||
|
++ptr;
|
||||||
|
version = strdup(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = strchr(str, '-');
|
||||||
|
if ( ptr ) {
|
||||||
|
*ptr = 0;
|
||||||
|
++ptr;
|
||||||
|
type = strdup(str);
|
||||||
|
ptr2 = strchr(ptr, ':');
|
||||||
|
if ( ptr2 ) {
|
||||||
|
*ptr2 = 0;
|
||||||
|
++ptr2;
|
||||||
|
hwrevs = strdup(ptr2);
|
||||||
|
}
|
||||||
|
device = strdup(ptr);
|
||||||
|
} else {
|
||||||
|
type = strdup(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! image->type )
|
||||||
|
image->type = image_type_from_string(type);
|
||||||
|
free(type);
|
||||||
|
|
||||||
|
if ( ! image->devices || image->devices->device || image->devices->device == DEVICE_ANY ) {
|
||||||
|
new_device = device_from_string(device);
|
||||||
|
if ( new_device ) {
|
||||||
|
if ( ! image->devices ) image->devices = calloc(1, sizeof(struct device_list));
|
||||||
|
if ( image->devices )
|
||||||
|
image->devices->device = new_device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(device);
|
||||||
|
|
||||||
|
if ( image->devices && image->devices->device && ! image->devices->hwrevs )
|
||||||
|
image->devices->hwrevs = hwrevs_alloc_from_string(hwrevs);
|
||||||
|
else
|
||||||
|
free(hwrevs);
|
||||||
|
|
||||||
|
if ( ! image->version )
|
||||||
|
image->version = version;
|
||||||
|
else
|
||||||
|
free(version);
|
||||||
|
|
||||||
|
free(str);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* format: type-device:hwrevs_version */
|
||||||
|
char * image_name_alloc_from_values(struct image * image) {
|
||||||
|
|
||||||
|
char * name;
|
||||||
|
char * ptr;
|
||||||
|
char * hwrevs;
|
||||||
|
size_t length;
|
||||||
|
const char * type;
|
||||||
|
const char * device;
|
||||||
|
|
||||||
|
type = image_type_to_string(image->type);
|
||||||
|
|
||||||
|
if ( ! type )
|
||||||
|
type = "unknown";
|
||||||
|
|
||||||
|
if ( image->devices )
|
||||||
|
device = device_to_string(image->devices->device);
|
||||||
|
else
|
||||||
|
device = NULL;
|
||||||
|
|
||||||
|
if ( image->devices && image->devices->hwrevs )
|
||||||
|
hwrevs = hwrevs_alloc_to_string(image->devices->hwrevs);
|
||||||
|
else
|
||||||
|
hwrevs = NULL;
|
||||||
|
|
||||||
|
length = 1 + strlen(type);
|
||||||
|
|
||||||
|
if ( device )
|
||||||
|
length += 1 + strlen(device);
|
||||||
|
if ( hwrevs )
|
||||||
|
length += 1 + strlen(hwrevs);
|
||||||
|
if ( image->version )
|
||||||
|
length += 1 + strlen(image->version);
|
||||||
|
|
||||||
|
name = calloc(1, length);
|
||||||
|
if ( ! name )
|
||||||
|
ALLOC_ERROR_RETURN(NULL);
|
||||||
|
|
||||||
|
strcpy(name, type);
|
||||||
|
ptr = name + strlen(name);
|
||||||
|
|
||||||
|
if ( device )
|
||||||
|
ptr += sprintf(ptr, "-%s", device);
|
||||||
|
if ( hwrevs )
|
||||||
|
ptr += sprintf(ptr, ":%s", hwrevs);
|
||||||
|
if ( image->version )
|
||||||
|
ptr += sprintf(ptr, "_%s", image->version);
|
||||||
|
|
||||||
|
free(hwrevs);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int image_append(struct image * image, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
|
||||||
|
|
||||||
|
enum image_type detected_type;
|
||||||
|
|
||||||
|
image->hash = image_hash_from_data(image);
|
||||||
|
|
||||||
|
image->devices = calloc(1, sizeof(struct device_list));
|
||||||
|
if ( ! image->devices )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
image->devices->device = DEVICE_ANY;
|
||||||
|
|
||||||
|
if ( device && device[0] ) {
|
||||||
|
image->devices->device = device_from_string(device);
|
||||||
|
if ( ! noverify && image->devices->device == DEVICE_UNKNOWN ) {
|
||||||
|
ERROR("Specified Device %s is unknown", device);
|
||||||
|
image_free(image);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
detected_type = image_type_from_data(image);
|
||||||
|
image->type = detected_type;
|
||||||
|
|
||||||
|
if ( type && type[0] ) {
|
||||||
|
image->type = image_type_from_string(type);
|
||||||
|
if ( ! noverify && image->type == IMAGE_UNKNOWN ) {
|
||||||
|
ERROR("Specified Image type %s is unknown", type);
|
||||||
|
image_free(image);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ( ! noverify && detected_type != image->type && detected_type != IMAGE_UNKNOWN ) {
|
||||||
|
ERROR("Image type mishmash (detected %s, got %s)", image_type_to_string(detected_type), type);
|
||||||
|
image_free(image);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( hwrevs && hwrevs[0] )
|
||||||
|
image->devices->hwrevs = hwrevs_alloc_from_string(hwrevs);
|
||||||
|
else
|
||||||
|
image->devices->hwrevs = NULL;
|
||||||
|
|
||||||
|
if ( version && version[0] )
|
||||||
|
image->version = strdup(version);
|
||||||
|
else
|
||||||
|
image->version = NULL;
|
||||||
|
|
||||||
|
if ( layout && layout[0] )
|
||||||
|
image->layout = strdup(layout);
|
||||||
|
else
|
||||||
|
image->layout = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void image_align(struct image * image) {
|
||||||
|
|
||||||
|
size_t align = 0;
|
||||||
|
|
||||||
|
if ( image->type == IMAGE_MMC )
|
||||||
|
align = 8;
|
||||||
|
else
|
||||||
|
align = 7;
|
||||||
|
|
||||||
|
if ( align == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ( image->size & ( ( 1ULL << align ) - 1 ) ) == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
align = ((image->size >> align) + 1) << align;
|
||||||
|
|
||||||
|
image->align = align - image->size;
|
||||||
|
image->size = align;
|
||||||
|
|
||||||
|
image->hash = image_hash_from_data(image);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct image * image_alloc(void) {
|
||||||
|
|
||||||
|
struct image * image = calloc(1, sizeof(struct image));
|
||||||
|
if ( ! image )
|
||||||
|
ALLOC_ERROR_RETURN(NULL);
|
||||||
|
return image;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
|
||||||
|
|
||||||
|
struct image * image = image_alloc();
|
||||||
|
if ( ! image )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
image->is_shared_fd = 0;
|
||||||
|
image->fd = open(file, O_RDONLY);
|
||||||
|
if ( image->fd < 0 ) {
|
||||||
|
ERROR_INFO("Cannot open image file %s", file);
|
||||||
|
free(image);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
image->size = lseek(image->fd, 0, SEEK_END);
|
||||||
|
image->offset = 0;
|
||||||
|
image->cur = 0;
|
||||||
|
image->orig_filename = strdup(file);
|
||||||
|
lseek(image->fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if ( image_append(image, type, device, hwrevs, version, layout) < 0 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ( ( ! type || ! type[0] ) && ( ! device || ! device[0] ) && ( ! hwrevs || ! hwrevs[0] ) && ( ! version || ! version[0] ) )
|
||||||
|
image_missing_values_from_name(image, file);
|
||||||
|
|
||||||
|
image_align(image);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
|
||||||
|
|
||||||
|
struct image * image = image_alloc();
|
||||||
|
if ( ! image )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
image->is_shared_fd = 1;
|
||||||
|
image->fd = fd;
|
||||||
|
image->size = size;
|
||||||
|
image->offset = offset;
|
||||||
|
image->cur = 0;
|
||||||
|
|
||||||
|
if ( image_append(image, type, device, hwrevs, version, layout) < 0 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ( ! noverify && image->hash != hash ) {
|
||||||
|
ERROR("Image hash mishmash (counted %#04x, got %#04x)", image->hash, hash);
|
||||||
|
image_free(image);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
image_align(image);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void image_free(struct image * image) {
|
||||||
|
|
||||||
|
if ( ! image )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( ! image->is_shared_fd ) {
|
||||||
|
close(image->fd);
|
||||||
|
image->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( image->devices ) {
|
||||||
|
struct device_list * next = image->devices->next;
|
||||||
|
free(image->devices->hwrevs);
|
||||||
|
free(image->devices);
|
||||||
|
image->devices = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(image->version);
|
||||||
|
free(image->layout);
|
||||||
|
free(image->orig_filename);
|
||||||
|
|
||||||
|
free(image);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void image_seek(struct image * image, size_t whence) {
|
||||||
|
|
||||||
|
if ( whence > image->size )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( whence >= image->size - image->align ) {
|
||||||
|
lseek(image->fd, image->size - image->align - 1, SEEK_SET);
|
||||||
|
image->acur = whence - ( image->size - image->align );
|
||||||
|
} else {
|
||||||
|
lseek(image->fd, image->offset + whence, SEEK_SET);
|
||||||
|
image->acur = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMAGE_STORE_CUR(image);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t image_read(struct image * image, void * buf, size_t count) {
|
||||||
|
|
||||||
|
size_t cur;
|
||||||
|
ssize_t ret;
|
||||||
|
size_t new_count = 0;
|
||||||
|
size_t ret_count = 0;
|
||||||
|
|
||||||
|
IMAGE_RESTORE_CUR(image);
|
||||||
|
|
||||||
|
if ( ! image->is_shared_fd || image->cur < image->size - image->align ) {
|
||||||
|
|
||||||
|
if ( image->is_shared_fd && image->cur + count > image->size - image->align )
|
||||||
|
new_count = image->size - image->align - image->cur;
|
||||||
|
else
|
||||||
|
new_count = count;
|
||||||
|
|
||||||
|
ret = read(image->fd, buf, new_count);
|
||||||
|
if ( ret > 0 )
|
||||||
|
ret_count += ret;
|
||||||
|
|
||||||
|
IMAGE_STORE_CUR(image);
|
||||||
|
|
||||||
|
if ( ret < 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ret_count == count )
|
||||||
|
return ret_count;
|
||||||
|
|
||||||
|
cur = lseek(image->fd, 0, SEEK_CUR) - image->offset;
|
||||||
|
|
||||||
|
if ( image->align && cur == image->size - image->align && image->acur < image->align ) {
|
||||||
|
|
||||||
|
if ( image->acur + count - ret_count > image->align )
|
||||||
|
new_count = image->align - image->acur;
|
||||||
|
else
|
||||||
|
new_count = count - ret_count;
|
||||||
|
|
||||||
|
memset((unsigned char *)buf+ret_count, 0xFF, new_count);
|
||||||
|
ret_count += new_count;
|
||||||
|
image->acur += new_count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void image_list_add(struct image_list ** list, struct image * image) {
|
||||||
|
|
||||||
|
struct image_list * last = calloc(1, sizeof(struct image_list));
|
||||||
|
if ( ! last )
|
||||||
|
ALLOC_ERROR_RETURN();
|
||||||
|
|
||||||
|
last->image = image;
|
||||||
|
|
||||||
|
if ( ! *list ) {
|
||||||
|
*list = last;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( (*list)->next )
|
||||||
|
list = &((*list)->next);
|
||||||
|
|
||||||
|
last->prev = *list;
|
||||||
|
(*list)->next = last;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void image_list_del(struct image_list * list) {
|
||||||
|
|
||||||
|
if ( ! list )
|
||||||
|
return;
|
||||||
|
|
||||||
|
image_list_unlink(list);
|
||||||
|
image_free(list->image);
|
||||||
|
free(list);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void image_list_unlink(struct image_list * list) {
|
||||||
|
|
||||||
|
if ( ! list )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( list->prev )
|
||||||
|
list->prev->next = list->next;
|
||||||
|
|
||||||
|
if ( list->next )
|
||||||
|
list->next->prev = list->prev;
|
||||||
|
|
||||||
|
list->prev = NULL;
|
||||||
|
list->next = NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t do_hash(uint16_t * b, size_t len) {
|
||||||
|
|
||||||
|
uint16_t result = 0;
|
||||||
|
|
||||||
|
for ( len >>= 1; len--; b = b+1 )
|
||||||
|
result^=b[0];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t image_hash_from_data(struct image * image) {
|
||||||
|
|
||||||
|
unsigned char buf[0x20000];
|
||||||
|
uint16_t hash = 0;
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
image_seek(image, 0);
|
||||||
|
while ( ( ret = image_read(image, buf, sizeof(buf)) ) )
|
||||||
|
hash ^= do_hash((uint16_t *)buf, ret);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * image_types[] = {
|
||||||
|
[IMAGE_XLOADER] = "xloader",
|
||||||
|
[IMAGE_2ND] = "2nd",
|
||||||
|
[IMAGE_SECONDARY] = "secondary",
|
||||||
|
[IMAGE_KERNEL] = "kernel",
|
||||||
|
[IMAGE_INITFS] = "initfs",
|
||||||
|
[IMAGE_ROOTFS] = "rootfs",
|
||||||
|
[IMAGE_MMC] = "mmc",
|
||||||
|
[IMAGE_CMT_2ND] = "cmt-2nd",
|
||||||
|
[IMAGE_CMT_ALGO] = "cmt-algo",
|
||||||
|
[IMAGE_CMT_MCUSW] = "cmt-mcusw",
|
||||||
|
};
|
||||||
|
|
||||||
|
enum image_type image_type_from_data(struct image * image) {
|
||||||
|
|
||||||
|
unsigned char buf[512];
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
image_seek(image, 0);
|
||||||
|
image_read(image, buf, sizeof(buf));
|
||||||
|
|
||||||
|
if ( memcmp(buf+52, "2NDAPE", 6) == 0 )
|
||||||
|
return IMAGE_2ND;
|
||||||
|
else if ( memcmp(buf+20, "2ND", 3) == 0 )
|
||||||
|
return IMAGE_2ND;
|
||||||
|
else if ( memcmp(buf+4, "NOLOScnd", 8) == 0 )
|
||||||
|
return IMAGE_SECONDARY;
|
||||||
|
else if ( memcmp(buf+20, "X-LOADER", 8) == 0 )
|
||||||
|
return IMAGE_XLOADER;
|
||||||
|
else if ( memcmp(buf+12, "NOLOXldr", 8) == 0 )
|
||||||
|
return IMAGE_XLOADER;
|
||||||
|
else if ( memcmp(buf+4, "NOLOXldr", 8) == 0 )
|
||||||
|
return IMAGE_2ND;
|
||||||
|
else if ( memcmp(buf+36, "\x18\x28\x6f\x01", 4) == 0 ) /* ARM Linux kernel magic number */
|
||||||
|
return IMAGE_KERNEL;
|
||||||
|
else if ( memcmp(buf, "\x14\x00\x00\xea", 4) == 0 ) /* ARM U-Boot - instruction branch +0x50 */
|
||||||
|
return IMAGE_KERNEL;
|
||||||
|
else if ( memcmp(buf, "UBI#", 4) == 0 ) /* UBI EC header */
|
||||||
|
return IMAGE_ROOTFS;
|
||||||
|
else if ( memcmp(buf+510, "\x55\xaa", 2) == 0 ) /* FAT boot sector signature */
|
||||||
|
return IMAGE_MMC;
|
||||||
|
else if ( memcmp(buf, "\xb0\x00\x01\x03\x9d\x00\x00\x00", 8) == 0 )
|
||||||
|
return IMAGE_CMT_2ND;
|
||||||
|
else if ( memcmp(buf, "\xb1\x00\x00\x00\x82\x00\x00\x00", 8) == 0 )
|
||||||
|
return IMAGE_CMT_ALGO;
|
||||||
|
else if ( memcmp(buf, "\xb2\x00\x00\x01\x44\x00\x00\x00", 8) == 0 )
|
||||||
|
return IMAGE_CMT_MCUSW;
|
||||||
|
else if ( memcmp(buf, "\x45\x3d\xcd\x28", 4) == 0 ) /* CRAMFS MAGIC */
|
||||||
|
return IMAGE_INITFS;
|
||||||
|
else if ( memcmp(buf, "\x85\x19", 2) == 0 ) { /* JFFS2 MAGIC */
|
||||||
|
if ( image->size < 0x300000 )
|
||||||
|
return IMAGE_INITFS;
|
||||||
|
else
|
||||||
|
return IMAGE_ROOTFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IMAGE_UNKNOWN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum image_type image_type_from_string(const char * type) {
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if ( ! type )
|
||||||
|
return IMAGE_UNKNOWN;
|
||||||
|
|
||||||
|
for ( i = 0; i < sizeof(image_types)/sizeof(image_types[0]); ++i )
|
||||||
|
if ( image_types[i] && strcmp(image_types[i], type) == 0 )
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return IMAGE_UNKNOWN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * image_type_to_string(enum image_type type) {
|
||||||
|
|
||||||
|
if ( type >= sizeof(image_types)/sizeof(image_types[0]) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return image_types[type];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int image_hwrev_is_valid(struct image * image, int16_t hwrev) {
|
||||||
|
|
||||||
|
struct device_list * device_ptr = image->devices;
|
||||||
|
|
||||||
|
while ( device_ptr ) {
|
||||||
|
if ( hwrev_is_valid(device_ptr->hwrevs, hwrev) )
|
||||||
|
return 1;
|
||||||
|
device_ptr = device_ptr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void image_print_info(struct image * image) {
|
||||||
|
|
||||||
|
const char * str;
|
||||||
|
struct device_list * device = image->devices;
|
||||||
|
|
||||||
|
if ( image->orig_filename )
|
||||||
|
printf("File: %s\n", image->orig_filename);
|
||||||
|
|
||||||
|
str = image_type_to_string(image->type);
|
||||||
|
printf(" Image type: %s\n", str ? str : "unknown");
|
||||||
|
printf(" Image size: %d bytes\n", image->size);
|
||||||
|
|
||||||
|
if ( image->version )
|
||||||
|
printf(" Image version: %s\n", image->version);
|
||||||
|
|
||||||
|
if ( image->layout )
|
||||||
|
printf(" Image layout: included\n");
|
||||||
|
|
||||||
|
while ( device ) {
|
||||||
|
|
||||||
|
char * str2 = NULL;
|
||||||
|
struct device_list * next = device->next;
|
||||||
|
|
||||||
|
if ( device->device == DEVICE_UNKNOWN )
|
||||||
|
str = "unknown";
|
||||||
|
else
|
||||||
|
str = device_to_string(device->device);
|
||||||
|
|
||||||
|
if ( str )
|
||||||
|
printf(" Valid for: device %s", str);
|
||||||
|
|
||||||
|
if ( str && device->hwrevs )
|
||||||
|
str2 = hwrevs_alloc_to_string(device->hwrevs);
|
||||||
|
|
||||||
|
if ( str2 ) {
|
||||||
|
printf(", HW revisions: %s\n", str2);
|
||||||
|
free(str2);
|
||||||
|
} else if ( str ) {
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
device = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMAGE_H
|
||||||
|
#define IMAGE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
enum image_type {
|
||||||
|
IMAGE_UNKNOWN = 0,
|
||||||
|
IMAGE_XLOADER,
|
||||||
|
IMAGE_2ND,
|
||||||
|
IMAGE_SECONDARY,
|
||||||
|
IMAGE_KERNEL,
|
||||||
|
IMAGE_INITFS,
|
||||||
|
IMAGE_ROOTFS,
|
||||||
|
IMAGE_MMC,
|
||||||
|
IMAGE_CMT_2ND,
|
||||||
|
IMAGE_CMT_ALGO,
|
||||||
|
IMAGE_CMT_MCUSW,
|
||||||
|
IMAGE_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct image {
|
||||||
|
enum image_type type;
|
||||||
|
struct device_list * devices;
|
||||||
|
char * version;
|
||||||
|
char * layout;
|
||||||
|
uint16_t hash;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
int is_shared_fd;
|
||||||
|
uint32_t align;
|
||||||
|
size_t offset;
|
||||||
|
size_t cur;
|
||||||
|
size_t acur;
|
||||||
|
char * orig_filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct image_list {
|
||||||
|
struct image * image;
|
||||||
|
struct image_list * prev;
|
||||||
|
struct image_list * next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout);
|
||||||
|
struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout);
|
||||||
|
void image_free(struct image * image);
|
||||||
|
void image_seek(struct image * image, size_t whence);
|
||||||
|
size_t image_read(struct image * image, void * buf, size_t count);
|
||||||
|
void image_print_info(struct image * image);
|
||||||
|
void image_list_add(struct image_list ** list, struct image * image);
|
||||||
|
void image_list_del(struct image_list * list);
|
||||||
|
void image_list_unlink(struct image_list * list);
|
||||||
|
|
||||||
|
uint16_t image_hash_from_data(struct image * image);
|
||||||
|
enum image_type image_type_from_data(struct image * image);
|
||||||
|
char * image_name_alloc_from_values(struct image * image);
|
||||||
|
enum image_type image_type_from_string(const char * type);
|
||||||
|
const char * image_type_to_string(enum image_type type);
|
||||||
|
int image_hwrev_is_valid(struct image * image, int16_t hwrev);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
libusb-sniff.c - Library for usb sniffing nokia's flasher-3.5
|
||||||
|
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* compile: gcc libusb-sniff.c -o libusb-sniff.so -W -Wall -O2 -fPIC -ldl -shared -m32 */
|
||||||
|
/* usage: sudo USBSNIFF_WAIT=1 LD_PRELOAD=./libusb-sniff.so flasher-3.5 ... */
|
||||||
|
/* usage: sudo USBSNIFF_SKIP_READ=1 USBSNIFF_SKIP_WRITE=1 LD_PRELOAD=./libusb-sniff.so flasher-3.5 ... */
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <usb.h>
|
||||||
|
|
||||||
|
static char to_ascii(char c) {
|
||||||
|
|
||||||
|
if ( c >= 32 && c <= 126 )
|
||||||
|
return c;
|
||||||
|
return '.';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_bytes(const char * buf, size_t size) {
|
||||||
|
|
||||||
|
size_t i, ascii_cnt = 0;
|
||||||
|
char ascii[17] = { 0, };
|
||||||
|
|
||||||
|
for ( i = 0; i < size; i++ ) {
|
||||||
|
if ( i % 16 == 0 ) {
|
||||||
|
if ( i != 0 ) {
|
||||||
|
printf(" |%s|\n", ascii);
|
||||||
|
ascii[0] = 0;
|
||||||
|
ascii_cnt = 0;
|
||||||
|
}
|
||||||
|
printf("%04X:", (unsigned int)i);
|
||||||
|
}
|
||||||
|
printf(" %02X", buf[i] & 0xFF);
|
||||||
|
ascii[ascii_cnt] = to_ascii(buf[i]);
|
||||||
|
ascii[ascii_cnt + 1] = 0;
|
||||||
|
ascii_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ascii[0] ) {
|
||||||
|
if ( size % 16 )
|
||||||
|
for ( i = 0; i < 16 - (size % 16); i++ )
|
||||||
|
printf(" ");
|
||||||
|
printf(" |%s|\n", ascii);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_bulk_write(usb_dev_handle * dev, int ep, const char * bytes, int size, int timeout) {
|
||||||
|
|
||||||
|
static int (*real_usb_bulk_write)(usb_dev_handle * dev, int ep, const char * bytes, int size, int timeout) = NULL;
|
||||||
|
|
||||||
|
if ( ! real_usb_bulk_write )
|
||||||
|
real_usb_bulk_write = dlsym(RTLD_NEXT, "usb_bulk_write");
|
||||||
|
|
||||||
|
if ( ! getenv("USBSNIFF_SKIP_WRITE") ) {
|
||||||
|
|
||||||
|
printf("\n==== usb_bulk_write (ep=%d size=%d timeout=%d) ====\n", ep, size, timeout);
|
||||||
|
dump_bytes(bytes, size);
|
||||||
|
printf("====\n");
|
||||||
|
|
||||||
|
if ( getenv("USBSNIFF_WAIT") ) {
|
||||||
|
printf("Press ENTER"); fflush(stdout); getchar();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_usb_bulk_write(dev, ep, bytes, size, timeout);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_bulk_read(usb_dev_handle * dev, int ep, char * bytes, int size, int timeout) {
|
||||||
|
|
||||||
|
static int (*real_usb_bulk_read)(usb_dev_handle * dev, int ep, char * bytes, int size, int timeout) = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ( ! real_usb_bulk_read )
|
||||||
|
real_usb_bulk_read = dlsym(RTLD_NEXT, "usb_bulk_read");
|
||||||
|
|
||||||
|
ret = real_usb_bulk_read(dev, ep, bytes, size, timeout);
|
||||||
|
|
||||||
|
if ( ! getenv("USBSNIFF_SKIP_READ") ) {
|
||||||
|
|
||||||
|
printf("\n==== usb_bulk_read (ep=%d size=%d timeout=%d) ret = %d ====\n", ep, size, timeout, ret);
|
||||||
|
if ( ret > 0 ) {
|
||||||
|
dump_bytes(bytes, ret);
|
||||||
|
printf("====\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( getenv("USBSNIFF_WAIT") ) {
|
||||||
|
printf("Press ENTER"); fflush(stdout); getchar();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout) {
|
||||||
|
|
||||||
|
static int (*real_usb_control_msg)(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout) = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ( ! real_usb_control_msg )
|
||||||
|
real_usb_control_msg = dlsym(RTLD_NEXT, "usb_control_msg");
|
||||||
|
|
||||||
|
if ( requesttype == 64 && ! getenv("USBSNIFF_SKIP_CONTROL") ) {
|
||||||
|
|
||||||
|
printf("\n==== usb_control_msg(requesttype=%d, request=%d, value=%d, index=%d, size=%d, timeout=%d) ====\n", requesttype, request, value, index, size, timeout);
|
||||||
|
dump_bytes(bytes, size);
|
||||||
|
printf("====\n");
|
||||||
|
|
||||||
|
if ( getenv("USBSNIFF_WAIT") ) {
|
||||||
|
printf("Press ENTER"); fflush(stdout); getchar();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = real_usb_control_msg(dev, requesttype, request, value, index, bytes, size, timeout);
|
||||||
|
|
||||||
|
if ( requesttype != 64 && ! getenv("USBSNIFF_SKIP_CONTROL") ) {
|
||||||
|
|
||||||
|
printf("\n==== usb_control_msg(requesttype=%d, request=%d, value=%d, index=%d, size=%d, timeout=%d) ret = %d ====\n", requesttype, request, value, index, size, timeout, ret);
|
||||||
|
if ( ret > 0 ) {
|
||||||
|
dump_bytes(bytes, ret);
|
||||||
|
printf("====\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( getenv("USBSNIFF_WAIT") ) {
|
||||||
|
printf("Press ENTER"); fflush(stdout); getchar();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_set_configuration(usb_dev_handle *dev, int configuration) {
|
||||||
|
|
||||||
|
static int (*real_usb_set_configuration)(usb_dev_handle *dev, int configuration) = NULL;
|
||||||
|
|
||||||
|
if ( ! real_usb_set_configuration )
|
||||||
|
real_usb_set_configuration = dlsym(RTLD_NEXT, "usb_set_configuration");
|
||||||
|
|
||||||
|
printf("\n==== usb_set_configuration (configuration=%d) ====\n", configuration);
|
||||||
|
|
||||||
|
return real_usb_set_configuration(dev, configuration);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_claim_interface(usb_dev_handle *dev, int interface) {
|
||||||
|
|
||||||
|
static int (*real_usb_claim_interface)(usb_dev_handle *dev, int interface) = NULL;
|
||||||
|
|
||||||
|
if ( ! real_usb_claim_interface )
|
||||||
|
real_usb_claim_interface = dlsym(RTLD_NEXT, "usb_claim_interface");
|
||||||
|
|
||||||
|
printf("\n==== usb_claim_interface (interface=%d) ====\n", interface);
|
||||||
|
|
||||||
|
return real_usb_claim_interface(dev, interface);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_set_altinterface(usb_dev_handle *dev, int alternate) {
|
||||||
|
|
||||||
|
static int (*real_usb_set_altinterface)(usb_dev_handle *dev, int alternate) = NULL;
|
||||||
|
|
||||||
|
if ( ! real_usb_set_altinterface )
|
||||||
|
real_usb_set_altinterface = dlsym(RTLD_NEXT, "usb_set_altinterface");
|
||||||
|
|
||||||
|
printf("\n==== usb_set_altinterface (alternate=%d) ====\n", alternate);
|
||||||
|
|
||||||
|
return real_usb_set_altinterface(dev, alternate);
|
||||||
|
|
||||||
|
}
|
||||||
+673
@@ -0,0 +1,673 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#include "local.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "cal.h"
|
||||||
|
#include "disk.h"
|
||||||
|
|
||||||
|
static int failed;
|
||||||
|
|
||||||
|
static enum device device = DEVICE_UNKNOWN;
|
||||||
|
static int16_t hwrev = -1;
|
||||||
|
static char kernel_ver[256];
|
||||||
|
static char initfs_ver[256];
|
||||||
|
static char nolo_ver[256];
|
||||||
|
static char sw_ver[256];
|
||||||
|
static char content_ver[256];
|
||||||
|
static char rd_mode[256];
|
||||||
|
static int usb_host_mode = -1;
|
||||||
|
static int root_device = -1;
|
||||||
|
|
||||||
|
#define min(a, b) (a < b ? a : b)
|
||||||
|
#define local_cal_copy(dest, from, len) strncpy(dest, from, min(len, sizeof(dest)-1))
|
||||||
|
#define local_cal_read(cal, str, ptr, len) ( cal_read_block(cal, str, &ptr, &len, 0) == 0 && ptr )
|
||||||
|
#define local_cal_readcopy(cal, str, dest) do { void * ptr; unsigned long int len; if ( local_cal_read(cal, str, ptr, len) ) local_cal_copy(dest, ptr, len); } while ( 0 )
|
||||||
|
|
||||||
|
static void local_cal_parse(void) {
|
||||||
|
|
||||||
|
struct cal * cal = NULL;
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
printf("Reading CAL...\n");
|
||||||
|
|
||||||
|
if ( cal_init(&cal) < 0 || ! cal )
|
||||||
|
return;
|
||||||
|
|
||||||
|
local_cal_readcopy(cal, "kernel-ver", kernel_ver);
|
||||||
|
local_cal_readcopy(cal, "initfs-ver", kernel_ver);
|
||||||
|
local_cal_readcopy(cal, "nolo-ver", nolo_ver);
|
||||||
|
local_cal_readcopy(cal, "sw-release-ver", sw_ver);
|
||||||
|
local_cal_readcopy(cal, "content-ver", content_ver);
|
||||||
|
local_cal_readcopy(cal, "r&d_mode", rd_mode);
|
||||||
|
|
||||||
|
/* overwritten hw revision */
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
local_cal_readcopy(cal, "hw-ver", buf);
|
||||||
|
|
||||||
|
if ( buf[0] && sscanf(buf, "%hd", &hwrev) != 1 )
|
||||||
|
hwrev = -1;
|
||||||
|
|
||||||
|
if ( hwrev == -1 ) {
|
||||||
|
|
||||||
|
/* original hw revision */
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
local_cal_readcopy(cal, "phone-info", buf);
|
||||||
|
buf[4] = 0;
|
||||||
|
|
||||||
|
if ( buf[0] && sscanf(buf, "%hd", &hwrev) != 1 )
|
||||||
|
hwrev = -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[0] = 0;
|
||||||
|
local_cal_readcopy(cal, "usb_host_mode", buf);
|
||||||
|
usb_host_mode = buf[0];
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
local_cal_readcopy(cal, "root_device", buf);
|
||||||
|
|
||||||
|
if ( strcmp(buf, "mmc") == 0 )
|
||||||
|
root_device = 1;
|
||||||
|
else if ( strcmp(buf, "usb") == 0 )
|
||||||
|
root_device = 2;
|
||||||
|
else
|
||||||
|
root_device = 0;
|
||||||
|
|
||||||
|
cal_finish(cal);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_init(void) {
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
char * ptr;
|
||||||
|
char * ptr2;
|
||||||
|
FILE * file;
|
||||||
|
|
||||||
|
if ( failed )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
file = fopen("/proc/cpuinfo", "r");
|
||||||
|
if ( ! file ) {
|
||||||
|
failed = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( fgets(buf, sizeof(buf), file) ) {
|
||||||
|
|
||||||
|
if ( strncmp(buf, "Hardware", strlen("Hardware")) == 0 ) {
|
||||||
|
|
||||||
|
ptr = buf + strlen("Hardware");
|
||||||
|
|
||||||
|
while ( ptr < buf + sizeof(buf) && *ptr > 0 && *ptr <= 32 )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( *ptr != ':' )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
while ( ptr < buf + sizeof(buf) && *ptr > 0 && *ptr <= 32 )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( ! *ptr )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ptr2 = buf + strlen(buf);
|
||||||
|
|
||||||
|
while ( *ptr2 <= 32 ) {
|
||||||
|
*ptr2 = 0;
|
||||||
|
--ptr2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( strcmp(ptr, "Nokia 770") == 0 )
|
||||||
|
device = DEVICE_SU_18;
|
||||||
|
else if ( strcmp(ptr, "Nokia N800") == 0 )
|
||||||
|
device = DEVICE_RX_34;
|
||||||
|
else if ( strcmp(ptr, "Nokia N810") == 0 )
|
||||||
|
device = DEVICE_RX_44;
|
||||||
|
else if ( strcmp(ptr, "Nokia N810 WiMAX") == 0 )
|
||||||
|
device = DEVICE_RX_48;
|
||||||
|
else if ( strcmp(ptr, "Nokia RX-51 board") == 0 )
|
||||||
|
device = DEVICE_RX_51;
|
||||||
|
|
||||||
|
if ( device ) {
|
||||||
|
printf("Found local device: %s\n", device_to_long_string(device));
|
||||||
|
fclose(file);
|
||||||
|
local_cal_parse();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
failed = 1;
|
||||||
|
printf("Not a local device\n");
|
||||||
|
fclose(file);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum device local_get_device(void) {
|
||||||
|
|
||||||
|
return device;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_flash_image(struct image * image) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)image;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int local_nanddump(const char * file, int mtd, int offset, int length) {
|
||||||
|
|
||||||
|
struct statvfs buf;
|
||||||
|
char * command;
|
||||||
|
char * path;
|
||||||
|
size_t size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
path = strdup(file);
|
||||||
|
if ( ! path )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
ret = statvfs(dirname(path), &buf);
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
if ( ret == 0 && buf.f_bsize * buf.f_bfree < (long unsigned int)length ) {
|
||||||
|
ERROR("Not enough free space (have: %lu, need: %d)", buf.f_bsize * buf.f_bfree, length);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = snprintf(NULL, 0, "nanddump -i -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
|
||||||
|
|
||||||
|
command = malloc(size+1);
|
||||||
|
if ( ! command )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
snprintf(command, size+1, "nanddump -i -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
|
||||||
|
|
||||||
|
ret = system(command);
|
||||||
|
|
||||||
|
free(command);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nanddump_args {
|
||||||
|
int valid;
|
||||||
|
int mtd;
|
||||||
|
int offset;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct nanddump_args nanddump_rx51[] = {
|
||||||
|
[IMAGE_XLOADER] = { 1, 0, 0x00000000, 0x00004000 },
|
||||||
|
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
|
||||||
|
[IMAGE_KERNEL] = { 1, 3, 0x00000800, 0x001FF800 },
|
||||||
|
[IMAGE_INITFS] = { 1, 4, 0x00000000, 0x00200000 },
|
||||||
|
[IMAGE_ROOTFS] = { 1, 5, 0x00000000, 0x0fb40000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME: Is this table correct? */
|
||||||
|
static struct nanddump_args nanddump_rx4x[] = {
|
||||||
|
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
|
||||||
|
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
|
||||||
|
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x0021F800 },
|
||||||
|
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00400000 },
|
||||||
|
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0f960000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME: Is this table correct? */
|
||||||
|
static struct nanddump_args nanddump_old[] = {
|
||||||
|
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
|
||||||
|
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
|
||||||
|
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x001FF800 },
|
||||||
|
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00200000 },
|
||||||
|
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0fb80000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nanddump_device {
|
||||||
|
size_t count;
|
||||||
|
struct nanddump_args * args;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NANDDUMP(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array }
|
||||||
|
|
||||||
|
static struct nanddump_device nanddump[] = {
|
||||||
|
NANDDUMP(DEVICE_SU_18, nanddump_old),
|
||||||
|
NANDDUMP(DEVICE_RX_34, nanddump_old),
|
||||||
|
NANDDUMP(DEVICE_RX_44, nanddump_rx4x),
|
||||||
|
NANDDUMP(DEVICE_RX_48, nanddump_rx4x),
|
||||||
|
NANDDUMP(DEVICE_RX_51, nanddump_rx51),
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef NANDDUMP
|
||||||
|
|
||||||
|
int local_dump_image(enum image_type image, const char * file) {
|
||||||
|
|
||||||
|
int ret = -1;
|
||||||
|
int fd = -1;
|
||||||
|
unsigned char * addr = NULL;
|
||||||
|
off_t nlen, len;
|
||||||
|
int align;
|
||||||
|
DIR * dir;
|
||||||
|
DIR * dir2;
|
||||||
|
FILE * f;
|
||||||
|
struct dirent * dirent;
|
||||||
|
struct dirent * dirent2;
|
||||||
|
struct stat st;
|
||||||
|
int maj, min;
|
||||||
|
char buf[1024];
|
||||||
|
char blk[1024];
|
||||||
|
|
||||||
|
printf("Dump %s image to file %s...\n", image_type_to_string(image), file);
|
||||||
|
|
||||||
|
if ( image == IMAGE_MMC ) {
|
||||||
|
|
||||||
|
maj = -1;
|
||||||
|
min = -1;
|
||||||
|
|
||||||
|
/* Find block device in /dev/ for MyDocs (mmc device, partition 1) */
|
||||||
|
|
||||||
|
dir = opendir("/sys/class/mmc_host/");
|
||||||
|
if ( ! dir ) {
|
||||||
|
ERROR("Cannot find MyDocs mmc device: Opening '/sys/class/mmc_host/' failed");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( ( dirent = readdir(dir) ) ) {
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/slot_name", dirent->d_name);
|
||||||
|
|
||||||
|
fd = open(buf, O_RDONLY);
|
||||||
|
if ( fd < 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buf[0] = 0;
|
||||||
|
if ( read(fd, buf, sizeof(buf)) < 0 )
|
||||||
|
buf[0] = 0;
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if ( strncmp(buf, "internal", strlen("internal")) != 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/", dirent->d_name, dirent->d_name);
|
||||||
|
|
||||||
|
dir2 = opendir(buf);
|
||||||
|
if ( ! dir2 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
while ( ( dirent2 = readdir(dir2) ) ) {
|
||||||
|
|
||||||
|
if ( strncmp(dirent2->d_name, "block:mmcblk", strlen("block:mmcblk")) != 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/%s/dev", dirent->d_name, dirent->d_name, dirent2->d_name);
|
||||||
|
|
||||||
|
f = fopen(buf, "r");
|
||||||
|
if ( ! f )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( fscanf(f, "%d:%d", &maj, &min) != 2 ) {
|
||||||
|
maj = -1;
|
||||||
|
min = -1;
|
||||||
|
fclose(f);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir2);
|
||||||
|
|
||||||
|
if ( maj != -1 && min != -1 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
if ( maj == -1 || min == -1 ) {
|
||||||
|
ERROR("Cannot find MyDocs mmc device: Slot 'internal' was not found");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERBOSE("Detected internal mmc device: major=%d minor=%d\n", maj, min);
|
||||||
|
|
||||||
|
blk[0] = 0;
|
||||||
|
|
||||||
|
dir = opendir("/dev/");
|
||||||
|
if ( ! dir ) {
|
||||||
|
ERROR("Cannot find MyDocs mmc device: Opening '/dev/' failed");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( ( dirent = readdir(dir) ) ) {
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "/dev/%s", dirent->d_name);
|
||||||
|
|
||||||
|
if ( stat(buf, &st) != 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( ! S_ISBLK(st.st_mode) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( makedev(maj, min) != st.st_rdev )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
strcpy(blk, buf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
|
if ( ! blk[0] ) {
|
||||||
|
ERROR("Cannot find MyDocs mmc device: Block device in /dev/ was not found");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERBOSE("Detected internal mmc device: '%s'\n", blk);
|
||||||
|
|
||||||
|
strncat(blk, "p1", sizeof(blk));
|
||||||
|
|
||||||
|
printf("Using MyDocs mmc device: '%s'\n", blk);
|
||||||
|
|
||||||
|
ret = disk_dump_raw(blk, file);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if ( device >= sizeof(nanddump)/sizeof(nanddump[0]) ) {
|
||||||
|
ERROR("Unsupported device");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( image >= nanddump[device].count ) {
|
||||||
|
ERROR("Unsupported image type: %s", image_type_to_string(image));
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset, nanddump[device].args[image].length);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ret != 0 ) {
|
||||||
|
ret = -1;
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(file, O_RDWR);
|
||||||
|
if ( fd < 0 )
|
||||||
|
goto clean;
|
||||||
|
|
||||||
|
len = lseek(fd, 0, SEEK_END);
|
||||||
|
if ( len == (off_t)-1 || len == 0 )
|
||||||
|
goto clean;
|
||||||
|
|
||||||
|
addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
|
||||||
|
if ( addr == MAP_FAILED )
|
||||||
|
addr = NULL;
|
||||||
|
|
||||||
|
if ( ! addr )
|
||||||
|
goto clean;
|
||||||
|
|
||||||
|
for ( nlen = len; nlen > 0; --nlen )
|
||||||
|
if ( addr[nlen-1] != 0xFF )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( image == IMAGE_MMC )
|
||||||
|
align = 8;
|
||||||
|
else
|
||||||
|
align = 7;
|
||||||
|
|
||||||
|
if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
|
||||||
|
nlen = ((nlen >> align) + 1) << align;
|
||||||
|
|
||||||
|
if ( nlen == 0 ) {
|
||||||
|
printf("File %s is empty, removing it...\n", file);
|
||||||
|
unlink(file);
|
||||||
|
} else if ( nlen != len ) {
|
||||||
|
printf("Truncating file %s to %d bytes...\n", file, (int)nlen);
|
||||||
|
if ( ftruncate(fd, nlen) < 0 )
|
||||||
|
ERROR_INFO("Cannot truncate file %s", file);
|
||||||
|
}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
if ( addr )
|
||||||
|
munmap(addr, len);
|
||||||
|
|
||||||
|
if ( fd >= 0 )
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_check_badblocks(const char * device) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)device;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_reboot_device(void) {
|
||||||
|
|
||||||
|
if ( system("dsmetool -b") == 0 )
|
||||||
|
return 0;
|
||||||
|
return system("reboot");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_root_device(void) {
|
||||||
|
|
||||||
|
return root_device;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_root_device(int device) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)device;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_usb_host_mode(void) {
|
||||||
|
|
||||||
|
return usb_host_mode;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_usb_host_mode(int enable) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)enable;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_rd_mode(void) {
|
||||||
|
|
||||||
|
if ( strncmp(rd_mode, "master", strlen("master")) == 0 )
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_rd_mode(int enable) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)enable;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_rd_flags(char * flags, size_t size) {
|
||||||
|
|
||||||
|
const char * ptr;
|
||||||
|
|
||||||
|
if ( strncmp(rd_mode, "master", strlen("master")) == 0 )
|
||||||
|
ptr = rd_mode + strlen("master");
|
||||||
|
else
|
||||||
|
ptr = rd_mode;
|
||||||
|
|
||||||
|
if ( *ptr == ',' )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( ! *ptr ) {
|
||||||
|
flags[0] = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(flags, ptr, size);
|
||||||
|
flags[size-1] = 0;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_rd_flags(const char * flags) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)flags;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t local_get_hwrev(void) {
|
||||||
|
|
||||||
|
return hwrev;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_hwrev(int16_t hwrev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)hwrev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_kernel_ver(char * ver, size_t size) {
|
||||||
|
|
||||||
|
strncpy(ver, kernel_ver, size);
|
||||||
|
ver[size-1] = 0;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_kernel_ver(const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_initfs_ver(char * ver, size_t size) {
|
||||||
|
|
||||||
|
strncpy(ver, initfs_ver, size);
|
||||||
|
ver[size-1] = 0;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_initfs_ver(const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_nolo_ver(char * ver, size_t size) {
|
||||||
|
|
||||||
|
strncpy(ver, nolo_ver, size);
|
||||||
|
ver[size-1] = 0;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_nolo_ver(const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_sw_ver(char * ver, size_t size) {
|
||||||
|
|
||||||
|
strncpy(ver, sw_ver, size);
|
||||||
|
ver[size-1] = 0;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_sw_ver(const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_get_content_ver(char * ver, size_t size) {
|
||||||
|
|
||||||
|
strncpy(ver, content_ver, size);
|
||||||
|
ver[size-1] = 0;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int local_set_content_ver(const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOCAL_H
|
||||||
|
#define LOCAL_H
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
int local_init(void);
|
||||||
|
|
||||||
|
enum device local_get_device(void);
|
||||||
|
|
||||||
|
int local_flash_image(struct image * image);
|
||||||
|
int local_dump_image(enum image_type image, const char * file);
|
||||||
|
int local_check_badblocks(const char * device);
|
||||||
|
|
||||||
|
int local_reboot_device(void);
|
||||||
|
|
||||||
|
int local_get_root_device(void);
|
||||||
|
int local_set_root_device(int device);
|
||||||
|
|
||||||
|
int local_get_usb_host_mode(void);
|
||||||
|
int local_set_usb_host_mode(int enable);
|
||||||
|
|
||||||
|
int local_get_rd_mode(void);
|
||||||
|
int local_set_rd_mode(int enable);
|
||||||
|
|
||||||
|
int local_get_rd_flags(char * flags, size_t size);
|
||||||
|
int local_set_rd_flags(const char * flags);
|
||||||
|
|
||||||
|
int16_t local_get_hwrev(void);
|
||||||
|
int local_set_hwrev(int16_t hwrev);
|
||||||
|
|
||||||
|
int local_get_kernel_ver(char * ver, size_t size);
|
||||||
|
int local_set_kernel_ver(const char * ver);
|
||||||
|
|
||||||
|
int local_get_initfs_ver(char * ver, size_t size);
|
||||||
|
int local_set_initfs_ver(const char * ver);
|
||||||
|
|
||||||
|
int local_get_nolo_ver(char * ver, size_t size);
|
||||||
|
int local_set_nolo_ver(const char * ver);
|
||||||
|
|
||||||
|
int local_get_sw_ver(char * ver, size_t size);
|
||||||
|
int local_set_sw_ver(const char * ver);
|
||||||
|
|
||||||
|
int local_get_content_ver(char * ver, size_t size);
|
||||||
|
int local_set_content_ver(const char * ver);
|
||||||
|
|
||||||
|
#endif
|
||||||
+1327
-306
File diff suppressed because it is too large.
Load diff
-60
@@ -1,60 +0,0 @@
|
|||||||
#ifndef _INCLUDE_MAIN_H_
|
|
||||||
#define _INCLUDE_MAIN_H_
|
|
||||||
|
|
||||||
#define _FILE_OFFSET_BITS 64
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
int reverse_extract_pieces(char *dir);
|
|
||||||
void flash_image(char *filename, char *piece, char *version);
|
|
||||||
int fiasco_read_image(char *file);
|
|
||||||
void check_nolo_order();
|
|
||||||
extern struct usb_dev_handle *dev;
|
|
||||||
unsigned long get_file_size(char *file);
|
|
||||||
void progressbar(unsigned long long part, unsigned long long total);
|
|
||||||
int get_status();
|
|
||||||
int get_peripheral_host_mode(int foo);
|
|
||||||
int boot_board(char *cmdline);
|
|
||||||
int boot_board(char *cmdline);
|
|
||||||
int reboot_board();
|
|
||||||
char *fpid_file(char *filename);
|
|
||||||
int set_rd_mode(unsigned short mode);
|
|
||||||
int set_usb_host_mode(unsigned short mode);
|
|
||||||
int query_hw_revision();
|
|
||||||
int query_rdmode_device();
|
|
||||||
int query_root_device();
|
|
||||||
int query_nolo_version();
|
|
||||||
int add_piece(char *piece);
|
|
||||||
|
|
||||||
#define D if (verbose)
|
|
||||||
|
|
||||||
#define CMD_WRITE 64
|
|
||||||
#define CMD_QUERY 192
|
|
||||||
|
|
||||||
#define NOLO_GET_STATUS 1
|
|
||||||
#define NOLO_GET_BOARD_ID 2
|
|
||||||
#define NOLO_GET_VERSION 3
|
|
||||||
|
|
||||||
struct piece_t {
|
|
||||||
char *name;
|
|
||||||
char *type;
|
|
||||||
char *vers;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int pcs_n;
|
|
||||||
extern struct piece_t pcs[10];
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PIECE_XLOADER = 0,
|
|
||||||
PIECE_SECONDARY,
|
|
||||||
PIECE_KERNEL,
|
|
||||||
PIECE_INITFS,
|
|
||||||
PIECE_ROOTFS,
|
|
||||||
PIECE_OMAPNAND,
|
|
||||||
PIECE_LAST
|
|
||||||
};
|
|
||||||
|
|
||||||
extern char *pieces[];
|
|
||||||
extern char *modes[];
|
|
||||||
extern char *root_devices[];
|
|
||||||
|
|
||||||
#endif
|
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2013 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define NAME "0xFFFF"
|
||||||
|
#define INFO NAME " \\- Open Free Fiasco Firmware Flasher, version " VERSION
|
||||||
|
#define DESCRIPTION "0xFFFF is Open Free Fiasco Firmware Flasher for Maemo devices. It support generating and unpacking FIASCO images on local computer. Useful for editing Maemo firmware package for future flash. It support via USB flashing any image type to Maemo device and also \"cold\" flashing which means flashing dead device with erased bootloader. There is support for booting kernel via USB without flashing to NAND and also changing configuration of Maemo device (enable/disable R&D mode, changing HW revision strings, ...).\n\n0xFFFF is alternative tool to proprietary Nokia flasher-3.5 and fiasco-gen. 0xFFFF generate compatible FIASCO images and also accept FIASCO images generated by Nokia fiasco-gen."
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
FILE * pipe;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
pipe = popen("./0xFFFF -h", "r");
|
||||||
|
if ( ! pipe )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
puts(".TH " NAME " 1 \"" __DATE__ "\" \"" NAME " " VERSION "\"");
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
puts(".SH NAME");
|
||||||
|
puts(INFO);
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
puts(".SH SYNOPSIS");
|
||||||
|
puts(".B " NAME);
|
||||||
|
puts(".I [options]");
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
puts(".SH DESCRIPTION");
|
||||||
|
puts(DESCRIPTION);
|
||||||
|
|
||||||
|
while ( fgets(buf, sizeof(buf), pipe) ) {
|
||||||
|
|
||||||
|
if ( ! buf[0] )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ( buf[0] == ' ' && buf[2] == ' ' ) {
|
||||||
|
|
||||||
|
char * ptr = buf;
|
||||||
|
|
||||||
|
while ( *ptr && *ptr == ' ' )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( ! *ptr )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
printf(".br\n%s", ptr);
|
||||||
|
|
||||||
|
} else if ( buf[0] == ' ' ) {
|
||||||
|
|
||||||
|
char * ptr = buf;
|
||||||
|
char * ptr2;
|
||||||
|
|
||||||
|
while ( *ptr && *ptr == ' ' )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( ! *ptr )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ptr2 = ptr;
|
||||||
|
|
||||||
|
while ( *ptr2 && ( *ptr2 != ' ' || *(ptr2-1) != ' ' ) )
|
||||||
|
++ptr2;
|
||||||
|
|
||||||
|
*(ptr2-1) = 0;
|
||||||
|
|
||||||
|
while ( *ptr2 && *ptr2 == ' ' )
|
||||||
|
++ptr2;
|
||||||
|
|
||||||
|
if ( *ptr2 )
|
||||||
|
printf(".TP\n.B %s\n%s", ptr, ptr2);
|
||||||
|
else
|
||||||
|
printf(".br\n%s\n", ptr);
|
||||||
|
|
||||||
|
} else if ( buf[strlen(buf)-2] == ':' ) {
|
||||||
|
|
||||||
|
printf("\n.SH %s\n", buf);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(pipe);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
+239
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mkii.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
|
||||||
|
int mkii_init(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("Mk II protocol is not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum device mkii_get_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return DEVICE_UNKNOWN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)image;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_reboot_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_root_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_root_device(struct usb_device_info * dev, int device) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)device;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_usb_host_mode(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_usb_host_mode(struct usb_device_info * dev, int enable) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)enable;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_rd_mode(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_rd_mode(struct usb_device_info * dev, int enable) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)enable;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)flags;
|
||||||
|
(void)size;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_rd_flags(struct usb_device_info * dev, const char * flags) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)flags;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t mkii_get_hwrev(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_hwrev(struct usb_device_info * dev, int16_t hwrev) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)hwrev;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_kernel_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
(void)size;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_kernel_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_initfs_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
(void)size;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_initfs_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
(void)size;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_nolo_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_sw_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
(void)size;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_sw_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_get_content_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
(void)size;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkii_set_content_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
ERROR("Not implemented yet");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MKII_H
|
||||||
|
#define MKII_H
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
|
||||||
|
int mkii_init(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
enum device mkii_get_device(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
int mkii_flash_image(struct usb_device_info * dev, struct image * image);
|
||||||
|
int mkii_reboot_device(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
int mkii_get_root_device(struct usb_device_info * dev);
|
||||||
|
int mkii_set_root_device(struct usb_device_info * dev, int device);
|
||||||
|
|
||||||
|
int mkii_get_usb_host_mode(struct usb_device_info * dev);
|
||||||
|
int mkii_set_usb_host_mode(struct usb_device_info * dev, int enable);
|
||||||
|
|
||||||
|
int mkii_get_rd_mode(struct usb_device_info * dev);
|
||||||
|
int mkii_set_rd_mode(struct usb_device_info * dev, int enable);
|
||||||
|
|
||||||
|
int mkii_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size);
|
||||||
|
int mkii_set_rd_flags(struct usb_device_info * dev, const char * flags);
|
||||||
|
|
||||||
|
int16_t mkii_get_hwrev(struct usb_device_info * dev);
|
||||||
|
int mkii_set_hwrev(struct usb_device_info * dev, int16_t hwrev);
|
||||||
|
|
||||||
|
int mkii_get_kernel_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int mkii_set_kernel_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int mkii_get_initfs_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int mkii_set_initfs_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int mkii_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int mkii_set_nolo_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int mkii_get_sw_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int mkii_set_sw_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int mkii_get_content_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int mkii_set_content_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
#endif
|
||||||
+885
@@ -0,0 +1,885 @@
|
|||||||
|
/*
|
||||||
|
* 0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
* Copyright (C) 2007-2009 pancake <pancake@youterm.com>
|
||||||
|
* Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
#include <usb.h>
|
||||||
|
|
||||||
|
#include "nolo.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "global.h"
|
||||||
|
#include "printf-utils.h"
|
||||||
|
|
||||||
|
/* Request type */
|
||||||
|
#define NOLO_WRITE 64
|
||||||
|
#define NOLO_QUERY 192
|
||||||
|
|
||||||
|
/* Request */
|
||||||
|
#define NOLO_STATUS 1
|
||||||
|
#define NOLO_GET_NOLO_VERSION 3
|
||||||
|
#define NOLO_IDENTIFY 4
|
||||||
|
#define NOLO_ERROR_LOG 5
|
||||||
|
#define NOLO_SET 16
|
||||||
|
#define NOLO_GET 17
|
||||||
|
#define NOLO_STRING 18
|
||||||
|
#define NOLO_SET_STRING 19
|
||||||
|
#define NOLO_GET_STRING 20
|
||||||
|
#define NOLO_SEND_IMAGE 66
|
||||||
|
#define NOLO_SET_SW_RELEASE 67
|
||||||
|
#define NOLO_FLASH_IMAGE 80
|
||||||
|
#define NOLO_SEND_FLASH_FINISH 82
|
||||||
|
#define NOLO_SEND_FLASH_IMAGE 84
|
||||||
|
#define NOLO_BOOT 130
|
||||||
|
#define NOLO_REBOOT 131
|
||||||
|
|
||||||
|
/* Indexes - Flash image */
|
||||||
|
#define NOLO_IMAGE_BOOTLOADER 1
|
||||||
|
#define NOLO_IMAGE_KERNEL 3
|
||||||
|
#define NOLO_IMAGE_INITFS 4
|
||||||
|
#define NOLO_IMAGE_CMT 66
|
||||||
|
|
||||||
|
/* Indexes - Set & Get */
|
||||||
|
#define NOLO_RD_MODE 0
|
||||||
|
#define NOLO_ROOT_DEVICE 1
|
||||||
|
#define NOLO_USB_HOST_MODE 2
|
||||||
|
#define NOLO_ADD_RD_FLAGS 3
|
||||||
|
#define NOLO_DEL_RD_FLAGS 4
|
||||||
|
|
||||||
|
/* Values - R&D flags */
|
||||||
|
#define NOLO_RD_FLAG_NO_OMAP_WD 0x002
|
||||||
|
#define NOLO_RD_FLAG_NO_EXT_WD 0x004
|
||||||
|
#define NOLO_RD_FLAG_NO_LIFEGUARD 0x008
|
||||||
|
#define NOLO_RD_FLAG_SERIAL_CONSOLE 0x010
|
||||||
|
#define NOLO_RD_FLAG_NO_USB_TIMEOUT 0x020
|
||||||
|
#define NOLO_RD_FLAG_STI_CONSOLE 0x040
|
||||||
|
#define NOLO_RD_FLAG_NO_CHARGING 0x080
|
||||||
|
#define NOLO_RD_FLAG_FORCE_POWER_KEY 0x100
|
||||||
|
|
||||||
|
/* Values - Boot mode */
|
||||||
|
#define NOLO_BOOT_MODE_NORMAL 0
|
||||||
|
#define NOLO_BOOT_MODE_UPDATE 1
|
||||||
|
|
||||||
|
#define NOLO_ERROR_RETURN(str, ...) do { nolo_error_log(dev, str == NULL); ERROR_RETURN(str, __VA_ARGS__); } while (0)
|
||||||
|
|
||||||
|
static void nolo_error_log(struct usb_device_info * dev, int only_clear) {
|
||||||
|
|
||||||
|
char buf[2048];
|
||||||
|
size_t i, count;
|
||||||
|
|
||||||
|
for ( count = 0; count < 20; ++count ) {
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_ERROR_LOG, 0, 0, buf, sizeof(buf), 2000) <= 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ( ! only_clear ) {
|
||||||
|
|
||||||
|
for ( i = 0; i < sizeof(buf)-2; ++i )
|
||||||
|
if ( buf[i] == 0 && buf[i+1] != 0 )
|
||||||
|
buf[i] = '\n';
|
||||||
|
|
||||||
|
buf[sizeof(buf)-1] = 0;
|
||||||
|
puts(buf);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nolo_identify_string(struct usb_device_info * dev, const char * str, char * out, size_t size) {
|
||||||
|
|
||||||
|
char buf[512];
|
||||||
|
char * ptr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
|
||||||
|
ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_IDENTIFY, 0, 0, (char *)buf, sizeof(buf), 2000);
|
||||||
|
if ( ret < 0 )
|
||||||
|
NOLO_ERROR_RETURN("NOLO_IDENTIFY failed", -1);
|
||||||
|
|
||||||
|
ptr = memmem(buf, ret, str, strlen(str));
|
||||||
|
if ( ! ptr )
|
||||||
|
ERROR_RETURN("Substring was not found", -1);
|
||||||
|
|
||||||
|
ptr += strlen(str) + 1;
|
||||||
|
|
||||||
|
while ( ptr-buf < ret && *ptr < 32 )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( ! *ptr )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
strncpy(out, ptr, size-1);
|
||||||
|
out[size-1] = 0;
|
||||||
|
return strlen(out);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nolo_set_string(struct usb_device_info * dev, char * str, char * arg) {
|
||||||
|
|
||||||
|
if ( simulate )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, str, strlen(str), 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("NOLO_STRING failed", -1);
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET_STRING, 0, 0, arg, strlen(arg), 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("NOLO_SET_STRING failed", -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nolo_get_string(struct usb_device_info * dev, char * str, char * out, size_t size) {
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, str, strlen(str), 2000) < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ( ( ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET_STRING, 0, 0, out, size-1, 2000) ) < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
out[size-1] = 0;
|
||||||
|
out[ret] = 0;
|
||||||
|
return strlen(out);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nolo_get_version_string(struct usb_device_info * dev, const char * str, char * out, size_t size) {
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
char buf[512];
|
||||||
|
|
||||||
|
if ( strlen(str) > 500 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
sprintf(buf, "version:%s", str);
|
||||||
|
|
||||||
|
ret = nolo_get_string(dev, buf, out, size);
|
||||||
|
|
||||||
|
nolo_error_log(dev, 1);
|
||||||
|
|
||||||
|
if ( ret < 0 )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ( ! out[0] )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_init(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
uint32_t val = 1;
|
||||||
|
enum device device;
|
||||||
|
|
||||||
|
printf("Initializing NOLO...\n");
|
||||||
|
|
||||||
|
while ( val != 0 )
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_STATUS, 0, 0, (char *)&val, 4, 2000) == -1 )
|
||||||
|
NOLO_ERROR_RETURN("NOLO_STATUS failed", -1);
|
||||||
|
|
||||||
|
/* clear error log */
|
||||||
|
nolo_error_log(dev, 1);
|
||||||
|
|
||||||
|
device = nolo_get_device(dev);
|
||||||
|
|
||||||
|
if ( ! dev->device )
|
||||||
|
dev->device = device;
|
||||||
|
|
||||||
|
if ( dev->device && device && dev->device != device ) {
|
||||||
|
ERROR("Device mishmash, expected %s, got %s", device_to_string(dev->device), device_to_string(device));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->hwrev = nolo_get_hwrev(dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum device nolo_get_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
char buf[20];
|
||||||
|
if ( nolo_identify_string(dev, "prod_code", buf, sizeof(buf)) < 0 )
|
||||||
|
return DEVICE_UNKNOWN;
|
||||||
|
else if ( buf[0] )
|
||||||
|
return device_from_string(buf);
|
||||||
|
else
|
||||||
|
return DEVICE_UNKNOWN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nolo_send_image(struct usb_device_info * dev, struct image * image, int flash) {
|
||||||
|
|
||||||
|
char buf[0x20000];
|
||||||
|
char * ptr;
|
||||||
|
const char * type;
|
||||||
|
uint8_t len;
|
||||||
|
uint16_t hash;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t need;
|
||||||
|
uint32_t readed;
|
||||||
|
int request;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ( flash )
|
||||||
|
printf("Send and flash image:\n");
|
||||||
|
else
|
||||||
|
printf("Load image:\n");
|
||||||
|
image_print_info(image);
|
||||||
|
|
||||||
|
if ( image->type == IMAGE_2ND || image->type == IMAGE_MMC )
|
||||||
|
ERROR_RETURN("Sending 2nd and mmc images are not supported", -1);
|
||||||
|
|
||||||
|
if ( ! flash && image->type == IMAGE_ROOTFS )
|
||||||
|
ERROR_RETURN("Rootfs image must be sent in flash mode", -1);
|
||||||
|
|
||||||
|
ptr = buf;
|
||||||
|
|
||||||
|
/* Signature */
|
||||||
|
memcpy(ptr, "\x2E\x19\x01\x01", 4);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
/* Space */
|
||||||
|
memcpy(ptr, "\x00", 1);
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
/* Hash */
|
||||||
|
hash = htons(image->hash);
|
||||||
|
memcpy(ptr, &hash, 2);
|
||||||
|
ptr += 2;
|
||||||
|
|
||||||
|
/* Type */
|
||||||
|
type = image_type_to_string(image->type);
|
||||||
|
if ( ! type )
|
||||||
|
ERROR_RETURN("Unknown image type", -1);
|
||||||
|
memset(ptr, 0, 12);
|
||||||
|
strncpy(ptr, type, 12);
|
||||||
|
ptr += 12;
|
||||||
|
|
||||||
|
/* Size */
|
||||||
|
size = htonl(image->size);
|
||||||
|
memcpy(ptr, &size, 4);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
/* Space */
|
||||||
|
memcpy(ptr, "\x00\x00\x00\x00", 4);
|
||||||
|
ptr += 4;
|
||||||
|
|
||||||
|
/* Device & hwrev */
|
||||||
|
if ( image->devices ) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
uint8_t len;
|
||||||
|
char buf[9];
|
||||||
|
char ** bufs = NULL;
|
||||||
|
struct device_list * device = image->devices;
|
||||||
|
|
||||||
|
while ( device ) {
|
||||||
|
if ( device->device == dev->device && hwrev_is_valid(device->hwrevs, dev->hwrev) )
|
||||||
|
break;
|
||||||
|
device = device->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( device )
|
||||||
|
bufs = device_list_alloc_to_bufs(device);
|
||||||
|
|
||||||
|
if ( bufs ) {
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
snprintf(buf, 8, "%d", dev->hwrev);
|
||||||
|
|
||||||
|
for ( i = 0; bufs[i]; ++i ) {
|
||||||
|
len = ((uint8_t*)bufs[i])[0];
|
||||||
|
if ( memmem(bufs[i]+1, len, buf, strlen(buf)) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( bufs[i] ) {
|
||||||
|
/* Device & hwrev string header */
|
||||||
|
memcpy(ptr, "\x32", 1);
|
||||||
|
ptr += 1;
|
||||||
|
/* Device & hwrev string size */
|
||||||
|
memcpy(ptr, &len, 1);
|
||||||
|
ptr += 1;
|
||||||
|
/* Device & hwrev string */
|
||||||
|
memcpy(ptr, bufs[i]+1, len);
|
||||||
|
ptr += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(bufs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Version */
|
||||||
|
if ( image->version ) {
|
||||||
|
len = strnlen(image->version, 255) + 1;
|
||||||
|
/* Version string header */
|
||||||
|
memcpy(ptr, "\x31", 1);
|
||||||
|
ptr += 1;
|
||||||
|
/* Version string size */
|
||||||
|
memcpy(ptr, &len, 1);
|
||||||
|
ptr += 1;
|
||||||
|
/* Version string */
|
||||||
|
memcpy(ptr, image->version, len);
|
||||||
|
ptr += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( flash )
|
||||||
|
request = NOLO_SEND_FLASH_IMAGE;
|
||||||
|
else
|
||||||
|
request = NOLO_SEND_IMAGE;
|
||||||
|
|
||||||
|
printf("Sending image header...\n");
|
||||||
|
|
||||||
|
if ( ! simulate ) {
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, request, 0, 0, buf, ptr-buf, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Sending image header failed", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( flash )
|
||||||
|
printf("Sending and flashing image...\n");
|
||||||
|
else
|
||||||
|
printf("Sending image...\n");
|
||||||
|
printf_progressbar(0, image->size);
|
||||||
|
image_seek(image, 0);
|
||||||
|
readed = 0;
|
||||||
|
while ( readed < image->size ) {
|
||||||
|
need = image->size - readed;
|
||||||
|
if ( need > sizeof(buf) )
|
||||||
|
need = sizeof(buf);
|
||||||
|
ret = image_read(image, buf, need);
|
||||||
|
if ( ret == 0 )
|
||||||
|
break;
|
||||||
|
if ( ! simulate ) {
|
||||||
|
if ( usb_bulk_write(dev->udev, 2, buf, ret, 5000) != ret ) {
|
||||||
|
PRINTF_END();
|
||||||
|
NOLO_ERROR_RETURN("Sending image failed", -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readed += ret;
|
||||||
|
printf_progressbar(readed, image->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( flash ) {
|
||||||
|
printf("Finishing flashing...\n");
|
||||||
|
if ( ! simulate ) {
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SEND_FLASH_FINISH, 0, 0, NULL, 0, 30000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Finishing failed", -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Done\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_load_image(struct usb_device_info * dev, struct image * image) {
|
||||||
|
|
||||||
|
if ( image->type != IMAGE_KERNEL && image->type != IMAGE_INITFS )
|
||||||
|
ERROR_RETURN("Only kernel or initfs image can be loaded", -1);
|
||||||
|
|
||||||
|
return nolo_send_image(dev, image, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
int flash;
|
||||||
|
int index;
|
||||||
|
unsigned long long int part;
|
||||||
|
unsigned long long int total;
|
||||||
|
unsigned long long int last_total;
|
||||||
|
char status[20];
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
if ( image->type == IMAGE_ROOTFS )
|
||||||
|
flash = 1;
|
||||||
|
else
|
||||||
|
flash = 0;
|
||||||
|
|
||||||
|
ret = nolo_send_image(dev, image, flash);
|
||||||
|
if ( ret < 0 )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ( image->type == IMAGE_SECONDARY )
|
||||||
|
index = NOLO_IMAGE_BOOTLOADER;
|
||||||
|
else if ( image->type == IMAGE_KERNEL )
|
||||||
|
index = NOLO_IMAGE_KERNEL;
|
||||||
|
else if ( image->type == IMAGE_CMT_MCUSW )
|
||||||
|
index = NOLO_IMAGE_CMT;
|
||||||
|
else
|
||||||
|
index = -1;
|
||||||
|
|
||||||
|
if ( image->type == IMAGE_CMT_MCUSW )
|
||||||
|
nolo_set_string(dev, "cmt:verify", "1");
|
||||||
|
|
||||||
|
if ( ! flash && index >= 0 ) {
|
||||||
|
|
||||||
|
printf("Flashing image...\n");
|
||||||
|
|
||||||
|
if ( ! simulate ) {
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_FLASH_IMAGE, 0, index, NULL, 0, 10000) )
|
||||||
|
NOLO_ERROR_RETURN("Flashing failed", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Done\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( image->type == IMAGE_CMT_MCUSW ) {
|
||||||
|
|
||||||
|
int state = 0;
|
||||||
|
last_total = 0;
|
||||||
|
|
||||||
|
if ( nolo_get_string(dev, "cmt:status", buf, sizeof(buf)) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("cmt:status failed", -1);
|
||||||
|
|
||||||
|
if ( strncmp(buf, "idle", strlen("idle")) == 0 )
|
||||||
|
state = 4;
|
||||||
|
else
|
||||||
|
printf("Erasing CMT...\n");
|
||||||
|
|
||||||
|
while ( state != 4 ) {
|
||||||
|
|
||||||
|
if ( nolo_get_string(dev, "cmt:status", buf, sizeof(buf)) < 0 ) {
|
||||||
|
PRINTF_END();
|
||||||
|
NOLO_ERROR_RETURN("cmt:status failed", -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( strncmp(buf, "finished", strlen("finished")) == 0 ) {
|
||||||
|
|
||||||
|
if ( state <= 0 ) {
|
||||||
|
printf_progressbar(last_total, last_total);
|
||||||
|
printf("Done\n");
|
||||||
|
}
|
||||||
|
if ( state <= 1 )
|
||||||
|
printf("Programming CMT...\n");
|
||||||
|
if ( state <= 2 ) {
|
||||||
|
printf_progressbar(last_total, last_total);
|
||||||
|
printf("Done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
state = 4;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if ( sscanf(buf, "%s:%llu/%llu", status, &part, &total) != 3 )
|
||||||
|
PRINTF_ERROR_RETURN("cmt:status unknown", -1);
|
||||||
|
|
||||||
|
if ( strcmp(status, "program") == 0 && state <= 0 ) {
|
||||||
|
printf_progressbar(last_total, last_total);
|
||||||
|
printf("Done\n");
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( strcmp(status, "program") == 0 && state <= 1 ) {
|
||||||
|
printf("Programming CMT...\n");
|
||||||
|
state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf_progressbar(part, total);
|
||||||
|
last_total = total;
|
||||||
|
|
||||||
|
if ( strcmp(status, "erase") == 0 && state <= 0 && part == total ) {
|
||||||
|
printf("Done\n");
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( strcmp(status, "program") == 0 && state <= 2 && part == total ) {
|
||||||
|
printf("Done\n");
|
||||||
|
state = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(0xc350); // 0.5s
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_boot_device(struct usb_device_info * dev, const char * cmdline) {
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
int mode = NOLO_BOOT_MODE_NORMAL;
|
||||||
|
|
||||||
|
if ( cmdline && strncmp(cmdline, "update", strlen("update")) == 0 && cmdline[strlen("update")] <= 32 ) {
|
||||||
|
mode = NOLO_BOOT_MODE_UPDATE;
|
||||||
|
cmdline += strlen("update");
|
||||||
|
if ( *cmdline ) ++cmdline;
|
||||||
|
while ( *cmdline && *cmdline <= 32 )
|
||||||
|
++cmdline;
|
||||||
|
if ( *cmdline ) {
|
||||||
|
printf("Booting kernel to update mode with cmdline: %s...\n", cmdline);
|
||||||
|
size = strlen(cmdline);
|
||||||
|
} else {
|
||||||
|
printf("Booting kernel to update mode with default cmdline...\n");
|
||||||
|
cmdline = NULL;
|
||||||
|
}
|
||||||
|
} else if ( cmdline && cmdline[0] ) {
|
||||||
|
printf("Booting kernel with cmdline: '%s'...\n", cmdline);
|
||||||
|
size = strlen(cmdline)+1;
|
||||||
|
} else {
|
||||||
|
printf("Booting kernel with default cmdline...\n");
|
||||||
|
cmdline = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_BOOT, mode, 0, (char *)cmdline, size, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Booting failed", -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_reboot_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
printf("Rebooting device...\n");
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_REBOOT, 0, 0, NULL, 0, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("NOLO_REBOOT failed", -1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_get_root_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
uint8_t device = 0;
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_ROOT_DEVICE, (char *)&device, 1, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot get root device", -1);
|
||||||
|
return device;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_root_device(struct usb_device_info * dev, int device) {
|
||||||
|
|
||||||
|
printf("Setting root device to %d...\n", device);
|
||||||
|
if ( simulate )
|
||||||
|
return 0;
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, device, NOLO_ROOT_DEVICE, NULL, 0, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot set root device", -1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_get_usb_host_mode(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
uint32_t enabled = 0;
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_USB_HOST_MODE, (void *)&enabled, 4, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot get USB host mode status", -1);
|
||||||
|
return enabled ? 1 : 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_usb_host_mode(struct usb_device_info * dev, int enable) {
|
||||||
|
|
||||||
|
printf("%s USB host mode...\n", enable ? "Enabling" : "Disabling");
|
||||||
|
if ( simulate )
|
||||||
|
return 0;
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, enable, NOLO_USB_HOST_MODE, NULL, 0, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot change USB host mode status", -1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_get_rd_mode(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
uint8_t enabled = 0;
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_RD_MODE, (char *)&enabled, 1, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot get R&D mode status", -1);
|
||||||
|
return enabled ? 1 : 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_rd_mode(struct usb_device_info * dev, int enable) {
|
||||||
|
|
||||||
|
printf("%s R&D mode...\n", enable ? "Enabling" : "Disabling");
|
||||||
|
if ( simulate )
|
||||||
|
return 0;
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, enable, NOLO_RD_MODE, NULL, 0, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot change R&D mode status", -1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#define APPEND_STRING(ptr, buf, size, string) do { if ( (int)size > ptr-buf ) ptr += snprintf(ptr, size-(ptr-buf), "%s,", string); } while (0)
|
||||||
|
|
||||||
|
int nolo_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size) {
|
||||||
|
|
||||||
|
uint16_t add_flags = 0;
|
||||||
|
char * ptr = flags;
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_ADD_RD_FLAGS, (char *)&add_flags, 2, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot get R&D flags", -1);
|
||||||
|
|
||||||
|
if ( add_flags & NOLO_RD_FLAG_NO_OMAP_WD )
|
||||||
|
APPEND_STRING(ptr, flags, size, "no-omap-wd");
|
||||||
|
if ( add_flags & NOLO_RD_FLAG_NO_EXT_WD )
|
||||||
|
APPEND_STRING(ptr, flags, size, "no-ext-wd");
|
||||||
|
if ( add_flags & NOLO_RD_FLAG_NO_LIFEGUARD )
|
||||||
|
APPEND_STRING(ptr, flags, size, "no-lifeguard-reset");
|
||||||
|
if ( add_flags & NOLO_RD_FLAG_SERIAL_CONSOLE )
|
||||||
|
APPEND_STRING(ptr, flags, size, "serial-console");
|
||||||
|
if ( add_flags & NOLO_RD_FLAG_NO_USB_TIMEOUT )
|
||||||
|
APPEND_STRING(ptr, flags, size, "no-usb-timeout");
|
||||||
|
if ( add_flags & NOLO_RD_FLAG_STI_CONSOLE )
|
||||||
|
APPEND_STRING(ptr, flags, size, "sti-console");
|
||||||
|
if ( add_flags & NOLO_RD_FLAG_NO_CHARGING )
|
||||||
|
APPEND_STRING(ptr, flags, size, "no-charging");
|
||||||
|
if ( add_flags & NOLO_RD_FLAG_FORCE_POWER_KEY )
|
||||||
|
APPEND_STRING(ptr, flags, size, "force-power-key");
|
||||||
|
|
||||||
|
if ( ptr != flags && *(ptr-1) == ',' )
|
||||||
|
*(--ptr) = 0;
|
||||||
|
|
||||||
|
return ptr-flags;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef APPEND_STRING
|
||||||
|
|
||||||
|
int nolo_set_rd_flags(struct usb_device_info * dev, const char * flags) {
|
||||||
|
|
||||||
|
const char * ptr = flags;
|
||||||
|
const char * endptr = ptr;
|
||||||
|
|
||||||
|
int add_flags = 0;
|
||||||
|
int del_flags = 0;
|
||||||
|
|
||||||
|
if ( flags && flags[0] )
|
||||||
|
printf("Setting R&D flags to: %s...\n", flags);
|
||||||
|
else
|
||||||
|
printf("Clearing all R&D flags...\n");
|
||||||
|
|
||||||
|
while ( ptr && *ptr ) {
|
||||||
|
|
||||||
|
while ( *ptr <= 32 )
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if ( ! *ptr )
|
||||||
|
break;
|
||||||
|
|
||||||
|
endptr = strchr(ptr, ',');
|
||||||
|
if ( endptr )
|
||||||
|
endptr -= 1;
|
||||||
|
else
|
||||||
|
endptr = ptr+strlen(ptr);
|
||||||
|
|
||||||
|
if ( strncmp("no-omap-wd", ptr, endptr-ptr) == 0 )
|
||||||
|
add_flags |= NOLO_RD_FLAG_NO_OMAP_WD;
|
||||||
|
if ( strncmp("no-ext-wd", ptr, endptr-ptr) == 0 )
|
||||||
|
add_flags |= NOLO_RD_FLAG_NO_EXT_WD;
|
||||||
|
if ( strncmp("no-lifeguard-reset", ptr, endptr-ptr) == 0 )
|
||||||
|
add_flags |= NOLO_RD_FLAG_NO_LIFEGUARD;
|
||||||
|
if ( strncmp("serial-console", ptr, endptr-ptr) == 0 )
|
||||||
|
add_flags |= NOLO_RD_FLAG_SERIAL_CONSOLE;
|
||||||
|
if ( strncmp("no-usb-timeout", ptr, endptr-ptr) == 0 )
|
||||||
|
add_flags |= NOLO_RD_FLAG_NO_USB_TIMEOUT;
|
||||||
|
if ( strncmp("sti-console", ptr, endptr-ptr) == 0 )
|
||||||
|
add_flags |= NOLO_RD_FLAG_STI_CONSOLE;
|
||||||
|
if ( strncmp("no-charging", ptr, endptr-ptr) == 0 )
|
||||||
|
add_flags |= NOLO_RD_FLAG_NO_CHARGING;
|
||||||
|
if ( strncmp("force-power-key", ptr, endptr-ptr) == 0 )
|
||||||
|
add_flags |= NOLO_RD_FLAG_FORCE_POWER_KEY;
|
||||||
|
|
||||||
|
if ( *(endptr+1) )
|
||||||
|
ptr = endptr+2;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! ( add_flags & NOLO_RD_FLAG_NO_OMAP_WD ) )
|
||||||
|
del_flags |= NOLO_RD_FLAG_NO_OMAP_WD;
|
||||||
|
if ( ! ( add_flags & NOLO_RD_FLAG_NO_EXT_WD ) )
|
||||||
|
del_flags |= NOLO_RD_FLAG_NO_EXT_WD;
|
||||||
|
if ( ! ( add_flags & NOLO_RD_FLAG_NO_LIFEGUARD ) )
|
||||||
|
del_flags |= NOLO_RD_FLAG_NO_LIFEGUARD;
|
||||||
|
if ( ! ( add_flags & NOLO_RD_FLAG_SERIAL_CONSOLE ) )
|
||||||
|
del_flags |= NOLO_RD_FLAG_SERIAL_CONSOLE;
|
||||||
|
if ( ! ( add_flags & NOLO_RD_FLAG_NO_USB_TIMEOUT ) )
|
||||||
|
del_flags |= NOLO_RD_FLAG_NO_USB_TIMEOUT;
|
||||||
|
if ( ! ( add_flags & NOLO_RD_FLAG_STI_CONSOLE ) )
|
||||||
|
del_flags |= NOLO_RD_FLAG_STI_CONSOLE;
|
||||||
|
if ( ! ( add_flags & NOLO_RD_FLAG_NO_CHARGING ) )
|
||||||
|
del_flags |= NOLO_RD_FLAG_NO_CHARGING;
|
||||||
|
if ( ! ( add_flags & NOLO_RD_FLAG_FORCE_POWER_KEY ) )
|
||||||
|
del_flags |= NOLO_RD_FLAG_FORCE_POWER_KEY;
|
||||||
|
|
||||||
|
if ( simulate )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, add_flags, NOLO_ADD_RD_FLAGS, NULL, 0, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot add R&D flags", -1);
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, del_flags, NOLO_DEL_RD_FLAGS, NULL, 0, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot del R&D flags", -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t nolo_get_hwrev(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
char buf[10];
|
||||||
|
if ( nolo_identify_string(dev, "hw_rev", buf, sizeof(buf)) <= 0 )
|
||||||
|
return -1;
|
||||||
|
return atoi(buf);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_hwrev(struct usb_device_info * dev, int16_t hwrev) {
|
||||||
|
|
||||||
|
char buf[9];
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
snprintf(buf, 8, "%d", hwrev);
|
||||||
|
printf("Setting HW revision to: %s\n", buf);
|
||||||
|
return nolo_set_string(dev, "hw_rev", buf);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_get_kernel_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
return nolo_get_version_string(dev, "kernel", ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_kernel_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
printf("nolo_set_kernel_ver is not implemented yet\n");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_get_initfs_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
return nolo_get_version_string(dev, "initfs", ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_initfs_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
printf("nolo_set_initfs_ver is not implemented yet\n");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
uint32_t version = 0;
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET_NOLO_VERSION, 0, 0, (char *)&version, 4, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("Cannot get NOLO version", -1);
|
||||||
|
|
||||||
|
if ( (version & 255) > 1 )
|
||||||
|
NOLO_ERROR_RETURN("Invalid NOLO version", -1);
|
||||||
|
|
||||||
|
return snprintf(ver, size, "%d.%d.%d", version >> 20 & 15, version >> 16 & 15, version >> 8 & 255);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_nolo_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
printf("nolo_set_nolo_ver is not implemented yet\n");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_get_sw_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
return nolo_get_version_string(dev, "sw-release", ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_sw_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
char buf[512];
|
||||||
|
char * ptr;
|
||||||
|
uint8_t len;
|
||||||
|
const char * str = "OSSO UART+USB";
|
||||||
|
|
||||||
|
printf("Setting Software release string to: %s\n", ver);
|
||||||
|
|
||||||
|
if ( strlen(ver) > UINT8_MAX )
|
||||||
|
NOLO_ERROR_RETURN("Software release string is too long", -1);
|
||||||
|
|
||||||
|
ptr = buf;
|
||||||
|
|
||||||
|
memcpy(ptr, "\xe8", 1);
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
len = strlen(str)+1;
|
||||||
|
memcpy(ptr, &len, 1);
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
memcpy(ptr, str, len);
|
||||||
|
ptr += len;
|
||||||
|
|
||||||
|
memcpy(ptr, "\x31", 1);
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
len = strlen(ver)+1;
|
||||||
|
memcpy(ptr, &len, 1);
|
||||||
|
ptr += 1;
|
||||||
|
|
||||||
|
memcpy(ptr, ver, len);
|
||||||
|
ptr += len;
|
||||||
|
|
||||||
|
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET_SW_RELEASE, 0, 0, buf, ptr-buf, 2000) < 0 )
|
||||||
|
NOLO_ERROR_RETURN("NOLO_SET_SW_RELEASE failed", -1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_get_content_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
return nolo_get_version_string(dev, "content", ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nolo_set_content_ver(struct usb_device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
printf("nolo_set_content_ver is not implemented yet\n");
|
||||||
|
(void)dev;
|
||||||
|
(void)ver;
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* 0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
* Copyright (C) 2007 pancake <pancake@youterm.com>
|
||||||
|
* Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NOLO_H
|
||||||
|
#define NOLO_H
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
|
||||||
|
int nolo_init(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
enum device nolo_get_device(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
int nolo_load_image(struct usb_device_info * dev, struct image * image);
|
||||||
|
int nolo_flash_image(struct usb_device_info * dev, struct image * image);
|
||||||
|
int nolo_boot_device(struct usb_device_info * dev, const char * cmdline);
|
||||||
|
int nolo_reboot_device(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
int nolo_get_root_device(struct usb_device_info * dev);
|
||||||
|
int nolo_set_root_device(struct usb_device_info * dev, int device);
|
||||||
|
|
||||||
|
int nolo_get_usb_host_mode(struct usb_device_info * dev);
|
||||||
|
int nolo_set_usb_host_mode(struct usb_device_info * dev, int enable);
|
||||||
|
|
||||||
|
int nolo_get_rd_mode(struct usb_device_info * dev);
|
||||||
|
int nolo_set_rd_mode(struct usb_device_info * dev, int enable);
|
||||||
|
|
||||||
|
int nolo_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size);
|
||||||
|
int nolo_set_rd_flags(struct usb_device_info * dev, const char * flags);
|
||||||
|
|
||||||
|
int16_t nolo_get_hwrev(struct usb_device_info * dev);
|
||||||
|
int nolo_set_hwrev(struct usb_device_info * dev, int16_t hwrev);
|
||||||
|
|
||||||
|
int nolo_get_kernel_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int nolo_set_kernel_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int nolo_get_initfs_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int nolo_set_initfs_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int nolo_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int nolo_set_nolo_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int nolo_get_sw_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int nolo_set_sw_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int nolo_get_content_ver(struct usb_device_info * dev, char * ver, size_t size);
|
||||||
|
int nolo_set_content_ver(struct usb_device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,640 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
#include "cold-flash.h"
|
||||||
|
#include "nolo.h"
|
||||||
|
#include "mkii.h"
|
||||||
|
#include "disk.h"
|
||||||
|
#include "local.h"
|
||||||
|
|
||||||
|
#include "operations.h"
|
||||||
|
|
||||||
|
struct device_info * dev_detect(void) {
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
struct device_info * dev = NULL;
|
||||||
|
struct usb_device_info * usb = NULL;
|
||||||
|
|
||||||
|
dev = calloc(1, sizeof(struct device_info));
|
||||||
|
if ( ! dev )
|
||||||
|
goto clean;
|
||||||
|
|
||||||
|
/* LOCAL */
|
||||||
|
if ( local_init() == 0 ) {
|
||||||
|
dev->method = METHOD_LOCAL;
|
||||||
|
dev->detected_device = local_get_device();
|
||||||
|
dev->detected_hwrev = local_get_hwrev();
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* USB */
|
||||||
|
usb = usb_open_and_wait_for_device();
|
||||||
|
if ( usb ) {
|
||||||
|
dev->method = METHOD_USB;
|
||||||
|
dev->usb = usb;
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
ret = nolo_init(dev->usb);
|
||||||
|
else if ( dev->usb->flash_device->protocol == FLASH_COLD )
|
||||||
|
ret = init_cold_flash(dev->usb);
|
||||||
|
else if ( dev->usb->flash_device->protocol == FLASH_MKII )
|
||||||
|
ret = mkii_init(dev->usb);
|
||||||
|
else if ( dev->usb->flash_device->protocol == FLASH_DISK )
|
||||||
|
ret = disk_init(dev->usb);
|
||||||
|
else {
|
||||||
|
ERROR("Unknown USB mode");
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ret < 0 )
|
||||||
|
goto clean;
|
||||||
|
|
||||||
|
dev->detected_device = dev_get_device(dev);
|
||||||
|
dev->detected_hwrev = dev_get_hwrev(dev);
|
||||||
|
|
||||||
|
if ( dev->detected_device && dev->usb->device && dev->detected_device != dev->usb->device ) {
|
||||||
|
ERROR("Bad device, expected %s, got %s", device_to_string(dev->usb->device), device_to_string(dev->detected_device));
|
||||||
|
goto clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
if (usb)
|
||||||
|
usb_close_device(usb);
|
||||||
|
free(dev);
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void dev_free(struct device_info * dev) {
|
||||||
|
|
||||||
|
if ( dev->usb )
|
||||||
|
usb_close_device(dev->usb);
|
||||||
|
free(dev);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum device dev_get_device(struct device_info * dev) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_device();
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
|
||||||
|
|
||||||
|
if ( protocol == FLASH_COLD )
|
||||||
|
return DEVICE_UNKNOWN;
|
||||||
|
else if ( protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_device(dev->usb);
|
||||||
|
else if ( protocol == FLASH_MKII )
|
||||||
|
return mkii_get_device(dev->usb);
|
||||||
|
/* else if ( protocol == FLASH_DISK )
|
||||||
|
return disk_get_device(dev->usb);*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEVICE_UNKNOWN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_load_image(struct device_info * dev, struct image * image) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL ) {
|
||||||
|
ERROR("Loading image on local device is not supported");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
|
||||||
|
|
||||||
|
if ( protocol == FLASH_NOLO )
|
||||||
|
return nolo_load_image(dev->usb, image);
|
||||||
|
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_cold_flash_images(struct device_info * dev, struct image * x2nd, struct image * secondary) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL ) {
|
||||||
|
ERROR("Cold Flashing on local device is not supported");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
|
||||||
|
|
||||||
|
if ( protocol == FLASH_COLD )
|
||||||
|
return cold_flash(dev->usb, x2nd, secondary);
|
||||||
|
|
||||||
|
usb_switch_to_cold(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_flash_image(struct device_info * dev, struct image * image) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_flash_image(image);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
|
||||||
|
|
||||||
|
if ( protocol == FLASH_NOLO )
|
||||||
|
return nolo_flash_image(dev->usb, image);
|
||||||
|
else if ( protocol == FLASH_MKII )
|
||||||
|
return mkii_flash_image(dev->usb, image);
|
||||||
|
else {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_dump_image(struct device_info * dev, enum image_type image, const char * file) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_dump_image(image, file);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
ERROR("Dump image via USB is not supported");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_check_badblocks(struct device_info * dev, const char * device) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_check_badblocks(device);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
ERROR("Check for badblocks via USB is not supported");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_boot_device(struct device_info * dev, const char * cmdline) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL ) {
|
||||||
|
ERROR("Booting device on local device does not make sense");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
|
||||||
|
|
||||||
|
if ( protocol == FLASH_NOLO )
|
||||||
|
return nolo_boot_device(dev->usb, cmdline);
|
||||||
|
else {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_reboot_device(struct device_info * dev) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_reboot_device();
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
|
||||||
|
|
||||||
|
if ( protocol == FLASH_COLD )
|
||||||
|
return leave_cold_flash(dev->usb);
|
||||||
|
else if ( protocol == FLASH_NOLO )
|
||||||
|
return nolo_reboot_device(dev->usb);
|
||||||
|
else if ( protocol == FLASH_MKII )
|
||||||
|
return mkii_reboot_device(dev->usb);
|
||||||
|
else {
|
||||||
|
ERROR("Rebooting device in RAW disk mode is not supported");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_root_device(struct device_info * dev) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_root_device();
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
|
||||||
|
|
||||||
|
if ( protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_root_device(dev->usb);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_root_device(struct device_info * dev, int device) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_root_device(device);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_root_device(dev->usb, device);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_usb_host_mode(struct device_info * dev) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_usb_host_mode();
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_usb_host_mode(dev->usb);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_usb_host_mode(struct device_info * dev, int enable) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_usb_host_mode(enable);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_usb_host_mode(dev->usb, enable);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_rd_mode(struct device_info * dev) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_rd_mode();
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_rd_mode(dev->usb);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_rd_mode(struct device_info * dev, int enable) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_rd_mode(enable);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_rd_mode(dev->usb, enable);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_rd_flags(struct device_info * dev, char * flags, size_t size) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_rd_flags(flags, size);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_rd_flags(dev->usb, flags, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_rd_flags(struct device_info * dev, const char * flags) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_rd_flags(flags);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_rd_flags(dev->usb, flags);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t dev_get_hwrev(struct device_info * dev) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_hwrev();
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_hwrev(dev->usb);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_hwrev(struct device_info * dev, int16_t hwrev) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_hwrev(hwrev);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_hwrev(dev->usb, hwrev);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_kernel_ver(struct device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_kernel_ver(ver, size);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_kernel_ver(dev->usb, ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_kernel_ver(struct device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_kernel_ver(ver);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_kernel_ver(dev->usb, ver);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_initfs_ver(struct device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_initfs_ver(ver, size);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_initfs_ver(dev->usb, ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_initfs_ver(struct device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_initfs_ver(ver);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_initfs_ver(dev->usb, ver);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_nolo_ver(struct device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_nolo_ver(ver, size);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_nolo_ver(dev->usb, ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_nolo_ver(struct device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_nolo_ver(ver);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_nolo_ver(dev->usb, ver);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_sw_ver(struct device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_sw_ver(ver, size);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_sw_ver(dev->usb, ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_sw_ver(struct device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_sw_ver(ver);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_sw_ver(dev->usb, ver);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_get_content_ver(struct device_info * dev, char * ver, size_t size) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_get_content_ver(ver, size);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_get_content_ver(dev->usb, ver, size);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int dev_set_content_ver(struct device_info * dev, const char * ver) {
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_LOCAL )
|
||||||
|
return local_set_content_ver(ver);
|
||||||
|
|
||||||
|
if ( dev->method == METHOD_USB ) {
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
|
||||||
|
return nolo_set_content_ver(dev->usb, ver);
|
||||||
|
|
||||||
|
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
|
||||||
|
usb_switch_to_nolo(dev->usb);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OPERATIONS_H
|
||||||
|
#define OPERATIONS_H
|
||||||
|
|
||||||
|
#include "image.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
|
||||||
|
enum connection_method {
|
||||||
|
METHOD_UNKNOWN = 0,
|
||||||
|
METHOD_USB,
|
||||||
|
METHOD_LOCAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device_info {
|
||||||
|
enum connection_method method;
|
||||||
|
enum device detected_device;
|
||||||
|
int16_t detected_hwrev;
|
||||||
|
struct usb_device_info * usb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct device_info * dev_detect(void);
|
||||||
|
void dev_free(struct device_info * dev);
|
||||||
|
|
||||||
|
enum device dev_get_device(struct device_info * dev);
|
||||||
|
|
||||||
|
int dev_cold_flash_images(struct device_info * dev, struct image * x2nd, struct image * secondary);
|
||||||
|
int dev_load_image(struct device_info * dev, struct image * image);
|
||||||
|
int dev_flash_image(struct device_info * dev, struct image * image);
|
||||||
|
int dev_dump_image(struct device_info * dev, enum image_type image, const char * file);
|
||||||
|
int dev_check_badblocks(struct device_info * dev, const char * device);
|
||||||
|
|
||||||
|
int dev_boot_device(struct device_info * dev, const char * cmdline);
|
||||||
|
int dev_reboot_device(struct device_info * dev);
|
||||||
|
|
||||||
|
int dev_get_root_device(struct device_info * dev);
|
||||||
|
int dev_set_root_device(struct device_info * dev, int device);
|
||||||
|
|
||||||
|
int dev_get_usb_host_mode(struct device_info * dev);
|
||||||
|
int dev_set_usb_host_mode(struct device_info * dev, int enable);
|
||||||
|
|
||||||
|
int dev_get_rd_mode(struct device_info * dev);
|
||||||
|
int dev_set_rd_mode(struct device_info * dev, int enable);
|
||||||
|
|
||||||
|
int dev_get_rd_flags(struct device_info * dev, char * flags, size_t size);
|
||||||
|
int dev_set_rd_flags(struct device_info * dev, const char * flags);
|
||||||
|
|
||||||
|
int16_t dev_get_hwrev(struct device_info * dev);
|
||||||
|
int dev_set_hwrev(struct device_info * dev, int16_t hwrev);
|
||||||
|
|
||||||
|
int dev_get_kernel_ver(struct device_info * dev, char * ver, size_t size);
|
||||||
|
int dev_set_kernel_ver(struct device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int dev_get_initfs_ver(struct device_info * dev, char * ver, size_t size);
|
||||||
|
int dev_set_initfs_ver(struct device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int dev_get_nolo_ver(struct device_info * dev, char * ver, size_t size);
|
||||||
|
int dev_set_nolo_ver(struct device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int dev_get_sw_ver(struct device_info * dev, char * ver, size_t size);
|
||||||
|
int dev_set_sw_ver(struct device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
int dev_get_content_ver(struct device_info * dev, char * ver, size_t size);
|
||||||
|
int dev_set_content_ver(struct device_info * dev, const char * ver);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007
|
|
||||||
* pancake <pancake@youterm.com>
|
|
||||||
*
|
|
||||||
* 0xFFFF 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.
|
|
||||||
*
|
|
||||||
* 0xFFFF 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 0xFFFF; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
int pcs_n = 0;
|
|
||||||
struct piece_t pcs[10];
|
|
||||||
|
|
||||||
int add_piece(char *piece)
|
|
||||||
{
|
|
||||||
int i,ok = 0;
|
|
||||||
char *file;
|
|
||||||
|
|
||||||
if (pcs_n==9) {
|
|
||||||
fprintf(stderr, "Oops...cannot add more pieces. no sense operation!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
file = strchr(piece, '%');
|
|
||||||
if (file) {
|
|
||||||
file[0]='\0';
|
|
||||||
file = file + 1;
|
|
||||||
for(i=0;pieces[i];i++)
|
|
||||||
if (!strcmp(pieces[i], piece))
|
|
||||||
ok = 1;
|
|
||||||
if (!ok) {
|
|
||||||
printf("Invalid piece name.\n");
|
|
||||||
printf("Pieces: ");
|
|
||||||
for(i=0;pieces[i];i++)
|
|
||||||
printf("%s ", pieces[i]);
|
|
||||||
printf("\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pcs[pcs_n].name = strdup(file);
|
|
||||||
pcs[pcs_n].type = strdup(piece);
|
|
||||||
pcs[pcs_n].vers = NULL; // TODO version string not yet supported
|
|
||||||
} else {
|
|
||||||
/*/ autodetect piece type */
|
|
||||||
pcs[pcs_n].type = fpid_file(piece);
|
|
||||||
if (pcs[pcs_n].type == NULL) {
|
|
||||||
printf("Use -p [piece]:[file]\n");
|
|
||||||
printf("Pieces: ");
|
|
||||||
for(i=0;pieces[i];i++)
|
|
||||||
printf("%s ", pieces[i]);
|
|
||||||
printf("\n");
|
|
||||||
exit(1);
|
|
||||||
} else {
|
|
||||||
pcs[pcs_n].name = strdup(piece);
|
|
||||||
pcs[pcs_n].type = strdup(pcs[pcs_n].type);
|
|
||||||
pcs[pcs_n].vers = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pcs_n++;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* 0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
* Copyright (C) 2007 pancake <pancake@youterm.com>
|
||||||
|
* Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
#include "printf-utils.h"
|
||||||
|
|
||||||
|
int printf_prev = 0;
|
||||||
|
|
||||||
|
void printf_progressbar(unsigned long long part, unsigned long long total) {
|
||||||
|
|
||||||
|
char *columns = getenv("COLUMNS");
|
||||||
|
int pc;
|
||||||
|
int tmp, cols = 80;
|
||||||
|
|
||||||
|
/* percentage calculation */
|
||||||
|
pc = (int)(part*100/total);
|
||||||
|
(pc<0)?pc=0:(pc>100)?pc=100:0;
|
||||||
|
|
||||||
|
PRINTF_BACK();
|
||||||
|
PRINTF_ADD("\x1b[K %3d%% [", pc);
|
||||||
|
if (columns)
|
||||||
|
cols = atoi(columns);
|
||||||
|
if (cols > 115)
|
||||||
|
cols = 115;
|
||||||
|
cols-=15;
|
||||||
|
for(tmp=cols*pc/100;tmp;tmp--) PRINTF_ADD("#");
|
||||||
|
for(tmp=cols-(cols*pc/100);tmp;tmp--) PRINTF_ADD("-");
|
||||||
|
PRINTF_ADD("]");
|
||||||
|
if (part == total) PRINTF_END();
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void printf_and_wait(const char * format, ...) {
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
char c;
|
||||||
|
fd_set rfds;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(0, &rfds);
|
||||||
|
|
||||||
|
while ( select(1, &rfds, NULL, NULL, &tv) == 1 )
|
||||||
|
if ( read(0, &c, 1) < 0 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vprintf(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(0, &rfds);
|
||||||
|
|
||||||
|
while ( select(1, &rfds, NULL, NULL, NULL) == 1 ) {
|
||||||
|
if ( read(0, &c, 1) < 0 || c == '\n' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
* Copyright (C) 2007 pancake <pancake@youterm.com>
|
||||||
|
* Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
*
|
||||||
|
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PRINTF_UTILS_H
|
||||||
|
#define PRINTF_UTILS_H
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
extern int printf_prev;
|
||||||
|
|
||||||
|
#define PRINTF_BACK() do { if ( printf_prev ) { printf("\r%-*s\r", printf_prev, ""); printf_prev = 0; } } while (0)
|
||||||
|
#define PRINTF_ADD(...) do { printf_prev += printf(__VA_ARGS__); } while (0)
|
||||||
|
#define PRINTF_LINE(...) do { PRINTF_BACK(); PRINTF_ADD(__VA_ARGS__); fflush(stdout); } while (0)
|
||||||
|
#define PRINTF_END() do { if ( printf_prev ) { printf("\n"); printf_prev = 0; } } while (0)
|
||||||
|
#define PRINTF_ERROR(...) do { PRINTF_END(); ERROR_INFO(__VA_ARGS__); } while (0)
|
||||||
|
#define PRINTF_ERROR_RETURN(str, ...) do { PRINTF_ERROR("%s", str); return __VA_ARGS__; } while (0)
|
||||||
|
|
||||||
|
void printf_progressbar(unsigned long long part, unsigned long long total);
|
||||||
|
void printf_and_wait(const char * format, ...);
|
||||||
|
|
||||||
|
#endif
|
||||||
-193
@@ -1,193 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007
|
|
||||||
* pancake <pancake@youterm.com>
|
|
||||||
*
|
|
||||||
* 0xFFFF 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.
|
|
||||||
*
|
|
||||||
* 0xFFFF 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 0xFFFF; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <usb.h>
|
|
||||||
|
|
||||||
/* wait for status = 0 */
|
|
||||||
int get_status()
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
if (usb_control_msg(dev, 192, 1, 0, 0, (char *)&ret, 4, 2000) == -1) {
|
|
||||||
fprintf(stderr, "Cannot get device status.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_peripheral_host_mode(int foo)
|
|
||||||
{
|
|
||||||
//unsigned short mode = 0;
|
|
||||||
|
|
||||||
// XXX BROKEN
|
|
||||||
#if 0
|
|
||||||
if (usb_control_msg(dev, 64, 16, 2, 0, 2, 0, 0, 2000)) {
|
|
||||||
fprintf(stderr, "Cannot query device.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Device is in \"%s\" mode (%hd)\n", (mode)?"host":"peripheral", mode);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* boot the omap mobo
|
|
||||||
*/
|
|
||||||
|
|
||||||
int boot_board(char *cmdline)
|
|
||||||
{
|
|
||||||
if (usb_control_msg(dev, CMD_WRITE, 130, 0, 0, cmdline, strlen(cmdline), 2000) == -1) {
|
|
||||||
fprintf(stderr, "Cannot boot kernel.\n");
|
|
||||||
perror("boot_board");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Booting kernel with arguments: '%s'.\n", cmdline);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* reboot the omap mobo
|
|
||||||
*/
|
|
||||||
int reboot_board()
|
|
||||||
{
|
|
||||||
// 131 = reboot
|
|
||||||
if (usb_control_msg(dev, CMD_WRITE, 131, 0, 0, 0, 0, 2000) == -1) {
|
|
||||||
fprintf(stderr, "Cannot reboot board.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Mobo rebooted!\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int set_rd_mode(unsigned short mode)
|
|
||||||
{
|
|
||||||
if (((short)mode)==-1)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (usb_control_msg(dev, CMD_WRITE, 16, mode, 0, 0, 0, 2000) == -1) {
|
|
||||||
fprintf(stderr, "Cannot set R&D flags.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("rd mode changed to %s\n", mode?"on":"off");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mode = 1 || 0
|
|
||||||
int set_usb_host_mode(unsigned short mode)
|
|
||||||
{
|
|
||||||
if (usb_control_msg(dev, CMD_WRITE, 16, mode, 2, 0, 0, 2000) == -1) {
|
|
||||||
fprintf(stderr, "Cannot change the usb-host mode.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("USB host mode is %s.\n", mode?"enabled":"disabled");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* query root device
|
|
||||||
*/
|
|
||||||
int query_hw_revision()
|
|
||||||
{
|
|
||||||
unsigned char string[512];
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
if (usb_control_msg(dev, CMD_QUERY, 4, 0, 0, (char *)string, 512, 2000) == -1) {
|
|
||||||
fprintf(stderr, "Cannot query hw revision.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("HW revision string: '");
|
|
||||||
for(i=0;i<44;i++) { // XXX ??
|
|
||||||
if (string[i]==0) {
|
|
||||||
printf(" ");
|
|
||||||
} else {
|
|
||||||
if (string[i]>19)
|
|
||||||
printf("%c", string[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("'\n");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int query_rdmode_device()
|
|
||||||
{
|
|
||||||
char isrd = 1;
|
|
||||||
|
|
||||||
if (usb_control_msg(dev, CMD_QUERY, 17, 0, 0, (char *)&isrd, 1, 2000) == -1) {
|
|
||||||
fprintf(stderr, "Cannot query rd mode.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
printf("RD mode is: %s\n", isrd?"on":"off");
|
|
||||||
|
|
||||||
return isrd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int query_root_device()
|
|
||||||
{
|
|
||||||
unsigned char opcode;
|
|
||||||
|
|
||||||
if (usb_control_msg(dev, 192, 17, 0, 1, (char *)&opcode, 1, 2000) < 0) {
|
|
||||||
fprintf(stderr, "Cannot query root device\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opcode>2) { // use sizeof || enum
|
|
||||||
printf("Invalid root device received from the device '%d'.\n", opcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Root device is: %s\n", root_devices[opcode]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int query_nolo_version()
|
|
||||||
{
|
|
||||||
unsigned int version; // ensure uint is at least 32 bits
|
|
||||||
|
|
||||||
//if (usb_control_msg(dev, 192, 3, 0, 1, (char *)&version, 4 , 2000) < 0) {
|
|
||||||
if (usb_control_msg(dev, 192, 3, 0, 0, (char *)&version, 4 , 2000) < 0) {
|
|
||||||
fprintf(stderr, "Cannot query nolo version. Old bootloader version?\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("NOLO Version %d.%d.%d\n",
|
|
||||||
version >> 20 & 15,
|
|
||||||
version >> 16 & 15,
|
|
||||||
version >> 8 & 255);
|
|
||||||
|
|
||||||
if ((version & 255)> 1)
|
|
||||||
printf("Invalid API version (%d)\n", version&255);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include <usb.h>
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
#include "device.h"
|
||||||
|
#include "usb-device.h"
|
||||||
|
#include "printf-utils.h"
|
||||||
|
#include "nolo.h"
|
||||||
|
#include "cold-flash.h"
|
||||||
|
#include "mkii.h"
|
||||||
|
|
||||||
|
static struct usb_flash_device usb_devices[] = {
|
||||||
|
{ 0x0421, 0x0105, 2, 1, -1, FLASH_NOLO, { DEVICE_SU_18, DEVICE_RX_44, DEVICE_RX_48, DEVICE_RX_51, 0 } },
|
||||||
|
{ 0x0421, 0x0106, 0, -1, -1, FLASH_COLD, { DEVICE_RX_51, 0 } },
|
||||||
|
/* { 0x0421, 0x01c7, 0, -1, -1, FLASH_DISK, { DEVICE_RX_51, 0 } }, */
|
||||||
|
/* { 0x0421, 0x01c8, 1, 1, -1, FLASH_MKII, { DEVICE_RX_51, 0 } }, */
|
||||||
|
/* { 0x0421, 0x0431, 0, -1, -1, FLASH_DISK, { DEVICE_SU_18, DEVICE_RX_34, 0 } }, */
|
||||||
|
{ 0x0421, 0x3f00, 2, 1, -1, FLASH_NOLO, { DEVICE_RX_34, 0 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * usb_flash_protocols[] = {
|
||||||
|
[FLASH_NOLO] = "NOLO",
|
||||||
|
[FLASH_COLD] = "Cold flashing",
|
||||||
|
/* [FLASH_MKII] = "Mk II protocol", */
|
||||||
|
/* [FLASH_DISK] = "RAW disk", */
|
||||||
|
};
|
||||||
|
|
||||||
|
const char * usb_flash_protocol_to_string(enum usb_flash_protocol protocol) {
|
||||||
|
|
||||||
|
if ( protocol >= sizeof(usb_flash_protocols)/sizeof(usb_flash_protocols[0]) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return usb_flash_protocols[protocol];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usb_flash_device_info_print(const struct usb_flash_device * dev) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
PRINTF_ADD("USB device: %s", device_to_string(dev->devices[0]));
|
||||||
|
|
||||||
|
for ( i = 1; dev->devices[i]; ++i )
|
||||||
|
PRINTF_ADD("/%s", device_to_string(dev->devices[i]));
|
||||||
|
|
||||||
|
PRINTF_ADD(" (%#04x:%#04x) in %s mode", dev->vendor, dev->product, usb_flash_protocol_to_string(dev->protocol));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usb_descriptor_info_print(usb_dev_handle * udev, struct usb_device * dev, char * product, size_t size) {
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
char buf2[1024];
|
||||||
|
unsigned int x;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
usb_get_string_simple(udev, dev->descriptor.iProduct, buf, sizeof(buf));
|
||||||
|
PRINTF_LINE("USB device product string: %s", buf[0] ? buf : "(not detected)");
|
||||||
|
PRINTF_END();
|
||||||
|
|
||||||
|
if ( product && buf[0] )
|
||||||
|
strncpy(product, buf, size);
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
memset(buf2, 0, sizeof(buf2));
|
||||||
|
ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, buf, sizeof(buf));
|
||||||
|
if ( ! isalnum(buf[0]) )
|
||||||
|
buf[0] = 0;
|
||||||
|
for ( i = 0; i < ret; i+=2 ) {
|
||||||
|
sscanf(buf+i, "%2x", &x);
|
||||||
|
if ( x > 32 && x < 128 )
|
||||||
|
buf2[i/2] = x;
|
||||||
|
else {
|
||||||
|
buf2[0] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ! isalnum(buf2[0]) )
|
||||||
|
buf2[0] = 0;
|
||||||
|
PRINTF_LINE("USB device serial number string: %s", buf2[0] ? buf2 : ( buf[0] ? buf : "(not detected)" ));
|
||||||
|
PRINTF_END();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
char product[1024];
|
||||||
|
struct usb_device_info * ret = NULL;
|
||||||
|
|
||||||
|
for ( i = 0; usb_devices[i].vendor; ++i ) {
|
||||||
|
|
||||||
|
if ( dev->descriptor.idVendor == usb_devices[i].vendor && dev->descriptor.idProduct == usb_devices[i].product ) {
|
||||||
|
|
||||||
|
printf("\b\b ");
|
||||||
|
PRINTF_END();
|
||||||
|
PRINTF_ADD("Found ");
|
||||||
|
usb_flash_device_info_print(&usb_devices[i]);
|
||||||
|
PRINTF_END();
|
||||||
|
|
||||||
|
PRINTF_LINE("Opening USB...");
|
||||||
|
usb_dev_handle * udev = usb_open(dev);
|
||||||
|
if ( ! udev ) {
|
||||||
|
PRINTF_ERROR("usb_open failed");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_descriptor_info_print(udev, dev, product, sizeof(product));
|
||||||
|
|
||||||
|
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
|
||||||
|
PRINTF_LINE("Detaching kernel from USB interface...");
|
||||||
|
usb_detach_kernel_driver_np(udev, usb_devices[i].interface);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PRINTF_LINE("Claiming USB interface...");
|
||||||
|
if ( usb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
|
||||||
|
PRINTF_ERROR("usb_claim_interface failed");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
usb_close(udev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( usb_devices[i].alternate >= 0 ) {
|
||||||
|
PRINTF_LINE("Setting alternate USB interface...");
|
||||||
|
if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
|
||||||
|
PRINTF_ERROR("usb_claim_interface failed");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
usb_close(udev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( usb_devices[i].configuration >= 0 ) {
|
||||||
|
PRINTF_LINE("Setting USB configuration...");
|
||||||
|
if ( usb_set_configuration(udev, usb_devices[i].configuration) < 0 ) {
|
||||||
|
PRINTF_ERROR("usb_set_configuration failed");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
usb_close(udev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = calloc(1, sizeof(struct usb_device_info));
|
||||||
|
if ( ! ret ) {
|
||||||
|
ALLOC_ERROR();
|
||||||
|
usb_close(udev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( strstr(product, "N900") )
|
||||||
|
ret->device = DEVICE_RX_51;
|
||||||
|
else
|
||||||
|
ret->device = DEVICE_UNKNOWN;
|
||||||
|
|
||||||
|
/* TODO: Autodetect more devices */
|
||||||
|
|
||||||
|
if ( device_to_string(ret->device) )
|
||||||
|
PRINTF_LINE("Detected USB device: %s", device_to_string(ret->device));
|
||||||
|
else
|
||||||
|
PRINTF_LINE("Detected USB device: (not detected)");
|
||||||
|
PRINTF_END();
|
||||||
|
|
||||||
|
if ( ret->device ) {
|
||||||
|
enum device * device;
|
||||||
|
for ( device = usb_devices[i].devices; *device; ++device )
|
||||||
|
if ( *device == ret->device )
|
||||||
|
break;
|
||||||
|
if ( ! *device ) {
|
||||||
|
ERROR("Device mishmash");
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
usb_close(udev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->hwrev = -1;
|
||||||
|
ret->flash_device = &usb_devices[i];
|
||||||
|
ret->udev = udev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_device_info * usb_search_device(struct usb_device * dev, int level) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
struct usb_device_info * ret = NULL;
|
||||||
|
|
||||||
|
if ( ! dev )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = usb_device_is_valid(dev);
|
||||||
|
if ( ret )
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for ( i = 0; i < dev->num_children; i++ ) {
|
||||||
|
ret = usb_search_device(dev->children[i], level + 1);
|
||||||
|
if ( ret )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static volatile sig_atomic_t signal_quit;
|
||||||
|
|
||||||
|
static void signal_handler(int signum) {
|
||||||
|
|
||||||
|
signal_quit = 1;
|
||||||
|
(void)signum;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usb_device_info * usb_open_and_wait_for_device(void) {
|
||||||
|
|
||||||
|
struct usb_bus * bus;
|
||||||
|
struct usb_device_info * ret = NULL;
|
||||||
|
int i = 0;
|
||||||
|
void (*prev)(int);
|
||||||
|
static char progress[] = {'/','-','\\', '|'};
|
||||||
|
|
||||||
|
usb_init();
|
||||||
|
usb_find_busses();
|
||||||
|
|
||||||
|
PRINTF_BACK();
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
signal_quit = 0;
|
||||||
|
|
||||||
|
prev = signal(SIGINT, signal_handler);
|
||||||
|
|
||||||
|
while ( ! signal_quit ) {
|
||||||
|
|
||||||
|
PRINTF_LINE("Waiting for USB device... %c", progress[++i%sizeof(progress)]);
|
||||||
|
|
||||||
|
usb_find_devices();
|
||||||
|
|
||||||
|
for ( bus = usb_get_busses(); bus; bus = bus->next ) {
|
||||||
|
|
||||||
|
if ( bus->root_dev )
|
||||||
|
ret = usb_search_device(bus->root_dev, 0);
|
||||||
|
else {
|
||||||
|
struct usb_device *dev;
|
||||||
|
for ( dev = bus->devices; dev; dev = dev->next ) {
|
||||||
|
ret = usb_search_device(dev, 0);
|
||||||
|
if ( ret )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ret )
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ret )
|
||||||
|
break;
|
||||||
|
|
||||||
|
usleep(0xc350); // 0.5s
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( prev != SIG_ERR )
|
||||||
|
signal(SIGINT, prev);
|
||||||
|
|
||||||
|
PRINTF_BACK();
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if ( ! ret )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_close_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
usb_close(dev->udev);
|
||||||
|
free(dev);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_switch_to_nolo(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
printf("\nSwitching to NOLO mode...\n");
|
||||||
|
|
||||||
|
if ( dev->flash_device->protocol == FLASH_COLD )
|
||||||
|
leave_cold_flash(dev);
|
||||||
|
else if ( dev->flash_device->protocol == FLASH_MKII )
|
||||||
|
mkii_reboot_device(dev);
|
||||||
|
else if ( dev->flash_device->protocol == FLASH_DISK )
|
||||||
|
printf_and_wait("Unplug USB cable, turn device off, press ENTER and plug USB cable again");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_switch_to_cold(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
printf("\nSwitching to Cold Flash mode...\n");
|
||||||
|
|
||||||
|
if ( dev->flash_device->protocol == FLASH_NOLO )
|
||||||
|
nolo_reboot_device(dev);
|
||||||
|
else if ( dev->flash_device->protocol == FLASH_MKII )
|
||||||
|
mkii_reboot_device(dev);
|
||||||
|
else if ( dev->flash_device->protocol == FLASH_DISK )
|
||||||
|
printf_and_wait("Unplug USB cable, turn device off, press ENTER and plug USB cable again");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_switch_to_mkii(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
printf("\nSwitching to Update mode...\n");
|
||||||
|
|
||||||
|
if ( dev->flash_device->protocol == FLASH_COLD )
|
||||||
|
leave_cold_flash(dev);
|
||||||
|
else if ( dev->flash_device->protocol == FLASH_NOLO )
|
||||||
|
nolo_boot_device(dev, "update");
|
||||||
|
else if ( dev->flash_device->protocol == FLASH_DISK )
|
||||||
|
printf_and_wait("Unplug USB cable, turn device off, press ENTER and plug USB cable again");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_switch_to_disk(struct usb_device_info * dev) {
|
||||||
|
|
||||||
|
printf("\nSwitching to RAW disk mode...\n");
|
||||||
|
|
||||||
|
if ( dev->flash_device->protocol == FLASH_COLD )
|
||||||
|
leave_cold_flash(dev);
|
||||||
|
else if ( dev->flash_device->protocol == FLASH_NOLO ) {
|
||||||
|
nolo_boot_device(dev, NULL);
|
||||||
|
printf_and_wait("Wait until device start, choose USB Mass Storage Mode and press ENTER");
|
||||||
|
} else if ( dev->flash_device->protocol == FLASH_MKII )
|
||||||
|
mkii_reboot_device(dev);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
||||||
|
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef USB_DEVICE_H
|
||||||
|
#define USB_DEVICE_H
|
||||||
|
|
||||||
|
#include <usb.h>
|
||||||
|
|
||||||
|
#include "device.h"
|
||||||
|
|
||||||
|
enum usb_flash_protocol {
|
||||||
|
FLASH_UNKN = 0,
|
||||||
|
FLASH_NOLO,
|
||||||
|
FLASH_COLD,
|
||||||
|
FLASH_MKII,
|
||||||
|
FLASH_DISK,
|
||||||
|
FLASH_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usb_flash_device {
|
||||||
|
uint16_t vendor;
|
||||||
|
uint16_t product;
|
||||||
|
int interface;
|
||||||
|
int alternate;
|
||||||
|
int configuration;
|
||||||
|
enum usb_flash_protocol protocol;
|
||||||
|
enum device devices[DEVICE_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usb_device_info {
|
||||||
|
enum device device;
|
||||||
|
int16_t hwrev;
|
||||||
|
const struct usb_flash_device * flash_device;
|
||||||
|
usb_dev_handle * udev;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char * usb_flash_protocol_to_string(enum usb_flash_protocol protocol);
|
||||||
|
struct usb_device_info * usb_open_and_wait_for_device(void);
|
||||||
|
void usb_close_device(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
void usb_switch_to_nolo(struct usb_device_info * dev);
|
||||||
|
void usb_switch_to_cold(struct usb_device_info * dev);
|
||||||
|
void usb_switch_to_mkii(struct usb_device_info * dev);
|
||||||
|
void usb_switch_to_disk(struct usb_device_info * dev);
|
||||||
|
|
||||||
|
#endif
|
||||||
-57
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007
|
|
||||||
* pancake <pancake@youterm.com>
|
|
||||||
*
|
|
||||||
* 0xFFFF 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.
|
|
||||||
*
|
|
||||||
* 0xFFFF 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 0xFFFF; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include <usb.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
unsigned long get_file_size(char *file)
|
|
||||||
{
|
|
||||||
FILE *fd = fopen(file, "r");
|
|
||||||
unsigned long len = 0;
|
|
||||||
if (fd == NULL) {
|
|
||||||
fprintf(stderr, "Cannot open file '%s'\n", file);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
fseek(fd, 0, SEEK_END);
|
|
||||||
len = ftell(fd);
|
|
||||||
fclose(fd);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void progressbar(unsigned long long part, unsigned long long total)
|
|
||||||
{
|
|
||||||
char *columns = getenv("COLUMNS");
|
|
||||||
int pc;
|
|
||||||
int tmp, cols = 80;
|
|
||||||
|
|
||||||
pc = (int)(part*100/total);
|
|
||||||
(pc<0)?pc=0:(pc>100)?pc=100:0;
|
|
||||||
printf("\e[K %3d%% [", pc);
|
|
||||||
if (columns)
|
|
||||||
cols = atoi(columns);
|
|
||||||
cols-=15;
|
|
||||||
for(tmp=cols*pc/100;tmp;tmp--) printf("#");
|
|
||||||
for(tmp=cols-(cols*pc/100);tmp;tmp--) printf("-");
|
|
||||||
printf("]\r");
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user