Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c88d802aa3 | ||
|
|
1f01a8330b | ||
|
|
48c6be2d65 | ||
|
|
71e0eb87ea | ||
|
|
04f94d957a | ||
|
|
7d07f81ec6 | ||
|
|
55bed7e8cd | ||
|
|
e6ac56569c |
No files matched your search
+2
-7
@@ -2,10 +2,6 @@ sudo: false
|
||||
|
||||
language: c
|
||||
|
||||
arch:
|
||||
- AMD64
|
||||
- ppc64le
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
@@ -13,15 +9,14 @@ compiler:
|
||||
addons: &addons
|
||||
apt:
|
||||
packages:
|
||||
- libusb-1.0-0-dev
|
||||
- pkg-config
|
||||
- libusb-dev
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
if: (branch = master) AND (type != pull_request)
|
||||
env:
|
||||
- secure: "f+qBVyDcDe/9IUmWcqlhL81s4QdY/eHeJW81Zfkfulu0Iai20Ro/lnj0PxVHeSo12cldUTG0XhY1GURYLe2RNdtB2ooe3d9JGn9uFrkyDNhmHcOuJQKY/g2XQ0gJQ9tpWkZhSzENl2C9H/uz87oGqSqwlCLdwixekk8vrmH5kpnNXtbgfK3EKWbhGN0Zub70+qeLa7jTShMN3HgJbrkDYgxUPMofqOCHp8W1xPIvUjNS4yQtN/Ahl6g7z79xopgCvGI91ZkAigSHJGBeHoq3rxG+ecoK+AprhiXuIZ8tD8bHv5IpKEi6mFGf4Fo0mQw+1b8g0HLBwWoiR5Yz7fv6fRgDhuK2AqZZmK8J6q13Lxl/DZS93hTeSJPk9FBEvJsPRwDUgy0P6HObmmEnmclERd9aqcK4RxrQkTjWK+rhHtoRg1kB2QiLz0dNpXQ/CTImv5jooYibo2TCyH6nBcEKzIxSQABvorEwpn7rx7UqL+rFqCQgLrqcRgCna615XpxpS+/W8VeScp2y1MzClwuudBaOiEAK5b6xa6HWk7RDQPkUAYmsnlFZ3zDbTiMzpKRYp/I2N6CPD50PX8lRJpxDSn6qL0HC0qCaYZqlKA+kKxl+OWbtUWM9mE9MJE3V8RRQO8g5p1mJ8NpjdOx7wwYk09BIp6YYPLXLj32hKn4kfXo="
|
||||
- secure: "JdUp+xFykPZoYA4aRfmYk2CtilLapniQllWPKo2dDdJd1vzdawfTvVxIAKjy7ac9RKwZzg3Chq3RsMEXPv8BtaLbssw266C7RDLMgjacl1eFLcmGRj/Gkk9peDSZ6vVdGEcA2j+6KDSfpCa/XjFjvOufZOgKw6m+3+d0A4G45SI="
|
||||
addons:
|
||||
<<: *addons
|
||||
coverity_scan:
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
Installation instructions:
|
||||
==========================
|
||||
|
||||
To build the flasher you will need gcc, make and libusb-1.0 (version 1.0.16
|
||||
or newer). Compiler and linker flags for libusb-1.0 are detected by pkg-config;
|
||||
without it set LIBUSB_CFLAGS and LIBUSB_LIBS manually (see config.mk), e.g.:
|
||||
|
||||
$ make LIBUSB_CFLAGS=-I/opt/homebrew/opt/libusb/include/libusb-1.0 \
|
||||
LIBUSB_LIBS="-L/opt/homebrew/opt/libusb/lib -lusb-1.0"
|
||||
|
||||
For crosscompiling to arm you can use scratchbox. But you will probably need
|
||||
the libusb-1.0.so of the scratchbox environment to the device.
|
||||
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:
|
||||
|
||||
|
||||
@@ -10,24 +10,24 @@
|
||||
_/ ___|_.|__|
|
||||
'`
|
||||
|
||||
0xFFFF is the Open Free Fiasco Firmware Flasher for Maemo devices. It supports
|
||||
generating and unpacking FIASCO images. It is useful for editing Maemo firmware
|
||||
packages before flashing. It supports flashing via USB any image type to a
|
||||
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 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 an alternative tool to proprietary Nokia flasher-3.5 and fiasco-gen.
|
||||
0xFFFF generates compatible FIASCO images and also accepts FIASCO images
|
||||
generated by Nokia fiasco-gen.
|
||||
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.
|
||||
It's not supposed to be stable, so Nokia will probably release incompatible
|
||||
It's not supposed to be stable, so nokia will probably release incompatible
|
||||
bootloaders to break this tool. USE IT AT YOUR OWN RISK.
|
||||
|
||||
PLEASE. Read all the documentation inside doc/* carefully before building or
|
||||
using the flasher to avoid questions, problems or so.
|
||||
PLEASE. Read carefully all the documentation inside doc/* for more information
|
||||
before building or using the flasher to avoid questions, problems or so.
|
||||
|
||||
https://github.com/pali/0xFFFF
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ cold-flash:
|
||||
* Detect device from asic id
|
||||
|
||||
disk:
|
||||
* Support for flashing mmc images
|
||||
* Badblock checking
|
||||
|
||||
fiasco:
|
||||
@@ -14,6 +15,7 @@ image:
|
||||
* Support for Harmattan images
|
||||
|
||||
local:
|
||||
* Support for flashing (on device)
|
||||
* Write versions
|
||||
* Badblock checking
|
||||
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
VERSION = 0.10
|
||||
VERSION = 0.8
|
||||
PREFIX = /usr/local
|
||||
|
||||
# NetBSD stuff
|
||||
#CPPFLAGS += -I/usr/pkg/include
|
||||
#LDFLAGS += -L/usr/pkg/lib -Wl,-R/usr/pkg/lib
|
||||
|
||||
# libusb-1.0 flags are detected by pkg-config, set them manually without it
|
||||
# (e.g. macOS with Homebrew libusb on Apple Silicon)
|
||||
#LIBUSB_CFLAGS = -I/opt/homebrew/opt/libusb/include/libusb-1.0
|
||||
#LIBUSB_LIBS = -L/opt/homebrew/opt/libusb/lib -lusb-1.0
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
0xffff (0.8-1) fremantle; urgency=low
|
||||
|
||||
* New upstream version
|
||||
|
||||
-- Pali Rohár <pali.rohar@gmail.com> Sun, 08 Jul 2018 12:43:42 +0200
|
||||
|
||||
0xffff (0.7-1) fremantle; urgency=low
|
||||
|
||||
* New upstream version
|
||||
|
||||
-- Pali Rohár <pali.rohar@gmail.com> Sun, 25 Dec 2016 11:47:44 +0100
|
||||
|
||||
0xffff (0.6.1-1) experimental; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
- Contains a few security related fixes (memory corruptions & leaks)
|
||||
- Support for -t (filter by type) for -e (dump images)
|
||||
- reattach kernel driver
|
||||
- minor fixes
|
||||
|
||||
-- Sebastian Reichel <sre@debian.org> Thu, 11 Dec 2014 21:52:53 +0100
|
||||
|
||||
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
+89
@@ -0,0 +1,89 @@
|
||||
Source: 0xffff
|
||||
Section: user/system
|
||||
Priority: extra
|
||||
Maintainer: Pali Rohár <pali.rohar@gmail.com>
|
||||
Standards-Version: 3.9.8
|
||||
Build-Depends: debhelper (>= 7),
|
||||
libusb-dev
|
||||
Homepage: https://github.com/pali/0xFFFF
|
||||
Vcs-Git: https://github.com/pali/0xFFFF.git
|
||||
Vcs-Browser: https://github.com/pali/0xFFFF/tree/maemo
|
||||
|
||||
Package: 0xffff
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}, mtd-utils
|
||||
Description: Open Free Fiasco Firmware Flasher
|
||||
The ‘Open Free Fiasco Firmware Flasher’ aka 0xFFFF utility implements
|
||||
a free userspace handler for the NOLO bootloader and extended features
|
||||
for flashing, dumping and getting information for the Nokia Internet
|
||||
Tablets. Thus it's a free alternative to Nokia's closed source flashing
|
||||
utility called flasher.
|
||||
.
|
||||
Supported operations currently include, but are not limited to:
|
||||
* generating and unpacking FIASCO images on local device
|
||||
* editing Maemo firmware packages
|
||||
* flashing any kind image type to Maemo devices via USB
|
||||
* "cold" flashing for devices with bricked bootloaders
|
||||
* direct kernel boot without flashing it to NAND
|
||||
* changing configuration of Maemo device (R&D flags, HW revision strings, ...)
|
||||
.
|
||||
Supported are the Nokia 770, N800, N810, N810w, N900, N950 and N9.
|
||||
XSBC-Maemo-Display-Name: 0xFFFF
|
||||
XB-Maemo-Icon-26:
|
||||
iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAGXRFWHRTb2Z0
|
||||
d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACYtJREFUeNrUWkurZUcVXvXY
|
||||
59zbtyXpICEiaFrJQFDo6CDOHAi2UQdOFBw4CAqCDhU0DuIPEBtCRupIBxk4
|
||||
MBMHgpIMnChE1OAD2uADEkFpUM9z710vv7Wq6ty6u09f0+nb3Tcb6u7Hqb33
|
||||
96361qq1al/1vscfp+Ac3fjH6+S9v3owP/iYMfqyMaabz2ax62wwtnPDOPgY
|
||||
ok8pxpQoKKW9UhRC8IFI+UQ4ds7HFKLW1mujffDexRi9MXiGMQG34uborbEO
|
||||
515pckopZ7RxuN8RyflgtBrxfKeNGlNMY0ppxItGUnowSm3Rr7ezubfdnCwe
|
||||
SuMw2EsPPvi9x957+SlrNAXvCCTIWkMKvQP6JEYdorQoG6gkUIpo+SgkStyV
|
||||
SQb0RwOolACOQdBIlAaQ7XGtT4q2lGhDDCjRGsZYg8Qa71sR75WSPe5Z411o
|
||||
doPfN1rrDs/q8MaVVt5Z5T1dnM++8sEPXHnqXzduxOuv/iVutlsGKeCxJbyE
|
||||
jxN2uJc3FfkcJzHviBlG5sq/kUq8D4qvyzWKpQ/fzn94H/Mzub88L0hfJc/w
|
||||
OPc8Ijh3is8xUhqIMZr+woULscMwRmjCwoDdY+959xcXiwX9/KVfRAyV0gYD
|
||||
xTBVeY2mjJuvAR3+aMrgjPRQKtVzrRSDwE1Kl1uEuBADKCX34g5VzKLk/ihk
|
||||
lQBl8CKt3IQA5MMEICttPIY5XDw6glSVspv15tGLRxcu/+rl3/D4q9lsJtjl
|
||||
1WyTA7TxBKRYfjZEO2IMTufRosxdVcoCPvEIQTaBrYlLjuWFH0Z0Y433LC3Y
|
||||
occ5a3ybz7EvmjdaD9IfvudG57d6G4E12fmse+d6tT76z38XcC6TwcOdEtvj
|
||||
EGL7jif/fU3x1yaDmWejNuCpEI4ilZT3AFPAwifgA9gPuGMIFAESfqDUBpw2
|
||||
inWuVNY+6z4l7NkX1ApWgI/QlvuD/qDZoWMEeRskaODBlmJ4oB9HGoYxycCy
|
||||
1R9OavYtT92nweIRotnn4ZkvBhqfRvc/oM8MUJIQqC00zeemWL/FutRnq8Jp
|
||||
uam0BtA1yC5x8xLHS7xa9sREEjsy+ogTg4CiASQGpZVDjBMJcTDEEajEeDSM
|
||||
DjxCHm/s5s96mn0W0ekF3PZ2eSR1n0qk3+/U5koXaQU9G6q6nwCXcMgWF/CF
|
||||
QAVfQHGESSsmQHTcUiYi0QfH6K8YfF8iGEASnBjagPGgp4SoTdra7tAhEnFc
|
||||
ZIdVhxD3h3GI1/afgcV/B/pfsnG4plP8pU7q0s76twTPsbyAL3quwKUJUIBa
|
||||
4HiBvrLHNd6DFI9MqpbvAWsANifPR2iGUnA6JDiwRAcLz547FwQThihxpE5/
|
||||
Bol3YSS+G0g/iuuPQLxftUHEb9HRngDvmv0O/EQ2FfyqtTg3oBGrcyvgNzje
|
||||
8nMYKT8XGANvmGhzGG68DzIKc4fJNAmDHC+Gr1kKf1Q0/0Kk7qOJDl/y+vAn
|
||||
mDyfwOj5E1av4MVJG/CnAW8tn7XfWL6A7xvwwO134GmycUye8+y6+9FCG7/V
|
||||
kbW+eRJzxcsYlb+q1H0yqQs/852+Ehm2b2QzNpavkmkJTMHv9F4IrCqBBvzY
|
||||
gOe5aS94IYDOMw7R0oH/HqRkPhJJfyiS+yl+/j3i2FXr+meQ+7wN/J5MWlKE
|
||||
4xFgy/eNbE61fNF7Bc9EBDzA7sDnWRfx3rlTwYu9Met2nNmIvj1m0YeSPXzR
|
||||
6fRPIHiii3LrDO49pzyNDSecdtij+XUhsdqneb7GwIvmN9wYPPb8nLHMwCyZ
|
||||
WHCdull0xghIHgPBk0l/V3H8tlHzrwd9dN1ZhmA/Hg/0OyD26xTdj2Eplo1T
|
||||
rNFW8xm8Bngrx8tCYNGCLwR2Dgvw/RQ8W/6NgBcCmH2ZgJd8RkmESeM3kW+8
|
||||
orS9GpX9RNTxFRXG57RzP9Tr9Lra6IcxIg8kg/s4XYXXgHqNSivI6QZAqx34
|
||||
VRvjJ5bvS7gdVc6Dbgt8HgEE1JRvyK2kYP55ONDzOsyv+QN3zazia5KbsIV6
|
||||
+zn/UPflcKmZiVPJg8i9oF8dv2H/pDqRUXXYKhukxVFi/EQ2bwq8EAB4Sfkl
|
||||
rc0kJLNRs2zR8Rm7gKs6nDN4KS7cD8xr/kf6b6mJOJK3ECzb078xV6xvBb5G
|
||||
GgbPDssZprxn5Een2wIvBJgxW6CkxabMEqk4aYBrSk7DecjOWVe0TQu1Po44
|
||||
kAVxZEFMZ+mYYwKtbJhkBY/mKni2fDoxPd0mAS73mqSspgmZgJYYz+YZdpGG
|
||||
HVW3sT6tbxE6V8XyN4Fnh71T8DmMah13TpzTYt0QqOBrmGzj/KbG8X2hskab
|
||||
Ap5lw5rnRGbkephLzjsFn30AD2IHypUThJJ9IRTnOmn5mg4XSxfwiwJ20ZCR
|
||||
jHKqebZ8BQ/Nx9MmqDdMQAoOPLg+rJRSgXaVEg3T3KZoejVNhat8JrKpSRk7
|
||||
rMxObPmzAL8jUPKZpgTMs+wey68ay7fpwLLR/qa1fMlr7gr4EwSK5WNOV2VE
|
||||
hgJ6O3HQ3ew6Ab8rRKrm26SMl18APp0l+ErAFZ2rov3YyGczyWv2WX65J5c/
|
||||
kVEiIYu3SofvmECxds/1sKQGx/l967DLKfg9hQjLpm9yeV/Ah7sFvh2BPvuv
|
||||
LJz4Rj7VYZdTy59SRY37qii6S5tNOaPcFgkxCY5KbMl1ydX3hsry+02yKRnl
|
||||
/y1Ezm4EkqzZMAj2Xl0WWLcFaAt+57CTdJjJD/cDfK0HhryEsdvGMiInnHYP
|
||||
+Dq79jU1aMBHukebLbPkuoTRVB24AbwsSx7rPYVIXzPKJh1OdA83Wxx4nYNQ
|
||||
DqGs7zJhtaFyva+KmoCPdI83duKq91iW0nn9vs0qV00hcqsSMNxry7cFzaaA
|
||||
5HqA1/T71KyiVctPqig3qV/vC/hcD2QJLWsWWvKfOgKbAn5qeV+qqPhmqqiz
|
||||
deJs8WVd6yyzabU6E7jJ8qUQSfcbfIlCPOuqKiH+gtKu72wby0sJWAqRcwH+
|
||||
mECCD+yqMLVbpGoKEUmHzxv4UlIalEZhjVosmKT5i2OtA1rLn2kVdbYE+IOS
|
||||
0uyknEp7HfUYVeQlQ65fRTZ3oxA5w2xUeaNpw18tEf99UFHWf/iLSLH8uQVf
|
||||
RyBARltrDaaEEPhbbI408jURmh/TeQWf10ZtF9iRu86mAAImSi4WeLklr5ad
|
||||
X/BCoOsMf/cdZ11HKJ/4HwdiMHyg0/2cYW8nG+X1IDefzxUI8P9ySP2KITj3
|
||||
4PMnpqT4ozZrP3bWxq7rUlmle0tsVv6xgWkg/Bg7IxPr/2K8Nbb/CTAAF12f
|
||||
5l7y6xMAAAAASUVORK5CYII=
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Source: https://github.com/pali/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+
|
||||
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.
|
||||
.
|
||||
On Debian systems, the complete text of the GPL-3 can be found in
|
||||
/usr/share/common-licenses/GPL-3.
|
||||
|
||||
Files: debian/*
|
||||
Copyright: Sebastian Reichel <sre@debian.org>
|
||||
License: ISC
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
doc/
|
||||
TODO
|
||||
README
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_install:
|
||||
dh_auto_install -- PREFIX=/usr
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
version=3
|
||||
|
||||
opts=filenamemangle=s/.+\/v?(\d\S+)\.tar\.gz/0xFFFF-$1\.tar\.gz/,pgpsigurlmangle=s/$/.asc/ \
|
||||
https://github.com/pali/0xFFFF/releases .*/0xffff_(\d\S+)\.orig\.tar\.gz
|
||||
+3
-2
@@ -30,10 +30,11 @@ Technical details:
|
||||
For dumping mtd partition is used tool nanddump. Here is example how to dump
|
||||
kernel image without padding to file zImage:
|
||||
|
||||
$ nanddump --omitoob -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2
|
||||
$ nanddump -o -b -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2
|
||||
|
||||
Params means:
|
||||
--omitoob - "Omit oob data"
|
||||
-o - "Omit oob data"
|
||||
-b - "Omit bad blocks"
|
||||
-s - "Start address"
|
||||
-l - "Length"
|
||||
-f - "Output file"
|
||||
|
||||
@@ -38,6 +38,3 @@ $ 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
|
||||
|
||||
Generate new FIASCO mmc image mmc_image.fiasco from layout file layout.txt and two partition files mydocs_fat32.bin (with name mydocs) and home.tar (without name) for device RX-51 with image version 1.0
|
||||
$ 0xFFFF -m RX-51:1.0:mmc:mydocs_fat32.bin@mydocs#home.tar%layout.txt -g mmc_image.fiasco
|
||||
+16
-66
@@ -38,74 +38,24 @@ IMAGE
|
||||
|
||||
1 byte = 0x54 -- signature
|
||||
1 byte -- number of subsection blocks
|
||||
block {
|
||||
1 byte -- type of subsection block
|
||||
0x2E - file data
|
||||
0x2F - partition info
|
||||
0x31 - version
|
||||
0x32 - device & hw revisions (size of device is 16, hw revision 8)
|
||||
0x33 - layout
|
||||
0x34 - image data part block (one block for one data part)
|
||||
1 byte -- length of subsection block
|
||||
N bytes -- subsection block data
|
||||
}
|
||||
1 byte -- checksum of subsection data without signature (0xFF - xorpair)
|
||||
N bytes -- image data
|
||||
|
||||
|
||||
FILE DATA BLOCK
|
||||
|
||||
1 byte -- asic index (always APE - 0x01)
|
||||
1 byte -- device type (always NAND - 0x01)
|
||||
1 byte -- device index (always 0x00)
|
||||
(start of data block)
|
||||
1 byte -- type of subsection block (data - always 0x2e)
|
||||
1 byte -- length of subsection block (data - always 25)
|
||||
3 bytes -- unknown (always 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 -- load address of image data (big endian, unused always zero)
|
||||
|
||||
|
||||
PARTITION INFO BLOCK
|
||||
|
||||
1 byte -- asic index (always APE - 0x01)
|
||||
1 byte -- device type (always NAND - 0x01)
|
||||
1 byte -- device index (always 0x00)
|
||||
4 bytes -- partition version (always 0x00 0x00 0x00 0x00)
|
||||
4 bytes -- spare (always 0xFF 0xFF 0xFF 0xFF)
|
||||
4 bytes -- number of partition blocks (big endian)
|
||||
4 bytes -- unknown (always 0x00 0x00 0x00 0x00)
|
||||
(end of data block)
|
||||
block {
|
||||
1 byte -- partition type (0x03 - kernel, 0x04 - initfs, 0x05 - rootfs)
|
||||
1 byte -- partition attribute (0x01 - read/write, 0x02 - read-only)
|
||||
4 bytes -- partition size (big endian, 0 - remaining space)
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
IMAGE DATA PART BLOCK
|
||||
|
||||
4 bytes -- unknown (always 0x00 0x00 0x00 0x00)
|
||||
4 bytes -- offset (big endian)
|
||||
4 bytes -- unknown (always 0x00 0x00 0x00 0x00)
|
||||
4 bytes -- size (big endian)
|
||||
N bytes -- partition name (prefix) in layout (may be omitted)
|
||||
|
||||
|
||||
LAYOUT DATA BLOCK
|
||||
|
||||
N bytes of text data, e.g.:
|
||||
|
||||
mmc {
|
||||
name = "internal";
|
||||
partition {
|
||||
fs_type = "vfat";
|
||||
prefix = "mydocs";
|
||||
no_create = true;
|
||||
}
|
||||
partition {
|
||||
size = 2048;
|
||||
fs_type = "ext3";
|
||||
prefix = "home";
|
||||
}
|
||||
partition {
|
||||
size = 768;
|
||||
fs_type = "swap";
|
||||
}
|
||||
}
|
||||
1 byte -- unknown (0x00 is accepted, maybe end of subsections?)
|
||||
N bytes -- image data
|
||||
+2
-6
@@ -9,13 +9,9 @@ CC ?= cc
|
||||
CROSS_CC ?= $(CROSS_COMPILE)$(CC)
|
||||
HOST_CC ?= $(HOST_COMPILE)$(CC)
|
||||
|
||||
PKG_CONFIG ?= pkg-config
|
||||
LIBUSB_CFLAGS ?= $(shell $(PKG_CONFIG) --cflags libusb-1.0 2>/dev/null)
|
||||
LIBUSB_LIBS ?= $(shell $(PKG_CONFIG) --libs libusb-1.0 2>/dev/null || echo -lusb-1.0)
|
||||
|
||||
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DBUILD_DATE="\"$(BUILD_DATE)\"" -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64
|
||||
CFLAGS += -W -Wall -O2 -pedantic -std=c99
|
||||
LIBS += $(LIBUSB_LIBS)
|
||||
LIBS += -lusb -ldl
|
||||
|
||||
DEPENDS = Makefile ../config.mk
|
||||
|
||||
@@ -43,7 +39,7 @@ libusb-sniff-64.so: libusb-sniff.c $(DEPENDS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -fPIC $< -ldl -shared -m64 -o $@
|
||||
|
||||
%.o: %.c $(DEPENDS)
|
||||
$(CROSS_CC) $(CFLAGS) $(CPPFLAGS) $(LIBUSB_CFLAGS) -c -o $@ $<
|
||||
$(CROSS_CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||
|
||||
install: $(BIN) $(BIN).1
|
||||
$(INSTALL) -D -m 755 $(BIN) $(DESTDIR)$(PREFIX)/bin/$(BIN)
|
||||
|
||||
+22
-22
@@ -167,12 +167,12 @@ struct xloader_msg xloader_msg_create(uint32_t type, struct image * image) {
|
||||
|
||||
}
|
||||
|
||||
static int read_asic(libusb_device_handle * udev, uint8_t * asic_buffer, int size, int asic_size) {
|
||||
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_recv(udev, USB_READ_EP, asic_buffer, size, READ_TIMEOUT);
|
||||
ret = usb_bulk_read(udev, USB_READ_EP, (char *)asic_buffer, size, READ_TIMEOUT);
|
||||
if ( ret != asic_size )
|
||||
ERROR_RETURN("Invalid size of ASIC ID", -1);
|
||||
|
||||
@@ -180,25 +180,25 @@ static int read_asic(libusb_device_handle * udev, uint8_t * asic_buffer, int siz
|
||||
|
||||
}
|
||||
|
||||
static int send_2nd(libusb_device_handle * udev, struct image * image) {
|
||||
static int send_2nd(usb_dev_handle * udev, struct image * image) {
|
||||
|
||||
uint8_t buffer[1024];
|
||||
uint32_t need, sent;
|
||||
int ret;
|
||||
|
||||
printf("Sending OMAP peripheral boot message...\n");
|
||||
ret = usb_bulk_send(udev, USB_WRITE_EP, &omap_peripheral_msg, sizeof(omap_peripheral_msg), WRITE_TIMEOUT);
|
||||
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&omap_peripheral_msg, sizeof(omap_peripheral_msg), WRITE_TIMEOUT);
|
||||
if ( ret != sizeof(omap_peripheral_msg) )
|
||||
ERROR_RETURN("Sending OMAP peripheral boot message failed", -1);
|
||||
|
||||
MSLEEP(5);
|
||||
SLEEP(5000);
|
||||
|
||||
printf("Sending 2nd X-Loader image size...\n");
|
||||
ret = usb_bulk_send(udev, USB_WRITE_EP, &image->size, 4, WRITE_TIMEOUT);
|
||||
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&image->size, 4, WRITE_TIMEOUT);
|
||||
if ( ret != 4 )
|
||||
ERROR_RETURN("Sending 2nd X-Loader image size failed", -1);
|
||||
|
||||
MSLEEP(5);
|
||||
SLEEP(5000);
|
||||
|
||||
printf("Sending 2nd X-Loader image...\n");
|
||||
printf_progressbar(0, image->size);
|
||||
@@ -211,18 +211,18 @@ static int send_2nd(libusb_device_handle * udev, struct image * image) {
|
||||
ret = image_read(image, buffer, need);
|
||||
if ( ret == 0 )
|
||||
break;
|
||||
if ( usb_bulk_send(udev, USB_WRITE_EP, buffer, ret, WRITE_TIMEOUT) != ret )
|
||||
if ( usb_bulk_write(udev, USB_WRITE_EP, (char *)buffer, ret, WRITE_TIMEOUT) != ret )
|
||||
PRINTF_ERROR_RETURN("Sending 2nd X-Loader image failed", -1);
|
||||
sent += ret;
|
||||
printf_progressbar(sent, image->size);
|
||||
}
|
||||
|
||||
MSLEEP(50);
|
||||
SLEEP(50000);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int send_secondary(libusb_device_handle * udev, struct image * image) {
|
||||
static int send_secondary(usb_dev_handle * udev, struct image * image) {
|
||||
|
||||
struct xloader_msg init_msg;
|
||||
uint8_t buffer[1024];
|
||||
@@ -232,13 +232,13 @@ static int send_secondary(libusb_device_handle * udev, struct image * image) {
|
||||
init_msg = xloader_msg_create(XLOADER_MSG_TYPE_SEND, image);
|
||||
|
||||
printf("Sending X-Loader init message...\n");
|
||||
ret = usb_bulk_send(udev, USB_WRITE_EP, &init_msg, sizeof(init_msg), WRITE_TIMEOUT);
|
||||
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&init_msg, sizeof(init_msg), WRITE_TIMEOUT);
|
||||
if ( ret != sizeof(init_msg) )
|
||||
ERROR_RETURN("Sending X-Loader init message failed", -1);
|
||||
|
||||
printf("Waiting for X-Loader response...\n");
|
||||
MSLEEP(5);
|
||||
ret = usb_bulk_recv(udev, USB_READ_EP, &buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
|
||||
SLEEP(5000);
|
||||
ret = usb_bulk_read(udev, USB_READ_EP, (char *)&buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
|
||||
if ( ret != 4 )
|
||||
ERROR_RETURN("No response", -1);
|
||||
|
||||
@@ -253,15 +253,15 @@ static int send_secondary(libusb_device_handle * udev, struct image * image) {
|
||||
ret = image_read(image, buffer, need);
|
||||
if ( ret == 0 )
|
||||
break;
|
||||
if ( usb_bulk_send(udev, USB_WRITE_EP, buffer, ret, WRITE_TIMEOUT) != ret )
|
||||
if ( usb_bulk_write(udev, USB_WRITE_EP, (char *)buffer, ret, WRITE_TIMEOUT) != ret )
|
||||
PRINTF_ERROR_RETURN("Sending Secondary image failed", -1);
|
||||
sent += ret;
|
||||
printf_progressbar(sent, image->size);
|
||||
}
|
||||
|
||||
printf("Waiting for X-Loader response...\n");
|
||||
MSLEEP(5);
|
||||
ret = usb_bulk_recv(udev, USB_READ_EP, &buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
|
||||
SLEEP(5000);
|
||||
ret = usb_bulk_read(udev, USB_READ_EP, (char *)&buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
|
||||
if ( ret != 4 )
|
||||
ERROR_RETURN("No response", -1);
|
||||
|
||||
@@ -269,7 +269,7 @@ static int send_secondary(libusb_device_handle * udev, struct image * image) {
|
||||
|
||||
}
|
||||
|
||||
static int ping_timeout(libusb_device_handle * udev) {
|
||||
static int ping_timeout(usb_dev_handle * udev) {
|
||||
|
||||
int ret;
|
||||
int pong = 0;
|
||||
@@ -281,7 +281,7 @@ static int ping_timeout(libusb_device_handle * udev) {
|
||||
int try_read = 4;
|
||||
|
||||
printf("Sending X-Loader ping message\n");
|
||||
ret = usb_bulk_send(udev, USB_WRITE_EP, &ping_msg, sizeof(ping_msg), WRITE_TIMEOUT);
|
||||
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&ping_msg, sizeof(ping_msg), WRITE_TIMEOUT);
|
||||
if ( ret != sizeof(ping_msg) )
|
||||
ERROR_RETURN("Sending X-Loader ping message failed", -1);
|
||||
|
||||
@@ -289,14 +289,14 @@ static int ping_timeout(libusb_device_handle * udev) {
|
||||
while ( try_read > 0 ) {
|
||||
|
||||
uint32_t ping_read;
|
||||
ret = usb_bulk_recv(udev, USB_READ_EP, &ping_read, sizeof(ping_read), READ_TIMEOUT);
|
||||
ret = usb_bulk_read(udev, USB_READ_EP, (char *)&ping_read, sizeof(ping_read), READ_TIMEOUT);
|
||||
if ( ret == sizeof(ping_read) ) {
|
||||
printf("Got it\n");
|
||||
pong = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
MSLEEP(5);
|
||||
SLEEP(5000);
|
||||
--try_read;
|
||||
|
||||
}
|
||||
@@ -409,11 +409,11 @@ int leave_cold_flash(struct usb_device_info * dev) {
|
||||
int ret;
|
||||
|
||||
printf("Sending OMAP memory boot message...\n");
|
||||
ret = usb_bulk_send(dev->udev, USB_WRITE_EP, &omap_memory_msg, sizeof(omap_memory_msg), WRITE_TIMEOUT);
|
||||
ret = usb_bulk_write(dev->udev, USB_WRITE_EP, (char *)&omap_memory_msg, sizeof(omap_memory_msg), WRITE_TIMEOUT);
|
||||
if ( ret != sizeof(omap_memory_msg) )
|
||||
ERROR_RETURN("Sending OMAP memory boot message failed", -1);
|
||||
|
||||
MSLEEP(250);
|
||||
SLEEP(1000000);
|
||||
return 0;
|
||||
|
||||
}
|
||||
+6
-8
@@ -184,11 +184,9 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( device_first->hwrevs ) {
|
||||
for ( i = 0; device_first->hwrevs[i] != -1; ++i )
|
||||
if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 )
|
||||
++local;
|
||||
}
|
||||
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;
|
||||
@@ -217,7 +215,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
|
||||
continue;
|
||||
}
|
||||
|
||||
do {
|
||||
while ( device_first->hwrevs[i+1] != -1 ) {
|
||||
|
||||
uint8_t len = 0;
|
||||
ret[j] = ++last_ptr;
|
||||
@@ -230,7 +228,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
|
||||
|
||||
for ( k = 0; k < MAX_HWREVS; ++k ) {
|
||||
|
||||
if ( ! device_first->hwrevs || device_first->hwrevs[i+1] == -1 )
|
||||
if ( device_first->hwrevs[i+1] == -1 )
|
||||
break;
|
||||
|
||||
++i;
|
||||
@@ -248,7 +246,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
|
||||
|
||||
++j;
|
||||
|
||||
} while ( device_first->hwrevs && device_first->hwrevs[i+1] != -1 );
|
||||
}
|
||||
|
||||
device_first = device_first->next;
|
||||
|
||||
|
||||
+42
-106
@@ -118,7 +118,7 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
|
||||
|
||||
blkdev[len] = 0;
|
||||
|
||||
fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK);
|
||||
fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK);
|
||||
if ( fd < 0 ) {
|
||||
ERROR_INFO("Cannot open block device %s", blkdev);
|
||||
return -1;
|
||||
@@ -144,13 +144,13 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
|
||||
ERROR("Block device name is too long");
|
||||
return -1;
|
||||
}
|
||||
fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL);
|
||||
fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL);
|
||||
if ( fd < 0 && errno == ENOENT ) {
|
||||
if ( snprintf(blkdev+len, sizeof(blkdev)-len, "%d", partition) >= (int)(sizeof(blkdev)-len) ) {
|
||||
ERROR("Block device name is too long");
|
||||
return -1;
|
||||
}
|
||||
fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL);
|
||||
fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL);
|
||||
}
|
||||
if ( fd < 0 && errno == ENOENT ) {
|
||||
blkdev[len] = 0;
|
||||
@@ -201,7 +201,7 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
|
||||
|
||||
int disk_dump_dev(int fd, const char * file) {
|
||||
|
||||
int fd2 = -1;
|
||||
int fd2;
|
||||
int ret;
|
||||
char * path;
|
||||
uint64_t blksize;
|
||||
@@ -253,15 +253,11 @@ int disk_dump_dev(int fd, const char * file) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ! simulate ) {
|
||||
|
||||
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
|
||||
if ( fd2 < 0 ) {
|
||||
ERROR_INFO("Cannot create file %s", file);
|
||||
return -1;
|
||||
}
|
||||
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
|
||||
if ( fd2 < 0 ) {
|
||||
ERROR_INFO("Cannot create file %s", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sent = 0;
|
||||
@@ -274,91 +270,26 @@ int disk_dump_dev(int fd, const char * file) {
|
||||
size = read(fd, global_buf, need);
|
||||
if ( size == 0 )
|
||||
break;
|
||||
if ( size < 0 ) {
|
||||
PRINTF_ERROR("Reading from block device failed");
|
||||
if ( ! simulate )
|
||||
close(fd2);
|
||||
if ( write(fd2, global_buf, size) != size ) {
|
||||
PRINTF_ERROR("Dumping image failed");
|
||||
close(fd2);
|
||||
return -1;
|
||||
}
|
||||
if ( ! simulate ) {
|
||||
if ( write(fd2, global_buf, size) != size ) {
|
||||
PRINTF_ERROR("Dumping image failed");
|
||||
close(fd2);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sent += size;
|
||||
printf_progressbar(sent, blksize);
|
||||
}
|
||||
|
||||
if ( ! simulate )
|
||||
close(fd2);
|
||||
close(fd2);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int disk_flash_dev(int fd, struct image * image) {
|
||||
int disk_flash_dev(int fd, const char * file) {
|
||||
|
||||
uint64_t blksize;
|
||||
size_t need, sent;
|
||||
ssize_t size;
|
||||
|
||||
if ( image->type != IMAGE_MMC )
|
||||
ERROR_RETURN("Only mmc images are supported", -1);
|
||||
|
||||
printf("Writing image to block device...\n");
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
if ( ioctl(fd, BLKGETSIZE64, &blksize) != 0 ) {
|
||||
ERROR_INFO("Cannot get size of block device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
blksize = lseek(fd, 0, SEEK_END);
|
||||
if ( (off_t)blksize == (off_t)-1 ) {
|
||||
ERROR_INFO("Cannot get size of block device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( lseek(fd, 0, SEEK_SET) == (off_t)-1 ) {
|
||||
ERROR_INFO("Cannot seek to begin of block device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if ( blksize == 0 )
|
||||
ERROR_RETURN("Block device has zero size", -1);
|
||||
|
||||
if ( image->size > blksize )
|
||||
ERROR_RETURN("Image is too big", -1);
|
||||
|
||||
sent = 0;
|
||||
printf_progressbar(0, image->size);
|
||||
|
||||
while ( sent < image->size ) {
|
||||
need = image->size - sent;
|
||||
if ( need > sizeof(global_buf) )
|
||||
need = sizeof(global_buf);
|
||||
size = image_read(image, global_buf, need);
|
||||
if ( size == 0 ) {
|
||||
PRINTF_ERROR("Failed to read image");
|
||||
return -1;
|
||||
}
|
||||
if ( ! simulate ) {
|
||||
if ( write(fd, global_buf, size) != size ) {
|
||||
PRINTF_ERROR("Writing image failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sent += size;
|
||||
printf_progressbar(sent, image->size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
ERROR("Not implemented yet");
|
||||
(void)fd;
|
||||
(void)file;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
@@ -385,9 +316,13 @@ int disk_init(struct usb_device_info * dev) {
|
||||
unsigned int devnum;
|
||||
unsigned int busnum;
|
||||
|
||||
libusb_device * device;
|
||||
struct usb_device * device;
|
||||
|
||||
device = libusb_get_device(dev->udev);
|
||||
device = usb_device(dev->udev);
|
||||
if ( ! device || ! device->bus ) {
|
||||
ERROR_INFO("Cannot read usb devnum and busnum");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir = opendir("/sys/dev/block/");
|
||||
if ( ! dir ) {
|
||||
@@ -428,11 +363,16 @@ int disk_init(struct usb_device_info * dev) {
|
||||
|
||||
fclose(f);
|
||||
|
||||
if ( (unsigned int)libusb_get_device_address(device) != devnum )
|
||||
if ( device->devnum != devnum )
|
||||
continue;
|
||||
|
||||
if ( (unsigned int)libusb_get_bus_number(device) != busnum )
|
||||
continue;
|
||||
if ( device->bus->location ) {
|
||||
if ( device->bus->location != busnum )
|
||||
continue;
|
||||
} else if ( device->bus->dirname[0] ) {
|
||||
if ( atoi(device->bus->dirname) != (int)busnum )
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( sscanf(dirent->d_name, "%d:%d", &maj2, &min2) != 2 ) {
|
||||
maj2 = -1;
|
||||
@@ -467,14 +407,16 @@ int disk_init(struct usb_device_info * dev) {
|
||||
maj2 = tmp;
|
||||
}
|
||||
|
||||
/* RX-51, RM-680 and RM-696 export MyDocs in first usb device and just first partion, so host system see whole device without MBR table */
|
||||
if ( dev->device == DEVICE_RX_51 || dev->device == DEVICE_RM_680 || dev->device == DEVICE_RM_696 )
|
||||
fd = disk_open_dev(maj1, min1, -1, simulate ? 1 : 0);
|
||||
/* TODO: change 1 to 0 when disk_flash_dev will be implemented */
|
||||
|
||||
/* RX-51 and RM-680 export MyDocs in first usb device and just first partion, so host system see whole device without MBR table */
|
||||
if ( dev->device == DEVICE_RX_51 || dev->device == DEVICE_RM_680 )
|
||||
fd = disk_open_dev(maj1, min1, -1, 1);
|
||||
/* Other devices can export SD card as first partition and export whole mmc device, so host system will see MBR table */
|
||||
else if ( maj2 != -1 && min2 != -1 )
|
||||
fd = disk_open_dev(maj2, min2, 1, simulate ? 1 : 0);
|
||||
fd = disk_open_dev(maj2, min2, 1, 1);
|
||||
else
|
||||
fd = disk_open_dev(maj1, min1, 1, simulate ? 1 : 0);
|
||||
fd = disk_open_dev(maj1, min1, 1, 1);
|
||||
|
||||
if ( fd < 0 )
|
||||
return -1;
|
||||
@@ -507,16 +449,10 @@ enum device disk_get_device(struct usb_device_info * dev) {
|
||||
|
||||
int disk_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||
|
||||
int ret;
|
||||
|
||||
printf("Flash image:\n");
|
||||
image_print_info(image);
|
||||
|
||||
ret = disk_flash_dev(dev->data, image);
|
||||
if ( ret == 0 )
|
||||
printf("Done\n");
|
||||
|
||||
return ret;
|
||||
ERROR("Not implemented yet");
|
||||
(void)dev;
|
||||
(void)image;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ enum device disk_get_device(struct usb_device_info * dev);
|
||||
|
||||
int disk_open_dev(int maj, int min, int partition, int readonly);
|
||||
int disk_dump_dev(int fd, const char * file);
|
||||
int disk_flash_dev(int fd, struct image * image);
|
||||
int disk_flash_dev(int fd, 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);
|
||||
|
||||
+77
-270
@@ -34,11 +34,10 @@
|
||||
#include "image.h"
|
||||
#include "fiasco.h"
|
||||
|
||||
#define CHECKSUM(checksum, buf, size) do { size_t _i; for ( _i = 0; _i < size; _i++ ) checksum += ((unsigned char *)buf)[_i]; } while (0)
|
||||
#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, checksum, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; CHECKSUM(checksum, buf, 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_FREE(file, fd, buf, size, var) do { if ( ! simulate ) { if ( write(fd, buf, size) != (ssize_t)size ) { free(var); FIASCO_WRITE_ERROR(file, fd, "Cannot write %d bytes", size); } } } while (0)
|
||||
#define WRITE_OR_FAIL(file, fd, buf, size) WRITE_OR_FAIL_FREE(file, fd, buf, size, NULL)
|
||||
|
||||
@@ -66,16 +65,9 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||
char hwrevs[1024];
|
||||
char version[257];
|
||||
char layout[257];
|
||||
uint8_t asicidx;
|
||||
uint8_t devicetype;
|
||||
uint8_t deviceidx;
|
||||
uint8_t checksum;
|
||||
uint32_t address;
|
||||
uint16_t hash;
|
||||
off_t offset;
|
||||
struct image * image;
|
||||
struct image_part * image_part;
|
||||
struct image_part * image_parts;
|
||||
|
||||
char hwrev[9];
|
||||
unsigned char buf[512];
|
||||
@@ -112,11 +104,11 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||
READ_OR_FAIL(fiasco, buf, length8);
|
||||
if ( byte == 0xe8 ) {
|
||||
memset(fiasco->name, 0, sizeof(fiasco->name));
|
||||
memcpy(fiasco->name, buf, length8);
|
||||
strncpy(fiasco->name, (char *)buf, length8);
|
||||
VERBOSE("Fiasco name: %s\n", fiasco->name);
|
||||
} else if ( byte == 0x31 ) {
|
||||
memset(fiasco->swver, 0, sizeof(fiasco->swver));
|
||||
memcpy(fiasco->swver, buf, length8);
|
||||
strncpy(fiasco->swver, (char *)buf, length8);
|
||||
VERBOSE("SW version: %s\n", fiasco->swver);
|
||||
} else {
|
||||
VERBOSE("Unknown header %#x\n", byte);
|
||||
@@ -128,41 +120,23 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||
while ( 1 ) {
|
||||
|
||||
/* If end of file, return fiasco image */
|
||||
checksum = 0x00;
|
||||
READ_OR_RETURN(fiasco, checksum, buf, 1);
|
||||
READ_OR_RETURN(fiasco, buf, 7);
|
||||
|
||||
/* Header of next image (0x54) */
|
||||
if ( buf[0] != 0x54 ) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
checksum = 0x00;
|
||||
count8 = buf[1];
|
||||
if ( count8 > 0 )
|
||||
--count8;
|
||||
|
||||
READ_OR_RETURN(fiasco, checksum, &count8, 1);
|
||||
|
||||
if ( count8 == 0 ) {
|
||||
ERROR("No section in image header");
|
||||
return fiasco;
|
||||
}
|
||||
|
||||
READ_OR_RETURN(fiasco, checksum, buf, 2);
|
||||
|
||||
/* File data section (0x2E) with length of 25 bytes */
|
||||
if ( buf[0] != 0x2E || buf[1] != 25 ) {
|
||||
ERROR("First section in image header is not file data with length of 25 bytes");
|
||||
return fiasco;
|
||||
}
|
||||
|
||||
READ_OR_RETURN(fiasco, checksum, &asicidx, 1);
|
||||
READ_OR_RETURN(fiasco, checksum, &devicetype, 1);
|
||||
READ_OR_RETURN(fiasco, checksum, &deviceidx, 1);
|
||||
|
||||
READ_OR_RETURN(fiasco, checksum, &hash, 2);
|
||||
READ_OR_RETURN(fiasco, &hash, 2);
|
||||
hash = ntohs(hash);
|
||||
|
||||
memset(type, 0, sizeof(type));
|
||||
READ_OR_RETURN(fiasco, checksum, type, 12);
|
||||
READ_OR_RETURN(fiasco, type, 12);
|
||||
|
||||
byte = type[0];
|
||||
if ( byte == 0xFF )
|
||||
@@ -170,35 +144,26 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||
|
||||
VERBOSE(" %s\n", type);
|
||||
|
||||
READ_OR_RETURN(fiasco, checksum, &length, 4);
|
||||
READ_OR_RETURN(fiasco, &length, 4);
|
||||
length = ntohl(length);
|
||||
|
||||
/* load address (unused) */
|
||||
READ_OR_RETURN(fiasco, checksum, &address, 4);
|
||||
|
||||
/* end of file data section */
|
||||
--count8;
|
||||
/* unknown */
|
||||
READ_OR_RETURN(fiasco, buf, 4);
|
||||
|
||||
VERBOSE(" size: %d bytes\n", length);
|
||||
VERBOSE(" address: 0x%04x\n", address);
|
||||
VERBOSE(" hash: 0x%04x\n", hash);
|
||||
VERBOSE(" asic idx: %d\n", asicidx);
|
||||
VERBOSE(" device type: %d\n", devicetype);
|
||||
VERBOSE(" device idx: %d\n", deviceidx);
|
||||
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));
|
||||
image_part = NULL;
|
||||
image_parts = NULL;
|
||||
|
||||
while ( count8 > 0 ) {
|
||||
|
||||
READ_OR_RETURN(fiasco, checksum, &byte, 1);
|
||||
READ_OR_RETURN(fiasco, checksum, &length8, 1);
|
||||
READ_OR_RETURN(fiasco, checksum, buf, length8);
|
||||
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);
|
||||
@@ -206,14 +171,14 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||
|
||||
if ( byte == '1' ) {
|
||||
memset(version, 0, sizeof(version));
|
||||
memcpy(version, buf, length8);
|
||||
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));
|
||||
memcpy(device, buf, tmp);
|
||||
strncpy(device, (char *)buf, tmp);
|
||||
VERBOSE("hw revision\n");
|
||||
VERBOSE(" device: %s\n", device);
|
||||
pbuf = buf + strlen(device) + 1;
|
||||
@@ -224,7 +189,7 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||
tmp = buf + length8 - pbuf;
|
||||
if ( tmp > 8 ) tmp = 8;
|
||||
memset(hwrev, 0, sizeof(hwrev));
|
||||
memcpy(hwrev, pbuf, tmp);
|
||||
strncpy(hwrev, (char *)pbuf, tmp);
|
||||
if ( ! hwrevs[0] )
|
||||
strcpy(hwrevs, hwrev);
|
||||
else {
|
||||
@@ -240,90 +205,17 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||
}
|
||||
} else if ( byte == '3' ) {
|
||||
memset(layout, 0, sizeof(layout));
|
||||
memcpy(layout, buf, length8);
|
||||
strncpy(layout, (char *)buf, length8);
|
||||
VERBOSE("layout\n");
|
||||
} else if ( byte == '4' ) {
|
||||
VERBOSE("data part\n");
|
||||
if ( length8 < 16 ) {
|
||||
VERBOSE(" (damaged)\n");
|
||||
} else {
|
||||
if ( image_parts ) {
|
||||
image_part->next = calloc(1, sizeof(struct image_part));
|
||||
if ( ! image_part->next )
|
||||
FIASCO_READ_ERROR(fiasco, "Cannot allocate image");
|
||||
image_part = image_part->next;
|
||||
} else {
|
||||
image_parts = calloc(1, sizeof(struct image_part));
|
||||
if ( ! image_parts )
|
||||
FIASCO_READ_ERROR(fiasco, "Cannot allocate image");
|
||||
image_part = image_parts;
|
||||
}
|
||||
image_part->offset = ntohl(*(uint32_t *)&buf[4]);
|
||||
image_part->size = ntohl(*(uint32_t *)&buf[12]);
|
||||
if ( length8 > 16 ) {
|
||||
image_part->name = calloc(1, length8-16+1);
|
||||
if ( image_part->name )
|
||||
memcpy(image_part->name, &buf[16], length8-16);
|
||||
}
|
||||
VERBOSE(" unknown: 0x%02x 0x%02x 0x%02x 0x%02x\n", buf[0], buf[1], buf[2], buf[3]);
|
||||
VERBOSE(" offset: %u bytes\n", image_part->offset);
|
||||
VERBOSE(" unknown: 0x%02x 0x%02x 0x%02x 0x%02x\n", buf[8], buf[9], buf[10], buf[11]);
|
||||
VERBOSE(" size: %u bytes\n", image_part->size);
|
||||
if ( image_part->name )
|
||||
VERBOSE(" partition name: %s\n", image_part->name);
|
||||
}
|
||||
} else if ( byte == 0x2F ) {
|
||||
VERBOSE("partition info\n");
|
||||
if ( length8 < 15 ) {
|
||||
VERBOSE(" (damaged)\n");
|
||||
} else {
|
||||
unsigned int i;
|
||||
unsigned int part_type;
|
||||
unsigned int part_attr;
|
||||
unsigned int part_size;
|
||||
unsigned int num_parts = ((unsigned)buf[11] << 24) | ((unsigned)buf[12] << 16) | ((unsigned)buf[13] << 8) | ((unsigned)buf[14] << 0);
|
||||
VERBOSE(" asic idx: %d\n", buf[0]);
|
||||
VERBOSE(" device type: %d\n", buf[1]);
|
||||
VERBOSE(" device idx: %d\n", buf[2]);
|
||||
VERBOSE(" version: 0x%02x%02x%02x%02x\n", buf[3], buf[4], buf[5], buf[6]);
|
||||
VERBOSE(" spare: 0x%02x%02x%02x%02x\n", buf[7], buf[8], buf[9], buf[10]);
|
||||
VERBOSE(" partitions: %d\n", num_parts);
|
||||
for ( i = 0; i < num_parts; i++ ) {
|
||||
VERBOSE(" partition\n");
|
||||
if ( 20 + i*6 >= length8 ) {
|
||||
VERBOSE(" (damaged)\n");
|
||||
continue;
|
||||
}
|
||||
part_type = buf[15 + i*6];
|
||||
part_attr = buf[16 + i*6];
|
||||
part_size = ((unsigned)buf[17 + i*6] << 24) | ((unsigned)buf[18 + i*6] << 16) | ((unsigned)buf[19 + i*6] << 8) | ((unsigned)buf[20 + i*6] << 0);
|
||||
VERBOSE(" type: 0x%02x (%s)\n", part_type, part_type == 0x03 ? "kernel" : part_type == 0x04 ? "initfs" : part_type == 0x05 ? "rootfs" : "unknown");
|
||||
VERBOSE(" attribute: 0x%02x (%s)\n", part_attr, part_attr == 0x1 ? "read/write" : part_attr == 0x2 ? "read-only" : "unknown");
|
||||
if ( part_size == 0 )
|
||||
VERBOSE(" size: remaining space\n");
|
||||
else
|
||||
VERBOSE(" size: %u bytes\n", part_size);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
VERBOSE("unknown (%#x)\n", byte);
|
||||
VERBOSE(" hexdump:");
|
||||
for ( i = 0; i < length8; i++ ) VERBOSE(" 0x%02x", buf[i]);
|
||||
VERBOSE("\n");
|
||||
VERBOSE("unknown ('%c':%#x)\n", byte, byte);
|
||||
}
|
||||
|
||||
--count8;
|
||||
}
|
||||
|
||||
/* checksum */
|
||||
READ_OR_RETURN(fiasco, checksum, buf, 1);
|
||||
VERBOSE(" subinfo checksum: 0x%02x\n", buf[0]);
|
||||
|
||||
if ( ! noverify && buf[0] != 0x00 && checksum != 0xFF ) {
|
||||
ERROR("Image header subinfo checksum mishmash (counted 0x%02x, got 0x%02x)", (0xFF - checksum + buf[0]) & 0xFF, buf[0]);
|
||||
return fiasco;
|
||||
}
|
||||
/* unknown */
|
||||
READ_OR_RETURN(fiasco, buf, 1);
|
||||
|
||||
offset = lseek(fiasco->fd, 0, SEEK_CUR);
|
||||
if ( offset == (off_t)-1 )
|
||||
@@ -334,7 +226,7 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
||||
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, image_parts);
|
||||
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");
|
||||
@@ -382,12 +274,10 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
|
||||
uint32_t length;
|
||||
uint16_t hash;
|
||||
uint8_t length8;
|
||||
uint8_t checksum;
|
||||
char ** device_hwrevs_bufs;
|
||||
const char * str;
|
||||
const char * type;
|
||||
struct image_list * image_list;
|
||||
struct image_part * image_part;
|
||||
struct image * image;
|
||||
unsigned char buf[4096];
|
||||
|
||||
@@ -485,46 +375,32 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
|
||||
/* signature */
|
||||
WRITE_OR_FAIL_FREE(file, fd, "T", 1, device_hwrevs_bufs);
|
||||
|
||||
checksum = 0x00;
|
||||
|
||||
/* number of subsections */
|
||||
length8 = device_count+1;
|
||||
if ( image->version )
|
||||
++length8;
|
||||
if ( image->layout )
|
||||
++length8;
|
||||
if ( image->parts ) {
|
||||
for ( image_part = image->parts; image_part; image_part = image_part->next )
|
||||
++length8;
|
||||
} else {
|
||||
++length;
|
||||
}
|
||||
WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs);
|
||||
CHECKSUM(checksum, &length8, 1);
|
||||
|
||||
/* file data: asic index: APE (0x01), device type: NAND (0x01), device index: 0 */
|
||||
/* unknown */
|
||||
WRITE_OR_FAIL_FREE(file, fd, "\x2e\x19\x01\x01\x00", 5, device_hwrevs_bufs);
|
||||
CHECKSUM(checksum, "\x2e\x19\x01\x01\x00", 5);
|
||||
|
||||
/* checksum */
|
||||
hash = htons(image->hash);
|
||||
WRITE_OR_FAIL_FREE(file, fd, &hash, 2, device_hwrevs_bufs);
|
||||
CHECKSUM(checksum, &hash, 2);
|
||||
|
||||
/* image type name */
|
||||
memset(buf, 0, 12);
|
||||
strncpy((char *)buf, type, 12);
|
||||
WRITE_OR_FAIL_FREE(file, fd, buf, 12, device_hwrevs_bufs);
|
||||
CHECKSUM(checksum, buf, 12);
|
||||
|
||||
/* image size */
|
||||
size = htonl(image->size);
|
||||
WRITE_OR_FAIL_FREE(file, fd, &size, 4, device_hwrevs_bufs);
|
||||
CHECKSUM(checksum, &size, 4);
|
||||
|
||||
/* image load address (unused always zero) */
|
||||
/* unknown */
|
||||
WRITE_OR_FAIL_FREE(file, fd, "\x00\x00\x00\x00", 4, device_hwrevs_bufs);
|
||||
CHECKSUM(checksum, "\x00\x00\x00\x00", 4);
|
||||
|
||||
/* append version subsection */
|
||||
if ( image->version ) {
|
||||
@@ -532,9 +408,6 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
|
||||
length8 = strlen(image->version)+1; /* +1 for NULL term */
|
||||
WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs);
|
||||
WRITE_OR_FAIL_FREE(file, fd, image->version, length8, device_hwrevs_bufs);
|
||||
CHECKSUM(checksum, "1", 1);
|
||||
CHECKSUM(checksum, &length8, 1);
|
||||
CHECKSUM(checksum, image->version, length8);
|
||||
}
|
||||
|
||||
/* append device & hwrevs subsection */
|
||||
@@ -543,9 +416,6 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
|
||||
length8 = ((uint8_t *)(device_hwrevs_bufs[i]))[0];
|
||||
WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs);
|
||||
WRITE_OR_FAIL_FREE(file, fd, device_hwrevs_bufs[i]+1, length8, device_hwrevs_bufs);
|
||||
CHECKSUM(checksum, "2", 1);
|
||||
CHECKSUM(checksum, &length8, 1);
|
||||
CHECKSUM(checksum, device_hwrevs_bufs[i]+1, length8);
|
||||
}
|
||||
free(device_hwrevs_bufs);
|
||||
|
||||
@@ -555,47 +425,10 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
|
||||
length8 = strlen(image->layout);
|
||||
WRITE_OR_FAIL(file, fd, &length8, 1);
|
||||
WRITE_OR_FAIL(file, fd, image->layout, length8);
|
||||
CHECKSUM(checksum, "3", 1);
|
||||
CHECKSUM(checksum, &length8, 1);
|
||||
CHECKSUM(checksum, image->layout, length8);
|
||||
}
|
||||
|
||||
if ( image->parts ) {
|
||||
/* for each image part append subsection */
|
||||
for ( image_part = image->parts; image_part; image_part = image_part->next ) {
|
||||
WRITE_OR_FAIL(file, fd, "4", 1); /* 4 - image data part */
|
||||
CHECKSUM(checksum, "4", 1);
|
||||
length = 16 + (image_part->name ? strlen(image_part->name) : 0);
|
||||
length8 = length <= UINT8_MAX ? length : UINT8_MAX;
|
||||
WRITE_OR_FAIL(file, fd, &length8, 1);
|
||||
CHECKSUM(checksum, &length8, 1);
|
||||
WRITE_OR_FAIL(file, fd, "\x00\x00\x00\x00", 4); /* unknown */
|
||||
CHECKSUM(checksum, "\x00\x00\x00\x00", 4);
|
||||
size = htonl(image_part->offset);
|
||||
WRITE_OR_FAIL(file, fd, &size, 4);
|
||||
CHECKSUM(checksum, &size, 4);
|
||||
WRITE_OR_FAIL(file, fd, "\x00\x00\x00\x00", 4); /* unknown */
|
||||
CHECKSUM(checksum, "\x00\x00\x00\x00", 4);
|
||||
size = htonl(image_part->size);
|
||||
WRITE_OR_FAIL(file, fd, &size, 4);
|
||||
CHECKSUM(checksum, &size, 4);
|
||||
if ( image_part->name ) {
|
||||
WRITE_OR_FAIL(file, fd, image_part->name, length8-16);
|
||||
CHECKSUM(checksum, image_part->name, (size_t)length8-16);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* append one image data part subsection */;
|
||||
WRITE_OR_FAIL(file, fd, "4\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14);
|
||||
CHECKSUM(checksum, "4\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 14);
|
||||
size = htonl(image->size);
|
||||
WRITE_OR_FAIL(file, fd, &size, 4);
|
||||
CHECKSUM(checksum, &size, 4);
|
||||
}
|
||||
|
||||
/* checksum of header */
|
||||
checksum = 0xFF - checksum;
|
||||
WRITE_OR_FAIL(file, fd, &checksum, 1);
|
||||
/* dummy byte - end of all subsections */
|
||||
WRITE_OR_FAIL(file, fd, "\x00", 1);
|
||||
|
||||
printf("Writing image data...\n");
|
||||
|
||||
@@ -628,10 +461,8 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
|
||||
char * name;
|
||||
char * layout_name;
|
||||
struct image * image;
|
||||
struct image_part * image_part;
|
||||
struct image_list * image_list;
|
||||
uint32_t offset, size, need, total_size, written;
|
||||
int part_num;
|
||||
uint32_t size;
|
||||
char cwd[256];
|
||||
unsigned char buf[4096];
|
||||
|
||||
@@ -658,30 +489,68 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
|
||||
while ( image_list ) {
|
||||
|
||||
fd = -1;
|
||||
name = NULL;
|
||||
layout_name = NULL;
|
||||
|
||||
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 ) {
|
||||
|
||||
name = image_name_alloc_from_values(image, -1);
|
||||
if ( ! name )
|
||||
ALLOC_ERROR_RETURN(-1);
|
||||
|
||||
layout_name = calloc(1, strlen(name) + sizeof("_layout.txt")-1 + 1);
|
||||
layout_name = calloc(1, strlen(name) + sizeof(".layout")-1 + 1);
|
||||
if ( ! layout_name ) {
|
||||
free(name);
|
||||
ALLOC_ERROR_RETURN(-1);
|
||||
}
|
||||
|
||||
sprintf(layout_name, "%s_layout.txt", name);
|
||||
free(name);
|
||||
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);
|
||||
free(name);
|
||||
free(layout_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
image_seek(image, 0);
|
||||
while ( 1 ) {
|
||||
size = image_read(image, buf, sizeof(buf));
|
||||
if ( size == 0 )
|
||||
break;
|
||||
if ( ! simulate ) {
|
||||
if ( write(fd, buf, size) != (ssize_t)size ) {
|
||||
ERROR_INFO_STR(name, "Cannot write %d bytes", size);
|
||||
close(fd);
|
||||
free(name);
|
||||
free(layout_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(name);
|
||||
|
||||
if ( ! simulate )
|
||||
close(fd);
|
||||
|
||||
if ( image->layout ) {
|
||||
|
||||
if ( ! simulate ) {
|
||||
fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644);
|
||||
if ( fd < 0 ) {
|
||||
@@ -702,73 +571,11 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
|
||||
|
||||
free(layout_name);
|
||||
|
||||
if ( ! simulate ) {
|
||||
if ( ! simulate )
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
part_num = 0;
|
||||
image_part = image->parts;
|
||||
|
||||
do {
|
||||
|
||||
offset = image_part ? image_part->offset : 0;
|
||||
total_size = image_part ? image_part->size : image->size;
|
||||
|
||||
name = image_name_alloc_from_values(image, image_part ? part_num : -1);
|
||||
if ( ! name )
|
||||
ALLOC_ERROR_RETURN(-1);
|
||||
|
||||
if ( image_part && ( part_num > 0 || image_part->next ) )
|
||||
printf(" Output file part %d: %s\n", part_num+1, name);
|
||||
else
|
||||
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);
|
||||
free(name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
written = 0;
|
||||
image_seek(image, offset);
|
||||
while ( written < total_size ) {
|
||||
need = total_size - written;
|
||||
if ( need > sizeof(buf) )
|
||||
need = sizeof(buf);
|
||||
size = image_read(image, buf, need);
|
||||
if ( size == 0 )
|
||||
break;
|
||||
if ( ! simulate ) {
|
||||
if ( write(fd, buf, size) != (ssize_t)size ) {
|
||||
ERROR_INFO_STR(name, "Cannot write %d bytes", size);
|
||||
close(fd);
|
||||
free(name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
written += size;
|
||||
}
|
||||
|
||||
free(name);
|
||||
|
||||
if ( ! simulate ) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
if ( image_part ) {
|
||||
image_part = image_part->next;
|
||||
part_num++;
|
||||
}
|
||||
|
||||
} while ( image_part );
|
||||
|
||||
image_list = image_list->next;
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ extern int verbose;
|
||||
#define ALLOC_ERROR() do { ERROR("Cannot allocate memory"); } while (0)
|
||||
#define ALLOC_ERROR_RETURN(...) do { ALLOC_ERROR(); return __VA_ARGS__; } while (0)
|
||||
|
||||
#define MSLEEP(msec) do { nanosleep(&(struct timespec){ (msec / 1000), (1000L * 1000L * (msec % 1000)) }, NULL); } while (0)
|
||||
#define SLEEP(usec) do { struct timespec _t = { 0, (usec) }; nanosleep(&_t, NULL); } while (0)
|
||||
|
||||
static inline void * MEMMEM(void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
|
||||
for ( size_t i = 0; i < haystacklen; ++i ) {
|
||||
|
||||
+105
-268
@@ -30,6 +30,9 @@
|
||||
#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) {
|
||||
|
||||
@@ -97,7 +100,7 @@ static void image_missing_values_from_name(struct image * image, const char * na
|
||||
}
|
||||
|
||||
/* format: type-device:hwrevs_version */
|
||||
char * image_name_alloc_from_values(struct image * image, int part_num) {
|
||||
char * image_name_alloc_from_values(struct image * image) {
|
||||
|
||||
char * name;
|
||||
char * ptr;
|
||||
@@ -105,8 +108,6 @@ char * image_name_alloc_from_values(struct image * image, int part_num) {
|
||||
size_t length;
|
||||
const char * type;
|
||||
const char * device;
|
||||
struct image_part * part;
|
||||
int i;
|
||||
|
||||
type = image_type_to_string(image->type);
|
||||
|
||||
@@ -123,14 +124,6 @@ char * image_name_alloc_from_values(struct image * image, int part_num) {
|
||||
else
|
||||
hwrevs = NULL;
|
||||
|
||||
part = image->parts;
|
||||
|
||||
if ( part && ( !part->next || part_num < 0 ) )
|
||||
part = NULL;
|
||||
|
||||
for ( i = 0; i < part_num && part; i++ )
|
||||
part = part->next;
|
||||
|
||||
length = 1 + strlen(type);
|
||||
|
||||
if ( device )
|
||||
@@ -139,10 +132,6 @@ char * image_name_alloc_from_values(struct image * image, int part_num) {
|
||||
length += 1 + strlen(hwrevs);
|
||||
if ( image->version )
|
||||
length += 1 + strlen(image->version);
|
||||
if ( part )
|
||||
length += 4 + 3; /* 3 <= strlen(part_num) */
|
||||
if ( part && part->name )
|
||||
length += 1 + strlen(part->name);
|
||||
|
||||
name = calloc(1, length);
|
||||
if ( ! name ) {
|
||||
@@ -160,19 +149,13 @@ char * image_name_alloc_from_values(struct image * image, int part_num) {
|
||||
if ( image->version )
|
||||
ptr += sprintf(ptr, "_%s", image->version);
|
||||
|
||||
if ( part ) {
|
||||
ptr += sprintf(ptr, "_part%d", part_num+1);
|
||||
if ( part->name )
|
||||
ptr += sprintf(ptr, "_%s", part->name);
|
||||
}
|
||||
|
||||
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, struct image_part * parts) {
|
||||
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;
|
||||
|
||||
@@ -227,42 +210,26 @@ static int image_append(struct image * image, const char * type, const char * de
|
||||
else
|
||||
image->layout = NULL;
|
||||
|
||||
image->parts = parts;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void image_align(struct image * image) {
|
||||
|
||||
struct image_fd * image_fd = image->fds;
|
||||
size_t align, aligned_size;
|
||||
uint32_t total_size;
|
||||
size_t align;
|
||||
|
||||
if ( image->type == IMAGE_MMC )
|
||||
align = 8;
|
||||
else
|
||||
align = 7;
|
||||
|
||||
if ( image_fd && ! image_fd->next && image->size == image_fd->size && ( image->size & ( ( 1ULL << align ) - 1 ) ) == 0 )
|
||||
if ( ( image->size & ( ( 1ULL << align ) - 1 ) ) == 0 )
|
||||
return;
|
||||
|
||||
total_size = 0;
|
||||
align = ((image->size >> align) + 1) << align;
|
||||
|
||||
while ( image_fd ) {
|
||||
|
||||
if ( ( image_fd->size & ( ( 1ULL << align ) - 1 ) ) != 0 ) {
|
||||
aligned_size = ((image_fd->size >> align) + 1) << align;
|
||||
image_fd->align = aligned_size - image_fd->size;
|
||||
image_fd->size = aligned_size;
|
||||
}
|
||||
|
||||
total_size += image_fd->size;
|
||||
image_fd = image_fd->next;
|
||||
|
||||
}
|
||||
|
||||
image->size = total_size;
|
||||
image->align = align - image->size;
|
||||
image->size = align;
|
||||
|
||||
image->hash = image_hash_from_data(image);
|
||||
|
||||
@@ -277,100 +244,58 @@ static struct image * image_alloc(void) {
|
||||
|
||||
}
|
||||
|
||||
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_part * parts) {
|
||||
struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
|
||||
|
||||
return image_alloc_from_files(&file, 1, type, device, hwrevs, version, layout, parts);
|
||||
int fd;
|
||||
|
||||
}
|
||||
|
||||
struct image * image_alloc_from_files(const char ** files, int count, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) {
|
||||
|
||||
struct image * image;
|
||||
int i;
|
||||
int * fds = calloc(count, sizeof(int));
|
||||
if ( ! fds )
|
||||
ALLOC_ERROR_RETURN(NULL);
|
||||
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
fds[i] = open(files[i], O_RDONLY);
|
||||
if ( fds[i] < 0 ) {
|
||||
ERROR_INFO("Cannot open image file %s", files[i]);
|
||||
free(fds);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
image = image_alloc_from_fds(fds, files, count, type, device, hwrevs, version, layout, parts);
|
||||
free(fds);
|
||||
return image;
|
||||
|
||||
}
|
||||
|
||||
struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) {
|
||||
|
||||
return image_alloc_from_fds(&fd, &orig_filename, 1, type, device, hwrevs, version, layout, parts);
|
||||
|
||||
}
|
||||
|
||||
struct image * image_alloc_from_fds(int * fds, const char ** orig_filenames, int count, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts) {
|
||||
|
||||
int i;
|
||||
struct image * image = image_alloc();
|
||||
if ( ! image ) {
|
||||
for ( i = 0; i < count; ++i )
|
||||
close(fds[i]);
|
||||
fd = open(file, O_RDONLY);
|
||||
if ( fd < 0 ) {
|
||||
ERROR_INFO("Cannot open image file %s", file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for ( i = 0; i < count; ++i ) {
|
||||
return image_alloc_from_fd(fd, file, type, device, hwrevs, version, layout);
|
||||
|
||||
off_t offset;
|
||||
struct image_fd * image_fds = image->fds;
|
||||
struct image_fd * image_fd = calloc(1, sizeof(struct image_fd));
|
||||
if ( ! image_fd ) {
|
||||
image_free(image);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! image_fds ) {
|
||||
image->fds = image_fd;
|
||||
} else {
|
||||
while ( image_fds->next )
|
||||
image_fds = image_fds->next;
|
||||
image_fds->next = image_fd;
|
||||
}
|
||||
|
||||
image_fd->is_shared_fd = 0;
|
||||
image_fd->fd = fds[i];
|
||||
|
||||
offset = lseek(image_fd->fd, 0, SEEK_END);
|
||||
if ( offset == (off_t)-1 ) {
|
||||
ERROR_INFO("Cannot seek to end of file %s", orig_filenames[i]);
|
||||
image_free(image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image_fd->size = offset;
|
||||
image_fd->offset = 0;
|
||||
image_fd->is_shared_fd = 0;
|
||||
image_fd->shared_cur = 0;
|
||||
image_fd->orig_filename = strdup(orig_filenames[i]);
|
||||
|
||||
image->size += image_fd->size;
|
||||
|
||||
if ( lseek(image_fd->fd, 0, SEEK_SET) == (off_t)-1 ) {
|
||||
ERROR_INFO("Cannot seek to begin of file %s", orig_filenames[i]);
|
||||
image_free(image);
|
||||
return NULL;
|
||||
}
|
||||
struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
|
||||
|
||||
off_t offset;
|
||||
struct image * image = image_alloc();
|
||||
if ( ! image ) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( image_append(image, type, device, hwrevs, version, layout, parts) < 0 )
|
||||
image->is_shared_fd = 0;
|
||||
image->fd = fd;
|
||||
|
||||
offset = lseek(image->fd, 0, SEEK_END);
|
||||
if ( offset == (off_t)-1 ) {
|
||||
ERROR_INFO("Cannot seek to end of file %s", orig_filename);
|
||||
close(image->fd);
|
||||
free(image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image->size = offset;
|
||||
image->offset = 0;
|
||||
image->cur = 0;
|
||||
image->orig_filename = strdup(orig_filename);
|
||||
|
||||
if ( lseek(image->fd, 0, SEEK_SET) == (off_t)-1 ) {
|
||||
ERROR_INFO("Cannot seek to begin of file %s", orig_filename);
|
||||
close(image->fd);
|
||||
free(image->orig_filename);
|
||||
free(image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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, count > 0 ? orig_filenames[0] : NULL);
|
||||
image_missing_values_from_name(image, orig_filename);
|
||||
|
||||
image_align(image);
|
||||
|
||||
@@ -378,25 +303,19 @@ struct image * image_alloc_from_fds(int * fds, const char ** orig_filenames, int
|
||||
|
||||
}
|
||||
|
||||
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_part * parts) {
|
||||
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();
|
||||
struct image_fd * image_fd = calloc(1, sizeof(struct image_fd));
|
||||
if ( ! image || ! image_fd ) {
|
||||
free(image);
|
||||
free(image_fd);
|
||||
if ( ! image )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image_fd->is_shared_fd = 1;
|
||||
image_fd->fd = fd;
|
||||
image_fd->size = size;
|
||||
image_fd->offset = offset;
|
||||
image_fd->shared_cur = 0;
|
||||
image->fds = image_fd;
|
||||
image->size = image_fd->size;
|
||||
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, parts) < 0 )
|
||||
if ( image_append(image, type, device, hwrevs, version, layout) < 0 )
|
||||
return NULL;
|
||||
|
||||
if ( ! noverify && image->hash != hash ) {
|
||||
@@ -416,13 +335,9 @@ void image_free(struct image * image) {
|
||||
if ( ! image )
|
||||
return;
|
||||
|
||||
while ( image->fds ) {
|
||||
struct image_fd * next = image->fds->next;
|
||||
if ( ! image->fds->is_shared_fd )
|
||||
close(image->fds->fd);
|
||||
free(image->fds->orig_filename);
|
||||
free(image->fds);
|
||||
image->fds = next;
|
||||
if ( ! image->is_shared_fd ) {
|
||||
close(image->fd);
|
||||
image->fd = -1;
|
||||
}
|
||||
|
||||
while ( image->devices ) {
|
||||
@@ -432,15 +347,9 @@ void image_free(struct image * image) {
|
||||
image->devices = next;
|
||||
}
|
||||
|
||||
while ( image->parts ) {
|
||||
struct image_part * next = image->parts->next;
|
||||
free(image->parts->name);
|
||||
free(image->parts);
|
||||
image->parts = next;
|
||||
}
|
||||
|
||||
free(image->version);
|
||||
free(image->layout);
|
||||
free(image->orig_filename);
|
||||
|
||||
free(image);
|
||||
|
||||
@@ -449,122 +358,74 @@ void image_free(struct image * image) {
|
||||
void image_seek(struct image * image, size_t whence) {
|
||||
|
||||
off_t offset;
|
||||
size_t start = 0;
|
||||
struct image_fd * image_fd = image->fds;
|
||||
|
||||
image->cur = whence;
|
||||
|
||||
if ( whence > image->size ) {
|
||||
ERROR("Seek in image failed: Position end of the image");
|
||||
if ( whence > image->size )
|
||||
return;
|
||||
}
|
||||
|
||||
while ( image_fd ) {
|
||||
if ( ( whence >= start && whence < start + image_fd->size ) || ! image_fd->next )
|
||||
break;
|
||||
start += image_fd->size;
|
||||
image_fd = image_fd->next;
|
||||
}
|
||||
|
||||
if ( whence - start >= image_fd->size - image_fd->align ) {
|
||||
offset = lseek(image_fd->fd, image_fd->size - image_fd->align, SEEK_SET);
|
||||
if ( whence >= image->size - image->align ) {
|
||||
offset = lseek(image->fd, image->size - image->align - 1, SEEK_SET);
|
||||
image->acur = whence - ( image->size - image->align );
|
||||
} else {
|
||||
offset = lseek(image_fd->fd, image_fd->offset + whence - start, SEEK_SET);
|
||||
offset = lseek(image->fd, image->offset + whence, SEEK_SET);
|
||||
image->acur = 0;
|
||||
}
|
||||
|
||||
if ( offset == (off_t)-1 )
|
||||
ERROR_INFO("Seek in file %s failed", (image_fd->orig_filename ? image_fd->orig_filename : "(unknown)"));
|
||||
else if ( image_fd->is_shared_fd )
|
||||
image_fd->shared_cur = offset;
|
||||
ERROR_INFO("Seek in file %s failed", (image->orig_filename ? image->orig_filename : "(unknown)"));
|
||||
|
||||
IMAGE_STORE_CUR(image);
|
||||
|
||||
}
|
||||
|
||||
size_t image_read(struct image * image, void * buf, size_t count) {
|
||||
|
||||
size_t cur;
|
||||
ssize_t ret;
|
||||
off_t offset;
|
||||
size_t new_count = 0;
|
||||
size_t ret_count = 0;
|
||||
size_t start = 0;
|
||||
struct image_fd * image_fd = image->fds;
|
||||
|
||||
while ( image_fd ) {
|
||||
if ( ( image->cur >= start && image->cur < start + image_fd->size ) || ! image_fd->next )
|
||||
break;
|
||||
start += image_fd->size;
|
||||
image_fd = image_fd->next;
|
||||
}
|
||||
IMAGE_RESTORE_CUR(image);
|
||||
|
||||
if ( image_fd->is_shared_fd ) {
|
||||
if ( lseek(image_fd->fd, image_fd->shared_cur, SEEK_SET) != image_fd->shared_cur ) {
|
||||
ERROR_INFO("Cannot restore offset of file %s", (image_fd->orig_filename ? image_fd->orig_filename : "(unknown)"));
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
while ( count > 0 ) {
|
||||
if ( ret_count == count )
|
||||
return ret_count;
|
||||
|
||||
if ( image->cur < start + image_fd->size - image_fd->align ) {
|
||||
offset = lseek(image->fd, 0, SEEK_CUR);
|
||||
if ( offset == (off_t)-1 ) {
|
||||
ERROR_INFO("Cannot get offset of file %s", (image->orig_filename ? image->orig_filename : "(unknown)"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( image->cur + count > start + image_fd->size - image_fd->align )
|
||||
new_count = start + image_fd->size - image_fd->align - image->cur;
|
||||
else
|
||||
new_count = count;
|
||||
cur = offset - image->offset;
|
||||
|
||||
ret = read(image_fd->fd, buf, new_count);
|
||||
if ( ret <= 0 )
|
||||
break;
|
||||
if ( image->align && cur == image->size - image->align && image->acur < image->align ) {
|
||||
|
||||
count -= ret;
|
||||
buf = (unsigned char *)buf + ret;
|
||||
ret_count += ret;
|
||||
image->cur += ret;
|
||||
if ( image->acur + count - ret_count > image->align )
|
||||
new_count = image->align - image->acur;
|
||||
else
|
||||
new_count = count - ret_count;
|
||||
|
||||
if ( image_fd->is_shared_fd )
|
||||
image_fd->shared_cur += ret;
|
||||
|
||||
if ( (size_t)ret != new_count )
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
if ( image_fd->align > 0 && count > 0 && image->cur < start + image_fd->size ) {
|
||||
|
||||
if ( count > image_fd->align )
|
||||
new_count = image_fd->align;
|
||||
else
|
||||
new_count = count;
|
||||
|
||||
if ( image->cur + new_count > start + image_fd->size )
|
||||
new_count = start + image_fd->size - image->cur;
|
||||
|
||||
memset(buf, 0xFF, new_count);
|
||||
ret = new_count;
|
||||
|
||||
count -= ret;
|
||||
buf = (unsigned char *)buf + ret;
|
||||
ret_count += ret;
|
||||
image->cur += ret;
|
||||
|
||||
}
|
||||
|
||||
if ( image->cur == start + image_fd->size ) {
|
||||
|
||||
start += image_fd->size;
|
||||
image_fd = image_fd->next;
|
||||
|
||||
if ( ! image_fd )
|
||||
break;
|
||||
|
||||
offset = lseek(image_fd->fd, image_fd->offset, SEEK_SET);
|
||||
if ( offset == (off_t)-1 ) {
|
||||
ERROR_INFO("Seek in file %s failed", (image_fd->orig_filename ? image_fd->orig_filename : "(unknown)"));
|
||||
break;
|
||||
} else if ( image_fd->is_shared_fd ) {
|
||||
image_fd->shared_cur = offset;
|
||||
}
|
||||
|
||||
}
|
||||
memset((unsigned char *)buf+ret_count, 0xFF, new_count);
|
||||
ret_count += new_count;
|
||||
image->acur += new_count;
|
||||
|
||||
}
|
||||
|
||||
@@ -655,9 +516,6 @@ static const char * image_types[] = {
|
||||
[IMAGE_CMT_2ND] = "cmt-2nd",
|
||||
[IMAGE_CMT_ALGO] = "cmt-algo",
|
||||
[IMAGE_CMT_MCUSW] = "cmt-mcusw",
|
||||
[IMAGE_1ST] = "1st",
|
||||
[IMAGE_CERT_SW] = "cert-sw",
|
||||
[IMAGE_APE_ALGO] = "ape-algo",
|
||||
};
|
||||
|
||||
enum image_type image_type_from_data(struct image * image) {
|
||||
@@ -748,18 +606,11 @@ int image_hwrev_is_valid(struct image * image, int16_t hwrev) {
|
||||
|
||||
void image_print_info(struct image * image) {
|
||||
|
||||
int i = 0;
|
||||
const char * str;
|
||||
struct image_fd * image_fd = image->fds;
|
||||
struct image_part * part = image->parts;
|
||||
struct device_list * device = image->devices;
|
||||
|
||||
if ( image->fds && image->fds->orig_filename ) {
|
||||
if ( image->fds->next )
|
||||
printf("Multifile image:\n");
|
||||
else
|
||||
printf("File: %s\n", image->fds->orig_filename);
|
||||
}
|
||||
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");
|
||||
@@ -771,20 +622,6 @@ void image_print_info(struct image * image) {
|
||||
if ( image->layout )
|
||||
printf(" Image layout: included\n");
|
||||
|
||||
while ( part ) {
|
||||
|
||||
if ( image->fds && image->fds->orig_filename && image->fds->next )
|
||||
printf("File: %s\n", (image_fd && image_fd->orig_filename) ? image_fd->orig_filename : "(unknown)");
|
||||
|
||||
printf(" Image part %d name: %s\n", i, part->name ? part->name : "(empty)");
|
||||
printf(" Image part %d size: %d bytes\n", i, part->size);
|
||||
|
||||
part = part->next;
|
||||
image_fd = image_fd ? image_fd->next : NULL;
|
||||
++i;
|
||||
|
||||
}
|
||||
|
||||
while ( device ) {
|
||||
|
||||
char * str2 = NULL;
|
||||
|
||||
+11
-29
@@ -37,30 +37,9 @@ enum image_type {
|
||||
IMAGE_CMT_2ND,
|
||||
IMAGE_CMT_ALGO,
|
||||
IMAGE_CMT_MCUSW,
|
||||
IMAGE_1ST,
|
||||
IMAGE_CERT_SW,
|
||||
IMAGE_APE_ALGO,
|
||||
IMAGE_COUNT,
|
||||
};
|
||||
|
||||
struct image_part {
|
||||
struct image_part * next;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
char * name;
|
||||
};
|
||||
|
||||
struct image_fd {
|
||||
struct image_fd * next;
|
||||
int fd;
|
||||
int is_shared_fd;
|
||||
off_t shared_cur;
|
||||
uint32_t size;
|
||||
uint32_t align;
|
||||
size_t offset;
|
||||
char * orig_filename;
|
||||
};
|
||||
|
||||
struct image {
|
||||
enum image_type type;
|
||||
struct device_list * devices;
|
||||
@@ -68,9 +47,14 @@ struct image {
|
||||
char * layout;
|
||||
uint16_t hash;
|
||||
uint32_t size;
|
||||
struct image_part * parts;
|
||||
struct image_fd * fds;
|
||||
|
||||
int fd;
|
||||
int is_shared_fd;
|
||||
uint32_t align;
|
||||
size_t offset;
|
||||
size_t cur;
|
||||
size_t acur;
|
||||
char * orig_filename;
|
||||
};
|
||||
|
||||
struct image_list {
|
||||
@@ -79,11 +63,9 @@ struct image_list {
|
||||
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_part * parts);
|
||||
struct image * image_alloc_from_files(const char ** files, int count, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts);
|
||||
struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts);
|
||||
struct image * image_alloc_from_fds(int * fds, const char ** orig_filenames, int count, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout, struct image_part * parts);
|
||||
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_part * parts);
|
||||
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_fd(int fd, const char * orig_filename, 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);
|
||||
@@ -94,7 +76,7 @@ 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, int part_num);
|
||||
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);
|
||||
|
||||
+65
-275
@@ -19,7 +19,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/types.h>
|
||||
@@ -199,6 +198,14 @@ enum device local_get_device(void) {
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -220,18 +227,15 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size = snprintf(NULL, 0, "nanddump --omitoob -s %d -l %d -f %s /dev/mtd%d", offset, length, file, mtd);
|
||||
size = snprintf(NULL, 0, "nanddump -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 --omitoob -s %d -l %d -f %s /dev/mtd%d", offset, length, file, mtd);
|
||||
snprintf(command, size+1, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
|
||||
|
||||
if ( ! simulate )
|
||||
ret = system(command);
|
||||
else
|
||||
ret = 0;
|
||||
ret = system(command);
|
||||
|
||||
free(command);
|
||||
|
||||
@@ -239,77 +243,52 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
|
||||
|
||||
}
|
||||
|
||||
static FILE * local_nandwrite(int mtd, int offset) {
|
||||
|
||||
char * command;
|
||||
FILE * stream;
|
||||
size_t size;
|
||||
|
||||
size = snprintf(NULL, 0, "nandwrite -a -s %d -p /dev/mtd%d -", offset, mtd);
|
||||
|
||||
command = malloc(size+1);
|
||||
if ( ! command )
|
||||
return NULL;
|
||||
|
||||
snprintf(command, size+1, "nandwrite -a -s %d -p /dev/mtd%d -", offset, mtd);
|
||||
|
||||
if ( ! simulate )
|
||||
stream = popen(command, "w");
|
||||
else
|
||||
stream = NULL;
|
||||
|
||||
free(command);
|
||||
|
||||
return stream;
|
||||
|
||||
}
|
||||
|
||||
struct nandpart_args {
|
||||
unsigned int mtd;
|
||||
unsigned int offset;
|
||||
unsigned int length;
|
||||
unsigned int header;
|
||||
struct nanddump_args {
|
||||
int valid;
|
||||
int mtd;
|
||||
int offset;
|
||||
int length;
|
||||
};
|
||||
|
||||
static struct nandpart_args nandpart_rx51[] = {
|
||||
[IMAGE_XLOADER] = { 0, 0x00000000, 0x00004000, 0x00000000 },
|
||||
[IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
|
||||
[IMAGE_KERNEL] = { 3, 0x00000000, 0x00200000, 0x00000800 },
|
||||
[IMAGE_INITFS] = { 4, 0x00000000, 0x00200000, 0x00000000 },
|
||||
[IMAGE_ROOTFS] = { 5, 0x00000000, 0x0fb40000, 0x00000000 },
|
||||
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 nandpart_args nandpart_rx4x[] = {
|
||||
[IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 },
|
||||
[IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
|
||||
[IMAGE_KERNEL] = { 2, 0x00000000, 0x00220000, 0x00000800 },
|
||||
[IMAGE_INITFS] = { 3, 0x00000000, 0x00400000, 0x00000000 },
|
||||
[IMAGE_ROOTFS] = { 4, 0x00000000, 0x0f960000, 0x00000000 },
|
||||
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 nandpart_args nandpart_old[] = {
|
||||
[IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 },
|
||||
[IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
|
||||
[IMAGE_KERNEL] = { 2, 0x00000000, 0x00200000, 0x00000800 },
|
||||
[IMAGE_INITFS] = { 3, 0x00000000, 0x00200000, 0x00000000 },
|
||||
[IMAGE_ROOTFS] = { 4, 0x00000000, 0x0fb80000, 0x00000000 },
|
||||
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 nand_device {
|
||||
struct nanddump_device {
|
||||
size_t count;
|
||||
struct nandpart_args * args;
|
||||
struct nanddump_args * args;
|
||||
};
|
||||
|
||||
#define NAND_DEVICE(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array }
|
||||
#define NANDDUMP(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array }
|
||||
|
||||
static struct nand_device nand_device[] = {
|
||||
NAND_DEVICE(DEVICE_SU_18, nandpart_old),
|
||||
NAND_DEVICE(DEVICE_RX_34, nandpart_old),
|
||||
NAND_DEVICE(DEVICE_RX_44, nandpart_rx4x),
|
||||
NAND_DEVICE(DEVICE_RX_48, nandpart_rx4x),
|
||||
NAND_DEVICE(DEVICE_RX_51, nandpart_rx51),
|
||||
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
|
||||
@@ -401,13 +380,10 @@ static void local_find_internal_mydocs(int * maj, int * min) {
|
||||
|
||||
int local_dump_image(enum image_type image, const char * file) {
|
||||
|
||||
unsigned char buf[20];
|
||||
int ret = -1;
|
||||
int fd = -1;
|
||||
int header = 0;
|
||||
unsigned char * addr = NULL;
|
||||
off_t nlen = (off_t)-1;
|
||||
off_t len;
|
||||
off_t nlen, len;
|
||||
int align;
|
||||
int maj, min;
|
||||
|
||||
@@ -439,49 +415,17 @@ int local_dump_image(enum image_type image, const char * file) {
|
||||
|
||||
} else {
|
||||
|
||||
if ( device >= sizeof(nand_device)/sizeof(nand_device[0]) ) {
|
||||
if ( device >= sizeof(nanddump)/sizeof(nanddump[0]) ) {
|
||||
ERROR("Unsupported device");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if ( image >= nand_device[device].count ) {
|
||||
if ( image >= nanddump[device].count ) {
|
||||
ERROR("Unsupported image type: %s", image_type_to_string(image));
|
||||
goto clean;
|
||||
}
|
||||
|
||||
header = nand_device[device].args[image].header;
|
||||
|
||||
if ( header > 0 ) {
|
||||
|
||||
ret = local_nanddump(file, nand_device[device].args[image].mtd, nand_device[device].args[image].offset, header);
|
||||
if ( ret != 0 ) {
|
||||
if ( ! simulate )
|
||||
unlink(file);
|
||||
ret = -1;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if ( ! simulate ) {
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if ( fd >= 0 ) {
|
||||
if ( read(fd, buf, 20) == 20 ) {
|
||||
if ( memcmp(buf, "NOLO!img\x02\x00\x00\x00\x00\x00\x00\x00", 16) == 0 )
|
||||
nlen = ((unsigned int)buf[16] << 0) | ((unsigned int)buf[17] << 8) | ((unsigned int)buf[18] << 16) | ((unsigned int)buf[19] << 24);
|
||||
else if ( memcmp(buf, "NOLO img", 8) == 0 )
|
||||
nlen = ((unsigned int)buf[8] << 0) | ((unsigned int)buf[9] << 8) | ((unsigned int)buf[10] << 16) | ((unsigned int)buf[11] << 24);
|
||||
}
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
unlink(file);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = local_nanddump(file, nand_device[device].args[image].mtd, nand_device[device].args[image].offset + header, nand_device[device].args[image].length - header);
|
||||
ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset, nanddump[device].args[image].length);
|
||||
|
||||
}
|
||||
|
||||
@@ -490,9 +434,6 @@ int local_dump_image(enum image_type image, const char * file) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if ( simulate )
|
||||
goto clean;
|
||||
|
||||
fd = open(file, O_RDWR);
|
||||
if ( fd < 0 )
|
||||
goto clean;
|
||||
@@ -501,35 +442,31 @@ int local_dump_image(enum image_type image, const char * file) {
|
||||
if ( len == (off_t)-1 || len == 0 )
|
||||
goto clean;
|
||||
|
||||
if ( header <= 0 || nlen == (off_t)-1 ) {
|
||||
addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if ( addr == MAP_FAILED )
|
||||
addr = NULL;
|
||||
|
||||
if ( addr == MAP_FAILED )
|
||||
addr = NULL;
|
||||
if ( ! addr )
|
||||
goto clean;
|
||||
|
||||
if ( ! addr )
|
||||
goto clean;
|
||||
for ( nlen = len; nlen > 0; --nlen )
|
||||
if ( addr[nlen-1] != 0xFF )
|
||||
break;
|
||||
|
||||
for ( nlen = len; nlen > 0; --nlen )
|
||||
if ( addr[nlen-1] != 0xFF )
|
||||
break;
|
||||
for ( ; nlen > 0; --nlen )
|
||||
if ( addr[nlen-1] != 0x00 )
|
||||
break;
|
||||
|
||||
for ( ; nlen > 0; --nlen )
|
||||
if ( addr[nlen-1] != 0x00 )
|
||||
break;
|
||||
if ( image == IMAGE_MMC )
|
||||
align = 8;
|
||||
else
|
||||
align = 7;
|
||||
|
||||
if ( image == IMAGE_MMC )
|
||||
align = 8;
|
||||
else
|
||||
align = 7;
|
||||
if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
|
||||
nlen = ((nlen >> align) + 1) << align;
|
||||
|
||||
if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
|
||||
nlen = ((nlen >> align) + 1) << align;
|
||||
|
||||
}
|
||||
|
||||
if ( header <= 0 && nlen == 0 ) {
|
||||
if ( nlen == 0 ) {
|
||||
printf("File %s is empty, removing it...\n", file);
|
||||
unlink(file);
|
||||
} else if ( nlen != len ) {
|
||||
@@ -550,153 +487,6 @@ clean:
|
||||
|
||||
}
|
||||
|
||||
int local_flash_image(struct image * image) {
|
||||
|
||||
unsigned char buf[0x20000];
|
||||
unsigned int remaining, size;
|
||||
void (*sighandler)(int);
|
||||
int min, maj, fd;
|
||||
FILE * stream;
|
||||
int ret;
|
||||
|
||||
printf("Flash image:\n");
|
||||
image_print_info(image);
|
||||
|
||||
if ( image->type == IMAGE_MMC ) {
|
||||
|
||||
maj = -1;
|
||||
min = -1;
|
||||
|
||||
local_find_internal_mydocs(&maj, &min);
|
||||
if ( maj == -1 || min == -1 )
|
||||
ERROR_RETURN("Cannot find MyDocs mmc device: Slot 'internal' was not found", -1);
|
||||
|
||||
VERBOSE("Detected internal MyDocs mmc device: major=%d minor=%d\n", maj, min);
|
||||
|
||||
fd = disk_open_dev(maj, min, 1, simulate ? 1 : 0);
|
||||
if ( fd < 0 )
|
||||
ERROR_RETURN("Cannot open MyDocs mmc device in /dev/", -1);
|
||||
|
||||
ret = disk_flash_dev(fd, image);
|
||||
|
||||
close(fd);
|
||||
|
||||
} else {
|
||||
|
||||
if ( device >= sizeof(nand_device)/sizeof(nand_device[0]) )
|
||||
ERROR_RETURN("Unsupported device", -1);
|
||||
|
||||
if ( image->type >= nand_device[device].count ) {
|
||||
ERROR("Unsupported image type: %s", image_type_to_string(image->type));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( image->size > nand_device[device].args[image->type].length - nand_device[device].args[image->type].header )
|
||||
ERROR_RETURN("Image is too big", -1);
|
||||
|
||||
printf("Using nandwrite for flashing %s image...\n", image_type_to_string(image->type));
|
||||
|
||||
stream = local_nandwrite(nand_device[device].args[image->type].mtd, nand_device[device].args[image->type].offset);
|
||||
if ( ! simulate && ! stream )
|
||||
ERROR_RETURN("Cannot start nandwrite process", -1);
|
||||
|
||||
ret = 0;
|
||||
sighandler = signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/* Write NOLO!img or NOLO img header with size */
|
||||
if ( nand_device[device].args[image->type].header > 0 ) {
|
||||
if ( device == DEVICE_RX_51 ) {
|
||||
memcpy(buf, "NOLO!img\x02\x00\x00\x00\x00\x00\x00\x00", 16);
|
||||
buf[16] = (image->size >> 0) & 0xFF;
|
||||
buf[17] = (image->size >> 8) & 0xFF;
|
||||
buf[18] = (image->size >> 16) & 0xFF;
|
||||
buf[19] = (image->size >> 24) & 0xFF;
|
||||
size = 20;
|
||||
} else {
|
||||
memcpy(buf, "NOLO img", 8);
|
||||
buf[ 8] = (image->size >> 0) & 0xFF;
|
||||
buf[ 9] = (image->size >> 8) & 0xFF;
|
||||
buf[10] = (image->size >> 16) & 0xFF;
|
||||
buf[11] = (image->size >> 24) & 0xFF;
|
||||
size = 12;
|
||||
}
|
||||
|
||||
if ( ! simulate ) {
|
||||
if ( fwrite(buf, size, 1, stream) != 1 ) {
|
||||
ret = -1;
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
remaining = nand_device[device].args[image->type].header - size;
|
||||
while ( remaining > 0 ) {
|
||||
size = remaining < sizeof(buf) ? remaining : sizeof(buf);
|
||||
if ( ! simulate ) {
|
||||
if ( fwrite(buf, size, 1, stream) != 1 ) {
|
||||
ret = -1;
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
remaining -= size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write image data */
|
||||
image_seek(image, 0);
|
||||
remaining = image->size;
|
||||
while ( remaining > 0 ) {
|
||||
size = remaining < sizeof(buf) ? remaining : sizeof(buf);
|
||||
size = image_read(image, buf, size);
|
||||
if ( size == 0 ) {
|
||||
ERROR("Failed to read image");
|
||||
ret = -1;
|
||||
goto clean;
|
||||
}
|
||||
if ( ! simulate ) {
|
||||
if ( fwrite(buf, size, 1, stream) != 1 ) {
|
||||
ret = -1;
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
remaining -= size;
|
||||
}
|
||||
|
||||
/* Write filler zeros to clear previous data */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
remaining = nand_device[device].args[image->type].length - (image->size + nand_device[device].args[image->type].header);
|
||||
while ( remaining > 0 ) {
|
||||
size = remaining < sizeof(buf) ? remaining : sizeof(buf);
|
||||
if ( ! simulate ) {
|
||||
if ( fwrite(buf, size, 1, stream) != 1 ) {
|
||||
ret = -1;
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
remaining -= size;
|
||||
}
|
||||
|
||||
clean:
|
||||
if ( ! simulate ) {
|
||||
if ( ret == 0 )
|
||||
ret = pclose(stream);
|
||||
else
|
||||
pclose(stream);
|
||||
}
|
||||
|
||||
signal(SIGPIPE, sighandler);
|
||||
|
||||
if ( ret != 0 )
|
||||
ERROR("Flashing failed");
|
||||
}
|
||||
|
||||
if ( ret == 0 )
|
||||
printf("Done\n");
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int local_check_badblocks(const char * device) {
|
||||
|
||||
ERROR("Not implemented yet");
|
||||
|
||||
+20
-133
@@ -77,14 +77,12 @@ static void show_usage(void) {
|
||||
"Input image specification:\n"
|
||||
" -M file specify fiasco image\n"
|
||||
" -m arg specify normal image\n"
|
||||
" arg is [[[dev:[hw:]]ver:]type:]file[@name][#file2[@name2]...][%%lay]\n"
|
||||
" arg is [[[dev:[hw:]]ver:]type:]file[%%lay]\n"
|
||||
" dev is device name string (default: empty)\n"
|
||||
" hw are comma separated list of HW revisions (default: empty)\n"
|
||||
" ver is image version string (default: empty)\n"
|
||||
" type is image type (default: autodetect)\n"
|
||||
" file is image file name\n"
|
||||
" fileN is file name of the Nth image part\n"
|
||||
" nameN is name of the Nth image part (default: none)\n"
|
||||
" lay is layout file name (default: none)\n"
|
||||
"\n"
|
||||
|
||||
@@ -145,34 +143,25 @@ int simulate;
|
||||
int noverify;
|
||||
int verbose;
|
||||
|
||||
/* arg = [[[dev:[hw:]]ver:]type:]file[@name][#file2[@name2][#file3[@name3]...]][%lay] */
|
||||
/* arg = [[[dev:[hw:]]ver:]type:]file[%%lay] */
|
||||
static void parse_image_arg(char * arg, struct image_list ** image_first) {
|
||||
|
||||
struct stat st;
|
||||
struct image * image;
|
||||
struct image_fd * image_fd;
|
||||
struct image_part * image_part;
|
||||
struct image_part * image_parts;
|
||||
char * file;
|
||||
const char ** files;
|
||||
char * type;
|
||||
char * device;
|
||||
char * hwrevs;
|
||||
char * version;
|
||||
char * layout;
|
||||
char * part_files;
|
||||
char * layout_file;
|
||||
char * name;
|
||||
char * ptr;
|
||||
uint32_t offset;
|
||||
int count;
|
||||
int fd;
|
||||
|
||||
/* First check if arg is file, then try to parse arg format */
|
||||
fd = open(arg, O_RDONLY);
|
||||
if ( fd >= 0 ) {
|
||||
if ( fstat(fd, &st) == 0 && !S_ISDIR(st.st_mode) ) {
|
||||
image = image_alloc_from_fd(fd, arg, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
image = image_alloc_from_fd(fd, arg, NULL, NULL, NULL, NULL, NULL);
|
||||
if ( ! image ) {
|
||||
ERROR("Cannot load image file %s", arg);
|
||||
exit(1);
|
||||
@@ -186,12 +175,7 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
part_files = strchr(arg, '#');
|
||||
if ( part_files )
|
||||
*(part_files++) = 0;
|
||||
|
||||
layout_file = part_files ? part_files : arg;
|
||||
layout_file = strchr(layout_file, '%');
|
||||
layout_file = strchr(arg, '%');
|
||||
if ( layout_file )
|
||||
*(layout_file++) = 0;
|
||||
|
||||
@@ -253,85 +237,16 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
count = 0;
|
||||
ptr = part_files;
|
||||
while ( ptr ) {
|
||||
count++;
|
||||
ptr = strchr(ptr, '#');
|
||||
if ( ptr )
|
||||
ptr++;
|
||||
}
|
||||
image = image_alloc_from_file(file, type, device, hwrevs, version, layout);
|
||||
|
||||
files = calloc(count+1, sizeof(*files));
|
||||
if ( ! files ) {
|
||||
ALLOC_ERROR();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
name = strchr(file, '@');
|
||||
if ( name ) {
|
||||
*name = 0;
|
||||
name++;
|
||||
}
|
||||
|
||||
if ( count > 0 || name ) {
|
||||
image_part = calloc(1, sizeof(*image_part));
|
||||
if ( ! image_part ) {
|
||||
ALLOC_ERROR();
|
||||
exit(1);
|
||||
}
|
||||
image_part->name = name ? strdup(name) : NULL;
|
||||
image_parts = image_part;
|
||||
} else {
|
||||
image_part = NULL;
|
||||
image_parts = NULL;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
files[count++] = file;
|
||||
|
||||
while ( part_files ) {
|
||||
ptr = strchr(part_files, '#');
|
||||
if ( ptr ) {
|
||||
*ptr = 0;
|
||||
ptr++;
|
||||
}
|
||||
name = strchr(part_files, '@');
|
||||
if ( name ) {
|
||||
*name = 0;
|
||||
name++;
|
||||
}
|
||||
image_part->next = calloc(1, sizeof(*image_part));
|
||||
if ( ! image_part->next ) {
|
||||
ALLOC_ERROR();
|
||||
exit(1);
|
||||
}
|
||||
image_part = image_part->next;
|
||||
image_part->name = name ? strdup(name) : NULL;
|
||||
files[count++] = part_files;
|
||||
part_files = ptr;
|
||||
}
|
||||
|
||||
image = image_alloc_from_files(files, count, type, device, hwrevs, version, layout, image_parts);
|
||||
free(files);
|
||||
free(layout);
|
||||
if ( layout )
|
||||
free(layout);
|
||||
|
||||
if ( ! image ) {
|
||||
ERROR("Cannot load image file %s", file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
image_part = image_parts;
|
||||
image_fd = image->fds;
|
||||
offset = 0;
|
||||
while ( image_part && image_fd ) {
|
||||
image_part->offset = offset;
|
||||
image_part->size = image_fd->size;
|
||||
offset += image_part->size;
|
||||
image_part = image_part->next;
|
||||
image_fd = image_fd->next;
|
||||
}
|
||||
|
||||
image_list_add(image_first, image);
|
||||
|
||||
}
|
||||
@@ -506,13 +421,9 @@ int main(int argc, char **argv) {
|
||||
enum device detected_device = DEVICE_UNKNOWN;
|
||||
int16_t detected_hwrev = -1;
|
||||
|
||||
struct stat st;
|
||||
|
||||
int i;
|
||||
char buf[512];
|
||||
char * ptr = NULL;
|
||||
char * ptr1 = NULL;
|
||||
char * ptr2 = NULL;
|
||||
char * tmp = NULL;
|
||||
|
||||
char nolo_ver[512];
|
||||
@@ -912,7 +823,7 @@ int main(int argc, char **argv) {
|
||||
while ( image_ptr ) {
|
||||
struct image_list * next = image_ptr->next;
|
||||
if ( image_ptr->image->type == IMAGE_UNKNOWN ) {
|
||||
WARNING("Removing unknown image (specified by %s %s)", (image_ptr->image->fds && image_ptr->image->fds->orig_filename) ? "file" : "fiasco", (image_ptr->image->fds && image_ptr->image->fds->orig_filename) ? image_ptr->image->fds->orig_filename : "image");
|
||||
WARNING("Removing unknown image (specified by %s %s)", image_ptr->image->orig_filename ? "file" : "fiasco", image_ptr->image->orig_filename ? image_ptr->image->orig_filename : "image");
|
||||
if ( image_ptr == image_first )
|
||||
image_first = next;
|
||||
if ( fiasco_in && image_ptr == fiasco_in->first )
|
||||
@@ -1123,9 +1034,9 @@ int main(int argc, char **argv) {
|
||||
/* filter images by device & hwrev */
|
||||
if ( detected_device )
|
||||
filter_images_by_device(dev->detected_device, &image_first);
|
||||
if ( detected_hwrev > 0 )
|
||||
if ( detected_hwrev )
|
||||
filter_images_by_hwrev(dev->detected_hwrev, &image_first);
|
||||
if ( fiasco_in && ( detected_device || detected_hwrev > 0 ) )
|
||||
if ( fiasco_in && ( detected_device || detected_hwrev ) )
|
||||
fiasco_in->first = image_first;
|
||||
|
||||
/* set kernel and initfs images for loading */
|
||||
@@ -1183,7 +1094,7 @@ int main(int argc, char **argv) {
|
||||
if ( dev_load ) {
|
||||
if ( image_kernel ) {
|
||||
ret = dev_load_image(dev, image_kernel->image);
|
||||
if ( ret == -EAGAIN )
|
||||
if ( ret < 0 )
|
||||
goto again;
|
||||
|
||||
if ( image_kernel == image_first )
|
||||
@@ -1197,7 +1108,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
if ( image_initfs ) {
|
||||
ret = dev_load_image(dev, image_initfs->image);
|
||||
if ( ret == -EAGAIN )
|
||||
if ( ret < 0 )
|
||||
goto again;
|
||||
|
||||
if ( image_initfs == image_first )
|
||||
@@ -1216,7 +1127,7 @@ int main(int argc, char **argv) {
|
||||
while ( image_ptr ) {
|
||||
struct image_list * next = image_ptr->next;
|
||||
ret = dev_flash_image(dev, image_ptr->image);
|
||||
if ( ret == -EAGAIN )
|
||||
if ( ret < 0 )
|
||||
goto again;
|
||||
|
||||
if ( image_ptr == image_first )
|
||||
@@ -1348,12 +1259,11 @@ int main(int argc, char **argv) {
|
||||
|
||||
for ( i = 0; i < IMAGE_COUNT; ++i ) {
|
||||
|
||||
if ( ! image_tmp_name(i) || ( stat(image_tmp_name(i), &st) < 0 && errno == ENOENT ) )
|
||||
if ( ! image_tmp_name(i) )
|
||||
continue;
|
||||
|
||||
buf[0] = 0;
|
||||
if ( dev->detected_hwrev > 0 )
|
||||
snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev);
|
||||
snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev);
|
||||
|
||||
switch ( i ) {
|
||||
case IMAGE_2ND:
|
||||
@@ -1383,9 +1293,7 @@ int main(int argc, char **argv) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: add support for dumping mmc layout and also other mmc partitions as image data parts */
|
||||
|
||||
image_dump = image_alloc_from_file(image_tmp_name(i), image_type_to_string(i), device_to_string(dev->detected_device), buf, ptr, NULL, NULL);
|
||||
image_dump = image_alloc_from_file(image_tmp_name(i), image_type_to_string(i), device_to_string(dev->detected_device), buf, ptr, NULL);
|
||||
|
||||
if ( ! image_dump )
|
||||
continue;
|
||||
@@ -1456,20 +1364,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
snprintf(buf, sizeof(buf), "%s", image_type_to_string(i));
|
||||
ptr1 = buf + strlen(buf);
|
||||
|
||||
if ( dev->detected_device ) {
|
||||
snprintf(ptr1, sizeof(buf)-(ptr1-buf), "-%s", device_to_string(dev->detected_device));
|
||||
ptr1 += strlen(ptr1);
|
||||
}
|
||||
|
||||
if ( dev->detected_hwrev > 0 )
|
||||
snprintf(ptr1, sizeof(buf)-(ptr1-buf), ":%hd", dev->detected_hwrev);
|
||||
ptr2 = ptr1 + strlen(ptr1);
|
||||
|
||||
if ( ptr && ptr[0] )
|
||||
snprintf(ptr2, sizeof(buf)-(ptr2-buf), "_%s", ptr);
|
||||
snprintf(buf, sizeof(buf), "%s-%s:%hd_%s", image_type_to_string(i), device_to_string(dev->detected_device), dev->detected_hwrev, ptr);
|
||||
|
||||
rename_ret = rename(image_tmp_name(i), buf);
|
||||
rename_errno = errno;
|
||||
@@ -1484,21 +1379,13 @@ int main(int argc, char **argv) {
|
||||
errno = rename_errno;
|
||||
ERROR_INFO("Renaming failed");
|
||||
|
||||
*ptr2 = 0;
|
||||
buf[0] = 0;
|
||||
snprintf(buf, sizeof(buf), "%s-%s_%s", image_type_to_string(i), device_to_string(dev->detected_device), ptr);
|
||||
printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf);
|
||||
|
||||
if ( rename(image_tmp_name(i), buf) < 0 ) {
|
||||
|
||||
if ( rename(image_tmp_name(i), buf) < 0 )
|
||||
ERROR_INFO("Renaming failed");
|
||||
|
||||
*ptr1 = 0;
|
||||
printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf);
|
||||
|
||||
if ( rename(image_tmp_name(i), buf) < 0 )
|
||||
ERROR_INFO("Renaming failed");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-23
@@ -48,7 +48,7 @@ struct mkii_message {
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
static int mkii_send_receive(libusb_device_handle * udev, uint8_t type, struct mkii_message * in_msg, size_t data_size, struct mkii_message * out_msg, size_t out_size) {
|
||||
static int mkii_send_receive(usb_dev_handle * udev, uint8_t type, struct mkii_message * in_msg, size_t data_size, struct mkii_message * out_msg, size_t out_size) {
|
||||
|
||||
int ret;
|
||||
static uint8_t number = 0;
|
||||
@@ -59,13 +59,13 @@ static int mkii_send_receive(libusb_device_handle * udev, uint8_t type, struct m
|
||||
in_msg->num = number++;
|
||||
in_msg->type = type;
|
||||
|
||||
ret = usb_bulk_send(udev, USB_WRITE_EP, in_msg, data_size + sizeof(*in_msg), 5000);
|
||||
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)in_msg, data_size + sizeof(*in_msg), 5000);
|
||||
if ( ret < 0 )
|
||||
return ret;
|
||||
if ( (size_t)ret != data_size + sizeof(*in_msg) )
|
||||
return -1;
|
||||
|
||||
ret = usb_bulk_recv(udev, USB_READ_EP, out_msg, out_size, 5000);
|
||||
ret = usb_bulk_read(udev, USB_READ_EP, (char *)out_msg, out_size, 5000);
|
||||
if ( ret < 0 )
|
||||
return ret;
|
||||
|
||||
@@ -89,7 +89,6 @@ int mkii_init(struct usb_device_info * dev) {
|
||||
|
||||
char buf[2048];
|
||||
struct mkii_message * msg;
|
||||
struct libusb_config_descriptor * config;
|
||||
enum device device;
|
||||
int ret;
|
||||
char * newptr;
|
||||
@@ -160,10 +159,8 @@ int mkii_init(struct usb_device_info * dev) {
|
||||
printf("\n");
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if ( libusb_get_config_descriptor(libusb_get_device(dev->udev), 0, &config) == 0 ) {
|
||||
libusb_get_string_descriptor_ascii(dev->udev, config->iConfiguration, (unsigned char *)buf, sizeof(buf));
|
||||
libusb_free_config_descriptor(config);
|
||||
}
|
||||
if ( usb_device(dev->udev)->descriptor.bNumConfigurations >= 1 )
|
||||
usb_get_string_simple(dev->udev, usb_device(dev->udev)->config[0].iConfiguration, buf, sizeof(buf));
|
||||
if ( strncmp(buf, "Firmware Upgrade Configuration", sizeof("Firmware Upgrade Configuration")) == 0 )
|
||||
dev->data |= MKII_UPDATE_MODE;
|
||||
|
||||
@@ -216,18 +213,14 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||
msg1 = (struct mkii_message *)buf1;
|
||||
ptr = msg->data;
|
||||
|
||||
/* File data header */
|
||||
memcpy(ptr, "\x2E", 1);
|
||||
ptr += 1;
|
||||
/* Signature */
|
||||
memcpy(ptr, "\x2E\x19\x01\x01", 4);
|
||||
ptr += 4;
|
||||
|
||||
/* Length of file data */
|
||||
memcpy(ptr, "\x19", 1);
|
||||
/* Space */
|
||||
memcpy(ptr, "\x00", 1);
|
||||
ptr += 1;
|
||||
|
||||
/* File data (ignored): asic index: APE (0x01), device type: NAND (0x01), device index: 0 */
|
||||
memcpy(ptr, "\x01\x01\x00", 3);
|
||||
ptr += 3;
|
||||
|
||||
/* Hash */
|
||||
hash = htons(image->hash);
|
||||
memcpy(ptr, &hash, 2);
|
||||
@@ -246,7 +239,7 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||
memcpy(ptr, &size, 4);
|
||||
ptr += 4;
|
||||
|
||||
/* Load address (ignored) */
|
||||
/* Space */
|
||||
memcpy(ptr, "\x00\x00\x00\x00", 4);
|
||||
ptr += 4;
|
||||
|
||||
@@ -368,11 +361,6 @@ int mkii_reboot_device(struct usb_device_info * dev, int update) {
|
||||
if ( ret != 1 || msg->data[0] != 0 )
|
||||
ERROR_RETURN("Cannot send reboot command", -1);
|
||||
|
||||
if (dev->data & MKII_UPDATE_MODE)
|
||||
MSLEEP(100);
|
||||
else
|
||||
MSLEEP(3000);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
+31
-35
@@ -88,7 +88,7 @@ static void nolo_error_log(struct usb_device_info * dev, int only_clear) {
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
ret = libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_ERROR_LOG, 0, 0, (unsigned char *)buf, sizeof(buf), 2000);
|
||||
ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_ERROR_LOG, 0, 0, buf, sizeof(buf), 2000);
|
||||
if ( ret < 0 )
|
||||
break;
|
||||
|
||||
@@ -118,7 +118,7 @@ static int nolo_identify_string(struct usb_device_info * dev, const char * str,
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
ret = libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_IDENTIFY, 0, 0, (unsigned char *)buf, sizeof(buf), 2000);
|
||||
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);
|
||||
|
||||
@@ -148,10 +148,10 @@ static int nolo_set_string(struct usb_device_info * dev, char * str, char * arg)
|
||||
if ( simulate )
|
||||
return 0;
|
||||
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, (unsigned char *)str, strlen(str), 2000) < 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 ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_SET_STRING, 0, 0, (unsigned char *)arg, strlen(arg), 2000) < 0 )
|
||||
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;
|
||||
@@ -162,10 +162,10 @@ static int nolo_get_string(struct usb_device_info * dev, char * str, char * out,
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, (unsigned char *)str, strlen(str), 2000) < 0 )
|
||||
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, str, strlen(str), 2000) < 0 )
|
||||
return -1;
|
||||
|
||||
if ( ( ret = libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_GET_STRING, 0, 0, (unsigned char *)out, size-1, 2000) ) < 0 )
|
||||
if ( ( ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET_STRING, 0, 0, out, size-1, 2000) ) < 0 )
|
||||
return -1;
|
||||
|
||||
if ( (size_t)ret > size-1 )
|
||||
@@ -209,7 +209,7 @@ int nolo_init(struct usb_device_info * dev) {
|
||||
printf("Initializing NOLO...\n");
|
||||
|
||||
while ( val != 0 )
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_STATUS, 0, 0, (unsigned char *)&val, 4, 2000) < 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 */
|
||||
@@ -269,18 +269,14 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
|
||||
|
||||
ptr = buf;
|
||||
|
||||
/* File data header */
|
||||
memcpy(ptr, "\x2E", 1);
|
||||
ptr += 1;
|
||||
/* Signature */
|
||||
memcpy(ptr, "\x2E\x19\x01\x01", 4);
|
||||
ptr += 4;
|
||||
|
||||
/* Length of file data */
|
||||
memcpy(ptr, "\x19", 1);
|
||||
/* Space */
|
||||
memcpy(ptr, "\x00", 1);
|
||||
ptr += 1;
|
||||
|
||||
/* File data (ignored by NOLO): asic index: APE (0x01), device type: NAND (0x01), device index: 0 */
|
||||
memcpy(ptr, "\x01\x01\x00", 3);
|
||||
ptr += 3;
|
||||
|
||||
/* Hash */
|
||||
hash = htons(image->hash);
|
||||
memcpy(ptr, &hash, 2);
|
||||
@@ -299,7 +295,7 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
|
||||
memcpy(ptr, &size, 4);
|
||||
ptr += 4;
|
||||
|
||||
/* Load address (ignored by NOLO) */
|
||||
/* Space */
|
||||
memcpy(ptr, "\x00\x00\x00\x00", 4);
|
||||
ptr += 4;
|
||||
|
||||
@@ -372,7 +368,7 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
|
||||
printf("Sending image header...\n");
|
||||
|
||||
if ( ! simulate ) {
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, request, 0, 0, (unsigned char *)buf, ptr-buf, 2000) < 0 )
|
||||
if ( usb_control_msg(dev->udev, NOLO_WRITE, request, 0, 0, buf, ptr-buf, 2000) < 0 )
|
||||
NOLO_ERROR_RETURN("Sending image header failed", -1);
|
||||
}
|
||||
|
||||
@@ -391,7 +387,7 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
|
||||
if ( ret == 0 )
|
||||
break;
|
||||
if ( ! simulate ) {
|
||||
if ( usb_bulk_send(dev->udev, USB_WRITE_DATA_EP, buf, ret, 5000) != ret ) {
|
||||
if ( usb_bulk_write(dev->udev, USB_WRITE_DATA_EP, buf, ret, 5000) != ret ) {
|
||||
PRINTF_END();
|
||||
NOLO_ERROR_RETURN("Sending image failed", -1);
|
||||
}
|
||||
@@ -403,7 +399,7 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
|
||||
if ( flash ) {
|
||||
printf("Finishing flashing...\n");
|
||||
if ( ! simulate ) {
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_SEND_FLASH_FINISH, 0, 0, NULL, 0, 30000) < 0 )
|
||||
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SEND_FLASH_FINISH, 0, 0, NULL, 0, 30000) < 0 )
|
||||
NOLO_ERROR_RETURN("Finishing failed", -1);
|
||||
}
|
||||
}
|
||||
@@ -460,7 +456,7 @@ int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||
printf("Flashing image...\n");
|
||||
|
||||
if ( ! simulate ) {
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_FLASH_IMAGE, 0, index, NULL, 0, 10000) )
|
||||
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_FLASH_IMAGE, 0, index, NULL, 0, 10000) )
|
||||
NOLO_ERROR_RETURN("Flashing failed", -1);
|
||||
}
|
||||
|
||||
@@ -545,7 +541,7 @@ int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||
|
||||
}
|
||||
|
||||
MSLEEP(50);
|
||||
SLEEP(0xc350); // 0.5s
|
||||
|
||||
}
|
||||
|
||||
@@ -581,7 +577,7 @@ int nolo_boot_device(struct usb_device_info * dev, const char * cmdline) {
|
||||
cmdline = NULL;
|
||||
}
|
||||
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_BOOT, mode, 0, (unsigned char *)cmdline, size, 2000) < 0 )
|
||||
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;
|
||||
@@ -591,7 +587,7 @@ int nolo_boot_device(struct usb_device_info * dev, const char * cmdline) {
|
||||
int nolo_reboot_device(struct usb_device_info * dev) {
|
||||
|
||||
printf("Rebooting device...\n");
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_REBOOT, 0, 0, NULL, 0, 2000) < 0 )
|
||||
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;
|
||||
|
||||
@@ -600,7 +596,7 @@ int nolo_reboot_device(struct usb_device_info * dev) {
|
||||
int nolo_get_root_device(struct usb_device_info * dev) {
|
||||
|
||||
uint8_t device = 0;
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_ROOT_DEVICE, (unsigned char *)&device, 1, 2000) < 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;
|
||||
|
||||
@@ -611,7 +607,7 @@ 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 ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_SET, device, NOLO_ROOT_DEVICE, NULL, 0, 2000) < 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;
|
||||
|
||||
@@ -620,7 +616,7 @@ int nolo_set_root_device(struct usb_device_info * dev, int device) {
|
||||
int nolo_get_usb_host_mode(struct usb_device_info * dev) {
|
||||
|
||||
uint32_t enabled = 0;
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_USB_HOST_MODE, (unsigned char *)&enabled, 4, 2000) < 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;
|
||||
|
||||
@@ -631,7 +627,7 @@ 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 ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_SET, enable, NOLO_USB_HOST_MODE, NULL, 0, 2000) < 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;
|
||||
|
||||
@@ -640,7 +636,7 @@ int nolo_set_usb_host_mode(struct usb_device_info * dev, int enable) {
|
||||
int nolo_get_rd_mode(struct usb_device_info * dev) {
|
||||
|
||||
uint8_t enabled = 0;
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_RD_MODE, (unsigned char *)&enabled, 1, 2000) < 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;
|
||||
|
||||
@@ -651,7 +647,7 @@ 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 ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_SET, enable, NOLO_RD_MODE, NULL, 0, 2000) < 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;
|
||||
|
||||
@@ -664,7 +660,7 @@ int nolo_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size) {
|
||||
uint16_t add_flags = 0;
|
||||
char * ptr = flags;
|
||||
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_ADD_RD_FLAGS, (unsigned char *)&add_flags, 2, 2000) < 0 )
|
||||
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 )
|
||||
@@ -764,10 +760,10 @@ int nolo_set_rd_flags(struct usb_device_info * dev, const char * flags) {
|
||||
if ( simulate )
|
||||
return 0;
|
||||
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_SET, add_flags, NOLO_ADD_RD_FLAGS, NULL, 0, 2000) < 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 ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_SET, del_flags, NOLO_DEL_RD_FLAGS, NULL, 0, 2000) < 0 )
|
||||
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;
|
||||
@@ -827,7 +823,7 @@ int nolo_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size) {
|
||||
|
||||
uint32_t version = 0;
|
||||
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_QUERY, NOLO_GET_NOLO_VERSION, 0, 0, (unsigned char *)&version, 4, 2000) < 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 )
|
||||
@@ -886,7 +882,7 @@ int nolo_set_sw_ver(struct usb_device_info * dev, const char * ver) {
|
||||
memcpy(ptr, ver, len);
|
||||
ptr += len;
|
||||
|
||||
if ( libusb_control_transfer(dev->udev, NOLO_WRITE, NOLO_SET_SW_RELEASE, 0, 0, (unsigned char *)buf, ptr-buf, 2000) < 0 )
|
||||
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;
|
||||
|
||||
+129
-191
@@ -17,6 +17,11 @@
|
||||
|
||||
*/
|
||||
|
||||
/* Enable RTLD_DEFAULT for glibc */
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
@@ -24,6 +29,7 @@
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "global.h"
|
||||
#include "device.h"
|
||||
@@ -33,26 +39,23 @@
|
||||
#include "cold-flash.h"
|
||||
#include "mkii.h"
|
||||
|
||||
#define USB_ERROR(str, err) do { PRINTF_END(); ERROR("%s: %s", str, libusb_strerror(err)); } while (0)
|
||||
|
||||
static libusb_context * usb_ctx;
|
||||
#ifdef __linux__
|
||||
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static struct usb_flash_device usb_devices[] = {
|
||||
/* vend prod i a protocol devices */
|
||||
{ 0x0421, 0x0096, -1, -1, FLASH_DISK, { DEVICE_RX_44, 0 } },
|
||||
{ 0x0421, 0x0105, 2, 1, FLASH_NOLO, { DEVICE_SU_18, DEVICE_RX_34, DEVICE_RX_44, DEVICE_RX_48, DEVICE_RX_51, DEVICE_RM_680, DEVICE_RM_696, 0 } },
|
||||
{ 0x0421, 0x0106, 0, 0, FLASH_COLD, { DEVICE_RX_51, DEVICE_RM_680, DEVICE_RM_696, 0 } },
|
||||
{ 0x0421, 0x0189, -1, -1, FLASH_DISK, { DEVICE_RX_48, 0 } },
|
||||
{ 0x0421, 0x01c7, -1, -1, FLASH_DISK, { DEVICE_RX_51, 0 } },
|
||||
{ 0x0421, 0x01c8, 1, 1, FLASH_MKII, { DEVICE_RX_51, DEVICE_RM_680, 0 } },
|
||||
{ 0x0421, 0x01c8, 1, 0, FLASH_UNKN, { DEVICE_RX_51, 0 } }, /* U-Boot mode (TTY via USB) */
|
||||
{ 0x0421, 0x03d1, -1, -1, FLASH_DISK, { DEVICE_RM_680, 0 } },
|
||||
{ 0x0421, 0x03d2, 1, 1, FLASH_MKII, { DEVICE_RM_680, 0 } },
|
||||
{ 0x0421, 0x0431, -1, -1, FLASH_DISK, { DEVICE_SU_18, DEVICE_RX_34, 0 } },
|
||||
{ 0x0421, 0x04c3, -1, -1, FLASH_DISK, { DEVICE_RX_34, 0 } },
|
||||
{ 0x0421, 0x0518, -1, -1, FLASH_DISK, { DEVICE_RM_696, 0 } },
|
||||
{ 0x0421, 0x0519, -1, -1, FLASH_UNKN, { DEVICE_RM_696, 0 } }, /* RNDIS/Ethernet mode */
|
||||
{ 0x0421, 0x051a, 2, 1, FLASH_UNKN, { DEVICE_RM_696, 0 } }, /* Sync mode (ADL protocol) */
|
||||
{ 0x0421, 0x0096, -1, -1, -1, FLASH_DISK, { DEVICE_RX_44, 0 } },
|
||||
{ 0x0421, 0x0105, 2, 1, -1, FLASH_NOLO, { DEVICE_SU_18, DEVICE_RX_34, DEVICE_RX_44, DEVICE_RX_48, DEVICE_RX_51, DEVICE_RM_680, DEVICE_RM_696, 0 } },
|
||||
{ 0x0421, 0x0106, 0, -1, -1, FLASH_COLD, { DEVICE_RX_51, DEVICE_RM_680, DEVICE_RM_696, 0 } },
|
||||
{ 0x0421, 0x0189, -1, -1, -1, FLASH_DISK, { DEVICE_RX_48, 0 } },
|
||||
{ 0x0421, 0x01c7, -1, -1, -1, FLASH_DISK, { DEVICE_RX_51, 0 } },
|
||||
{ 0x0421, 0x01c8, 1, 1, -1, FLASH_MKII, { DEVICE_RX_51, DEVICE_RM_680, 0 } },
|
||||
{ 0x0421, 0x03d1, -1, -1, -1, FLASH_DISK, { DEVICE_RM_680, 0 } },
|
||||
{ 0x0421, 0x0431, -1, -1, -1, FLASH_DISK, { DEVICE_SU_18, DEVICE_RX_34, 0 } },
|
||||
{ 0x0421, 0x04c3, -1, -1, -1, FLASH_DISK, { DEVICE_RX_34, 0 } },
|
||||
{ 0x0421, 0x3f00, 2, 1, -1, FLASH_NOLO, { DEVICE_RX_34, 0 } },
|
||||
};
|
||||
|
||||
static const char * usb_flash_protocols[] = {
|
||||
@@ -84,20 +87,31 @@ static void usb_flash_device_info_print(const struct usb_flash_device * dev) {
|
||||
|
||||
}
|
||||
|
||||
static void usb_reattach_kernel_driver(libusb_device_handle * udev, int interface, int detached) {
|
||||
static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
|
||||
struct {
|
||||
int ifno;
|
||||
int ioctl_code;
|
||||
void * data;
|
||||
} command = {
|
||||
.ifno = interface,
|
||||
.ioctl_code = _IO('U', 23),
|
||||
.data = NULL,
|
||||
};
|
||||
|
||||
if ( interface < 0 )
|
||||
return;
|
||||
|
||||
libusb_release_interface(udev, interface);
|
||||
|
||||
/* Reattach only driver detached by us, on macOS reattaching re-enumerates (resets) device */
|
||||
if ( detached )
|
||||
libusb_attach_kernel_driver(udev, interface);
|
||||
usb_release_interface(udev, interface);
|
||||
ioctl(*((int *)udev), _IOWR('U', 18, command), &command);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void usb_descriptor_info_print(libusb_device_handle * udev, const struct libusb_device_descriptor * desc, char * product, size_t size) {
|
||||
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];
|
||||
@@ -106,7 +120,7 @@ static void usb_descriptor_info_print(libusb_device_handle * udev, const struct
|
||||
int i;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
libusb_get_string_descriptor_ascii(udev, desc->iProduct, (unsigned char *)buf, 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();
|
||||
|
||||
@@ -115,12 +129,12 @@ static void usb_descriptor_info_print(libusb_device_handle * udev, const struct
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memset(buf2, 0, sizeof(buf2));
|
||||
ret = libusb_get_string_descriptor_ascii(udev, desc->iSerialNumber, (unsigned char *)buf, sizeof(buf));
|
||||
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 > 31 && x < 127 )
|
||||
if ( x > 32 && x < 128 )
|
||||
buf2[i/2] = x;
|
||||
else {
|
||||
buf2[0] = 0;
|
||||
@@ -134,51 +148,15 @@ static void usb_descriptor_info_print(libusb_device_handle * udev, const struct
|
||||
|
||||
}
|
||||
|
||||
static int usb_device_has_interface(libusb_device * dev, int interface, int alternate) {
|
||||
static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
|
||||
|
||||
struct libusb_config_descriptor * config;
|
||||
int ret = 1;
|
||||
|
||||
if ( interface == -1 )
|
||||
return 1;
|
||||
|
||||
if ( libusb_get_config_descriptor(dev, 0, &config) < 0 )
|
||||
return 0;
|
||||
|
||||
if ( interface >= config->bNumInterfaces )
|
||||
ret = 0;
|
||||
else if ( alternate != -1 && alternate >= config->interface[interface].num_altsetting )
|
||||
ret = 0;
|
||||
|
||||
libusb_free_config_descriptor(config);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
|
||||
size_t i;
|
||||
int err;
|
||||
int detached = 0;
|
||||
int i;
|
||||
char product[1024];
|
||||
struct libusb_device_descriptor desc;
|
||||
struct usb_device_info * ret = NULL;
|
||||
|
||||
if ( libusb_get_device_descriptor(dev, &desc) < 0 )
|
||||
return NULL;
|
||||
for ( i = 0; usb_devices[i].vendor; ++i ) {
|
||||
|
||||
for ( i = 0; i < sizeof(usb_devices)/sizeof(usb_devices[0]); ++i ) {
|
||||
|
||||
if ( desc.idVendor == usb_devices[i].vendor && desc.idProduct == usb_devices[i].product ) {
|
||||
|
||||
if ( usb_devices[i].protocol == FLASH_UNKN )
|
||||
continue;
|
||||
|
||||
if ( desc.bNumConfigurations < 1 )
|
||||
continue;
|
||||
|
||||
if ( ! usb_device_has_interface(dev, usb_devices[i].interface, usb_devices[i].alternate) )
|
||||
continue;
|
||||
if ( dev->descriptor.idVendor == usb_devices[i].vendor && dev->descriptor.idProduct == usb_devices[i].product ) {
|
||||
|
||||
printf("\b\b ");
|
||||
PRINTF_END();
|
||||
@@ -187,37 +165,28 @@ static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
PRINTF_END();
|
||||
|
||||
PRINTF_LINE("Opening USB...");
|
||||
libusb_device_handle * udev;
|
||||
err = libusb_open(dev, &udev);
|
||||
if ( err < 0 ) {
|
||||
USB_ERROR("libusb_open failed", err);
|
||||
usb_dev_handle * udev = usb_open(dev);
|
||||
if ( ! udev ) {
|
||||
PRINTF_ERROR("usb_open failed");
|
||||
fprintf(stderr, "\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(product, 0, sizeof(product));
|
||||
usb_descriptor_info_print(udev, &desc, product, sizeof(product));
|
||||
usb_descriptor_info_print(udev, dev, product, sizeof(product));
|
||||
|
||||
if ( usb_devices[i].interface >= 0 ) {
|
||||
|
||||
if ( libusb_kernel_driver_active(udev, usb_devices[i].interface) == 1 ) {
|
||||
PRINTF_LINE("Detaching kernel from USB interface...");
|
||||
err = libusb_detach_kernel_driver(udev, usb_devices[i].interface);
|
||||
if ( err == 0 )
|
||||
detached = 1;
|
||||
else {
|
||||
PRINTF_END();
|
||||
WARNING("Cannot detach kernel driver: %s", libusb_strerror(err));
|
||||
}
|
||||
}
|
||||
#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...");
|
||||
err = libusb_claim_interface(udev, usb_devices[i].interface);
|
||||
if ( err < 0 ) {
|
||||
USB_ERROR("libusb_claim_interface failed", err);
|
||||
if ( usb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
|
||||
PRINTF_ERROR("usb_claim_interface failed");
|
||||
fprintf(stderr, "\n");
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface, detached);
|
||||
libusb_close(udev);
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
|
||||
usb_close(udev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -225,12 +194,22 @@ static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
|
||||
if ( usb_devices[i].alternate >= 0 ) {
|
||||
PRINTF_LINE("Setting alternate USB interface...");
|
||||
err = libusb_set_interface_alt_setting(udev, usb_devices[i].interface, usb_devices[i].alternate);
|
||||
if ( err < 0 ) {
|
||||
USB_ERROR("libusb_set_interface_alt_setting failed", err);
|
||||
if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
|
||||
PRINTF_ERROR("usb_claim_interface failed");
|
||||
fprintf(stderr, "\n");
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface, detached);
|
||||
libusb_close(udev);
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
|
||||
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_reattach_kernel_driver(udev, usb_devices[i].interface);
|
||||
usb_close(udev);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -238,8 +217,8 @@ static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
ret = calloc(1, sizeof(struct usb_device_info));
|
||||
if ( ! ret ) {
|
||||
ALLOC_ERROR();
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface, detached);
|
||||
libusb_close(udev);
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
|
||||
usb_close(udev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -251,13 +230,13 @@ static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
ret->device = DEVICE_RX_44;
|
||||
else if ( strcmp(product, "Nokia N810 Internet Tablet WiMAX Edition") == 0 || strcmp(product, "Nokia-RX48 (Update mode)") == 0 )
|
||||
ret->device = DEVICE_RX_48;
|
||||
else if ( strcmp(product, "N900 (Storage Mode)") == 0 || strcmp(product, "Nokia N900 (Update mode)") == 0 || strcmp(product, "N900 (PC-Suite Mode)") == 0 || strcmp(product, "N900 (U-Boot)") == 0 )
|
||||
else if ( strcmp(product, "N900 (Storage Mode)") == 0 || strcmp(product, "Nokia N900 (Update mode)") == 0 || strcmp(product, "N900 (PC-Suite Mode)") == 0 )
|
||||
ret->device = DEVICE_RX_51;
|
||||
else if ( strcmp(product, "Nokia N950") == 0 || strcmp(product, "N950 (Update mode)") == 0 )
|
||||
else if ( strcmp(product, "Nokia N950") == 0 || strcmp(product, "Sync Mode") == 0 || strcmp(product, "N950 (Update mode)") == 0 )
|
||||
ret->device = DEVICE_RM_680;
|
||||
else if ( strcmp(product, "Nokia N9") == 0 || strcmp(product, "N9 (Update mode)") == 0 || strcmp(product, "Nokia N9 RNDIS/Ethernet") == 0 )
|
||||
else if ( strcmp(product, "N9 (Update mode)") == 0 || strcmp(product, "Nxy (Update mode)") == 0 )
|
||||
ret->device = DEVICE_RM_696;
|
||||
else if ( strcmp(product, "Nokia USB ROM") == 0 || strcmp(product, "Sync Mode") == 0 || strcmp(product, "Nxy (Update mode)") == 0 )
|
||||
else if ( strcmp(product, "Nokia USB ROM") == 0 )
|
||||
ret->device = DEVICE_ANY;
|
||||
else
|
||||
ret->device = DEVICE_UNKNOWN;
|
||||
@@ -271,8 +250,8 @@ static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
if ( ! noverify && ret->device == DEVICE_UNKNOWN ) {
|
||||
ERROR("Device detection failed");
|
||||
fprintf(stderr, "\n");
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface, detached);
|
||||
libusb_close(udev);
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
|
||||
usb_close(udev);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
@@ -285,8 +264,8 @@ static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
if ( ! *device ) {
|
||||
ERROR("Device mishmash");
|
||||
fprintf(stderr, "\n");
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface, detached);
|
||||
libusb_close(udev);
|
||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
|
||||
usb_close(udev);
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
@@ -295,7 +274,6 @@ static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
ret->hwrev = -1;
|
||||
ret->flash_device = &usb_devices[i];
|
||||
ret->udev = udev;
|
||||
ret->detached = detached;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -304,6 +282,28 @@ static struct usb_device_info * usb_device_is_valid(libusb_device * dev) {
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -313,33 +313,19 @@ static void signal_handler(int signum) {
|
||||
|
||||
}
|
||||
|
||||
static void usb_exit(void) {
|
||||
|
||||
libusb_exit(usb_ctx);
|
||||
usb_ctx = NULL;
|
||||
|
||||
}
|
||||
|
||||
struct usb_device_info * usb_open_and_wait_for_device(void) {
|
||||
|
||||
libusb_device ** devs;
|
||||
ssize_t count;
|
||||
ssize_t j;
|
||||
struct usb_bus * bus;
|
||||
struct usb_device_info * ret = NULL;
|
||||
int i = 0;
|
||||
int err;
|
||||
void (*prev)(int);
|
||||
static char progress[] = {'/','-','\\', '|'};
|
||||
|
||||
/* Context is kept until exit, so device list stays up to date between waits */
|
||||
if ( ! usb_ctx ) {
|
||||
err = libusb_init(&usb_ctx);
|
||||
if ( err < 0 ) {
|
||||
USB_ERROR("libusb_init failed", err);
|
||||
return NULL;
|
||||
}
|
||||
atexit(usb_exit);
|
||||
}
|
||||
if ( dlsym(RTLD_DEFAULT, "libusb_init") )
|
||||
ERROR_RETURN("You are trying to use broken libusb-1.0 library (either directly or via wrapper) which has slow listing of usb devices. It cannot be used for flashing or cold-flashing. Please use libusb 0.1.", NULL);
|
||||
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
|
||||
PRINTF_BACK();
|
||||
printf("\n");
|
||||
@@ -352,25 +338,30 @@ struct usb_device_info * usb_open_and_wait_for_device(void) {
|
||||
|
||||
PRINTF_LINE("Waiting for USB device... %c", progress[++i%sizeof(progress)]);
|
||||
|
||||
count = libusb_get_device_list(usb_ctx, &devs);
|
||||
if ( count < 0 ) {
|
||||
USB_ERROR("libusb_get_device_list failed", (int)count);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
for ( j = 0; j < count; ++j ) {
|
||||
ret = usb_device_is_valid(devs[j]);
|
||||
if ( ret )
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opened device handle holds its own reference */
|
||||
libusb_free_device_list(devs, 1);
|
||||
}
|
||||
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
MSLEEP(50);
|
||||
SLEEP(0xc350); // 0.5s
|
||||
|
||||
}
|
||||
|
||||
@@ -390,65 +381,12 @@ struct usb_device_info * usb_open_and_wait_for_device(void) {
|
||||
void usb_close_device(struct usb_device_info * dev) {
|
||||
|
||||
if ( dev->flash_device->protocol != FLASH_COLD )
|
||||
usb_reattach_kernel_driver(dev->udev, dev->flash_device->interface, dev->detached);
|
||||
libusb_close(dev->udev);
|
||||
usb_reattach_kernel_driver(dev->udev, dev->flash_device->interface);
|
||||
usb_close(dev->udev);
|
||||
free(dev);
|
||||
|
||||
}
|
||||
|
||||
/* Translate libusb error, so error messages which print errno stay meaningful */
|
||||
static int usb_error_to_errno(int err) {
|
||||
|
||||
switch ( err ) {
|
||||
case LIBUSB_ERROR_INVALID_PARAM: return EINVAL;
|
||||
case LIBUSB_ERROR_ACCESS: return EACCES;
|
||||
case LIBUSB_ERROR_NO_DEVICE: return ENODEV;
|
||||
case LIBUSB_ERROR_NOT_FOUND: return ENOENT;
|
||||
case LIBUSB_ERROR_BUSY: return EBUSY;
|
||||
case LIBUSB_ERROR_TIMEOUT: return ETIMEDOUT;
|
||||
case LIBUSB_ERROR_OVERFLOW: return EOVERFLOW;
|
||||
case LIBUSB_ERROR_PIPE: return EPIPE;
|
||||
case LIBUSB_ERROR_INTERRUPTED: return EINTR;
|
||||
case LIBUSB_ERROR_NO_MEM: return ENOMEM;
|
||||
case LIBUSB_ERROR_NOT_SUPPORTED: return ENOTSUP;
|
||||
default: return EIO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Returns number of transferred bytes or negative libusb error code */
|
||||
static int usb_bulk_transfer(libusb_device_handle * udev, unsigned char endpoint, unsigned char * data, int size, unsigned int timeout) {
|
||||
|
||||
int transferred = 0;
|
||||
int ret;
|
||||
|
||||
ret = libusb_bulk_transfer(udev, endpoint, data, size, &transferred, timeout);
|
||||
if ( ret == 0 )
|
||||
return transferred;
|
||||
|
||||
errno = usb_error_to_errno(ret);
|
||||
|
||||
/* Timed out transfer which moved some data is reported as short transfer, callers check its size */
|
||||
if ( ret == LIBUSB_ERROR_TIMEOUT && transferred > 0 )
|
||||
return transferred;
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int usb_bulk_send(libusb_device_handle * udev, unsigned char endpoint, const void * data, int size, unsigned int timeout) {
|
||||
|
||||
/* libusb does not modify buffer of OUT transfer */
|
||||
return usb_bulk_transfer(udev, endpoint, (unsigned char *)data, size, timeout);
|
||||
|
||||
}
|
||||
|
||||
int usb_bulk_recv(libusb_device_handle * udev, unsigned char endpoint, void * data, int size, unsigned int timeout) {
|
||||
|
||||
return usb_bulk_transfer(udev, endpoint, data, size, timeout);
|
||||
|
||||
}
|
||||
|
||||
void usb_switch_to_nolo(struct usb_device_info * dev) {
|
||||
|
||||
printf("\nSwitching to NOLO mode...\n");
|
||||
|
||||
+11
-9
@@ -22,11 +22,16 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libusb.h>
|
||||
/* u_int*_t types are not defined without _GNU_SOURCE but usb.h needs them */
|
||||
#define u_int8_t uint8_t
|
||||
#define u_int16_t uint16_t
|
||||
#define u_int32_t uint32_t
|
||||
|
||||
#define USB_READ_EP (LIBUSB_ENDPOINT_IN | 0x1)
|
||||
#define USB_WRITE_EP (LIBUSB_ENDPOINT_OUT | 0x1)
|
||||
#define USB_WRITE_DATA_EP (LIBUSB_ENDPOINT_OUT | 0x2)
|
||||
#include <usb.h>
|
||||
|
||||
#define USB_READ_EP (USB_ENDPOINT_IN | 0x1)
|
||||
#define USB_WRITE_EP (USB_ENDPOINT_OUT | 0x1)
|
||||
#define USB_WRITE_DATA_EP (USB_ENDPOINT_OUT | 0x2)
|
||||
|
||||
#include "device.h"
|
||||
|
||||
@@ -44,6 +49,7 @@ struct usb_flash_device {
|
||||
uint16_t product;
|
||||
int interface;
|
||||
int alternate;
|
||||
int configuration;
|
||||
enum usb_flash_protocol protocol;
|
||||
enum device devices[DEVICE_COUNT];
|
||||
};
|
||||
@@ -52,8 +58,7 @@ struct usb_device_info {
|
||||
enum device device;
|
||||
int16_t hwrev;
|
||||
const struct usb_flash_device * flash_device;
|
||||
libusb_device_handle * udev;
|
||||
int detached;
|
||||
usb_dev_handle * udev;
|
||||
int data;
|
||||
};
|
||||
|
||||
@@ -61,9 +66,6 @@ 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);
|
||||
|
||||
int usb_bulk_send(libusb_device_handle * udev, unsigned char endpoint, const void * data, int size, unsigned int timeout);
|
||||
int usb_bulk_recv(libusb_device_handle * udev, unsigned char endpoint, void * data, int size, unsigned int timeout);
|
||||
|
||||
void usb_switch_to_nolo(struct usb_device_info * dev);
|
||||
void usb_switch_to_cold(struct usb_device_info * dev);
|
||||
void usb_switch_to_update(struct usb_device_info * dev);
|
||||
|
||||
Reference in new issue
Block a user