71 Commits
Author SHA1 Message Date
Pali Rohár f6b0a7be3a Release version 0.10 2022-01-04 17:29:07 +01:00
Pali Rohár 8a9e2759d4 device: Fix 0xFFFF crash when generating fiasco image without hwrev 2021-05-02 18:44:22 +02:00
Pali Rohár bacbb0165b fiasco: Mute warning about uninitialized variables fs and checksum 2021-05-02 17:56:24 +02:00
Pali Rohár df2340e48d main: Fix NULL pointer derefernce 2021-05-02 17:48:49 +02:00
Pali Rohár a5279bffaf local: Fix flashing and dumping kernel images with "NOLO img" header
"NOLO img" header (instead of "NOLO!img" header) is used on older devices.
2021-05-02 17:35:09 +02:00
Pali Rohár b46e4a6ad5 image: Define 1st, cert-sw and ape-algo Harmattan images
This change allows 0xFFFF to unpack Harmattan fiasco images.
2021-05-02 17:19:56 +02:00
Pali Rohár e65d7d1636 fiasco: Show verbose hexdump information about unknown section 2021-05-02 17:06:20 +02:00
Pali Rohár 1f466936cb fiasco: When generating fiasco image append image data part sections
Nokia's fiasco-gen writes data part section even if there is only one part.
So do the same thing in 0xFFFF.
2021-05-02 17:04:27 +02:00
Pali Rohár df8e50a824 fiasco: Add support for unpacking multiple parts of one image
Fiasco mmc image contains layout and two parts in one data section. First
part is FAT32 partition (MyDocs) and second part is tar archive for second
ext3 partition (/home). This change extends fiasco parser to load all parts
from one data section and correctly unpack all parts.
2021-05-02 17:01:48 +02:00
Pali Rohár 4f45b045c3 fiasco: Implement subsection checksum verification during parsing fiasco image
When checksum is set to 0x00 then skip verification due to backward
compatibility with 0xFFFF version 0.9 and earlier.
2021-05-02 14:24:51 +02:00
Pali Rohár 3c4943340b fiasco: Write correct subsection checksum when generating fiasco image
Previously 0xFFFF written fixed value 0x00 instead of correct checksum.
Apparently both NOLO and Nokia's flasher-3.5 ignored checksum value
verification when checksum was set to 0x00.

Also Nokia's fiasco-gen writes correct checksum (not 0x00) to final fiasco
image file.
2021-05-02 14:22:55 +02:00
Pali Rohár ce67a58983 fiasco: Update comments about unknown bytes and parsing of fiasco images
Allow to parse also fiasco images which do not have common parameters:
* asic index: APE (0x01)
* device type: NAND (0x01)
* device index: 0
2021-05-02 14:19:38 +02:00
Pali Rohár a6b6b71ded doc: Update fiasco documenation 2021-05-02 14:09:53 +02:00
Pali Rohár 580f1de0fe mkii: Update comments about unknown bytes in flashing protocol 2021-05-02 13:43:21 +02:00
Pali Rohár f9e88d6f91 nolo: Update comments about unknown bytes in flashing protocol 2021-05-02 13:42:36 +02:00
Pali Rohár ca035e2ec1 main: Fix renaming of dumped images
Some information (device, hwrev or version string) does not have to be available.
2021-05-02 13:36:56 +02:00
Pali Rohár 5c0720da32 local: Fix reading kernel size when dumping image 2021-05-01 21:06:37 +02:00
Pali Rohár 374fd1be01 TODO: Update implemented parts 2021-05-01 20:41:40 +02:00
Pali Rohár f144067634 local: Respect -s (simulate) flag for dump -e operation 2021-05-01 20:39:44 +02:00
Pali Rohár bbf438e1a8 disk: Respect -s (simulate) flag for dump -e operation 2021-05-01 20:38:26 +02:00
Pali Rohár 670db0d169 main: Retry load and flash operations only on -EAGAIN error 2021-05-01 20:10:21 +02:00
Pali Rohár 6eb58dcccb local: Implement local flashing via nandwrite 2021-05-01 20:09:40 +02:00
Pali Rohár b090564a85 disk: Implement flashing mmc images 2021-05-01 20:07:49 +02:00
Pali Rohár 38f83f8db4 local: Rename nanddump structures to just nand
They can be used also for other nand commands like nandwrite.
2021-05-01 18:27:32 +02:00
Pali Rohár 342dc610b3 local: Parse real kernel size from NOLO!img header when dumping kernel image
Kernel image is prepended with 2kB header with NOLO!img magic and contains
size of the kernel image. 0xFFFF until now just skipped this header. With
this change is reads from it real kernel image size and correctly truncate
final dumped image for 0xFFFF -e/-E dump operation.
2021-05-01 18:20:13 +02:00
Pali Rohár 67427daf17 local: Fix calling nanddump
In last 15 years nanddump changed its command line arguments. Argument -b
(omit bad blocks) was completely removed and argument -o (omit oob data)
changed its meaning to "include" oob data. So for compatibility with all
nanddump versions, do not use argument -b and instead of -o use argument
--omitoob which is present in all nanddump versions and has same meaning
to omit oob data.

This change should fix dumping firmware files on devices with recent
versions of nanddump.
2021-05-01 15:34:22 +02:00
Pali Rohár bf24ca2345 Release version 0.9 2021-01-05 19:16:39 +01:00
Pali Rohár 5c845a947e usb-device: Specify alternate id for cold flashing 2021-01-05 15:51:10 +01:00
Pali Rohár 673ccaf71d usb-device: Add N900 U-Boot mode (TTY via USB) to device list 2021-01-05 15:32:20 +01:00
Pali Rohár 9bc4b8c26f usb-device: Check that usb device provides required interface/alternate settings 2021-01-05 15:04:31 +01:00
Pali Rohár e6422cf5a2 usb-device: Remove dead usb_set_configuration() code
It is on worng place, must be called prior usb_claim_interface() and currently no device use it.
2021-01-05 14:38:02 +01:00
Pali Rohár a6effa8f62 usb-device: Remove 0x0421/0x3f00 from list
It was some internal Nokia development board with just temporary device id. Not a real RX-34 device.
2021-01-05 13:45:01 +01:00
Pali Rohár e16a79f75e usb-device: Fix interface id for Nokia N9 Sync mode and disable it as it use unsupported ADL protocol 2021-01-05 13:28:29 +01:00
Pali Rohár 93bd73d451 usb-device: Fix iterating over supported list of devices 2021-01-05 12:35:40 +01:00
Pali Rohár 0e5ceffa42 disk: Fix detecting Nokia N9 device 2021-01-05 12:32:34 +01:00
Pali Rohár ca080dd33f usb-device: Add device ids for Nokia N950 and Nokia N9 2020-12-26 01:40:57 +01:00
Pali Rohár 4ae1f13624 usb-device: Fix range or printable characters 2020-11-29 21:56:29 +01:00
Pali Rohár 69a7c2705e usb-device: Fix error message for usb_set_altinterface 2020-11-29 21:55:17 +01:00
Devendranath Thadi 8d053c9074 Travis-ci: added support for ppc64le
Signed-off-by: Devendranath Thadi <devendranath.thadi3@gmail.com>
2020-11-17 09:02:09 +00:00
Pali Rohár f37c2cd7e8 all: Fix delays for all operations 2020-04-25 20:04:51 +02:00
Pali Rohár e94279eecb local: Do not show error message about missing dump files which were skipped 2020-01-15 23:38:29 +01:00
Pali Rohár 52793b733d disk: Check if reading from block device failed 2019-09-30 17:42:16 +02:00
Sevan Janiyan 4bd0a47b22 Rewrap 2019-09-30 00:39:24 +01:00
Sevan Janiyan adeca0dd45 Grammar 2019-09-30 00:38:57 +01:00
Pali Rohár b87411c02f Release version 0.8 2018-07-08 12:22:33 +02:00
Aaro Koskinen 7f38b4bd10 usb-device: restore N800 support
N800 has stopped working at some point, not sure why:

  $ 0xFFFF -I
  [...]
  Waiting for USB device...
  Found USB device: SU-18/RX-44/RX-48/RX-51/RM-680 (0x421:0x105) in NOLO mode
  USB device product string: Nokia N800 (Update mode)
  USB device serial number string: (not detected)
  Detected USB device: RX-34
  Error: Device mishmash

Add the device to 0421:0105 list, and it works again:

  Waiting for USB device...
  Found USB device: SU-18/RX-34/RX-44/RX-48/RX-51/RM-680 (0x421:0x105) in NOLO mode
  USB device product string: Nokia N800 (Update mode)
  USB device serial number string: (not detected)
  Detected USB device: RX-34

  Initializing NOLO...
  Device: RX-34
  [...]
2018-04-19 22:46:11 +03:00
Pali Rohár 9e5646d30e travis: Do not run Coverity Scan jobs on non-master branches and in pull requests 2018-02-26 13:10:35 +01:00
Pali Rohár 33442482c6 disk: Fix detection of busnum
Unpatched version of libusb on linux platform does not set location, but
Debian's version of libusb has a patch which set it. For compatibility with
other systems without unpatched libusb version, read busnum from dirname
which seems to be always set.

Fixes: https://github.com/pali/0xFFFF/issues/5
2018-02-08 23:20:14 +01:00
Pali Rohár e987dcd948 disk: Remove remaining ENOMEDIUM 2018-02-08 20:35:12 +01:00
Pali Rohár 2fd11378c8 disk: Fix swapping maj1:min1 and maj2:min2 2018-02-08 20:28:31 +01:00
Pali Rohár 808ce724ee main: Print message after dumping finish 2018-02-08 19:49:54 +01:00
Pali Rohár ca1db96690 disk: Fix compile warning: comparison between signed and unsigned integer expressions 2018-02-08 19:49:13 +01:00
Pali Rohár a6c20b5ee4 disk: Open whole block device with O_NONBLOCK
This would simplify handling of ENOMEDIUM error.
2018-02-08 19:48:34 +01:00
Pali Rohár e685787e67 disk: Ensure that maj1:min1 is first device and maj2:min2 is second device 2018-02-08 19:24:11 +01:00
Edward Betts 10b495120e correct spelling mistake 2017-08-30 12:05:42 +01:00
Pali Rohár 559fe2a3bd disk: After opening blkdev, check that it is really block device 2017-07-09 17:26:13 +02:00
Pali Rohár ccec7a182f disk: Close device file handle when freeing structures 2017-07-09 14:57:41 +02:00
Pali Rohár 31569c169a disk: Fix detection of correct device in disk_open_dev() 2017-07-09 14:56:30 +02:00
Pali Rohár 27a55c3367 disk: Choose correct partition in disk_open_dev() 2017-07-06 20:55:41 +02:00
Pali Rohár cda5dc6116 main: Use image_alloc_from_fd() to fix race condition between calling stat and opening file 2017-06-17 23:48:01 +02:00
Pali Rohár 5cbd5e92b8 image: Add new function image_alloc_from_fd() 2017-06-17 23:47:10 +02:00
Pali Rohár 1ec3777cb8 image: Call image_free() when image_append() is failing 2017-06-17 23:46:50 +02:00
Pali Rohár 897919a70f main: Fix race condition between calling stat and rename 2017-06-17 23:10:36 +02:00
Pali Rohár 76b18b9d39 travis: Fix coverity job 2017-03-03 18:44:29 +01:00
Pali Rohár ffcc10f689 travis: Simplify configuration, move coverity_scan to matrix 2017-02-26 17:00:07 +01:00
Pali Rohár 16cdf3e776 travis: Run on container-based infrastructure 2017-02-26 16:19:42 +01:00
Pali Rohár dc81ebb855 travis: Use apt addon instead sudo 2017-02-26 16:09:52 +01:00
Pali Rohár 66ecce9a3d disk: Remove check which is always false
Type unsigned long long int according to C99 can store at least 2^64-1.
2017-01-09 22:56:33 +01:00
Pali Rohár 87867a5904 cal: Fix race condition between calling stat and opening file 2017-01-08 14:33:08 +01:00
Pali Rohár f0b8ee117b Makefile: Fix setting compiler 2017-01-08 03:42:34 +01:00
Pali Rohár 4c8206b44f travis: Enable clang and use separate job for Coverity 2017-01-08 03:33:39 +01:00
23 changed files with 983 additions and 314 deletions

No files matched your search

+22 -12
View File
@@ -1,22 +1,28 @@
sudo: false
language: c
arch:
- AMD64
- ppc64le
compiler:
- gcc
- clang
before_install:
- sudo apt-get update -qq
- sudo apt-get install -qq -y libusb-dev
script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make ; fi
addons: &addons
apt:
packages:
- libusb-dev
matrix:
exclude:
- compiler: clang
- env: COVERITY_SCAN_BRANCH=1
env:
global:
include:
- compiler: gcc
if: (branch = master) AND (type != pull_request)
env:
- secure: "JdUp+xFykPZoYA4aRfmYk2CtilLapniQllWPKo2dDdJd1vzdawfTvVxIAKjy7ac9RKwZzg3Chq3RsMEXPv8BtaLbssw266C7RDLMgjacl1eFLcmGRj/Gkk9peDSZ6vVdGEcA2j+6KDSfpCa/XjFjvOufZOgKw6m+3+d0A4G45SI="
addons:
addons:
<<: *addons
coverity_scan:
project:
name: "pali/0xFFFF"
@@ -24,3 +30,7 @@ addons:
notification_email: pali.rohar@gmail.com
build_command: make
branch_pattern: master
script:
- if [ -n "$COVERITY_SCAN_TOKEN" ]; then exit 0; fi
- make
+13 -13
View File
@@ -10,24 +10,24 @@
_/ ___|_.|__|
'`
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 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 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.
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.
Use it with CARE. This is an experimental tool and it can brick your device.
It's not suposed to be stable, so nokia will probably release incompatible
It's not supposed to be stable, so Nokia will probably release incompatible
bootloaders to break this tool. USE IT AT YOUR OWN RISK.
PLEASE. Read carefully all the documentation inside doc/* for more information
before building or using the flasher to avoid questions, problems or so.
PLEASE. Read all the documentation inside doc/* carefully before building or
using the flasher to avoid questions, problems or so.
https://github.com/pali/0xFFFF
-2
View File
@@ -5,7 +5,6 @@ cold-flash:
* Detect device from asic id
disk:
* Support for flashing mmc images
* Badblock checking
fiasco:
@@ -15,7 +14,6 @@ image:
* Support for Harmattan images
local:
* Support for flashing (on device)
* Write versions
* Badblock checking
+1 -1
View File
@@ -1,4 +1,4 @@
VERSION = 0.7
VERSION = 0.10
PREFIX = /usr/local
# NetBSD stuff
+2 -3
View File
@@ -30,11 +30,10 @@ Technical details:
For dumping mtd partition is used tool nanddump. Here is example how to dump
kernel image without padding to file zImage:
$ nanddump -o -b -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2
$ nanddump --omitoob -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2
Params means:
-o - "Omit oob data"
-b - "Omit bad blocks"
--omitoob - "Omit oob data"
-s - "Start address"
-l - "Length"
-f - "Output file"
+55 -15
View File
@@ -38,24 +38,64 @@ IMAGE
1 byte = 0x54 -- signature
1 byte -- number of subsection blocks
(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 -- unknown (always 0x00 0x00 0x00 0x00)
(end of data block)
block {
1 byte -- type of subsection block
'1' - version
'2' - device & hw revisions (size of device is 16, hw revision 8)
'3' - layout
'4' - unknown
'/' - unknown
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 -- unknown (0x00 is accepted, maybe end of subsections?)
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)
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
N bytes -- unknown
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";
}
}
+3 -3
View File
@@ -5,9 +5,9 @@ INSTALL ?= install
BUILD_DATE ?= $(shell LC_ALL=C date '+%b %e %Y')
CC = gcc
CROSS_CC = $(CROSS_COMPILE)$(CC)
HOST_CC = $(HOST_COMPILE)$(CC)
CC ?= cc
CROSS_CC ?= $(CROSS_COMPILE)$(CC)
HOST_CC ?= $(HOST_COMPILE)$(CC)
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DBUILD_DATE="\"$(BUILD_DATE)\"" -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64
CFLAGS += -W -Wall -O2 -pedantic -std=c99
+3 -3
View File
@@ -76,14 +76,14 @@ int cal_init_file(const char * file, struct cal ** cal_out) {
off_t lsize = 0;
#endif
if ( stat(file, &st) != 0 )
return -1;
fd = open(file, O_RDONLY);
if ( fd < 0 )
return -1;
if ( fstat(fd, &st) != 0 )
goto err;
if ( S_ISREG(st.st_mode) )
size = st.st_size;
else if ( S_ISBLK(st.st_mode) ) {
+7 -7
View File
@@ -191,14 +191,14 @@ static int send_2nd(usb_dev_handle * udev, struct image * image) {
if ( ret != sizeof(omap_peripheral_msg) )
ERROR_RETURN("Sending OMAP peripheral boot message failed", -1);
SLEEP(5000);
MSLEEP(5);
printf("Sending 2nd X-Loader image size...\n");
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);
SLEEP(5000);
MSLEEP(5);
printf("Sending 2nd X-Loader image...\n");
printf_progressbar(0, image->size);
@@ -217,7 +217,7 @@ static int send_2nd(usb_dev_handle * udev, struct image * image) {
printf_progressbar(sent, image->size);
}
SLEEP(50000);
MSLEEP(50);
return 0;
}
@@ -237,7 +237,7 @@ static int send_secondary(usb_dev_handle * udev, struct image * image) {
ERROR_RETURN("Sending X-Loader init message failed", -1);
printf("Waiting for X-Loader response...\n");
SLEEP(5000);
MSLEEP(5);
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);
@@ -260,7 +260,7 @@ static int send_secondary(usb_dev_handle * udev, struct image * image) {
}
printf("Waiting for X-Loader response...\n");
SLEEP(5000);
MSLEEP(5);
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);
@@ -296,7 +296,7 @@ static int ping_timeout(usb_dev_handle * udev) {
break;
}
SLEEP(5000);
MSLEEP(5);
--try_read;
}
@@ -413,7 +413,7 @@ int leave_cold_flash(struct usb_device_info * dev) {
if ( ret != sizeof(omap_memory_msg) )
ERROR_RETURN("Sending OMAP memory boot message failed", -1);
SLEEP(1000000);
MSLEEP(250);
return 0;
}
+5 -3
View File
@@ -184,9 +184,11 @@ 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;
}
size += (1+16+(MAX_HWREVS+1)*8)*(local/MAX_HWREVS+1);
count += local/MAX_HWREVS;
@@ -215,7 +217,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
continue;
}
while ( device_first->hwrevs[i+1] != -1 ) {
do {
uint8_t len = 0;
ret[j] = ++last_ptr;
@@ -228,7 +230,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
for ( k = 0; k < MAX_HWREVS; ++k ) {
if ( device_first->hwrevs[i+1] == -1 )
if ( ! device_first->hwrevs || device_first->hwrevs[i+1] == -1 )
break;
++i;
@@ -246,7 +248,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;
+160 -40
View File
@@ -51,6 +51,7 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
DIR * dir;
struct dirent * dirent;
int found;
int old_errno;
size_t len;
char blkdev[1024];
@@ -117,6 +118,18 @@ 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);
if ( fd < 0 ) {
ERROR_INFO("Cannot open block device %s", blkdev);
return -1;
} else {
if ( fstat(fd, &st) != 0 || ! S_ISBLK(st.st_mode) || makedev(maj, min) != st.st_rdev ) {
ERROR("Block device %s does not have id %d:%d\n", blkdev, maj, min);
close(fd);
return -1;
}
}
} else if ( partition > 0 ) {
/* Select partition */
@@ -127,35 +140,48 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
return -1;
}
memcpy(blkdev+len, "p1", 3);
if ( stat(blkdev, &st) != 0 || ! S_ISBLK(st.st_mode) ) {
memcpy(blkdev+len, "1", 2);
if ( stat(blkdev, &st) != 0 || ! S_ISBLK(st.st_mode) ) {
blkdev[len] = 0;
fd = open(blkdev, O_RDONLY);
if ( fd < 0 ) {
if ( errno != ENOMEDIUM ) {
ERROR_INFO("Cannot open block device %s", blkdev);
if ( snprintf(blkdev+len, sizeof(blkdev)-len, "p%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);
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);
}
if ( fd < 0 && errno == ENOENT ) {
blkdev[len] = 0;
fd = open(blkdev, O_RDONLY | O_NONBLOCK);
if ( fd < 0 ) {
ERROR_INFO("Cannot open block device %s", blkdev);
} else {
close(fd);
ERROR("Block device does not have partitions");
ERROR("Block device %s does not have partitions", blkdev);
}
return -1;
}
}
}
if ( fd < 0 )
old_errno = errno;
printf("Found block device %s for partition %d\n", blkdev, partition);
if ( fd < 0 ) {
errno = old_errno;
ERROR_INFO("Cannot open block device %s", blkdev);
} else if ( fstat(fd, &st) != 0 || ! S_ISBLK(st.st_mode) ) {
ERROR("Block device %s is not block device\n", blkdev);
close(fd);
return -1;
}
fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL);
} else {
ERROR("Invalid partition %d for block device %s", partition, blkdev);
fd = -1;
if ( fd < 0 ) {
if ( errno != ENOMEDIUM )
ERROR_INFO("Cannot open block device %s", blkdev);
return -1;
}
return fd;
@@ -175,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;
int fd2 = -1;
int ret;
char * path;
uint64_t blksize;
@@ -195,7 +221,7 @@ int disk_dump_dev(int fd, const char * file) {
#else
blksize = lseek(fd, 0, SEEK_END);
if ( blksize == (off_t)-1 ) {
if ( (off_t)blksize == (off_t)-1 ) {
ERROR_INFO("Cannot get size of block device");
return -1;
}
@@ -207,11 +233,6 @@ int disk_dump_dev(int fd, const char * file) {
#endif
if ( blksize > ULLONG_MAX ) {
ERROR("Block device is too big");
return -1;
}
if ( blksize == 0 ) {
ERROR("Block device has zero size");
return -1;
@@ -232,6 +253,8 @@ 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 ) {
@@ -239,6 +262,8 @@ int disk_dump_dev(int fd, const char * file) {
return -1;
}
}
sent = 0;
printf_progressbar(0, blksize);
@@ -249,26 +274,91 @@ 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);
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);
return 0;
}
int disk_flash_dev(int fd, const char * file) {
int disk_flash_dev(int fd, struct image * image) {
ERROR("Not implemented yet");
(void)fd;
(void)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;
}
@@ -281,6 +371,7 @@ int disk_init(struct usb_device_info * dev) {
int maj2;
int min1;
int min2;
int tmp;
maj1 = -1;
maj2 = -1;
@@ -341,9 +432,17 @@ int disk_init(struct usb_device_info * dev) {
fclose(f);
if ( devnum != device->devnum || device->bus->location != busnum )
if ( device->devnum != devnum )
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;
min2 = -1;
@@ -367,18 +466,26 @@ int disk_init(struct usb_device_info * dev) {
return -1;
}
/* TODO: change 1 to 0 when disk_flash_dev will be implemented */
/* Ensure that maj1:min1 is first device and maj2:min2 is second device */
if ( min2 != -1 && min2 < min1 ) {
tmp = min1;
min1 = min2;
min2 = tmp;
tmp = maj1;
maj1 = maj2;
maj2 = tmp;
}
/* 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);
/* 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);
/* 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, 1);
fd = disk_open_dev(maj2, min2, 1, simulate ? 1 : 0);
else
fd = disk_open_dev(maj1, min1, 1, 1);
fd = disk_open_dev(maj1, min1, 1, simulate ? 1 : 0);
if ( fd < 0 && errno != ENOMEDIUM )
if ( fd < 0 )
return -1;
dev->data = fd;
@@ -394,6 +501,13 @@ int disk_init(struct usb_device_info * dev) {
}
void disk_exit(struct usb_device_info * dev) {
if ( dev->data >= 0 )
close(dev->data);
}
enum device disk_get_device(struct usb_device_info * dev) {
return dev->device;
@@ -402,10 +516,16 @@ enum device disk_get_device(struct usb_device_info * dev) {
int disk_flash_image(struct usb_device_info * dev, struct image * image) {
ERROR("Not implemented yet");
(void)dev;
(void)image;
return -1;
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;
}
+2 -1
View File
@@ -24,12 +24,13 @@
#include "usb-device.h"
int disk_init(struct usb_device_info * dev);
void disk_exit(struct usb_device_info * dev);
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, const char * file);
int disk_flash_dev(int fd, struct image * image);
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);
+226 -72
View File
@@ -34,10 +34,11 @@
#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, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; } 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 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)
@@ -65,9 +66,16 @@ 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];
@@ -120,23 +128,41 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
while ( 1 ) {
/* If end of file, return fiasco image */
READ_OR_RETURN(fiasco, buf, 7);
checksum = 0x00;
READ_OR_RETURN(fiasco, checksum, buf, 1);
/* Header of next image */
if ( ! ( buf[0] == 0x54 && buf[2] == 0x2E && buf[3] == 0x19 && buf[4] == 0x01 && buf[5] == 0x01 && buf[6] == 0x00 ) ) {
/* Header of next image (0x54) */
if ( buf[0] != 0x54 ) {
ERROR("Invalid next image header");
return fiasco;
}
count8 = buf[1];
if ( count8 > 0 )
--count8;
checksum = 0x00;
READ_OR_RETURN(fiasco, &hash, 2);
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);
hash = ntohs(hash);
memset(type, 0, sizeof(type));
READ_OR_RETURN(fiasco, type, 12);
READ_OR_RETURN(fiasco, checksum, type, 12);
byte = type[0];
if ( byte == 0xFF )
@@ -144,26 +170,35 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
VERBOSE(" %s\n", type);
READ_OR_RETURN(fiasco, &length, 4);
READ_OR_RETURN(fiasco, checksum, &length, 4);
length = ntohl(length);
/* unknown */
READ_OR_RETURN(fiasco, buf, 4);
/* load address (unused) */
READ_OR_RETURN(fiasco, checksum, &address, 4);
/* end of file data section */
--count8;
VERBOSE(" size: %d bytes\n", length);
VERBOSE(" hash: %#04x\n", hash);
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(" 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, &byte, 1);
READ_OR_RETURN(fiasco, &length8, 1);
READ_OR_RETURN(fiasco, buf, length8);
READ_OR_RETURN(fiasco, checksum, &byte, 1);
READ_OR_RETURN(fiasco, checksum, &length8, 1);
READ_OR_RETURN(fiasco, checksum, buf, length8);
VERBOSE(" subinfo\n");
VERBOSE(" length: %d\n", length8);
@@ -207,15 +242,55 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
memset(layout, 0, sizeof(layout));
strncpy(layout, (char *)buf, length8);
VERBOSE("layout\n");
} else if ( byte == '4' ) {
VERBOSE("data part\n");
if ( length8 < 16 ) {
VERBOSE(" (damaged)\n");
} else {
VERBOSE("unknown ('%c':%#x)\n", byte, byte);
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 {
int i;
VERBOSE("unknown (%#x)\n", byte);
VERBOSE(" hexdump:");
for ( i = 0; i < length8; i++ ) VERBOSE(" 0x%02x", buf[i]);
VERBOSE("\n");
}
--count8;
}
/* unknown */
READ_OR_RETURN(fiasco, buf, 1);
/* 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;
}
offset = lseek(fiasco->fd, 0, SEEK_CUR);
if ( offset == (off_t)-1 )
@@ -226,7 +301,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 = image_alloc_from_shared_fd(fiasco->fd, length, offset, hash, type, device, hwrevs, version, layout, image_parts);
if ( ! image )
FIASCO_READ_ERROR(fiasco, "Cannot allocate image");
@@ -274,10 +349,12 @@ 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];
@@ -375,32 +452,40 @@ 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;
length8 = device_count+2;
if ( image->version )
++length8;
if ( image->layout )
++length8;
WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs);
CHECKSUM(checksum, &length8, 1);
/* unknown */
/* file data: asic index: APE (0x01), device type: NAND (0x01), device index: 0 */
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);
/* unknown */
/* image load address (unused always zero) */
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 ) {
@@ -408,6 +493,9 @@ 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 */
@@ -416,6 +504,9 @@ 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);
@@ -425,10 +516,47 @@ 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);
}
/* dummy byte - end of all subsections */
WRITE_OR_FAIL(file, fd, "\x00", 1);
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, length-16);
CHECKSUM(checksum, image_part->name, length-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);
printf("Writing image data...\n");
@@ -461,8 +589,10 @@ 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 size;
uint32_t offset, size, need, total_size, written;
int part_num;
char cwd[256];
unsigned char buf[4096];
@@ -489,68 +619,30 @@ 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 ) {
layout_name = calloc(1, strlen(name) + sizeof(".layout")-1 + 1);
name = image_name_alloc_from_values(image, -1);
if ( ! name )
ALLOC_ERROR_RETURN(-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", name);
sprintf(layout_name, "%s_layout", name);
free(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 ) {
@@ -571,11 +663,73 @@ 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
View File
@@ -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 SLEEP(usec) do { struct timespec _t = { 0, (usec) }; nanosleep(&_t, NULL); } while (0)
#define MSLEEP(msec) do { nanosleep(&(struct timespec){ (msec / 1000), (1000L * 1000L * (msec % 1000)) }, 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 ) {
+65 -20
View File
@@ -100,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) {
char * image_name_alloc_from_values(struct image * image, int part_num) {
char * name;
char * ptr;
@@ -108,6 +108,8 @@ char * image_name_alloc_from_values(struct image * image) {
size_t length;
const char * type;
const char * device;
struct image_part * part;
int i;
type = image_type_to_string(image->type);
@@ -124,6 +126,14 @@ char * image_name_alloc_from_values(struct image * image) {
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 )
@@ -132,6 +142,10 @@ char * image_name_alloc_from_values(struct image * image) {
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 ) {
@@ -149,21 +163,29 @@ char * image_name_alloc_from_values(struct image * image) {
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) {
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) {
enum image_type detected_type;
image->hash = image_hash_from_data(image);
image->devices = calloc(1, sizeof(struct device_list));
if ( ! image->devices )
return -1;
if ( ! image->devices ) {
image_free(image);
ALLOC_ERROR_RETURN(-1);
}
image->devices->device = DEVICE_ANY;
@@ -208,6 +230,8 @@ static int image_append(struct image * image, const char * type, const char * de
else
image->layout = NULL;
image->parts = parts;
return 0;
}
@@ -242,24 +266,35 @@ 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 * 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) {
off_t offset;
struct image * image = image_alloc();
if ( ! image )
return NULL;
int fd;
image->is_shared_fd = 0;
image->fd = open(file, O_RDONLY);
if ( image->fd < 0 ) {
fd = open(file, O_RDONLY);
if ( fd < 0 ) {
ERROR_INFO("Cannot open image file %s", file);
free(image);
return NULL;
}
return image_alloc_from_fd(fd, file, type, device, hwrevs, version, layout, 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) {
off_t offset;
struct image * image = image_alloc();
if ( ! image ) {
close(fd);
return NULL;
}
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", file);
ERROR_INFO("Cannot seek to end of file %s", orig_filename);
close(image->fd);
free(image);
return NULL;
@@ -268,21 +303,21 @@ struct image * image_alloc_from_file(const char * file, const char * type, const
image->size = offset;
image->offset = 0;
image->cur = 0;
image->orig_filename = strdup(file);
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", file);
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 )
if ( image_append(image, type, device, hwrevs, version, layout, parts) < 0 )
return NULL;
if ( ( ! type || ! type[0] ) && ( ! device || ! device[0] ) && ( ! hwrevs || ! hwrevs[0] ) && ( ! version || ! version[0] ) )
image_missing_values_from_name(image, file);
image_missing_values_from_name(image, orig_filename);
image_align(image);
@@ -290,7 +325,7 @@ struct image * image_alloc_from_file(const char * file, const char * type, const
}
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_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 = image_alloc();
if ( ! image )
@@ -302,7 +337,7 @@ struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, ui
image->offset = offset;
image->cur = 0;
if ( image_append(image, type, device, hwrevs, version, layout) < 0 )
if ( image_append(image, type, device, hwrevs, version, layout, parts) < 0 )
return NULL;
if ( ! noverify && image->hash != hash ) {
@@ -334,6 +369,13 @@ 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);
@@ -503,6 +545,9 @@ 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) {
+15 -3
View File
@@ -37,9 +37,19 @@ 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 {
enum image_type type;
struct device_list * devices;
@@ -47,6 +57,7 @@ struct image {
char * layout;
uint16_t hash;
uint32_t size;
struct image_part * parts;
int fd;
int is_shared_fd;
@@ -63,8 +74,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 * 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_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_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_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);
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);
@@ -75,7 +87,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);
char * image_name_alloc_from_values(struct image * image, int part_num);
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);
+257 -47
View File
@@ -19,6 +19,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/statvfs.h>
#include <sys/types.h>
@@ -198,14 +199,6 @@ 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;
@@ -227,15 +220,18 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
return 1;
}
size = snprintf(NULL, 0, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
size = snprintf(NULL, 0, "nanddump --omitoob -s %d -l %d -f %s /dev/mtd%d", offset, length, file, mtd);
command = malloc(size+1);
if ( ! command )
return 1;
snprintf(command, size+1, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
snprintf(command, size+1, "nanddump --omitoob -s %d -l %d -f %s /dev/mtd%d", offset, length, file, mtd);
if ( ! simulate )
ret = system(command);
else
ret = 0;
free(command);
@@ -243,52 +239,77 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
}
struct nanddump_args {
int valid;
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;
};
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 },
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 },
};
/* FIXME: Is this table correct? */
static struct nanddump_args nanddump_rx4x[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x0021F800 },
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00400000 },
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0f960000 },
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 },
};
/* FIXME: Is this table correct? */
static struct nanddump_args nanddump_old[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x001FF800 },
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00200000 },
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0fb80000 },
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 },
};
struct nanddump_device {
struct nand_device {
size_t count;
struct nanddump_args * args;
struct nandpart_args * args;
};
#define NANDDUMP(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array }
#define NAND_DEVICE(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array }
static struct nanddump_device nanddump[] = {
NANDDUMP(DEVICE_SU_18, nanddump_old),
NANDDUMP(DEVICE_RX_34, nanddump_old),
NANDDUMP(DEVICE_RX_44, nanddump_rx4x),
NANDDUMP(DEVICE_RX_48, nanddump_rx4x),
NANDDUMP(DEVICE_RX_51, nanddump_rx51),
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),
};
#undef NANDDUMP
@@ -380,10 +401,13 @@ 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, len;
off_t nlen = (off_t)-1;
off_t len;
int align;
int maj, min;
@@ -415,17 +439,49 @@ int local_dump_image(enum image_type image, const char * file) {
} else {
if ( device >= sizeof(nanddump)/sizeof(nanddump[0]) ) {
if ( device >= sizeof(nand_device)/sizeof(nand_device[0]) ) {
ERROR("Unsupported device");
goto clean;
}
if ( image >= nanddump[device].count ) {
if ( image >= nand_device[device].count ) {
ERROR("Unsupported image type: %s", image_type_to_string(image));
goto clean;
}
ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset, nanddump[device].args[image].length);
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);
}
@@ -434,6 +490,9 @@ 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;
@@ -442,6 +501,8 @@ 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);
if ( addr == MAP_FAILED )
@@ -466,7 +527,9 @@ int local_dump_image(enum image_type image, const char * file) {
if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
nlen = ((nlen >> align) + 1) << align;
if ( nlen == 0 ) {
}
if ( header <= 0 && nlen == 0 ) {
printf("File %s is empty, removing it...\n", file);
unlink(file);
} else if ( nlen != len ) {
@@ -487,6 +550,153 @@ 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");
+75 -21
View File
@@ -143,7 +143,7 @@ int simulate;
int noverify;
int verbose;
/* arg = [[[dev:[hw:]]ver:]type:]file[%%lay] */
/* arg = [[[dev:[hw:]]ver:]type:]file[%file2%file3...%lay] */
static void parse_image_arg(char * arg, struct image_list ** image_first) {
struct stat st;
@@ -154,11 +154,16 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
char * hwrevs;
char * version;
char * layout;
char * parts;
char * layout_file;
char * ptr;
int fd;
/* First check if arg is file, then try to parse arg format */
if ( stat(arg, &st) == 0 ) {
image = image_alloc_from_file(arg, NULL, NULL, NULL, NULL, NULL);
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);
if ( ! image ) {
ERROR("Cannot load image file %s", arg);
exit(1);
@@ -166,10 +171,21 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
image_list_add(image_first, image);
return;
}
close(fd);
} else if ( errno != ENOENT ) {
ERROR("Cannot load image file %s", arg);
exit(1);
}
layout_file = strchr(arg, '%');
if ( layout_file )
*(layout_file++) = 0;
parts = strchr(arg, '%');
if ( parts )
*(parts++) = 0;
layout_file = parts;
if ( layout_file ) {
while ( ( ptr = strchr(layout_file, '%') ) )
layout_file = ptr+1;
}
type = NULL;
device = NULL;
@@ -229,7 +245,9 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
close(fd);
}
image = image_alloc_from_file(file, type, device, hwrevs, version, layout);
/* TODO: alloc parts */
image = image_alloc_from_file(file, type, device, hwrevs, version, layout, NULL);
if ( layout )
free(layout);
@@ -413,9 +431,13 @@ 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];
@@ -1026,9 +1048,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 )
if ( detected_hwrev > 0 )
filter_images_by_hwrev(dev->detected_hwrev, &image_first);
if ( fiasco_in && ( detected_device || detected_hwrev ) )
if ( fiasco_in && ( detected_device || detected_hwrev > 0 ) )
fiasco_in->first = image_first;
/* set kernel and initfs images for loading */
@@ -1086,7 +1108,7 @@ int main(int argc, char **argv) {
if ( dev_load ) {
if ( image_kernel ) {
ret = dev_load_image(dev, image_kernel->image);
if ( ret < 0 )
if ( ret == -EAGAIN )
goto again;
if ( image_kernel == image_first )
@@ -1100,7 +1122,7 @@ int main(int argc, char **argv) {
if ( image_initfs ) {
ret = dev_load_image(dev, image_initfs->image);
if ( ret < 0 )
if ( ret == -EAGAIN )
goto again;
if ( image_initfs == image_first )
@@ -1119,7 +1141,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 < 0 )
if ( ret == -EAGAIN )
goto again;
if ( image_ptr == image_first )
@@ -1239,6 +1261,8 @@ int main(int argc, char **argv) {
if ( chdir(buf) < 0 )
ERROR_INFO("Cannot chdir back to %s", buf);
printf("Done\n");
}
/* dump fiasco */
@@ -1249,10 +1273,11 @@ int main(int argc, char **argv) {
for ( i = 0; i < IMAGE_COUNT; ++i ) {
if ( ! image_tmp_name(i) )
if ( ! image_tmp_name(i) || ( stat(image_tmp_name(i), &st) < 0 && errno == ENOENT ) )
continue;
buf[0] = 0;
if ( dev->detected_hwrev > 0 )
snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev);
switch ( i ) {
@@ -1283,7 +1308,9 @@ int main(int argc, char **argv) {
break;
}
image_dump = image_alloc_from_file(image_tmp_name(i), image_type_to_string(i), device_to_string(dev->detected_device), buf, ptr, NULL);
/* 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);
if ( ! image_dump )
continue;
@@ -1319,14 +1346,12 @@ int main(int argc, char **argv) {
for ( i = 0; i < IMAGE_COUNT; ++i ) {
struct stat st;
int rename_ret;
int rename_errno;
if ( ! image_tmp_name(i) )
continue;
if ( stat(image_tmp_name(i), &st) != 0 )
continue;
switch ( i ) {
case IMAGE_2ND:
case IMAGE_XLOADER:
@@ -1356,15 +1381,42 @@ int main(int argc, char **argv) {
}
buf[0] = 0;
snprintf(buf, sizeof(buf), "%s-%s:%hd_%s", image_type_to_string(i), device_to_string(dev->detected_device), dev->detected_hwrev, ptr);
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);
rename_ret = rename(image_tmp_name(i), buf);
rename_errno = errno;
if ( rename_ret < 0 && rename_errno == ENOENT )
continue;
printf("Renaming %s image file to %s...\n", image_type_to_string(i), buf);
if ( rename_ret < 0 ) {
errno = rename_errno;
ERROR_INFO("Renaming failed");
*ptr2 = 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");
buf[0] = 0;
snprintf(buf, sizeof(buf), "%s-%s_%s", image_type_to_string(i), device_to_string(dev->detected_device), ptr);
*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 )
@@ -1376,6 +1428,8 @@ int main(int argc, char **argv) {
}
}
/* boot */
if ( dev_boot ) {
dev_boot_device(dev, dev_boot_arg);
+16 -7
View File
@@ -213,14 +213,18 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
msg1 = (struct mkii_message *)buf1;
ptr = msg->data;
/* Signature */
memcpy(ptr, "\x2E\x19\x01\x01", 4);
ptr += 4;
/* Space */
memcpy(ptr, "\x00", 1);
/* File data header */
memcpy(ptr, "\x2E", 1);
ptr += 1;
/* Length of file data */
memcpy(ptr, "\x19", 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);
@@ -239,7 +243,7 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
memcpy(ptr, &size, 4);
ptr += 4;
/* Space */
/* Load address (ignored) */
memcpy(ptr, "\x00\x00\x00\x00", 4);
ptr += 4;
@@ -361,6 +365,11 @@ 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;
}
+12 -8
View File
@@ -269,14 +269,18 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
ptr = buf;
/* Signature */
memcpy(ptr, "\x2E\x19\x01\x01", 4);
ptr += 4;
/* Space */
memcpy(ptr, "\x00", 1);
/* File data header */
memcpy(ptr, "\x2E", 1);
ptr += 1;
/* Length of file data */
memcpy(ptr, "\x19", 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);
@@ -295,7 +299,7 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
memcpy(ptr, &size, 4);
ptr += 4;
/* Space */
/* Load address (ignored by NOLO) */
memcpy(ptr, "\x00\x00\x00\x00", 4);
ptr += 4;
@@ -541,7 +545,7 @@ int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
}
SLEEP(0xc350); // 0.5s
MSLEEP(50);
}
+4 -1
View File
@@ -91,8 +91,11 @@ clean:
void dev_free(struct device_info * dev) {
if ( dev->usb )
if ( dev->usb ) {
if ( dev->usb->flash_device->protocol == FLASH_DISK )
disk_exit(dev->usb);
usb_close_device(dev->usb);
}
free(dev);
}
+39 -30
View File
@@ -46,16 +46,21 @@
#endif
static struct usb_flash_device usb_devices[] = {
{ 0x0421, 0x0096, -1, -1, -1, FLASH_DISK, { DEVICE_RX_44, 0 } },
{ 0x0421, 0x0105, 2, 1, -1, FLASH_NOLO, { DEVICE_SU_18, 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 } },
/* 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) */
};
static const char * usb_flash_protocols[] = {
@@ -134,7 +139,7 @@ static void usb_descriptor_info_print(usb_dev_handle * udev, struct usb_device *
buf[0] = 0;
for ( i = 0; i < ret; i+=2 ) {
sscanf(buf+i, "%2x", &x);
if ( x > 32 && x < 128 )
if ( x > 31 && x < 127 )
buf2[i/2] = x;
else {
buf2[0] = 0;
@@ -150,14 +155,29 @@ static void usb_descriptor_info_print(usb_dev_handle * udev, struct usb_device *
static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
int i;
size_t i;
char product[1024];
struct usb_device_info * ret = NULL;
for ( i = 0; usb_devices[i].vendor; ++i ) {
for ( i = 0; i < sizeof(usb_devices)/sizeof(usb_devices[0]); ++i ) {
if ( dev->descriptor.idVendor == usb_devices[i].vendor && dev->descriptor.idProduct == usb_devices[i].product ) {
if ( usb_devices[i].protocol == FLASH_UNKN )
continue;
if ( dev->descriptor.bNumConfigurations < 1 )
continue;
if ( usb_devices[i].interface != -1 ) {
if ( usb_devices[i].interface >= dev->config[0].bNumInterfaces )
continue;
if ( usb_devices[i].alternate != -1 ) {
if ( usb_devices[i].alternate >= dev->config[0].interface[usb_devices[i].interface].num_altsetting )
continue;
}
}
printf("\b\b ");
PRINTF_END();
PRINTF_ADD("Found ");
@@ -195,18 +215,7 @@ static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
if ( usb_devices[i].alternate >= 0 ) {
PRINTF_LINE("Setting alternate USB interface...");
if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
PRINTF_ERROR("usb_claim_interface failed");
fprintf(stderr, "\n");
usb_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");
PRINTF_ERROR("usb_set_altinterface failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
@@ -230,13 +239,13 @@ static struct usb_device_info * usb_device_is_valid(struct usb_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 )
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 )
ret->device = DEVICE_RX_51;
else if ( strcmp(product, "Nokia N950") == 0 || strcmp(product, "Sync Mode") == 0 || strcmp(product, "N950 (Update mode)") == 0 )
else if ( strcmp(product, "Nokia N950") == 0 || strcmp(product, "N950 (Update mode)") == 0 )
ret->device = DEVICE_RM_680;
else if ( strcmp(product, "N9 (Update mode)") == 0 || strcmp(product, "Nxy (Update mode)") == 0 )
else if ( strcmp(product, "Nokia N9") == 0 || strcmp(product, "N9 (Update mode)") == 0 || strcmp(product, "Nokia N9 RNDIS/Ethernet") == 0 )
ret->device = DEVICE_RM_696;
else if ( strcmp(product, "Nokia USB ROM") == 0 )
else if ( strcmp(product, "Nokia USB ROM") == 0 || strcmp(product, "Sync Mode") == 0 || strcmp(product, "Nxy (Update mode)") == 0 )
ret->device = DEVICE_ANY;
else
ret->device = DEVICE_UNKNOWN;
@@ -361,7 +370,7 @@ struct usb_device_info * usb_open_and_wait_for_device(void) {
if ( ret )
break;
SLEEP(0xc350); // 0.5s
MSLEEP(50);
}
-1
View File
@@ -49,7 +49,6 @@ struct usb_flash_device {
uint16_t product;
int interface;
int alternate;
int configuration;
enum usb_flash_protocol protocol;
enum device devices[DEVICE_COUNT];
};