Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6b0a7be3a | ||
|
|
8a9e2759d4 | ||
|
|
bacbb0165b | ||
|
|
df2340e48d | ||
|
|
a5279bffaf | ||
|
|
b46e4a6ad5 | ||
|
|
e65d7d1636 | ||
|
|
1f466936cb | ||
|
|
df8e50a824 | ||
|
|
4f45b045c3 | ||
|
|
3c4943340b | ||
|
|
ce67a58983 | ||
|
|
a6b6b71ded | ||
|
|
580f1de0fe | ||
|
|
f9e88d6f91 | ||
|
|
ca035e2ec1 | ||
|
|
5c0720da32 | ||
|
|
374fd1be01 | ||
|
|
f144067634 | ||
|
|
bbf438e1a8 | ||
|
|
670db0d169 | ||
|
|
6eb58dcccb | ||
|
|
b090564a85 | ||
|
|
38f83f8db4 | ||
|
|
342dc610b3 | ||
|
|
67427daf17 | ||
|
|
bf24ca2345 | ||
|
|
5c845a947e | ||
|
|
673ccaf71d | ||
|
|
9bc4b8c26f | ||
|
|
e6422cf5a2 | ||
|
|
a6effa8f62 | ||
|
|
e16a79f75e | ||
|
|
93bd73d451 | ||
|
|
0e5ceffa42 | ||
|
|
ca080dd33f | ||
|
|
4ae1f13624 | ||
|
|
69a7c2705e | ||
|
|
8d053c9074 | ||
|
|
f37c2cd7e8 | ||
|
|
e94279eecb | ||
|
|
52793b733d | ||
|
|
4bd0a47b22 | ||
|
|
adeca0dd45 | ||
|
|
b87411c02f | ||
|
|
7f38b4bd10 | ||
|
|
9e5646d30e | ||
|
|
33442482c6 | ||
|
|
e987dcd948 | ||
|
|
2fd11378c8 | ||
|
|
808ce724ee | ||
|
|
ca1db96690 | ||
|
|
a6c20b5ee4 | ||
|
|
e685787e67 | ||
|
|
10b495120e | ||
|
|
559fe2a3bd | ||
|
|
ccec7a182f | ||
|
|
31569c169a | ||
|
|
27a55c3367 | ||
|
|
cda5dc6116 | ||
|
|
5cbd5e92b8 | ||
|
|
1ec3777cb8 | ||
|
|
897919a70f | ||
|
|
76b18b9d39 | ||
|
|
ffcc10f689 | ||
|
|
16cdf3e776 | ||
|
|
dc81ebb855 | ||
|
|
66ecce9a3d | ||
|
|
87867a5904 | ||
|
|
f0b8ee117b | ||
|
|
4c8206b44f |
No files matched your search
+20
-10
@@ -1,22 +1,28 @@
|
|||||||
|
sudo: false
|
||||||
|
|
||||||
language: c
|
language: c
|
||||||
|
|
||||||
|
arch:
|
||||||
|
- AMD64
|
||||||
|
- ppc64le
|
||||||
|
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
before_install:
|
|
||||||
- sudo apt-get update -qq
|
addons: &addons
|
||||||
- sudo apt-get install -qq -y libusb-dev
|
apt:
|
||||||
script: if [ "${COVERITY_SCAN_BRANCH}" != 1 ]; then make ; fi
|
packages:
|
||||||
|
- libusb-dev
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
exclude:
|
include:
|
||||||
- compiler: clang
|
- compiler: gcc
|
||||||
- env: COVERITY_SCAN_BRANCH=1
|
if: (branch = master) AND (type != pull_request)
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
|
||||||
- secure: "JdUp+xFykPZoYA4aRfmYk2CtilLapniQllWPKo2dDdJd1vzdawfTvVxIAKjy7ac9RKwZzg3Chq3RsMEXPv8BtaLbssw266C7RDLMgjacl1eFLcmGRj/Gkk9peDSZ6vVdGEcA2j+6KDSfpCa/XjFjvOufZOgKw6m+3+d0A4G45SI="
|
- secure: "JdUp+xFykPZoYA4aRfmYk2CtilLapniQllWPKo2dDdJd1vzdawfTvVxIAKjy7ac9RKwZzg3Chq3RsMEXPv8BtaLbssw266C7RDLMgjacl1eFLcmGRj/Gkk9peDSZ6vVdGEcA2j+6KDSfpCa/XjFjvOufZOgKw6m+3+d0A4G45SI="
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
|
<<: *addons
|
||||||
coverity_scan:
|
coverity_scan:
|
||||||
project:
|
project:
|
||||||
name: "pali/0xFFFF"
|
name: "pali/0xFFFF"
|
||||||
@@ -24,3 +30,7 @@ addons:
|
|||||||
notification_email: pali.rohar@gmail.com
|
notification_email: pali.rohar@gmail.com
|
||||||
build_command: make
|
build_command: make
|
||||||
branch_pattern: master
|
branch_pattern: master
|
||||||
|
|
||||||
|
script:
|
||||||
|
- if [ -n "$COVERITY_SCAN_TOKEN" ]; then exit 0; fi
|
||||||
|
- make
|
||||||
@@ -10,24 +10,24 @@
|
|||||||
_/ ___|_.|__|
|
_/ ___|_.|__|
|
||||||
'`
|
'`
|
||||||
|
|
||||||
0xFFFF is Open Free Fiasco Firmware Flasher for Maemo devices. It support
|
0xFFFF is the Open Free Fiasco Firmware Flasher for Maemo devices. It supports
|
||||||
generating and unpacking FIASCO images on local computer. Useful for editing
|
generating and unpacking FIASCO images. It is useful for editing Maemo firmware
|
||||||
Maemo firmware package for future flash. It support via USB flashing any image
|
packages before flashing. It supports flashing via USB any image type to a
|
||||||
type to Maemo device and also \"cold\" flashing which means flashing dead device
|
Maemo device and also \"cold\" flashing which means flashing dead device with
|
||||||
with erased bootloader. There is support for booting kernel via USB without
|
erased bootloader. There is support for booting kernel via USB without flashing
|
||||||
flashing to NAND and also changing configuration of Maemo device (enable/disable
|
to NAND and also changing configuration of Maemo device (enable/disable R&D
|
||||||
R&D mode, changing HW revision strings, ...).
|
mode, changing HW revision strings, ...).
|
||||||
|
|
||||||
0xFFFF is alternative tool to proprietary Nokia flasher-3.5 and fiasco-gen.
|
0xFFFF is an alternative tool to proprietary Nokia flasher-3.5 and fiasco-gen.
|
||||||
0xFFFF generate compatible FIASCO images and also accept FIASCO images generated
|
0xFFFF generates compatible FIASCO images and also accepts FIASCO images
|
||||||
by Nokia fiasco-gen.
|
generated by Nokia fiasco-gen.
|
||||||
|
|
||||||
Use it with CARE. This is an experimental tool and it can brick your device.
|
Use it with CARE. This is an experimental tool and it can brick your device.
|
||||||
It's not suposed to be stable, so nokia will probably release incompatible
|
It's not supposed to be stable, so Nokia will probably release incompatible
|
||||||
bootloaders to break this tool. USE IT AT YOUR OWN RISK.
|
bootloaders to break this tool. USE IT AT YOUR OWN RISK.
|
||||||
|
|
||||||
PLEASE. Read carefully all the documentation inside doc/* for more information
|
PLEASE. Read all the documentation inside doc/* carefully before building or
|
||||||
before building or using the flasher to avoid questions, problems or so.
|
using the flasher to avoid questions, problems or so.
|
||||||
|
|
||||||
https://github.com/pali/0xFFFF
|
https://github.com/pali/0xFFFF
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ cold-flash:
|
|||||||
* Detect device from asic id
|
* Detect device from asic id
|
||||||
|
|
||||||
disk:
|
disk:
|
||||||
* Support for flashing mmc images
|
|
||||||
* Badblock checking
|
* Badblock checking
|
||||||
|
|
||||||
fiasco:
|
fiasco:
|
||||||
@@ -15,7 +14,6 @@ image:
|
|||||||
* Support for Harmattan images
|
* Support for Harmattan images
|
||||||
|
|
||||||
local:
|
local:
|
||||||
* Support for flashing (on device)
|
|
||||||
* Write versions
|
* Write versions
|
||||||
* Badblock checking
|
* Badblock checking
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
VERSION = 0.7
|
VERSION = 0.10
|
||||||
PREFIX = /usr/local
|
PREFIX = /usr/local
|
||||||
|
|
||||||
# NetBSD stuff
|
# NetBSD stuff
|
||||||
|
|||||||
+2
-3
@@ -30,11 +30,10 @@ Technical details:
|
|||||||
For dumping mtd partition is used tool nanddump. Here is example how to dump
|
For dumping mtd partition is used tool nanddump. Here is example how to dump
|
||||||
kernel image without padding to file zImage:
|
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:
|
Params means:
|
||||||
-o - "Omit oob data"
|
--omitoob - "Omit oob data"
|
||||||
-b - "Omit bad blocks"
|
|
||||||
-s - "Start address"
|
-s - "Start address"
|
||||||
-l - "Length"
|
-l - "Length"
|
||||||
-f - "Output file"
|
-f - "Output file"
|
||||||
|
|||||||
+55
-15
@@ -38,24 +38,64 @@ IMAGE
|
|||||||
|
|
||||||
1 byte = 0x54 -- signature
|
1 byte = 0x54 -- signature
|
||||||
1 byte -- number of subsection blocks
|
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 {
|
block {
|
||||||
1 byte -- type of subsection block
|
1 byte -- type of subsection block
|
||||||
'1' - version
|
0x2E - file data
|
||||||
'2' - device & hw revisions (size of device is 16, hw revision 8)
|
0x2F - partition info
|
||||||
'3' - layout
|
0x31 - version
|
||||||
'4' - unknown
|
0x32 - device & hw revisions (size of device is 16, hw revision 8)
|
||||||
'/' - unknown
|
0x33 - layout
|
||||||
|
0x34 - image data part block (one block for one data part)
|
||||||
1 byte -- length of subsection block
|
1 byte -- length of subsection block
|
||||||
N bytes -- subsection block data
|
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
|
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
@@ -5,9 +5,9 @@ INSTALL ?= install
|
|||||||
|
|
||||||
BUILD_DATE ?= $(shell LC_ALL=C date '+%b %e %Y')
|
BUILD_DATE ?= $(shell LC_ALL=C date '+%b %e %Y')
|
||||||
|
|
||||||
CC = gcc
|
CC ?= cc
|
||||||
CROSS_CC = $(CROSS_COMPILE)$(CC)
|
CROSS_CC ?= $(CROSS_COMPILE)$(CC)
|
||||||
HOST_CC = $(HOST_COMPILE)$(CC)
|
HOST_CC ?= $(HOST_COMPILE)$(CC)
|
||||||
|
|
||||||
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DBUILD_DATE="\"$(BUILD_DATE)\"" -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64
|
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DBUILD_DATE="\"$(BUILD_DATE)\"" -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64
|
||||||
CFLAGS += -W -Wall -O2 -pedantic -std=c99
|
CFLAGS += -W -Wall -O2 -pedantic -std=c99
|
||||||
|
|||||||
@@ -76,14 +76,14 @@ int cal_init_file(const char * file, struct cal ** cal_out) {
|
|||||||
off_t lsize = 0;
|
off_t lsize = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( stat(file, &st) != 0 )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
fd = open(file, O_RDONLY);
|
fd = open(file, O_RDONLY);
|
||||||
|
|
||||||
if ( fd < 0 )
|
if ( fd < 0 )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if ( fstat(fd, &st) != 0 )
|
||||||
|
goto err;
|
||||||
|
|
||||||
if ( S_ISREG(st.st_mode) )
|
if ( S_ISREG(st.st_mode) )
|
||||||
size = st.st_size;
|
size = st.st_size;
|
||||||
else if ( S_ISBLK(st.st_mode) ) {
|
else if ( S_ISBLK(st.st_mode) ) {
|
||||||
|
|||||||
+7
-7
@@ -191,14 +191,14 @@ static int send_2nd(usb_dev_handle * udev, struct image * image) {
|
|||||||
if ( ret != sizeof(omap_peripheral_msg) )
|
if ( ret != sizeof(omap_peripheral_msg) )
|
||||||
ERROR_RETURN("Sending OMAP peripheral boot message failed", -1);
|
ERROR_RETURN("Sending OMAP peripheral boot message failed", -1);
|
||||||
|
|
||||||
SLEEP(5000);
|
MSLEEP(5);
|
||||||
|
|
||||||
printf("Sending 2nd X-Loader image size...\n");
|
printf("Sending 2nd X-Loader image size...\n");
|
||||||
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&image->size, 4, WRITE_TIMEOUT);
|
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&image->size, 4, WRITE_TIMEOUT);
|
||||||
if ( ret != 4 )
|
if ( ret != 4 )
|
||||||
ERROR_RETURN("Sending 2nd X-Loader image size failed", -1);
|
ERROR_RETURN("Sending 2nd X-Loader image size failed", -1);
|
||||||
|
|
||||||
SLEEP(5000);
|
MSLEEP(5);
|
||||||
|
|
||||||
printf("Sending 2nd X-Loader image...\n");
|
printf("Sending 2nd X-Loader image...\n");
|
||||||
printf_progressbar(0, image->size);
|
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);
|
printf_progressbar(sent, image->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
SLEEP(50000);
|
MSLEEP(50);
|
||||||
return 0;
|
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);
|
ERROR_RETURN("Sending X-Loader init message failed", -1);
|
||||||
|
|
||||||
printf("Waiting for X-Loader response...\n");
|
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 */
|
ret = usb_bulk_read(udev, USB_READ_EP, (char *)&buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
|
||||||
if ( ret != 4 )
|
if ( ret != 4 )
|
||||||
ERROR_RETURN("No response", -1);
|
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");
|
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 */
|
ret = usb_bulk_read(udev, USB_READ_EP, (char *)&buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
|
||||||
if ( ret != 4 )
|
if ( ret != 4 )
|
||||||
ERROR_RETURN("No response", -1);
|
ERROR_RETURN("No response", -1);
|
||||||
@@ -296,7 +296,7 @@ static int ping_timeout(usb_dev_handle * udev) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLEEP(5000);
|
MSLEEP(5);
|
||||||
--try_read;
|
--try_read;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -413,7 +413,7 @@ int leave_cold_flash(struct usb_device_info * dev) {
|
|||||||
if ( ret != sizeof(omap_memory_msg) )
|
if ( ret != sizeof(omap_memory_msg) )
|
||||||
ERROR_RETURN("Sending OMAP memory boot message failed", -1);
|
ERROR_RETURN("Sending OMAP memory boot message failed", -1);
|
||||||
|
|
||||||
SLEEP(1000000);
|
MSLEEP(250);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
+5
-3
@@ -184,9 +184,11 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( device_first->hwrevs ) {
|
||||||
for ( i = 0; device_first->hwrevs[i] != -1; ++i )
|
for ( i = 0; device_first->hwrevs[i] != -1; ++i )
|
||||||
if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 )
|
if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 )
|
||||||
++local;
|
++local;
|
||||||
|
}
|
||||||
|
|
||||||
size += (1+16+(MAX_HWREVS+1)*8)*(local/MAX_HWREVS+1);
|
size += (1+16+(MAX_HWREVS+1)*8)*(local/MAX_HWREVS+1);
|
||||||
count += local/MAX_HWREVS;
|
count += local/MAX_HWREVS;
|
||||||
@@ -215,7 +217,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( device_first->hwrevs[i+1] != -1 ) {
|
do {
|
||||||
|
|
||||||
uint8_t len = 0;
|
uint8_t len = 0;
|
||||||
ret[j] = ++last_ptr;
|
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 ) {
|
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;
|
break;
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
@@ -246,7 +248,7 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
|
|||||||
|
|
||||||
++j;
|
++j;
|
||||||
|
|
||||||
}
|
} while ( device_first->hwrevs && device_first->hwrevs[i+1] != -1 );
|
||||||
|
|
||||||
device_first = device_first->next;
|
device_first = device_first->next;
|
||||||
|
|
||||||
|
|||||||
+160
-40
@@ -51,6 +51,7 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
|
|||||||
DIR * dir;
|
DIR * dir;
|
||||||
struct dirent * dirent;
|
struct dirent * dirent;
|
||||||
int found;
|
int found;
|
||||||
|
int old_errno;
|
||||||
size_t len;
|
size_t len;
|
||||||
char blkdev[1024];
|
char blkdev[1024];
|
||||||
|
|
||||||
@@ -117,6 +118,18 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
|
|||||||
|
|
||||||
blkdev[len] = 0;
|
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 ) {
|
} else if ( partition > 0 ) {
|
||||||
|
|
||||||
/* Select partition */
|
/* Select partition */
|
||||||
@@ -127,35 +140,48 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(blkdev+len, "p1", 3);
|
if ( snprintf(blkdev+len, sizeof(blkdev)-len, "p%d", partition) >= (int)(sizeof(blkdev)-len) ) {
|
||||||
if ( stat(blkdev, &st) != 0 || ! S_ISBLK(st.st_mode) ) {
|
ERROR("Block device name is too long");
|
||||||
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);
|
|
||||||
return -1;
|
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 {
|
} else {
|
||||||
close(fd);
|
close(fd);
|
||||||
ERROR("Block device does not have partitions");
|
ERROR("Block device %s does not have partitions", blkdev);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
if ( fd < 0 )
|
||||||
}
|
old_errno = errno;
|
||||||
|
|
||||||
printf("Found block device %s for partition %d\n", blkdev, partition);
|
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;
|
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 disk_dump_dev(int fd, const char * file) {
|
||||||
|
|
||||||
int fd2;
|
int fd2 = -1;
|
||||||
int ret;
|
int ret;
|
||||||
char * path;
|
char * path;
|
||||||
uint64_t blksize;
|
uint64_t blksize;
|
||||||
@@ -195,7 +221,7 @@ int disk_dump_dev(int fd, const char * file) {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
blksize = lseek(fd, 0, SEEK_END);
|
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");
|
ERROR_INFO("Cannot get size of block device");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -207,11 +233,6 @@ int disk_dump_dev(int fd, const char * file) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ( blksize > ULLONG_MAX ) {
|
|
||||||
ERROR("Block device is too big");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( blksize == 0 ) {
|
if ( blksize == 0 ) {
|
||||||
ERROR("Block device has zero size");
|
ERROR("Block device has zero size");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -232,6 +253,8 @@ int disk_dump_dev(int fd, const char * file) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ! simulate ) {
|
||||||
|
|
||||||
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
|
|
||||||
if ( fd2 < 0 ) {
|
if ( fd2 < 0 ) {
|
||||||
@@ -239,6 +262,8 @@ int disk_dump_dev(int fd, const char * file) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
sent = 0;
|
sent = 0;
|
||||||
printf_progressbar(0, blksize);
|
printf_progressbar(0, blksize);
|
||||||
|
|
||||||
@@ -249,26 +274,91 @@ int disk_dump_dev(int fd, const char * file) {
|
|||||||
size = read(fd, global_buf, need);
|
size = read(fd, global_buf, need);
|
||||||
if ( size == 0 )
|
if ( size == 0 )
|
||||||
break;
|
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 ) {
|
if ( write(fd2, global_buf, size) != size ) {
|
||||||
PRINTF_ERROR("Dumping image failed");
|
PRINTF_ERROR("Dumping image failed");
|
||||||
close(fd2);
|
close(fd2);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sent += size;
|
sent += size;
|
||||||
printf_progressbar(sent, blksize);
|
printf_progressbar(sent, blksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( ! simulate )
|
||||||
close(fd2);
|
close(fd2);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int disk_flash_dev(int fd, const char * file) {
|
int disk_flash_dev(int fd, struct image * image) {
|
||||||
|
|
||||||
ERROR("Not implemented yet");
|
uint64_t blksize;
|
||||||
(void)fd;
|
size_t need, sent;
|
||||||
(void)file;
|
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;
|
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 maj2;
|
||||||
int min1;
|
int min1;
|
||||||
int min2;
|
int min2;
|
||||||
|
int tmp;
|
||||||
|
|
||||||
maj1 = -1;
|
maj1 = -1;
|
||||||
maj2 = -1;
|
maj2 = -1;
|
||||||
@@ -341,9 +432,17 @@ int disk_init(struct usb_device_info * dev) {
|
|||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if ( devnum != device->devnum || device->bus->location != busnum )
|
if ( device->devnum != devnum )
|
||||||
continue;
|
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 ) {
|
if ( sscanf(dirent->d_name, "%d:%d", &maj2, &min2) != 2 ) {
|
||||||
maj2 = -1;
|
maj2 = -1;
|
||||||
min2 = -1;
|
min2 = -1;
|
||||||
@@ -367,18 +466,26 @@ int disk_init(struct usb_device_info * dev) {
|
|||||||
return -1;
|
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 */
|
/* 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 )
|
if ( dev->device == DEVICE_RX_51 || dev->device == DEVICE_RM_680 || dev->device == DEVICE_RM_696 )
|
||||||
fd = disk_open_dev(maj1, min1, -1, 1);
|
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 */
|
/* 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 )
|
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
|
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;
|
return -1;
|
||||||
|
|
||||||
dev->data = fd;
|
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) {
|
enum device disk_get_device(struct usb_device_info * dev) {
|
||||||
|
|
||||||
return dev->device;
|
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) {
|
int disk_flash_image(struct usb_device_info * dev, struct image * image) {
|
||||||
|
|
||||||
ERROR("Not implemented yet");
|
int ret;
|
||||||
(void)dev;
|
|
||||||
(void)image;
|
printf("Flash image:\n");
|
||||||
return -1;
|
image_print_info(image);
|
||||||
|
|
||||||
|
ret = disk_flash_dev(dev->data, image);
|
||||||
|
if ( ret == 0 )
|
||||||
|
printf("Done\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -24,12 +24,13 @@
|
|||||||
#include "usb-device.h"
|
#include "usb-device.h"
|
||||||
|
|
||||||
int disk_init(struct usb_device_info * dev);
|
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);
|
enum device disk_get_device(struct usb_device_info * dev);
|
||||||
|
|
||||||
int disk_open_dev(int maj, int min, int partition, int readonly);
|
int disk_open_dev(int maj, int min, int partition, int readonly);
|
||||||
int disk_dump_dev(int fd, const char * file);
|
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_flash_image(struct usb_device_info * dev, struct image * image);
|
||||||
int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file);
|
int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file);
|
||||||
|
|||||||
+226
-72
@@ -34,10 +34,11 @@
|
|||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "fiasco.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_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 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_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_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)
|
#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 hwrevs[1024];
|
||||||
char version[257];
|
char version[257];
|
||||||
char layout[257];
|
char layout[257];
|
||||||
|
uint8_t asicidx;
|
||||||
|
uint8_t devicetype;
|
||||||
|
uint8_t deviceidx;
|
||||||
|
uint8_t checksum;
|
||||||
|
uint32_t address;
|
||||||
uint16_t hash;
|
uint16_t hash;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
struct image * image;
|
struct image * image;
|
||||||
|
struct image_part * image_part;
|
||||||
|
struct image_part * image_parts;
|
||||||
|
|
||||||
char hwrev[9];
|
char hwrev[9];
|
||||||
unsigned char buf[512];
|
unsigned char buf[512];
|
||||||
@@ -120,23 +128,41 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
|||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
|
|
||||||
/* If end of file, return fiasco image */
|
/* 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 */
|
/* Header of next image (0x54) */
|
||||||
if ( ! ( buf[0] == 0x54 && buf[2] == 0x2E && buf[3] == 0x19 && buf[4] == 0x01 && buf[5] == 0x01 && buf[6] == 0x00 ) ) {
|
if ( buf[0] != 0x54 ) {
|
||||||
ERROR("Invalid next image header");
|
ERROR("Invalid next image header");
|
||||||
return fiasco;
|
return fiasco;
|
||||||
}
|
}
|
||||||
|
|
||||||
count8 = buf[1];
|
checksum = 0x00;
|
||||||
if ( count8 > 0 )
|
|
||||||
--count8;
|
|
||||||
|
|
||||||
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);
|
hash = ntohs(hash);
|
||||||
|
|
||||||
memset(type, 0, sizeof(type));
|
memset(type, 0, sizeof(type));
|
||||||
READ_OR_RETURN(fiasco, type, 12);
|
READ_OR_RETURN(fiasco, checksum, type, 12);
|
||||||
|
|
||||||
byte = type[0];
|
byte = type[0];
|
||||||
if ( byte == 0xFF )
|
if ( byte == 0xFF )
|
||||||
@@ -144,26 +170,35 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
|||||||
|
|
||||||
VERBOSE(" %s\n", type);
|
VERBOSE(" %s\n", type);
|
||||||
|
|
||||||
READ_OR_RETURN(fiasco, &length, 4);
|
READ_OR_RETURN(fiasco, checksum, &length, 4);
|
||||||
length = ntohl(length);
|
length = ntohl(length);
|
||||||
|
|
||||||
/* unknown */
|
/* load address (unused) */
|
||||||
READ_OR_RETURN(fiasco, buf, 4);
|
READ_OR_RETURN(fiasco, checksum, &address, 4);
|
||||||
|
|
||||||
|
/* end of file data section */
|
||||||
|
--count8;
|
||||||
|
|
||||||
VERBOSE(" size: %d bytes\n", length);
|
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);
|
VERBOSE(" subsections: %d\n", count8);
|
||||||
|
|
||||||
memset(device, 0, sizeof(device));
|
memset(device, 0, sizeof(device));
|
||||||
memset(hwrevs, 0, sizeof(hwrevs));
|
memset(hwrevs, 0, sizeof(hwrevs));
|
||||||
memset(version, 0, sizeof(version));
|
memset(version, 0, sizeof(version));
|
||||||
memset(layout, 0, sizeof(layout));
|
memset(layout, 0, sizeof(layout));
|
||||||
|
image_part = NULL;
|
||||||
|
image_parts = NULL;
|
||||||
|
|
||||||
while ( count8 > 0 ) {
|
while ( count8 > 0 ) {
|
||||||
|
|
||||||
READ_OR_RETURN(fiasco, &byte, 1);
|
READ_OR_RETURN(fiasco, checksum, &byte, 1);
|
||||||
READ_OR_RETURN(fiasco, &length8, 1);
|
READ_OR_RETURN(fiasco, checksum, &length8, 1);
|
||||||
READ_OR_RETURN(fiasco, buf, length8);
|
READ_OR_RETURN(fiasco, checksum, buf, length8);
|
||||||
|
|
||||||
VERBOSE(" subinfo\n");
|
VERBOSE(" subinfo\n");
|
||||||
VERBOSE(" length: %d\n", length8);
|
VERBOSE(" length: %d\n", length8);
|
||||||
@@ -207,15 +242,55 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
|||||||
memset(layout, 0, sizeof(layout));
|
memset(layout, 0, sizeof(layout));
|
||||||
strncpy(layout, (char *)buf, length8);
|
strncpy(layout, (char *)buf, length8);
|
||||||
VERBOSE("layout\n");
|
VERBOSE("layout\n");
|
||||||
|
} else if ( byte == '4' ) {
|
||||||
|
VERBOSE("data part\n");
|
||||||
|
if ( length8 < 16 ) {
|
||||||
|
VERBOSE(" (damaged)\n");
|
||||||
} else {
|
} 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;
|
--count8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unknown */
|
/* checksum */
|
||||||
READ_OR_RETURN(fiasco, buf, 1);
|
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);
|
offset = lseek(fiasco->fd, 0, SEEK_CUR);
|
||||||
if ( offset == (off_t)-1 )
|
if ( offset == (off_t)-1 )
|
||||||
@@ -226,7 +301,7 @@ struct fiasco * fiasco_alloc_from_file(const char * file) {
|
|||||||
VERBOSE(" hwrevs: %s\n", hwrevs);
|
VERBOSE(" hwrevs: %s\n", hwrevs);
|
||||||
VERBOSE(" data at: %#08x\n", (unsigned int)offset);
|
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 )
|
if ( ! image )
|
||||||
FIASCO_READ_ERROR(fiasco, "Cannot allocate 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;
|
uint32_t length;
|
||||||
uint16_t hash;
|
uint16_t hash;
|
||||||
uint8_t length8;
|
uint8_t length8;
|
||||||
|
uint8_t checksum;
|
||||||
char ** device_hwrevs_bufs;
|
char ** device_hwrevs_bufs;
|
||||||
const char * str;
|
const char * str;
|
||||||
const char * type;
|
const char * type;
|
||||||
struct image_list * image_list;
|
struct image_list * image_list;
|
||||||
|
struct image_part * image_part;
|
||||||
struct image * image;
|
struct image * image;
|
||||||
unsigned char buf[4096];
|
unsigned char buf[4096];
|
||||||
|
|
||||||
@@ -375,32 +452,40 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
|
|||||||
/* signature */
|
/* signature */
|
||||||
WRITE_OR_FAIL_FREE(file, fd, "T", 1, device_hwrevs_bufs);
|
WRITE_OR_FAIL_FREE(file, fd, "T", 1, device_hwrevs_bufs);
|
||||||
|
|
||||||
|
checksum = 0x00;
|
||||||
|
|
||||||
/* number of subsections */
|
/* number of subsections */
|
||||||
length8 = device_count+1;
|
length8 = device_count+2;
|
||||||
if ( image->version )
|
if ( image->version )
|
||||||
++length8;
|
++length8;
|
||||||
if ( image->layout )
|
if ( image->layout )
|
||||||
++length8;
|
++length8;
|
||||||
WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs);
|
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);
|
WRITE_OR_FAIL_FREE(file, fd, "\x2e\x19\x01\x01\x00", 5, device_hwrevs_bufs);
|
||||||
|
CHECKSUM(checksum, "\x2e\x19\x01\x01\x00", 5);
|
||||||
|
|
||||||
/* checksum */
|
/* checksum */
|
||||||
hash = htons(image->hash);
|
hash = htons(image->hash);
|
||||||
WRITE_OR_FAIL_FREE(file, fd, &hash, 2, device_hwrevs_bufs);
|
WRITE_OR_FAIL_FREE(file, fd, &hash, 2, device_hwrevs_bufs);
|
||||||
|
CHECKSUM(checksum, &hash, 2);
|
||||||
|
|
||||||
/* image type name */
|
/* image type name */
|
||||||
memset(buf, 0, 12);
|
memset(buf, 0, 12);
|
||||||
strncpy((char *)buf, type, 12);
|
strncpy((char *)buf, type, 12);
|
||||||
WRITE_OR_FAIL_FREE(file, fd, buf, 12, device_hwrevs_bufs);
|
WRITE_OR_FAIL_FREE(file, fd, buf, 12, device_hwrevs_bufs);
|
||||||
|
CHECKSUM(checksum, buf, 12);
|
||||||
|
|
||||||
/* image size */
|
/* image size */
|
||||||
size = htonl(image->size);
|
size = htonl(image->size);
|
||||||
WRITE_OR_FAIL_FREE(file, fd, &size, 4, device_hwrevs_bufs);
|
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);
|
WRITE_OR_FAIL_FREE(file, fd, "\x00\x00\x00\x00", 4, device_hwrevs_bufs);
|
||||||
|
CHECKSUM(checksum, "\x00\x00\x00\x00", 4);
|
||||||
|
|
||||||
/* append version subsection */
|
/* append version subsection */
|
||||||
if ( image->version ) {
|
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 */
|
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, &length8, 1, device_hwrevs_bufs);
|
||||||
WRITE_OR_FAIL_FREE(file, fd, image->version, length8, 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 */
|
/* 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];
|
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, &length8, 1, device_hwrevs_bufs);
|
||||||
WRITE_OR_FAIL_FREE(file, fd, device_hwrevs_bufs[i]+1, length8, 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);
|
free(device_hwrevs_bufs);
|
||||||
|
|
||||||
@@ -425,10 +516,47 @@ int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
|
|||||||
length8 = strlen(image->layout);
|
length8 = strlen(image->layout);
|
||||||
WRITE_OR_FAIL(file, fd, &length8, 1);
|
WRITE_OR_FAIL(file, fd, &length8, 1);
|
||||||
WRITE_OR_FAIL(file, fd, image->layout, length8);
|
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 */
|
if ( image->parts ) {
|
||||||
WRITE_OR_FAIL(file, fd, "\x00", 1);
|
/* 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");
|
printf("Writing image data...\n");
|
||||||
|
|
||||||
@@ -461,8 +589,10 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
|
|||||||
char * name;
|
char * name;
|
||||||
char * layout_name;
|
char * layout_name;
|
||||||
struct image * image;
|
struct image * image;
|
||||||
|
struct image_part * image_part;
|
||||||
struct image_list * image_list;
|
struct image_list * image_list;
|
||||||
uint32_t size;
|
uint32_t offset, size, need, total_size, written;
|
||||||
|
int part_num;
|
||||||
char cwd[256];
|
char cwd[256];
|
||||||
unsigned char buf[4096];
|
unsigned char buf[4096];
|
||||||
|
|
||||||
@@ -489,68 +619,30 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
|
|||||||
while ( image_list ) {
|
while ( image_list ) {
|
||||||
|
|
||||||
fd = -1;
|
fd = -1;
|
||||||
name = NULL;
|
|
||||||
layout_name = NULL;
|
|
||||||
|
|
||||||
image = image_list->image;
|
image = image_list->image;
|
||||||
|
|
||||||
name = image_name_alloc_from_values(image);
|
|
||||||
if ( ! name )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Unpacking image...\n");
|
printf("Unpacking image...\n");
|
||||||
image_print_info(image);
|
image_print_info(image);
|
||||||
|
|
||||||
if ( image->layout ) {
|
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 ) {
|
if ( ! layout_name ) {
|
||||||
free(name);
|
free(name);
|
||||||
ALLOC_ERROR_RETURN(-1);
|
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(" 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 ) {
|
if ( ! simulate ) {
|
||||||
fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644);
|
fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644);
|
||||||
if ( fd < 0 ) {
|
if ( fd < 0 ) {
|
||||||
@@ -571,11 +663,73 @@ int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
|
|||||||
|
|
||||||
free(layout_name);
|
free(layout_name);
|
||||||
|
|
||||||
if ( ! simulate )
|
if ( ! simulate ) {
|
||||||
close(fd);
|
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;
|
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() do { ERROR("Cannot allocate memory"); } while (0)
|
||||||
#define ALLOC_ERROR_RETURN(...) do { ALLOC_ERROR(); return __VA_ARGS__; } 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) {
|
static inline void * MEMMEM(void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
|
||||||
for ( size_t i = 0; i < haystacklen; ++i ) {
|
for ( size_t i = 0; i < haystacklen; ++i ) {
|
||||||
|
|||||||
+65
-20
@@ -100,7 +100,7 @@ static void image_missing_values_from_name(struct image * image, const char * na
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* format: type-device:hwrevs_version */
|
/* 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 * name;
|
||||||
char * ptr;
|
char * ptr;
|
||||||
@@ -108,6 +108,8 @@ char * image_name_alloc_from_values(struct image * image) {
|
|||||||
size_t length;
|
size_t length;
|
||||||
const char * type;
|
const char * type;
|
||||||
const char * device;
|
const char * device;
|
||||||
|
struct image_part * part;
|
||||||
|
int i;
|
||||||
|
|
||||||
type = image_type_to_string(image->type);
|
type = image_type_to_string(image->type);
|
||||||
|
|
||||||
@@ -124,6 +126,14 @@ char * image_name_alloc_from_values(struct image * image) {
|
|||||||
else
|
else
|
||||||
hwrevs = NULL;
|
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);
|
length = 1 + strlen(type);
|
||||||
|
|
||||||
if ( device )
|
if ( device )
|
||||||
@@ -132,6 +142,10 @@ char * image_name_alloc_from_values(struct image * image) {
|
|||||||
length += 1 + strlen(hwrevs);
|
length += 1 + strlen(hwrevs);
|
||||||
if ( image->version )
|
if ( image->version )
|
||||||
length += 1 + strlen(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);
|
name = calloc(1, length);
|
||||||
if ( ! name ) {
|
if ( ! name ) {
|
||||||
@@ -149,21 +163,29 @@ char * image_name_alloc_from_values(struct image * image) {
|
|||||||
if ( image->version )
|
if ( image->version )
|
||||||
ptr += sprintf(ptr, "_%s", 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);
|
free(hwrevs);
|
||||||
|
|
||||||
return name;
|
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;
|
enum image_type detected_type;
|
||||||
|
|
||||||
image->hash = image_hash_from_data(image);
|
image->hash = image_hash_from_data(image);
|
||||||
|
|
||||||
image->devices = calloc(1, sizeof(struct device_list));
|
image->devices = calloc(1, sizeof(struct device_list));
|
||||||
if ( ! image->devices )
|
if ( ! image->devices ) {
|
||||||
return -1;
|
image_free(image);
|
||||||
|
ALLOC_ERROR_RETURN(-1);
|
||||||
|
}
|
||||||
|
|
||||||
image->devices->device = DEVICE_ANY;
|
image->devices->device = DEVICE_ANY;
|
||||||
|
|
||||||
@@ -208,6 +230,8 @@ static int image_append(struct image * image, const char * type, const char * de
|
|||||||
else
|
else
|
||||||
image->layout = NULL;
|
image->layout = NULL;
|
||||||
|
|
||||||
|
image->parts = parts;
|
||||||
|
|
||||||
return 0;
|
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;
|
int fd;
|
||||||
struct image * image = image_alloc();
|
|
||||||
if ( ! image )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
image->is_shared_fd = 0;
|
fd = open(file, O_RDONLY);
|
||||||
image->fd = open(file, O_RDONLY);
|
if ( fd < 0 ) {
|
||||||
if ( image->fd < 0 ) {
|
|
||||||
ERROR_INFO("Cannot open image file %s", file);
|
ERROR_INFO("Cannot open image file %s", file);
|
||||||
free(image);
|
|
||||||
return NULL;
|
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);
|
offset = lseek(image->fd, 0, SEEK_END);
|
||||||
if ( offset == (off_t)-1 ) {
|
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);
|
close(image->fd);
|
||||||
free(image);
|
free(image);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -268,21 +303,21 @@ struct image * image_alloc_from_file(const char * file, const char * type, const
|
|||||||
image->size = offset;
|
image->size = offset;
|
||||||
image->offset = 0;
|
image->offset = 0;
|
||||||
image->cur = 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 ) {
|
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);
|
close(image->fd);
|
||||||
free(image->orig_filename);
|
free(image->orig_filename);
|
||||||
free(image);
|
free(image);
|
||||||
return NULL;
|
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;
|
return NULL;
|
||||||
|
|
||||||
if ( ( ! type || ! type[0] ) && ( ! device || ! device[0] ) && ( ! hwrevs || ! hwrevs[0] ) && ( ! version || ! version[0] ) )
|
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);
|
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();
|
struct image * image = image_alloc();
|
||||||
if ( ! image )
|
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->offset = offset;
|
||||||
image->cur = 0;
|
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;
|
return NULL;
|
||||||
|
|
||||||
if ( ! noverify && image->hash != hash ) {
|
if ( ! noverify && image->hash != hash ) {
|
||||||
@@ -334,6 +369,13 @@ void image_free(struct image * image) {
|
|||||||
image->devices = next;
|
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->version);
|
||||||
free(image->layout);
|
free(image->layout);
|
||||||
free(image->orig_filename);
|
free(image->orig_filename);
|
||||||
@@ -503,6 +545,9 @@ static const char * image_types[] = {
|
|||||||
[IMAGE_CMT_2ND] = "cmt-2nd",
|
[IMAGE_CMT_2ND] = "cmt-2nd",
|
||||||
[IMAGE_CMT_ALGO] = "cmt-algo",
|
[IMAGE_CMT_ALGO] = "cmt-algo",
|
||||||
[IMAGE_CMT_MCUSW] = "cmt-mcusw",
|
[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) {
|
enum image_type image_type_from_data(struct image * image) {
|
||||||
|
|||||||
+15
-3
@@ -37,9 +37,19 @@ enum image_type {
|
|||||||
IMAGE_CMT_2ND,
|
IMAGE_CMT_2ND,
|
||||||
IMAGE_CMT_ALGO,
|
IMAGE_CMT_ALGO,
|
||||||
IMAGE_CMT_MCUSW,
|
IMAGE_CMT_MCUSW,
|
||||||
|
IMAGE_1ST,
|
||||||
|
IMAGE_CERT_SW,
|
||||||
|
IMAGE_APE_ALGO,
|
||||||
IMAGE_COUNT,
|
IMAGE_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct image_part {
|
||||||
|
struct image_part * next;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t size;
|
||||||
|
char * name;
|
||||||
|
};
|
||||||
|
|
||||||
struct image {
|
struct image {
|
||||||
enum image_type type;
|
enum image_type type;
|
||||||
struct device_list * devices;
|
struct device_list * devices;
|
||||||
@@ -47,6 +57,7 @@ struct image {
|
|||||||
char * layout;
|
char * layout;
|
||||||
uint16_t hash;
|
uint16_t hash;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
struct image_part * parts;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
int is_shared_fd;
|
int is_shared_fd;
|
||||||
@@ -63,8 +74,9 @@ struct image_list {
|
|||||||
struct image_list * next;
|
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_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_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_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_free(struct image * image);
|
||||||
void image_seek(struct image * image, size_t whence);
|
void image_seek(struct image * image, size_t whence);
|
||||||
size_t image_read(struct image * image, void * buf, size_t count);
|
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);
|
uint16_t image_hash_from_data(struct image * image);
|
||||||
enum image_type image_type_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);
|
enum image_type image_type_from_string(const char * type);
|
||||||
const char * image_type_to_string(enum image_type type);
|
const char * image_type_to_string(enum image_type type);
|
||||||
int image_hwrev_is_valid(struct image * image, int16_t hwrev);
|
int image_hwrev_is_valid(struct image * image, int16_t hwrev);
|
||||||
|
|||||||
+257
-47
@@ -19,6 +19,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
#include <sys/types.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) {
|
static int local_nanddump(const char * file, int mtd, int offset, int length) {
|
||||||
|
|
||||||
struct statvfs buf;
|
struct statvfs buf;
|
||||||
@@ -227,15 +220,18 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
|
|||||||
return 1;
|
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);
|
command = malloc(size+1);
|
||||||
if ( ! command )
|
if ( ! command )
|
||||||
return 1;
|
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);
|
ret = system(command);
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
free(command);
|
free(command);
|
||||||
|
|
||||||
@@ -243,52 +239,77 @@ static int local_nanddump(const char * file, int mtd, int offset, int length) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct nanddump_args {
|
static FILE * local_nandwrite(int mtd, int offset) {
|
||||||
int valid;
|
|
||||||
int mtd;
|
char * command;
|
||||||
int offset;
|
FILE * stream;
|
||||||
int length;
|
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[] = {
|
static struct nandpart_args nandpart_rx51[] = {
|
||||||
[IMAGE_XLOADER] = { 1, 0, 0x00000000, 0x00004000 },
|
[IMAGE_XLOADER] = { 0, 0x00000000, 0x00004000, 0x00000000 },
|
||||||
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
|
[IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
|
||||||
[IMAGE_KERNEL] = { 1, 3, 0x00000800, 0x001FF800 },
|
[IMAGE_KERNEL] = { 3, 0x00000000, 0x00200000, 0x00000800 },
|
||||||
[IMAGE_INITFS] = { 1, 4, 0x00000000, 0x00200000 },
|
[IMAGE_INITFS] = { 4, 0x00000000, 0x00200000, 0x00000000 },
|
||||||
[IMAGE_ROOTFS] = { 1, 5, 0x00000000, 0x0fb40000 },
|
[IMAGE_ROOTFS] = { 5, 0x00000000, 0x0fb40000, 0x00000000 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FIXME: Is this table correct? */
|
/* FIXME: Is this table correct? */
|
||||||
static struct nanddump_args nanddump_rx4x[] = {
|
static struct nandpart_args nandpart_rx4x[] = {
|
||||||
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
|
[IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 },
|
||||||
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
|
[IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
|
||||||
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x0021F800 },
|
[IMAGE_KERNEL] = { 2, 0x00000000, 0x00220000, 0x00000800 },
|
||||||
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00400000 },
|
[IMAGE_INITFS] = { 3, 0x00000000, 0x00400000, 0x00000000 },
|
||||||
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0f960000 },
|
[IMAGE_ROOTFS] = { 4, 0x00000000, 0x0f960000, 0x00000000 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FIXME: Is this table correct? */
|
/* FIXME: Is this table correct? */
|
||||||
static struct nanddump_args nanddump_old[] = {
|
static struct nandpart_args nandpart_old[] = {
|
||||||
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
|
[IMAGE_XLOADER] = { 0, 0x00000200, 0x00003E00, 0x00000000 },
|
||||||
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
|
[IMAGE_SECONDARY] = { 0, 0x00004000, 0x0001C000, 0x00000000 },
|
||||||
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x001FF800 },
|
[IMAGE_KERNEL] = { 2, 0x00000000, 0x00200000, 0x00000800 },
|
||||||
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00200000 },
|
[IMAGE_INITFS] = { 3, 0x00000000, 0x00200000, 0x00000000 },
|
||||||
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0fb80000 },
|
[IMAGE_ROOTFS] = { 4, 0x00000000, 0x0fb80000, 0x00000000 },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nanddump_device {
|
struct nand_device {
|
||||||
size_t count;
|
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[] = {
|
static struct nand_device nand_device[] = {
|
||||||
NANDDUMP(DEVICE_SU_18, nanddump_old),
|
NAND_DEVICE(DEVICE_SU_18, nandpart_old),
|
||||||
NANDDUMP(DEVICE_RX_34, nanddump_old),
|
NAND_DEVICE(DEVICE_RX_34, nandpart_old),
|
||||||
NANDDUMP(DEVICE_RX_44, nanddump_rx4x),
|
NAND_DEVICE(DEVICE_RX_44, nandpart_rx4x),
|
||||||
NANDDUMP(DEVICE_RX_48, nanddump_rx4x),
|
NAND_DEVICE(DEVICE_RX_48, nandpart_rx4x),
|
||||||
NANDDUMP(DEVICE_RX_51, nanddump_rx51),
|
NAND_DEVICE(DEVICE_RX_51, nandpart_rx51),
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef NANDDUMP
|
#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) {
|
int local_dump_image(enum image_type image, const char * file) {
|
||||||
|
|
||||||
|
unsigned char buf[20];
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
int header = 0;
|
||||||
unsigned char * addr = NULL;
|
unsigned char * addr = NULL;
|
||||||
off_t nlen, len;
|
off_t nlen = (off_t)-1;
|
||||||
|
off_t len;
|
||||||
int align;
|
int align;
|
||||||
int maj, min;
|
int maj, min;
|
||||||
|
|
||||||
@@ -415,17 +439,49 @@ int local_dump_image(enum image_type image, const char * file) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if ( device >= sizeof(nanddump)/sizeof(nanddump[0]) ) {
|
if ( device >= sizeof(nand_device)/sizeof(nand_device[0]) ) {
|
||||||
ERROR("Unsupported device");
|
ERROR("Unsupported device");
|
||||||
goto clean;
|
goto clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( image >= nanddump[device].count ) {
|
if ( image >= nand_device[device].count ) {
|
||||||
ERROR("Unsupported image type: %s", image_type_to_string(image));
|
ERROR("Unsupported image type: %s", image_type_to_string(image));
|
||||||
goto clean;
|
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;
|
goto clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( simulate )
|
||||||
|
goto clean;
|
||||||
|
|
||||||
fd = open(file, O_RDWR);
|
fd = open(file, O_RDWR);
|
||||||
if ( fd < 0 )
|
if ( fd < 0 )
|
||||||
goto clean;
|
goto clean;
|
||||||
@@ -442,6 +501,8 @@ int local_dump_image(enum image_type image, const char * file) {
|
|||||||
if ( len == (off_t)-1 || len == 0 )
|
if ( len == (off_t)-1 || len == 0 )
|
||||||
goto clean;
|
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 )
|
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 )
|
if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
|
||||||
nlen = ((nlen >> align) + 1) << align;
|
nlen = ((nlen >> align) + 1) << align;
|
||||||
|
|
||||||
if ( nlen == 0 ) {
|
}
|
||||||
|
|
||||||
|
if ( header <= 0 && nlen == 0 ) {
|
||||||
printf("File %s is empty, removing it...\n", file);
|
printf("File %s is empty, removing it...\n", file);
|
||||||
unlink(file);
|
unlink(file);
|
||||||
} else if ( nlen != len ) {
|
} 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) {
|
int local_check_badblocks(const char * device) {
|
||||||
|
|
||||||
ERROR("Not implemented yet");
|
ERROR("Not implemented yet");
|
||||||
|
|||||||
+75
-21
@@ -143,7 +143,7 @@ int simulate;
|
|||||||
int noverify;
|
int noverify;
|
||||||
int verbose;
|
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) {
|
static void parse_image_arg(char * arg, struct image_list ** image_first) {
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@@ -154,11 +154,16 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
|
|||||||
char * hwrevs;
|
char * hwrevs;
|
||||||
char * version;
|
char * version;
|
||||||
char * layout;
|
char * layout;
|
||||||
|
char * parts;
|
||||||
char * layout_file;
|
char * layout_file;
|
||||||
|
char * ptr;
|
||||||
|
int fd;
|
||||||
|
|
||||||
/* First check if arg is file, then try to parse arg format */
|
/* First check if arg is file, then try to parse arg format */
|
||||||
if ( stat(arg, &st) == 0 ) {
|
fd = open(arg, O_RDONLY);
|
||||||
image = image_alloc_from_file(arg, NULL, NULL, NULL, NULL, NULL);
|
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 ) {
|
if ( ! image ) {
|
||||||
ERROR("Cannot load image file %s", arg);
|
ERROR("Cannot load image file %s", arg);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -166,10 +171,21 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
|
|||||||
image_list_add(image_first, image);
|
image_list_add(image_first, image);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
close(fd);
|
||||||
|
} else if ( errno != ENOENT ) {
|
||||||
|
ERROR("Cannot load image file %s", arg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
layout_file = strchr(arg, '%');
|
parts = strchr(arg, '%');
|
||||||
if ( layout_file )
|
if ( parts )
|
||||||
*(layout_file++) = 0;
|
*(parts++) = 0;
|
||||||
|
|
||||||
|
layout_file = parts;
|
||||||
|
if ( layout_file ) {
|
||||||
|
while ( ( ptr = strchr(layout_file, '%') ) )
|
||||||
|
layout_file = ptr+1;
|
||||||
|
}
|
||||||
|
|
||||||
type = NULL;
|
type = NULL;
|
||||||
device = NULL;
|
device = NULL;
|
||||||
@@ -229,7 +245,9 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
|
|||||||
close(fd);
|
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 )
|
if ( layout )
|
||||||
free(layout);
|
free(layout);
|
||||||
@@ -413,9 +431,13 @@ int main(int argc, char **argv) {
|
|||||||
enum device detected_device = DEVICE_UNKNOWN;
|
enum device detected_device = DEVICE_UNKNOWN;
|
||||||
int16_t detected_hwrev = -1;
|
int16_t detected_hwrev = -1;
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
char * ptr = NULL;
|
char * ptr = NULL;
|
||||||
|
char * ptr1 = NULL;
|
||||||
|
char * ptr2 = NULL;
|
||||||
char * tmp = NULL;
|
char * tmp = NULL;
|
||||||
|
|
||||||
char nolo_ver[512];
|
char nolo_ver[512];
|
||||||
@@ -1026,9 +1048,9 @@ int main(int argc, char **argv) {
|
|||||||
/* filter images by device & hwrev */
|
/* filter images by device & hwrev */
|
||||||
if ( detected_device )
|
if ( detected_device )
|
||||||
filter_images_by_device(dev->detected_device, &image_first);
|
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);
|
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;
|
fiasco_in->first = image_first;
|
||||||
|
|
||||||
/* set kernel and initfs images for loading */
|
/* set kernel and initfs images for loading */
|
||||||
@@ -1086,7 +1108,7 @@ int main(int argc, char **argv) {
|
|||||||
if ( dev_load ) {
|
if ( dev_load ) {
|
||||||
if ( image_kernel ) {
|
if ( image_kernel ) {
|
||||||
ret = dev_load_image(dev, image_kernel->image);
|
ret = dev_load_image(dev, image_kernel->image);
|
||||||
if ( ret < 0 )
|
if ( ret == -EAGAIN )
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
if ( image_kernel == image_first )
|
if ( image_kernel == image_first )
|
||||||
@@ -1100,7 +1122,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
if ( image_initfs ) {
|
if ( image_initfs ) {
|
||||||
ret = dev_load_image(dev, image_initfs->image);
|
ret = dev_load_image(dev, image_initfs->image);
|
||||||
if ( ret < 0 )
|
if ( ret == -EAGAIN )
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
if ( image_initfs == image_first )
|
if ( image_initfs == image_first )
|
||||||
@@ -1119,7 +1141,7 @@ int main(int argc, char **argv) {
|
|||||||
while ( image_ptr ) {
|
while ( image_ptr ) {
|
||||||
struct image_list * next = image_ptr->next;
|
struct image_list * next = image_ptr->next;
|
||||||
ret = dev_flash_image(dev, image_ptr->image);
|
ret = dev_flash_image(dev, image_ptr->image);
|
||||||
if ( ret < 0 )
|
if ( ret == -EAGAIN )
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
if ( image_ptr == image_first )
|
if ( image_ptr == image_first )
|
||||||
@@ -1239,6 +1261,8 @@ int main(int argc, char **argv) {
|
|||||||
if ( chdir(buf) < 0 )
|
if ( chdir(buf) < 0 )
|
||||||
ERROR_INFO("Cannot chdir back to %s", buf);
|
ERROR_INFO("Cannot chdir back to %s", buf);
|
||||||
|
|
||||||
|
printf("Done\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dump fiasco */
|
/* dump fiasco */
|
||||||
@@ -1249,10 +1273,11 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
for ( i = 0; i < IMAGE_COUNT; ++i ) {
|
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;
|
continue;
|
||||||
|
|
||||||
buf[0] = 0;
|
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 ) {
|
switch ( i ) {
|
||||||
@@ -1283,7 +1308,9 @@ int main(int argc, char **argv) {
|
|||||||
break;
|
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 )
|
if ( ! image_dump )
|
||||||
continue;
|
continue;
|
||||||
@@ -1319,14 +1346,12 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
for ( i = 0; i < IMAGE_COUNT; ++i ) {
|
for ( i = 0; i < IMAGE_COUNT; ++i ) {
|
||||||
|
|
||||||
struct stat st;
|
int rename_ret;
|
||||||
|
int rename_errno;
|
||||||
|
|
||||||
if ( ! image_tmp_name(i) )
|
if ( ! image_tmp_name(i) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( stat(image_tmp_name(i), &st) != 0 )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch ( i ) {
|
switch ( i ) {
|
||||||
case IMAGE_2ND:
|
case IMAGE_2ND:
|
||||||
case IMAGE_XLOADER:
|
case IMAGE_XLOADER:
|
||||||
@@ -1356,15 +1381,42 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf[0] = 0;
|
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);
|
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 ) {
|
if ( rename(image_tmp_name(i), buf) < 0 ) {
|
||||||
|
|
||||||
ERROR_INFO("Renaming failed");
|
ERROR_INFO("Renaming failed");
|
||||||
|
|
||||||
buf[0] = 0;
|
*ptr1 = 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);
|
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 )
|
||||||
@@ -1376,6 +1428,8 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* boot */
|
/* boot */
|
||||||
if ( dev_boot ) {
|
if ( dev_boot ) {
|
||||||
dev_boot_device(dev, dev_boot_arg);
|
dev_boot_device(dev, dev_boot_arg);
|
||||||
|
|||||||
+16
-7
@@ -213,14 +213,18 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
|
|||||||
msg1 = (struct mkii_message *)buf1;
|
msg1 = (struct mkii_message *)buf1;
|
||||||
ptr = msg->data;
|
ptr = msg->data;
|
||||||
|
|
||||||
/* Signature */
|
/* File data header */
|
||||||
memcpy(ptr, "\x2E\x19\x01\x01", 4);
|
memcpy(ptr, "\x2E", 1);
|
||||||
ptr += 4;
|
|
||||||
|
|
||||||
/* Space */
|
|
||||||
memcpy(ptr, "\x00", 1);
|
|
||||||
ptr += 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 */
|
||||||
hash = htons(image->hash);
|
hash = htons(image->hash);
|
||||||
memcpy(ptr, &hash, 2);
|
memcpy(ptr, &hash, 2);
|
||||||
@@ -239,7 +243,7 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
|
|||||||
memcpy(ptr, &size, 4);
|
memcpy(ptr, &size, 4);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
|
|
||||||
/* Space */
|
/* Load address (ignored) */
|
||||||
memcpy(ptr, "\x00\x00\x00\x00", 4);
|
memcpy(ptr, "\x00\x00\x00\x00", 4);
|
||||||
ptr += 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 )
|
if ( ret != 1 || msg->data[0] != 0 )
|
||||||
ERROR_RETURN("Cannot send reboot command", -1);
|
ERROR_RETURN("Cannot send reboot command", -1);
|
||||||
|
|
||||||
|
if (dev->data & MKII_UPDATE_MODE)
|
||||||
|
MSLEEP(100);
|
||||||
|
else
|
||||||
|
MSLEEP(3000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-8
@@ -269,14 +269,18 @@ static int nolo_send_image(struct usb_device_info * dev, struct image * image, i
|
|||||||
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
|
|
||||||
/* Signature */
|
/* File data header */
|
||||||
memcpy(ptr, "\x2E\x19\x01\x01", 4);
|
memcpy(ptr, "\x2E", 1);
|
||||||
ptr += 4;
|
|
||||||
|
|
||||||
/* Space */
|
|
||||||
memcpy(ptr, "\x00", 1);
|
|
||||||
ptr += 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 */
|
||||||
hash = htons(image->hash);
|
hash = htons(image->hash);
|
||||||
memcpy(ptr, &hash, 2);
|
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);
|
memcpy(ptr, &size, 4);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
|
|
||||||
/* Space */
|
/* Load address (ignored by NOLO) */
|
||||||
memcpy(ptr, "\x00\x00\x00\x00", 4);
|
memcpy(ptr, "\x00\x00\x00\x00", 4);
|
||||||
ptr += 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
@@ -91,8 +91,11 @@ clean:
|
|||||||
|
|
||||||
void dev_free(struct device_info * dev) {
|
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);
|
usb_close_device(dev->usb);
|
||||||
|
}
|
||||||
free(dev);
|
free(dev);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-30
@@ -46,16 +46,21 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct usb_flash_device usb_devices[] = {
|
static struct usb_flash_device usb_devices[] = {
|
||||||
{ 0x0421, 0x0096, -1, -1, -1, FLASH_DISK, { DEVICE_RX_44, 0 } },
|
/* vend prod i a protocol devices */
|
||||||
{ 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, 0x0096, -1, -1, FLASH_DISK, { DEVICE_RX_44, 0 } },
|
||||||
{ 0x0421, 0x0106, 0, -1, -1, FLASH_COLD, { DEVICE_RX_51, DEVICE_RM_680, DEVICE_RM_696, 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, 0x0189, -1, -1, -1, FLASH_DISK, { DEVICE_RX_48, 0 } },
|
{ 0x0421, 0x0106, 0, 0, FLASH_COLD, { DEVICE_RX_51, DEVICE_RM_680, DEVICE_RM_696, 0 } },
|
||||||
{ 0x0421, 0x01c7, -1, -1, -1, FLASH_DISK, { DEVICE_RX_51, 0 } },
|
{ 0x0421, 0x0189, -1, -1, FLASH_DISK, { DEVICE_RX_48, 0 } },
|
||||||
{ 0x0421, 0x01c8, 1, 1, -1, FLASH_MKII, { DEVICE_RX_51, DEVICE_RM_680, 0 } },
|
{ 0x0421, 0x01c7, -1, -1, FLASH_DISK, { DEVICE_RX_51, 0 } },
|
||||||
{ 0x0421, 0x03d1, -1, -1, -1, FLASH_DISK, { DEVICE_RM_680, 0 } },
|
{ 0x0421, 0x01c8, 1, 1, FLASH_MKII, { DEVICE_RX_51, DEVICE_RM_680, 0 } },
|
||||||
{ 0x0421, 0x0431, -1, -1, -1, FLASH_DISK, { DEVICE_SU_18, DEVICE_RX_34, 0 } },
|
{ 0x0421, 0x01c8, 1, 0, FLASH_UNKN, { DEVICE_RX_51, 0 } }, /* U-Boot mode (TTY via USB) */
|
||||||
{ 0x0421, 0x04c3, -1, -1, -1, FLASH_DISK, { DEVICE_RX_34, 0 } },
|
{ 0x0421, 0x03d1, -1, -1, FLASH_DISK, { DEVICE_RM_680, 0 } },
|
||||||
{ 0x0421, 0x3f00, 2, 1, -1, FLASH_NOLO, { DEVICE_RX_34, 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[] = {
|
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;
|
buf[0] = 0;
|
||||||
for ( i = 0; i < ret; i+=2 ) {
|
for ( i = 0; i < ret; i+=2 ) {
|
||||||
sscanf(buf+i, "%2x", &x);
|
sscanf(buf+i, "%2x", &x);
|
||||||
if ( x > 32 && x < 128 )
|
if ( x > 31 && x < 127 )
|
||||||
buf2[i/2] = x;
|
buf2[i/2] = x;
|
||||||
else {
|
else {
|
||||||
buf2[0] = 0;
|
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) {
|
static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
|
||||||
|
|
||||||
int i;
|
size_t i;
|
||||||
char product[1024];
|
char product[1024];
|
||||||
struct usb_device_info * ret = NULL;
|
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 ( 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("\b\b ");
|
||||||
PRINTF_END();
|
PRINTF_END();
|
||||||
PRINTF_ADD("Found ");
|
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 ) {
|
if ( usb_devices[i].alternate >= 0 ) {
|
||||||
PRINTF_LINE("Setting alternate USB interface...");
|
PRINTF_LINE("Setting alternate USB interface...");
|
||||||
if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
|
if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
|
||||||
PRINTF_ERROR("usb_claim_interface failed");
|
PRINTF_ERROR("usb_set_altinterface 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");
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
|
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
|
||||||
usb_close(udev);
|
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;
|
ret->device = DEVICE_RX_44;
|
||||||
else if ( strcmp(product, "Nokia N810 Internet Tablet WiMAX Edition") == 0 || strcmp(product, "Nokia-RX48 (Update mode)") == 0 )
|
else if ( strcmp(product, "Nokia N810 Internet Tablet WiMAX Edition") == 0 || strcmp(product, "Nokia-RX48 (Update mode)") == 0 )
|
||||||
ret->device = DEVICE_RX_48;
|
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;
|
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;
|
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;
|
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;
|
ret->device = DEVICE_ANY;
|
||||||
else
|
else
|
||||||
ret->device = DEVICE_UNKNOWN;
|
ret->device = DEVICE_UNKNOWN;
|
||||||
@@ -361,7 +370,7 @@ struct usb_device_info * usb_open_and_wait_for_device(void) {
|
|||||||
if ( ret )
|
if ( ret )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
SLEEP(0xc350); // 0.5s
|
MSLEEP(50);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ struct usb_flash_device {
|
|||||||
uint16_t product;
|
uint16_t product;
|
||||||
int interface;
|
int interface;
|
||||||
int alternate;
|
int alternate;
|
||||||
int configuration;
|
|
||||||
enum usb_flash_protocol protocol;
|
enum usb_flash_protocol protocol;
|
||||||
enum device devices[DEVICE_COUNT];
|
enum device devices[DEVICE_COUNT];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user