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

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

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

No files matched your search

+4
View File
@@ -2,6 +2,10 @@ sudo: false
language: c language: c
arch:
- AMD64
- ppc64le
compiler: compiler:
- gcc - gcc
- clang - clang
+13 -13
View File
@@ -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 supposed to be stable, so nokia will probably release incompatible It's not supposed to be stable, so Nokia will probably release incompatible
bootloaders to break this tool. USE IT AT YOUR OWN RISK. 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
-2
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
VERSION = 0.8 VERSION = 0.10
PREFIX = /usr/local PREFIX = /usr/local
# NetBSD stuff # NetBSD stuff
+2 -3
View File
@@ -30,11 +30,10 @@ Technical details:
For dumping mtd partition is used tool nanddump. Here is example how to dump 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
View File
@@ -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";
}
}
+7 -7
View File
@@ -191,14 +191,14 @@ static int send_2nd(usb_dev_handle * udev, struct image * image) {
if ( ret != sizeof(omap_peripheral_msg) ) 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;
} }
+8 -6
View File
@@ -184,9 +184,11 @@ char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
continue; continue;
} }
for ( i = 0; device_first->hwrevs[i] != -1; ++i ) if ( device_first->hwrevs ) {
if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 ) for ( i = 0; device_first->hwrevs[i] != -1; ++i )
++local; if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 )
++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;
+101 -28
View File
@@ -118,7 +118,7 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
blkdev[len] = 0; blkdev[len] = 0;
fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK); fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK);
if ( fd < 0 ) { if ( fd < 0 ) {
ERROR_INFO("Cannot open block device %s", blkdev); ERROR_INFO("Cannot open block device %s", blkdev);
return -1; return -1;
@@ -144,13 +144,13 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
ERROR("Block device name is too long"); ERROR("Block device name is too long");
return -1; return -1;
} }
fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL); fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL);
if ( fd < 0 && errno == ENOENT ) { if ( fd < 0 && errno == ENOENT ) {
if ( snprintf(blkdev+len, sizeof(blkdev)-len, "%d", partition) >= (int)(sizeof(blkdev)-len) ) { if ( snprintf(blkdev+len, sizeof(blkdev)-len, "%d", partition) >= (int)(sizeof(blkdev)-len) ) {
ERROR("Block device name is too long"); ERROR("Block device name is too long");
return -1; return -1;
} }
fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL); fd = open(blkdev, ((simulate || readonly) ? O_RDONLY : O_RDWR) | O_EXCL);
} }
if ( fd < 0 && errno == ENOENT ) { if ( fd < 0 && errno == ENOENT ) {
blkdev[len] = 0; blkdev[len] = 0;
@@ -201,7 +201,7 @@ int disk_open_dev(int maj, int min, int partition, int readonly) {
int disk_dump_dev(int fd, const char * file) { int 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;
@@ -253,11 +253,15 @@ int disk_dump_dev(int fd, const char * file) {
return -1; return -1;
} }
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if ( ! simulate ) {
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if ( fd2 < 0 ) {
ERROR_INFO("Cannot create file %s", file);
return -1;
}
if ( fd2 < 0 ) {
ERROR_INFO("Cannot create file %s", file);
return -1;
} }
sent = 0; sent = 0;
@@ -270,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 ( write(fd2, global_buf, size) != size ) { if ( size < 0 ) {
PRINTF_ERROR("Dumping image failed"); PRINTF_ERROR("Reading from block device failed");
close(fd2); if ( ! simulate )
close(fd2);
return -1; return -1;
} }
if ( ! simulate ) {
if ( write(fd2, global_buf, size) != size ) {
PRINTF_ERROR("Dumping image failed");
close(fd2);
return -1;
}
}
sent += size; sent += size;
printf_progressbar(sent, blksize); printf_progressbar(sent, blksize);
} }
close(fd2); if ( ! simulate )
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;
return -1;
if ( image->type != IMAGE_MMC )
ERROR_RETURN("Only mmc images are supported", -1);
printf("Writing image to block device...\n");
#ifdef __linux__
if ( ioctl(fd, BLKGETSIZE64, &blksize) != 0 ) {
ERROR_INFO("Cannot get size of block device");
return -1;
}
#else
blksize = lseek(fd, 0, SEEK_END);
if ( (off_t)blksize == (off_t)-1 ) {
ERROR_INFO("Cannot get size of block device");
return -1;
}
if ( lseek(fd, 0, SEEK_SET) == (off_t)-1 ) {
ERROR_INFO("Cannot seek to begin of block device");
return -1;
}
#endif
if ( blksize == 0 )
ERROR_RETURN("Block device has zero size", -1);
if ( image->size > blksize )
ERROR_RETURN("Image is too big", -1);
sent = 0;
printf_progressbar(0, image->size);
while ( sent < image->size ) {
need = image->size - sent;
if ( need > sizeof(global_buf) )
need = sizeof(global_buf);
size = image_read(image, global_buf, need);
if ( size == 0 ) {
PRINTF_ERROR("Failed to read image");
return -1;
}
if ( ! simulate ) {
if ( write(fd, global_buf, size) != size ) {
PRINTF_ERROR("Writing image failed");
return -1;
}
}
sent += size;
printf_progressbar(sent, image->size);
}
return 0;
} }
@@ -407,16 +476,14 @@ int disk_init(struct usb_device_info * dev) {
maj2 = tmp; maj2 = tmp;
} }
/* TODO: change 1 to 0 when disk_flash_dev will be implemented */ /* RX-51, RM-680 and RM-696 export MyDocs in first usb device and just first partion, so host system see whole device without MBR table */
if ( dev->device == DEVICE_RX_51 || dev->device == DEVICE_RM_680 || dev->device == DEVICE_RM_696 )
/* RX-51 and RM-680 export MyDocs in first usb device and just first partion, so host system see whole device without MBR table */ fd = disk_open_dev(maj1, min1, -1, simulate ? 1 : 0);
if ( dev->device == DEVICE_RX_51 || dev->device == DEVICE_RM_680 )
fd = disk_open_dev(maj1, min1, -1, 1);
/* Other devices can export SD card as first partition and export whole mmc device, so host system will see MBR table */ /* 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 ) if ( fd < 0 )
return -1; return -1;
@@ -449,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;
} }
+1 -1
View File
@@ -30,7 +30,7 @@ enum device disk_get_device(struct usb_device_info * dev);
int disk_open_dev(int maj, int min, int partition, int readonly); int disk_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
View File
@@ -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 {
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 { } else {
VERBOSE("unknown ('%c':%#x)\n", byte, byte); 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
View File
@@ -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 ) {
+40 -8
View File
@@ -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,13 +163,19 @@ 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;
@@ -210,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;
} }
@@ -244,7 +266,7 @@ 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) {
int fd; int fd;
@@ -254,11 +276,11 @@ struct image * image_alloc_from_file(const char * file, const char * type, const
return NULL; return NULL;
} }
return image_alloc_from_fd(fd, file, type, device, hwrevs, version, layout); 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 * 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; off_t offset;
struct image * image = image_alloc(); struct image * image = image_alloc();
@@ -291,7 +313,7 @@ struct image * image_alloc_from_fd(int fd, const char * orig_filename, const cha
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] ) )
@@ -303,7 +325,7 @@ struct image * image_alloc_from_fd(int fd, const char * orig_filename, const cha
} }
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 )
@@ -315,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 ) {
@@ -347,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);
@@ -516,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 -4
View File
@@ -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,9 +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_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout); struct image * image_alloc_from_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 * 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);
@@ -76,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);
+275 -65
View File
@@ -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);
ret = system(command); if ( ! simulate )
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,31 +501,35 @@ 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;
addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); if ( header <= 0 || nlen == (off_t)-1 ) {
if ( addr == MAP_FAILED ) addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
addr = NULL;
if ( ! addr ) if ( addr == MAP_FAILED )
goto clean; addr = NULL;
for ( nlen = len; nlen > 0; --nlen ) if ( ! addr )
if ( addr[nlen-1] != 0xFF ) goto clean;
break;
for ( ; nlen > 0; --nlen ) for ( nlen = len; nlen > 0; --nlen )
if ( addr[nlen-1] != 0x00 ) if ( addr[nlen-1] != 0xFF )
break; break;
if ( image == IMAGE_MMC ) for ( ; nlen > 0; --nlen )
align = 8; if ( addr[nlen-1] != 0x00 )
else break;
align = 7;
if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 ) if ( image == IMAGE_MMC )
nlen = ((nlen >> align) + 1) << align; align = 8;
else
align = 7;
if ( nlen == 0 ) { if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
nlen = ((nlen >> align) + 1) << align;
}
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");
+56 -18
View File
@@ -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,14 +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; 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 */
fd = open(arg, O_RDONLY); fd = open(arg, O_RDONLY);
if ( fd >= 0 ) { if ( fd >= 0 ) {
if ( fstat(fd, &st) == 0 && !S_ISDIR(st.st_mode) ) { if ( fstat(fd, &st) == 0 && !S_ISDIR(st.st_mode) ) {
image = image_alloc_from_fd(fd, arg, NULL, NULL, NULL, NULL, NULL); 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);
@@ -175,9 +177,15 @@ static void parse_image_arg(char * arg, struct image_list ** image_first) {
exit(1); 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;
@@ -237,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);
@@ -421,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];
@@ -1034,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 */
@@ -1094,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 )
@@ -1108,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 )
@@ -1127,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 )
@@ -1259,11 +1273,12 @@ 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;
snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev); if ( dev->detected_hwrev > 0 )
snprintf(buf, sizeof(buf), "%hd", dev->detected_hwrev);
switch ( i ) { switch ( i ) {
case IMAGE_2ND: case IMAGE_2ND:
@@ -1293,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;
@@ -1364,7 +1381,20 @@ 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_ret = rename(image_tmp_name(i), buf);
rename_errno = errno; rename_errno = errno;
@@ -1379,13 +1409,21 @@ int main(int argc, char **argv) {
errno = rename_errno; errno = rename_errno;
ERROR_INFO("Renaming failed"); ERROR_INFO("Renaming failed");
buf[0] = 0; *ptr2 = 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 ) {
ERROR_INFO("Renaming failed"); ERROR_INFO("Renaming failed");
*ptr1 = 0;
printf("Trying to rename %s image file to %s...\n", image_type_to_string(i), buf);
if ( rename(image_tmp_name(i), buf) < 0 )
ERROR_INFO("Renaming failed");
}
} }
} }
+16 -7
View File
@@ -213,14 +213,18 @@ int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
msg1 = (struct mkii_message *)buf1; 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
View File
@@ -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);
} }
+39 -30
View File
@@ -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_34, 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);
} }
-1
View File
@@ -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];
}; };