531 Commits
Author SHA1 Message Date
Pali Rohár b87411c02f Release version 0.8 2018-07-08 12:22:33 +02:00
Aaro Koskinen 7f38b4bd10 usb-device: restore N800 support
N800 has stopped working at some point, not sure why:

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

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

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

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

Fixes: https://github.com/pali/0xFFFF/issues/5
2018-02-08 23:20:14 +01:00
Pali Rohár e987dcd948 disk: Remove remaining ENOMEDIUM 2018-02-08 20:35:12 +01:00
Pali Rohár 2fd11378c8 disk: Fix swapping maj1:min1 and maj2:min2 2018-02-08 20:28:31 +01:00
Pali Rohár 808ce724ee main: Print message after dumping finish 2018-02-08 19:49:54 +01:00
Pali Rohár ca1db96690 disk: Fix compile warning: comparison between signed and unsigned integer expressions 2018-02-08 19:49:13 +01:00
Pali Rohár a6c20b5ee4 disk: Open whole block device with O_NONBLOCK
This would simplify handling of ENOMEDIUM error.
2018-02-08 19:48:34 +01:00
Pali Rohár e685787e67 disk: Ensure that maj1:min1 is first device and maj2:min2 is second device 2018-02-08 19:24:11 +01:00
Edward Betts 10b495120e correct spelling mistake 2017-08-30 12:05:42 +01:00
Pali Rohár 559fe2a3bd disk: After opening blkdev, check that it is really block device 2017-07-09 17:26:13 +02:00
Pali Rohár ccec7a182f disk: Close device file handle when freeing structures 2017-07-09 14:57:41 +02:00
Pali Rohár 31569c169a disk: Fix detection of correct device in disk_open_dev() 2017-07-09 14:56:30 +02:00
Pali Rohár 27a55c3367 disk: Choose correct partition in disk_open_dev() 2017-07-06 20:55:41 +02:00
Pali Rohár cda5dc6116 main: Use image_alloc_from_fd() to fix race condition between calling stat and opening file 2017-06-17 23:48:01 +02:00
Pali Rohár 5cbd5e92b8 image: Add new function image_alloc_from_fd() 2017-06-17 23:47:10 +02:00
Pali Rohár 1ec3777cb8 image: Call image_free() when image_append() is failing 2017-06-17 23:46:50 +02:00
Pali Rohár 897919a70f main: Fix race condition between calling stat and rename 2017-06-17 23:10:36 +02:00
Pali Rohár 76b18b9d39 travis: Fix coverity job 2017-03-03 18:44:29 +01:00
Pali Rohár ffcc10f689 travis: Simplify configuration, move coverity_scan to matrix 2017-02-26 17:00:07 +01:00
Pali Rohár 16cdf3e776 travis: Run on container-based infrastructure 2017-02-26 16:19:42 +01:00
Pali Rohár dc81ebb855 travis: Use apt addon instead sudo 2017-02-26 16:09:52 +01:00
Pali Rohár 66ecce9a3d disk: Remove check which is always false
Type unsigned long long int according to C99 can store at least 2^64-1.
2017-01-09 22:56:33 +01:00
Pali Rohár 87867a5904 cal: Fix race condition between calling stat and opening file 2017-01-08 14:33:08 +01:00
Pali Rohár f0b8ee117b Makefile: Fix setting compiler 2017-01-08 03:42:34 +01:00
Pali Rohár 4c8206b44f travis: Enable clang and use separate job for Coverity 2017-01-08 03:33:39 +01:00
Pali Rohár 9bf886c041 Release version 0.7 2016-12-25 11:46:12 +01:00
Pali Rohár 955ee1bd1e TODO: Update state 2016-12-24 18:23:43 +01:00
Aaro Koskinen 08485a0c09 all: Add basic support for Nokia N9 2016-12-24 18:23:28 +01:00
Pali Rohár b4314bce15 cal: Fix pointer check 2016-12-24 18:22:02 +01:00
Pali Rohár 117d0bb2d0 cal: cal_read_block allocate memory 2016-12-24 18:06:57 +01:00
Pali Rohár f7bad18a56 disk: Fix for RM-680 2016-12-23 10:13:42 +01:00
Pali Rohár 82de19bee1 disk: Check for ENOMEDIUM when partition is required 2016-12-23 10:13:23 +01:00
Pali Rohár b7c28b2c1b cal: SSIZE_MAX is not required to be defined 2016-12-23 10:13:07 +01:00
Pali Rohár 0a1ac25219 cal: Move sys/ioctl.h to __linux__ 2016-12-23 10:12:27 +01:00
Pali Rohár bd59c47ec3 usb-device: Detect Nokia N950 in disk mode 2016-12-21 18:25:25 +01:00
Pali Rohár 645e280d69 cal: Fix memory leak 2016-12-17 18:00:07 +01:00
Aaro Koskinen d4ff1d9328 usb-device: Add another product string for RM-680 2016-12-17 17:46:35 +01:00
Pali Rohár bc0f663e92 cal: Fix check for lseek errors 2016-12-17 03:00:12 +01:00
Pali Rohár b8fb95b2aa all: Enable Large File Support 2016-12-17 01:53:16 +01:00
Pali Rohár e36423e8c2 all: Fix printing fsblkcnt_t and off_t types 2016-12-17 01:52:50 +01:00
Pali Rohár 430930537c all: Use #include <sys/sysmacros.h> for major() instead #define _BSD_SOURCE 2016-12-17 01:51:33 +01:00
Pali Rohár 7522a9fbc7 all: Fix compilation when u_int*_t are not defined and used by usb.h 2016-12-16 15:39:46 +01:00
Pali Rohár 6ec64f4992 operations: Fix NULL pointer dereference in dev_boot_device
This will fix a crash when calling "0xFFFF -b" from Mk II Update mode.
2016-12-10 14:13:41 +01:00
Pali Rohár 8f57f7ef61 mkii: Fix detection of Update mode 2016-12-10 14:13:14 +01:00
Pali Rohár 3d71caab8f usb-device: Do not reattach kernel driver after closing cold flash mode 2016-12-07 11:56:37 +01:00
Pali Rohár 4ccf8fb369 usb-device: Do not print verbose message "Reattach kernel driver to USB interface..." 2016-12-07 11:55:54 +01:00
Pali Rohár 188fa70c80 cold-flash: Increase timeout after leaving cold flash mode
Switching to NOLO takes about one second and NOLO itself wait another second. So it should be OK.
2016-12-07 11:55:26 +01:00
Pali Rohár f2a51b5041 disk: Do not fail when empty block device is exported 2016-12-07 11:38:07 +01:00
Pali Rohár 19e2b22193 image: Remove dead code in image_align() 2016-12-07 00:39:36 +01:00
Pali Rohár 15dbd14d7a doc: Update fiasco documentation 2016-12-06 23:42:41 +01:00
Pali Rohár 0650cdf51f cold-flash: Show OMAP chip revision 2016-12-06 23:13:48 +01:00
Pali Rohár 9ea8f2bb38 cal: Style fix 2016-12-06 23:13:12 +01:00
Pali Rohár 9a5f940046 usb-device: Check that we are not using broken libusb-1.0 library 2016-12-06 23:11:47 +01:00
Pali Rohár 5e79d651ca all: Compile globally without _GNU_SOURCE, define _BSD_SOURCE or _GNU_SOURCE where needed 2016-12-06 23:10:58 +01:00
Pali Rohár 676da47751 all: Revert libusb-1.0 support
Listing of usb devices with libusb-1.0 is too slow and not usable for
flashing or cold-flashing Nokia N900.

Old libusb (0.1) does not have this problem and works perfectly.

Problem for libusb-1.0 was reported at least two times into libusb-devel
mailing list, but upstream developers are totally ignore it. One message is
in archive: https://sourceforge.net/p/libusb/mailman/message/34985373/

Because of that there is just one option: use tested and working libusb 0.1
library instead some experimental and non-working libusb-1.0.
2016-12-06 22:39:44 +01:00
Pali Rohár ea7f2a441a all: Add support for Nokia N950 (RM-680) 2016-06-27 17:24:51 +02:00
Pali Rohár 61d77eed68 mkii: Call /version/sw_release only for protocol version 2
Looks like command /version/sw_release is supported only by protocol version 2.
2016-06-27 17:24:05 +02:00
Pali Rohár 8a433f2d7a usb-device: Do not reattach kernel driver if USB interface is not used 2016-05-12 00:18:02 +02:00
Pali Rohár cf95375177 disk: Fix detection of MyDocs partition in DISK RAW mode for non RX-51 devices 2016-05-12 00:12:55 +02:00
Pali Rohár d2e7b3d242 mkii: Implement rebooting to Update mode 2016-03-12 12:47:41 +01:00
Pali Rohár 54805eb040 mkii: Define MKII_UPDATE_MODE instead hardcoded constant 2016-03-12 12:01:27 +01:00
Pali Rohár 7b3e9bcf00 mkii: Use libusb_get_active_config_descriptor() instead libusb_get_config_descriptor()
This will fix problem that it was used incorrect config index
2016-03-12 11:38:00 +01:00
Pali Rohár 96e4fa5995 mkii: Fix memory leak, call libusb_free_config_descriptor() 2016-03-12 11:36:50 +01:00
Pali Rohár c560f3642c usb-device: Finish usb device detection based on product strings 2016-03-09 00:15:59 +01:00
Pali Rohár 98451c5851 usb-device: Add FLASH_DISK usb ids for all supported devices 2016-03-09 00:15:25 +01:00
Pali Rohár a1623bcb7e image: Fix detection of jffs2 initfs images
Looks like that some official initfs images are bigger then 3MB, so set limit to 10MB
2016-03-09 00:07:52 +01:00
Pali Rohár c90c6319fe main: Initialize buf before calling dev_get_rd_flags() 2016-02-23 18:38:48 +01:00
Pali Rohár aeb9e897db usb-device: Autodetect Nokia 770 device from product string 2016-02-23 18:23:04 +01:00
Pali Rohár 6952d73082 libusb-sniff: Fix libusb_control_transfer function 2016-02-23 18:15:55 +01:00
Pali Rohár bc7894b99d all: Fix usb endpoints after conversion to libusb 1.0
Endpoint in nolo.c for libusb_bulk_transfer must be 0x02, not 0x01.
2016-02-21 20:52:21 +01:00
Pali Rohár abcf256268 disk: Use correct libusb function which returns Linux devnum value
It is libusb_get_device_address() and not libusb_get_port_number()
2016-02-12 22:27:35 +01:00
Pali Rohár 09920cf8ab config.mk: Version is from git 2016-01-23 16:46:05 +01:00
Pali Rohár 96de6a6215 usb-device: Fix memory leak when listing devices 2016-01-23 16:38:17 +01:00
Pali Rohár 2504f9e553 travis: Update travis script for clang and libusb-1.0 2016-01-23 16:27:35 +01:00
Pali Rohár 2e9748e6a5 cold-flash: Comment unused omap variables 2016-01-23 16:26:40 +01:00
Pali Rohár fc987674dd all: Code style fixes 2016-01-23 16:07:02 +01:00
Pali Rohár 62fa041f86 all: Rename variable readed to sent 2016-01-23 16:06:51 +01:00
Sebastian Reichel ed4bdab6e7 libusb-sniff: add libusb 1.0 support
This adds additional support for libusb-1.0 to the
sniffing library. Afterwards it can be used with
libusb 1.0 and libusb 0.1 based binaries.
2016-01-23 16:16:18 +01:00
Sebastian Reichel d5028a12ca all: Switch to libusb-1.0
libusb 0.1 is deprecated. This updates 0xFFFF to use the
newer libusb 1.0 API instead.
2016-01-23 16:06:12 +01:00
Pali Rohár 6482e4d2b7 libusb-sniff: Use POSIX.1-2003 workaround for dlsym() assignment which is compatible with C99 2016-01-23 16:03:01 +01:00
Sebastian Reichel 57b0c6d0c4 libusb-sniff: avoid usb.h include
usb.h is only required for the definition of usb_dev_handle,
which is never used, so it can be defined as anonymous struct
instead. This has the advantage, that libusb is not required
on the system compiling the library.
2016-01-23 16:02:46 +01:00
Sebastian Reichel 4a4005b46d libusb-sniff: add header for getenv() 2016-01-23 16:02:40 +01:00
Pali Rohár 5f0897d372 doc: Remove nanddump param -i also from doc 2016-01-13 22:28:36 +01:00
Sebastian Reichel d4342a8cdf disk: dirent.h is required for DIR
Without <dirent.h> include newer gcc releases
throw warnings about undefined "DIR".
2016-01-13 22:23:29 +01:00
Sebastian Reichel 055621d3a2 all: free() is defined in stdlib.h
Without including <stdlib.h> newer gcc releases throw
warnings about undefined free().
2016-01-13 22:23:29 +01:00
Pali Rohár f36a762168 fiasco: Fix code for append device & hwrevs subsection
Fix possible use-after-free in WRITE_OR_FAIL_FREE() macro
2016-01-10 17:26:23 +01:00
Pali Rohár c258289b74 image: Check for return value fo image_read() in image_type_from_data() 2016-01-10 14:33:30 +01:00
Pali Rohár 3c1ab9934d main: Check for SW rel version length 2016-01-10 14:32:43 +01:00
Pali Rohár b48b9b558c fiasco: Remove wrong checks for 'name' and 'swver'
Members 'name' and 'swver' of fiasco are arrays, not pointers
2016-01-10 14:31:28 +01:00
Pali Rohár b7f80de25d all: Check for return value of lseek 2016-01-10 14:29:18 +01:00
Pali Rohár 1ee86c05f4 fiasco: Fix memory leak for device_hwrevs_bufs variable 2016-01-10 13:29:28 +01:00
Pali Rohár 79af7395bf fiasco: In simulate mode do not close invalid not open fd 2016-01-10 13:27:17 +01:00
Pali Rohár ccef3c6daa README: Update 0xFFFF website 2016-01-10 12:53:57 +01:00
Pali Rohár 05f7048580 local: Call nanddump without -i param
Param -i was removed in recent versions of mtd-utils.
And in older versions it did nothing.
2016-01-10 12:33:22 +01:00
Pali Rohár 75ea4bfbd8 image: Fix condition for detecting device 2015-06-24 19:09:34 +02:00
Pali Rohár 3f406cc9ad fiasco: Fix checking for header of next image 2015-06-24 18:30:07 +02:00
Dhole 94a2fe0c17 mangen: Set build date externally
Patch build system to allow the build date in the man entry
to be set externally. In Debian it will be set to the latest
debian/changelog entry for reproducibility.
2015-06-24 17:46:28 +02:00
Pali Rohár 289d2f22b2 image: Fix detecting new ARM U-Boot images 2015-01-15 09:42:40 +01:00
Pali Rohár f965980e2b all: Fix MEMMEM implementation 2015-01-15 09:42:01 +01:00
Pali Rohár ef678ecf6c fiasco: Remove not reached code 2014-11-26 17:00:10 +01:00
Pali Rohár 33f1dc8b55 local: Fix argument for mmap/munmap 2014-11-26 16:53:08 +01:00
Pali Rohár bb90caec1b all: Fix overflow in shift operators 2014-11-26 16:49:39 +01:00
Pali Rohár c86e130ab1 Makefile: Now 0xFFFF is Posix compatible, enable -D_POSIX_C_SOURCE=200809L 2014-11-26 16:35:01 +01:00
Pali Rohár 448365b588 cal: Enable Linux code only on Linux 2014-11-26 16:33:21 +01:00
Pali Rohár ef1960cc32 disk: Enable Linux code only on Linux 2014-11-26 16:33:07 +01:00
Pali Rohár 5633a06710 local: Enable N900 code only for ARM and enable Linux code only on Linux 2014-11-26 16:32:36 +01:00
Pali Rohár d61815f40e mkii: Fix argument for usb_bulk_write 2014-11-26 16:30:54 +01:00
Pali Rohár 15219cb99c main: Add missing extern variables for getopt 2014-11-26 16:30:32 +01:00
Pali Rohár db4c7c1951 all: Use internal MEMMEM instead gnu memem
It is used only on small strings, so it is fast enough
2014-11-26 16:29:53 +01:00
Pali Rohár 52efd5a404 nolo: Check for return buffer size 2014-11-26 15:47:21 +01:00
Pali Rohár bc9f42f559 all: Use nanosleep (via SLEEP) instead usleep 2014-11-26 15:46:03 +01:00
Pali Rohár a9b1332f8f mkii: Update code with to reflect documentation 2014-11-26 15:09:01 +01:00
Pali Rohár e8f9a79174 doc/mkii: Update info about protocol 2014-11-26 15:07:50 +01:00
Pali Rohár 349a9d40ef mkii: Fix mode information 2014-11-26 14:26:14 +01:00
Pali Rohár c87687128f mkii: Fix mkii_reboot_device 2014-11-26 14:25:50 +01:00
Pali Rohár 8b5c945078 mkii: Fix mkii_get_hwrev 2014-11-26 14:25:41 +01:00
Pali Rohár 2c15535099 operations: Enable mkii_get_sw_ver 2014-11-21 17:48:01 +01:00
Pali Rohár 8369f94195 mkii: Implement mkii_get_sw_ver 2014-11-21 17:47:47 +01:00
Pali Rohár f1095777c6 operations: Check for supported image types in dev_flash_image 2014-11-21 17:16:44 +01:00
Pali Rohár 6372323ee8 usb-device: Difference between Update and PC Suite mode 2014-11-21 17:16:10 +01:00
Pali Rohár 7023b4b290 mkii: Check for Update and PC Suite mode 2014-11-21 17:15:16 +01:00
Pali Rohár 8c305104a0 mkii: Check for supported image types 2014-11-21 17:14:39 +01:00
Pali Rohár d3eb042a1c operations: Enable dumping mmc images via USB disk protocol 2014-11-21 16:41:05 +01:00
Pali Rohár 93680de944 disk: Implement disk_dump_image() 2014-11-21 16:33:42 +01:00
Pali Rohár 5fd0755448 disk: Find emmc device in disk_init() 2014-11-21 16:33:28 +01:00
Pali Rohár bebb608bc8 usb-device: Add data info to struct usb_device 2014-11-21 16:32:30 +01:00
Pali Rohár 75c87a1583 disk: Ignore '.' and '..' when listing directory 2014-11-21 16:31:29 +01:00
Pali Rohár 5d20747c30 local: Ignore '.' and '..' when listing directory 2014-11-21 16:31:13 +01:00
Pali Rohár e66015b880 disk: Remove old disk functions (they are not used anymore) 2014-11-21 15:03:18 +01:00
Pali Rohár e30e08136a local: Use new disk functions 2014-11-21 15:02:10 +01:00
Pali Rohár e00331fb42 disk: Implement new functions for raw disk access 2014-11-21 15:01:30 +01:00
Pali Rohár eb23177014 disk: Implement init and get_device functions 2014-11-18 23:52:14 +01:00
Pali Rohár 5611e8a68c operations: When reboot is not supported use usb_switch_to_nolo() 2014-11-18 23:51:48 +01:00
Pali Rohár bc4aeefab5 usb-device: Do not claim USB interface in raw disk mode 2014-11-18 23:51:04 +01:00
Pali Rohár ea980459f1 operations: Enable RAW disk 2014-11-18 23:31:49 +01:00
Pali Rohár c23e8df260 usb-device: Enable also RAW disk 2014-11-18 23:31:28 +01:00
Pali Rohár 1a59034571 operations: Fix code to work also with Mk II protocol 2014-11-18 23:27:21 +01:00
Pali Rohár feb2d3ac6a usb-device: Rename usb_switch_to_mkii to usb_switch_to_update 2014-11-18 23:26:50 +01:00
Pali Rohár 78fc280577 usb-device: Enable Mk II protocol 2014-11-18 23:26:19 +01:00
Pali Rohár ea9f9d5a69 mkii: Unfinished code for image flashing 2014-11-18 23:25:25 +01:00
Pali Rohár 3dc90e643c mkii: Implement device reboot 2014-11-18 23:24:55 +01:00
Pali Rohár 351bfbd055 mkii: Implement device initialization 2014-11-18 23:24:02 +01:00
Pali Rohár 3538c40ad1 Relase version 0.6.1 2014-11-18 23:23:23 +01:00
Pali Rohár b286e79ddb cold-flash: struct xloader_msg must be packed 2014-11-18 23:19:54 +01:00
Pali Rohár e443393aa5 fiasco: Fix possible memory leak 2014-11-18 20:31:16 +01:00
Pali Rohár 8c788bad62 nolo: Do not call NOLO_ERROR_LOG when not needed 2014-11-18 20:15:14 +01:00
Pali Rohár 142ef93ddc fiasco: Fix initializing variables 2014-11-18 20:14:23 +01:00
Pali Rohár 89566f559b fiasco: Fix memory leaks 2014-11-18 18:49:32 +01:00
Pali Rohár cfd3b662a5 Makefile: Fix compilation of libusb-sniff libraries 2014-11-18 18:09:30 +01:00
Pali Rohár 65888448bf main: When doing normal flash filter all 2nd images
This will fix infinite loop after successfull fiasco image flash
2014-11-18 18:09:06 +01:00
Pali Rohár 26b6f86f84 nolo: Fix parsing cmt status
Now flashing cmt images should work without problems
2014-11-18 18:07:59 +01:00
Pali Rohár f3d203c205 main: Correctly set and free processed images
This will fix more memory corruptions (specially at quit).
2014-11-18 18:06:22 +01:00
Pali Rohár 79a171e823 printf-utils: Fix division by zero if total is zero 2014-11-18 18:04:45 +01:00
Pali Rohár 99608d2b3f usb-device: Reattach kernel driver 2014-11-09 21:51:51 +01:00
Pali Rohár f0712d5b23 all: Replace strlen() call on const string with sizeof()-1 2014-10-19 20:23:21 +02:00
Pali Rohár 8d52950ede main: Use snprintf instead sprintf and initialize buffer to NULL term 2014-10-19 20:18:47 +02:00
Pali Rohár a8986bf631 local: Check return value of snprintf 2014-10-19 20:18:02 +02:00
Pali Rohár 9a1f63c5ae nolo: Check return value of sprintf 2014-10-19 20:17:29 +02:00
Pali Rohár b1564909d7 nolo: Fix size of snprintf buffer 2014-10-19 20:17:06 +02:00
Pali Rohár d6eba11357 fiasco: fiasco_alloc_from_file: check if hwrevs has enough size 2014-10-19 18:26:47 +02:00
Pali Rohár c88e5264c9 main: Update usage 2014-09-29 00:48:37 +02:00
Pali Rohár 84fc04f647 main: Implement -t (filter by type) for -e (dump images) 2014-09-29 00:48:13 +02:00
Pali Rohár 03c6c3899f main: Fix memory corruption 2014-09-29 00:45:17 +02:00
Pali Rohár 1610debbd5 usb-device: Fix memory leak 2014-09-29 00:44:19 +02:00
Pali Rohár 4356b2124e local: Fix memory corruptions 2014-09-29 00:43:54 +02:00
Pali Rohár dfc021d7c4 image: Fix memory leaks 2014-09-29 00:43:15 +02:00
Pali Rohár 23b916bcc9 fiasco: Call free at correct place 2014-09-29 00:42:52 +02:00
Pali Rohár d88176dbef travis: Add .travis.yml for coverity 2014-09-29 00:03:59 +02:00
Pali Rohár 46750e99d0 local: Fix truncating file 2014-06-19 13:27:34 +02:00
Pali Rohár 193e01aa66 debian: Remove debian packaging 2014-06-18 12:42:55 +02:00
Pali Rohár f898ac4411 all: Fix typo 2014-05-10 22:39:47 +02:00
Pali Rohár c6ee6a8e68 Makefile: Fix depends for manpage 2013-09-23 11:41:27 +02:00
Pali Rohár 1096c8b426 doc: Fix typo 2013-09-23 11:33:03 +02:00
Pali Rohár 97eb4484d9 main: Fix typo 2013-09-23 11:32:46 +02:00
Pali Rohár d247e9bdc8 mangen: Add backslash before hyphen 2013-09-23 11:21:24 +02:00
Sebastian Reichel c5d3897e77 mangen: Fix manpage footer for terminals with 80 columns
Signed-off-by: Sebastian Reichel <sre@ring0.de>
2013-09-23 11:10:09 +02:00
Pali Rohár 3b68eaf303 Makefile: Add examples to manpage 2013-09-21 11:10:44 +02:00
Pali Rohár 62e26a81aa doc: Update examples 2013-09-21 11:10:13 +02:00
Pali Rohár 75abff061a main: Fix typo in help 2013-09-21 11:09:11 +02:00
Pali Rohár 17dd99f368 local: Fix searching for MyDocs mmc device
Device name in /sys/block/ could not be same as in /dev/ if udev renaming it.
And this is real problem on Maemo without special kernel patch when device
booting with inserted SD card. So read major and minor numbers from /sys/
and find coresponding device in /dev/. These two numbers will be same after
renaming device too.
2013-09-20 18:12:28 +02:00
Pali Rohár 89bc4a10a3 usb-device: Do not use sighandler_t 2013-09-20 18:08:31 +02:00
Pali Rohár 61a23aff66 printf-utils: Add missing includes 2013-09-20 18:08:01 +02:00
Pali Rohár 9b68e43ac1 TODO: Add TODO file 2013-09-07 22:51:02 +02:00
Pali Rohár de32a6140a operations: Fix crash when no usb device is detected 2013-09-07 22:50:37 +02:00
Pali Rohár 55bfee79a2 usb-device: Handle Ctrl+C SIGINT and quit wait loop 2013-09-07 22:49:08 +02:00
Pali Rohár 287cb10250 usb-device: Remove useless check for LIBUSB_HAS_GET_DRIVER_NP 2013-09-07 22:31:39 +02:00
Pali Rohár 08e53f404d printf-utils: Remove dead HAVE_SQUEUE code 2013-09-07 22:30:06 +02:00
Pali Rohár f3870fd788 debian: Update description 2013-09-07 22:17:35 +02:00
Pali Rohár 1b393d1e41 local: Rename macro local_cal_store to local_cal_readcopy 2013-09-07 22:16:47 +02:00
Pali Rohár 1c1bfb9c78 image: Fix buffer pointer in function image_hash_from_data 2013-04-21 17:53:34 +02:00
Pali Rohár 0cd7a0c2cc image: image_read returns unsigned type 2013-04-21 17:52:51 +02:00
Pali Rohár 79832d9289 local: Fix filename for local mmc dump 2013-04-21 17:52:14 +02:00
Pali Rohár 796dc3a677 Makefile: Add support for cross compile 2013-04-21 17:07:01 +02:00
Pali Rohár 1c20e5ff5f local: Simplify nanddump code 2013-04-21 16:36:30 +02:00
Pali Rohár fbd23222b1 local: Add nanddump table for RX-44 and RX-48 2013-04-21 16:34:43 +02:00
Pali Rohár 47bdc71eea debian: Add debian packaging 2013-04-07 15:21:41 +02:00
Pali Rohár d9e43ef41c doc: Add examples 2013-04-07 15:16:50 +02:00
Pali Rohár 3d914ce22b doc: Remove usage (now replaced by autogenerated manpage) 2013-04-07 14:59:07 +02:00
Pali Rohár 2b80f8e620 Makefile: Add libusb-sniff library rules 2013-04-07 14:47:52 +02:00
Pali Rohár 0df9ca3e59 Makefile: Remove dependency on libm.so 2013-04-07 14:40:29 +02:00
Pali Rohár 3637723661 main: Fix compile warning: declared with attribute warn_unused_result 2013-04-07 14:40:05 +02:00
Pali Rohár a02caaac15 printf-utils: Fix compile warning: declared with attribute warn_unused_result 2013-04-07 14:39:45 +02:00
Pali Rohár a1febdd2ea local: Fix compile warning: declared with attribute warn_unused_result 2013-04-07 14:39:26 +02:00
Pali Rohár 848e3fe06c device: Remove dependency on log10, max value of uint16_t is 5 2013-04-07 14:38:41 +02:00
Pali Rohár eb97fad2a7 usb-device: Disable Mk II protocol and RAW disk because are not implemented yet 2013-04-07 14:24:31 +02:00
Pali Rohár 7de5d7fd92 main: Fix help title 2013-04-07 14:23:48 +02:00
Pali Rohár 032538ec5a usb-device: Fix crashing when accessing out of global array usb_flash_protocols in function usb_flash_protocol_to_string 2013-04-07 14:23:26 +02:00
Pali Rohár 2c34ec70d2 Makefile: Add mangen rules 2013-04-07 14:12:04 +02:00
Pali Rohár 5a6965afef mangen: Generate manpage from 0xFFFF -h output 2013-04-07 14:11:52 +02:00
Pali Rohár acf7e1cad7 README: Update info 2013-04-07 14:10:54 +02:00
Pali Rohár 37844a6b9a main: Fix memory corruption when loading/flashing FIASCO images 2013-04-06 16:04:08 +02:00
Pali Rohár 5c90f39f6e image: Do not call image_free on NULL pointer 2013-02-25 11:35:08 +01:00
Pali Rohár 5ca1e0c899 nolo: Show only first 20 error messages, fix possible infinity loop 2013-02-25 11:32:28 +01:00
Pali Rohár b997951f97 nolo: Respect simulate flag
* Do not flash images
* Do not write strings
2013-02-25 11:30:57 +01:00
Aaro Koskinen 6dae516af2 cold-flash: accept also OMAP3630 in the ASIC ID
Accept also OMAP3630 in the ASIC ID offset 4. With this patch it's
possible communicate also with N950/N9. When plugging in the USB cable
into a powered-off device, it seems to start in cold-flash mode, and
currently 0xFFFF fails with "Invalid ASIC ID."

So far only loading & booting kernel with "0xFFFF -m kernel:zImage -l -b"
has been tested, and it works.

WARNING: When booting a self-made kernel on N950/N9, NOLO will detect this
and will permanently show a crappy disclaimer about warranty voided during
the boot, even if you boot again with a stock Nokia kernel. This may also
impact some SW functionality. I have no idea how to reset this condition.
2013-02-18 00:18:44 +01:00
Aaro Koskinen f5a9d273ce cold-flash: correct chip/soc name
RX-51/N900 has OMAP3430, and it seems this is what the ASIC ID field at
offset 4 refers to. Fix the comment and printf.
2013-02-18 00:18:44 +01:00
Pali Rohár 22f71b0f25 nolo: Implement NOLO error log, for each failed usb operation print error from NOLO
* When some usb operation failed, NOLO adding string error to log
* Error log can be transfered via usb_control_msg function
2013-02-04 02:46:00 +01:00
Pali Rohár f96a530392 doc/local-flash: Add info about ubi on n900 2013-02-01 13:42:14 +01:00
Pali Rohár 3e17c94722 doc/dumping: Add info about naddump 2013-02-01 13:41:53 +01:00
Pali Rohár 1eef797e29 local: Fix initfs nand partition which is without NOLO header, rename variable nanddump_n900 to nanddump_rx51 2013-02-01 13:19:35 +01:00
Pali Rohár 62bb8e4e28 Makefile: Add $(BIN) to destination in make install 2013-01-24 10:52:34 +01:00
Pali Rohár 2f7bab98bf Makefile: Fix make install 2013-01-24 01:48:19 +01:00
Pali Rohár 3480526cde main: Fix loading kernel & initfs images 2013-01-12 14:26:47 +01:00
Pali Rohár 7dd8fdb560 main: In load mode, do not set kernel or initfs image more times 2013-01-11 21:56:33 +01:00
Pali Rohár 1bcaf8f79c nolo: Fix possible reading from uninitialized memory 2013-01-05 13:31:58 +01:00
Pali Rohár e362f3cab9 Fix crashing when accessing out of global arrays 2013-01-05 12:11:03 +01:00
Pali Rohár 9ea9bea096 Fix Makefile 2012-11-25 23:05:04 +01:00
Pali Rohár 1e84b07b39 Update doc 2012-11-25 22:57:04 +01:00
Pali Rohár e205b47789 Update INSTALL and README, added AUTHORS 2012-11-25 21:18:27 +01:00
Pali Rohár 1edbc5e52e Update Makefiles 2012-11-25 21:15:35 +01:00
Pali Rohár 0629204d39 Remove old mtd headers from tree 2012-11-25 20:59:32 +01:00
Pali Rohár a01de09ca5 Remove old console prompt from tree 2012-11-25 20:59:10 +01:00
Pali Rohár 355fe9dc62 Remove old queue mode from tree 2012-11-25 20:58:28 +01:00
Pali Rohár 857123e9e4 main: Remove console prompt and shared queue mode 2012-11-25 20:57:11 +01:00
Pali Rohár edb4793863 Remove old gui from tree 2012-11-25 20:54:22 +01:00
Pali Rohár 880a3e0846 Remove old logotool from tree 2012-11-25 20:52:16 +01:00
Pali Rohár 9833f94dad Remove old man pages from tree 2012-11-25 20:51:18 +01:00
Pali Rohár cffeb329c4 Remove libusb from tree 2012-11-25 20:49:10 +01:00
Pali Rohár 4f6eb6e936 local: Read from CAL also overwritten hw revision 2012-11-24 15:42:34 +01:00
Pali Rohár 1776315097 device: Fix memory corruption in device_list_alloc_to_bufs 2012-11-24 12:55:48 +01:00
Pali Rohár def1d49ab4 device: Fix memory corruption, allocate enought memory for device_list_alloc_to_bufs 2012-11-24 12:39:47 +01:00
Pali Rohár 3e863759d3 device: Fix memory corruption, do not call log10(0) 2012-11-24 12:38:56 +01:00
Pali Rohár 87202c38a0 main: After dumping rename image to standardized name 2012-11-24 11:38:15 +01:00
Pali Rohár 246394d25b local: Use disk_dump_raw for dumping mmc image, use linux sysfs for finding MyDocs device 2012-11-24 11:09:46 +01:00
Pali Rohár 6ecc3e2a80 local: Fix default value for usb_host_mode and root_device, fix align for mmc, remove empty dumps 2012-11-24 11:08:25 +01:00
Pali Rohár 9164f331a3 disk: Added function disk_dump_raw for dumping raw block device 2012-11-24 11:06:26 +01:00
Pali Rohár d5ff815e72 main: When dumping, store image versions to fiasco image 2012-11-24 02:44:57 +01:00
Pali Rohár 8c624670cc main: Added support for initfs version string (param -T) 2012-11-24 01:04:02 +01:00
Pali Rohár 51072eb40a operations: Added support for initfs version string 2012-11-24 01:03:27 +01:00
Pali Rohár bd54b19bbf mkii: Added template for initfs version string 2012-11-24 01:03:06 +01:00
Pali Rohár 69b5278710 nolo: Added support for initfs version string 2012-11-24 01:02:45 +01:00
Pali Rohár 2e78262c10 local: Use in-tree CAL parser 2012-11-24 01:01:53 +01:00
Pali Rohár c03e01879e cal: Added CAL parser from Calvaria 2012-11-24 00:54:01 +01:00
Pali Rohár 9087b564ba local: Fix image dumping (now dumping on N900 working) 2012-11-23 22:09:10 +01:00
Pali Rohár 8084f68b50 local: Fix device detection 2012-11-23 22:08:45 +01:00
Pali Rohár 1ebc2b8308 image: Align all images (not only mmc and kernel) 2012-11-23 22:07:48 +01:00
Pali Rohár ae03494a73 main: Fix memory corruption 2012-11-21 14:54:24 +01:00
Pali Rohár 6665ba9917 usb-device: Disable FLASH_DISK and FLASH_MKII modes in usb device table until there will be implementation 2012-11-21 14:19:46 +01:00
Pali Rohár 75df75b4e9 usb-device: Fix formatting messages and fix usb_switch_to_cold 2012-11-21 14:16:10 +01:00
Pali Rohár 82dd535429 operations: Rebooting in cold flash mode does not make sense, instead boot to NOLO 2012-11-21 14:15:22 +01:00
Pali Rohár 288726981a local: Do not call local_init more times 2012-11-21 14:14:21 +01:00
Pali Rohár 8635ea66a7 cold-flash: Decrease usleep time after leave_cold_flash 2012-11-21 14:13:12 +01:00
Pali Rohár cbffb8f924 console: Reformat code 2012-11-20 22:09:09 +01:00
Pali Rohár 7b5d36bd4c Remove old dump code 2012-11-20 22:02:56 +01:00
Pali Rohár 067c84ea2c usb-device: Fix usb_switch_to_cold 2012-11-20 21:52:03 +01:00
Pali Rohár 29c2b60670 nolo: Fix unused parameter warnings 2012-11-20 21:51:37 +01:00
Pali Rohár 09b6b377fe mkii: Fix unused parameter warnings 2012-11-20 21:51:29 +01:00
Pali Rohár a6ec2b36c4 local: Fix unused parameter warnings 2012-11-20 21:51:21 +01:00
Pali Rohár 2cbeb4d0fe disk: Fix unused parameter warnings 2012-11-20 21:51:12 +01:00
Pali Rohár 116e77bef7 mkii: Fix return values 2012-11-20 21:41:58 +01:00
Pali Rohár 2746da7a03 disk: Fix return values 2012-11-20 21:40:26 +01:00
Pali Rohár 3d7b15e30b local: Fix return values 2012-11-20 21:38:11 +01:00
Pali Rohár 912ec5210e local: Fix condition in local_dump_image 2012-11-20 21:35:19 +01:00
Pali Rohár 6a6a6348f5 image: Fix memory leak 2012-11-20 21:31:40 +01:00
Pali Rohár 01ec9928f9 local: Implement local_dump_image 2012-11-20 21:24:02 +01:00
Pali Rohár bd141d2739 device: Fix memory corruption 2012-11-20 21:13:18 +01:00
Pali Rohár 463dc3c6dd main: Implement dump 2012-11-20 20:42:58 +01:00
Pali Rohár 3f96851407 Change dump_image API 2012-11-20 20:42:17 +01:00
Pali Rohár 10217cd331 image: Fix function image_missing_values_from_name 2012-11-20 19:51:36 +01:00
Pali Rohár 886b40e4b5 Makefile: Remove CFLAGS unsupported by old gcc 2012-11-19 14:08:45 +01:00
Pali Rohár 99294e1b74 operations: Added support for Mk II and RAW disk mode 2012-11-15 15:24:43 +01:00
Pali Rohár 5f0b6bb328 usb-device: Added support for Mk II 2012-11-15 15:23:45 +01:00
Pali Rohár aa366ea133 Makefile: Add mkii.o and disk.o 2012-11-15 15:22:57 +01:00
Pali Rohár 4ef49e123a main: In help show also supported connection protocols 2012-11-15 15:22:00 +01:00
Pali Rohár 64505e1b73 usb-device: Add FLASH_COUNT 2012-11-15 15:21:23 +01:00
Pali Rohár a9c0daab68 Added template for USB RAW disk mode 2012-11-15 15:21:00 +01:00
Pali Rohár 420482c6b7 Added template for Mk II flashing protocol 2012-11-15 15:12:58 +01:00
Pali Rohár 09a6405501 operations: Remove network connection method 2012-11-15 13:13:32 +01:00
Pali Rohár cc8cca84ef operations: Added support for local device 2012-11-15 01:40:09 +01:00
Pali Rohár e98891e52d Added code for local on device operations 2012-11-15 01:39:18 +01:00
Pali Rohár e66d87fde0 Added macro PRINTF_ERROR_RETURN which working with progressbar 2012-09-23 17:09:27 +02:00
Pali Rohár e4f7cf7bc5 main: Fix loading images 2012-09-23 16:48:24 +02:00
Pali Rohár cd9b51ad80 main: Set swver from fiasco image 2012-09-23 16:31:52 +02:00
Pali Rohár 2189eebaf0 main: Fix '-x' option 2012-09-23 16:24:51 +02:00
Pali Rohár 08adc52c78 Remove WITH_ defines 2012-09-23 16:19:43 +02:00
Pali Rohár 95571860d0 main: Rewrite to use operations.h 2012-09-23 16:19:16 +02:00
Pali Rohár f35c4048fe operations: Added operations file for wrapping all device operations 2012-09-23 16:13:33 +02:00
Pali Rohár d76b5a2b44 cold-flash: Added function init_cold_flash, basic check if asic id is correct 2012-09-23 16:12:22 +02:00
Pali Rohár d8c6a03147 device: Fix compile error 2012-09-23 14:14:49 +02:00
Pali Rohár fc51f45195 usb-device: Added usb_switch_to_ functions 2012-09-23 14:03:28 +02:00
Pali Rohár 26c1c2914e nolo: In nolo_init check if device match to usb device, remove detected_ prefix 2012-09-23 14:02:52 +02:00
Pali Rohár 230d45c9e3 main: detected_ prefix was removed 2012-09-23 14:01:51 +02:00
Pali Rohár f059663164 usb-device: Check for USB product string if device match, remove detected_ prefix 2012-09-23 14:01:20 +02:00
Pali Rohár d9e6d47f1b nolo: Fixed nolo_get_string 2012-09-23 13:59:31 +02:00
Pali Rohár b2bd1d90c7 usb-device: Fix serial number string 2012-09-23 13:51:29 +02:00
Pali Rohár 863cf8134a nolo_get_hwrev and nolo_set_hwrev - use int16_t 2012-09-23 12:24:09 +02:00
Pali Rohár 6c220a45fd nolo: nolo_boot_device - cmdline is const 2012-09-23 12:23:40 +02:00
Pali Rohár ada683ed9b image: Added mmc detection 2012-09-23 11:51:18 +02:00
Pali Rohár 5efa0d96b8 usb-device: If usb_claim_interface fail, exit program 2012-09-23 01:52:17 +02:00
Pali Rohár a321f275ef libusb-sniff: Fix usb_control_msg log 2012-09-23 01:49:29 +02:00
Pali Rohár 7868ad0c71 nolo: Fix cmt info and implement nolo_set_hwrev 2012-09-23 01:48:44 +02:00
Pali Rohár c0e490cc30 nolo: Implemented nolo_set_sw_ver 2012-09-23 00:20:10 +02:00
Pali Rohár 15b05dce75 nolo: Fix nolo_send_image 2012-09-22 23:59:15 +02:00
Pali Rohár e4b4d211c1 usb-device: fix usb device serial number string 2012-09-22 23:20:01 +02:00
Pali Rohár b0130e52d6 Fix compilation on 32bit system 2012-09-22 23:16:56 +02:00
Pali Rohár 6d69da6cd1 nolo: Show progressbar and wait when flashing cmt 2012-09-22 23:02:35 +02:00
Pali Rohár 3666e285dc doc: Update fiasco documentation 2012-09-22 22:32:13 +02:00
Pali Rohár ddb3406855 nolo: Implement loading and flashing images 2012-09-22 22:29:55 +02:00
Pali Rohár 11410296a7 nolo: Implement nolo_set_string and nolo_get_string 2012-09-22 22:29:05 +02:00
Pali Rohár d636ef78dd hwrev is int16_t 2012-09-22 21:23:56 +02:00
Pali Rohár 0d6b32c371 device: fix hwrev_is_valid 2012-09-22 21:00:12 +02:00
Pali Rohár 66966a242d main: update filtering 2012-09-22 20:56:28 +02:00
Pali Rohár d1bb1b6094 Fix generating fiasco images 2012-09-22 20:45:27 +02:00
Pali Rohár 28ca666c6e fiasco: Fix fiasco_write_to_file 2012-09-22 20:37:30 +02:00
Pali Rohár f8ad95ee4d device: Fix device_list_alloc_to_bufs 2012-09-22 20:36:44 +02:00
Pali Rohár f6c9450319 device: Fix hwrevs_alloc_from_string 2012-09-22 19:55:31 +02:00
Pali Rohár 2127e08052 image: Fix autoidentify images 2012-09-22 19:55:14 +02:00
Pali Rohár a072a2cf83 fiasco: Use image_list 2012-09-22 19:49:58 +02:00
Pali Rohár 3a83d99f9a main: Use image_list 2012-09-22 19:49:48 +02:00
Pali Rohár 1a89112c25 image: Implement image_hwrev_is_valid 2012-09-22 19:49:04 +02:00
Pali Rohár 10a2bc6319 device: Rename function to hwrev_is_valid 2012-09-22 19:48:40 +02:00
Pali Rohár 55c158fc34 image: Use device_list 2012-09-22 19:38:13 +02:00
Pali Rohár e41cf5236a device: Fix device_list_alloc_to_bufs 2012-09-22 19:37:21 +02:00
Pali Rohár 54ddeb6407 device: Implement hwrevs as array of int16_t 2012-09-22 18:16:26 +02:00
Pali Rohár 8167e841ce main: Added support for loading and flashing images 2012-09-22 11:33:14 +02:00
Pali Rohár ad7bab8df8 main: Fixed infinite loops 2012-09-22 11:32:41 +02:00
Pali Rohár 805bafacef libusb-sniff: Disable printing output of libusb function if env USBSNIFF_SKIP_* is set 2012-09-22 10:20:49 +02:00
Pali Rohár 40cd74c506 image: Do not verify image types and devices if noverify was specified 2012-08-27 17:18:38 +02:00
Pali Rohár c92df79829 main: Update help for 80 chars terminals 2012-08-24 10:45:47 +02:00
Pali Rohár 62aa414dc0 main: Fix error message 2012-08-24 10:33:57 +02:00
Pali Rohár 36aff5fca4 image: Check if specified image type and device are correct 2012-08-24 10:33:38 +02:00
Pali Rohár d9aeffa1d0 image: Fix image detection, detect kernel by magic number and U-Boot by arm branch instruction 2012-08-24 10:01:32 +02:00
Pali Rohár d0d249c738 fiasco: Fixed compile warnings 2012-08-13 11:57:30 +02:00
Pali Rohár db546a17b8 cold-flash: Add all omap boot messages 2012-08-12 17:32:42 +02:00
Pali Rohár d35d6142ca nolo: Respect simulate flag 2012-08-12 12:21:49 +02:00
Pali Rohár 2d52d8c3c6 fiasco: Respect simulate flag 2012-08-12 12:19:33 +02:00
Pali Rohár 1ba42ce46f image: Fix image_missing_values_from_name 2012-08-12 10:41:38 +02:00
Pali Rohár 1736afae69 Remove IMAGE_OMAP_NAND type - it is 2nd 2012-08-12 10:41:05 +02:00
Pali Rohár 0f5f96149f Added LD_PRELOAD library libusb-sniff for sniffing usb communication 2012-08-12 10:09:30 +02:00
Pali Rohár e084cdaabe doc/fiasco: Update info 2012-08-11 22:25:25 +02:00
Pali Rohár 89e70ea88c doc/mkii: Added initial RE documentation about Mk II protocol 2012-08-11 22:12:01 +02:00
Pali Rohár 2544d42ee2 main: Check if some action was specified 2012-08-11 21:37:55 +02:00
Pali Rohár 0d1d64bbfe Makefile: Remove duplicate flags 2012-08-11 21:24:18 +02:00
Pali Rohár 26099e9536 image_read returns size_t, so 0 when error or end of file 2012-08-11 21:23:53 +02:00
Pali Rohár 17c6aefdcb printf-utils: Add newline when 100% 2012-08-11 21:20:14 +02:00
Pali Rohár ab07fec919 main: Fix parse_image_arg, check if arg is file 2012-08-11 18:16:29 +02:00
Pali Rohár 0e687beed3 image: Fix image_missing_values_from_name 2012-08-11 18:16:02 +02:00
Pali Rohár 131e8bbe1f image: Fix image_read 2012-08-11 18:04:52 +02:00
Pali Rohár 0809303feb image: Detect ROMFS file as initfs 2012-08-11 17:16:09 +02:00
Pali Rohár 33d00aa714 image: Fix aligning, now aligning is working again 2012-08-11 17:15:53 +02:00
Pali Rohár 24a12b2e72 main: Fix usb loop 2012-08-11 15:25:28 +02:00
Pali Rohár 6062a736d2 usb-device: Fix usb_descriptor_info_print and Mk II name 2012-08-11 15:24:46 +02:00
Pali Rohár 6cd01df098 main: Added support for booting into update mode 2012-08-11 15:24:16 +02:00
Pali Rohár 8a21acc9cc nolo: Merge functions nolo_boot and nolo_boot_to_update_mode to nolo_boot_device 2012-08-11 15:24:02 +02:00
Pali Rohár 8c1cfe3a6e nolo: Implement nolo_boot_to_update_mode 2012-08-11 14:53:22 +02:00
Pali Rohár 8e2c830433 usb-device: Show USB device descriptor info 2012-08-11 14:40:56 +02:00
Pali Rohár 868bee0413 nolo: Implement setting and getting R&D flags, remove old code 2012-08-11 14:40:08 +02:00
Pali Rohár d6ad749515 main: Options -b -e -u working without argument 2012-08-11 11:57:20 +02:00
Pali Rohár 83bcb7358c Rewrite Makefile, move WITH_DEVICE, WITH_USB and WITH_SQUEUES to Makefile 2012-08-11 11:12:58 +02:00
Pali Rohár 67d3e4de70 main: Try cold flash again only if it returns -EAGAIN 2012-08-11 10:39:52 +02:00
Pali Rohár 8c5590d150 cold-flash: Rewrite error messages and return negative error values, -EAGAIN if not in cold flash mode 2012-08-11 10:39:11 +02:00
Pali Rohár cb25a8bd3e main: Move image fitering to functions, do not fail if device or hwrev is not detected 2012-08-11 09:54:05 +02:00
Pali Rohár 3c4c0088f0 nolo: Make sure that nolo_get_device return valid or unknown device 2012-08-11 09:51:13 +02:00
Pali Rohár e75b963d3a usb-device: Add variable detected_hwrev to struct usb_device_info 2012-08-11 09:50:38 +02:00
Pali Rohár 378dfe3162 nolo: Implement getting all version strings 2012-08-10 22:35:02 +02:00
Pali Rohár dddf92646d main: Compile only supported options 2012-08-10 22:18:33 +02:00
Pali Rohár 791f805fa0 main: Implement setting configuration 2012-08-10 22:09:31 +02:00
Pali Rohár 5325bfdfd1 main: finish device identify 2012-08-10 21:54:37 +02:00
Pali Rohár 3d42ebaf73 nolo: show note about unimplemented functions 2012-08-10 21:54:21 +02:00
Pali Rohár 4ab76a5112 global: Fix ERROR_INFO_STR 2012-08-10 21:48:17 +02:00
Pali Rohár f4b0e9b6f3 Comment all old code 2012-08-10 21:37:37 +02:00
Pali Rohár 6cf03a9e28 Rename main2.c to main.c 2012-08-10 21:36:46 +02:00
Pali Rohár ded123141c Remove old main.c code 2012-08-10 21:36:03 +02:00
Pali Rohár 8ea3ba3771 nolo: Remove old code 2012-08-10 21:35:37 +02:00
Pali Rohár 0e0844b78b main: Fail if device is not in NOLO mode, show NOLO version 2012-08-10 21:27:18 +02:00
Pali Rohár a1d95afbf7 Fix NOLO communication 2012-08-10 21:23:19 +02:00
Pali Rohár dc8844f112 nolo: Start implementing new nolo code 2012-08-10 19:14:09 +02:00
Pali Rohár a67a16479c global: Added macro ERROR_RETURN 2012-08-10 19:13:56 +02:00
Pali Rohár 24f34d2f55 nolo: Prepair new function names 2012-08-10 17:19:44 +02:00
Pali Rohár 19a8d76e0c main: Do not enter to usb mode if not needed 2012-08-10 17:19:03 +02:00
Pali Rohár aa89ef8dad usb-device: Update usb interface and alternate number for RX-51 Mk II protocol 2012-08-10 15:39:55 +02:00
Pali Rohár ff7a89b781 main: Update help 2012-08-10 14:58:54 +02:00
Pali Rohár 8eb58ad08c Move checking for flashing protocol from main to cold-flash 2012-08-10 14:56:38 +02:00
Pali Rohár 32f2e53304 printf-utils: Added function printf_and_wait 2012-08-10 14:47:31 +02:00
Pali Rohár f79b653523 cold-flash: Use struct usb_device_info 2012-08-10 13:22:01 +02:00
Pali Rohár cc6e2dcfcd usb-device: Include once 2012-08-10 12:26:13 +02:00
Pali Rohár adbe2dabad Remove old hexdup.c code 2012-08-10 12:23:54 +02:00
Pali Rohár 4b7769a67d Remove old os.h code 2012-08-10 12:20:57 +02:00
Pali Rohár 27acbb09a5 Fix compilation 2012-08-10 12:19:28 +02:00
Pali Rohár b142205f1c Remove old main.h code 2012-08-10 12:14:05 +02:00
Pali Rohár e4858deccd console: Prepair for new code 2012-08-10 12:10:17 +02:00
Pali Rohár 3ce8ca13f1 Rename utils.c to printf-utils.c, remove unused functions 2012-08-10 12:03:30 +02:00
Pali Rohár ad68e324c6 Fix ERROR macros 2012-08-10 12:01:14 +02:00
Pali Rohár 34b55a222e dump: Prepair for new code 2012-08-10 10:49:40 +02:00
Pali Rohár bc9441ddd6 qmode: Prepair for new code 2012-08-10 10:39:39 +02:00
Pali Rohár 6e0941a3c4 Comment all old code 2012-08-09 21:17:45 +02:00
Pali Rohár 603a64757d Remove old serial.c code 2012-08-09 21:13:13 +02:00
Pali Rohár 2002ba27a2 Move query.c into nolo.c 2012-08-09 21:07:30 +02:00
Pali Rohár 01a7da1d95 Rename flash.c to nolo.c 2012-08-09 21:02:20 +02:00
Pali Rohár 70c09fb5b7 Remove old pieces.c and fpid.c code 2012-08-09 20:49:10 +02:00
Pali Rohár 29084d4acf flash: Rewrite flash_image code to use struct * image 2012-08-09 20:38:47 +02:00
Pali Rohár 0d76941600 Add new code to Makefile 2012-08-09 20:30:55 +02:00
Pali Rohár 5dc162bc4a Delete old check_nolo_order code 2012-08-09 20:11:25 +02:00
Pali Rohár 564b0715f1 Remove old devices.c code 2012-08-09 20:04:25 +02:00
Pali Rohár 6e710dcac9 Remove old hash.c code 2012-08-09 19:52:22 +02:00
Pali Rohár b2883167d5 Rename new fiasco2 to fiasco 2012-08-09 19:50:14 +02:00
Pali Rohár 1b99ad115a Remove old fiasco.c code 2012-08-09 19:48:21 +02:00
Pali Rohár 9baad78435 main: Implement cold flash 2012-08-09 19:44:47 +02:00
Pali Rohár d2ce7052ec fiasco: If image_name_alloc_from_values fails, return -1 2012-08-09 19:43:57 +02:00
Pali Rohár d29c63cac9 usb-device: Rename struct members of usb_device_info 2012-08-09 19:43:22 +02:00
Pali Rohár f597e28a87 usb-device: Rename usb_wait_for_device to usb_open_and_wait_for_device 2012-08-09 18:29:13 +02:00
Pali Rohár a0eff48f30 usb-device: Added PRINTF_ macros for printing and clearing line 2012-08-09 18:25:48 +02:00
Pali Rohár 5310efb16c Added new global macros for ERROR/WARNING/VERBOSE, use it 2012-08-09 17:50:50 +02:00
Pali Rohár 01239ea839 Rename usb_device to usb-device, fix includes 2012-08-09 16:13:43 +02:00
Pali Rohár b4cbab6774 main: Implement more options 2012-08-09 16:07:48 +02:00
Pali Rohár 366680af1b fiasco: Added function fiasco_print_info, fixed fiasco_free 2012-08-09 16:05:44 +02:00
Pali Rohár 4de49acb49 image: Added functions image_print_info, image_list_unlink, image_hwrev_is_valid 2012-08-09 16:01:36 +02:00
Pali Rohár 238f92ab25 device: Fix device_from_string 2012-08-09 16:00:37 +02:00
Pali Rohár 71b63c29d3 cold-flash: Remove usb_detach_kernel_driver_np and usb_claim_interface, now handled in usb_device.c 2012-08-08 21:39:38 +02:00
Pali Rohár e7de4ffe34 main: Start implementing new main.c 2012-08-08 21:33:53 +02:00
Pali Rohár b581c7f25d image: call image_align after checking hash 2012-08-08 20:39:27 +02:00
Pali Rohár d10814e808 main: updated prepaired options 2012-08-08 18:11:26 +02:00
Pali Rohár b582869208 Added enum DEVICE_COUNT and IMAGE_COUNT, Added function device_to_long_string 2012-08-08 18:10:53 +02:00
Pali Rohár dd2c6b7f18 usb_device: Added code for searching usb devices 2012-08-08 17:02:31 +02:00
Pali Rohár 5b17b8e398 cold-flash: Fix usb_set_configuration and usb_claim_interface, Update information about OMAP boot messages, implement function leave_cold_flash 2012-08-08 16:57:39 +02:00
Pali Rohár d96a54994e Added missing license headers 2012-08-08 11:44:50 +02:00
Pali Rohár b80dfdc657 cold-flash: prepair cold-flash code 2012-08-08 11:33:08 +02:00
Pali Rohár d06e88ce39 image: image_type_from_data - added support for rx-51 images 2012-08-07 21:52:16 +02:00
Pali Rohár df9fae0c0e fiasco: after fiasco_unpack return back to origin directory 2012-08-07 21:18:17 +02:00
Pali Rohár 3fed685e79 image: function image_list_add will add image to the end of list 2012-08-07 20:52:37 +02:00
Pali Rohár ef4a506905 fiasco: fix creating fiasco image 2012-08-07 20:41:43 +02:00
Pali Rohár 1a7d30cebf image: Implement image_hash_from_data 2012-08-07 20:10:48 +02:00
Pali Rohár ea52c0509a fiasco: remove align code (now handled by image_read) 2012-08-07 18:43:52 +02:00
Pali Rohár 01726cddc5 image: align image only if needed 2012-08-07 18:42:05 +02:00
Pali Rohár cd52b36d38 image: Added support for aligning images (kernel and mmc), function image_read will fill buf with 0xFF 2012-08-07 18:37:16 +02:00
Pali Rohár 7ab41812ea fiasco: Implemented unpacking to directory 2012-08-07 17:31:53 +02:00
Pali Rohár 2cab7a9c80 fiasco: fix memory errors, prepaire code for unpacking 2012-08-07 17:13:06 +02:00
Pali Rohár 3ead19bdea image: Implement image_missing_values_from_name and image_name_alloc_from_values 2012-08-07 17:10:49 +02:00
Pali Rohár 03eeca994d Added new files device.c and device.h 2012-08-07 16:57:55 +02:00
Pali Rohár b596e97926 Compile fixes 2012-08-07 14:53:52 +02:00
Pali Rohár 589443a356 fiasco: align also kernel 2012-08-07 14:20:54 +02:00
Pali Rohár 869a872897 Implement fiasco functions 2012-08-07 14:01:15 +02:00
Pali Rohár 48fc14c913 Implement image functions 2012-08-07 14:00:50 +02:00
Pali Rohár 37f5d06973 Update device table 2012-08-07 13:57:54 +02:00
Pali Rohár f8d3fa0ecd Prepaired new code for fiasco images 2012-07-14 10:33:15 +02:00
Pali Rohár f62628bf29 Update fiasco documentation 2012-07-14 09:22:47 +02:00
Pali Rohár 8301455a5b Align also kernel image 2012-07-14 09:21:34 +02:00
Pali Rohár 860d71d18a Fix prepaired new 0xFFFF options 2012-06-24 15:00:52 +02:00
Pali Rohár 48384d4e47 Rename n700 --> 770 2012-06-24 11:43:11 +02:00
Pali Rohár ce177a9588 Update usb device table 2012-06-24 11:42:41 +02:00
Pali Rohár 2421b9f6c2 fiasco - remove dead code 2012-06-23 21:26:30 +02:00
Pali Rohár eac07b18d9 Added option to use only image pieces for specific device / hw revision 2012-06-23 18:49:07 +02:00
Pali Rohár 418f3cfd4b Cold Flasher - Remove duplicate usb code, prepair for flashing form fiasco images 2012-06-23 18:19:08 +02:00
Pali Rohár 3f0d6f85d3 Import my open source tool for Cold Flashing: cold-flasher-rx51.c 2012-06-23 18:17:49 +02:00
Pali Rohár 027a6d9a18 Fix compilation warnings 2012-06-23 17:39:33 +02:00
Pali Rohár 58c0dbe275 Update fiasco documentation, now is on 95% complete 2012-06-23 17:03:25 +02:00
Pali Rohár 2110196958 Fiasco image: Allow to specify device string without hw revision (then image is valid for all hw revisions). Generating images should be complete! 2012-06-23 17:01:48 +02:00
Pali Rohár 9195f3c7da Fixed creating fiasco images, added param version: for specifing sw-ver. Now generated fiasco images are valid for nokia flasher. 2012-06-23 16:54:05 +02:00
Pali Rohár 4f92794cdf Rename fwname to swver 2012-06-23 16:21:28 +02:00
Pali Rohár 535561efbf Fix unpacking fiasco images (check for number of subsections). Now unpacking is complete! 2012-06-23 15:54:13 +02:00
Pali Rohár 5da30a5bc5 Fix memory problems when unpacking fiasco images 2012-06-23 15:01:10 +02:00
Pali Rohár 8fdba437af Unpacking fiasco - added support for FW headers (FW name) 2012-06-23 14:09:33 +02:00
Pali Rohár 583cc8a963 When identifing fiasco image, show all pieces 2012-06-23 13:24:12 +02:00
Pali Rohár 491f06015b Added preview of new 0xFFFF arguments to main.c. This change will be needed to support other flashing modes (cold, MK II, ...) 2012-06-23 13:15:44 +02:00
Pali Rohár 1aca3bef85 Fix creating fiasco images - added support for specifing device, hwrevs, version, mmc layout and auto align mmc images
Format of arguments for adding piece to fiasco image is now:
$ 0xFFFF -p [[[[dev:hw:]ver:]type:]file[%%layout]
2012-06-23 13:11:54 +02:00
Pali Rohár b4575a40fc Rename hwrev to hwrevs and fix unpacking fiasco images. hwrevs do not have to be separated by nullterm if size of hwrev is 8. 2012-06-23 13:09:44 +02:00
Pali Rohár 8bc521f3e5 do_hash_file - align size for mmc images, append chars \xff (nokia flasher needs mmc images alingned) 2012-06-23 13:07:34 +02:00
Pali Rohár b1cfc3181b Prepair flash_image for specifing device and hw revisions 2012-06-23 13:05:46 +02:00
Pali Rohár 1ddf269c69 Prepair piece structure for device & hw revisions 2012-06-23 13:02:52 +02:00
Pali Rohár dc910a5317 Prepair for flashing via MK II protocol (N900 in PC-Suite mode) 2012-06-23 13:00:12 +02:00
pancake 34c8fb057d * Apply Pali Rohár patch - Add support for device and hw revisions specified in hw pieces - Updated documentation - Fixed problems when unpacking - Ready for mmc and cold flashing 2012-06-23 10:43:20 +02:00
pancake 04f9369ace * Apply Pali Rohár patch fixing RX51 Fiasco Image parsing 2011-12-16 16:17:17 +01:00
pancake b0f69c8b6b * Add manpages (thanks sre!) 2010-11-18 16:32:00 +01:00
pancake dc4fd72133 * Fix warning in dump.c * Port GUI to GtkON syntax * Fix build for latest valac
--HG--
rename : src/gui/gui.gtkaml => src/gui/gui.gtkaml.orig
2010-11-18 00:30:13 +01:00
pancake 20eed53d8c * Fix usb initialization link with n900 * minor syntax fixup 2010-04-26 18:29:19 +02:00
pancake e2aaa2cb40 * Add C files of the gui, so it can be built without gtkamlc or valac * Fix build of gui.gtkaml (sync with last vala) * Update version number in gui about dialog * Some syntax cleanup and removed some unnecesary printf calls 2009-12-22 00:08:47 +01:00
pancake 4d7899fa40 * Use /usr/local PREFIX by default * Bump revision to 0.5 2009-12-21 23:16:28 +01:00
pancake@flubox 3f975a93b3 * Fix segmentation fault with -O2 while unpacking (thanks for reporting) * Various random checks to ensure read/write ops are success 2009-12-21 14:40:12 +01:00
pancake@localhost.localdomain 5f4476566d * Fix n900 identification for dump (-e) * Make clean libusb from the root makefile 2009-10-18 21:03:16 +02:00
pancake@localhost.localdomain b7206abf11 * Fix static build 2009-10-17 15:51:00 +02:00
pancake@localhost.localdomain 034b17cef4 * Added support for local n900 nand dump * Do some code cleanup, update headers from 2007 to 2009 :) - Fix warning messages 2009-10-17 15:43:39 +02:00
pancake 3a1053b29e * Oops missing up
* Added fixups for make install/deinstall
* HAVE_GUI is now enabled by default
* New 'stop' button for goxf GUI
* Fix lil bug in squeue.c
* Initial .desktop icon for freedesktop environments (GNOME)
2008-12-14 03:05:19 +01:00
pancake fc3a613276 * Minor stetical fixups
* Cut 0.4 release :)
2008-12-14 01:40:49 +01:00
pancake 5a96158322 * Implement and test direct file FIASCO flash - openfiasco receives options for grepping for pieces and be verbose - fixed flashing order using grep options xloader, secondary, kernel, initfs, rootfs - Tested and working - Added parser for the hw revision string
* Autodetect device hw revision and setup the subversion string
  on the fly.
2008-12-08 18:13:36 +01:00
pancake 3d427bfd77 * Added -n flag to do not write to disk or flash (simulation)
* Added -S flag to specify subversion id manually while flashing or dumping
* Fixed support for the last fiasco image
  - Skip paddings
  - More verbose output while parsing FIASCO headers
* Initial implementation of the full direct FIASCO flasher
  - No need to dump manually before flashing
* Some warnings and code cleanup
* Fix building issue
* Add HAVE_GUI directive in config.mk
* Up to version 0.4
2008-12-08 00:21:05 +01:00
pancake edac98d26e * Shift doc/faq to doc/faq2
* Add 'doc/faq' with most used commands
* -e can be used with -u to specify the path to extract the files
* Remove gui directory
  - GUI source is in src/gui
  - Incrusted inside the build and install targets
    (ignores build and install errors)
2008-03-07 00:20:45 +01:00
pancake 83c25d7eb2 * Initial working version of the flash gui - Renamed to goxf - Needs 'sudo' to be enabled to the user without password - Identify and ban piece files while including them in the list - Support for flashing multiple piece files - progressbar and warn/error messages handled - Supports reboot mobo command
* Make qmode be functional
* Lot of hardcore fixups on squeue_open
  - Should work now everywhere fine asumid UID 1000 as allowed user
  - Reduce timeouts
  - Add push2 method
2008-03-06 17:58:06 +01:00
pancake 2ddb2923c6 * Initial import of the GtkAML gui frontend - Mostly implemented in just one night :)
* Import the squeue c and vapi sources
* Make 0xFFFF run as squeue daemon with -Q flag
* Up to 0.4
2008-03-05 18:38:42 +01:00
pancake 32a59f4279 * Initial support for n810
- Fix set_altinterface workaround which seems to be checked by nolo 1.7
- n810 has the same USBID than n770
* Define some nolo commands used in query.c in nolo.h
* Get SW version with -i too
2008-02-18 01:25:00 +01:00
pancake fc6bacdb94 * Fix build of gui
* Some initial callbacks and glade tests
2008-02-04 04:30:46 +01:00
pancake 680fd91de8 * Take proper values for claim_interface and set_altinterface from the device->config->interface->altsetting structure 2008-02-02 05:17:58 +01:00
pancake 288cad1c2e * Up to 0.3.2
* Add HAVE_USB to config.mk
  - Now is possible to build a usb-less version of the flasher
    (only for unpacking and so, offline operations)
* Refactor varname. Avoid portability problems:
  - reboot -> moboreboot
2008-01-14 11:25:08 +01:00
pancake 4115aab13d - Import patches from Osvaldo Santana * Fix build on gcc 4 * Fix nanddump call definition (ignore oob added) * Fixed some stupid bugs with -pedantic -std=c99
release 0.3.1
2007-11-20 04:14:13 +01:00
pancake fbdac811fc * Make the fiasco writing api work (some hardcoded things, but mostly ok)
* Move documentation of fiasco format to doc/
* 0.3 release
2007-10-20 02:32:24 +02:00
pancake d15412a788 * Add documentation for the FIASCO format
* Initial fiasco writer api
* Lot of new checks and code cleanup
* fiasco callback now receives a filedescriptor inside header_t
  - the lseek and data free is autonatically done by the main loop
* Split fiasco_data_read() code, useful for streams (embeddeds low mem footprint)
* Add '-P' flag to create a new fiasco pack
2007-10-11 03:14:11 +02:00
pancake 85fdbfb354 * Finally implement the support for the FIASCO firmware format
* Up version to 0.3
* Alphabetically order the help message flags
* Cleaner short help message
* Pseudo-api for creating firmwares (not yet finished)
* Add '-F' flag to flash from a fiasco image
2007-10-08 00:25:56 +02:00
pancake 11e32133b0 * Upgrade to GPLv3 2007-06-30 03:58:18 +02:00
pancake 1f3c790d87 * Initial import of the maemo bug report #1584 into documentation 2007-06-25 23:00:29 +02:00
pancake 6521a8e9d1 * Update documentation for the 0.2 release
* Fix case0 bug of libusb in usb_device_found function
2007-06-25 15:14:14 +02:00
pancake 3728cdea31 * Add new command 'nanddump' for the console shell
* Avoid dumping non-mtd files because writesize = 0
  - Properly close the file when failing

* Better doc/pieces documentation
2007-06-16 05:52:46 +02:00
pancake c1d909c415 * Fix the dump of xloader and secondary.bin
- Looks like they protect these blocks by marking this section as badblocks.
  - We just ignore badblock marks when dumping the bootloader

* Handle feof (^D) on the prompt
2007-06-16 05:21:14 +02:00
pancake 579dbe9837 * Fix device identification for n800. patch from Robert Schuster
- Looks like n770 and n800 have different USB identifiers on the
    bootloader and the operating system.

* Print oops message and exit when the use has no permissions to
  access to the usb.
2007-06-14 23:32:52 +02:00
pancake ed3cb1d3f8 * Finally integrate libusb in Makefiles. Use 'allusb' target to build a 0xFFFF binary without library dependencies (libusb)
* Add 'static' makefile target for building a statically linked 0xFFFF

* Documentate all makefile targets in INSTALL
2007-06-12 23:43:35 +02:00
pancake ea97ac427e * Initial import of the libusb source tree into the flasher - optional, but useful for embedding - avoids gnu autosux problems 2007-06-12 15:29:07 +02:00
pancake a3af55acb4 * Initial implementation of the pretty-print config partition dumper
* Handled with the '-x' flag.
2007-06-11 02:29:11 +02:00
pancake 83b41f9371 * Initial implementation of the "badblocks" (-C) command.
* Initial work on the reorganization of the dump.c code
  to avoid spagetti code. ATM is just a draft

* Dump now shows you more info
2007-06-10 16:15:30 +02:00
pancake c46961d511 * Fix in fpid for proper JFFS2 identification
* Add new flag '-c' that makes 0xFFFF run as a shell
* Split the connect_via_usb() code from main()
* Add console handler for shell like usage of the flasher
2007-06-10 05:41:50 +02:00
pancake ec71146727 * Drop the partition limit. It is calculed with ioctl()
* Query the user to strip or not the dumped pieces
* Add new flag '-s' for serial port console
2007-06-10 00:38:55 +02:00
pancake 43d8d45919 * Initial import of the offline work of the GUI environment
- Not yet usable, it's just a sketch with glade O:)
- But you can get fun hacking on the source!

* Add deinstall target to the Makefile

* Add INSTALL file for build & install instructions

* Add documentation for local flashing.
2007-06-02 05:32:43 +02:00
pancake f299486ef9 * Covardly copy the nanddump() function from the mtd-utils to fix dump functionality
- The new function works like the old rf_extract one, no parameters has
  changed.
- Now a complete dump/restore will be possible.
- Check for badblocks while copying data
- Shows information about the partition

* Better use of query_error_message() for debugging
2007-06-02 02:23:58 +02:00
pancake 1515b7c7c1 * Fix rootfs boundaries for a proper dump.
* Replace Y/n for y/N
* Implement the command '5' (read error message)
2007-05-25 00:33:58 +02:00
pancake ed37b5ee62 * Enhacements and fixups for logotool
* Add support for RGBA raw images (New flag -a)
* Autodetect RGBA images
* Fix endianness stuff when writting the logo header
2007-05-05 03:04:52 +02:00
pancake d0f9d78335 * Move usb-dev related code to devices.c from main.c
* Create a root Makefile to build the flasher, logotool and install
* Clean some warning messages
2007-05-01 15:01:23 +02:00
pancake 3e13254858 * Initial import of the logotool utility 2007-04-30 06:26:27 +02:00
pancake 5e3de1ba06 * Argument 'help' for the -f flag provides information about the rd flags 2007-04-26 00:30:46 +02:00
pancake 5b5425e0d0 * import of the 'set-rd-flags+cleanups' patch from Robert Schuster
adds support for setting and clearing the rd flags (no-retu-watchdog,
  serial-console and the like).

  The interface to it is a bit cryptic (construct your own hex number) but
  it works like like 'chmod'.
2007-04-25 21:47:53 +02:00
pancake 60f2337927 * import of the 'set-get-query_header' from Robert Schuster
1) name the simple functions get_foo and set_foo (and make them more
  consistent e.g. set_rd_mode and get_rd_mode).

  2) moved remaining simple queries from main.c into query.c

  3) created separate query.h header and included it in main.c

  4) implemented get_usb_mode (they do not have this in the proprietary
  flasher) and added this function to a normal run (-> you will see the
  current USB mode when running with -i)
2007-04-25 21:05:03 +02:00
pancake 196f1f7abb * Do not strip the initfs.jffs2 image, it is only 2MB
* Some fixups on the doc/dumping documentation
2007-04-20 21:00:12 +02:00
pancake 300635ad8f * 'set root device' patch inclusion from Robert Schuster 2007-04-20 18:27:31 +02:00
59 changed files with 10046 additions and 1707 deletions

No files matched your search

+32
View File
@@ -0,0 +1,32 @@
sudo: false
language: c
compiler:
- gcc
- clang
addons: &addons
apt:
packages:
- libusb-dev
matrix:
include:
- compiler: gcc
if: (branch = master) AND (type != pull_request)
env:
- secure: "JdUp+xFykPZoYA4aRfmYk2CtilLapniQllWPKo2dDdJd1vzdawfTvVxIAKjy7ac9RKwZzg3Chq3RsMEXPv8BtaLbssw266C7RDLMgjacl1eFLcmGRj/Gkk9peDSZ6vVdGEcA2j+6KDSfpCa/XjFjvOufZOgKw6m+3+d0A4G45SI="
addons:
<<: *addons
coverity_scan:
project:
name: "pali/0xFFFF"
description: "Build submitted via Travis CI"
notification_email: pali.rohar@gmail.com
build_command: make
branch_pattern: master
script:
- if [ -n "$COVERITY_SCAN_TOKEN" ]; then exit 0; fi
- make
+2
View File
@@ -0,0 +1,2 @@
Copyright (C) 2007-2010 pancake <pancake@youterm.com>
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
+753 -251
View File
File diff suppressed because it is too large. Load diff
+26
View File
@@ -0,0 +1,26 @@
Installation instructions:
==========================
To build the flasher you will need gcc, make and libusb. For crosscompiling
to arm you can use scratchbox. But you will probably need the libusb.so of
the scratchbox environment to the device.
Just type:
$ make
The most interesting targets for make are:
all normal build
install installs into /usr/local by default
uninstall remove installed files
clean clean compilation objects and generated binaries
The installation procedure is quite simple and you can define a new PREFIX
manually from the command line:
$ sudo make install PREFIX=/usr
The default one is /usr/local (not very userfriendly but standards are
standards :P hehe)
+2
View File
@@ -0,0 +1,2 @@
all clean install uninstall:
$(MAKE) -C src $@
+24 -9
View File
@@ -1,6 +1,5 @@
------. ,---------.--.--.
/ | ___ | | | \\------------ -- .
| .__ / \/ . ____/ _/ _/ The 0pen
@@ -11,21 +10,37 @@
_/ ___|_.|__|
'`
The 'Free Fiasco Firmware Flasher' aka 0xFFFF utility tries to implement
a free (GPL'd) userspace handler for the NOLO bootloader.
0xFFFF is Open Free Fiasco Firmware Flasher for Maemo devices. It support
generating and unpacking FIASCO images on local computer. Useful for editing
Maemo firmware package for future flash. It support via USB flashing any image
type to Maemo device and also \"cold\" flashing which means flashing dead device
with erased bootloader. There is support for booting kernel via USB without
flashing to NAND and also changing configuration of Maemo device (enable/disable
R&D mode, changing HW revision strings, ...).
0xFFFF is alternative tool to proprietary Nokia flasher-3.5 and fiasco-gen.
0xFFFF generate compatible FIASCO images and also accept FIASCO images generated
by Nokia fiasco-gen.
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.
This tool has been designed and tested on n770. The n800 flash should work
but it's not tested and is known to use different request codes.
PLEASE. Read carefully all the documentation inside doc/* for more information
before building or using the flasher to avoid questions, problems or so.
https://github.com/pali/0xFFFF
-----------8<---------------------------------------------------------------
Build:
$ make
To install: (by default is /usr/local)
$ make install PREFIX=/usr DESTDIR=/
Have phun!
--pancake
--Pali
+26
View File
@@ -0,0 +1,26 @@
cal:
* Write support
cold-flash:
* Detect device from asic id
disk:
* Support for flashing mmc images
* Badblock checking
fiasco:
* Support for Harmattan images
image:
* Support for Harmattan images
local:
* Support for flashing (on device)
* Write versions
* Badblock checking
mkii:
* Support for flashing
nolo:
* Implement functions for setting nolo, kernel, initfs and content versions (it is possible?)
+6
View File
@@ -0,0 +1,6 @@
VERSION = 0.8
PREFIX = /usr/local
# NetBSD stuff
#CPPFLAGS += -I/usr/pkg/include
#LDFLAGS += -L/usr/pkg/lib -Wl,-R/usr/pkg/lib
+53 -28
View File
@@ -1,36 +1,16 @@
<b>Dumping the firmware</b>
Dumping the firmware:
This technique consists on reconstructing a firmware image dumping
pieces at certains offsets of the device internal memory.
pieces at certain offsets of the device internal memory.
Technical details:
<b>End user details:</b>
* Extract the firmware pieces from a running device
* The internal flash memory is exposed to the system as MTD devices.
* Is possible to dump the individual sections of a flashed firmware.
*
* This functionality is useful to extract backups of your system
* firmware. This is really useful when you're on a desert island
* without an internet connection.
*
* This tool needs more testing, so take care and don't blame me if
* it breaks your system. It *is* to your responsability, use at
* your own risk
*
* NOTE: It's theorically possible to flash the device on the fly from
* the running OS, but this has not yet been tested. Keep tuned for
* updates and newz.
*
* Have fun!
* READ src/local.c for detailed information.
<b>Technical details:</b>
* The internal flash memory is exposed to the system as MTD devices. So it's
* possible to dump the individual sections of a flashed firmware.
*
* READ src/dump.c for detailed information.
mtd0 - contains xloader and sencodary pieces of the bootloaders
mtd0 - contains xloader and secondary pieces of the bootloaders
0x00000 - xloader.bin (size is 0x03600)
0x04000 - secondary.bin (size is 0x15400)
0x1FFFF - eof
@@ -40,6 +20,51 @@ pieces at certains offsets of the device internal memory.
mtd2 - starts with NOLO img\x5c\x13 and \x00 padding
0x00800 - zImage
mtd3 - rootfs.jffs2 (20M) aka 0x200000 vs 0x3900000
> NOLO is a four byte marker, next four bytes
> can vary since it is kernel image size
mtd3 - initfs.jffs2 (2M) aka 0x200000 vs 0x3900000
mtd4 - rootfs.jffs2 (a fucking copy of the above rootfs?)
For dumping mtd partition is used tool nanddump. Here is example how to dump
kernel image without padding to file zImage:
$ nanddump -o -b -s 0x00000800 -l 0x001FF800 -f zImage /dev/mtd2
Params means:
-o - "Omit oob data"
-b - "Omit bad blocks"
-s - "Start address"
-l - "Length"
-f - "Output file"
Please note that some new versions of nanddump have some options removed and
some are enabled by default. Before using check params of your nanddump version.
// Extra notes //
[MTD] NAND Consolidate oobinfo handling
The info structure for out of band data was copied into
the mtd structure. Make it a pointer and remove the ability
to set it from userspace. The position of ecc bytes is
defined by the hardware and should not be changed by software.
// The oob stuff
In mtd3 the OOB data is 64 bytes aka 0x40, and this oob stuff
appears every 2KB aka 0x800 bytes.
/*
* Obsolete legacy interface. Keep it in order not to break userspace
* interfaces
*/
struct nand_oobinfo {
uint32_t useecc;
uint32_t eccbytes;
uint32_t oobfree[8][2];
uint32_t eccpos[32];
};
+40
View File
@@ -0,0 +1,40 @@
Via USB:
Identify device:
$ 0xFFFF -I
Load kernel & initfs and boot it with cmdline:
$ 0xFFFF -m initfs:<file> -m kernel:<file> -l -b "<cmdline>"
Flash kernel and reboot:
$ 0xFFFF -m kernel:<file> -f -r
Flash FIASCO image and reboot:
$ 0xFFFF -M <file> -f -r
Flash only kernel from FIASCO image and reboot:
$ 0xFFFF -M <file> -t kernel -f -r
Cold-Flash 2nd and secondary bootloaders:
$ 0xFFFF -m 2nd:<file> -m secondary:<file> -c
On device (need nanddump from mtd-utils):
Dump all images to current directory:
$ 0xFFFF -e
Dump all images to one FIASCO file:
$ 0xFFFF -E <file>
FIASCO packaging:
Show FIASCO image content:
$ 0xFFFF -M <file> -i
Unpack FIASCO image to current directory:
$ 0xFFFF -M <file> -u
Generate new FIASCO image image.fiasco from files xloader.bin, nolo.bin, zImage, rootfs and append device&version information (xloader for RX-51 hw revision: 2101 and 2102, version 1.0)
$ 0xFFFF -m RX-51:2101,2102:1.0:xloader:xloader.bin -m RX-51:2101,2102:1.0:secondary:nolo.bin -m 2.6.28:kernel:zImage -m rootfs -g image.fiasco
+20 -55
View File
@@ -1,70 +1,35 @@
<b>FAQ</b>
FAQ:
This file tries to collect a bunch of common questions/answers about flashing
*) How can I set my Internet Tablet into RD mode with 0xFFFF?
<b>*) Why implement a free software flasher?</b>
The Nokia Internet Tablets are based on Free Software (software libre), but
not everything included *is* free software, for instance, the firmware flasher
tool.
The 0xFFFF project aims to feed the minds of those who really want to
understand how these gadgets work internally, free the knowledge to
avoid the restrictions and fill the lack of information on the most
important part of the system.
That's it, now you can build and run this flasher on *BSD, w32, MacOSX on ARM,
powerpc, x86, mips, etc...
Just type '0xFFFF -R 1' as root
<b>*) Can I brick my device?</b>
*) How can I unpack a FIASCO firmware?
Of course! You're free to do what you want with your device :)
Seriously. Flashing a device is not a safe thing, so I give no warranty
of what will happen to your device when using this tool.
BTW, after a huge number of tests I can say that these devices are hard
to brick, but if you are scared about bricking your device you should
use the flasher provided by Nokia, it's better for your heart's health.
Just type '0xFFFF -M FiascoFirmware.bin -u'
<b>*) What can I do with 0xFFFF?</b>
*) How can I flash a new rootfs?
Actually 0xFFFF allows you to:
- flash separated pieces of the firmware.
- retrieve information about the device
- reboot de mother board
- extract the current firmware pieces from the device (reverse flash)
- set the USB host/slave mode
- set the R&R mode
- identify firmware pieces
# 0xFFFF -m rootfs.jffs2 -f
<b>*) What is NOLO?</b>
*) How can I flash a full FIASCO image?
NOLO is the 'server-side' part of the flasher from Nokia. NOLO means
NOkia LOader and it's composed by two pieces of the firmware that are
flashed together.
On the n800 firmwares, these two pieces are distributed in a single
file, but when flashing a n770, NOLO requires to provide the xloader
(without commiting) and then the secondary piece.
This piece of software is closed source and is the responsable of
handling the requests from the client-side flasher. It provides a
query-like interface via usb control messages for doing different
actions on the device.
# 0xFFFF -M FiascoFirmware.fiasco -f
<b>*) How can I identify my device?</b>
Advanced commands:
Theorically n770 and n800 have different USB device ID, but this is not
true at all. The first series of the n800 comes with the same usb-id
than n770. That's weird!
*) How to extract the firmware pieces from a running device?
So, the only way to identify the device is by asking nolo for the version
information of different pieces of the firmware. This can be faked, because
you can flash n770 stuff on n800 and viceversa, but it's not recommended
because it wouldn't work :)
It is possible to dump the firmware pieces from the internal MTD to reconstruct a FIASCO image.
To do this recompile the flasher for ARM and run this command in the device:
# mkdir /media/mmc1/backup
# 0xFFFF -e /media/mmc1/backup
To dump directly into FIASCO image run:
# 0xFFFF -E /media/mmc1/backup.fiasco
+80
View File
@@ -0,0 +1,80 @@
FAQ2:
This file tries to collect a bunch of common questions/answers about flashing
*) Why implement a free software flasher?
The Nokia Internet Tablets are based on Free Software (software libre), but
not everything included *is* free software, for instance, the firmware flasher
tool.
The 0xFFFF project aims to feed the minds of those who really want to
understand how these gadgets work internally, free the knowledge to
avoid the restrictions and fill the lack of information on the most
important part of the system.
That's it, now you can build and run this flasher on *BSD, w32, MacOSX on ARM,
powerpc, x86, mips, etc...
*) Can I brick my device?
Of course! You're free to do what you want with your device :)
Seriously. Flashing a device is not a safe thing, so I give no warranty
of what will happen to your device when using this tool.
BTW, after a huge number of tests I can say that these devices are hard
to brick, but if you are scared about bricking your device you should
use the flasher provided by Nokia, it's better for your heart's health.
*) What can I do with 0xFFFF?
Actually 0xFFFF allows you to:
- flash separated pieces of the firmware
- flash full FIASCO image
- load kernel & initfs without flashing
- cold-flash bricked device (without NOLO)
- retrieve information about the device
- reboot de mother board
- extract the current firmware pieces from the device (dump)
- set the USB host/slave mode
- set the R&R mode and flags
- pack/unpack FIASCO firmwares
- automatic piece identifier
*) What is NOLO?
NOLO is the 'server-side' part of the flasher from Nokia. NOLO means
NOkia LOader and it's composed by two pieces of the firmware that are
flashed together.
On the n800 firmwares, these two pieces are distributed in a single
file, but when flashing a 770, NOLO requires to provide the xloader
(without committing) and then the secondary piece.
This piece of software is closed source and is the responsible of
handling the requests from the client-side flasher. It provides a
query-like interface via usb control messages for doing different
actions on the device.
*) How can I identify my device?
Theoretically 770 and n800 have different USB device ID, but this is not
true at all. The first series of the n800 comes with the same usb-id
than 770. That's weird!
So, the only way to identify the device is by asking nolo for the version
information of different pieces of the firmware. This can be faked, because
you can flash 770 stuff on n800 and viceversa, but it's not recommended
because it wouldn't work :)
*) Can I unpack FIASCO blobs?
Yes, last version of 0xFFFF has full support of FIASCO images.
+61
View File
@@ -0,0 +1,61 @@
Copyright (C) 2007-2011 pancake <pancake@youterm.com>
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
SPECS FOR THE FIASCO FIRMWARE FILE FORMAT ffff!
-----------------------------------------------
This is final working version of FIASCO format. FIASCO image which
is generated by this spec is acceptable by Nokia flasher-3.5 and
unpack data same as FIASCO image generated by Nokia fiasco-gen. This
format is implemented in 0xFFFF and every image which I tested
(generated by 0xFFFF and fiasco-gen) was properly unpacked under
0xFFFF and flasher-3.5 with same result. Small difference is that
fiasco-gen add some unknown subsection block to image header
(type '4' or '/') which contains some messy characters... But if
these sections missing, flasher-3.5 working fine too. And old FIASCO
images (for N8x0) does not have these subsection...
FILE HEADER
1 byte = 0xb4 -- signature
4 bytes -- FW header length (big endian)
FW HEADER
4 bytes -- number of FW header blocks (big endian)
block {
1 byte -- type of block
0xE8 - Fiasco name
0x31 - FW name
1 byte -- length of block data
N bytes -- block data
}
IMAGE
1 byte = 0x54 -- signature
1 byte -- number of subsection blocks
(start of data block)
1 byte -- type of subsection block (data - always 0x2e)
1 byte -- length of subsection block (data - always 25)
3 bytes -- unknown (always 0x01 0x01 0x00)
2 bytes -- checksum for the image contents (xorpair) (big endian)
12 bytes -- image name type (first byte is FF if is the last image)
4 bytes -- length of image data (big endian)
4 bytes -- unknown (always 0x00 0x00 0x00 0x00)
(end of data block)
block {
1 byte -- type of subsection block
'1' - version
'2' - device & hw revisions (size of device is 16, hw revision 8)
'3' - layout
'4' - unknown
'/' - unknown
1 byte -- length of subsection block
N bytes -- subsection block data
}
1 byte -- unknown (0x00 is accepted, maybe end of subsections?)
N bytes -- image data
+36
View File
@@ -0,0 +1,36 @@
It is possible to flash directly from the device, so this brings the possibility
to completely replace the bootloader flasher by a userland one with extended
features for backuping and recovering data.
The way to flash is using mtd-utils:
$ flash_eraseall -j /dev/mtd3
$ nandwrite -a -p /dev/mtd3 initfs.jffs2
This is an specific example plagied from initfs_flasher of bootmenu.
The '-j' flag says that this is a jffs2 partition. Theoretically this
flag is not required for zImage, and the bootloader pieces.
The '-a' creates the OOB data automatically, and the '-p' flag pads
the data to fill the block.
These flags are only fine for initfs, so this will be probably wrong
for other pieces. Using the dump functionality you can check if you
have flashed properly every piece inside the device, but keep in mind
that it is dangerous and you can brick your device.
But feel free to send feedback to provide a full support for local
flashing on 770 and n800.
Nokia N900 using ubi layout on top of /dev/mtd5 rootfs partition. Therefor
formatting rootfs should be done via ubiformat tool which preserve erase counters.
Erasing N900 rootfs:
$ ubiformat /dev/mtd5
Flashing new ubi image to N900 rootfs:
$ ubiformat /dev/mtd5 -s 512 -O 512 -f image.ubi
+156
View File
@@ -0,0 +1,156 @@
Copyright (C) 2012-2014 Pali Rohár <pali.rohar@gmail.com>
Mk II protocol is the only protocol which can be used to flash eMMC images.
NOLO does not support eMMC, so flashing eMMC is done in Maemo system. NOLO
will boot device into "update" mode and Maemo will start only softupd daemon
(which is responsible for flashing from Maemo system) and load kernel driver
g_softupd which handle USB communication to user space daemon. When device
is in PC Suite mode Maemo system start softupd daemon and load kernel driver
g_nokia which can also handle communication via Mk II protocol.
Default Maemo flasher (v2.5.2 (Oct 21 2009)) support only some basic functions
via Mk II protocol - it can send eMMC image to softupd server which flash it.
But there is unofficial Maemo flasher (flasher v2.8.2 (Jan 8 2010)) distributed
with omap aes kernel driver for Nokia RX-51 under name "flasher.rover" which
support more functions. So "flasher.rover" is better for RE this protocol.
Via Mk II protocol over usb with softupd daemon in device it is possible to
flash any type of image except rootfs (xloader, secondary, kernel, mmc,
cmt-2nd, cmt-algo, cmt-mcusw). Maemo system using same Mk II protocol over
local TCP socket (server also provided by softupd) to update/flash system.
Over usb are used only these functions for communication:
usb_claim_interface (interface=1)
usb_set_altinterface (alternate=1)
usb_bulk_write (ep=1, timeout=5000)
usb_bulk_read (ep=129, timeout=5000)
And this function for sending raw data:
usb_bulk_write (ep=2, timeout=1000)
For every (request) message which is send by host, server send back response.
Format of message every message is same. It has 6 bytes header and (at least)
4 bytes body.
HEADER
4 bytes -- type of header
0x8810001B - out (sent by host: usb_bulk_write)
0x8800101B - in (received by host: usb_bulk_read)
2 bytes -- size of body (big endian)
BODY
2 bytes -- unknown (always zero)
1 byte -- or. num of message (starting with zero)
1 byte -- type of message
N bytes -- data
Reply message data always starts with char 0x00 (except pong response).
Message types:
0x00 - PING
0x01 - GET
0x02 - TELL
0x0C - REBOOT
0x20 - RESPONCE
Here are some sniffed messages from Nokia RX-51. First two messages seems to
must be always protocol version exchange (first host ask for protocol version of
server and then host send its protocol version). On RX-51 is used version "2".
Ping:
req_type = 0x00
res_type = 0x20
Get protocol version:
req_type = 0x01
req_data = "/update/protocol_version"
res_type = 0x21
res_data = 0x00 "2"
Tell our protocol version:
req_type = 0x02
req_data = "/update/host_protocol_version" 0x00 "2"
res_type = 0x22
res_data = 0x00
Get device:
req_type = 0x01
req_data = "/device/product_code"
res_type = 0x21
res_data = 0x00 "RX-51"
Get hwrev:
req_type = 0x01
req_data = "/device/hw_build"
res_type = 0x21
res_data = 0x00 "2101"
Get image types:
req_type = 0x01
req_data = "/update/supported_images"
res_type = 0x21
res_data = 0x00 "xloader,secondary,kernel,mmc,cmt-2nd,cmt-algo,cmt-mcusw"
Reboot device:
req_type = 0x0C
req_data = "reboot" 0x00
res_type = 0x2C
res_data = 0x00
Send image (mmc):
req_type = 0x03
res_type = 0x23
res_data = 0x00
req_type = 0x04
req_data = fiasco subimage header
res_type = 0x24
res_data = 0x00 0x00 0x00 0x00 0x00 0x00 0x02 0x00 0x00
req_type = 0x05
req_data = 0x00 0x00 0x00 0x00 "usb:raw"
res_type = 0x25
res_data = 0x00
req_type = 0x06
req_data = 0x00 0x00 0x00 0x00
res_type = 0x26
res_data = 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
req_type = 0x0B
req_data = 0x00 0x00 0x00 0x64
res_type = 0x2B
res_data = 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x00
req_type = 0x08
req_data = 0x00 0x00 0x00 0x00 0x00 0x10 0x00 0x00
res_type = 0x28
res_data = 0x00
(raw data on ep=2 size=1048576)
req_type = 0x06
req_data = 0x00 0x00 0x00 0x00
res_type = 0x26
res_data = 0x00 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0F 0x9F 0x2C 0x00 0x00
req_type = 0x0B
req_data = 0x00 0x00 0x00 0x64
res_type = 0x2B
res_data = 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x01 0xF0 0x00 0x00 0x00
req_type = 0x08
req_data = 0x00 0x00 0x00 0x00 0x00 0x10 0x00 0x00
res_type = 0x28
res_data = 0x00
(raw data on ep=2 size=1048576)
...
+12 -19
View File
@@ -1,4 +1,4 @@
<b>Nokia tips</b>
Nokia tips:
When developing this tool I've found some bugs and misfeatures that
should be fixed to make flashing safer and cleaner.
@@ -9,7 +9,7 @@ it's really hard to break the device and it works pretty nice. BTW I
think that there are some things that should be fixed.
<b>*) Flashing at low battery level</b>
*) Flashing at low battery level
When the device is under a certain limit of battery it will not start,
this is done by initfs, without any warning message or so, this really
@@ -20,7 +20,7 @@ think that there are some things that should be fixed.
This is *really* dangerous and not very user friendly.
<b>*) Internal nolo state not reset'd</b>
*) Internal nolo state not reset'd
It's possible to get nolo on a strange state that always returns error
when flashing pieces, it's mandatory to reboot the device to recover
@@ -29,7 +29,7 @@ think that there are some things that should be fixed.
This is an strange and not very clear to me.
<b>*) Buffer overflows</b>
*) Buffer overflows
The original nokia flasher has some buffer overflow bugs that should
be fixed. They're safe for 99.9% of cases, but bofs on critical programs
@@ -40,31 +40,24 @@ think that there are some things that should be fixed.
than this one.
<b>*) Missing stuff</b>
There are some flashing options that are not working like passing arguments
to the kernel, set the hw revision or do a cold flash (the most critical
part is undocumented).
<b>*) Weird firmware format</b>
*) Weird firmware format
The (new and old) FIASCO firmware format is not a very clean format, it
doesn't provide any checksumming facility to ensure that the contents of
the firmware have been modified or incorrect, so i'll rather encourage
the firmware have been modified or incorrect, so I'll rather encourage
to design and create a standard firmware format for embedded devices with
checksumming, signatures, handling libraries, documentation and so.
I'll happilly collaborate on the design of this open firmware format, and
I'll happily collaborate on the design of this open firmware format, and
it would be used on all the open source-based devices to aim interoperability
between devices and flashers, providing a more standard and reliable way of
flashing devices.
This will ease the development on new devices, so the information and the
code could be revised and enhaced by zillions of eyes.
code could be revised and enhanced by zillions of eyes.
<b>*) Poor checksumming</b>
*) Poor checksumming
The only checksum is a 16 bit xor of the whole firmware piece and it's only
checked after sending the piece to the device.
@@ -73,7 +66,7 @@ think that there are some things that should be fixed.
algorithm. It currently performs a unique check at the end, it could be
better to check each data block to avoid errors or invalid flashing, isn't it ?
<b>*) No validation of pieces before flashing</b>
*) No validation of pieces before flashing
I've implemented a minimal check of the pieces to avoid flashing invalid
pieces on the wrong place. This is done in fpid.c (firmware piece identifier).
@@ -82,7 +75,7 @@ think that there are some things that should be fixed.
that can (pseudo)brick the device.
<b>*) Reverse flashing</b>
*) Reverse flashing
If you want to test a new firmware, but you don't want to loose all the
contents of your device. The only way to do that (afaik) is from the
@@ -94,7 +87,7 @@ think that there are some things that should be fixed.
case of a wrong checksumming (for example)
<b>*) Documentation</b>
*) Documentation
The nokia flasher comes as is, without documentation. This is not good
to anybody, because the lack of information is always the root of problems,
-2
View File
@@ -1,2 +0,0 @@
Consequences of a weird flashing :)<br />
<img src="img/n770bars.jpg">
+31
View File
@@ -4,3 +4,34 @@ Fiasco firmware pieces
The firmware for the maemo devices is composed by a set of pieces containing
the required parts to update the whole system following a partition layout
defined by NOLO on the internal flash memory.
Nokia provides a blob packed with a proprietary format called 'FIASCO'. This
blob contains the following pieces:
- 2nd - for Cold Flashing
- xloader - first part of nolo
- secondary - second part of nolo (usb support and launches kernel)
- kernel - the kernel
- initfs - initial system that initializes everything and runs rootfs
- rootfs - the whole system image
Some of these pieces are versioned to match board specific features
(mostly xloader and secondary ones).
To flash an initfs partition and reboot:
$ 0xFFFF -m initfs:initfs.jffs2 -f -r
The format of the argument is [[[device:[hw-revision:]]verion:]piece-type:]file-name[%layout-file-name]
Pieces can be automatically identified by using the '-i' flag:
$ 0xFFFF -m initfs.jffs2 -i
You can dump these pieces from the internal memory of the internet
tablet by using the mtd-utils over /dev/mtd* or just running:
770$ 0xFFFF -e /media/mmc1
There is another way for dumping pieces with extra parameters and options,
read doc/dumping for more information.
-54
View File
@@ -1,54 +0,0 @@
<b>Usage guide</b>
0xFFFF is a free software implementation of the flasher for the Nokia Internet
Tablets (n770 and n800).
<pre>
- flash separated pieces of the firmware.
- retrieve information about the device
- reboot de mother board
- extract the current firmware pieces from the device (dump)
- set the USB host/slave mode
- set the R&R mode
- identify firmware pieces
</pre>
This is the help message of the tool:
<pre>
<b>~$ 0xFFFF -h</b>
0xFFFF v0.1 - The Open Free Fiasco Firmware Flasher
-b [arg] boots the kernel with arguments
-e [path] dump the firmware pieces into the path
-p [[p:]file] piece-of-firmware : file-where-this-piece-is
-r [0|1] disable/enable R&D mode
-u [fiasco] unpack target fiasco image
-U [0|1] disable/enable the usb host mode
-h show this help message
-i show device information (let standby mode)
-I [piece] identify a firmware piece
-l list supported usb device ids
-d [vid:pid] injects a usb device into the supported list
-R reboot the omap board
-v be verbose and noisy
-V show 0xFFFF version information
Pieces are: xloader secondary kernel initfs rootfs omap-nand
</pre>
Before anything we can execute failsafe queries like getting device information:
<pre> <b>~$ 0xFFFF -i</b></pre>
This command will put the bootloader in standby mode, so you can now send other
commands without having to reboot the tablet manually. To reboot the mother
board via USB type:
<pre> <b>~$ 0xFFFF -R</b></pre>
You can run 'offline' commands to identify the type of the firmware pieces:
<pre> <b>~$ 0xFFFF -I zImage -I xloader.bin -I initfs.jffs2.orig</b>
kernel: zImage
xloader: xloader.bin
initfs: initfs.jffs2.orig</pre>
If you want to backup your device firmware you can crosscompile the 0xFFFF
utility and type this on the terminal:
<pre> <b>~$ sudo gainroot</b>
~# mkdir /media/mmc1/firmware
~# ./0xFFFF -e /media/mmc1/firmware</pre>
Now is time to flash something :) By default the flasher identifies the type
of the piece automatically, but you can force't prefixing the filename with
the piece-type name. To do this is just as simple as typing:
<pre> <b>~$ 0xFFFF -p zImage</b></pre>
+50 -8
View File
@@ -1,11 +1,53 @@
VERSION=0.1
OBJ=main.o fiasco.o hexdump.o dump.o flash.o
OBJ+=hash.o fpid.o query.o pieces.o utils.o
BIN=0xFFFF
CFLAGS+=-DVERSION=\"${VERSION}\" -Wall -g
include ../config.mk
main: ${OBJ}
${CC} ${LDFLAGS} -o ${BIN} ${OBJ} -lusb
PREFIX ?= /usr/local
INSTALL ?= install
BUILD_DATE ?= $(shell LC_ALL=C date '+%b %e %Y')
CC ?= cc
CROSS_CC ?= $(CROSS_COMPILE)$(CC)
HOST_CC ?= $(HOST_COMPILE)$(CC)
CPPFLAGS += -DVERSION=\"$(VERSION)\" -DBUILD_DATE="\"$(BUILD_DATE)\"" -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64
CFLAGS += -W -Wall -O2 -pedantic -std=c99
LIBS += -lusb -ldl
DEPENDS = Makefile ../config.mk
OBJS = main.o nolo.o printf-utils.o image.o fiasco.o device.o usb-device.o cold-flash.o operations.o local.o mkii.o disk.o cal.o
BIN = 0xFFFF
MANGEN = mangen
all: $(BIN) $(BIN).1
$(BIN): $(OBJS) $(DEPENDS)
$(CROSS_CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) $(OBJS) $(LIBS)
$(MANGEN): $(MANGEN).c $(DEPENDS)
$(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
$(BIN).1: $(BIN) $(MANGEN) $(DEPENDS) ../doc/examples
./$(MANGEN) > $@.tmp
(printf '.SH EXAMPLES\n.\n.PP\n.B\n'; cat ../doc/examples) | sed 's/^$$/.fi\n.\n.PP\n.B/' | sed '/^\.PP$$/N;/\.B/N;/\.fi/N;s/^\.PP\n\.B\n\.fi\n//' | sed '/^\.B/N;s/\n/ /;/^\.B/s/$$/\n.nf/' | sed '/^\.nf/N;/^\.fi/N;s/^\.nf\n.fi/./' >> $@.tmp
mv $@.tmp $@
libusb-sniff-32.so: libusb-sniff.c $(DEPENDS)
$(CC) $(CFLAGS) $(LDFLAGS) -fPIC $< -ldl -shared -m32 -o $@
libusb-sniff-64.so: libusb-sniff.c $(DEPENDS)
$(CC) $(CFLAGS) $(LDFLAGS) -fPIC $< -ldl -shared -m64 -o $@
%.o: %.c $(DEPENDS)
$(CROSS_CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
install: $(BIN) $(BIN).1
$(INSTALL) -D -m 755 $(BIN) $(DESTDIR)$(PREFIX)/bin/$(BIN)
$(INSTALL) -D -m 644 $(BIN).1 $(DESTDIR)$(PREFIX)/share/man/man1/$(BIN).1
uninstall:
$(RM) $(DESTDIR)$(PREFIX)/bin/$(BIN)
$(RM) $(DESTDIR)$(PREFIX)/share/man/man1/$(BIN).1
clean:
-rm -f ${OBJ} ${BIN}
-$(RM) $(OBJS) $(BIN) $(MANGEN) $(BIN).1 $(BIN).1.tmp libusb-sniff-32.so libusb-sniff-64.so
+295
View File
@@ -0,0 +1,295 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (c) 2011 Michael Buesch <mb@bu3sch.de>
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* This is simple CAL parser form Calvaria */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef __linux__
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <mtd/mtd-user.h>
#include <sys/sysmacros.h>
#endif
#include "cal.h"
#define MAX_SIZE 393216
#define INDEX_LAST (0xFF + 1)
#define HDR_MAGIC "ConF"
struct cal {
ssize_t size;
void * mem;
};
struct header {
char magic[4]; /* Magic sequence */
uint8_t type; /* Type number */
uint8_t index; /* Index number */
uint16_t flags; /* Flags */
char name[16]; /* Human readable section name */
uint32_t length; /* Payload length */
uint32_t datasum; /* Data CRC32 checksum */
uint32_t hdrsum; /* Header CRC32 checksum */
} __attribute__((__packed__));
int cal_init_file(const char * file, struct cal ** cal_out) {
int fd = -1;
uint64_t blksize = 0;
ssize_t size = 0;
void * mem = NULL;
struct cal * cal = NULL;
struct stat st;
#ifdef __linux__
mtd_info_t mtd_info;
#else
off_t lsize = 0;
#endif
fd = open(file, O_RDONLY);
if ( fd < 0 )
return -1;
if ( fstat(fd, &st) != 0 )
goto err;
if ( S_ISREG(st.st_mode) )
size = st.st_size;
else if ( S_ISBLK(st.st_mode) ) {
#ifdef __linux__
if ( ioctl(fd, BLKGETSIZE64, &blksize) != 0 )
goto err;
#else
lsize = lseek(fd, 0, SEEK_END);
if ( lsize == (off_t)-1 )
goto err;
if ( lseek(fd, 0, SEEK_SET) == (off_t)-1 )
goto err;
blksize = lsize;
#endif
#ifdef SSIZE_MAX
if ( blksize > SSIZE_MAX )
goto err;
#endif
size = blksize;
} else {
#ifdef __linux__
if ( S_ISCHR(st.st_mode) && major(st.st_rdev) == 90 ) {
if ( ioctl(fd, MEMGETINFO, &mtd_info) != 0 )
goto err;
size = mtd_info.size;
} else {
goto err;
}
#else
goto err;
#endif
}
if ( size == 0 || size > MAX_SIZE )
goto err;
mem = malloc(size);
if ( ! mem )
goto err;
if ( read(fd, mem, size) != size )
goto err;
cal = malloc(sizeof(struct cal));
if ( ! cal )
goto err;
cal->mem = mem;
cal->size = size;
close(fd);
*cal_out = cal;
return 0;
err:
close(fd);
free(mem);
free(cal);
return -1;
}
int cal_init(struct cal ** cal_out) {
return cal_init_file("/dev/mtd1ro", cal_out);
}
void cal_finish(struct cal * cal) {
if ( cal ) {
free(cal->mem);
free(cal);
}
}
static uint32_t crc32(uint32_t crc, const void * _data, size_t size) {
const uint8_t * data = _data;
uint8_t value;
unsigned int bit;
size_t i;
const uint32_t poly = 0xEDB88320;
for ( i = 0; i < size; i++ ) {
value = data[i];
for ( bit = 8; bit; bit-- ) {
if ( (crc & 1) != (value & 1) )
crc = (crc >> 1) ^ poly;
else
crc >>= 1;
value >>= 1;
}
}
return crc;
}
static int is_header(void *data, size_t size) {
struct header * hdr = data;
if ( size < sizeof(struct header) )
return 0;
if ( memcmp(hdr->magic, HDR_MAGIC, sizeof(hdr->magic)) != 0 )
return 0;
return 1;
}
static int64_t find_section(void *start, uint64_t count, int want_index, const char *want_name) {
int64_t offset = 0, found_offset = -1;
uint8_t * data = start;
struct header *hdr;
char sectname[sizeof(hdr->name) + 1] = { 0, };
uint32_t payload_len;
int previous_index = -1;
while ( 1 ) {
/* Find header start */
if ( count < sizeof(struct header) )
break;
if ( ! is_header(data + offset, count) ) {
count--;
offset++;
continue;
}
hdr = (struct header *)(data + offset);
payload_len = hdr->length;
if ( count - sizeof(struct header) < payload_len )
return -1;
memcpy(sectname, hdr->name, sizeof(hdr->name));
if ( want_index == INDEX_LAST ) {
if ( (int)hdr->index <= previous_index )
goto next;
} else {
if ( want_index >= 0 && want_index != hdr->index )
goto next;
}
if ( want_name && strcmp(sectname, want_name) != 0 )
goto next;
/* Found it */
found_offset = offset;
if ( want_index == INDEX_LAST )
previous_index = hdr->index;
else
break;
next:
count -= sizeof(struct header) + payload_len;
offset += sizeof(struct header) + payload_len;
}
return found_offset;
}
int cal_read_block(struct cal * cal, const char * name, void ** ptr, unsigned long * len, unsigned long flags) {
int64_t find_offset;
uint64_t filelen = cal->size;
uint8_t * data = cal->mem;
struct header * hdr;
void * offset;
find_offset = find_section(data, filelen, INDEX_LAST, name);
if ( find_offset < 0 )
return -1;
hdr = (struct header *)(data + find_offset);
if ( flags && hdr->flags != flags )
return -1;
if ( crc32(0, hdr, sizeof(*hdr) - 4) != hdr->hdrsum )
return -1;
offset = data + find_offset + sizeof(struct header);
if ( crc32(0, offset, hdr->length) != hdr->datasum )
return -1;
*ptr = malloc(hdr->length);
if (!*ptr)
return -1;
memcpy(*ptr, offset, hdr->length);
*len = hdr->length;
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (c) 2011 Michael Buesch <mb@bu3sch.de>
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CAL_H
#define CAL_H
#define CAL_MAX_NAME_LEN 16
#define CAL_FLAG_USER 0x0001
#define CAL_FLAG_WRITE_ONCE 0x0002
struct cal;
int cal_init(struct cal ** cal_out);
int cal_init_file(const char * file, struct cal ** cal_out);
void cal_finish(struct cal * cal);
int cal_read_block(struct cal * cal, const char * name, void ** ptr, unsigned long * len, unsigned long flags);
#endif
+419
View File
@@ -0,0 +1,419 @@
/*
cold-flash.c - Cold flashing
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "global.h"
#include "cold-flash.h"
#include "image.h"
#include "usb-device.h"
#include "printf-utils.h"
#define READ_TIMEOUT 500
#define WRITE_TIMEOUT 3000
static uint32_t tab[256];
static void crc32_gentab(void) {
int i, j;
uint32_t crc;
uint32_t poly = 0xEDB88320L;
for ( i = 0; i < 256; i++) {
crc = i;
for ( j = 8; j > 0; j-- ) {
if ( crc & 1 )
crc = (crc >> 1) ^ poly;
else
crc >>= 1;
}
tab[i] = crc;
}
}
static uint32_t crc32(unsigned char * bytes, size_t size, uint32_t crc) {
static int gen = 0;
uint32_t i;
if ( ! gen ) {
crc32_gentab();
gen = 1;
}
for ( i = 0; i < size; ++i )
crc = (crc >> 8) ^ tab[(crc ^ bytes[i]) & 0xff];
return crc;
}
/* Omap Boot Messages */
/* See spruf98v.pdf (page 3444): OMAP35x Technical Reference Manual - 25.4.5 Peripheral Booting */
/* Omap Peripheral boot message */
static const uint32_t omap_peripheral_msg = 0xF0030002;
/* Unused */
#if 0
/* Omap Void (no device) boot message */
static const uint32_t omap_void_msg = 0xF0030006;
/* Omap XIP memory boot message */
static const uint32_t omap_xip_msg = 0xF0030106;
/* Omap Nand boot message */
static const uint32_t omap_nand_msg = 0xF0030206;
/* Omap OneNAND boot message */
static const uint32_t omap_onenand_msg = 0xF0030306;
/* Omap DOC boot message */
static const uint32_t omap_doc_msg = 0xF0030406;
/* Omap MMC/SD2 boot message */
static const uint32_t omap_mmc2_msg = 0xF0030506;
/* Omap MMC/SD1 boot message */
static const uint32_t omap_mmc1_msg = 0xF0030606;
/* Omap XIP memory with wait monitoring boot message */
static const uint32_t omap_xipwait_msg = 0xF0030706;
/* Omap UART boot message */
static const uint32_t omap_uart_msg = 0xF0031006;
/* Omap HS USB boot message */
static const uint32_t omap_hsusb_msg = 0xF0031106;
/* Omap next device boot message */
static const uint32_t omap_next_msg = 0xFFFFFFFF;
#endif
/* Omap memory boot message */
static const uint32_t omap_memory_msg = 0;
/* Nokia X-Loader messages */
/* Structure of X-Loader message */
struct xloader_msg {
uint32_t type; /* 4 bytes - type of message */
uint32_t size; /* 4 bytes - size of file */
uint32_t crc1; /* 4 bytes - crc32 of file */
uint32_t crc2; /* 4 bytes - crc32 of first 12 bytes of message */
} __attribute__((__packed__));
#define XLOADER_MSG_TYPE_PING 0x6301326E
#define XLOADER_MSG_TYPE_SEND 0x6302326E
struct xloader_msg xloader_msg_create(uint32_t type, struct image * image) {
struct xloader_msg msg;
uint32_t need, sent;
int ret;
uint8_t buffer[1024];
msg.type = type;
msg.size = 0;
msg.crc1 = 0;
if ( image ) {
msg.size = image->size;
image_seek(image, 0);
sent = 0;
while ( sent < image->size ) {
need = image->size - sent;
if ( need > sizeof(buffer) )
need = sizeof(buffer);
ret = image_read(image, buffer, need);
if ( ret == 0 )
break;
msg.crc1 = crc32(buffer, ret, msg.crc1);
sent += ret;
}
}
msg.crc2 = crc32((unsigned char *)&msg, 12, 0);
return msg;
}
static int read_asic(usb_dev_handle * udev, uint8_t * asic_buffer, int size, int asic_size) {
int ret;
printf("Waiting for ASIC ID...\n");
ret = usb_bulk_read(udev, USB_READ_EP, (char *)asic_buffer, size, READ_TIMEOUT);
if ( ret != asic_size )
ERROR_RETURN("Invalid size of ASIC ID", -1);
return 0;
}
static int send_2nd(usb_dev_handle * udev, struct image * image) {
uint8_t buffer[1024];
uint32_t need, sent;
int ret;
printf("Sending OMAP peripheral boot message...\n");
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&omap_peripheral_msg, sizeof(omap_peripheral_msg), WRITE_TIMEOUT);
if ( ret != sizeof(omap_peripheral_msg) )
ERROR_RETURN("Sending OMAP peripheral boot message failed", -1);
SLEEP(5000);
printf("Sending 2nd X-Loader image size...\n");
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&image->size, 4, WRITE_TIMEOUT);
if ( ret != 4 )
ERROR_RETURN("Sending 2nd X-Loader image size failed", -1);
SLEEP(5000);
printf("Sending 2nd X-Loader image...\n");
printf_progressbar(0, image->size);
image_seek(image, 0);
sent = 0;
while ( sent < image->size ) {
need = image->size - sent;
if ( need > sizeof(buffer) )
need = sizeof(buffer);
ret = image_read(image, buffer, need);
if ( ret == 0 )
break;
if ( usb_bulk_write(udev, USB_WRITE_EP, (char *)buffer, ret, WRITE_TIMEOUT) != ret )
PRINTF_ERROR_RETURN("Sending 2nd X-Loader image failed", -1);
sent += ret;
printf_progressbar(sent, image->size);
}
SLEEP(50000);
return 0;
}
static int send_secondary(usb_dev_handle * udev, struct image * image) {
struct xloader_msg init_msg;
uint8_t buffer[1024];
uint32_t need, sent;
int ret;
init_msg = xloader_msg_create(XLOADER_MSG_TYPE_SEND, image);
printf("Sending X-Loader init message...\n");
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&init_msg, sizeof(init_msg), WRITE_TIMEOUT);
if ( ret != sizeof(init_msg) )
ERROR_RETURN("Sending X-Loader init message failed", -1);
printf("Waiting for X-Loader response...\n");
SLEEP(5000);
ret = usb_bulk_read(udev, USB_READ_EP, (char *)&buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
if ( ret != 4 )
ERROR_RETURN("No response", -1);
printf("Sending Secondary image...\n");
printf_progressbar(0, image->size);
image_seek(image, 0);
sent = 0;
while ( sent < image->size ) {
need = image->size - sent;
if ( need > sizeof(buffer) )
need = sizeof(buffer);
ret = image_read(image, buffer, need);
if ( ret == 0 )
break;
if ( usb_bulk_write(udev, USB_WRITE_EP, (char *)buffer, ret, WRITE_TIMEOUT) != ret )
PRINTF_ERROR_RETURN("Sending Secondary image failed", -1);
sent += ret;
printf_progressbar(sent, image->size);
}
printf("Waiting for X-Loader response...\n");
SLEEP(5000);
ret = usb_bulk_read(udev, USB_READ_EP, (char *)&buffer, 4, READ_TIMEOUT); /* 4 bytes - dummy value */
if ( ret != 4 )
ERROR_RETURN("No response", -1);
return 0;
}
static int ping_timeout(usb_dev_handle * udev) {
int ret;
int pong = 0;
int try_ping = 10;
while ( try_ping > 0 ) {
struct xloader_msg ping_msg = xloader_msg_create(XLOADER_MSG_TYPE_PING, NULL);
int try_read = 4;
printf("Sending X-Loader ping message\n");
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)&ping_msg, sizeof(ping_msg), WRITE_TIMEOUT);
if ( ret != sizeof(ping_msg) )
ERROR_RETURN("Sending X-Loader ping message failed", -1);
printf("Waiting for X-Loader pong response...\n");
while ( try_read > 0 ) {
uint32_t ping_read;
ret = usb_bulk_read(udev, USB_READ_EP, (char *)&ping_read, sizeof(ping_read), READ_TIMEOUT);
if ( ret == sizeof(ping_read) ) {
printf("Got it\n");
pong = 1;
break;
}
SLEEP(5000);
--try_read;
}
if ( pong )
break;
printf("Response timeout\n");
--try_ping;
}
if ( pong )
return 0;
else
return -1;
}
int init_cold_flash(struct usb_device_info * dev) {
uint8_t asic_buffer[127];
int asic_size = 69;
const char * chip = NULL;
int revision;
int i;
if ( dev->flash_device->protocol != FLASH_COLD )
ERROR_RETURN("Device is not in Cold Flash mode", -1);
if ( read_asic(dev->udev, asic_buffer, sizeof(asic_buffer), asic_size) != 0 )
ERROR_RETURN("Reading ASIC ID failed", -1);
if ( verbose ) {
printf("Got ASIC ID:");
for ( i = 0; i < asic_size; ++i )
printf(" 0x%.2X", (unsigned int)asic_buffer[i]);
printf("\n");
}
/* TODO: Detect device from asic id */
/* ASIC ID specification: http://processors.wiki.ti.com/index.php/OMAP35x_and_AM/DM37x_Initialization#UART.2FUSB_Booting */
/* Number of subblocks */
if ( asic_buffer[0] != 0x05 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* 1. ID Subblock - header */
if ( memcmp(asic_buffer+1, "\x01\x05\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* 1. ID Subblock - OMAP chip version (check for OMAP3430 or 3630) */
if ( memcmp(asic_buffer+4, "\x34\x30\x07", 3) == 0 )
chip = "OMAP3430";
else if ( memcmp(asic_buffer+4, "\x36\x30\x07", 3) == 0 )
chip = "OMAP3630";
else
ERROR_RETURN("Invalid ASIC ID", -1);
/* 1. ID Subblock - OMAP chip revision */
revision = asic_buffer[7];
/* 2. Secure Mode Subblock - header */
if ( memcmp(asic_buffer+8, "\x13\x02\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* 3. 2nd ID Subblock - header */
if ( memcmp(asic_buffer+12, "\x12\x15\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* 4. Root Key Hash Subblock - header */
if ( memcmp(asic_buffer+35, "\x14\x15\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* 5. Checksum subblock - header */
if ( memcmp(asic_buffer+58, "\x15\x09\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
printf("Detected %s chip (revision %d)\n", chip, revision);
return 0;
}
int cold_flash(struct usb_device_info * dev, struct image * x2nd, struct image * secondary) {
if ( x2nd->type != IMAGE_2ND )
ERROR_RETURN("Image type is not 2nd X-Loader", -1);
if ( secondary->type != IMAGE_SECONDARY )
ERROR_RETURN("Image type is not Secondary", -1);
if ( send_2nd(dev->udev, x2nd) != 0 )
ERROR_RETURN("Sending 2nd X-Loader image failed", -1);
if ( ping_timeout(dev->udev) != 0 )
ERROR_RETURN("Sending X-Loader ping message failed", -1);
if ( send_secondary(dev->udev, secondary) != 0 )
ERROR_RETURN("Sending Secondary image failed", -1);
printf("Done\n");
return 0;
}
int leave_cold_flash(struct usb_device_info * dev) {
int ret;
printf("Sending OMAP memory boot message...\n");
ret = usb_bulk_write(dev->udev, USB_WRITE_EP, (char *)&omap_memory_msg, sizeof(omap_memory_msg), WRITE_TIMEOUT);
if ( ret != sizeof(omap_memory_msg) )
ERROR_RETURN("Sending OMAP memory boot message failed", -1);
SLEEP(1000000);
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
/*
cold-flash.h - Cold flashing
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COLD_FLASH_H
#define COLD_FLASH_H
#include "image.h"
#include "usb-device.h"
/* Initialize Cold Flash mde */
int init_cold_flash(struct usb_device_info * dev);
/* Flash 2nd and secondary image in Cold Flash mode. After flashing device will boot secondary image */
int cold_flash(struct usb_device_info * dev, struct image * x2nd, struct image * secondary);
/* Leave Cold Flashing mode and continue booting */
int leave_cold_flash(struct usb_device_info * dev);
#endif
+332
View File
@@ -0,0 +1,332 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "global.h"
#include "device.h"
static const char * devices[] = {
[DEVICE_SU_18] = "SU-18",
[DEVICE_RX_34] = "RX-34",
[DEVICE_RX_44] = "RX-44",
[DEVICE_RX_48] = "RX-48",
[DEVICE_RX_51] = "RX-51",
[DEVICE_RM_680] = "RM-680",
[DEVICE_RM_696] = "RM-696",
};
enum device device_from_string(const char * device) {
size_t i;
if ( ! device || ! device[0] )
return DEVICE_ANY;
for ( i = 0; i < sizeof(devices)/sizeof(devices[0]); ++i )
if ( devices[i] && strcmp(devices[i], device) == 0 )
return i;
return DEVICE_UNKNOWN;
}
const char * device_to_string(enum device device) {
if ( device >= sizeof(devices)/sizeof(devices[0]) )
return NULL;
return devices[device];
}
static const char * long_devices[] = {
[DEVICE_SU_18] = "Nokia 770",
[DEVICE_RX_34] = "Nokia N800",
[DEVICE_RX_44] = "Nokia N810",
[DEVICE_RX_48] = "Nokia N810 Wimax",
[DEVICE_RX_51] = "Nokia N900",
[DEVICE_RM_680] = "Nokia N950",
[DEVICE_RM_696] = "Nokia N9",
};
const char * device_to_long_string(enum device device) {
if ( device >= sizeof(long_devices)/sizeof(long_devices[0]) )
return NULL;
return long_devices[device];
}
int hwrev_is_valid(const int16_t * hwrevs, int16_t hwrev) {
int i;
/* hwrevs not specified, valid for any hwrev */
if ( ! hwrevs )
return 1;
for ( i = 0; hwrevs[i] != -1; ++i )
if ( hwrev == hwrevs[i] )
return 1;
return 0;
}
int16_t * hwrevs_alloc_from_string(const char * str) {
const char * ptr = str;
const char * oldptr = ptr;
int count = 2;
int16_t * ret;
int16_t tmp;
int i;
char buf[5];
if ( ! str )
return NULL;
while ( (ptr = strchr(ptr, ',')) ) {
++count;
++ptr;
}
ret = calloc(count, sizeof(int16_t));
if ( ! ret )
return NULL;
i = 0;
ptr = str;
while ( (ptr = strchr(ptr, ',')) ) {
strncpy(buf, oldptr, ptr-oldptr);
buf[4] = 0;
tmp = atoi(buf);
if ( tmp >= 0 )
ret[i++] = tmp;
++ptr;
oldptr = ptr;
}
tmp = atoi(oldptr);
if ( tmp >= 0 )
ret[i++] = tmp;
ret[i++] = -1;
return ret;
}
char * hwrevs_alloc_to_string(const int16_t * hwrevs) {
char * ret;
char * ptr;
int i;
int len = 0;
for ( i = 0; hwrevs[i] != -1; ++i )
len += 7;
ret = calloc(1, len+1);
if ( ! ret )
return NULL;
ptr = ret;
for ( i = 0; hwrevs[i] != -1; ++i )
ptr += sprintf(ptr, "%d,", hwrevs[i]);
*(ptr-1) = 0;
return ret;
}
#define MAX_HWREVS 29
char ** device_list_alloc_to_bufs(const struct device_list * device_list) {
int count = 0;
int size = 0;
const char * device;
const struct device_list * device_first;
char ** ret;
char * last_ptr;
int i, j, k;
device_first = device_list;
while ( device_first ) {
int local = 0;
if ( ! device_to_string(device_first->device) ) {
device_first = device_first->next;
continue;
}
for ( i = 0; device_first->hwrevs[i] != -1; ++i )
if ( device_first->hwrevs[i] >= 0 && device_first->hwrevs[i] <= 9999 )
++local;
size += (1+16+(MAX_HWREVS+1)*8)*(local/MAX_HWREVS+1);
count += local/MAX_HWREVS;
if ( local%MAX_HWREVS != 0 || local == 0 )
++count;
device_first = device_first->next;
}
ret = calloc(1, (count+1)*sizeof(char *) + size);
if ( ! ret )
return NULL;
j = 0;
last_ptr = (char *)ret + (count+1)*sizeof(char *);
device_first = device_list;
while ( device_first ) {
i = -1;
device = device_to_string(device_first->device);
if ( ! device ) {
device_first = device_first->next;
continue;
}
while ( device_first->hwrevs[i+1] != -1 ) {
uint8_t len = 0;
ret[j] = ++last_ptr;
strncpy(ret[j]+1, device, 16);
last_ptr += 16;
len += 16;
k = 0;
for ( k = 0; k < MAX_HWREVS; ++k ) {
if ( device_first->hwrevs[i+1] == -1 )
break;
++i;
if ( device_first->hwrevs[i] < 0 || device_first->hwrevs[i] > 9999 )
continue;
snprintf(ret[j]+1+16+k*8, 8, "%d", device_first->hwrevs[i]);
last_ptr += 8;
len += 8;
}
((uint8_t*)ret[j])[0] = len;
++j;
}
device_first = device_first->next;
}
ret[j] = NULL;
return ret;
}
struct device_list * device_list_alloc_from_buf(const char * buf, size_t size) {
int i;
int len;
int count;
char str[17];
const char * ptr1;
const char * ptr;
struct device_list * ret;
ret = calloc(1, sizeof(struct device_list));
if ( ! ret )
return NULL;
len = strnlen(buf, size);
if ( len > 16 )
len = 16;
memset(str, 0, sizeof(str));
memcpy(str, buf, len);
ptr1 = buf + len;
ret->device = device_from_string(str);
ptr = ptr1;
count = 1;
while ( ptr < buf + size ) {
while ( ptr < buf + size && *ptr < 32 )
++ptr;
if ( ptr >= buf + size )
break;
len = strnlen(ptr, buf + size - ptr);
if ( len > 8 )
len = 8;
ptr += len + 1;
++count;
}
ret->hwrevs = calloc(count, sizeof(int16_t));
if ( ! ret->hwrevs )
return ret;
ptr = ptr1;
i = 0;
while ( ptr < buf + size ) {
while ( ptr < buf + size && *ptr < 32 )
++ptr;
if ( ptr >= buf + size )
break;
len = strnlen(ptr, buf + size - ptr);
if ( len > 8 )
len = 8;
memset(str, 0, sizeof(str));
memcpy(str, ptr, len);
ptr += len + 1;
ret->hwrevs[i++] = atoi(str);
}
ret->hwrevs[i] = -1;
return ret;
}
+61
View File
@@ -0,0 +1,61 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DEVICE_H
#define DEVICE_H
#include <stdint.h>
enum device {
DEVICE_UNKNOWN = 0,
DEVICE_ANY, /* Unspecified / Any device */
DEVICE_SU_18, /* Nokia 770 */
DEVICE_RX_34, /* Nokia N800 */
DEVICE_RX_44, /* Nokia N810 */
DEVICE_RX_48, /* Nokia N810 WiMax */
DEVICE_RX_51, /* Nokia N900 */
DEVICE_RM_680, /* Nokia N950 */
DEVICE_RM_696, /* Nokia N9 */
DEVICE_COUNT,
};
/*
hwrevs - array of int16_t
- terminated by -1
- valid numbers: 0-9999
*/
struct device_list {
enum device device;
int16_t * hwrevs;
struct device_list * next;
};
enum device device_from_string(const char * device);
const char * device_to_string(enum device device);
const char * device_to_long_string(enum device device);
int hwrev_is_valid(const int16_t * hwrevs, int16_t hwrev);
int16_t * hwrevs_alloc_from_string(const char * str);
char * hwrevs_alloc_to_string(const int16_t * hwrevs);
char ** device_list_alloc_to_bufs(const struct device_list * device_list);
struct device_list * device_list_alloc_from_buf(const char * buf, size_t size);
#endif
+475
View File
@@ -0,0 +1,475 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <fcntl.h>
#include <libgen.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#ifdef __linux__
#include <sys/sysmacros.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <dirent.h>
#include <errno.h>
#endif
#include "disk.h"
#include "global.h"
#include "image.h"
#include "device.h"
#include "usb-device.h"
#include "printf-utils.h"
static char global_buf[1UL << 22]; /* 4MB */
int disk_open_dev(int maj, int min, int partition, int readonly) {
#ifdef __linux__
int fd;
struct stat st;
DIR * dir;
struct dirent * dirent;
int found;
int old_errno;
size_t len;
char blkdev[1024];
dir = opendir("/dev/");
if ( ! dir ) {
ERROR_INFO("Cannot open '/dev/' directory");
return -1;
}
found = 0;
while ( ( dirent = readdir(dir) ) ) {
if ( strncmp(dirent->d_name, ".", sizeof(".")) == 0 || strncmp(dirent->d_name, "..", sizeof("..")) == 0 )
continue;
if ( snprintf(blkdev, sizeof(blkdev), "/dev/%s", dirent->d_name) <= 0 )
continue;
if ( stat(blkdev, &st) != 0 )
continue;
if ( ! S_ISBLK(st.st_mode) )
continue;
if ( makedev(maj, min) != st.st_rdev )
continue;
found = 1;
break;
}
closedir(dir);
if ( ! found ) {
ERROR("Cannot find block device with id %d:%d", maj, min);
return -1;
}
printf("Found block device %s with id %d:%d\n", blkdev, maj, min);
if ( partition == -1 ) {
/* Check if block device does not have partitions */
len = strlen(blkdev);
if ( sizeof(blkdev) <= len+2 ) {
ERROR("Block device name is too long");
return -1;
}
memcpy(blkdev+len, "p1", 3);
if ( stat(blkdev, &st) == 0 ) {
ERROR("Block device has partitions");
return -1;
}
memcpy(blkdev+len, "1", 2);
if ( stat(blkdev, &st) == 0 ) {
ERROR("Block device has partitions");
return -1;
}
blkdev[len] = 0;
fd = open(blkdev, (readonly ? O_RDONLY : O_RDWR) | O_EXCL | O_NONBLOCK);
if ( fd < 0 ) {
ERROR_INFO("Cannot open block device %s", blkdev);
return -1;
} else {
if ( fstat(fd, &st) != 0 || ! S_ISBLK(st.st_mode) || makedev(maj, min) != st.st_rdev ) {
ERROR("Block device %s does not have id %d:%d\n", blkdev, maj, min);
close(fd);
return -1;
}
}
} else if ( partition > 0 ) {
/* Select partition */
len = strlen(blkdev);
if ( sizeof(blkdev) <= len+2 ) {
ERROR("Block device name is too long");
return -1;
}
if ( snprintf(blkdev+len, sizeof(blkdev)-len, "p%d", partition) >= (int)(sizeof(blkdev)-len) ) {
ERROR("Block device name is too long");
return -1;
}
fd = open(blkdev, (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, (readonly ? O_RDONLY : O_RDWR) | O_EXCL);
}
if ( fd < 0 && errno == ENOENT ) {
blkdev[len] = 0;
fd = open(blkdev, O_RDONLY | O_NONBLOCK);
if ( fd < 0 ) {
ERROR_INFO("Cannot open block device %s", blkdev);
} else {
close(fd);
ERROR("Block device %s does not have partitions", blkdev);
}
return -1;
}
if ( fd < 0 )
old_errno = errno;
printf("Found block device %s for partition %d\n", blkdev, partition);
if ( fd < 0 ) {
errno = old_errno;
ERROR_INFO("Cannot open block device %s", blkdev);
} else if ( fstat(fd, &st) != 0 || ! S_ISBLK(st.st_mode) ) {
ERROR("Block device %s is not block device\n", blkdev);
close(fd);
return -1;
}
} else {
ERROR("Invalid partition %d for block device %s", partition, blkdev);
fd = -1;
}
return fd;
#else
ERROR("Not implemented yet");
(void)min;
(void)maj;
(void)partition;
(void)readonly;
return -1;
#endif
}
int disk_dump_dev(int fd, const char * file) {
int fd2;
int ret;
char * path;
uint64_t blksize;
size_t need, sent;
ssize_t size;
struct statvfs buf;
printf("Dump block device to file %s...\n", file);
#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("Block device has zero size");
return -1;
}
path = strdup(file);
if ( ! path ) {
ALLOC_ERROR();
return -1;
}
ret = statvfs(dirname(path), &buf);
free(path);
if ( ret == 0 && buf.f_bsize * buf.f_bfree < blksize ) {
ERROR("Not enough free space (have: %llu, need: %llu)", (unsigned long long int)(buf.f_bsize) * buf.f_bfree, (unsigned long long int)blksize);
return -1;
}
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if ( fd2 < 0 ) {
ERROR_INFO("Cannot create file %s", file);
return -1;
}
sent = 0;
printf_progressbar(0, blksize);
while ( sent < blksize ) {
need = blksize - sent;
if ( need > sizeof(global_buf) )
need = sizeof(global_buf);
size = read(fd, global_buf, need);
if ( size == 0 )
break;
if ( write(fd2, global_buf, size) != size ) {
PRINTF_ERROR("Dumping image failed");
close(fd2);
return -1;
}
sent += size;
printf_progressbar(sent, blksize);
}
close(fd2);
return 0;
}
int disk_flash_dev(int fd, const char * file) {
ERROR("Not implemented yet");
(void)fd;
(void)file;
return -1;
}
int disk_init(struct usb_device_info * dev) {
#ifdef __linux__
int fd;
int maj1;
int maj2;
int min1;
int min2;
int tmp;
maj1 = -1;
maj2 = -1;
min1 = -1;
min2 = -1;
FILE * f;
DIR * dir;
struct dirent * dirent;
char buf[1024];
unsigned int devnum;
unsigned int busnum;
struct usb_device * device;
device = usb_device(dev->udev);
if ( ! device || ! device->bus ) {
ERROR_INFO("Cannot read usb devnum and busnum");
return -1;
}
dir = opendir("/sys/dev/block/");
if ( ! dir ) {
ERROR_INFO("Cannot open '/sys/dev/block/' directory");
return -1;
}
while ( ( dirent = readdir(dir) ) ) {
if ( strncmp(dirent->d_name, ".", sizeof(".")) == 0 || strncmp(dirent->d_name, "..", sizeof("..")) == 0 )
continue;
if ( snprintf(buf, sizeof(buf), "/sys/dev/block/%s/device/../../../../busnum", dirent->d_name) <= 0 )
continue;
f = fopen(buf, "r");
if ( ! f )
continue;
if ( fscanf(f, "%u", &busnum) != 1 ) {
fclose(f);
continue;
}
fclose(f);
if ( snprintf(buf, sizeof(buf), "/sys/dev/block/%s/device/../../../../devnum", dirent->d_name) <= 0 )
continue;
f = fopen(buf, "r");
if ( ! f )
continue;
if ( fscanf(f, "%u", &devnum) != 1 ) {
fclose(f);
continue;
}
fclose(f);
if ( device->devnum != devnum )
continue;
if ( device->bus->location ) {
if ( device->bus->location != busnum )
continue;
} else if ( device->bus->dirname[0] ) {
if ( atoi(device->bus->dirname) != (int)busnum )
continue;
}
if ( sscanf(dirent->d_name, "%d:%d", &maj2, &min2) != 2 ) {
maj2 = -1;
min2 = -1;
continue;
}
if ( maj1 != -1 && min1 != -1 && maj2 != -1 && min2 != -1 )
break;
maj1 = maj2;
min1 = min2;
maj2 = -1;
min2 = -1;
}
closedir(dir);
if ( maj1 == -1 || min1 == -1 ) {
ERROR("Cannot find id for mmc block disk device");
return -1;
}
/* 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;
}
/* TODO: change 1 to 0 when disk_flash_dev will be implemented */
/* RX-51 and RM-680 export MyDocs in first usb device and just first partion, so host system see whole device without MBR table */
if ( dev->device == DEVICE_RX_51 || dev->device == DEVICE_RM_680 )
fd = disk_open_dev(maj1, min1, -1, 1);
/* Other devices can export SD card as first partition and export whole mmc device, so host system will see MBR table */
else if ( maj2 != -1 && min2 != -1 )
fd = disk_open_dev(maj2, min2, 1, 1);
else
fd = disk_open_dev(maj1, min1, 1, 1);
if ( fd < 0 )
return -1;
dev->data = fd;
return 0;
#else
ERROR("Not implemented yet");
(void)dev;
return -1;
#endif
}
void disk_exit(struct usb_device_info * dev) {
if ( dev->data >= 0 )
close(dev->data);
}
enum device disk_get_device(struct usb_device_info * dev) {
return dev->device;
}
int disk_flash_image(struct usb_device_info * dev, struct image * image) {
ERROR("Not implemented yet");
(void)dev;
(void)image;
return -1;
}
int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file) {
if ( image != IMAGE_MMC )
ERROR_RETURN("Only mmc images are supported", -1);
return disk_dump_dev(dev->data, file);
}
int disk_check_badblocks(struct usb_device_info * dev, const char * device) {
ERROR("Not implemented yet");
(void)dev;
(void)device;
return -1;
}
+39
View File
@@ -0,0 +1,39 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DISK_H
#define DISK_H
#include "image.h"
#include "device.h"
#include "usb-device.h"
int disk_init(struct usb_device_info * dev);
void disk_exit(struct usb_device_info * dev);
enum device disk_get_device(struct usb_device_info * dev);
int disk_open_dev(int maj, int min, int partition, int readonly);
int disk_dump_dev(int fd, const char * file);
int disk_flash_dev(int fd, const char * file);
int disk_flash_image(struct usb_device_info * dev, struct image * image);
int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file);
int disk_check_badblocks(struct usb_device_info * dev, const char * device);
#endif
-145
View File
@@ -1,145 +0,0 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "main.h"
#include <usb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int rf_extract(char *dev, off_t from, off_t to, char *file)
{
off_t i, blk = 0xfffff;
char buf[0xfffff];
FILE *fs = fopen(dev, "rb");
FILE *fd = fopen(file, "wb+");
if (from>to) {
printf("Bad range %lld - %lld for %s\n", from, to, file);
goto __rf_extract_exit;
}
if (fs == NULL) { perror(dev); goto __rf_extract_exit; }
if (fd == NULL) { perror(file); goto __rf_extract_exit; }
printf("%s: extracting...", file);
fflush(stdout);
fseek(fs, from, SEEK_SET);
for(i=from;i<to;i+=blk) {
int ret;
if (i+blk>to) blk = to-i;
ret = fread(buf, blk, 1, fs);
if (feof(fs)) break;
fwrite(buf, blk, 1, fd);
}
printf("\r%s: %lld bytes dumped from %s\n",
file, to-from, dev);
__rf_extract_exit:
if (fs) fclose(fs);
if (fd) fclose(fd);
return 1;
}
int rf_strip(char *file)
{
FILE *fd = fopen(file, "rw");
unsigned char buf[4096];
int ret;
off_t eof = 0;
if (!fd) {
fprintf(stderr, "Weird! can't open %s???\n", file);
exit(0);
}
printf("Stripping padding from %s... ", file);
fflush(stdout);
fseek(fd, 0, SEEK_END);
do {
fseek(fd, -4096, SEEK_CUR);
ret = fread(buf, 1, 4096, fd);
fseek(fd, -4096, SEEK_CUR);
for(ret--;ret>0;ret--)
if (buf[ret]!=0xff) {
fseek(fd, ret+1, SEEK_CUR);
eof = ftell(fd);
goto __done;
}
} while(1);
__done:
fclose(fd);
if (eof) truncate(file, eof);
printf("done at %d\n", (int)eof);
return 1;
}
int is_n800()
{
int n800 = 0;
unsigned char buf[4];
FILE *fd = fopen("/dev/mtd0", "rb");
if (!fd) {
fprintf(stderr, "Cannot open /dev/mtd0.\n");
exit(1);
}
fread(buf, 4, 1,fd);
if (!memcmp("\xff\xff\xff\xff", buf, 4))
n800 = 1;
fclose(fd);
return n800;
}
int reverse_extract_pieces(char *dir)
{
char reply;
chdir(dir);
rf_extract("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin");
rf_extract("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin");
rf_extract("/dev/mtd2", 0x000800, 0x200000, "zImage");
rf_extract("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2");
printf("\nWARNING: the rootfs extraction on n800 is known to be buggy! feedback is welcome.\n\n");
printf("Extract rootfs? (Y/n): "); fflush(stdout);
read(0, &reply, 1);
if (reply=='y'||reply=='Y')
rf_extract("/dev/mtd4", 0x000000, 0xffffff, "rootfs.jffs2");
else printf("*** Ignoring rootfs\n");
rf_strip("xloader.bin");
rf_strip("secondary.bin");
rf_strip("zImage");
rf_strip("initfs.jffs2");
printf("Identifying extracted files...\n");
printf("%s: xloader\n", fpid_file("xloader.bin"));
printf("%s: secondary.bin\n", fpid_file("secondary.bin"));
printf("%s: zImage\n", fpid_file("zImage"));
printf("%s: initfs.jffs2\n", fpid_file("initfs.jffs2"));
return 1;
}
+574 -104
View File
@@ -1,136 +1,606 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2007-2011 pancake <pancake@youterm.com>
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#warning The FIASCO format is not yet fully implemented.
#include "global.h"
#include "device.h"
#include "image.h"
#include "fiasco.h"
#define FIASCO_READ_ERROR(fiasco, ...) do { ERROR_INFO(__VA_ARGS__); fiasco_free(fiasco); return NULL; } while (0)
#define FIASCO_WRITE_ERROR(file, fd, ...) do { ERROR_INFO_STR(file, __VA_ARGS__); if ( fd >= 0 ) close(fd); return -1; } while (0)
#define READ_OR_FAIL(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) { FIASCO_READ_ERROR(fiasco, "Cannot read %d bytes", size); } } while (0)
#define READ_OR_RETURN(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; } while (0)
#define WRITE_OR_FAIL_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)
struct fiasco * fiasco_alloc_empty(void) {
struct fiasco * fiasco = calloc(1, sizeof(struct fiasco));
if ( ! fiasco )
ALLOC_ERROR_RETURN(NULL);
fiasco->fd = -1;
return fiasco;
off_t piece_header_to_size(unsigned char *header)
{
off_t sz = 0;
sz += header[0x15+3];
sz += header[0x15+2] << 8;
sz += header[0x15+1] << 16;
sz += header[0x15+0] << 24;
return sz;
}
int piece_header_is_valid(unsigned char *header)
{
if (header[0]=='T' && header[1]=='\x02')
return 1;
struct fiasco * fiasco_alloc_from_file(const char * file) {
uint8_t byte;
uint32_t length;
uint32_t count;
uint8_t length8;
uint8_t count8;
char type[13];
char device[17];
char hwrevs[1024];
char version[257];
char layout[257];
uint16_t hash;
off_t offset;
struct image * image;
char hwrev[9];
unsigned char buf[512];
unsigned char *pbuf;
struct fiasco * fiasco = fiasco_alloc_empty();
if ( ! fiasco )
return NULL;
fiasco->fd = open(file, O_RDONLY);
if ( fiasco->fd < 0 ) {
ERROR_INFO("Cannot open file");
fiasco_free(fiasco);
return NULL;
}
fiasco->orig_filename = strdup(file);
READ_OR_FAIL(fiasco, &byte, 1);
if ( byte != 0xb4 )
FIASCO_READ_ERROR(fiasco, "Invalid fiasco signature");
READ_OR_FAIL(fiasco, &length, 4);
length = ntohl(length);
READ_OR_FAIL(fiasco, &count, 4);
count = ntohl(count);
VERBOSE("Number of header blocks: %d\n", count);
while ( count > 0 ) {
READ_OR_FAIL(fiasco, &byte, 1);
READ_OR_FAIL(fiasco, &length8, 1);
READ_OR_FAIL(fiasco, buf, length8);
if ( byte == 0xe8 ) {
memset(fiasco->name, 0, sizeof(fiasco->name));
strncpy(fiasco->name, (char *)buf, length8);
VERBOSE("Fiasco name: %s\n", fiasco->name);
} else if ( byte == 0x31 ) {
memset(fiasco->swver, 0, sizeof(fiasco->swver));
strncpy(fiasco->swver, (char *)buf, length8);
VERBOSE("SW version: %s\n", fiasco->swver);
} else {
VERBOSE("Unknown header %#x\n", byte);
}
--count;
}
/* walk the tree */
while ( 1 ) {
/* If end of file, return fiasco image */
READ_OR_RETURN(fiasco, buf, 7);
/* Header of next image */
if ( ! ( buf[0] == 0x54 && buf[2] == 0x2E && buf[3] == 0x19 && buf[4] == 0x01 && buf[5] == 0x01 && buf[6] == 0x00 ) ) {
ERROR("Invalid next image header");
return fiasco;
}
count8 = buf[1];
if ( count8 > 0 )
--count8;
READ_OR_RETURN(fiasco, &hash, 2);
hash = ntohs(hash);
memset(type, 0, sizeof(type));
READ_OR_RETURN(fiasco, type, 12);
byte = type[0];
if ( byte == 0xFF )
return fiasco;
VERBOSE(" %s\n", type);
READ_OR_RETURN(fiasco, &length, 4);
length = ntohl(length);
/* unknown */
READ_OR_RETURN(fiasco, buf, 4);
VERBOSE(" size: %d bytes\n", length);
VERBOSE(" hash: %#04x\n", hash);
VERBOSE(" subsections: %d\n", count8);
memset(device, 0, sizeof(device));
memset(hwrevs, 0, sizeof(hwrevs));
memset(version, 0, sizeof(version));
memset(layout, 0, sizeof(layout));
while ( count8 > 0 ) {
READ_OR_RETURN(fiasco, &byte, 1);
READ_OR_RETURN(fiasco, &length8, 1);
READ_OR_RETURN(fiasco, buf, length8);
VERBOSE(" subinfo\n");
VERBOSE(" length: %d\n", length8);
VERBOSE(" type: ");
if ( byte == '1' ) {
memset(version, 0, sizeof(version));
strncpy(version, (char *)buf, length8);
VERBOSE("version string\n");
VERBOSE(" version: %s\n", version);
} else if ( byte == '2' ) {
int tmp = length8;
if ( tmp > 16 ) tmp = 16;
memset(device, 0, sizeof(device));
strncpy(device, (char *)buf, tmp);
VERBOSE("hw revision\n");
VERBOSE(" device: %s\n", device);
pbuf = buf + strlen(device) + 1;
while ( pbuf < buf + length8 ) {
while ( pbuf < buf + length8 && *pbuf < 32 )
++pbuf;
if ( pbuf >= buf + length8 ) break;
tmp = buf + length8 - pbuf;
if ( tmp > 8 ) tmp = 8;
memset(hwrev, 0, sizeof(hwrev));
strncpy(hwrev, (char *)pbuf, tmp);
if ( ! hwrevs[0] )
strcpy(hwrevs, hwrev);
else {
size_t len1 = strlen(hwrevs);
size_t len2 = strlen(hwrev);
if ( len1 + len2 + 2 < sizeof(hwrevs) ) {
hwrevs[len1] = ',';
memcpy(hwrevs+len1+1, hwrev, len2+1);
}
}
VERBOSE(" hw revision: %s\n", hwrev);
pbuf += strlen(hwrev) + 1;
}
} else if ( byte == '3' ) {
memset(layout, 0, sizeof(layout));
strncpy(layout, (char *)buf, length8);
VERBOSE("layout\n");
} else {
VERBOSE("unknown ('%c':%#x)\n", byte, byte);
}
--count8;
}
/* unknown */
READ_OR_RETURN(fiasco, buf, 1);
offset = lseek(fiasco->fd, 0, SEEK_CUR);
if ( offset == (off_t)-1 )
FIASCO_READ_ERROR(fiasco, "Cannot get offset of file");
VERBOSE(" version: %s\n", version);
VERBOSE(" device: %s\n", device);
VERBOSE(" hwrevs: %s\n", hwrevs);
VERBOSE(" data at: %#08x\n", (unsigned int)offset);
image = image_alloc_from_shared_fd(fiasco->fd, length, offset, hash, type, device, hwrevs, version, layout);
if ( ! image )
FIASCO_READ_ERROR(fiasco, "Cannot allocate image");
fiasco_add_image(fiasco, image);
if ( lseek(fiasco->fd, offset+length, SEEK_SET) == (off_t)-1 )
FIASCO_READ_ERROR(fiasco, "Cannot seek to next image in file");
}
}
void fiasco_free(struct fiasco * fiasco) {
struct image_list * list = fiasco->first;
while ( list ) {
struct image_list * next = list->next;
image_list_del(list);
list = next;
}
if ( fiasco->fd >= 0 )
close(fiasco->fd);
free(fiasco->orig_filename);
free(fiasco);
}
void fiasco_add_image(struct fiasco * fiasco, struct image * image) {
image_list_add(&fiasco->first, image);
}
int fiasco_write_to_file(struct fiasco * fiasco, const char * file) {
int fd = -1;
int i;
int device_count;
uint32_t size;
uint32_t length;
uint16_t hash;
uint8_t length8;
char ** device_hwrevs_bufs;
const char * str;
const char * type;
struct image_list * image_list;
struct image * image;
unsigned char buf[4096];
if ( ! fiasco )
return -1;
printf("Generating Fiasco image %s...\n", file);
if ( ! fiasco->first )
FIASCO_WRITE_ERROR(file, fd, "Nothing to write");
if ( strlen(fiasco->name)+1 > UINT8_MAX )
FIASCO_WRITE_ERROR(file, fd, "Fiasco name string is too long");
if ( strlen(fiasco->swver)+1 > UINT8_MAX )
FIASCO_WRITE_ERROR(file, fd, "SW version string is too long");
if ( ! simulate ) {
fd = open(file, O_RDWR|O_CREAT|O_TRUNC, 0644);
if ( fd < 0 ) {
ERROR_INFO("Cannot create file");
return -1;
}
}
printf("Writing Fiasco header...\n");
WRITE_OR_FAIL(file, fd, "\xb4", 1); /* signature */
if ( fiasco->name[0] )
str = fiasco->name;
else
str = "OSSO UART+USB";
length = 4 + strlen(str) + 3;
if ( fiasco->swver[0] )
length += strlen(fiasco->swver) + 3;
length = htonl(length);
WRITE_OR_FAIL(file, fd, &length, 4); /* FW header length */
if ( fiasco->swver[0] )
length = htonl(2);
else
length = htonl(1);
WRITE_OR_FAIL(file, fd, &length, 4); /* FW header blocks count */
/* Fiasco name */
length8 = strlen(str)+1;
WRITE_OR_FAIL(file, fd, "\xe8", 1);
WRITE_OR_FAIL(file, fd, &length8, 1);
WRITE_OR_FAIL(file, fd, str, length8);
/* SW version */
if ( fiasco->swver[0] ) {
printf("Writing SW version: %s\n", fiasco->swver);
length8 = strlen(fiasco->swver)+1;
WRITE_OR_FAIL(file, fd, "\x31", 1);
WRITE_OR_FAIL(file, fd, &length8, 1);
WRITE_OR_FAIL(file, fd, fiasco->swver, length8);
};
printf("\n");
image_list = fiasco->first;
while ( image_list ) {
image = image_list->image;
if ( ! image )
FIASCO_WRITE_ERROR(file, fd, "Empty image");
printf("Writing image...\n");
image_print_info(image);
type = image_type_to_string(image->type);
if ( ! type )
FIASCO_WRITE_ERROR(file, fd, "Unknown image type");
if ( image->version && strlen(image->version) > UINT8_MAX )
FIASCO_WRITE_ERROR(file, fd, "Image version string is too long");
if ( image->layout && strlen(image->layout) > UINT8_MAX )
FIASCO_WRITE_ERROR(file, fd, "Image layout is too long");
device_hwrevs_bufs = device_list_alloc_to_bufs(image->devices);
device_count = 0;
if ( device_hwrevs_bufs && device_hwrevs_bufs[0] )
for ( ; device_hwrevs_bufs[device_count]; ++device_count );
printf("Writing image header...\n");
/* signature */
WRITE_OR_FAIL_FREE(file, fd, "T", 1, device_hwrevs_bufs);
/* number of subsections */
length8 = device_count+1;
if ( image->version )
++length8;
if ( image->layout )
++length8;
WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs);
/* unknown */
WRITE_OR_FAIL_FREE(file, fd, "\x2e\x19\x01\x01\x00", 5, device_hwrevs_bufs);
/* checksum */
hash = htons(image->hash);
WRITE_OR_FAIL_FREE(file, fd, &hash, 2, device_hwrevs_bufs);
/* image type name */
memset(buf, 0, 12);
strncpy((char *)buf, type, 12);
WRITE_OR_FAIL_FREE(file, fd, buf, 12, device_hwrevs_bufs);
/* image size */
size = htonl(image->size);
WRITE_OR_FAIL_FREE(file, fd, &size, 4, device_hwrevs_bufs);
/* unknown */
WRITE_OR_FAIL_FREE(file, fd, "\x00\x00\x00\x00", 4, device_hwrevs_bufs);
/* append version subsection */
if ( image->version ) {
WRITE_OR_FAIL_FREE(file, fd, "1", 1, device_hwrevs_bufs); /* 1 - version */
length8 = strlen(image->version)+1; /* +1 for NULL term */
WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs);
WRITE_OR_FAIL_FREE(file, fd, image->version, length8, device_hwrevs_bufs);
}
/* append device & hwrevs subsection */
for ( i = 0; i < device_count; ++i ) {
WRITE_OR_FAIL_FREE(file, fd, "2", 1, device_hwrevs_bufs); /* 2 - device & hwrevs */
length8 = ((uint8_t *)(device_hwrevs_bufs[i]))[0];
WRITE_OR_FAIL_FREE(file, fd, &length8, 1, device_hwrevs_bufs);
WRITE_OR_FAIL_FREE(file, fd, device_hwrevs_bufs[i]+1, length8, device_hwrevs_bufs);
}
free(device_hwrevs_bufs);
/* append layout subsection */
if ( image->layout ) {
WRITE_OR_FAIL(file, fd, "3", 1); /* 3 - layout */
length8 = strlen(image->layout);
WRITE_OR_FAIL(file, fd, &length8, 1);
WRITE_OR_FAIL(file, fd, image->layout, length8);
}
/* dummy byte - end of all subsections */
WRITE_OR_FAIL(file, fd, "\x00", 1);
printf("Writing image data...\n");
image_seek(image, 0);
while ( 1 ) {
size = image_read(image, buf, sizeof(buf));
if ( size == 0 )
break;
WRITE_OR_FAIL(file, fd, buf, size);
}
image_list = image_list->next;
if ( image_list )
printf("\n");
}
if ( ! simulate )
close(fd);
printf("\nDone\n\n");
return 0;
}
#define piece_header_to_name(x) x+0x9;
int fiasco_unpack(struct fiasco * fiasco, const char * dir) {
/*
* Teh Fiasco firmware parser lives here!
*/
int fiasco_read_image(char *file)
{
int fd;
unsigned char header[5];
unsigned char version[55];
char *version2;
char * name;
char * layout_name;
struct image * image;
struct image_list * image_list;
uint32_t size;
char cwd[256];
unsigned char buf[4096];
fd = open(file, O_RDONLY);
if ( dir ) {
printf("WARNING: Fiasco firmware is not yet fully supported. Don't relay on it ATM.\n");
memset(cwd, 0, sizeof(cwd));
if (fd == -1) {
printf("Cannot open fiasco image.\n");
if ( ! getcwd(cwd, sizeof(cwd)) ) {
ERROR_INFO("Cannot store current directory");
return -1;
}
// b4 00 00 00 00 36
if (read(fd, header, 5) != 5) {
printf("Error reading fiasco header\n");
goto __fiasco_read_image_end;
if ( chdir(dir) < 0 ) {
ERROR_INFO("Cannot change current directory to %s", dir);
return -1;
}
if (header[0] != 0xb4) {
printf("Invalid fiasco signature.\n");
goto __fiasco_read_image_end;
}
// skip 6 bytes
read(fd, version, 6);
// print version header
if (read(fd, version, 55) != 55) {
printf("Error reading fiasco version.\n");
goto __fiasco_read_image_end;
}
printf("# Fiasco header information:\n");
printf("# ==========================\n");
printf("# firmware type: %s\n", version);
version2 = version+strlen((char *)version)+3;
if (*version2=='.')
printf("firmware version: (null) (old firmware? no version string found?)\n");
else printf("firmware version: %s\n", version2);
fiasco_print_info(fiasco);
// pieces:
// after the version2 string starts the header-body loop love
lseek(fd, 0xf + strlen(version2) + strlen(version), SEEK_SET);
do {
char piece_header[30];
char description[256];
unsigned char desc_len;
char *name;
off_t size;
off_t tmp = lseek(fd, 0, SEEK_CUR);
image_list = fiasco->first;
size = read(fd, piece_header, 30);
if (size != 30) {
fprintf(stderr, "Unexpected end of file\n");
while ( image_list ) {
fd = -1;
name = NULL;
layout_name = NULL;
image = image_list->image;
name = image_name_alloc_from_values(image);
if ( ! name )
return -1;
printf("\n");
printf("Unpacking image...\n");
image_print_info(image);
if ( image->layout ) {
layout_name = calloc(1, strlen(name) + sizeof(".layout")-1 + 1);
if ( ! layout_name ) {
free(name);
ALLOC_ERROR_RETURN(-1);
}
sprintf(layout_name, "%s.layout", name);
printf(" Layout file: %s\n", layout_name);
}
printf(" Output file: %s\n", name);
if ( ! simulate ) {
fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644);
if ( fd < 0 ) {
ERROR_INFO("Cannot create output file %s", name);
free(name);
free(layout_name);
return -1;
}
}
image_seek(image, 0);
while ( 1 ) {
size = image_read(image, buf, sizeof(buf));
if ( size == 0 )
break;
}
dump_bytes(piece_header,30);
if (!piece_header_is_valid(piece_header)) {
fprintf(stderr, "Oops. Invalid piece header.\n");
break;
}
size = piece_header_to_size(piece_header);
name = piece_header_to_name(piece_header);
printf("# %s is %lld bytes\n", name, size);
read(fd, description, 255);
printf("# version: %s\n", description);
/* lseek foreach subimage */
lseek(fd, tmp, SEEK_SET);
lseek(fd, strlen(description) + 0x20, SEEK_CUR);
printf("rsc '%s' %lld '%s.bin' 0 %lld\n", file, lseek(fd,0,SEEK_CUR), name, size);
lseek(fd, size, SEEK_CUR);
} while(1);
//printf("Image '%s', size %d bytes.\n", image, size);
__fiasco_read_image_end:
if ( ! simulate ) {
if ( write(fd, buf, size) != (ssize_t)size ) {
ERROR_INFO_STR(name, "Cannot write %d bytes", size);
close(fd);
return 0;
free(name);
free(layout_name);
return -1;
}
}
}
free(name);
if ( ! simulate )
close(fd);
if ( image->layout ) {
if ( ! simulate ) {
fd = open(layout_name, O_RDWR|O_CREAT|O_TRUNC, 0644);
if ( fd < 0 ) {
ERROR_INFO("Cannot create layout file %s", layout_name);
free(layout_name);
return -1;
}
size = strlen(image->layout);
if ( write(fd, image->layout, size) != (ssize_t)size ) {
ERROR_INFO_STR(layout_name, "Cannot write %d bytes", size);
close(fd);
free(layout_name);
return -1;
}
}
free(layout_name);
if ( ! simulate )
close(fd);
}
image_list = image_list->next;
}
if ( dir ) {
if ( chdir(cwd) < 0 ) {
ERROR_INFO("Cannot change current directory back to %s", cwd);
return -1;
}
}
printf("\nDone\n\n");
return 0;
}
void fiasco_print_info(struct fiasco * fiasco) {
if ( fiasco->orig_filename )
printf("File: %s\n", fiasco->orig_filename);
if ( fiasco->name[0] )
printf(" Fiasco Name: %s\n", fiasco->name);
if ( fiasco->swver[0] )
printf(" Fiasco Software release version: %s\n", fiasco->swver);
}
+42
View File
@@ -0,0 +1,42 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2007-2011 pancake <pancake@youterm.com>
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FIASCO_H
#define FIASCO_H
#include "image.h"
struct fiasco {
char name[257];
char swver[257];
int fd;
char * orig_filename;
struct image_list * first;
};
struct fiasco * fiasco_alloc_empty(void);
struct fiasco * fiasco_alloc_from_file(const char * file);
void fiasco_free(struct fiasco * fiasco);
void fiasco_add_image(struct fiasco * fiasco, struct image * image);
int fiasco_write_to_file(struct fiasco * fiasco, const char * file);
int fiasco_unpack(struct fiasco * fiasco, const char * dir);
void fiasco_print_info(struct fiasco * fiasco);
#endif
-167
View File
@@ -1,167 +0,0 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "main.h"
#include "hash.h"
#include <usb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void check_nolo_order_failed()
{
fprintf(stderr, "\nERROR: Provide xloader before the secondary. NOLO disagrees anything else.\n");
fprintf(stderr, "Use: -p xloader.bin -p secondary.bin\n");
exit(1);
}
void check_nolo_order()
{
int i, xlo = 0;
for(i=0;i<pcs_n;i++) {
if (!strcmp(pcs[i].type, "xloader")) {
if (!xlo && ++i<pcs_n) {
printf("CHK%s\n", pcs[i].type);
xlo++;
if (!strcmp(pcs[i].type, "secondary")) {
xlo = 0x11;
break;
} else check_nolo_order_failed();
} check_nolo_order_failed();
} else
if (!strcmp(pcs[i].type, "secondary"))
check_nolo_order_failed();
}
if (xlo && xlo != 0x11)
check_nolo_order_failed();
}
void flash_image(char *filename, char *piece, char *version)
{
FILE *fd;
int vlen = 0;
int request;
/*/ n800 flash queries have a variable size */
unsigned char fquery[256]; /* flash query */
unsigned long long size, off;
unsigned char bsize[4], tmp;
unsigned char nolofiller[128];
ushort hash = do_hash_file(filename);
if (version)
vlen = strlen(version)+1;
fd = fopen(filename, "rb");
if (fd == NULL) {
printf("Cannot open file\n");
exit(1);
}
/* cook flash query */
memset(fquery, '\x00', 27); // reset buffer
memcpy(fquery, "\x2e\x19\x01\x01", 4); // header
//memcpy(fquery+5, "\xbf\x6b", 2); // some magic (modified crc16???)
memcpy(fquery+5, &hash, 2);
tmp = fquery[5]; fquery[5] = fquery[6]; fquery[6] = tmp;
memcpy(fquery+7, piece, strlen(piece)); // XXX ??!??
printf("| hash: 0x%hhx%hhx ", fquery[5], fquery[6]);
size = get_file_size(filename);
bsize[0] = (size & 0xff000000) >> 24;
bsize[1] = (size & 0x00ff0000) >> 16;
bsize[2] = (size & 0x0000ff00) >> 8;
bsize[3] = (size & 0x000000ff);
printf("size: %lld (%02x %02x %02x %02x)\n",
size, bsize[0], bsize[1], bsize[2], bsize[3]);
memcpy(fquery+0x13, &bsize, 4);
if (vlen) memcpy(fquery+27, version, vlen);
if (!strcmp(piece, "rootfs"))
request = 85;
else request = 68;
//dump_bytes(fquery, 27+vlen);
if (usb_control_msg(dev, CMD_WRITE, request, 0, 0, (char *)fquery, 27+vlen, 2000) <0) {
perror("flash_image.header");
exit(1);
}
/*/ cook and bulk nollo filler */
memset(&nolofiller, '\xff', 128);
memcpy(nolofiller+0x00, "NOLO filler", 11);
memcpy(nolofiller+0x40, "NOLO filler", 11);
usb_bulk_write(dev, 2, (char *)nolofiller, 128, 5000);
usb_bulk_write(dev, 2, (char *)nolofiller, 0, 5000);
/*/ bulk write image here */
printf("[=] Bulkwriting the %s piece...\n", piece);
fflush(stdout);
for(off = 0; off<size; off += BSIZE) {
char buf[BSIZE];
int bread, bsize = size-off;
if (bsize>BSIZE) bsize = BSIZE;
bread = fread(buf, bsize, 1, fd);
if (bread != 1)
printf("WARNING: Oops wrong read %d vs %d \n", bread, bsize);
bread = usb_bulk_write(dev, 2, buf, bsize, 5000);
progressbar(off, size);
if (bread<0) perror(" -ee- ");
fflush(stdout);
}
fclose(fd);
/*/ EOF */
usb_bulk_write(dev, 2, (char *)nolofiller, 0, 1000);
progressbar(1, 1);
printf("\n");
// index = 4????
if (!strcmp(piece, "rootfs")) {
if (usb_control_msg(dev, CMD_WRITE, 82, 0, 0, (char *)fquery, 0, 30000)<0) {
fprintf(stderr, "Oops. Invalid checksum?\n");
exit(1);
}
} else {
int t = 0;
if (!strcmp(piece, "secondary"))
t = 1;
else
if (!strcmp(piece, "kernel"))
t = 3;
else
if (!strcmp(piece, "initfs"))
t = 4;
if (!strcmp(piece, "xloader"))
printf("xloader flashed not commiting until secondary arrives...\n");
else
if (usb_control_msg(dev, CMD_WRITE, 80, 0, t, (char *)fquery, 0, 10000)<0) {
fprintf(stderr, "Oops. Invalid checksum?\n");
exit(1);
}
}
// unknown query !! :""
if (usb_control_msg(dev, CMD_WRITE, 67, 0, 0, (char *)fquery, 0, 2000)<0) {
fprintf(stderr, "Oops, the flash was denied or so :/\n");
exit(1);
}
printf("Flash done succesfully.\n");
}
-75
View File
@@ -1,75 +0,0 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
char *fpid_file(char *filename)
{
FILE *fd;
char buf[512];
unsigned char *b = (unsigned char *)&buf;
char *piece = NULL;
long size;
// 2nd : +0x34 = 2NDAPE
// secondary: +0x04 = NOLOScnd
// x-loader : +0x14 = X-LOADER
// xloader8 : +0x0c = NOLOXldr
// kernel : +0x00 = 0000 a0e1 0000 a0e1
// initfs : <2M...be sure with 3M 0x300000
fd = fopen(filename, "r");
if (fd == NULL) {
printf("Cannot open file '%s'\n", filename);
return NULL;
}
fread(buf, 512, 1, fd);
fseek(fd, 0, SEEK_END);
size = ftell(fd);
fclose(fd);
#if 0
if (!memcmp(b+0x34, "2NDAPE", 6))
return PIECE_2ND;
else
#endif
if (!memcmp(b+0x04, "NOLOScnd", 8))
return pieces[PIECE_SECONDARY];
else
if (!memcmp(b+0x14, "X-LOADER", 8))
return pieces[PIECE_XLOADER];
else
if (!memcmp(b+0x0c, "NOLOXldr", 8)) // TODO: this is xloader800, not valid on 770?
return pieces[PIECE_XLOADER];
else
if (!memcmp(b+0x00, "\x00\x00\xa0\xe1\x00\x00\xa0\xe1", 8))
return pieces[PIECE_KERNEL];
else
if (!memcmp(b+0x00, "\x85\x19\x01\xe0", 4)) {
/*/ is jffs2 */
if (size < 0x300000)
return pieces[PIECE_INITFS];
return pieces[PIECE_ROOTFS];
}
return piece;
}
+40
View File
@@ -0,0 +1,40 @@
#ifndef GLOBAL_H
#define GLOBAL_H
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
extern int simulate;
extern int noverify;
extern int verbose;
#define VERBOSE(...) do { if ( verbose ) { fprintf(stderr, __VA_ARGS__); } } while (0)
#define WARNING(...) do { fprintf(stderr, "Warning: "); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n"); } while (0)
#define ERROR_INFO_STR(str, ...) do { if ( str[0] ) fprintf(stderr, "Error: %s: ", str); else fprintf(stderr, "Error: "); fprintf(stderr, __VA_ARGS__); if ( errno ) fprintf(stderr, ": %s\n", strerror(errno)); else fprintf(stderr, "\n"); } while (0)
#define ERROR_STR(str, ...) do { errno = 0; ERROR_INFO_STR(str, __VA_ARGS__); } while (0)
#define ERROR_INFO(...) do { ERROR_INFO_STR("", __VA_ARGS__); } while (0)
#define ERROR(...) do { ERROR_STR("", __VA_ARGS__); } while (0)
#define ERROR_RETURN(str, ...) do { ERROR("%s", str); return __VA_ARGS__; } while (0)
#define ALLOC_ERROR() do { ERROR("Cannot allocate memory"); } while (0)
#define ALLOC_ERROR_RETURN(...) do { ALLOC_ERROR(); return __VA_ARGS__; } while (0)
#define SLEEP(usec) do { struct timespec _t = { 0, (usec) }; nanosleep(&_t, NULL); } while (0)
static inline void * MEMMEM(void *haystack, size_t haystacklen, const void *needle, size_t needlelen) {
for ( size_t i = 0; i < haystacklen; ++i ) {
for ( size_t j = 0; j < needlelen; ++j ) {
if ( ((char *)haystack)[i+j] != ((const char *)needle)[j] )
break;
if ( j != needlelen - 1 )
continue;
return (char *)haystack + i;
}
}
return NULL;
}
#endif
-62
View File
@@ -1,62 +0,0 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdio.h>
#include "hash.h"
usho do_hash(usho *b, int len)
{
usho result = 0;
for(len>>=1;len--;b=b+1)
result^=b[0];
return result;
}
usho do_hash_file(char *filename)
{
unsigned char buf[BSIZE];
FILE *fd = fopen(filename, "r");
usho hash = 0;
int ret;
if (fd == NULL) {
fprintf(stderr, "ERROR: File '%s' not found.\n", filename);
return -1;
}
do { ret = fread(&buf, 1, BSIZE, fd);
if (ret == -1)
return 0;
hash ^= do_hash((usho *)&buf, ret);
} while(ret);
fclose(fd);
return hash;
}
#if 0
main()
{
usho us = do_hash_file("zImage");
unsigned char *h= (unsigned char *)&us;
printf("%x %x\n",h[0],h[1]);
}
#endif
-10
View File
@@ -1,10 +0,0 @@
#ifndef _INCLUDE_HASH_H_
#define _INCLUDE_HASH_H_
#define usho unsigned short
#define BSIZE 0x20000
usho do_hash(usho *b, int len);
usho do_hash_file(char *filename);
#endif
-67
View File
@@ -1,67 +0,0 @@
/*
* Copyright (C) 2006-2007
* pancake <pancake@youterm.com>
*
* radare is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* radare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with radare; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdio.h>
#include <string.h>
#include "hexdump.h"
char getprintablechar(char a)
{
if (a>=' '&&a<='~')
return a;
return '.';
}
int is_printable (int c)
{
if (c<' '||c>'~') return 0;
return 1;
}
/*
* Helper function
*/
void dump_bytes(unsigned char *buf, int len)
{
int i,j,seek = 0;
int inc = 16;
for(i=0; i<len; i+=inc) {
fprintf(stderr, "0x%08x | ", seek+i);
for(j=i;j<i+inc;j++) {
if (j>=len) {
fprintf(stderr, " ");
continue;
}
fprintf(stderr, "%02x ", buf[j]);
}
fprintf(stderr, " ");
for(j=i; j<i+inc; j++) {
if (j >= len)
fprintf(stderr, " ");
else
if ( is_printable(buf[j]) )
fprintf(stderr, "%c", buf[j]);
else fprintf(stderr, ".");
}
fprintf(stderr, "\n");
}
fflush(stderr);
}
-3
View File
@@ -1,3 +0,0 @@
char getprintablechar(char a);
int is_printable (int c);
void dump_bytes(unsigned char *buf, int len);
+651
View File
@@ -0,0 +1,651 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "global.h"
#include "device.h"
#include "image.h"
#define IMAGE_STORE_CUR(image) do { if ( image->is_shared_fd ) { image->cur = lseek(image->fd, 0, SEEK_CUR) - image->offset; if ( image->cur > image->size ) image->cur = image->size; } } while (0)
#define IMAGE_RESTORE_CUR(image) do { if ( image->is_shared_fd ) { if ( image->cur <= image->size ) lseek(image->fd, image->offset + image->cur, SEEK_SET); else lseek(image->fd, image->offset + image->size, SEEK_SET); } } while (0)
/* format: type-device:hwrevs_version */
static void image_missing_values_from_name(struct image * image, const char * name) {
char * str;
char * ptr;
char * ptr2;
char * type = NULL;
char * device = NULL;
char * hwrevs = NULL;
char * version = NULL;
enum device new_device;
str = strdup(name);
if ( ! str )
return;
ptr = strchr(str, '_');
if ( ptr ) {
*ptr = 0;
++ptr;
version = strdup(ptr);
}
ptr = strchr(str, '-');
if ( ptr ) {
*ptr = 0;
++ptr;
type = strdup(str);
ptr2 = strchr(ptr, ':');
if ( ptr2 ) {
*ptr2 = 0;
++ptr2;
hwrevs = strdup(ptr2);
}
device = strdup(ptr);
} else {
type = strdup(str);
}
if ( ! image->type )
image->type = image_type_from_string(type);
free(type);
if ( ! image->devices || ! image->devices->device || image->devices->device == DEVICE_ANY ) {
new_device = device_from_string(device);
if ( new_device ) {
if ( ! image->devices ) image->devices = calloc(1, sizeof(struct device_list));
if ( image->devices )
image->devices->device = new_device;
}
}
free(device);
if ( image->devices && image->devices->device && ! image->devices->hwrevs )
image->devices->hwrevs = hwrevs_alloc_from_string(hwrevs);
if ( ! image->version )
image->version = version;
else
free(version);
free(hwrevs);
free(str);
}
/* format: type-device:hwrevs_version */
char * image_name_alloc_from_values(struct image * image) {
char * name;
char * ptr;
char * hwrevs;
size_t length;
const char * type;
const char * device;
type = image_type_to_string(image->type);
if ( ! type )
type = "unknown";
if ( image->devices )
device = device_to_string(image->devices->device);
else
device = NULL;
if ( image->devices && image->devices->hwrevs )
hwrevs = hwrevs_alloc_to_string(image->devices->hwrevs);
else
hwrevs = NULL;
length = 1 + strlen(type);
if ( device )
length += 1 + strlen(device);
if ( hwrevs )
length += 1 + strlen(hwrevs);
if ( image->version )
length += 1 + strlen(image->version);
name = calloc(1, length);
if ( ! name ) {
free(hwrevs);
ALLOC_ERROR_RETURN(NULL);
}
strcpy(name, type);
ptr = name + strlen(name);
if ( device )
ptr += sprintf(ptr, "-%s", device);
if ( hwrevs )
ptr += sprintf(ptr, ":%s", hwrevs);
if ( image->version )
ptr += sprintf(ptr, "_%s", image->version);
free(hwrevs);
return name;
}
static int image_append(struct image * image, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
enum image_type detected_type;
image->hash = image_hash_from_data(image);
image->devices = calloc(1, sizeof(struct device_list));
if ( ! image->devices ) {
image_free(image);
ALLOC_ERROR_RETURN(-1);
}
image->devices->device = DEVICE_ANY;
if ( device && device[0] ) {
image->devices->device = device_from_string(device);
if ( ! noverify && image->devices->device == DEVICE_UNKNOWN ) {
ERROR("Specified Device %s is unknown", device);
image_free(image);
return -1;
}
}
detected_type = image_type_from_data(image);
image->type = detected_type;
if ( type && type[0] ) {
image->type = image_type_from_string(type);
if ( ! noverify && image->type == IMAGE_UNKNOWN ) {
ERROR("Specified Image type %s is unknown", type);
image_free(image);
return -1;
}
if ( ! noverify && detected_type != image->type && detected_type != IMAGE_UNKNOWN ) {
ERROR("Image type mishmash (detected %s, got %s)", image_type_to_string(detected_type), type);
image_free(image);
return -1;
}
}
if ( hwrevs && hwrevs[0] )
image->devices->hwrevs = hwrevs_alloc_from_string(hwrevs);
else
image->devices->hwrevs = NULL;
if ( version && version[0] )
image->version = strdup(version);
else
image->version = NULL;
if ( layout && layout[0] )
image->layout = strdup(layout);
else
image->layout = NULL;
return 0;
}
static void image_align(struct image * image) {
size_t align;
if ( image->type == IMAGE_MMC )
align = 8;
else
align = 7;
if ( ( image->size & ( ( 1ULL << align ) - 1 ) ) == 0 )
return;
align = ((image->size >> align) + 1) << align;
image->align = align - image->size;
image->size = align;
image->hash = image_hash_from_data(image);
}
static struct image * image_alloc(void) {
struct image * image = calloc(1, sizeof(struct image));
if ( ! image )
ALLOC_ERROR_RETURN(NULL);
return image;
}
struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
int fd;
fd = open(file, O_RDONLY);
if ( fd < 0 ) {
ERROR_INFO("Cannot open image file %s", file);
return NULL;
}
return image_alloc_from_fd(fd, file, type, device, hwrevs, version, 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) {
off_t offset;
struct image * image = image_alloc();
if ( ! image ) {
close(fd);
return NULL;
}
image->is_shared_fd = 0;
image->fd = fd;
offset = lseek(image->fd, 0, SEEK_END);
if ( offset == (off_t)-1 ) {
ERROR_INFO("Cannot seek to end of file %s", orig_filename);
close(image->fd);
free(image);
return NULL;
}
image->size = offset;
image->offset = 0;
image->cur = 0;
image->orig_filename = strdup(orig_filename);
if ( lseek(image->fd, 0, SEEK_SET) == (off_t)-1 ) {
ERROR_INFO("Cannot seek to begin of file %s", orig_filename);
close(image->fd);
free(image->orig_filename);
free(image);
return NULL;
}
if ( image_append(image, type, device, hwrevs, version, layout) < 0 )
return NULL;
if ( ( ! type || ! type[0] ) && ( ! device || ! device[0] ) && ( ! hwrevs || ! hwrevs[0] ) && ( ! version || ! version[0] ) )
image_missing_values_from_name(image, orig_filename);
image_align(image);
return image;
}
struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout) {
struct image * image = image_alloc();
if ( ! image )
return NULL;
image->is_shared_fd = 1;
image->fd = fd;
image->size = size;
image->offset = offset;
image->cur = 0;
if ( image_append(image, type, device, hwrevs, version, layout) < 0 )
return NULL;
if ( ! noverify && image->hash != hash ) {
ERROR("Image hash mishmash (counted %#04x, got %#04x)", image->hash, hash);
image_free(image);
return NULL;
}
image_align(image);
return image;
}
void image_free(struct image * image) {
if ( ! image )
return;
if ( ! image->is_shared_fd ) {
close(image->fd);
image->fd = -1;
}
while ( image->devices ) {
struct device_list * next = image->devices->next;
free(image->devices->hwrevs);
free(image->devices);
image->devices = next;
}
free(image->version);
free(image->layout);
free(image->orig_filename);
free(image);
}
void image_seek(struct image * image, size_t whence) {
off_t offset;
if ( whence > image->size )
return;
if ( whence >= image->size - image->align ) {
offset = lseek(image->fd, image->size - image->align - 1, SEEK_SET);
image->acur = whence - ( image->size - image->align );
} else {
offset = lseek(image->fd, image->offset + whence, SEEK_SET);
image->acur = 0;
}
if ( offset == (off_t)-1 )
ERROR_INFO("Seek in file %s failed", (image->orig_filename ? image->orig_filename : "(unknown)"));
IMAGE_STORE_CUR(image);
}
size_t image_read(struct image * image, void * buf, size_t count) {
size_t cur;
ssize_t ret;
off_t offset;
size_t new_count = 0;
size_t ret_count = 0;
IMAGE_RESTORE_CUR(image);
if ( ! image->is_shared_fd || image->cur < image->size - image->align ) {
if ( image->is_shared_fd && image->cur + count > image->size - image->align )
new_count = image->size - image->align - image->cur;
else
new_count = count;
ret = read(image->fd, buf, new_count);
if ( ret > 0 )
ret_count += ret;
IMAGE_STORE_CUR(image);
if ( ret < 0 )
return 0;
}
if ( ret_count == count )
return ret_count;
offset = lseek(image->fd, 0, SEEK_CUR);
if ( offset == (off_t)-1 ) {
ERROR_INFO("Cannot get offset of file %s", (image->orig_filename ? image->orig_filename : "(unknown)"));
return 0;
}
cur = offset - image->offset;
if ( image->align && cur == image->size - image->align && image->acur < image->align ) {
if ( image->acur + count - ret_count > image->align )
new_count = image->align - image->acur;
else
new_count = count - ret_count;
memset((unsigned char *)buf+ret_count, 0xFF, new_count);
ret_count += new_count;
image->acur += new_count;
}
return ret_count;
}
void image_list_add(struct image_list ** list, struct image * image) {
struct image_list * last = calloc(1, sizeof(struct image_list));
if ( ! last )
ALLOC_ERROR_RETURN();
last->image = image;
if ( ! *list ) {
*list = last;
return;
}
while ( (*list)->next )
list = &((*list)->next);
last->prev = *list;
(*list)->next = last;
}
void image_list_del(struct image_list * list) {
if ( ! list )
return;
image_list_unlink(list);
image_free(list->image);
free(list);
}
void image_list_unlink(struct image_list * list) {
if ( ! list )
return;
if ( list->prev )
list->prev->next = list->next;
if ( list->next )
list->next->prev = list->prev;
list->prev = NULL;
list->next = NULL;
}
static uint16_t do_hash(uint16_t * b, size_t len) {
uint16_t result = 0;
for ( len >>= 1; len--; b = b+1 )
result^=b[0];
return result;
}
uint16_t image_hash_from_data(struct image * image) {
unsigned char buf[0x20000];
uint16_t hash = 0;
size_t ret;
image_seek(image, 0);
while ( ( ret = image_read(image, buf, sizeof(buf)) ) )
hash ^= do_hash((uint16_t *)buf, ret);
return hash;
}
static const char * image_types[] = {
[IMAGE_XLOADER] = "xloader",
[IMAGE_2ND] = "2nd",
[IMAGE_SECONDARY] = "secondary",
[IMAGE_KERNEL] = "kernel",
[IMAGE_INITFS] = "initfs",
[IMAGE_ROOTFS] = "rootfs",
[IMAGE_MMC] = "mmc",
[IMAGE_CMT_2ND] = "cmt-2nd",
[IMAGE_CMT_ALGO] = "cmt-algo",
[IMAGE_CMT_MCUSW] = "cmt-mcusw",
};
enum image_type image_type_from_data(struct image * image) {
unsigned char buf[512];
size_t size;
memset(buf, 0, sizeof(buf));
image_seek(image, 0);
size = image_read(image, buf, sizeof(buf));
if ( size >= 58 && memcmp(buf+52, "2NDAPE", 6) == 0 )
return IMAGE_2ND;
else if ( size >= 23 && memcmp(buf+20, "2ND", 3) == 0 )
return IMAGE_2ND;
else if ( size >= 8 && memcmp(buf+4, "NOLOScnd", 8) == 0 )
return IMAGE_SECONDARY;
else if ( size >= 28 && memcmp(buf+20, "X-LOADER", 8) == 0 )
return IMAGE_XLOADER;
else if ( size >= 20 && memcmp(buf+12, "NOLOXldr", 8) == 0 )
return IMAGE_XLOADER;
else if ( size >= 12 && memcmp(buf+4, "NOLOXldr", 8) == 0 )
return IMAGE_2ND;
else if ( size >= 40 && memcmp(buf+36, "\x18\x28\x6f\x01", 4) == 0 ) /* ARM Linux kernel magic number */
return IMAGE_KERNEL;
else if ( size >= 4 && memcmp(buf+1, "\x00\x00\xea", 3) == 0 ) /* ARM U-Boot - instruction branch */
return IMAGE_KERNEL;
else if ( size >= 4 && memcmp(buf, "UBI#", 4) == 0 ) /* UBI EC header */
return IMAGE_ROOTFS;
else if ( size >= 512 && memcmp(buf+510, "\x55\xaa", 2) == 0 ) /* FAT boot sector signature */
return IMAGE_MMC;
else if ( size >= 8 && memcmp(buf, "\xb0\x00\x01\x03\x9d\x00\x00\x00", 8) == 0 )
return IMAGE_CMT_2ND;
else if ( size >= 8 && memcmp(buf, "\xb1\x00\x00\x00\x82\x00\x00\x00", 8) == 0 )
return IMAGE_CMT_ALGO;
else if ( size >= 8 && memcmp(buf, "\xb2\x00\x00\x01\x44\x00\x00\x00", 8) == 0 )
return IMAGE_CMT_MCUSW;
else if ( size >= 4 && memcmp(buf, "\x45\x3d\xcd\x28", 4) == 0 ) /* CRAMFS MAGIC */
return IMAGE_INITFS;
else if ( size >= 2 && memcmp(buf, "\x85\x19", 2) == 0 ) { /* JFFS2 MAGIC */
if ( image->size < 0x1000000 )
return IMAGE_INITFS;
else
return IMAGE_ROOTFS;
}
return IMAGE_UNKNOWN;
}
enum image_type image_type_from_string(const char * type) {
size_t i;
if ( ! type )
return IMAGE_UNKNOWN;
for ( i = 0; i < sizeof(image_types)/sizeof(image_types[0]); ++i )
if ( image_types[i] && strcmp(image_types[i], type) == 0 )
return i;
return IMAGE_UNKNOWN;
}
const char * image_type_to_string(enum image_type type) {
if ( type >= sizeof(image_types)/sizeof(image_types[0]) )
return NULL;
return image_types[type];
}
int image_hwrev_is_valid(struct image * image, int16_t hwrev) {
struct device_list * device_ptr = image->devices;
while ( device_ptr ) {
if ( hwrev_is_valid(device_ptr->hwrevs, hwrev) )
return 1;
device_ptr = device_ptr->next;
}
return 0;
}
void image_print_info(struct image * image) {
const char * str;
struct device_list * device = image->devices;
if ( image->orig_filename )
printf("File: %s\n", image->orig_filename);
str = image_type_to_string(image->type);
printf(" Image type: %s\n", str ? str : "unknown");
printf(" Image size: %d bytes\n", image->size);
if ( image->version )
printf(" Image version: %s\n", image->version);
if ( image->layout )
printf(" Image layout: included\n");
while ( device ) {
char * str2 = NULL;
struct device_list * next = device->next;
if ( device->device == DEVICE_UNKNOWN )
str = "unknown";
else
str = device_to_string(device->device);
if ( str )
printf(" Valid for: device %s", str);
if ( str && device->hwrevs )
str2 = hwrevs_alloc_to_string(device->hwrevs);
if ( str2 ) {
printf(", HW revisions: %s\n", str2);
free(str2);
} else if ( str ) {
printf("\n");
}
device = next;
}
}
+84
View File
@@ -0,0 +1,84 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IMAGE_H
#define IMAGE_H
#include <stdint.h>
#include <sys/types.h>
#include "device.h"
enum image_type {
IMAGE_UNKNOWN = 0,
IMAGE_XLOADER,
IMAGE_2ND,
IMAGE_SECONDARY,
IMAGE_KERNEL,
IMAGE_INITFS,
IMAGE_ROOTFS,
IMAGE_MMC,
IMAGE_CMT_2ND,
IMAGE_CMT_ALGO,
IMAGE_CMT_MCUSW,
IMAGE_COUNT,
};
struct image {
enum image_type type;
struct device_list * devices;
char * version;
char * layout;
uint16_t hash;
uint32_t size;
int fd;
int is_shared_fd;
uint32_t align;
size_t offset;
size_t cur;
size_t acur;
char * orig_filename;
};
struct image_list {
struct image * image;
struct image_list * prev;
struct image_list * next;
};
struct image * image_alloc_from_file(const char * file, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout);
struct image * image_alloc_from_fd(int fd, const char * orig_filename, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout);
struct image * image_alloc_from_shared_fd(int fd, size_t size, size_t offset, uint16_t hash, const char * type, const char * device, const char * hwrevs, const char * version, const char * layout);
void image_free(struct image * image);
void image_seek(struct image * image, size_t whence);
size_t image_read(struct image * image, void * buf, size_t count);
void image_print_info(struct image * image);
void image_list_add(struct image_list ** list, struct image * image);
void image_list_del(struct image_list * list);
void image_list_unlink(struct image_list * list);
uint16_t image_hash_from_data(struct image * image);
enum image_type image_type_from_data(struct image * image);
char * image_name_alloc_from_values(struct image * image);
enum image_type image_type_from_string(const char * type);
const char * image_type_to_string(enum image_type type);
int image_hwrev_is_valid(struct image * image, int16_t hwrev);
#endif
+331
View File
@@ -0,0 +1,331 @@
/*
libusb-sniff.c - Library for usb sniffing nokia's flasher-3.5
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* compile: gcc libusb-sniff.c -o libusb-sniff.so -W -Wall -O2 -fPIC -ldl -shared -m32 */
/* usage: sudo USBSNIFF_WAIT=1 LD_PRELOAD=./libusb-sniff.so flasher-3.5 ... */
/* usage: sudo USBSNIFF_SKIP_READ=1 USBSNIFF_SKIP_WRITE=1 LD_PRELOAD=./libusb-sniff.so flasher-3.5 ... */
/* Enable RTLD_NEXT for glibc */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <dlfcn.h>
struct usb_dev_handle;
struct libusb_device_handle;
typedef struct usb_dev_handle usb_dev_handle;
typedef struct libusb_device_handle libusb_device_handle;
static char to_ascii(char c) {
if ( c >= 32 && c <= 126 )
return c;
return '.';
}
static void dump_bytes(const char * buf, size_t size) {
size_t i, ascii_cnt = 0;
char ascii[17] = { 0, };
for ( i = 0; i < size; i++ ) {
if ( i % 16 == 0 ) {
if ( i != 0 ) {
printf(" |%s|\n", ascii);
ascii[0] = 0;
ascii_cnt = 0;
}
printf("%04X:", (unsigned int)i);
}
printf(" %02X", buf[i] & 0xFF);
ascii[ascii_cnt] = to_ascii(buf[i]);
ascii[ascii_cnt + 1] = 0;
ascii_cnt++;
}
if ( ascii[0] ) {
if ( size % 16 )
for ( i = 0; i < 16 - (size % 16); i++ )
printf(" ");
printf(" |%s|\n", ascii);
}
}
int usb_bulk_write(usb_dev_handle * dev, int ep, const char * bytes, int size, int timeout) {
static int (*real_usb_bulk_write)(usb_dev_handle * dev, int ep, const char * bytes, int size, int timeout) = NULL;
if ( ! real_usb_bulk_write )
*(void **)(&real_usb_bulk_write) = dlsym(RTLD_NEXT, "usb_bulk_write");
if ( ! getenv("USBSNIFF_SKIP_WRITE") ) {
printf("\n==== usb_bulk_write (ep=%d size=%d timeout=%d) ====\n", ep, size, timeout);
dump_bytes(bytes, size);
printf("====\n");
if ( getenv("USBSNIFF_WAIT") ) {
printf("Press ENTER"); fflush(stdout); getchar();
}
}
return real_usb_bulk_write(dev, ep, bytes, size, timeout);
}
int usb_bulk_read(usb_dev_handle * dev, int ep, char * bytes, int size, int timeout) {
static int (*real_usb_bulk_read)(usb_dev_handle * dev, int ep, char * bytes, int size, int timeout) = NULL;
int ret;
if ( ! real_usb_bulk_read )
*(void **)(&real_usb_bulk_read) = dlsym(RTLD_NEXT, "usb_bulk_read");
ret = real_usb_bulk_read(dev, ep, bytes, size, timeout);
if ( ! getenv("USBSNIFF_SKIP_READ") ) {
printf("\n==== usb_bulk_read (ep=%d size=%d timeout=%d) ret = %d ====\n", ep, size, timeout, ret);
if ( ret > 0 ) {
dump_bytes(bytes, ret);
printf("====\n");
}
if ( getenv("USBSNIFF_WAIT") ) {
printf("Press ENTER"); fflush(stdout); getchar();
}
}
return ret;
}
int libusb_bulk_transfer(libusb_device_handle *dev, unsigned char ep, unsigned char *bytes, int size, int *actual_length, unsigned int timeout) {
static int (*real_libusb_bulk_transfer)(libusb_device_handle *dev, unsigned char ep, unsigned char *bytes, int size, int *actual_length, unsigned int timeout) = NULL;
int ret;
if ( ! real_libusb_bulk_transfer )
*(void **)(&real_libusb_bulk_transfer) = dlsym(RTLD_NEXT, "libusb_bulk_transfer");
if ( ep == 0x81 ) {
ret = real_libusb_bulk_transfer(dev, ep, bytes, size, actual_length, timeout);
if ( ! getenv("USBSNIFF_SKIP_READ") ) {
printf("\n==== usb_bulk_read (ep=%d size=%d timeout=%d) ret = %d ====\n", ep, size, timeout, (ret < 0) ? ret : *actual_length);
if ( ret == 0 ) {
dump_bytes((char*) bytes, *actual_length);
printf("====\n");
}
if ( getenv("USBSNIFF_WAIT") ) {
printf("Press ENTER"); fflush(stdout); getchar();
}
}
return ret;
} else {
if ( ! getenv("USBSNIFF_SKIP_WRITE") ) {
printf("\n==== usb_bulk_write (ep=%d size=%d timeout=%d) ====\n", ep, size, timeout);
dump_bytes((char*) bytes, size);
printf("====\n");
if ( getenv("USBSNIFF_WAIT") ) {
printf("Press ENTER"); fflush(stdout); getchar();
}
}
return real_libusb_bulk_transfer(dev, ep, bytes, size, actual_length, timeout);
}
}
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout) {
static int (*real_usb_control_msg)(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout) = NULL;
int ret;
if ( ! real_usb_control_msg )
*(void **)(&real_usb_control_msg) = dlsym(RTLD_NEXT, "usb_control_msg");
if ( requesttype == 64 && ! getenv("USBSNIFF_SKIP_CONTROL") ) {
printf("\n==== usb_control_msg(requesttype=%d, request=%d, value=%d, index=%d, size=%d, timeout=%d) ====\n", requesttype, request, value, index, size, timeout);
dump_bytes(bytes, size);
printf("====\n");
if ( getenv("USBSNIFF_WAIT") ) {
printf("Press ENTER"); fflush(stdout); getchar();
}
}
ret = real_usb_control_msg(dev, requesttype, request, value, index, bytes, size, timeout);
if ( requesttype != 64 && ! getenv("USBSNIFF_SKIP_CONTROL") ) {
printf("\n==== usb_control_msg(requesttype=%d, request=%d, value=%d, index=%d, size=%d, timeout=%d) ret = %d ====\n", requesttype, request, value, index, size, timeout, ret);
if ( ret > 0 ) {
dump_bytes(bytes, ret);
printf("====\n");
}
if ( getenv("USBSNIFF_WAIT") ) {
printf("Press ENTER"); fflush(stdout); getchar();
}
}
return ret;
}
int libusb_control_transfer(libusb_device_handle *dev, uint8_t requesttype, uint8_t request, uint16_t value, uint16_t index, unsigned char *bytes, uint16_t size, unsigned int timeout) {
static int (*real_libusb_control_transfer)(libusb_device_handle *dev, uint8_t requesttype, uint8_t request, uint16_t value, uint16_t index, unsigned char *bytes, uint16_t size, unsigned int timeout) = NULL;
int ret;
if ( ! real_libusb_control_transfer )
*(void **)(&real_libusb_control_transfer) = dlsym(RTLD_NEXT, "libusb_control_transfer");
if ( requesttype == 64 && ! getenv("USBSNIFF_SKIP_CONTROL") ) {
printf("\n==== usb_control_msg(requesttype=%d, request=%d, value=%d, index=%d, size=%d, timeout=%d) ====\n", (int)requesttype, (int)request, (int)value, (int)index, (int)size, (int)timeout);
dump_bytes((char*) bytes, size);
printf("====\n");
if ( getenv("USBSNIFF_WAIT") ) {
printf("Press ENTER"); fflush(stdout); getchar();
}
}
ret = real_libusb_control_transfer(dev, requesttype, request, value, index, bytes, size, timeout);
if ( requesttype != 64 && ! getenv("USBSNIFF_SKIP_CONTROL") ) {
printf("\n==== usb_control_msg(requesttype=%d, request=%d, value=%d, index=%d, size=%d, timeout=%d) ret = %d ====\n", (int)requesttype, (int)request, (int)value, (int)index, (int)size, (int)timeout, ret);
if ( ret > 0 ) {
dump_bytes((char*) bytes, ret);
printf("====\n");
}
if ( getenv("USBSNIFF_WAIT") ) {
printf("Press ENTER"); fflush(stdout); getchar();
}
}
return ret;
}
int usb_set_configuration(usb_dev_handle *dev, int configuration) {
static int (*real_usb_set_configuration)(usb_dev_handle *dev, int configuration) = NULL;
if ( ! real_usb_set_configuration )
*(void **)(&real_usb_set_configuration) = dlsym(RTLD_NEXT, "usb_set_configuration");
printf("\n==== usb_set_configuration (configuration=%d) ====\n", configuration);
return real_usb_set_configuration(dev, configuration);
}
int libusb_set_configuration(libusb_device_handle *dev, int configuration) {
static int (*real_usb_set_configuration)(libusb_device_handle *dev, int configuration) = NULL;
if ( ! real_usb_set_configuration )
*(void **)(&real_usb_set_configuration) = dlsym(RTLD_NEXT, "libusb_set_configuration");
printf("\n==== usb_set_configuration (configuration=%d) ====\n", configuration);
return real_usb_set_configuration(dev, configuration);
}
int usb_claim_interface(usb_dev_handle *dev, int interface) {
static int (*real_usb_claim_interface)(usb_dev_handle *dev, int interface) = NULL;
if ( ! real_usb_claim_interface )
*(void **)(&real_usb_claim_interface) = dlsym(RTLD_NEXT, "usb_claim_interface");
printf("\n==== usb_claim_interface (interface=%d) ====\n", interface);
return real_usb_claim_interface(dev, interface);
}
int libusb_claim_interface(libusb_device_handle *dev, int interface) {
static int (*real_usb_claim_interface)(libusb_device_handle *dev, int interface) = NULL;
if ( ! real_usb_claim_interface )
*(void **)(&real_usb_claim_interface) = dlsym(RTLD_NEXT, "libusb_claim_interface");
printf("\n==== usb_claim_interface (interface=%d) ====\n", interface);
return real_usb_claim_interface(dev, interface);
}
int usb_set_altinterface(usb_dev_handle *dev, int alternate) {
static int (*real_usb_set_altinterface)(usb_dev_handle *dev, int alternate) = NULL;
if ( ! real_usb_set_altinterface )
*(void **)(&real_usb_set_altinterface) = dlsym(RTLD_NEXT, "usb_set_altinterface");
printf("\n==== usb_set_altinterface (alternate=%d) ====\n", alternate);
return real_usb_set_altinterface(dev, alternate);
}
int libusb_set_interface_alt_setting(libusb_device_handle *dev, int interface, int alternate) {
static int (*real_usb_set_altinterface)(libusb_device_handle *dev, int interface, int alternate) = NULL;
if ( ! real_usb_set_altinterface )
*(void **)(&real_usb_set_altinterface) = dlsym(RTLD_NEXT, "libusb_set_interface_alt_setting");
printf("\n==== usb_set_altinterface (alternate=%d) ====\n", alternate);
return real_usb_set_altinterface(dev, interface, alternate);
}
+674
View File
@@ -0,0 +1,674 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <libgen.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include "local.h"
#include "global.h"
#include "device.h"
#include "image.h"
#include "cal.h"
#include "disk.h"
static int failed;
static enum device device = DEVICE_UNKNOWN;
static int16_t hwrev = -1;
static char kernel_ver[256];
static char initfs_ver[256];
static char nolo_ver[256];
static char sw_ver[256];
static char content_ver[256];
static char rd_mode[256];
static int usb_host_mode = -1;
static int root_device = -1;
#define min(a, b) (a < b ? a : b)
#define local_cal_copy(dest, from, len) strncpy(dest, from, min(len, sizeof(dest)-1))
#define local_cal_read(cal, str, ptr, len) ( cal_read_block(cal, str, &ptr, &len, 0) == 0 && ptr )
#define local_cal_readcopy(cal, str, dest) do { void * ptr; unsigned long int len; if ( local_cal_read(cal, str, ptr, len) ) { local_cal_copy(dest, ptr, len); free(ptr); } } while ( 0 )
#if defined(__linux__) && defined(__arm__)
static void local_cal_parse(void) {
struct cal * cal = NULL;
char buf[128];
printf("Reading CAL...\n");
if ( cal_init(&cal) < 0 || ! cal )
return;
local_cal_readcopy(cal, "kernel-ver", kernel_ver);
local_cal_readcopy(cal, "initfs-ver", kernel_ver);
local_cal_readcopy(cal, "nolo-ver", nolo_ver);
local_cal_readcopy(cal, "sw-release-ver", sw_ver);
local_cal_readcopy(cal, "content-ver", content_ver);
local_cal_readcopy(cal, "r&d_mode", rd_mode);
/* overwritten hw revision */
memset(buf, 0, sizeof(buf));
local_cal_readcopy(cal, "hw-ver", buf);
if ( buf[0] && sscanf(buf, "%hd", &hwrev) != 1 )
hwrev = -1;
if ( hwrev == -1 ) {
/* original hw revision */
memset(buf, 0, sizeof(buf));
local_cal_readcopy(cal, "phone-info", buf);
buf[4] = 0;
if ( buf[0] && sscanf(buf, "%hd", &hwrev) != 1 )
hwrev = -1;
}
buf[0] = 0;
local_cal_readcopy(cal, "usb_host_mode", buf);
usb_host_mode = buf[0];
memset(buf, 0, sizeof(buf));
local_cal_readcopy(cal, "root_device", buf);
if ( strcmp(buf, "mmc") == 0 )
root_device = 1;
else if ( strcmp(buf, "usb") == 0 )
root_device = 2;
else
root_device = 0;
cal_finish(cal);
}
#endif
int local_init(void) {
#if defined(__linux__) && defined(__arm__)
char buf[1024];
char * ptr;
char * ptr2;
FILE * file;
#endif
if ( failed )
return -1;
#if defined(__linux__) && defined(__arm__)
file = fopen("/proc/cpuinfo", "r");
if ( ! file ) {
failed = 1;
return -1;
}
while ( fgets(buf, sizeof(buf), file) ) {
if ( strncmp(buf, "Hardware", sizeof("Hardware")-1) == 0 ) {
ptr = buf + sizeof("Hardware")-1;
while ( ptr < buf + sizeof(buf) && *ptr > 0 && *ptr <= 32 )
++ptr;
if ( *ptr != ':' )
continue;
++ptr;
while ( ptr < buf + sizeof(buf) && *ptr > 0 && *ptr <= 32 )
++ptr;
if ( ! *ptr )
continue;
ptr2 = buf + strlen(buf);
while ( *ptr2 <= 32 ) {
*ptr2 = 0;
--ptr2;
}
if ( strcmp(ptr, "Nokia 770") == 0 )
device = DEVICE_SU_18;
else if ( strcmp(ptr, "Nokia N800") == 0 )
device = DEVICE_RX_34;
else if ( strcmp(ptr, "Nokia N810") == 0 )
device = DEVICE_RX_44;
else if ( strcmp(ptr, "Nokia N810 WiMAX") == 0 )
device = DEVICE_RX_48;
else if ( strcmp(ptr, "Nokia RX-51 board") == 0 )
device = DEVICE_RX_51;
if ( device ) {
printf("Found local device: %s\n", device_to_long_string(device));
fclose(file);
local_cal_parse();
return 0;
}
}
}
fclose(file);
#endif
failed = 1;
printf("Not a local device\n");
return -1;
}
enum device local_get_device(void) {
return device;
}
int local_flash_image(struct image * image) {
ERROR("Not implemented yet");
(void)image;
return -1;
}
static int local_nanddump(const char * file, int mtd, int offset, int length) {
struct statvfs buf;
char * command;
char * path;
size_t size;
int ret;
path = strdup(file);
if ( ! path )
return 1;
ret = statvfs(dirname(path), &buf);
free(path);
if ( ret == 0 && buf.f_bsize * buf.f_bfree < (long unsigned int)length ) {
ERROR("Not enough free space (have: %ju, need: %d)", (intmax_t)(buf.f_bsize * buf.f_bfree), length);
return 1;
}
size = snprintf(NULL, 0, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
command = malloc(size+1);
if ( ! command )
return 1;
snprintf(command, size+1, "nanddump -o -b -s %d -l %d -f %s /dev/mtd%dro", offset, length, file, mtd);
ret = system(command);
free(command);
return ret;
}
struct nanddump_args {
int valid;
int mtd;
int offset;
int length;
};
static struct nanddump_args nanddump_rx51[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000000, 0x00004000 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
[IMAGE_KERNEL] = { 1, 3, 0x00000800, 0x001FF800 },
[IMAGE_INITFS] = { 1, 4, 0x00000000, 0x00200000 },
[IMAGE_ROOTFS] = { 1, 5, 0x00000000, 0x0fb40000 },
};
/* FIXME: Is this table correct? */
static struct nanddump_args nanddump_rx4x[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x0021F800 },
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00400000 },
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0f960000 },
};
/* FIXME: Is this table correct? */
static struct nanddump_args nanddump_old[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x001FF800 },
[IMAGE_INITFS] = { 1, 3, 0x00000000, 0x00200000 },
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0fb80000 },
};
struct nanddump_device {
size_t count;
struct nanddump_args * args;
};
#define NANDDUMP(device, array) [device] = { .count = sizeof(array)/sizeof(array[0]), .args = array }
static struct nanddump_device nanddump[] = {
NANDDUMP(DEVICE_SU_18, nanddump_old),
NANDDUMP(DEVICE_RX_34, nanddump_old),
NANDDUMP(DEVICE_RX_44, nanddump_rx4x),
NANDDUMP(DEVICE_RX_48, nanddump_rx4x),
NANDDUMP(DEVICE_RX_51, nanddump_rx51),
};
#undef NANDDUMP
static void local_find_internal_mydocs(int * maj, int * min) {
#ifdef __linux__
int fd;
DIR * dir;
DIR * dir2;
FILE * f;
struct dirent * dirent;
struct dirent * dirent2;
char buf[1024];
/* Find min & maj id for block device MyDocs (mmc device, partition 1) */
dir = opendir("/sys/class/mmc_host/");
if ( ! dir ) {
ERROR("Cannot find MyDocs mmc device: Opening '/sys/class/mmc_host/' failed");
return;
}
while ( ( dirent = readdir(dir) ) ) {
if ( strncmp(dirent->d_name, ".", sizeof(".")) == 0 || strncmp(dirent->d_name, "..", sizeof("..")) == 0 )
continue;
if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/slot_name", dirent->d_name) <= 0 )
continue;
fd = open(buf, O_RDONLY);
if ( fd < 0 )
continue;
memset(buf, 0, sizeof(buf));
if ( read(fd, buf, sizeof(buf)-1) < 0 )
buf[0] = 0;
close(fd);
fd = -1;
if ( strncmp(buf, "internal", sizeof("internal")-1) != 0 )
continue;
if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/", dirent->d_name, dirent->d_name) <= 0 )
continue;
dir2 = opendir(buf);
if ( ! dir2 )
continue;
while ( ( dirent2 = readdir(dir2) ) ) {
if ( strncmp(dirent2->d_name, "block:mmcblk", sizeof("block:mmcblk")-1) != 0 )
continue;
if ( snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/%s/dev", dirent->d_name, dirent->d_name, dirent2->d_name) <= 0 )
continue;
f = fopen(buf, "r");
if ( ! f )
continue;
if ( fscanf(f, "%d:%d", maj, min) != 2 ) {
*maj = -1;
*min = -1;
fclose(f);
continue;
}
fclose(f);
break;
}
closedir(dir2);
if ( *maj != -1 && *min != -1 )
break;
}
closedir(dir);
#endif
}
int local_dump_image(enum image_type image, const char * file) {
int ret = -1;
int fd = -1;
unsigned char * addr = NULL;
off_t nlen, len;
int align;
int maj, min;
printf("Dump %s image to file %s...\n", image_type_to_string(image), file);
if ( image == IMAGE_MMC ) {
maj = -1;
min = -1;
local_find_internal_mydocs(&maj, &min);
if ( maj == -1 || min == -1 ) {
ERROR("Cannot find MyDocs mmc device: Slot 'internal' was not found");
goto clean;
}
VERBOSE("Detected internal MyDocs mmc device: major=%d minor=%d\n", maj, min);
fd = disk_open_dev(maj, min, 1, 1);
if ( fd < 0 ) {
ERROR("Cannot open MyDocs mmc device in /dev/");
goto clean;
}
ret = disk_dump_dev(fd, file);
close(fd);
fd = -1;
} else {
if ( device >= sizeof(nanddump)/sizeof(nanddump[0]) ) {
ERROR("Unsupported device");
goto clean;
}
if ( image >= nanddump[device].count ) {
ERROR("Unsupported image type: %s", image_type_to_string(image));
goto clean;
}
ret = local_nanddump(file, nanddump[device].args[image].mtd, nanddump[device].args[image].offset, nanddump[device].args[image].length);
}
if ( ret != 0 ) {
ret = -1;
goto clean;
}
fd = open(file, O_RDWR);
if ( fd < 0 )
goto clean;
len = lseek(fd, 0, SEEK_END);
if ( len == (off_t)-1 || len == 0 )
goto clean;
addr = (unsigned char *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
if ( addr == MAP_FAILED )
addr = NULL;
if ( ! addr )
goto clean;
for ( nlen = len; nlen > 0; --nlen )
if ( addr[nlen-1] != 0xFF )
break;
for ( ; nlen > 0; --nlen )
if ( addr[nlen-1] != 0x00 )
break;
if ( image == IMAGE_MMC )
align = 8;
else
align = 7;
if ( ( nlen & ( ( 1ULL << align ) - 1 ) ) != 0 )
nlen = ((nlen >> align) + 1) << align;
if ( nlen == 0 ) {
printf("File %s is empty, removing it...\n", file);
unlink(file);
} else if ( nlen != len ) {
printf("Truncating file %s to %d bytes...\n", file, (int)nlen);
if ( ftruncate(fd, nlen) < 0 )
ERROR_INFO("Cannot truncate file %s", file);
}
clean:
if ( addr )
munmap((void *)addr, len);
if ( fd >= 0 )
close(fd);
printf("\n");
return ret;
}
int local_check_badblocks(const char * device) {
ERROR("Not implemented yet");
(void)device;
return -1;
}
int local_reboot_device(void) {
if ( system("dsmetool -b") == 0 )
return 0;
return system("reboot");
}
int local_get_root_device(void) {
return root_device;
}
int local_set_root_device(int device) {
ERROR("Not implemented yet");
(void)device;
return -1;
}
int local_get_usb_host_mode(void) {
return usb_host_mode;
}
int local_set_usb_host_mode(int enable) {
ERROR("Not implemented yet");
(void)enable;
return -1;
}
int local_get_rd_mode(void) {
if ( strncmp(rd_mode, "master", sizeof("master")-1) == 0 )
return 1;
else
return 0;
}
int local_set_rd_mode(int enable) {
ERROR("Not implemented yet");
(void)enable;
return -1;
}
int local_get_rd_flags(char * flags, size_t size) {
const char * ptr;
if ( strncmp(rd_mode, "master", sizeof("master")-1) == 0 )
ptr = rd_mode + sizeof("master")-1;
else
ptr = rd_mode;
if ( *ptr == ',' )
++ptr;
if ( ! *ptr ) {
flags[0] = 0;
return 0;
}
strncpy(flags, ptr, size);
flags[size-1] = 0;
return 0;
}
int local_set_rd_flags(const char * flags) {
ERROR("Not implemented yet");
(void)flags;
return -1;
}
int16_t local_get_hwrev(void) {
return hwrev;
}
int local_set_hwrev(int16_t hwrev) {
ERROR("Not implemented yet");
(void)hwrev;
return -1;
}
int local_get_kernel_ver(char * ver, size_t size) {
strncpy(ver, kernel_ver, size);
ver[size-1] = 0;
return 0;
}
int local_set_kernel_ver(const char * ver) {
ERROR("Not implemented yet");
(void)ver;
return -1;
}
int local_get_initfs_ver(char * ver, size_t size) {
strncpy(ver, initfs_ver, size);
ver[size-1] = 0;
return 0;
}
int local_set_initfs_ver(const char * ver) {
ERROR("Not implemented yet");
(void)ver;
return -1;
}
int local_get_nolo_ver(char * ver, size_t size) {
strncpy(ver, nolo_ver, size);
ver[size-1] = 0;
return 0;
}
int local_set_nolo_ver(const char * ver) {
ERROR("Not implemented yet");
(void)ver;
return -1;
}
int local_get_sw_ver(char * ver, size_t size) {
strncpy(ver, sw_ver, size);
ver[size-1] = 0;
return 0;
}
int local_set_sw_ver(const char * ver) {
ERROR("Not implemented yet");
(void)ver;
return -1;
}
int local_get_content_ver(char * ver, size_t size) {
strncpy(ver, content_ver, size);
ver[size-1] = 0;
return 0;
}
int local_set_content_ver(const char * ver) {
ERROR("Not implemented yet");
(void)ver;
return -1;
}
+65
View File
@@ -0,0 +1,65 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOCAL_H
#define LOCAL_H
#include "image.h"
#include "device.h"
int local_init(void);
enum device local_get_device(void);
int local_flash_image(struct image * image);
int local_dump_image(enum image_type image, const char * file);
int local_check_badblocks(const char * device);
int local_reboot_device(void);
int local_get_root_device(void);
int local_set_root_device(int device);
int local_get_usb_host_mode(void);
int local_set_usb_host_mode(int enable);
int local_get_rd_mode(void);
int local_set_rd_mode(int enable);
int local_get_rd_flags(char * flags, size_t size);
int local_set_rd_flags(const char * flags);
int16_t local_get_hwrev(void);
int local_set_hwrev(int16_t hwrev);
int local_get_kernel_ver(char * ver, size_t size);
int local_set_kernel_ver(const char * ver);
int local_get_initfs_ver(char * ver, size_t size);
int local_set_initfs_ver(const char * ver);
int local_get_nolo_ver(char * ver, size_t size);
int local_set_nolo_ver(const char * ver);
int local_get_sw_ver(char * ver, size_t size);
int local_set_sw_ver(const char * ver);
int local_get_content_ver(char * ver, size_t size);
int local_set_content_ver(const char * ver);
#endif
+1356 -260
View File
File diff suppressed because it is too large. Load diff
-60
View File
@@ -1,60 +0,0 @@
#ifndef _INCLUDE_MAIN_H_
#define _INCLUDE_MAIN_H_
#define _FILE_OFFSET_BITS 64
#define _GNU_SOURCE
int reverse_extract_pieces(char *dir);
void flash_image(char *filename, char *piece, char *version);
int fiasco_read_image(char *file);
void check_nolo_order();
extern struct usb_dev_handle *dev;
unsigned long get_file_size(char *file);
void progressbar(unsigned long long part, unsigned long long total);
int get_status();
int get_peripheral_host_mode(int foo);
int boot_board(char *cmdline);
int boot_board(char *cmdline);
int reboot_board();
char *fpid_file(char *filename);
int set_rd_mode(unsigned short mode);
int set_usb_host_mode(unsigned short mode);
int query_hw_revision();
int query_rdmode_device();
int query_root_device();
int query_nolo_version();
int add_piece(char *piece);
#define D if (verbose)
#define CMD_WRITE 64
#define CMD_QUERY 192
#define NOLO_GET_STATUS 1
#define NOLO_GET_BOARD_ID 2
#define NOLO_GET_VERSION 3
struct piece_t {
char *name;
char *type;
char *vers;
};
extern int pcs_n;
extern struct piece_t pcs[10];
enum {
PIECE_XLOADER = 0,
PIECE_SECONDARY,
PIECE_KERNEL,
PIECE_INITFS,
PIECE_ROOTFS,
PIECE_OMAPNAND,
PIECE_LAST
};
extern char *pieces[];
extern char *modes[];
extern char *root_devices[];
#endif
+110
View File
@@ -0,0 +1,110 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2013 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAME "0xFFFF"
#define INFO NAME " \\- Open Free Fiasco Firmware Flasher, version " VERSION
#define DESCRIPTION "0xFFFF is Open Free Fiasco Firmware Flasher for Maemo devices. It support generating and unpacking FIASCO images on local computer. Useful for editing Maemo firmware package for future flash. It support via USB flashing any image type to Maemo device and also \"cold\" flashing which means flashing dead device with erased bootloader. There is support for booting kernel via USB without flashing to NAND and also changing configuration of Maemo device (enable/disable R&D mode, changing HW revision strings, ...).\n\n0xFFFF is alternative tool to proprietary Nokia flasher-3.5 and fiasco-gen. 0xFFFF generate compatible FIASCO images and also accept FIASCO images generated by Nokia fiasco-gen."
#ifndef BUILD_DATE
#define BUILD_DATE __DATE__
#endif
int main() {
FILE * pipe;
char buf[1024];
pipe = popen("./0xFFFF -h", "r");
if ( ! pipe )
return 1;
puts(".TH " NAME " 1 \"" BUILD_DATE "\" \"" NAME " " VERSION "\"");
puts("");
puts(".SH NAME");
puts(INFO);
puts("");
puts(".SH SYNOPSIS");
puts(".B " NAME);
puts(".I [options]");
puts("");
puts(".SH DESCRIPTION");
puts(DESCRIPTION);
while ( fgets(buf, sizeof(buf), pipe) ) {
if ( ! buf[0] )
continue;
if ( buf[0] == ' ' && buf[2] == ' ' ) {
char * ptr = buf;
while ( *ptr && *ptr == ' ' )
++ptr;
if ( ! *ptr )
continue;
printf(".br\n%s", ptr);
} else if ( buf[0] == ' ' ) {
char * ptr = buf;
char * ptr2;
while ( *ptr && *ptr == ' ' )
++ptr;
if ( ! *ptr )
continue;
ptr2 = ptr;
while ( *ptr2 && ( *ptr2 != ' ' || *(ptr2-1) != ' ' ) )
++ptr2;
*(ptr2-1) = 0;
while ( *ptr2 && *ptr2 == ' ' )
++ptr2;
if ( *ptr2 )
printf(".TP\n.B %s\n%s", ptr, ptr2);
else
printf(".br\n%s\n", ptr);
} else if ( buf[strlen(buf)-2] == ':' ) {
printf("\n.SH %s\n", buf);
}
}
pclose(pipe);
return 0;
}
+571
View File
@@ -0,0 +1,571 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include "mkii.h"
#include "global.h"
#include "image.h"
#include "device.h"
#include "usb-device.h"
#define MKII_OUT 0x8810001B
#define MKII_IN 0x8800101B
#define MKII_PING 0x00
#define MKII_GET 0x01
#define MKII_TELL 0x02
#define MKII_REBOOT 0x0C
#define MKII_RESPONCE 0x20
struct mkii_message {
uint32_t header;
uint16_t size;
uint16_t zero;
uint8_t num;
uint8_t type;
char data[];
} __attribute__((__packed__));
static int mkii_send_receive(usb_dev_handle * udev, uint8_t type, struct mkii_message * in_msg, size_t data_size, struct mkii_message * out_msg, size_t out_size) {
int ret;
static uint8_t number = 0;
in_msg->header = MKII_OUT;
in_msg->size = htons(data_size + 4);
in_msg->zero = 0;
in_msg->num = number++;
in_msg->type = type;
ret = usb_bulk_write(udev, USB_WRITE_EP, (char *)in_msg, data_size + sizeof(*in_msg), 5000);
if ( ret < 0 )
return ret;
if ( (size_t)ret != data_size + sizeof(*in_msg) )
return -1;
ret = usb_bulk_read(udev, USB_READ_EP, (char *)out_msg, out_size, 5000);
if ( ret < 0 )
return ret;
if ( out_msg->header != MKII_IN )
return -1;
if ( out_msg->type != (type | MKII_RESPONCE) )
return -1;
if ( (size_t)ret < sizeof(*out_msg) )
return -1;
if ( ntohs(out_msg->size) != ret - sizeof(*out_msg) + 4 )
return -1;
return ret - sizeof(*out_msg);
}
int mkii_init(struct usb_device_info * dev) {
char buf[2048];
struct mkii_message * msg;
enum device device;
int ret;
char * newptr;
char * ptr;
enum image_type type;
printf("Initializing Mk II protocol...\n");
msg = (struct mkii_message *)buf;
ret = mkii_send_receive(dev->udev, MKII_PING, msg, 0, msg, sizeof(buf));
if ( ret != 0 )
ERROR_RETURN("Cannot ping device", -1);
memcpy(msg->data, "/update/protocol_version", sizeof("/update/protocol_version")-1);
ret = mkii_send_receive(dev->udev, MKII_GET, msg, sizeof("/update/protocol_version")-1, msg, sizeof(buf));
if ( ret < 2 || msg->data[0] != 0 )
ERROR_RETURN("Cannot get Mk II protocol version", -1);
msg->data[ret] = 0;
if ( ret == 2 && msg->data[1] == 0x32 )
dev->data |= MKII_SUPPORT_SW_RELEASE;
printf("Detected Mk II protocol version: %s\n", msg->data);
memcpy(msg->data, "/update/host_protocol_version\x00\x32", sizeof("/update/host_protocol_version\x00\x32")-1);
ret = mkii_send_receive(dev->udev, MKII_TELL, msg, sizeof("/update/host_protocol_version\x00\x32")-1, msg, sizeof(buf));
if ( ret != 1 || msg->data[0] != 0 )
ERROR_RETURN("Cannot send our protocol version", -1);
device = mkii_get_device(dev);
if ( ! dev->device )
dev->device = device;
if ( dev->device && device && dev->device != device ) {
ERROR("Device mishmash, expected %s, got %s", device_to_string(dev->device), device_to_string(device));
return -1;
}
dev->hwrev = mkii_get_hwrev(dev);
memcpy(msg->data, "/update/supported_images", sizeof("/update/supported_images")-1);
ret = mkii_send_receive(dev->udev, MKII_GET, msg, sizeof("/update/supported_images")-1, msg, sizeof(buf));
if ( ret < 2 || msg->data[0] != 0 )
ERROR_RETURN("Cannot get supported image types", -1);
msg->data[ret] = 0;
ptr = msg->data + 1;
printf("Supported images by current device configuration:");
while ( ptr && *ptr ) {
newptr = strchr(ptr, ',');
if ( newptr ) {
*newptr = 0;
++newptr;
}
type = image_type_from_string(ptr);
if ( type != IMAGE_UNKNOWN ) {
dev->data |= (1UL << type);
printf(" %s", ptr);
}
ptr = newptr;
}
printf("\n");
memset(buf, 0, sizeof(buf));
if ( usb_device(dev->udev)->descriptor.bNumConfigurations >= 1 )
usb_get_string_simple(dev->udev, usb_device(dev->udev)->config[0].iConfiguration, buf, sizeof(buf));
if ( strncmp(buf, "Firmware Upgrade Configuration", sizeof("Firmware Upgrade Configuration")) == 0 )
dev->data |= MKII_UPDATE_MODE;
printf("Mode: %s\n", (dev->data & MKII_UPDATE_MODE) ? "Update" : "PC Suite");
return 0;
}
enum device mkii_get_device(struct usb_device_info * dev) {
char buf[2048];
struct mkii_message * msg;
int ret;
msg = (struct mkii_message *)buf;
memcpy(msg->data, "/device/product_code", sizeof("/device/product_code")-1);
ret = mkii_send_receive(dev->udev, MKII_GET, msg, sizeof("/device/product_code")-1, msg, sizeof(buf));
if ( ret < 2 || msg->data[0] != 0 || msg->data[1] == 0 )
return DEVICE_UNKNOWN;
msg->data[ret] = 0;
return device_from_string((char *)msg->data+1);
}
int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
char buf1[512];
char buf[2048];
struct mkii_message * msg1;
struct mkii_message * msg;
char * ptr;
const char * type;
uint8_t len;
uint16_t hash;
uint32_t size;
int ret;
ERROR("Not implemented yet");
return -1;
if ( ! ( dev->data & (1UL << image->type) ) ) {
ERROR("Flashing image %s is not supported in current device configuration", image_type_to_string(image->type));
return -1;
}
msg = (struct mkii_message *)buf;
msg1 = (struct mkii_message *)buf1;
ptr = msg->data;
/* Signature */
memcpy(ptr, "\x2E\x19\x01\x01", 4);
ptr += 4;
/* Space */
memcpy(ptr, "\x00", 1);
ptr += 1;
/* Hash */
hash = htons(image->hash);
memcpy(ptr, &hash, 2);
ptr += 2;
/* Type */
type = image_type_to_string(image->type);
if ( ! type )
ERROR_RETURN("Unknown image type", -1);
memset(ptr, 0, 12);
strncpy(ptr, type, 12);
ptr += 12;
/* Size */
size = htonl(image->size);
memcpy(ptr, &size, 4);
ptr += 4;
/* Space */
memcpy(ptr, "\x00\x00\x00\x00", 4);
ptr += 4;
/* Device & hwrev */
if ( image->devices ) {
int i;
uint8_t len;
char buf[9];
char ** bufs = NULL;
struct device_list * device = image->devices;
while ( device ) {
if ( device->device == dev->device && hwrev_is_valid(device->hwrevs, dev->hwrev) )
break;
device = device->next;
}
if ( device )
bufs = device_list_alloc_to_bufs(device);
if ( bufs ) {
memset(buf, 0, sizeof(buf));
snprintf(buf, 8+1, "%d", dev->hwrev);
for ( i = 0; bufs[i]; ++i ) {
len = ((uint8_t*)bufs[i])[0];
if ( MEMMEM(bufs[i]+1, len, buf, strlen(buf)) )
break;
}
if ( bufs[i] ) {
/* Device & hwrev string header */
memcpy(ptr, "\x32", 1);
ptr += 1;
/* Device & hwrev string size */
memcpy(ptr, &len, 1);
ptr += 1;
/* Device & hwrev string */
memcpy(ptr, bufs[i]+1, len);
ptr += len;
}
free(bufs);
}
}
/* Version */
if ( image->version ) {
len = strnlen(image->version, 255) + 1;
/* Version string header */
memcpy(ptr, "\x31", 1);
ptr += 1;
/* Version string size */
memcpy(ptr, &len, 1);
ptr += 1;
/* Version string */
memcpy(ptr, image->version, len);
ptr += len;
}
/* append layout subsection */
if ( image->layout ) {
len = strlen(image->layout);
/* Layout header */
memcpy(ptr, "\x33", 1);
ptr += 1;
/* Layout size */
memcpy(ptr, &len, 1);
ptr += 1;
/* Layout string */
memcpy(ptr, image->layout, len);
ptr += len;
}
/* end */
memcpy(ptr, "\x00", 1);
ptr += 1;
ret = mkii_send_receive(dev->udev, 0x03, msg1, 0, msg1, sizeof(buf1));
if ( ret != 1 || msg1->data[0] != 0 )
return -1;
ret = mkii_send_receive(dev->udev, 0x04, msg, ptr - msg->data, msg, sizeof(buf));
if ( ret != 9 )
return -1;
/* TODO: send image itself */
return 0;
}
int mkii_reboot_device(struct usb_device_info * dev, int update) {
char buf[2048];
struct mkii_message * msg;
const char * str;
int len;
int ret;
msg = (struct mkii_message *)buf;
if ( update ) {
printf("Rebooting device to Update mode...\n");
len = sizeof("reboot=update");
str = "reboot=update";
} else {
printf("Rebooting device...\n");
len = sizeof("reboot");
str = "reboot";
}
memcpy(msg->data, str, len);
ret = mkii_send_receive(dev->udev, MKII_REBOOT, msg, len, msg, sizeof(buf));
if ( ret != 1 || msg->data[0] != 0 )
ERROR_RETURN("Cannot send reboot command", -1);
return 0;
}
int mkii_get_root_device(struct usb_device_info * dev) {
ERROR("Not implemented yet");
(void)dev;
return -1;
}
int mkii_set_root_device(struct usb_device_info * dev, int device) {
ERROR("Not implemented yet");
(void)dev;
(void)device;
return -1;
}
int mkii_get_usb_host_mode(struct usb_device_info * dev) {
ERROR("Not implemented yet");
(void)dev;
return -1;
}
int mkii_set_usb_host_mode(struct usb_device_info * dev, int enable) {
ERROR("Not implemented yet");
(void)dev;
(void)enable;
return -1;
}
int mkii_get_rd_mode(struct usb_device_info * dev) {
ERROR("Not implemented yet");
(void)dev;
return -1;
}
int mkii_set_rd_mode(struct usb_device_info * dev, int enable) {
ERROR("Not implemented yet");
(void)dev;
(void)enable;
return -1;
}
int mkii_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size) {
ERROR("Not implemented yet");
(void)dev;
(void)flags;
(void)size;
return -1;
}
int mkii_set_rd_flags(struct usb_device_info * dev, const char * flags) {
ERROR("Not implemented yet");
(void)dev;
(void)flags;
return -1;
}
int16_t mkii_get_hwrev(struct usb_device_info * dev) {
char buf[2048];
struct mkii_message * msg;
int ret;
msg = (struct mkii_message *)buf;
memcpy(msg->data, "/device/hw_build", sizeof("/device/hw_build")-1);
ret = mkii_send_receive(dev->udev, MKII_GET, msg, sizeof("/device/hw_build")-1, msg, sizeof(buf));
if ( ret < 2 || msg->data[0] != 0 || msg->data[1] == 0 )
ERROR_RETURN("Cannot get hw revision", -1);
msg->data[ret] = 0;
return atoi(msg->data+1);
}
int mkii_set_hwrev(struct usb_device_info * dev, int16_t hwrev) {
ERROR("Not implemented yet");
(void)dev;
(void)hwrev;
return -1;
}
int mkii_get_kernel_ver(struct usb_device_info * dev, char * ver, size_t size) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
(void)size;
return -1;
}
int mkii_set_kernel_ver(struct usb_device_info * dev, const char * ver) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
return -1;
}
int mkii_get_initfs_ver(struct usb_device_info * dev, char * ver, size_t size) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
(void)size;
return -1;
}
int mkii_set_initfs_ver(struct usb_device_info * dev, const char * ver) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
return -1;
}
int mkii_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
(void)size;
return -1;
}
int mkii_set_nolo_ver(struct usb_device_info * dev, const char * ver) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
return -1;
}
int mkii_get_sw_ver(struct usb_device_info * dev, char * ver, size_t size) {
char buf[2048];
struct mkii_message * msg;
int ret;
if ( ! ( dev->data & MKII_SUPPORT_SW_RELEASE ) )
return -1;
msg = (struct mkii_message *)buf;
memcpy(msg->data, "/version/sw_release", sizeof("/version/sw_release")-1);
ret = mkii_send_receive(dev->udev, MKII_GET, msg, sizeof("/version/sw_release")-1, msg, sizeof(buf));
if ( ret < 2 || msg->data[0] != 0 || msg->data[1] == 0 )
ERROR_RETURN("Cannot get sw release", -1);
msg->data[ret] = 0;
strncpy(ver, msg->data+1, size);
ver[size-1] = 0;
return strlen(ver);
}
int mkii_set_sw_ver(struct usb_device_info * dev, const char * ver) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
return -1;
}
int mkii_get_content_ver(struct usb_device_info * dev, char * ver, size_t size) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
(void)size;
return -1;
}
int mkii_set_content_ver(struct usb_device_info * dev, const char * ver) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
return -1;
}
+67
View File
@@ -0,0 +1,67 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MKII_H
#define MKII_H
#include "image.h"
#include "device.h"
#include "usb-device.h"
#define MKII_SUPPORT_SW_RELEASE (1UL << 30)
#define MKII_UPDATE_MODE (1UL << 31)
int mkii_init(struct usb_device_info * dev);
enum device mkii_get_device(struct usb_device_info * dev);
int mkii_flash_image(struct usb_device_info * dev, struct image * image);
int mkii_reboot_device(struct usb_device_info * dev, int update);
int mkii_get_root_device(struct usb_device_info * dev);
int mkii_set_root_device(struct usb_device_info * dev, int device);
int mkii_get_usb_host_mode(struct usb_device_info * dev);
int mkii_set_usb_host_mode(struct usb_device_info * dev, int enable);
int mkii_get_rd_mode(struct usb_device_info * dev);
int mkii_set_rd_mode(struct usb_device_info * dev, int enable);
int mkii_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size);
int mkii_set_rd_flags(struct usb_device_info * dev, const char * flags);
int16_t mkii_get_hwrev(struct usb_device_info * dev);
int mkii_set_hwrev(struct usb_device_info * dev, int16_t hwrev);
int mkii_get_kernel_ver(struct usb_device_info * dev, char * ver, size_t size);
int mkii_set_kernel_ver(struct usb_device_info * dev, const char * ver);
int mkii_get_initfs_ver(struct usb_device_info * dev, char * ver, size_t size);
int mkii_set_initfs_ver(struct usb_device_info * dev, const char * ver);
int mkii_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size);
int mkii_set_nolo_ver(struct usb_device_info * dev, const char * ver);
int mkii_get_sw_ver(struct usb_device_info * dev, char * ver, size_t size);
int mkii_set_sw_ver(struct usb_device_info * dev, const char * ver);
int mkii_get_content_ver(struct usb_device_info * dev, char * ver, size_t size);
int mkii_set_content_ver(struct usb_device_info * dev, const char * ver);
#endif
+905
View File
@@ -0,0 +1,905 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007-2009 pancake <pancake@youterm.com>
* Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include "nolo.h"
#include "image.h"
#include "global.h"
#include "printf-utils.h"
/* Request type */
#define NOLO_WRITE 64
#define NOLO_QUERY 192
/* Request */
#define NOLO_STATUS 1
#define NOLO_GET_NOLO_VERSION 3
#define NOLO_IDENTIFY 4
#define NOLO_ERROR_LOG 5
#define NOLO_SET 16
#define NOLO_GET 17
#define NOLO_STRING 18
#define NOLO_SET_STRING 19
#define NOLO_GET_STRING 20
#define NOLO_SEND_IMAGE 66
#define NOLO_SET_SW_RELEASE 67
#define NOLO_FLASH_IMAGE 80
#define NOLO_SEND_FLASH_FINISH 82
#define NOLO_SEND_FLASH_IMAGE 84
#define NOLO_BOOT 130
#define NOLO_REBOOT 131
/* Indexes - Flash image */
#define NOLO_IMAGE_BOOTLOADER 1
#define NOLO_IMAGE_KERNEL 3
#define NOLO_IMAGE_INITFS 4
#define NOLO_IMAGE_CMT 66
/* Indexes - Set & Get */
#define NOLO_RD_MODE 0
#define NOLO_ROOT_DEVICE 1
#define NOLO_USB_HOST_MODE 2
#define NOLO_ADD_RD_FLAGS 3
#define NOLO_DEL_RD_FLAGS 4
/* Values - R&D flags */
#define NOLO_RD_FLAG_NO_OMAP_WD 0x002
#define NOLO_RD_FLAG_NO_EXT_WD 0x004
#define NOLO_RD_FLAG_NO_LIFEGUARD 0x008
#define NOLO_RD_FLAG_SERIAL_CONSOLE 0x010
#define NOLO_RD_FLAG_NO_USB_TIMEOUT 0x020
#define NOLO_RD_FLAG_STI_CONSOLE 0x040
#define NOLO_RD_FLAG_NO_CHARGING 0x080
#define NOLO_RD_FLAG_FORCE_POWER_KEY 0x100
/* Values - Boot mode */
#define NOLO_BOOT_MODE_NORMAL 0
#define NOLO_BOOT_MODE_UPDATE 1
#define NOLO_ERROR_RETURN(str, ...) do { nolo_error_log(dev, str == NULL); ERROR_RETURN(str, __VA_ARGS__); } while (0)
static void nolo_error_log(struct usb_device_info * dev, int only_clear) {
char buf[2048];
size_t i, count;
int ret;
for ( count = 0; count < 20; ++count ) {
memset(buf, 0, sizeof(buf));
ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_ERROR_LOG, 0, 0, buf, sizeof(buf), 2000);
if ( ret < 0 )
break;
if ( ! only_clear ) {
for ( i = 0; i < sizeof(buf)-2; ++i )
if ( buf[i] == 0 && buf[i+1] != 0 )
buf[i] = '\n';
buf[sizeof(buf)-1] = 0;
puts(buf);
}
if ( (size_t)ret < sizeof(buf) )
break;
}
}
static int nolo_identify_string(struct usb_device_info * dev, const char * str, char * out, size_t size) {
char buf[512];
char * ptr;
int ret;
memset(buf, 0, sizeof(buf));
ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_IDENTIFY, 0, 0, (char *)buf, sizeof(buf), 2000);
if ( ret < 0 )
NOLO_ERROR_RETURN("NOLO_IDENTIFY failed", -1);
if ( (size_t)ret > sizeof(buf) )
ret = sizeof(buf);
ptr = MEMMEM(buf, ret, str, strlen(str));
if ( ! ptr )
ERROR_RETURN("Substring was not found", -1);
ptr += strlen(str) + 1;
while ( ptr-buf < ret && *ptr < 32 )
++ptr;
if ( ! *ptr )
return -1;
strncpy(out, ptr, size-1);
out[size-1] = 0;
return strlen(out);
}
static int nolo_set_string(struct usb_device_info * dev, char * str, char * arg) {
if ( simulate )
return 0;
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, str, strlen(str), 2000) < 0 )
NOLO_ERROR_RETURN("NOLO_STRING failed", -1);
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET_STRING, 0, 0, arg, strlen(arg), 2000) < 0 )
NOLO_ERROR_RETURN("NOLO_SET_STRING failed", -1);
return 0;
}
static int nolo_get_string(struct usb_device_info * dev, char * str, char * out, size_t size) {
int ret = 0;
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, str, strlen(str), 2000) < 0 )
return -1;
if ( ( ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET_STRING, 0, 0, out, size-1, 2000) ) < 0 )
return -1;
if ( (size_t)ret > size-1 )
ret = size-1;
out[size-1] = 0;
out[ret] = 0;
return strlen(out);
}
static int nolo_get_version_string(struct usb_device_info * dev, const char * str, char * out, size_t size) {
int ret;
char buf[512];
if ( strlen(str) > 500 )
return -1;
if ( sprintf(buf, "version:%s", str) <= 0 )
return -1;
ret = nolo_get_string(dev, buf, out, size);
if ( ret < 0 ) {
nolo_error_log(dev, 1);
return ret;
}
if ( ! out[0] )
return -1;
return ret;
}
int nolo_init(struct usb_device_info * dev) {
uint32_t val = 1;
enum device device;
printf("Initializing NOLO...\n");
while ( val != 0 )
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_STATUS, 0, 0, (char *)&val, 4, 2000) == -1 )
NOLO_ERROR_RETURN("NOLO_STATUS failed", -1);
/* clear error log */
nolo_error_log(dev, 1);
device = nolo_get_device(dev);
if ( ! dev->device )
dev->device = device;
if ( dev->device && device && dev->device != device ) {
ERROR("Device mishmash, expected %s, got %s", device_to_string(dev->device), device_to_string(device));
return -1;
}
dev->hwrev = nolo_get_hwrev(dev);
return 0;
}
enum device nolo_get_device(struct usb_device_info * dev) {
char buf[20];
if ( nolo_identify_string(dev, "prod_code", buf, sizeof(buf)) < 0 )
return DEVICE_UNKNOWN;
else if ( buf[0] )
return device_from_string(buf);
else
return DEVICE_UNKNOWN;
}
static int nolo_send_image(struct usb_device_info * dev, struct image * image, int flash) {
char buf[0x20000];
char * ptr;
const char * type;
uint8_t len;
uint16_t hash;
uint32_t size;
uint32_t need;
uint32_t sent;
int request;
int ret;
if ( flash )
printf("Send and flash image:\n");
else
printf("Load image:\n");
image_print_info(image);
if ( image->type == IMAGE_2ND || image->type == IMAGE_MMC )
ERROR_RETURN("Sending 2nd and mmc images are not supported", -1);
if ( ! flash && image->type == IMAGE_ROOTFS )
ERROR_RETURN("Rootfs image must be sent in flash mode", -1);
ptr = buf;
/* Signature */
memcpy(ptr, "\x2E\x19\x01\x01", 4);
ptr += 4;
/* Space */
memcpy(ptr, "\x00", 1);
ptr += 1;
/* Hash */
hash = htons(image->hash);
memcpy(ptr, &hash, 2);
ptr += 2;
/* Type */
type = image_type_to_string(image->type);
if ( ! type )
ERROR_RETURN("Unknown image type", -1);
memset(ptr, 0, 12);
strncpy(ptr, type, 12);
ptr += 12;
/* Size */
size = htonl(image->size);
memcpy(ptr, &size, 4);
ptr += 4;
/* Space */
memcpy(ptr, "\x00\x00\x00\x00", 4);
ptr += 4;
/* Device & hwrev */
if ( image->devices ) {
int i;
uint8_t len;
char buf[9];
char ** bufs = NULL;
struct device_list * device = image->devices;
while ( device ) {
if ( device->device == dev->device && hwrev_is_valid(device->hwrevs, dev->hwrev) )
break;
device = device->next;
}
if ( device )
bufs = device_list_alloc_to_bufs(device);
if ( bufs ) {
memset(buf, 0, sizeof(buf));
snprintf(buf, 8+1, "%d", dev->hwrev);
for ( i = 0; bufs[i]; ++i ) {
len = ((uint8_t*)bufs[i])[0];
if ( MEMMEM(bufs[i]+1, len, buf, strlen(buf)) )
break;
}
if ( bufs[i] ) {
/* Device & hwrev string header */
memcpy(ptr, "\x32", 1);
ptr += 1;
/* Device & hwrev string size */
memcpy(ptr, &len, 1);
ptr += 1;
/* Device & hwrev string */
memcpy(ptr, bufs[i]+1, len);
ptr += len;
}
free(bufs);
}
}
/* Version */
if ( image->version ) {
len = strnlen(image->version, 255) + 1;
/* Version string header */
memcpy(ptr, "\x31", 1);
ptr += 1;
/* Version string size */
memcpy(ptr, &len, 1);
ptr += 1;
/* Version string */
memcpy(ptr, image->version, len);
ptr += len;
}
if ( flash )
request = NOLO_SEND_FLASH_IMAGE;
else
request = NOLO_SEND_IMAGE;
printf("Sending image header...\n");
if ( ! simulate ) {
if ( usb_control_msg(dev->udev, NOLO_WRITE, request, 0, 0, buf, ptr-buf, 2000) < 0 )
NOLO_ERROR_RETURN("Sending image header failed", -1);
}
if ( flash )
printf("Sending and flashing image...\n");
else
printf("Sending image...\n");
printf_progressbar(0, image->size);
image_seek(image, 0);
sent = 0;
while ( sent < image->size ) {
need = image->size - sent;
if ( need > sizeof(buf) )
need = sizeof(buf);
ret = image_read(image, buf, need);
if ( ret == 0 )
break;
if ( ! simulate ) {
if ( usb_bulk_write(dev->udev, USB_WRITE_DATA_EP, buf, ret, 5000) != ret ) {
PRINTF_END();
NOLO_ERROR_RETURN("Sending image failed", -1);
}
}
sent += ret;
printf_progressbar(sent, image->size);
}
if ( flash ) {
printf("Finishing flashing...\n");
if ( ! simulate ) {
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SEND_FLASH_FINISH, 0, 0, NULL, 0, 30000) < 0 )
NOLO_ERROR_RETURN("Finishing failed", -1);
}
}
printf("Done\n");
return 0;
}
int nolo_load_image(struct usb_device_info * dev, struct image * image) {
if ( image->type != IMAGE_KERNEL && image->type != IMAGE_INITFS )
ERROR_RETURN("Only kernel or initfs image can be loaded", -1);
return nolo_send_image(dev, image, 0);
}
int nolo_flash_image(struct usb_device_info * dev, struct image * image) {
int ret;
int flash;
int index;
unsigned long long int part;
unsigned long long int total;
unsigned long long int last_total;
char buf[128];
char * ptr;
if ( image->type == IMAGE_ROOTFS )
flash = 1;
else
flash = 0;
ret = nolo_send_image(dev, image, flash);
if ( ret < 0 )
return ret;
if ( image->type == IMAGE_SECONDARY )
index = NOLO_IMAGE_BOOTLOADER;
else if ( image->type == IMAGE_KERNEL )
index = NOLO_IMAGE_KERNEL;
else if ( image->type == IMAGE_CMT_MCUSW )
index = NOLO_IMAGE_CMT;
else
index = -1;
if ( image->type == IMAGE_CMT_MCUSW )
nolo_set_string(dev, "cmt:verify", "1");
if ( ! flash && index >= 0 ) {
printf("Flashing image...\n");
if ( ! simulate ) {
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_FLASH_IMAGE, 0, index, NULL, 0, 10000) )
NOLO_ERROR_RETURN("Flashing failed", -1);
}
printf("Done\n");
}
if ( image->type == IMAGE_CMT_MCUSW ) {
int state = 0;
last_total = 0;
if ( nolo_get_string(dev, "cmt:status", buf, sizeof(buf)) < 0 )
NOLO_ERROR_RETURN("cmt:status failed", -1);
if ( strncmp(buf, "idle", sizeof("idle")-1) == 0 )
state = 4;
else
printf("Erasing CMT...\n");
while ( state != 4 ) {
if ( nolo_get_string(dev, "cmt:status", buf, sizeof(buf)) < 0 ) {
PRINTF_END();
NOLO_ERROR_RETURN("cmt:status failed", -1);
}
if ( strncmp(buf, "finished", sizeof("finished")-1) == 0 ) {
if ( state <= 0 ) {
printf_progressbar(last_total, last_total);
printf("Done\n");
}
if ( state <= 1 )
printf("Programming CMT...\n");
if ( state <= 2 ) {
printf_progressbar(last_total, last_total);
printf("Done\n");
}
state = 4;
} else if ( strncmp(buf, "error", sizeof("error")-1) == 0 ) {
PRINTF_ERROR_RETURN("cmt:status error", -1);
} else {
ptr = strchr(buf, ':');
if ( ! ptr )
PRINTF_ERROR_RETURN("cmt:status unknown", -1);
*ptr = 0;
ptr++;
if ( sscanf(ptr, "%llu/%llu", &part, &total) != 2 )
PRINTF_ERROR_RETURN("cmt:status unknown", -1);
if ( strcmp(buf, "program") == 0 && state <= 0 ) {
printf_progressbar(last_total, last_total);
printf("Done\n");
state = 1;
}
if ( strcmp(buf, "program") == 0 && state <= 1 ) {
printf("Programming CMT...\n");
state = 2;
}
printf_progressbar(part, total);
last_total = total;
if ( strcmp(buf, "erase") == 0 && state <= 0 && part == total ) {
printf("Done\n");
state = 1;
}
if ( strcmp(buf, "program") == 0 && state <= 2 && part == total ) {
printf("Done\n");
state = 3;
}
}
SLEEP(0xc350); // 0.5s
}
}
return 0;
}
int nolo_boot_device(struct usb_device_info * dev, const char * cmdline) {
int size = 0;
int mode = NOLO_BOOT_MODE_NORMAL;
if ( cmdline && strncmp(cmdline, "update", sizeof("update")-1) == 0 && cmdline[sizeof("update")-1] <= 32 ) {
mode = NOLO_BOOT_MODE_UPDATE;
cmdline += sizeof("update")-1;
if ( *cmdline ) ++cmdline;
while ( *cmdline && *cmdline <= 32 )
++cmdline;
if ( *cmdline ) {
printf("Booting kernel to update mode with cmdline: %s...\n", cmdline);
size = strlen(cmdline);
} else {
printf("Booting kernel to update mode with default cmdline...\n");
cmdline = NULL;
}
} else if ( cmdline && cmdline[0] ) {
printf("Booting kernel with cmdline: '%s'...\n", cmdline);
size = strlen(cmdline)+1;
} else {
printf("Booting kernel with default cmdline...\n");
cmdline = NULL;
}
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_BOOT, mode, 0, (char *)cmdline, size, 2000) < 0 )
NOLO_ERROR_RETURN("Booting failed", -1);
return 0;
}
int nolo_reboot_device(struct usb_device_info * dev) {
printf("Rebooting device...\n");
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_REBOOT, 0, 0, NULL, 0, 2000) < 0 )
NOLO_ERROR_RETURN("NOLO_REBOOT failed", -1);
return 0;
}
int nolo_get_root_device(struct usb_device_info * dev) {
uint8_t device = 0;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_ROOT_DEVICE, (char *)&device, 1, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot get root device", -1);
return device;
}
int nolo_set_root_device(struct usb_device_info * dev, int device) {
printf("Setting root device to %d...\n", device);
if ( simulate )
return 0;
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, device, NOLO_ROOT_DEVICE, NULL, 0, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot set root device", -1);
return 0;
}
int nolo_get_usb_host_mode(struct usb_device_info * dev) {
uint32_t enabled = 0;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_USB_HOST_MODE, (void *)&enabled, 4, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot get USB host mode status", -1);
return enabled ? 1 : 0;
}
int nolo_set_usb_host_mode(struct usb_device_info * dev, int enable) {
printf("%s USB host mode...\n", enable ? "Enabling" : "Disabling");
if ( simulate )
return 0;
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, enable, NOLO_USB_HOST_MODE, NULL, 0, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot change USB host mode status", -1);
return 0;
}
int nolo_get_rd_mode(struct usb_device_info * dev) {
uint8_t enabled = 0;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_RD_MODE, (char *)&enabled, 1, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot get R&D mode status", -1);
return enabled ? 1 : 0;
}
int nolo_set_rd_mode(struct usb_device_info * dev, int enable) {
printf("%s R&D mode...\n", enable ? "Enabling" : "Disabling");
if ( simulate )
return 0;
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, enable, NOLO_RD_MODE, NULL, 0, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot change R&D mode status", -1);
return 0;
}
#define APPEND_STRING(ptr, buf, size, string) do { if ( (int)size > ptr-buf ) ptr += snprintf(ptr, size-(ptr-buf), "%s,", string); } while (0)
int nolo_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size) {
uint16_t add_flags = 0;
char * ptr = flags;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_ADD_RD_FLAGS, (char *)&add_flags, 2, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot get R&D flags", -1);
if ( add_flags & NOLO_RD_FLAG_NO_OMAP_WD )
APPEND_STRING(ptr, flags, size, "no-omap-wd");
if ( add_flags & NOLO_RD_FLAG_NO_EXT_WD )
APPEND_STRING(ptr, flags, size, "no-ext-wd");
if ( add_flags & NOLO_RD_FLAG_NO_LIFEGUARD )
APPEND_STRING(ptr, flags, size, "no-lifeguard-reset");
if ( add_flags & NOLO_RD_FLAG_SERIAL_CONSOLE )
APPEND_STRING(ptr, flags, size, "serial-console");
if ( add_flags & NOLO_RD_FLAG_NO_USB_TIMEOUT )
APPEND_STRING(ptr, flags, size, "no-usb-timeout");
if ( add_flags & NOLO_RD_FLAG_STI_CONSOLE )
APPEND_STRING(ptr, flags, size, "sti-console");
if ( add_flags & NOLO_RD_FLAG_NO_CHARGING )
APPEND_STRING(ptr, flags, size, "no-charging");
if ( add_flags & NOLO_RD_FLAG_FORCE_POWER_KEY )
APPEND_STRING(ptr, flags, size, "force-power-key");
if ( ptr != flags && *(ptr-1) == ',' )
*(--ptr) = 0;
return ptr-flags;
}
#undef APPEND_STRING
int nolo_set_rd_flags(struct usb_device_info * dev, const char * flags) {
const char * ptr = flags;
const char * endptr = ptr;
int add_flags = 0;
int del_flags = 0;
if ( flags && flags[0] )
printf("Setting R&D flags to: %s...\n", flags);
else
printf("Clearing all R&D flags...\n");
while ( ptr && *ptr ) {
while ( *ptr <= 32 )
++ptr;
if ( ! *ptr )
break;
endptr = strchr(ptr, ',');
if ( endptr )
endptr -= 1;
else
endptr = ptr+strlen(ptr);
if ( strncmp("no-omap-wd", ptr, endptr-ptr) == 0 )
add_flags |= NOLO_RD_FLAG_NO_OMAP_WD;
if ( strncmp("no-ext-wd", ptr, endptr-ptr) == 0 )
add_flags |= NOLO_RD_FLAG_NO_EXT_WD;
if ( strncmp("no-lifeguard-reset", ptr, endptr-ptr) == 0 )
add_flags |= NOLO_RD_FLAG_NO_LIFEGUARD;
if ( strncmp("serial-console", ptr, endptr-ptr) == 0 )
add_flags |= NOLO_RD_FLAG_SERIAL_CONSOLE;
if ( strncmp("no-usb-timeout", ptr, endptr-ptr) == 0 )
add_flags |= NOLO_RD_FLAG_NO_USB_TIMEOUT;
if ( strncmp("sti-console", ptr, endptr-ptr) == 0 )
add_flags |= NOLO_RD_FLAG_STI_CONSOLE;
if ( strncmp("no-charging", ptr, endptr-ptr) == 0 )
add_flags |= NOLO_RD_FLAG_NO_CHARGING;
if ( strncmp("force-power-key", ptr, endptr-ptr) == 0 )
add_flags |= NOLO_RD_FLAG_FORCE_POWER_KEY;
if ( *(endptr+1) )
ptr = endptr+2;
else
break;
}
if ( ! ( add_flags & NOLO_RD_FLAG_NO_OMAP_WD ) )
del_flags |= NOLO_RD_FLAG_NO_OMAP_WD;
if ( ! ( add_flags & NOLO_RD_FLAG_NO_EXT_WD ) )
del_flags |= NOLO_RD_FLAG_NO_EXT_WD;
if ( ! ( add_flags & NOLO_RD_FLAG_NO_LIFEGUARD ) )
del_flags |= NOLO_RD_FLAG_NO_LIFEGUARD;
if ( ! ( add_flags & NOLO_RD_FLAG_SERIAL_CONSOLE ) )
del_flags |= NOLO_RD_FLAG_SERIAL_CONSOLE;
if ( ! ( add_flags & NOLO_RD_FLAG_NO_USB_TIMEOUT ) )
del_flags |= NOLO_RD_FLAG_NO_USB_TIMEOUT;
if ( ! ( add_flags & NOLO_RD_FLAG_STI_CONSOLE ) )
del_flags |= NOLO_RD_FLAG_STI_CONSOLE;
if ( ! ( add_flags & NOLO_RD_FLAG_NO_CHARGING ) )
del_flags |= NOLO_RD_FLAG_NO_CHARGING;
if ( ! ( add_flags & NOLO_RD_FLAG_FORCE_POWER_KEY ) )
del_flags |= NOLO_RD_FLAG_FORCE_POWER_KEY;
if ( simulate )
return 0;
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, add_flags, NOLO_ADD_RD_FLAGS, NULL, 0, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot add R&D flags", -1);
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET, del_flags, NOLO_DEL_RD_FLAGS, NULL, 0, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot del R&D flags", -1);
return 0;
}
int16_t nolo_get_hwrev(struct usb_device_info * dev) {
char buf[10];
if ( nolo_identify_string(dev, "hw_rev", buf, sizeof(buf)) <= 0 )
return -1;
return atoi(buf);
}
int nolo_set_hwrev(struct usb_device_info * dev, int16_t hwrev) {
char buf[9];
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%d", hwrev);
printf("Setting HW revision to: %s\n", buf);
return nolo_set_string(dev, "hw_rev", buf);
}
int nolo_get_kernel_ver(struct usb_device_info * dev, char * ver, size_t size) {
return nolo_get_version_string(dev, "kernel", ver, size);
}
int nolo_set_kernel_ver(struct usb_device_info * dev, const char * ver) {
printf("nolo_set_kernel_ver is not implemented yet\n");
(void)dev;
(void)ver;
return -1;
}
int nolo_get_initfs_ver(struct usb_device_info * dev, char * ver, size_t size) {
return nolo_get_version_string(dev, "initfs", ver, size);
}
int nolo_set_initfs_ver(struct usb_device_info * dev, const char * ver) {
printf("nolo_set_initfs_ver is not implemented yet\n");
(void)dev;
(void)ver;
return -1;
}
int nolo_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size) {
uint32_t version = 0;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET_NOLO_VERSION, 0, 0, (char *)&version, 4, 2000) < 0 )
NOLO_ERROR_RETURN("Cannot get NOLO version", -1);
if ( (version & 255) > 1 )
NOLO_ERROR_RETURN("Invalid NOLO version", -1);
return snprintf(ver, size, "%d.%d.%d", version >> 20 & 15, version >> 16 & 15, version >> 8 & 255);
}
int nolo_set_nolo_ver(struct usb_device_info * dev, const char * ver) {
printf("nolo_set_nolo_ver is not implemented yet\n");
(void)dev;
(void)ver;
return -1;
}
int nolo_get_sw_ver(struct usb_device_info * dev, char * ver, size_t size) {
return nolo_get_version_string(dev, "sw-release", ver, size);
}
int nolo_set_sw_ver(struct usb_device_info * dev, const char * ver) {
char buf[512];
char * ptr;
uint8_t len;
const char * str = "OSSO UART+USB";
printf("Setting Software release string to: %s\n", ver);
if ( strlen(ver) > UINT8_MAX )
NOLO_ERROR_RETURN("Software release string is too long", -1);
ptr = buf;
memcpy(ptr, "\xe8", 1);
ptr += 1;
len = strlen(str)+1;
memcpy(ptr, &len, 1);
ptr += 1;
memcpy(ptr, str, len);
ptr += len;
memcpy(ptr, "\x31", 1);
ptr += 1;
len = strlen(ver)+1;
memcpy(ptr, &len, 1);
ptr += 1;
memcpy(ptr, ver, len);
ptr += len;
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET_SW_RELEASE, 0, 0, buf, ptr-buf, 2000) < 0 )
NOLO_ERROR_RETURN("NOLO_SET_SW_RELEASE failed", -1);
return 0;
}
int nolo_get_content_ver(struct usb_device_info * dev, char * ver, size_t size) {
return nolo_get_version_string(dev, "content", ver, size);
}
int nolo_set_content_ver(struct usb_device_info * dev, const char * ver) {
printf("nolo_set_content_ver is not implemented yet\n");
(void)dev;
(void)ver;
return -1;
}
+65
View File
@@ -0,0 +1,65 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
* Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NOLO_H
#define NOLO_H
#include "image.h"
#include "usb-device.h"
int nolo_init(struct usb_device_info * dev);
enum device nolo_get_device(struct usb_device_info * dev);
int nolo_load_image(struct usb_device_info * dev, struct image * image);
int nolo_flash_image(struct usb_device_info * dev, struct image * image);
int nolo_boot_device(struct usb_device_info * dev, const char * cmdline);
int nolo_reboot_device(struct usb_device_info * dev);
int nolo_get_root_device(struct usb_device_info * dev);
int nolo_set_root_device(struct usb_device_info * dev, int device);
int nolo_get_usb_host_mode(struct usb_device_info * dev);
int nolo_set_usb_host_mode(struct usb_device_info * dev, int enable);
int nolo_get_rd_mode(struct usb_device_info * dev);
int nolo_set_rd_mode(struct usb_device_info * dev, int enable);
int nolo_get_rd_flags(struct usb_device_info * dev, char * flags, size_t size);
int nolo_set_rd_flags(struct usb_device_info * dev, const char * flags);
int16_t nolo_get_hwrev(struct usb_device_info * dev);
int nolo_set_hwrev(struct usb_device_info * dev, int16_t hwrev);
int nolo_get_kernel_ver(struct usb_device_info * dev, char * ver, size_t size);
int nolo_set_kernel_ver(struct usb_device_info * dev, const char * ver);
int nolo_get_initfs_ver(struct usb_device_info * dev, char * ver, size_t size);
int nolo_set_initfs_ver(struct usb_device_info * dev, const char * ver);
int nolo_get_nolo_ver(struct usb_device_info * dev, char * ver, size_t size);
int nolo_set_nolo_ver(struct usb_device_info * dev, const char * ver);
int nolo_get_sw_ver(struct usb_device_info * dev, char * ver, size_t size);
int nolo_set_sw_ver(struct usb_device_info * dev, const char * ver);
int nolo_get_content_ver(struct usb_device_info * dev, char * ver, size_t size);
int nolo_set_content_ver(struct usb_device_info * dev, const char * ver);
#endif
+679
View File
@@ -0,0 +1,679 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "global.h"
#include "device.h"
#include "usb-device.h"
#include "cold-flash.h"
#include "nolo.h"
#include "mkii.h"
#include "disk.h"
#include "local.h"
#include "operations.h"
struct device_info * dev_detect(void) {
int ret = 0;
struct device_info * dev = NULL;
struct usb_device_info * usb = NULL;
dev = calloc(1, sizeof(struct device_info));
if ( ! dev )
goto clean;
/* LOCAL */
if ( local_init() == 0 ) {
dev->method = METHOD_LOCAL;
dev->detected_device = local_get_device();
dev->detected_hwrev = local_get_hwrev();
return dev;
}
/* USB */
usb = usb_open_and_wait_for_device();
if ( usb ) {
dev->method = METHOD_USB;
dev->usb = usb;
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
ret = nolo_init(dev->usb);
else if ( dev->usb->flash_device->protocol == FLASH_COLD )
ret = init_cold_flash(dev->usb);
else if ( dev->usb->flash_device->protocol == FLASH_MKII )
ret = mkii_init(dev->usb);
else if ( dev->usb->flash_device->protocol == FLASH_DISK )
ret = disk_init(dev->usb);
else {
ERROR("Unknown USB mode");
goto clean;
}
if ( ret < 0 )
goto clean;
dev->detected_device = dev_get_device(dev);
dev->detected_hwrev = dev_get_hwrev(dev);
if ( dev->detected_device && dev->usb->device && dev->detected_device != dev->usb->device ) {
ERROR("Bad device, expected %s, got %s", device_to_string(dev->usb->device), device_to_string(dev->detected_device));
goto clean;
}
return dev;
}
clean:
if ( usb )
usb_close_device(usb);
free(dev);
return NULL;
}
void dev_free(struct device_info * dev) {
if ( dev->usb ) {
if ( dev->usb->flash_device->protocol == FLASH_DISK )
disk_exit(dev->usb);
usb_close_device(dev->usb);
}
free(dev);
}
enum device dev_get_device(struct device_info * dev) {
if ( dev->method == METHOD_LOCAL )
return local_get_device();
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_COLD )
return DEVICE_UNKNOWN;
else if ( protocol == FLASH_NOLO )
return nolo_get_device(dev->usb);
else if ( protocol == FLASH_MKII )
return mkii_get_device(dev->usb);
else if ( protocol == FLASH_DISK )
return disk_get_device(dev->usb);
}
return DEVICE_UNKNOWN;
}
int dev_load_image(struct device_info * dev, struct image * image) {
if ( dev->method == METHOD_LOCAL ) {
ERROR("Loading image on local device is not supported");
return -1;
}
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_load_image(dev->usb, image);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_cold_flash_images(struct device_info * dev, struct image * x2nd, struct image * secondary) {
if ( dev->method == METHOD_LOCAL ) {
ERROR("Cold Flashing on local device is not supported");
return -1;
}
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_COLD )
return cold_flash(dev->usb, x2nd, secondary);
usb_switch_to_cold(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_flash_image(struct device_info * dev, struct image * image) {
if ( dev->method == METHOD_LOCAL )
return local_flash_image(image);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO ) {
if ( image->type != IMAGE_MMC )
return nolo_flash_image(dev->usb, image);
usb_switch_to_update(dev->usb);
return -EAGAIN;
} else if ( protocol == FLASH_MKII ) {
if ( dev->usb->data & (1UL << image->type) )
return mkii_flash_image(dev->usb, image);
}
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_dump_image(struct device_info * dev, enum image_type image, const char * file) {
if ( dev->method == METHOD_LOCAL )
return local_dump_image(image, file);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_DISK )
return disk_dump_image(dev->usb, image, file);
ERROR("Dump image via USB not in Mass Storage Mode is not supported");
return -1;
}
return -1;
}
int dev_check_badblocks(struct device_info * dev, const char * device) {
if ( dev->method == METHOD_LOCAL )
return local_check_badblocks(device);
if ( dev->method == METHOD_USB ) {
ERROR("Check for badblocks via USB is not supported");
return -1;
}
return -1;
}
int dev_boot_device(struct device_info * dev, const char * cmdline) {
if ( dev->method == METHOD_LOCAL ) {
ERROR("Booting device on local device does not make sense");
return -1;
}
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_boot_device(dev->usb, cmdline);
else if ( protocol == FLASH_MKII && cmdline && strcmp(cmdline, "update") == 0 )
return mkii_reboot_device(dev->usb, 1);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_reboot_device(struct device_info * dev) {
if ( dev->method == METHOD_LOCAL )
return local_reboot_device();
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_COLD )
return leave_cold_flash(dev->usb);
else if ( protocol == FLASH_NOLO )
return nolo_reboot_device(dev->usb);
else if ( protocol == FLASH_MKII )
return mkii_reboot_device(dev->usb, 0);
else {
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
}
return -1;
}
int dev_get_root_device(struct device_info * dev) {
if ( dev->method == METHOD_LOCAL )
return local_get_root_device();
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_root_device(dev->usb);
}
return -1;
}
int dev_set_root_device(struct device_info * dev, int device) {
if ( dev->method == METHOD_LOCAL )
return local_set_root_device(device);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_root_device(dev->usb, device);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_get_usb_host_mode(struct device_info * dev) {
if ( dev->method == METHOD_LOCAL )
return local_get_usb_host_mode();
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_usb_host_mode(dev->usb);
}
return -1;
}
int dev_set_usb_host_mode(struct device_info * dev, int enable) {
if ( dev->method == METHOD_LOCAL )
return local_set_usb_host_mode(enable);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_usb_host_mode(dev->usb, enable);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_get_rd_mode(struct device_info * dev) {
if ( dev->method == METHOD_LOCAL )
return local_get_rd_mode();
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_rd_mode(dev->usb);
}
return -1;
}
int dev_set_rd_mode(struct device_info * dev, int enable) {
if ( dev->method == METHOD_LOCAL )
return local_set_rd_mode(enable);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_rd_mode(dev->usb, enable);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_get_rd_flags(struct device_info * dev, char * flags, size_t size) {
if ( dev->method == METHOD_LOCAL )
return local_get_rd_flags(flags, size);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_rd_flags(dev->usb, flags, size);
}
return -1;
}
int dev_set_rd_flags(struct device_info * dev, const char * flags) {
if ( dev->method == METHOD_LOCAL )
return local_set_rd_flags(flags);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_rd_flags(dev->usb, flags);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int16_t dev_get_hwrev(struct device_info * dev) {
if ( dev->method == METHOD_LOCAL )
return local_get_hwrev();
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_hwrev(dev->usb);
else if ( protocol == FLASH_MKII )
return mkii_get_hwrev(dev->usb);
}
return -1;
}
int dev_set_hwrev(struct device_info * dev, int16_t hwrev) {
if ( dev->method == METHOD_LOCAL )
return local_set_hwrev(hwrev);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_hwrev(dev->usb, hwrev);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_get_kernel_ver(struct device_info * dev, char * ver, size_t size) {
if ( dev->method == METHOD_LOCAL )
return local_get_kernel_ver(ver, size);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_kernel_ver(dev->usb, ver, size);
}
return -1;
}
int dev_set_kernel_ver(struct device_info * dev, const char * ver) {
if ( dev->method == METHOD_LOCAL )
return local_set_kernel_ver(ver);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_kernel_ver(dev->usb, ver);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_get_initfs_ver(struct device_info * dev, char * ver, size_t size) {
if ( dev->method == METHOD_LOCAL )
return local_get_initfs_ver(ver, size);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_initfs_ver(dev->usb, ver, size);
}
return -1;
}
int dev_set_initfs_ver(struct device_info * dev, const char * ver) {
if ( dev->method == METHOD_LOCAL )
return local_set_initfs_ver(ver);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_initfs_ver(dev->usb, ver);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_get_nolo_ver(struct device_info * dev, char * ver, size_t size) {
if ( dev->method == METHOD_LOCAL )
return local_get_nolo_ver(ver, size);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_nolo_ver(dev->usb, ver, size);
}
return -1;
}
int dev_set_nolo_ver(struct device_info * dev, const char * ver) {
if ( dev->method == METHOD_LOCAL )
return local_set_nolo_ver(ver);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_nolo_ver(dev->usb, ver);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_get_sw_ver(struct device_info * dev, char * ver, size_t size) {
if ( dev->method == METHOD_LOCAL )
return local_get_sw_ver(ver, size);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_sw_ver(dev->usb, ver, size);
else if ( protocol == FLASH_MKII )
return mkii_get_sw_ver(dev->usb, ver, size);
}
return -1;
}
int dev_set_sw_ver(struct device_info * dev, const char * ver) {
if ( dev->method == METHOD_LOCAL )
return local_set_sw_ver(ver);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_sw_ver(dev->usb, ver);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
int dev_get_content_ver(struct device_info * dev, char * ver, size_t size) {
if ( dev->method == METHOD_LOCAL )
return local_get_content_ver(ver, size);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_get_content_ver(dev->usb, ver, size);
}
return -1;
}
int dev_set_content_ver(struct device_info * dev, const char * ver) {
if ( dev->method == METHOD_LOCAL )
return local_set_content_ver(ver);
if ( dev->method == METHOD_USB ) {
enum usb_flash_protocol protocol = dev->usb->flash_device->protocol;
if ( protocol == FLASH_NOLO )
return nolo_set_content_ver(dev->usb, ver);
usb_switch_to_nolo(dev->usb);
return -EAGAIN;
}
return -1;
}
+83
View File
@@ -0,0 +1,83 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPERATIONS_H
#define OPERATIONS_H
#include "image.h"
#include "usb-device.h"
enum connection_method {
METHOD_UNKNOWN = 0,
METHOD_USB,
METHOD_LOCAL,
};
struct device_info {
enum connection_method method;
enum device detected_device;
int16_t detected_hwrev;
struct usb_device_info * usb;
};
struct device_info * dev_detect(void);
void dev_free(struct device_info * dev);
enum device dev_get_device(struct device_info * dev);
int dev_cold_flash_images(struct device_info * dev, struct image * x2nd, struct image * secondary);
int dev_load_image(struct device_info * dev, struct image * image);
int dev_flash_image(struct device_info * dev, struct image * image);
int dev_dump_image(struct device_info * dev, enum image_type image, const char * file);
int dev_check_badblocks(struct device_info * dev, const char * device);
int dev_boot_device(struct device_info * dev, const char * cmdline);
int dev_reboot_device(struct device_info * dev);
int dev_get_root_device(struct device_info * dev);
int dev_set_root_device(struct device_info * dev, int device);
int dev_get_usb_host_mode(struct device_info * dev);
int dev_set_usb_host_mode(struct device_info * dev, int enable);
int dev_get_rd_mode(struct device_info * dev);
int dev_set_rd_mode(struct device_info * dev, int enable);
int dev_get_rd_flags(struct device_info * dev, char * flags, size_t size);
int dev_set_rd_flags(struct device_info * dev, const char * flags);
int16_t dev_get_hwrev(struct device_info * dev);
int dev_set_hwrev(struct device_info * dev, int16_t hwrev);
int dev_get_kernel_ver(struct device_info * dev, char * ver, size_t size);
int dev_set_kernel_ver(struct device_info * dev, const char * ver);
int dev_get_initfs_ver(struct device_info * dev, char * ver, size_t size);
int dev_set_initfs_ver(struct device_info * dev, const char * ver);
int dev_get_nolo_ver(struct device_info * dev, char * ver, size_t size);
int dev_set_nolo_ver(struct device_info * dev, const char * ver);
int dev_get_sw_ver(struct device_info * dev, char * ver, size_t size);
int dev_set_sw_ver(struct device_info * dev, const char * ver);
int dev_get_content_ver(struct device_info * dev, char * ver, size_t size);
int dev_set_content_ver(struct device_info * dev, const char * ver);
#endif
-78
View File
@@ -1,78 +0,0 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int pcs_n = 0;
struct piece_t pcs[10];
int add_piece(char *piece)
{
int i,ok = 0;
char *file;
if (pcs_n==9) {
fprintf(stderr, "Oops...cannot add more pieces. no sense operation!\n");
return 0;
}
file = strchr(piece, '%');
if (file) {
file[0]='\0';
file = file + 1;
for(i=0;pieces[i];i++)
if (!strcmp(pieces[i], piece))
ok = 1;
if (!ok) {
printf("Invalid piece name.\n");
printf("Pieces: ");
for(i=0;pieces[i];i++)
printf("%s ", pieces[i]);
printf("\n");
exit(1);
}
pcs[pcs_n].name = strdup(file);
pcs[pcs_n].type = strdup(piece);
pcs[pcs_n].vers = NULL; // TODO version string not yet supported
} else {
/*/ autodetect piece type */
pcs[pcs_n].type = fpid_file(piece);
if (pcs[pcs_n].type == NULL) {
printf("Use -p [piece]:[file]\n");
printf("Pieces: ");
for(i=0;pieces[i];i++)
printf("%s ", pieces[i]);
printf("\n");
exit(1);
} else {
pcs[pcs_n].name = strdup(piece);
pcs[pcs_n].type = strdup(pcs[pcs_n].type);
pcs[pcs_n].vers = NULL;
}
}
pcs_n++;
return 1;
}
+90
View File
@@ -0,0 +1,90 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
* Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include "global.h"
#include "printf-utils.h"
int printf_prev = 0;
void printf_progressbar(unsigned long long part, unsigned long long total) {
char *columns = getenv("COLUMNS");
int pc;
int tmp, cols = 80;
/* percentage calculation */
pc = total == 0 ? 100 : (int)(part*100/total);
( pc < 0 ) ? pc = 0 : ( pc > 100 ) ? pc = 100 : 0;
PRINTF_BACK();
PRINTF_ADD("\x1b[K %3d%% [", pc);
if ( columns )
cols = atoi(columns);
if ( cols > 115 )
cols = 115;
cols-=15;
for ( tmp = cols*pc/100; tmp; tmp-- ) PRINTF_ADD("#");
for ( tmp = cols-(cols*pc/100); tmp; tmp-- ) PRINTF_ADD("-");
PRINTF_ADD("]");
if ( part == total ) PRINTF_END();
fflush(stdout);
}
void printf_and_wait(const char * format, ...) {
va_list ap;
char c;
fd_set rfds;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
while ( select(1, &rfds, NULL, NULL, &tv) == 1 )
if ( read(0, &c, 1) < 0 )
break;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
fflush(stdout);
FD_ZERO(&rfds);
FD_SET(0, &rfds);
while ( select(1, &rfds, NULL, NULL, NULL) == 1 ) {
if ( read(0, &c, 1) < 0 || c == '\n' )
break;
}
}
+37
View File
@@ -0,0 +1,37 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.com>
* Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PRINTF_UTILS_H
#define PRINTF_UTILS_H
#include "global.h"
extern int printf_prev;
#define PRINTF_BACK() do { if ( printf_prev ) { printf("\r%-*s\r", printf_prev, ""); printf_prev = 0; } } while (0)
#define PRINTF_ADD(...) do { printf_prev += printf(__VA_ARGS__); } while (0)
#define PRINTF_LINE(...) do { PRINTF_BACK(); PRINTF_ADD(__VA_ARGS__); fflush(stdout); } while (0)
#define PRINTF_END() do { if ( printf_prev ) { printf("\n"); printf_prev = 0; } } while (0)
#define PRINTF_ERROR(...) do { PRINTF_END(); ERROR_INFO(__VA_ARGS__); } while (0)
#define PRINTF_ERROR_RETURN(str, ...) do { PRINTF_ERROR("%s", str); return __VA_ARGS__; } while (0)
void printf_progressbar(unsigned long long part, unsigned long long total);
void printf_and_wait(const char * format, ...);
#endif
-193
View File
@@ -1,193 +0,0 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <usb.h>
/* wait for status = 0 */
int get_status()
{
int ret = 0;
if (usb_control_msg(dev, 192, 1, 0, 0, (char *)&ret, 4, 2000) == -1) {
fprintf(stderr, "Cannot get device status.\n");
exit(1);
}
return ret;
}
int get_peripheral_host_mode(int foo)
{
//unsigned short mode = 0;
// XXX BROKEN
#if 0
if (usb_control_msg(dev, 64, 16, 2, 0, 2, 0, 0, 2000)) {
fprintf(stderr, "Cannot query device.\n");
return -1;
}
printf("Device is in \"%s\" mode (%hd)\n", (mode)?"host":"peripheral", mode);
#endif
return 0;
}
/*
* boot the omap mobo
*/
int boot_board(char *cmdline)
{
if (usb_control_msg(dev, CMD_WRITE, 130, 0, 0, cmdline, strlen(cmdline), 2000) == -1) {
fprintf(stderr, "Cannot boot kernel.\n");
perror("boot_board");
return -1;
}
printf("Booting kernel with arguments: '%s'.\n", cmdline);
return 0;
}
/*
* reboot the omap mobo
*/
int reboot_board()
{
// 131 = reboot
if (usb_control_msg(dev, CMD_WRITE, 131, 0, 0, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot reboot board.\n");
return -1;
}
printf("Mobo rebooted!\n");
return 0;
}
int set_rd_mode(unsigned short mode)
{
if (((short)mode)==-1)
return 1;
if (usb_control_msg(dev, CMD_WRITE, 16, mode, 0, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set R&D flags.\n");
return 1;
}
printf("rd mode changed to %s\n", mode?"on":"off");
return 0;
}
// mode = 1 || 0
int set_usb_host_mode(unsigned short mode)
{
if (usb_control_msg(dev, CMD_WRITE, 16, mode, 2, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot change the usb-host mode.\n");
return -1;
}
printf("USB host mode is %s.\n", mode?"enabled":"disabled");
return 0;
}
/*
* query root device
*/
int query_hw_revision()
{
unsigned char string[512];
int i = 0;
if (usb_control_msg(dev, CMD_QUERY, 4, 0, 0, (char *)string, 512, 2000) == -1) {
fprintf(stderr, "Cannot query hw revision.\n");
return -1;
}
printf("HW revision string: '");
for(i=0;i<44;i++) { // XXX ??
if (string[i]==0) {
printf(" ");
} else {
if (string[i]>19)
printf("%c", string[i]);
}
}
printf("'\n");
return 0;
}
int query_rdmode_device()
{
char isrd = 1;
if (usb_control_msg(dev, CMD_QUERY, 17, 0, 0, (char *)&isrd, 1, 2000) == -1) {
fprintf(stderr, "Cannot query rd mode.\n");
return -1;
}
printf("RD mode is: %s\n", isrd?"on":"off");
return isrd;
}
int query_root_device()
{
unsigned char opcode;
if (usb_control_msg(dev, 192, 17, 0, 1, (char *)&opcode, 1, 2000) < 0) {
fprintf(stderr, "Cannot query root device\n");
return -1;
}
if (opcode>2) { // use sizeof || enum
printf("Invalid root device received from the device '%d'.\n", opcode);
}
printf("Root device is: %s\n", root_devices[opcode]);
return 0;
}
int query_nolo_version()
{
unsigned int version; // ensure uint is at least 32 bits
//if (usb_control_msg(dev, 192, 3, 0, 1, (char *)&version, 4 , 2000) < 0) {
if (usb_control_msg(dev, 192, 3, 0, 0, (char *)&version, 4 , 2000) < 0) {
fprintf(stderr, "Cannot query nolo version. Old bootloader version?\n");
exit(1);
}
printf("NOLO Version %d.%d.%d\n",
version >> 20 & 15,
version >> 16 & 15,
version >> 8 & 255);
if ((version & 255)> 1)
printf("Invalid API version (%d)\n", version&255);
return 0;
}
+447
View File
@@ -0,0 +1,447 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Enable RTLD_DEFAULT for glibc */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <dlfcn.h>
#include "global.h"
#include "device.h"
#include "usb-device.h"
#include "printf-utils.h"
#include "nolo.h"
#include "cold-flash.h"
#include "mkii.h"
#ifdef __linux__
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
#include <sys/ioctl.h>
#endif
#endif
static struct usb_flash_device usb_devices[] = {
{ 0x0421, 0x0096, -1, -1, -1, FLASH_DISK, { DEVICE_RX_44, 0 } },
{ 0x0421, 0x0105, 2, 1, -1, FLASH_NOLO, { DEVICE_SU_18, DEVICE_RX_34, DEVICE_RX_44, DEVICE_RX_48, DEVICE_RX_51, DEVICE_RM_680, DEVICE_RM_696, 0 } },
{ 0x0421, 0x0106, 0, -1, -1, FLASH_COLD, { DEVICE_RX_51, DEVICE_RM_680, DEVICE_RM_696, 0 } },
{ 0x0421, 0x0189, -1, -1, -1, FLASH_DISK, { DEVICE_RX_48, 0 } },
{ 0x0421, 0x01c7, -1, -1, -1, FLASH_DISK, { DEVICE_RX_51, 0 } },
{ 0x0421, 0x01c8, 1, 1, -1, FLASH_MKII, { DEVICE_RX_51, DEVICE_RM_680, 0 } },
{ 0x0421, 0x03d1, -1, -1, -1, FLASH_DISK, { DEVICE_RM_680, 0 } },
{ 0x0421, 0x0431, -1, -1, -1, FLASH_DISK, { DEVICE_SU_18, DEVICE_RX_34, 0 } },
{ 0x0421, 0x04c3, -1, -1, -1, FLASH_DISK, { DEVICE_RX_34, 0 } },
{ 0x0421, 0x3f00, 2, 1, -1, FLASH_NOLO, { DEVICE_RX_34, 0 } },
};
static const char * usb_flash_protocols[] = {
[FLASH_NOLO] = "NOLO",
[FLASH_COLD] = "Cold flashing",
[FLASH_MKII] = "Mk II protocol",
[FLASH_DISK] = "RAW disk",
};
const char * usb_flash_protocol_to_string(enum usb_flash_protocol protocol) {
if ( protocol >= sizeof(usb_flash_protocols)/sizeof(usb_flash_protocols[0]) )
return NULL;
return usb_flash_protocols[protocol];
}
static void usb_flash_device_info_print(const struct usb_flash_device * dev) {
int i;
PRINTF_ADD("USB device: %s", device_to_string(dev->devices[0]));
for ( i = 1; dev->devices[i]; ++i )
PRINTF_ADD("/%s", device_to_string(dev->devices[i]));
PRINTF_ADD(" (%#04x:%#04x) in %s mode", dev->vendor, dev->product, usb_flash_protocol_to_string(dev->protocol));
}
static void usb_reattach_kernel_driver(usb_dev_handle * udev, int interface) {
#ifdef __linux__
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
struct {
int ifno;
int ioctl_code;
void * data;
} command = {
.ifno = interface,
.ioctl_code = _IO('U', 23),
.data = NULL,
};
if ( interface < 0 )
return;
usb_release_interface(udev, interface);
ioctl(*((int *)udev), _IOWR('U', 18, command), &command);
#endif
#endif
}
static void usb_descriptor_info_print(usb_dev_handle * udev, struct usb_device * dev, char * product, size_t size) {
char buf[1024];
char buf2[1024];
unsigned int x;
int ret;
int i;
memset(buf, 0, sizeof(buf));
usb_get_string_simple(udev, dev->descriptor.iProduct, buf, sizeof(buf));
PRINTF_LINE("USB device product string: %s", buf[0] ? buf : "(not detected)");
PRINTF_END();
if ( product && buf[0] )
strncpy(product, buf, size);
memset(buf, 0, sizeof(buf));
memset(buf2, 0, sizeof(buf2));
ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber, buf, sizeof(buf));
if ( ! isalnum(buf[0]) )
buf[0] = 0;
for ( i = 0; i < ret; i+=2 ) {
sscanf(buf+i, "%2x", &x);
if ( x > 32 && x < 128 )
buf2[i/2] = x;
else {
buf2[0] = 0;
break;
}
}
if ( ! isalnum(buf2[0]) )
buf2[0] = 0;
PRINTF_LINE("USB device serial number string: %s", buf2[0] ? buf2 : ( buf[0] ? buf : "(not detected)" ));
PRINTF_END();
}
static struct usb_device_info * usb_device_is_valid(struct usb_device * dev) {
int i;
char product[1024];
struct usb_device_info * ret = NULL;
for ( i = 0; usb_devices[i].vendor; ++i ) {
if ( dev->descriptor.idVendor == usb_devices[i].vendor && dev->descriptor.idProduct == usb_devices[i].product ) {
printf("\b\b ");
PRINTF_END();
PRINTF_ADD("Found ");
usb_flash_device_info_print(&usb_devices[i]);
PRINTF_END();
PRINTF_LINE("Opening USB...");
usb_dev_handle * udev = usb_open(dev);
if ( ! udev ) {
PRINTF_ERROR("usb_open failed");
fprintf(stderr, "\n");
return NULL;
}
usb_descriptor_info_print(udev, dev, product, sizeof(product));
if ( usb_devices[i].interface >= 0 ) {
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
PRINTF_LINE("Detaching kernel from USB interface...");
usb_detach_kernel_driver_np(udev, usb_devices[i].interface);
#endif
PRINTF_LINE("Claiming USB interface...");
if ( usb_claim_interface(udev, usb_devices[i].interface) < 0 ) {
PRINTF_ERROR("usb_claim_interface failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
return NULL;
}
}
if ( usb_devices[i].alternate >= 0 ) {
PRINTF_LINE("Setting alternate USB interface...");
if ( usb_set_altinterface(udev, usb_devices[i].alternate) < 0 ) {
PRINTF_ERROR("usb_claim_interface failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
return NULL;
}
}
if ( usb_devices[i].configuration >= 0 ) {
PRINTF_LINE("Setting USB configuration...");
if ( usb_set_configuration(udev, usb_devices[i].configuration) < 0 ) {
PRINTF_ERROR("usb_set_configuration failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
return NULL;
}
}
ret = calloc(1, sizeof(struct usb_device_info));
if ( ! ret ) {
ALLOC_ERROR();
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
return NULL;
}
if ( strcmp(product, "Nokia 770") == 0 || strcmp(product, "Nokia 770 (Update mode)") == 0 )
ret->device = DEVICE_SU_18;
else if ( strcmp(product, "Nokia N800 Internet Tablet") == 0 || strcmp(product, "Nokia N800 (Update mode)") == 0 )
ret->device = DEVICE_RX_34;
else if ( strcmp(product, "Nokia N810 Internet Tablet") == 0 || strcmp(product, "Nokia N810 (Update mode)") == 0 )
ret->device = DEVICE_RX_44;
else if ( strcmp(product, "Nokia N810 Internet Tablet WiMAX Edition") == 0 || strcmp(product, "Nokia-RX48 (Update mode)") == 0 )
ret->device = DEVICE_RX_48;
else if ( strcmp(product, "N900 (Storage Mode)") == 0 || strcmp(product, "Nokia N900 (Update mode)") == 0 || strcmp(product, "N900 (PC-Suite Mode)") == 0 )
ret->device = DEVICE_RX_51;
else if ( strcmp(product, "Nokia N950") == 0 || strcmp(product, "Sync Mode") == 0 || strcmp(product, "N950 (Update mode)") == 0 )
ret->device = DEVICE_RM_680;
else if ( strcmp(product, "N9 (Update mode)") == 0 || strcmp(product, "Nxy (Update mode)") == 0 )
ret->device = DEVICE_RM_696;
else if ( strcmp(product, "Nokia USB ROM") == 0 )
ret->device = DEVICE_ANY;
else
ret->device = DEVICE_UNKNOWN;
if ( device_to_string(ret->device) )
PRINTF_LINE("Detected USB device: %s", device_to_string(ret->device));
else
PRINTF_LINE("Detected USB device: (not detected)");
PRINTF_END();
if ( ! noverify && ret->device == DEVICE_UNKNOWN ) {
ERROR("Device detection failed");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
free(ret);
return NULL;
}
if ( ! noverify && ret->device != DEVICE_ANY ) {
enum device * device;
for ( device = usb_devices[i].devices; *device; ++device )
if ( *device == ret->device )
break;
if ( ! *device ) {
ERROR("Device mishmash");
fprintf(stderr, "\n");
usb_reattach_kernel_driver(udev, usb_devices[i].interface);
usb_close(udev);
free(ret);
return NULL;
}
}
ret->hwrev = -1;
ret->flash_device = &usb_devices[i];
ret->udev = udev;
break;
}
}
return ret;
}
static struct usb_device_info * usb_search_device(struct usb_device * dev, int level) {
int i;
struct usb_device_info * ret = NULL;
if ( ! dev )
return NULL;
ret = usb_device_is_valid(dev);
if ( ret )
return ret;
for ( i = 0; i < dev->num_children; i++ ) {
ret = usb_search_device(dev->children[i], level + 1);
if ( ret )
break;
}
return ret;
}
static volatile sig_atomic_t signal_quit;
static void signal_handler(int signum) {
signal_quit = 1;
(void)signum;
}
struct usb_device_info * usb_open_and_wait_for_device(void) {
struct usb_bus * bus;
struct usb_device_info * ret = NULL;
int i = 0;
void (*prev)(int);
static char progress[] = {'/','-','\\', '|'};
if ( dlsym(RTLD_DEFAULT, "libusb_init") )
ERROR_RETURN("You are trying to use broken libusb-1.0 library (either directly or via wrapper) which has slow listing of usb devices. It cannot be used for flashing or cold-flashing. Please use libusb 0.1.", NULL);
usb_init();
usb_find_busses();
PRINTF_BACK();
printf("\n");
signal_quit = 0;
prev = signal(SIGINT, signal_handler);
while ( ! signal_quit ) {
PRINTF_LINE("Waiting for USB device... %c", progress[++i%sizeof(progress)]);
usb_find_devices();
for ( bus = usb_get_busses(); bus; bus = bus->next ) {
if ( bus->root_dev )
ret = usb_search_device(bus->root_dev, 0);
else {
struct usb_device *dev;
for ( dev = bus->devices; dev; dev = dev->next ) {
ret = usb_search_device(dev, 0);
if ( ret )
break;
}
}
if ( ret )
break;
}
if ( ret )
break;
SLEEP(0xc350); // 0.5s
}
if ( prev != SIG_ERR )
signal(SIGINT, prev);
PRINTF_BACK();
printf("\n");
if ( ! ret )
return NULL;
return ret;
}
void usb_close_device(struct usb_device_info * dev) {
if ( dev->flash_device->protocol != FLASH_COLD )
usb_reattach_kernel_driver(dev->udev, dev->flash_device->interface);
usb_close(dev->udev);
free(dev);
}
void usb_switch_to_nolo(struct usb_device_info * dev) {
printf("\nSwitching to NOLO mode...\n");
if ( dev->flash_device->protocol == FLASH_COLD )
leave_cold_flash(dev);
else if ( dev->flash_device->protocol == FLASH_MKII )
mkii_reboot_device(dev, 0);
else if ( dev->flash_device->protocol == FLASH_DISK )
printf_and_wait("Unplug USB cable, turn device off, press ENTER and plug USB cable again");
}
void usb_switch_to_cold(struct usb_device_info * dev) {
printf("\nSwitching to Cold Flash mode...\n");
if ( dev->flash_device->protocol == FLASH_NOLO )
nolo_reboot_device(dev);
else if ( dev->flash_device->protocol == FLASH_MKII )
mkii_reboot_device(dev, 0);
else if ( dev->flash_device->protocol == FLASH_DISK )
printf_and_wait("Unplug USB cable, turn device off, press ENTER and plug USB cable again");
}
void usb_switch_to_update(struct usb_device_info * dev) {
printf("\nSwitching to Update mode...\n");
if ( dev->flash_device->protocol == FLASH_COLD )
leave_cold_flash(dev);
else if ( dev->flash_device->protocol == FLASH_NOLO )
nolo_boot_device(dev, "update");
else if ( dev->flash_device->protocol == FLASH_MKII && ! ( dev->data & MKII_UPDATE_MODE ) )
mkii_reboot_device(dev, 1);
else if ( dev->flash_device->protocol == FLASH_DISK )
printf_and_wait("Unplug USB cable, turn device off, press ENTER and plug USB cable again");
}
void usb_switch_to_disk(struct usb_device_info * dev) {
printf("\nSwitching to RAW disk mode...\n");
if ( dev->flash_device->protocol == FLASH_COLD )
leave_cold_flash(dev);
else if ( dev->flash_device->protocol == FLASH_NOLO ) {
nolo_boot_device(dev, NULL);
printf_and_wait("Wait until device start, choose USB Mass Storage Mode and press ENTER");
} else if ( dev->flash_device->protocol == FLASH_MKII ) {
if ( dev->data & MKII_UPDATE_MODE )
mkii_reboot_device(dev, 0);
else
printf_and_wait("Unplug USB cable, plug again, choose USB Mass Storage Mode and press ENTER");
}
}
+74
View File
@@ -0,0 +1,74 @@
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2012 Pali Rohár <pali.rohar@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef USB_DEVICE_H
#define USB_DEVICE_H
#include <stdint.h>
/* u_int*_t types are not defined without _GNU_SOURCE but usb.h needs them */
#define u_int8_t uint8_t
#define u_int16_t uint16_t
#define u_int32_t uint32_t
#include <usb.h>
#define USB_READ_EP (USB_ENDPOINT_IN | 0x1)
#define USB_WRITE_EP (USB_ENDPOINT_OUT | 0x1)
#define USB_WRITE_DATA_EP (USB_ENDPOINT_OUT | 0x2)
#include "device.h"
enum usb_flash_protocol {
FLASH_UNKN = 0,
FLASH_NOLO,
FLASH_COLD,
FLASH_MKII,
FLASH_DISK,
FLASH_COUNT,
};
struct usb_flash_device {
uint16_t vendor;
uint16_t product;
int interface;
int alternate;
int configuration;
enum usb_flash_protocol protocol;
enum device devices[DEVICE_COUNT];
};
struct usb_device_info {
enum device device;
int16_t hwrev;
const struct usb_flash_device * flash_device;
usb_dev_handle * udev;
int data;
};
const char * usb_flash_protocol_to_string(enum usb_flash_protocol protocol);
struct usb_device_info * usb_open_and_wait_for_device(void);
void usb_close_device(struct usb_device_info * dev);
void usb_switch_to_nolo(struct usb_device_info * dev);
void usb_switch_to_cold(struct usb_device_info * dev);
void usb_switch_to_update(struct usb_device_info * dev);
void usb_switch_to_disk(struct usb_device_info * dev);
#endif
-57
View File
@@ -1,57 +0,0 @@
/*
* Copyright (C) 2007
* pancake <pancake@youterm.com>
*
* 0xFFFF is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 0xFFFF is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0xFFFF; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "main.h"
#include <usb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned long get_file_size(char *file)
{
FILE *fd = fopen(file, "r");
unsigned long len = 0;
if (fd == NULL) {
fprintf(stderr, "Cannot open file '%s'\n", file);
exit(1);
}
fseek(fd, 0, SEEK_END);
len = ftell(fd);
fclose(fd);
return len;
}
void progressbar(unsigned long long part, unsigned long long total)
{
char *columns = getenv("COLUMNS");
int pc;
int tmp, cols = 80;
pc = (int)(part*100/total);
(pc<0)?pc=0:(pc>100)?pc=100:0;
printf("\e[K %3d%% [", pc);
if (columns)
cols = atoi(columns);
cols-=15;
for(tmp=cols*pc/100;tmp;tmp--) printf("#");
for(tmp=cols-(cols*pc/100);tmp;tmp--) printf("-");
printf("]\r");
fflush(stdout);
}