217 Commits
Author SHA1 Message Date
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
49 changed files with 7477 additions and 3132 deletions

No files matched your search

+4 -7
View File
@@ -1,9 +1,6 @@
VERSION=0.5
PREFIX=/usr/local
VERSION = 0.6
PREFIX = /usr/local
# NetBSD stuff
CFLAGS+=-I/usr/pkg/include -g -O2
LDFLAGS+=-L/usr/pkg/lib -Wl,-R/usr/pkg/lib
HAVE_USB=1
HAVE_GUI=1
#CFLAGS += -I/usr/pkg/include -g -O2
#LDFLAGS += -L/usr/pkg/lib -Wl,-R/usr/pkg/lib
+13 -5
View File
@@ -1,11 +1,19 @@
Copyright (C) 2007-2011 pancake <pancake@youterm.com>
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
SPECS FOR TEH FIASCO FIRMWARE FILE FORMAT ffff!
SPECS FOR THE FIASCO FIRMWARE FILE FORMAT ffff!
-----------------------------------------------
These notes has not been taken properly and may be wrong. It must
be revised to fit the reality. But this is mostly a general idea:
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 FIASO 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 subsectin...
FILE HEADER
@@ -38,12 +46,12 @@ IMAGE
block {
1 byte -- type of subsection block
'1' - version
'2' - device & hw revisions (separated by char 0x00, max size of device is 16, hw revision 8)
'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 (maybe end of subsections?)
1 byte -- unknown (0x00 is accepted, maybe end of subsections?)
N bytes -- image data
+90
View File
@@ -0,0 +1,90 @@
Copyright (C) 2012 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)
For every (request) message which is send by host, server send back responce.
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
4 bytes -- type of message
N bytes -- data
Reply message data always starts with char 0x00 (except pong 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 = 0x00000000
res_type = 0x20000000
Get protocol version:
req_type = 0x01010000
req_data = "/update/protocol_version"
res_type = 0x21010000
res_data = 0x00 "2"
Tell our protocol version:
req_type = 0x02020000
req_data = "/update/host_protocol_version" 0x00 "2"
res_type = 0x22020000
res_data = 0x00
Get device:
req_type = 0x01030000
req_data = "/device/product_code"
res_type = 0x21030000
res_data = 0x00 "RX-51"
Get hwrev:
req_type = 0x01040000
req_data = "/device/hw_build"
res_type = 0x21040000
res_data = 0x00 "2101"
Get image types:
req_type = 0x01050000
req_data = "/update/supported_images"
res_type = 0x21050000
res_data = 0x00 "xloader,secondary,kernel,mmc,cmt-2nd,cmt-algo,cmt-mcusw"
Reboot device:
req_type = 0x0C060000
req_data = "reboot"
res_type = 0x2C060000
res_data = 0x00
+11 -20
View File
@@ -1,28 +1,19 @@
include ../config.mk
OBJ=main.o fiasco.o hexdump.o dump.o flash.o serial.o qmode.o
OBJ+=hash.o fpid.o query.o pieces.o utils.o devices.o console.o
OBJ+=squeue/squeue.o
BIN=0xFFFF
#LIBS=`${HAVE_USB} && echo -- '-lusb'`
LIBS=`if [ "${HAVE_USB}" = 1 ]; then echo '-lusb'; fi`
CFLAGS+=-DVERSION=\"${VERSION}\" -Wall -I .
CFLAGS+=-pedantic -std=c99 -DHAVE_USB=${HAVE_USB} -Wno-unused-result
USBOBJ=../libusb/error.o ../libusb/usb.o ../libusb/descriptors.o
USBOBJ+=../libusb/linux.o ## XXX not portable
CFLAGS+=-I../libusb
LDFLAGS+=-L../libusb
CPPFLAGS += -DVERSION=\"$(VERSION)\" -D_GNU_SOURCE -I.
CFLAGS += -W -Wall -O2 -pedantic -std=c99
LIBS += -lm -lusb
all: ${BIN}
OBJS = main.o nolo.o printf-utils.o image.o fiasco.o device.o usb-device.o cold-flash.o qmode.o console.o squeue/squeue.o operations.o local.o mkii.o disk.o cal.o
BIN = 0xFFFF
${BIN}: ${OBJ}
${CC} ${LDFLAGS} -o ${BIN} ${OBJ} ${LIBS}
all: $(BIN)
allusb: ${OBJ}
${CC} ${LDFLAGS} -o ${BIN} ${OBJ} ${USBOBJ}
$(BIN): $(OBJS) Makefile ../config.mk
$(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN) $(OBJS) $(LIBS)
static: ${OBJ}
${CC} ${LDFLAGS} -o ${BIN} -static ${OBJ} ${USBOBJ}
%.o: %.c Makefile ../config.mk
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
clean:
-rm -f ${OBJ} ${BIN}
-rm -f $(OBJS) $(BIN)
+263
View File
@@ -0,0 +1,263 @@
/*
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/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <mtd/mtd-user.h>
#include "cal.h"
#define MAX_SIZE 393216
#define INDEX_LAST (0xFF + 1)
#define HDR_MAGIC "ConF"
struct cal {
int fd;
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;
mtd_info_t mtd_info;
if ( stat(file, &st) != 0 )
return -1;
fd = open(file, O_RDONLY);
if ( fd < 0 )
return -1;
if ( S_ISREG(st.st_mode) )
size = st.st_size;
else if ( S_ISBLK(st.st_mode) ) {
if ( ioctl(fd, BLKGETSIZE64, &blksize) != 0 )
goto err;
if ( blksize > SSIZE_MAX )
goto err;
size = blksize;
} else 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;
}
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->fd = fd;
cal->mem = mem;
cal->size = size;
*cal_out = cal;
return 0;
err:
close(fd);
free(mem);
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;
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;
*ptr = data + find_offset + sizeof(struct header);
*len = hdr->length;
if ( crc32(0, *ptr, *len) != hdr->datasum )
return -1;
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
+410
View File
@@ -0,0 +1,410 @@
/*
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 <usb.h>
#include "global.h"
#include "cold-flash.h"
#include "image.h"
#include "usb-device.h"
#include "printf-utils.h"
#define READ_DEV 0x81
#define WRITE_DEV 0x01
#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 Periheral Booting */
/* Omap Peripheral boot message */
static const uint32_t omap_peripheral_msg = 0xF0030002;
/* 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;
/* 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 */
};
#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, readed;
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);
readed = 0;
while ( readed < image->size ) {
need = image->size - readed;
if ( need > sizeof(buffer) )
need = sizeof(buffer);
ret = image_read(image, buffer, need);
if ( ret == 0 )
break;
msg.crc1 = crc32(buffer, ret, msg.crc1);
readed += 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, READ_DEV, (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, readed;
int ret;
printf("Sending OMAP peripheral boot message...\n");
ret = usb_bulk_write(udev, WRITE_DEV, (char *)&omap_peripheral_msg, sizeof(omap_peripheral_msg), WRITE_TIMEOUT);
usleep(5000);
if ( ret != sizeof(omap_peripheral_msg) )
ERROR_RETURN("Sending OMAP peripheral boot message failed", -1);
printf("Sending 2nd X-Loader image size...\n");
ret = usb_bulk_write(udev, WRITE_DEV, (char *)&image->size, 4, WRITE_TIMEOUT);
usleep(5000);
if ( ret != 4 )
ERROR_RETURN("Sending 2nd X-Loader image size failed", -1);
printf("Sending 2nd X-Loader image...\n");
printf_progressbar(0, image->size);
image_seek(image, 0);
readed = 0;
while ( readed < image->size ) {
need = image->size - readed;
if ( need > sizeof(buffer) )
need = sizeof(buffer);
ret = image_read(image, buffer, need);
if ( ret == 0 )
break;
if ( usb_bulk_write(udev, WRITE_DEV, (char *)buffer, ret, WRITE_TIMEOUT) != ret )
PRINTF_ERROR_RETURN("Sending 2nd X-Loader image failed", -1);
readed += ret;
printf_progressbar(readed, image->size);
}
usleep(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, readed;
int ret;
init_msg = xloader_msg_create(XLOADER_MSG_TYPE_SEND, image);
printf("Sending X-Loader init message...\n");
ret = usb_bulk_write(udev, WRITE_DEV, (char *)&init_msg, sizeof(init_msg), WRITE_TIMEOUT);
usleep(5000);
if ( ret != sizeof(init_msg) )
ERROR_RETURN("Sending X-Loader init message failed", -1);
printf("Waiting for X-Loader response...\n");
ret = usb_bulk_read(udev, READ_DEV, (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);
readed = 0;
while ( readed < image->size ) {
need = image->size - readed;
if ( need > sizeof(buffer) )
need = sizeof(buffer);
ret = image_read(image, buffer, need);
if ( ret == 0 )
break;
if ( usb_bulk_write(udev, WRITE_DEV, (char *)buffer, ret, WRITE_TIMEOUT) != ret )
PRINTF_ERROR_RETURN("Sending Secondary image failed", -1);
readed += ret;
printf_progressbar(readed, image->size);
}
usleep(5000);
printf("Waiting for X-Loader response...\n");
ret = usb_bulk_read(udev, READ_DEV, (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, WRITE_DEV, (char *)&ping_msg, sizeof(ping_msg), WRITE_TIMEOUT);
if ( ret != sizeof(ping_msg) )
ERROR_RETURN("Sending X-Loader ping message faild", -1);
printf("Waiting for X-Loader pong response...\n");
while ( try_read > 0 ) {
uint32_t ping_read;
ret = usb_bulk_read(udev, READ_DEV, (char *)&ping_read, sizeof(ping_read), READ_TIMEOUT);
if ( ret == sizeof(ping_read) ) {
printf("Got it\n");
pong = 1;
break;
}
usleep(5000);
--try_read;
}
if ( pong )
break;
printf("Responce 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;
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);
/* ID Subblock - header */
if ( memcmp(asic_buffer+1, "\x01\x05\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* ID Subblock - OMAP chip version (check for OMAP35x) */
if ( memcmp(asic_buffer+4, "\x34\x30\x07", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* Reserved1 - header */
if ( memcmp(asic_buffer+8, "\x13\x02\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* 2nd ID Subblock - header */
if ( memcmp(asic_buffer+12, "\x12\x15\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* Reserved2 - header */
if ( memcmp(asic_buffer+35, "\x14\x15\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
/* Checksum subblock - header */
if ( memcmp(asic_buffer+58, "\x15\x09\x01", 3) != 0 )
ERROR_RETURN("Invalid ASIC ID", -1);
printf("Detected OMAP35x chip\n");
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, WRITE_DEV, (char *)&omap_memory_msg, sizeof(omap_memory_msg), WRITE_TIMEOUT);
usleep(5000);
if ( ret != sizeof(omap_memory_msg) )
ERROR_RETURN("Sending OMAP memory boot message failed", -1);
usleep(250000);
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
+59 -67
View File
@@ -1,6 +1,7 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007, 2008 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
@@ -16,21 +17,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if HAVE_USB
#include "main.h"
#include "query.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
void cmd_exit(char *line)
{
#include "global.h"
#include "console.h"
static void cmd_exit(char *line) {
exit(0);
(void)line;
}
void cmd_help(char *line)
{
static void cmd_help(char *line) {
printf("connect connects via usb to nolo\n");
printf("reboot reboots remote host\n");
printf("info shows info of the remote system\n");
@@ -42,25 +43,16 @@ void cmd_help(char *line)
printf(" f.ex: nanddump /dev/mtd0 0x0 0x4000 xloader.bin 1 1\n");
printf("exit exits the shell\n");
fflush(stdout);
(void)line;
}
void cmd_info(char *line)
{
char *p, str[128];
get_sw_version();
get_hw_revision(str, 128); // get hardware revision:
p = strstr(str, "hw_rev:");
if (p) // TODO: delimit string by comma
printf("SubVersionString autodetected: '%s'\n", p+7);
else printf("SubVersionString autodetected: (error)\n");
get_root_device(); // only for flashing
get_usb_mode();
get_rd_mode();
get_rd_flags();
static void cmd_info(char *line) {
/* TODO */
(void)line;
}
void cmd_nanddump(char *line)
{
static void cmd_nanddump(char *line) {
char dev[128];
int from;
int length;
@@ -72,58 +64,54 @@ void cmd_nanddump(char *line)
(char *)&dev, (unsigned int*)&from, (unsigned int *)&length,
(char *)&out, (int*)&ignbb, (int *)&ignoob);
if (ignoob == -1) {
eprintf("Invalid arguments.\n");
eprintf("nanddump [dev] [start] [len] [out] [ignore-badblocks] [ignore-oob]\n");
eprintf(" f.ex: nanddump /dev/mtd0 0x0 0x4000 xloader.bin 1 1\n");
} else
nanddump(dev, from, length, out, ignbb, ignoob);
/* TODO */
}
void cmd_dump(char *line)
{
if (!line[0]) {
static void cmd_dump(char *line) {
if ( ! line[0] ) {
printf("Usage: dump [path]\n");
return;
}
while(line[0]==' ') line = line +1;
reverse_extract_pieces(line);
while ( line[0] == ' ' )
++line;
/* TODO */
}
void cmd_badblocks(char *line)
{
if (!line[0]) {
printf("Usage: dump [path]\n");
static void cmd_badblocks(char *line) {
if ( ! line[0] ) {
printf("Usage: badblocks [path]\n");
return;
}
while(line[0]==' ') line = line +1;
check_badblocks(line);
while ( line[0] == ' ' )
++line;
/* TODO */
}
void cmd_connect(char *line)
{
connect_via_usb();
static void cmd_connect(char *line) {
/* TODO */
(void)line;
}
void cmd_reboot(char *line)
{
reboot_board();
static void cmd_reboot(char *line) {
/* TODO */
(void)line;
}
void cmd_shell(char *line)
{
static void cmd_shell(char *line) {
system("/bin/sh");
(void)line;
}
#define CMDS 11
#define IS_CMD(x) !strcmp(console_commands[i].name, x)
#define CALL_CMD(x) console_commands[x].callback((char *)line)
#define FOREACH_CMD(x) for(x=0;x<CMDS;x++)
struct cmd_t {
static struct cmd_t {
char *name;
void (*callback)(char *);
} console_commands[CMDS] = {
} console_commands[] = {
{ .name = "exit", .callback = &cmd_exit },
{ .name = "q", .callback = &cmd_exit },
{ .name = "connect", .callback = &cmd_connect },
@@ -137,38 +125,42 @@ struct cmd_t {
{ .name = "shell", .callback = &cmd_shell }
};
static int console_command(const char *line)
{
int i;
static int console_command(char *line) {
size_t i;
char command[11];
command[0] = '\0';
sscanf(line, "%10s", command);
line = line + strlen(command);
FOREACH_CMD(i)
if (IS_CMD(command))
CALL_CMD(i);
//
for ( i = 0; i < (sizeof(console_commands)/sizeof(console_commands[0])); ++i )
if ( strcmp(console_commands[i].name, command) == 0 )
console_commands[i].callback(line);
return 1;
}
int console_prompt()
{
int console_prompt(void) {
char line[1024];
do {
write(1, "0xFFFF> ", 8);
line[0] = '\0';
fgets(line, 1024, stdin);
if (feof(stdin)) {
if ( feof(stdin) ) {
write(1, "\n", 1);
break;
}
if (line[0]) line[strlen(line)-1] = '\0';
if ( line[0] )
line[strlen(line)-1] = '\0';
line[1023] = '\0';
} while(console_command(line));
} while ( console_command(line) );
return 0;
}
#endif
+25
View File
@@ -0,0 +1,25 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007, 2008 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 CONSOLE_H
#define CONSOLE_H
int console_prompt(void);
#endif
+329
View File
@@ -0,0 +1,329 @@
/*
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 <math.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",
};
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",
};
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 += log10(hwrevs[i]+1)+2;
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;
}
+59
View File
@@ -0,0 +1,59 @@
/*
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_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
-126
View File
@@ -1,126 +0,0 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007-2009 pancake <pancake@nopcode.org>
* 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/>.
*/
#if HAVE_USB
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* The internet tablet PC (and probably most of
* Nokia devices have different USB-IDs depending
* on the boot state.
*
* The following table shows this info:
*
* omap-rom nolo flash-mode mass-stor pc-suite
* 770 0421:0105 0421:0431
* n800 0421:04c3 0421:0431
* n810 0421:0105
* n900 0421:0106 0421:0105 0421:01c8 0421:01c7 0421:01c8
*
* mode images protocol
* omap-rom 2nd, secondary OMAP messages + Nokia X-Loader protocol
* nolo all except mmc NOLO
* flash-mode mmc MK II
* mass-storage sd, first emmc Standard USB Mass Storage
* pc-suite mmc MK II
*
*/
struct devices supported_devices[SUPPORTED_DEVICES] = {
{ "FFFF", 0x0000, 0x0000, FLASH_NORMAL }, // dummy
{ "unkn", 0x0421, 0x3f00, FLASH_NORMAL }, // probably a development board
{ "n800", 0x0421, 0x04c3, FLASH_NORMAL }, // n800
{ "770/n810/n900", 0x0421, 0x0105, FLASH_NORMAL }, // 770, n810, n900
{ "n900", 0x0421, 0x0106, FLASH_COLD }, // n900 cold flashing
{ "n900", 0x0421, 0x01c8, FLASH_MKII }, // n900 mmc flashing
{ "770/n800", 0x0421, 0x0431, FLASH_DISK }, // 770, n800 usb mass storage
{ "n900", 0x0421, 0x01c7, FLASH_DISK }, // n900 usb mass storage
{ NULL },
{ NULL }
};
/** Returns 0 when no device was found and a positive
* non-zero value when one was found.
*
* The return value is the index into the supported_devices
* array which denotes the device which was found.
*/
int is_valid_device(struct usb_device_descriptor *udd)
{
int i;
struct devices ptr = supported_devices[1];
for(i=1 ; ptr.vendor_id; ptr = supported_devices[++i])
if ((udd->idVendor == ptr.vendor_id)
&& (udd->idProduct == ptr.product_id)) {
D printf("found %s\n", supported_devices[i].name);
return i;
}
return 0;
}
/*
* List all supported device-ids and it's names
*
*/
void list_valid_devices()
{
int i;
struct devices ptr = supported_devices[1];
for(i=1; ptr.name; ptr = supported_devices[++i])
printf("%04x:%04x %s\n", ptr.vendor_id, ptr.product_id, ptr.name);
}
/*
* Returns true (1) when a valid usb device is found and stores the udd and devices
* structures for the specified device.
* Otherwise returns false (0)
*/
int usb_device_found(struct usb_device_descriptor *udd, struct devices *it_device)
{
int dev_index = 0;
struct usb_bus *bus;
if ((usb_find_busses()<0) || (usb_find_devices()==-1)) {
fprintf(stderr, "\nerror: no usb bus or device found.\n");
exit(1);
} else {
for (bus = usb_busses; bus; bus = bus->next) {
struct usb_device *dev = bus->devices;
D printf("bus: \n");
for (; dev; dev = dev->next) {
*udd = dev->descriptor;
D printf(" dev (%s) - ", dev->filename);
D printf("vendor: %04x product: %04x\n", udd->idVendor, udd->idProduct);
if ((dev_index = is_valid_device(udd))) {
device = dev;
printf("%s found!\n", dev->filename);
*it_device = supported_devices[dev_index];
return 1;
}
}
}
}
return 0;
}
#endif
+188
View File
@@ -0,0 +1,188 @@
/*
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 <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/statvfs.h>
#include <linux/fs.h>
#include "disk.h"
#include "global.h"
#include "image.h"
#include "device.h"
#include "usb-device.h"
#include "printf-utils.h"
static char global_buf[1 << 22]; /* 4MB */
int disk_init(struct usb_device_info * dev) {
ERROR("RAW mode is not implemented yet");
(void)dev;
return -1;
}
enum device disk_get_device(struct usb_device_info * dev) {
ERROR("Not implemented yet");
(void)dev;
return DEVICE_UNKNOWN;
}
int disk_flash_raw(const char * blkdev, const char * file) {
ERROR("Not implemented yet");
(void)blkdev;
(void)file;
return -1;
}
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_raw(const char * blkdev, const char * file) {
int fd1, fd2;
int ret;
char * path;
uint64_t blksize;
size_t need, readed;
ssize_t size;
struct stat st;
struct statvfs buf;
printf("Dump block device %s to file %s...\n", blkdev, file);
if ( stat(blkdev, &st) != 0 ) {
ERROR_INFO("Cannot stat block device %s", blkdev);
return -1;
}
if ( ! S_ISBLK(st.st_mode) ) {
ERROR("Invalid block device %s", blkdev);
return -1;
}
fd1 = open(blkdev, O_RDONLY);
if ( fd1 < 0 ) {
ERROR_INFO("Cannot open block device %s", blkdev);
return -1;
}
if ( ioctl(fd1, BLKGETSIZE64, &blksize) != 0 ) {
ERROR_INFO("Cannot get size of block device %s", blkdev);
close(fd1);
return -1;
}
if ( blksize > ULLONG_MAX ) {
ERROR("Block device %s is too big", blkdev);
close(fd1);
return -1;
}
if ( blksize == 0 ) {
ERROR("Block device %s has zero size", blkdev);
close(fd1);
return -1;
}
path = strdup(file);
if ( ! path ) {
ALLOC_ERROR();
close(fd1);
return -1;
}
ret = statvfs(dirname(path), &buf);
free(path);
if ( ret == 0 && buf.f_bsize * buf.f_bfree < blksize ) {
ERROR("Not enought free space (have: %llu, need: %llu)", (unsigned long long int)(buf.f_bsize) * buf.f_bfree, (unsigned long long int)blksize);
close(fd1);
return -1;
}
fd2 = creat(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if ( fd2 < 0 ) {
ERROR_INFO("Cannot create file %s", file);
close(fd1);
return -1;
}
readed = 0;
printf_progressbar(0, blksize);
while ( readed < blksize ) {
need = blksize - readed;
if ( need > sizeof(global_buf) )
need = sizeof(global_buf);
size = read(fd1, global_buf, need);
if ( size == 0 )
break;
if ( write(fd2, global_buf, size) != size ) {
PRINTF_ERROR("Dumping image failed");
close(fd1);
close(fd2);
return -1;
}
readed += size;
printf_progressbar(readed, blksize);
}
close(fd1);
close(fd2);
return 0;
}
int disk_dump_image(struct usb_device_info * dev, enum image_type image, const char * file) {
ERROR("Not implemented yet");
(void)dev;
(void)image;
(void)file;
return -1;
}
int disk_check_badblocks(struct usb_device_info * dev, const char * device) {
ERROR("Not implemented yet");
(void)dev;
(void)device;
return -1;
}
+37
View File
@@ -0,0 +1,37 @@
/*
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);
enum device disk_get_device(struct usb_device_info * dev);
int disk_flash_raw(const char * blkdev, const char * file);
int disk_dump_raw(const char * blkdev, 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
-640
View File
@@ -1,640 +0,0 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007-2009 pancake <pancake@nopcode.org>
*
* 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 "hexdump.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Extracts a piece from an mtd device
* -----------------------------------
* This function is known to be buggy, It does not takes care about
* badblocks and oob data. It is replaced by nanddump(), but will
* probably be fixed in the future or it will die.
*/
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", (long long int)from, (long long int)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("Extracting %s...\n", file);
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);
progressbar(i, to);
if (!ret || feof(fs)) break;
fwrite(buf, blk, 1, fd);
}
printf("\r%s: %lld bytes dumped from %s\n",
file, (long long int)(to-from), dev);
__rf_extract_exit:
if (fs) fclose(fs);
if (fd) fclose(fd);
return 1;
}
/*
* This function was covardly copied from nanddump.c @ mtd-utils-20060907
*/
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
//#include <asm/types.h>
#include <mtd/mtd-user.h>
#ifndef loff_t
#define loff_t off_t
#endif
#define M_RDONLY 0x00000001
#define M_RDRW 0x00000002
#define M_OMITOOB 0x00000010
#define M_OMITBAD 0x00000011
#define M_OMITECC 0x00000012
int mtd_open(char *file, mtd_info_t *meminfo, int *oobinfochanged,
struct nand_oobinfo *old_oobinfo, int *eccstats, int flags)
{
int fd;
*oobinfochanged = 0 ;
fd = open(file, (flags&M_RDONLY)?O_RDONLY:O_RDWR);
if (fd == -1) {
perror("mtd_open");
return -1;
}
/* Fill in MTD device capability structure */
if (ioctl(fd, MEMGETINFO, meminfo) != 0) {
perror("MEMGETINFO");
close(fd);
return 1;
}
/* Make sure device page sizes are valid */
if (!(meminfo->oobsize == 64 && meminfo->writesize == 2048) &&
!(meminfo->oobsize == 16 && meminfo->writesize == 512) &&
!(meminfo->oobsize == 8 && meminfo->writesize == 256)) {
fprintf(stderr, "Unknown flash (not normal NAND)\n");
close(fd);
return -1;
}
return fd;
}
int mtd_close(int fd, struct nand_oobinfo *old_oobinfo, int oobinfochanged)
{
if (fd == -1)
return 1;
/* reset oobinfo */
if (oobinfochanged == 1) {
if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
perror ("MEMSETOOBSEL");
close(fd);
return 1;
}
}
/* Close the output file and MTD device */
return close(fd);
}
// configuration for nanddump //
//int noecc = 0; // don't error correct
static int omitoob = 1; // omit oob data
static int omitbad = 1;
// configuration for nanddump //
#define CONFIGURE_FLAGS(x) \
omitoob = x & M_OMITOOB; \
omitbad = x & M_OMITBAD;
int check_badblocks(char *mtddev)
{
int fd;
int oobinfochanged = 0 ;
int badblock = 0;
int badblocks = 1;
int eccstats = 0;
unsigned long int i;
unsigned long long blockstart = 1;
unsigned char oobbuf[64];
struct nand_oobinfo old_oobinfo;
struct mtd_oob_buf oob = {0, 16, oobbuf};
/* XXX stat1 is never initialized !!! */
struct mtd_ecc_stats stat1, stat2;
mtd_info_t meminfo;
fd = mtd_open(mtddev, &meminfo, &oobinfochanged, &old_oobinfo, &eccstats, M_RDONLY);
if (fd == -1) {
printf("cannot open mtd\n");
return 1;
}
fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
fprintf(stderr, "Size %u, flags %u, type 0x%x\n",
meminfo.size, meminfo.flags, (int)meminfo.type);
oob.length = meminfo.oobsize;
for(i = 0; i < meminfo.size; i+= meminfo.writesize) {
// new eraseblock , check for bad block
if (blockstart != (i & (~meminfo.erasesize + 1))) {
blockstart = i & (~meminfo.erasesize + 1);
if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
perror("ioctl(MEMGETBADBLOCK)");
goto closeall;
}
}
if (badblock) {
if (omitbad) {
printf("Bad block found at 0x%lx\n", i);
continue;
}
} else {
char readbuf[2048]; // XXX hardcoded like mtd-utils?? ugly!
// dummy -- should be removed
if (pread(fd, readbuf, meminfo.writesize, i) != meminfo.writesize) {
perror("pread");
goto closeall;
}
}
/* ECC stats available ? */
memset (&stat1, 0, sizeof (stat1));
if (eccstats) {
if (ioctl (fd, ECCGETSTATS, &stat2)) {
perror("ioctl(ECCGETSTATS)");
goto closeall;
}
if (stat1.failed != stat2.failed)
fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
" at offset 0x%08lx\n",
stat2.failed - stat1.failed, i);
if (stat1.corrected != stat2.corrected)
fprintf(stderr, "ECC: %d corrected bitflip(s) at"
" offset 0x%08lx\n",
stat2.corrected - stat1.corrected, i);
stat1 = stat2;
}
if (badblock) {
printf("Oops badblock %d at 0x%lx !\n", badblocks++, i);
} else {
/* Read OOB data and exit on failure */
oob.start = i;
if (ioctl(fd, MEMREADOOB, &oob) != 0) {
perror("ioctl(MEMREADOOB)");
goto closeall;
}
}
/* Write out OOB data */
if (badblock)
D dump_bytes(oobbuf, meminfo.oobsize);
}
mtd_close(fd, &old_oobinfo, oobinfochanged);
return 0;
closeall:
mtd_close(fd, &old_oobinfo, oobinfochanged);
return 1;
}
// XXX warning ioob is not used
// isbl is used to skip bad blocks ?
int nanddump(char *mtddev, unsigned long start_addr, unsigned long length, char *dumpfile, int isbl, int ioob)
{
unsigned char readbuf[2048];
int oobinfochanged = 0 ;
unsigned char oobbuf[64];
unsigned long ofs, end_addr = 0;
unsigned long long blockstart = 1;
struct nand_oobinfo none_oobinfo = {
.useecc = MTD_NANDECC_OFF,
};
int fd, ofd, bs, badblock = 0;
struct mtd_oob_buf oob = {0, 16, oobbuf};
mtd_info_t meminfo;
int badblocks = 1;
struct nand_oobinfo old_oobinfo;
int eccstats = 0;
struct mtd_ecc_stats stat1, stat2;
int flags = M_RDONLY;
printf("\nExtracting %s from %s...\n", dumpfile, mtddev);
fd = mtd_open(mtddev, &meminfo, &oobinfochanged, &old_oobinfo, &eccstats, flags);
if (meminfo.writesize == 0) {
printf("What the fuck.. this is not an MTD device!\n");
close(fd);
return 1;
}
/* Read the real oob length */
oob.length = meminfo.oobsize;
fprintf(stderr, "Block size %u, page size %u, OOB size %u\n",
meminfo.erasesize, meminfo.writesize, meminfo.oobsize);
fprintf(stderr, "Size %u, flags %u, type 0x%x\n",
meminfo.size, meminfo.flags, (int)meminfo.type);
if (flags & M_OMITECC) { // (noecc)
switch (ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW)) {
case -ENOTTY:
if (ioctl (fd, MEMGETOOBSEL, old_oobinfo) != 0) {
perror ("MEMGETOOBSEL");
close (fd);
exit (1);
}
if (ioctl (fd, MEMSETOOBSEL, none_oobinfo) != 0) {
perror ("MEMSETOOBSEL");
close (fd);
exit (1);
}
oobinfochanged = 1;
break;
case 0:
oobinfochanged = 2;
break;
default:
perror ("MTDFILEMODE");
close (fd);
return 1;
}
} else {
/* check if we can read ecc stats */
if (!ioctl(fd, ECCGETSTATS, &stat1)) {
eccstats = 1;
fprintf(stderr, "ECC failed: %d\n", stat1.failed);
fprintf(stderr, "ECC corrected: %d\n", stat1.corrected);
fprintf(stderr, "Number of bad blocks: %d\n", stat1.badblocks);
fprintf(stderr, "Number of bbt blocks: %d\n", stat1.bbtblocks);
} else
perror("No ECC status information available");
}
/* Open output file for writing. If file name is "-", write to standard
* output. */
if (!dumpfile) {
ofd = STDOUT_FILENO;
} else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) {
perror ("open outfile");
close(fd);
return 1;
}
/* Initialize start/end addresses and block size */
if (length)
end_addr = start_addr + length;
if (!length || end_addr > meminfo.size)
end_addr = meminfo.size;
bs = meminfo.writesize;
fprintf(stderr,
"Dumping data starting at 0x%08x and ending at 0x%08x...\n",
(unsigned int) start_addr, (unsigned int) end_addr);
/* Dump the flash contents */
for (ofs = start_addr; ofs < end_addr ; ofs+=bs) {
// new eraseblock , check for bad block
if (blockstart != (ofs & (~meminfo.erasesize + 1))) {
blockstart = ofs & (~meminfo.erasesize + 1);
if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) {
perror("ioctl(MEMGETBADBLOCK)");
goto closeall;
}
}
if (!isbl && badblock) {
if (omitbad)
continue;
memset (readbuf, 0xff, bs);
} else {
/* Read page data and exit on failure */
if (pread(fd, readbuf, bs, ofs) != bs) {
perror("pread");
goto closeall;
}
}
// TODO exist on n800??? // remove code?
/* ECC stats available ? */
if (eccstats) {
if (ioctl(fd, ECCGETSTATS, &stat2)) {
perror("ioctl(ECCGETSTATS)");
goto closeall;
}
if (stat1.failed != stat2.failed)
fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
" at offset 0x%08lx\n",
stat2.failed - stat1.failed, ofs);
if (stat1.corrected != stat2.corrected)
fprintf(stderr, "ECC: %d corrected bitflip(s) at"
" offset 0x%08lx\n",
stat2.corrected - stat1.corrected, ofs);
stat1 = stat2;
}
/* Write out page data */
//if (pretty_print) dump_bytes(readbuf, bs);
write(ofd, readbuf, bs);
progressbar(ofs, end_addr);
// OOB STUFF //
if (omitoob)
continue;
if (!isbl&&badblock) {
printf("Oops badblock %d *ignored* at 0x%lx !\n", badblocks++, ofs);
memset (readbuf, 0xff, meminfo.oobsize);
} else {
/* Read OOB data and exit on failure */
oob.start = ofs;
if (ioctl(fd, MEMREADOOB, &oob) != 0) {
perror("ioctl(MEMREADOOB)");
goto closeall;
}
}
/* Write out OOB data */
D dump_bytes(oobbuf, meminfo.oobsize);
write(ofd, oobbuf, meminfo.oobsize);
}
mtd_close(fd, &old_oobinfo, oobinfochanged);
close(ofd);
return 0;
closeall:
mtd_close(fd, &old_oobinfo, oobinfochanged);
close(ofd);
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);
if (ftell(fd)>4096) {
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;
}
static int is_n900()
{
int n900 = 0;
unsigned char buf[4];
FILE *fd = fopen("/dev/mtd2", "rb");
if (!fd) {
fprintf(stderr, "Cannot open /dev/mtd2.\n");
exit(1);
}
fread(buf, 4, 1, fd);
if (!memcmp("\xff\xff\xff\xff", buf, 4))
n900 = 1;
fclose(fd);
return n900;
}
static 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 dump_config()
{
mtd_info_t meminfo;
int fd = open("/dev/mtd1", O_RDONLY);
char buf[1024];
int i=0,j;
int ret;
if (fd == -1) {
perror("open /dev/mtd1");
return 1;
}
if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
perror("MEMGETINFO");
close(fd);
return 1;
}
while(i<0x60000) {
iniloop:
ret = read(fd, buf, 4);
if (ret == -1)
break;
if (!memcmp(buf,"ConF", 4)) {
loop:
read(fd, buf, 4);
if (ret == -1) break;
printf("\n0x%08x : ConF %02x %02x %02x %02x : ", i,
buf[0], buf[1], buf[2], buf[3]);
fflush(stdout);
while(1) {
ret = read(fd, buf, 4);
if (ret <1) {
printf("Unexpected eof\n");
break;
}
if (buf[0]=='\0'||buf[1]=='\0'||buf[2]=='\0'||buf[3]=='\0') {
printf("%s \t ", buf);
fflush(stdout);
while(1) {
ret = read(fd, buf, 4);
if (ret <1) {
printf("Unexpected eof\n");
break;
}
if (!memcmp(buf,"\xff\xff\xff\xff", 4))
goto iniloop;
if (!memcmp(buf,"ConF", 4))
goto loop;
printf ("%02x %02x %02x %02x ",
buf[0], buf[1], buf[2], buf[3]);
}
break;
} else {
write(1, buf,4);
}
}
}
j = lseek(fd, 0, SEEK_CUR);
if (j==i) break; i = j;
}
close(fd);
printf("\n");
return 0;
}
int reverse_extract_pieces_n900(char *dir)
{
char reply;
chdir(dir);
printf("Device detected: n900\n");
// Some of the values here are probably not correct
// I need a firmware to identify if the sizes of the pieces are ok
nanddump("/dev/mtd0", 0, 0, "xloader.bin", 1, 0); // fix size?
nanddump("/dev/mtd1", 0, 0, "config.bin", 1, 0);
nanddump("/dev/mtd3", 0, 0, "nolo.bin", 0, 0);
printf("\n\nExtract rootfs? (y/N): "); fflush(stdout);
read(0, &reply, 1);
if (reply=='y'||reply=='Y') {
//rf_extract("/dev/mtd4", 0x000000, 0x6000000, "rootfs.jffs2");
nanddump("/dev/mtd5", 0x000000, 0, "rootfs.jffs2", 0,0);
} else printf("*** Ignoring rootfs\n");
printf("\n\nStrip dumped files? (y/N): "); fflush(stdout);
read(0, &reply, 1);
if (reply=='y'||reply=='Y') {
rf_strip("xloader.bin");
rf_strip("config.bin");
rf_strip("nolo.bin");
} else printf("*** Ignoring strip\n");
printf("\nIdentifying extracted files...\n");
printf("%s: xloader\n", fpid_file("xloader.bin"));
printf("%s: config.bin\n", fpid_file("config.bin"));
printf("%s: nolo.bin\n", fpid_file("nolo.bin"));
printf("%s: rootfs.jffs2\n", fpid_file("rootfs.jffs2"));
return 1;
}
int reverse_extract_pieces(char *dir)
{
char reply;
if (is_n900())
return reverse_extract_pieces_n900(dir);
printf("Device detected: 770/n800/n900\n");
chdir(dir);
// TODO: get values from /proc/mtd ???
//rf_extract("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin");
nanddump("/dev/mtd0", is_n800()?0x200:0, 0x4000, "xloader.bin", 1,0); // 0x3600 size?
//rf_extract("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin");
nanddump("/dev/mtd0", 0x004000, 0, "secondary.bin", 1,0);
nanddump("/dev/mtd1", 0, 0, "config.bin", 0,0);
//rf_extract("/dev/mtd2", 0x000800, 0x200000, "zImage");
nanddump("/dev/mtd2", 0x000800, 0, "zImage", 0,0);
//rf_extract("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2");
nanddump("/dev/mtd3", 0x000000, 0, "initfs.jffs2", 0,0);
printf("\n\nExtract rootfs? (y/N): "); fflush(stdout);
read(0, &reply, 1);
if (reply=='y'||reply=='Y') {
//rf_extract("/dev/mtd4", 0x000000, 0x6000000, "rootfs.jffs2");
nanddump("/dev/mtd4", 0x000000, 0, "rootfs.jffs2", 0,0);
} else printf("*** Ignoring rootfs\n");
printf("\n\nStrip dumped files? (y/N): "); fflush(stdout);
read(0, &reply, 1);
if (reply=='y'||reply=='Y') {
rf_strip("xloader.bin");
rf_strip("secondary.bin");
rf_strip("zImage");
rf_strip("initfs.jffs2");
} else printf("*** Ignoring strip\n");
printf("\nIdentifying extracted files...\n");
printf("%s: xloader\n", fpid_file("xloader.bin"));
printf("%s: secondary.bin\n", fpid_file("secondary.bin"));
printf("%s: config.bin\n", fpid_file("config.bin"));
printf("%s: zImage\n", fpid_file("zImage"));
printf("%s: initfs.jffs2\n", fpid_file("initfs.jffs2"));
printf("%s: rootfs.jffs2\n", fpid_file("rootfs.jffs2"));
return 1;
}
+490 -566
View File
File diff suppressed because it is too large. Load diff
+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
-215
View File
@@ -1,215 +0,0 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.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/>.
*/
#if HAVE_USB
#include "main.h"
#include "hash.h"
#include "hexdump.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 query_error_message()
{
/* query error message */
int len = 0;
char nolomsg[2048];
memset(nolomsg, '\0', 2048);
usb_control_msg(dev, 192, 5, 0, 0, nolomsg, 2048, 2000);
nolomsg[2047] = '\0';
printf("\nNOLO says:\n");
if (nolomsg[0] == '\0') {
printf(" (.. silence ..)\n");
} else {
dump_bytes((unsigned char *)nolomsg, 128);
do {
printf(" - %s\n", nolomsg+len);
len+=strlen(nolomsg+len)+1;
} while(nolomsg[len]!='\0');
}
}
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(const char *filename, const char *piece, const char *device, const char *hwrevs, const 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, piece);
if (piece == NULL) {
//exit(1);
piece = fpid_file(filename);
if (piece == NULL) {
printf("Unknown piece type\n");
return;
}
printf("Piece type: %s\n", piece);
}
if (piece != NULL) {
if (!strcmp(piece, "fiasco")) {
fiasco_flash(filename);
return;
}
}
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) {
query_error_message();
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);
if (bread == 64) {
query_error_message();
fclose(fd);
return;
}
progressbar(off, size);
if (bread<0) {
printf("\n");
perror(" -ee- ");
fclose(fd);
return;
}
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");
}
#endif
-107
View File
@@ -1,107 +0,0 @@
/*
* 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 "main.h"
#include <stdio.h>
#include <string.h>
/* global structs */
char *pieces[] = {
"xloader", // xloader.bin
"2nd", // 2nd.bin
"secondary", // secondary.bin
"kernel", // zImage
"initfs", // initfs
"rootfs", // rootfs
"omap-nand", // 8kB of food for the nand
"mmc", // raw eMMC image
"cmt-2nd", // cmt-2nd
"cmt-algo", // cmt-algo
"cmt-mcusw", // cmt-mcusw
"fiasco", // FIASCO IMAGE
NULL
};
long fpid_size(const char *filename)
{
long sz;
FILE *fd = fopen(filename, "r");
fseek(fd, 0, SEEK_END);
sz = ftell(fd);
fclose(fd);
return sz;
}
const char *fpid_file(const char *filename)
{
FILE *fd;
char buf[512];
unsigned char *b = (unsigned char *)&buf;
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 (!memcmp(b, "\xb4", 1))
return pieces[PIECE_FIASCO];
else
if (!memcmp(b+0x34, "2NDAPE", 6))
return pieces[PIECE_2ND];
else
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))
return pieces[PIECE_XLOADER];
else
if (!memcmp(b+4,"NOLOXldr",8))
// TODO: this is xloader800, not valid on 770?
return pieces[PIECE_2ND];
else
if (!memcmp(b+0x00, "\x00\x00\xa0\xe1\x00\x00\xa0\xe1", 8)
|| (!memcmp(b, "\x21\x01\x01", 3)))
return pieces[PIECE_KERNEL];
else
// JFFS2 MAGIC
if (!memcmp(b+0x00, "\x85\x19", 2)) { //\x01\xe0", 4)) {
/*/ is jffs2 */
if (size < 0x300000)
return pieces[PIECE_INITFS];
return pieces[PIECE_ROOTFS];
}
return NULL;
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef GLOBAL_H
#define GLOBAL_H
#include <stdio.h>
#include <string.h>
#include <errno.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)
#endif
-82
View File
@@ -1,82 +0,0 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007-2009 pancake <pancake@youterm.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 "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(const char *filename, const char *type)
{
unsigned char buf[BSIZE];
FILE *fd = fopen(filename, "r");
usho hash = 0;
int align = 0;
int size;
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);
size = ftell(fd);
fclose(fd);
/* mmc and kernel image must be aligned */
if (type) {
if (strcmp(type, "mmc") == 0)
align = ((size >> 8) + 1) << 8;
else if (strcmp(type, "kernel") == 0)
align = ((size >> 7) + 1) << 7;
}
if (align) {
printf("align from %d to %d\n", size, align);
buf[0] = 0xff;
while (size < align) {
hash ^= do_hash((usho *)&buf, 1);
++size;
}
}
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(const char *filename, const char *type);
#endif
-65
View File
@@ -1,65 +0,0 @@
/*
* radare - advanced commandline hexadecimal editor
* Copyright (C) 2006,2007 pancake <pancake@youterm.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 "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);
+608
View File
@@ -0,0 +1,608 @@
/*
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);
else
free(hwrevs);
if ( ! image->version )
image->version = version;
else
free(version);
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 )
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 )
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 = 0;
if ( image->type == IMAGE_MMC )
align = 8;
else
align = 7;
if ( align == 0 )
return;
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) {
struct image * image = image_alloc();
if ( ! image )
return NULL;
image->is_shared_fd = 0;
image->fd = open(file, O_RDONLY);
if ( image->fd < 0 ) {
ERROR_INFO("Cannot open image file %s", file);
free(image);
return NULL;
}
image->size = lseek(image->fd, 0, SEEK_END);
image->offset = 0;
image->cur = 0;
image->orig_filename = strdup(file);
lseek(image->fd, 0, SEEK_SET);
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, file);
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->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) {
if ( whence > image->size )
return;
if ( whence >= image->size - image->align ) {
lseek(image->fd, image->size - image->align - 1, SEEK_SET);
image->acur = whence - ( image->size - image->align );
} else {
lseek(image->fd, image->offset + whence, SEEK_SET);
image->acur = 0;
}
IMAGE_STORE_CUR(image);
}
size_t image_read(struct image * image, void * buf, size_t count) {
size_t cur;
ssize_t ret;
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 ret;
}
if ( ret_count == count )
return ret_count;
cur = lseek(image->fd, 0, SEEK_CUR) - 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, int 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;
int 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];
memset(buf, 0, sizeof(buf));
image_seek(image, 0);
image_read(image, buf, sizeof(buf));
if ( memcmp(buf+52, "2NDAPE", 6) == 0 )
return IMAGE_2ND;
else if ( memcmp(buf+20, "2ND", 3) == 0 )
return IMAGE_2ND;
else if ( memcmp(buf+4, "NOLOScnd", 8) == 0 )
return IMAGE_SECONDARY;
else if ( memcmp(buf+20, "X-LOADER", 8) == 0 )
return IMAGE_XLOADER;
else if ( memcmp(buf+12, "NOLOXldr", 8) == 0 )
return IMAGE_XLOADER;
else if ( memcmp(buf+4, "NOLOXldr", 8) == 0 )
return IMAGE_2ND;
else if ( memcmp(buf+36, "\x18\x28\x6f\x01", 4) == 0 ) /* ARM Linux kernel magic number */
return IMAGE_KERNEL;
else if ( memcmp(buf, "\x14\x00\x00\xea", 4) == 0 ) /* ARM U-Boot - instruction branch +0x50 */
return IMAGE_KERNEL;
else if ( memcmp(buf, "UBI#", 4) == 0 ) /* UBI EC header */
return IMAGE_ROOTFS;
else if ( memcmp(buf+510, "\x55\xaa", 2) == 0 ) /* FAT boot sector signature */
return IMAGE_MMC;
else if ( memcmp(buf, "\xb0\x00\x01\x03\x9d\x00\x00\x00", 8) == 0 )
return IMAGE_CMT_2ND;
else if ( memcmp(buf, "\xb1\x00\x00\x00\x82\x00\x00\x00", 8) == 0 )
return IMAGE_CMT_ALGO;
else if ( memcmp(buf, "\xb2\x00\x00\x01\x44\x00\x00\x00", 8) == 0 )
return IMAGE_CMT_MCUSW;
else if ( memcmp(buf, "\x45\x3d\xcd\x28", 4) == 0 ) /* CRAMFS MAGIC */
return IMAGE_INITFS;
else if ( memcmp(buf, "\x85\x19", 2) == 0 ) { /* JFFS2 MAGIC */
if ( image->size < 0x300000 )
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;
}
}
+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 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_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
+194
View File
@@ -0,0 +1,194 @@
/*
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 ... */
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <usb.h>
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 )
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 )
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 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 )
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 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 )
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 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 )
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 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 )
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);
}
+615
View File
@@ -0,0 +1,615 @@
/*
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/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_store(cal, str, dest) do { void * ptr; unsigned long int len; if ( local_cal_read(cal, str, ptr, len) ) local_cal_copy(dest, ptr, len); } while ( 0 )
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_store(cal, "kernel-ver", kernel_ver);
local_cal_store(cal, "initfs-ver", kernel_ver);
local_cal_store(cal, "nolo-ver", nolo_ver);
local_cal_store(cal, "sw-release-ver", sw_ver);
local_cal_store(cal, "content-ver", content_ver);
local_cal_store(cal, "r&d_mode", rd_mode);
/* overwritten hw revision */
memset(buf, 0, sizeof(buf));
local_cal_store(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_store(cal, "phone-info", buf);
buf[4] = 0;
if ( buf[0] && sscanf(buf, "%hd", &hwrev) != 1 )
hwrev = -1;
}
buf[0] = 0;
local_cal_store(cal, "usb_host_mode", buf);
usb_host_mode = buf[0];
memset(buf, 0, sizeof(buf));
local_cal_store(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);
}
int local_init(void) {
char buf[1024];
char * ptr;
char * ptr2;
FILE * file;
if ( failed )
return -1;
file = fopen("/proc/cpuinfo", "r");
if ( ! file ) {
failed = 1;
return -1;
}
while ( fgets(buf, sizeof(buf), file) ) {
if ( strncmp(buf, "Hardware", strlen("Hardware")) == 0 ) {
ptr = buf + strlen("Hardware");
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;
}
}
}
failed = 1;
printf("Not a local device\n");
fclose(file);
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 enought free space (have: %lu, need: %d)", buf.f_bsize * buf.f_bfree, length);
return 1;
}
size = snprintf(NULL, 0, "nanddump -i -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 -i -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_n900[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000000, 0x00004000 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
[IMAGE_KERNEL] = { 1, 3, 0x00000800, 0x001FF800 },
[IMAGE_INITFS] = { 1, 4, 0x00000800, 0x001FF800 },
[IMAGE_ROOTFS] = { 1, 5, 0x00000000, 0x0fb40000 },
};
/* FIXME: Is this table correct? */
static struct nanddump_args nanddump[] = {
[IMAGE_XLOADER] = { 1, 0, 0x00000200, 0x00003E00 },
[IMAGE_SECONDARY] = { 1, 0, 0x00004000, 0x0001C000 },
[IMAGE_KERNEL] = { 1, 2, 0x00000800, 0x001FF800 },
[IMAGE_INITFS] = { 1, 3, 0x00000800, 0x001FF800 },
[IMAGE_ROOTFS] = { 1, 4, 0x00000000, 0x0fb80000 },
};
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;
DIR * dir;
DIR * dir2;
struct dirent * dirent;
struct dirent * dirent2;
char * ptr;
int i;
char buf[1024];
char blk[1024];
printf("Dump %s image to file %s...\n", image_type_to_string(image), file);
if ( image == IMAGE_MMC ) {
/* Find block device in /dev/ for MyDocs (mmc device, partition 1) */
dir = opendir("/sys/class/mmc_host/");
if ( ! dir ) {
ERROR("Cannot find MyDocs mmc device");
goto clean;
}
blk[0] = 0;
while ( ( dirent = readdir(dir) ) ) {
snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/slot_name", dirent->d_name);
fd = open(buf, O_RDONLY);
if ( fd < 0 )
continue;
buf[0] = 0;
read(fd, buf, sizeof(buf));
close(fd);
if ( strncmp(buf, "internal", strlen("internal")) != 0 )
continue;
snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001", dirent->d_name, dirent->d_name);
dir2 = opendir(buf);
if ( ! dir2 )
continue;
while ( ( dirent2 = readdir(dir2) ) ) {
if ( strncmp(dirent2->d_name, "block:mmcblk", strlen("block:mmcblk")) != 0 )
continue;
snprintf(buf, sizeof(buf), "/sys/class/mmc_host/%s/%s:0001/%s", dirent->d_name, dirent->d_name, dirent2->d_name);
blk[0] = 0;
if ( readlink(buf, blk, sizeof(blk)) < 0 )
continue;
ptr = strrchr(blk, '/');
if ( ! ptr ) {
blk[0] = 0;
continue;
}
strcpy(blk, "/dev/");
i = strlen("/dev/");
++ptr;
while ( *ptr )
blk[i++] = *(ptr++);
strcpy(blk+i, "p1");
break;
}
closedir(dir2);
if ( blk[0] )
break;
}
closedir(dir);
if ( ! blk[0] ) {
ERROR("Cannot find MyDocs mmc device");
goto clean;
}
ret = disk_dump_raw(blk, image_type_to_string(image));
} else {
if ( device == DEVICE_RX_51 ) {
if ( image >= sizeof(nanddump_n900)/sizeof(nanddump_n900[0]) || ! nanddump_n900[image].valid ) {
ERROR("Unsuported image type: %s", image_type_to_string(image));
goto clean;
}
ret = local_nanddump(file, nanddump_n900[image].mtd, nanddump_n900[image].offset, nanddump_n900[image].length);
} else {
if ( image >= sizeof(nanddump)/sizeof(nanddump[0]) || ! nanddump[image].valid ) {
ERROR("Unsuported image type: %s", image_type_to_string(image));
goto clean;
}
ret = local_nanddump(file, nanddump[image].mtd, nanddump[image].offset, nanddump[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 = 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;
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);
ftruncate(fd, nlen);
}
clean:
if ( addr )
munmap(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", strlen("master")) == 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", strlen("master")) == 0 )
ptr = rd_mode + strlen("master");
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
+1320 -452
View File
File diff suppressed because it is too large. Load diff
-136
View File
@@ -1,136 +0,0 @@
#ifndef _INCLUDE_MAIN_H_
#define _INCLUDE_MAIN_H_
#include "hash.h"
#include "nolo.h"
#include "os.h"
extern char strbuf[1024];
#define _FILE_OFFSET_BITS 64
#define _GNU_SOURCE
// Forward declaration for use in function arguments.
struct devices;
int queue_mode();
int reverse_extract_pieces(char *dir);
void flash_image(const char *filename, const char *piece, const char *device, const char *hwrevs, const char *version);
int fiasco_read_image(char *file);
void check_nolo_order();
extern struct usb_dev_handle *dev;
unsigned long get_file_size(const char *file);
void progressbar(unsigned long long part, unsigned long long total);
const char *fpid_file(const char *filename);
int add_piece(char *piece);
void eprintf(const char *format, ...);
#include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#if HAVE_USB
#include <usb.h>
int fiasco_flash(const char *file);
extern struct usb_device *device;
extern struct usb_dev_handle *dev;
int is_valid_device(struct usb_device_descriptor *udd);
void list_valid_devices();
int usb_device_found(struct usb_device_descriptor *udd, struct devices *it_device);
int console(const char *device);
int connect_via_usb();
#endif
int console_prompt();
//
void cmd_info(char *line);
int check_badblocks(char *mtddev);
int dump_config();
extern int verbose;
#define D if (verbose)
#define CMD_WRITE 64
#define CMD_QUERY 192
struct piece_t {
char *name;
char *type;
char *device;
char *hwrevs;
char *version;
};
enum flash_mode {
FLASH_COLD,
FLASH_NORMAL,
FLASH_MKII,
FLASH_DISK,
};
struct devices {
char *name;
unsigned short vendor_id;
unsigned short product_id;
enum flash_mode mode;
};
#define SUPPORTED_DEVICES 10
extern struct devices supported_devices[SUPPORTED_DEVICES];
extern int pcs_n;
extern struct piece_t pcs[10];
enum {
PIECE_XLOADER = 0,
PIECE_2ND,
PIECE_SECONDARY,
PIECE_KERNEL,
PIECE_INITFS,
PIECE_ROOTFS,
PIECE_OMAPNAND,
PIECE_MMC,
PIECE_CMT_2ND,
PIECE_CMT_ALGO,
PIECE_CMT_MCUSW,
PIECE_FIASCO,
PIECE_LAST
};
struct header_t {
int fd;
char swver[128];
char type[128];
char device[16];
char hwrevs[128];
char version[128];
unsigned short hash;
unsigned int size;
unsigned char *data;
char *name;
char *layout;
};
extern char *pieces[];
extern char *modes[];
extern char *root_devices[];
// fiasco
int openfiasco(const char *name, const char *type, const char *device, const char *hwrev, const char *version, int v);
int fiasco_new(const char *filename, const char *name);
void fiasco_data_read(struct header_t *header);
extern int (*fiasco_callback)(struct header_t *header);
int fiasco_add(int fd, const char *name, const char *file, const char *layout, const char *device, const char *hwrevs, const char *version);
int fiasco_pack(int optind, char *argv[]);
int nanddump(char *mtddev, unsigned long start_addr, unsigned long length, char *dumpfile, int isbl, int ioob);
//
int reboot_board();
int get_rd_flags();
int get_usb_mode();
int get_nolo_version();
#endif
+239
View File
@@ -0,0 +1,239 @@
/*
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 "mkii.h"
#include "global.h"
#include "image.h"
#include "device.h"
#include "usb-device.h"
int mkii_init(struct usb_device_info * dev) {
ERROR("Mk II protocol is not implemented yet");
(void)dev;
return -1;
}
enum device mkii_get_device(struct usb_device_info * dev) {
ERROR("Not implemented yet");
(void)dev;
return DEVICE_UNKNOWN;
}
int mkii_flash_image(struct usb_device_info * dev, struct image * image) {
ERROR("Not implemented yet");
(void)dev;
(void)image;
return -1;
}
int mkii_reboot_device(struct usb_device_info * dev) {
ERROR("Not implemented yet");
(void)dev;
return -1;
}
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) {
ERROR("Not implemented yet");
(void)dev;
return -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) {
ERROR("Not implemented yet");
(void)dev;
(void)ver;
(void)size;
return -1;
}
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;
}
+64
View File
@@ -0,0 +1,64 @@
/*
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"
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 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
+832
View File
@@ -0,0 +1,832 @@
/*
* 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 <usb.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_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
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 )
ERROR_RETURN("NOLO_IDENTIFY failed", -1);
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 ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, str, strlen(str), 2000) < 0 )
ERROR_RETURN("NOLO_STRING failed", -1);
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SET_STRING, 0, 0, arg, strlen(arg), 2000) < 0 )
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;
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_STRING, 0, 0, str, strlen(str), 2000) < 0 )
ERROR_RETURN("NOLO_STRING failed", -1);
if ( ( ret = usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET_STRING, 0, 0, out, size-1, 2000) ) < 0 )
ERROR_RETURN("NOLO_GET_STRING failed", -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;
sprintf(buf, "version:%s", str);
ret = nolo_get_string(dev, buf, out, size);
if ( ret < 0 )
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 )
ERROR_RETURN("NOLO_STATUS failed", -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 readed;
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, "%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 ( usb_control_msg(dev->udev, NOLO_WRITE, request, 0, 0, buf, ptr-buf, 2000) < 0 )
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);
readed = 0;
while ( readed < image->size ) {
need = image->size - readed;
if ( need > sizeof(buf) )
need = sizeof(buf);
ret = image_read(image, buf, need);
if ( ret == 0 )
break;
if ( usb_bulk_write(dev->udev, 2, buf, ret, 5000) != ret )
PRINTF_ERROR_RETURN("Sending image failed", -1);
readed += ret;
printf_progressbar(readed, image->size);
}
if ( flash ) {
printf("Finishing flashing...\n");
if ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_SEND_FLASH_FINISH, 0, 0, NULL, 0, 30000) < 0 )
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 status[20];
char buf[128];
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 ( usb_control_msg(dev->udev, NOLO_WRITE, NOLO_FLASH_IMAGE, 0, index, NULL, 0, 10000) )
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 )
ERROR_RETURN("cmt:status failed", -1);
if ( strncmp(buf, "idle", strlen("idle")) == 0 )
state = 4;
else
printf("Erasing CMT...\n");
while ( state != 4 ) {
if ( nolo_get_string(dev, "cmt:status", buf, sizeof(buf)) < 0 )
PRINTF_ERROR_RETURN("cmt:status failed", -1);
if ( strncmp(buf, "finished", strlen("finished")) == 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 ( sscanf(buf, "%s:%llu/%llu", status, &part, &total) != 3 )
PRINTF_ERROR_RETURN("cmt:status unknown", -1);
if ( strcmp(status, "program") == 0 && state <= 0 ) {
printf_progressbar(last_total, last_total);
printf("Done\n");
state = 1;
}
if ( strcmp(status, "program") == 0 && state <= 1 ) {
printf("Programming CMT...\n");
state = 2;
}
printf_progressbar(part, total);
last_total = total;
if ( strcmp(status, "erase") == 0 && state <= 0 && part == total ) {
printf("Done\n");
state = 1;
}
if ( strcmp(status, "program") == 0 && state <= 2 && part == total ) {
printf("Done\n");
state = 3;
}
}
usleep(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", strlen("update")) == 0 && cmdline[strlen("update")] <= 32 ) {
mode = NOLO_BOOT_MODE_UPDATE;
cmdline += strlen("update");
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 )
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 )
ERROR_RETURN("NOLO_REBOOT failed", -1);
return 0;
}
int nolo_get_root_device(struct usb_device_info * dev) {
uint8_t device;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_ROOT_DEVICE, (char *)&device, 1, 2000) < 0 )
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 )
ERROR_RETURN("Cannot set root device", -1);
return 0;
}
int nolo_get_usb_host_mode(struct usb_device_info * dev) {
uint32_t enabled;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_USB_HOST_MODE, (void *)&enabled, 4, 2000) < 0 )
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 )
ERROR_RETURN("Cannot change USB host mode status", -1);
return 0;
}
int nolo_get_rd_mode(struct usb_device_info * dev) {
uint8_t enabled;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_RD_MODE, (char *)&enabled, 1, 2000) < 0 )
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 )
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;
char * ptr = flags;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET, 0, NOLO_ADD_RD_FLAGS, (char *)&add_flags, 2, 2000) < 0 )
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 )
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 )
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, 8, "%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;
if ( usb_control_msg(dev->udev, NOLO_QUERY, NOLO_GET_NOLO_VERSION, 0, 0, (char *)&version, 4, 2000) < 0 )
ERROR_RETURN("Cannot get NOLO version", -1);
if ( (version & 255) > 1 )
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 )
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 )
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;
}
+64 -6
View File
@@ -1,7 +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/>.
*/
#define NOLO_GET_STATUS 1
#define NOLO_GET_BOARD_ID 2
#define NOLO_GET_VERSION 3
#define NOLO_GET_HWVERSION 4
#define NOLO_SET_RDFLAGS 16
#define NOLO_GET_RDFLAGS 17
#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
+639
View File
@@ -0,0 +1,639 @@
/*
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 "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:
usb_close_device(usb);
free(dev);
return NULL;
}
void dev_free(struct device_info * dev) {
if ( 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 )
return nolo_flash_image(dev->usb, image);
else if ( protocol == FLASH_MKII )
return mkii_flash_image(dev->usb, image);
else {
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 ) {
ERROR("Dump image via USB 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 {
usb_switch_to_nolo(dev->usb);
return 0;
}
}
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);
else {
ERROR("Rebooting device in RAW disk mode is not supported");
return -1;
}
}
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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_root_device(dev->usb, device);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_usb_host_mode(dev->usb, enable);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_rd_mode(dev->usb, enable);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_rd_flags(dev->usb, flags);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_hwrev(dev->usb, hwrev);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_kernel_ver(dev->usb, ver);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_initfs_ver(dev->usb, ver);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_nolo_ver(dev->usb, ver);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_sw_ver(dev->usb, ver);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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 ) {
if ( dev->usb->flash_device->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 ) {
if ( dev->usb->flash_device->protocol == FLASH_NOLO )
return nolo_set_content_ver(dev->usb, ver);
if ( dev->usb->flash_device->protocol == FLASH_COLD ) {
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
-19
View File
@@ -1,19 +0,0 @@
#ifndef _OS_H_
#define _OS_H_
#if __linux__ || __NetBSD__ || __FreBSD__ || __OpenBSD__ || __Darwin__ || __MacOSX__
#define HAVE_SQUEUE 1
#else
#define HAVE_SQUEUE 0
#endif
#if HAVE_SQUEUE
#include "squeue/squeue.h"
extern int qmode;
extern struct squeue_t *p;
#endif
#endif
-80
View File
@@ -1,80 +0,0 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.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>
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].device = NULL;
pcs[pcs_n].hwrevs = NULL;
pcs[pcs_n].version = NULL; // TODO version string not yet supported
} else {
/*/ autodetect piece type */
pcs[pcs_n].type = (char *)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].device = NULL;
pcs[pcs_n].hwrevs = NULL;
pcs[pcs_n].version = NULL;
}
}
pcs_n++;
return 1;
}
+48 -28
View File
@@ -1,6 +1,7 @@
/*
* 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
@@ -16,31 +17,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
unsigned long get_file_size(const 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;
}
#include "global.h"
void progressbar(unsigned long long part, unsigned long long total)
{
char *columns = getenv("COLUMNS");
#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;
int tmp, cols = 80;
/* percentage calculation */
pc = (int)(part*100/total);
@@ -53,24 +45,52 @@ void progressbar(unsigned long long part, unsigned long long total)
squeue_push2(p, "bar", msg, 0);
} else {
#endif
printf("\x1b[K %3d%% [", pc);
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("#");
for(tmp=cols-(cols*pc/100);tmp;tmp--) printf("-");
printf("]\r");
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);
#if HAVE_SQUEUE
}
#endif
}
void eprintf(const char *format, ...)
{
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 )
read(0, &c, 1);
va_start(ap, format);
vfprintf(stderr, format, ap);
vprintf(format, ap);
va_end(ap);
//fflush(stderr); // XXX CRASH?!? stdin here?!?!?
fflush(stdout);
FD_ZERO(&rfds);
FD_SET(0, &rfds);
while ( select(1, &rfds, NULL, NULL, NULL) == 1 ) {
read(0, &c, 1);
if ( 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
+36 -21
View File
@@ -1,6 +1,7 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2008 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
@@ -16,30 +17,43 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
#include "os.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include "global.h"
#include "qmode.h"
#include "nolo.h"
#if HAVE_SQUEUE
#include "squeue/squeue.h"
extern int qmode;
extern struct squeue_t *p;
#endif
#if HAVE_SQUEUE
struct squeue_t *q;
struct squeue_t *p;
int fork_enabled = 0;
int dofork()
static int fork_enabled = 0;
static int dofork()
{
if (fork_enabled)
return fork();
return 0;
}
void process_message(char *msg)
static void process_message(char *msg)
{
char *str;
char *arg;
@@ -52,24 +66,24 @@ void process_message(char *msg)
if (c!=0) {
arg[0]='\0';
arg = arg +1;
if (!strcmp(str, "flash")) {
/* if (!strcmp(str, "flash")) {
const char *type = fpid_file(arg);
if (type == NULL) {
squeue_push2(p, "error", "Unknown piece format", 1);
} else flash_image(arg, type, NULL, NULL, NULL);
} else
} else*/
if (!strcmp(str, "reset")) {
if (reboot_board() == 0) {
squeue_push2(p,"info", "Device reboots", 1);
} else squeue_push2(p,"error", "Cannot reboot device", 1);
// if (reboot_board() == 0) {
// squeue_push2(p,"info", "Device reboots", 1);
// } else squeue_push2(p,"error", "Cannot reboot device", 1);
} else
if (!strcmp(str, "info")) {
get_rd_flags();
squeue_push2(p, "info", strbuf, 1);
get_nolo_version();
squeue_push2(p, "info", strbuf, 1);
get_usb_mode();
squeue_push2(p, "info", strbuf, 1);
// get_rd_flags();
// squeue_push2(p, "info", strbuf, 1);
// get_nolo_version();
// squeue_push2(p, "info", strbuf, 1);
// get_usb_mode();
// squeue_push2(p, "info", strbuf, 1);
} else
squeue_push2(p, "error", "invalid command", 0);
} else {
@@ -78,7 +92,7 @@ void process_message(char *msg)
free(str);
}
static void cc()
static void cc(int signum)
{
squeue_close(p);
squeue_close(q);
@@ -88,7 +102,7 @@ static void cc()
exit(1);
}
int queue_mode()
int queue_mode(void)
{
int pid = 0;
char *msg;
@@ -116,11 +130,11 @@ int queue_mode()
} else {
do {
#if HAVE_USB
if (connect_via_usb()) {
/* if (connect_via_usb()) {
fprintf(stderr, "Cannot connect to device. It is possibly not in boot stage.\n");
squeue_push2(p, "error", "Cannot connect to the device", 1);
return 0;
}
}*/
#endif
printf("Waiting for a client in shared queues..\n");
setsid();
@@ -138,9 +152,10 @@ int queue_mode()
return 0;
}
#else
int queue_mode()
int queue_mode(void)
{
/* dummy */
fprintf(stderr, "No HAVE_SQUEUE support\n");
return 1;
}
#endif
+25
View File
@@ -0,0 +1,25 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2008 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 QMODE_H
#define QMODE_H
int queue_mode(void);
#endif
-363
View File
@@ -1,363 +0,0 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007-2009 pancake <@youterm.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/>.
*/
#if HAVE_USB
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <usb.h>
char strbuf[1024];
/* wait for status = 0 */
int get_status()
{
int ret = 0;
if (usb_control_msg(dev, CMD_QUERY, 1, 0, 0, (char *)&ret, 4, 2000) == -1) {
fprintf(stderr, "Cannot get device status.\n");
exit(1);
}
return ret;
}
/**
* request type: CMD_WRITE
* request : 16
* value : 0|1 (=> client|host)
* index : 2
*/
int set_usb_mode(unsigned int mode)
{
if (mode > 1) {
printf("Invalid USB mode specified '%d'.\n", mode);
return -1;
}
if (usb_control_msg(dev, CMD_WRITE, 16, mode, 2, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set USB mode.\n");
return -1;
}
printf("Set USB mode to: '%s'.\n", (mode) ? "host" : "client");
return 0;
}
/**
* request type: CMD_QUERY
* request : 17
* index : 2
*
* return value: 0|1 (=> client|host)
*/
int get_usb_mode()
{
unsigned short mode = 0;
if (usb_control_msg(dev, CMD_QUERY, 17, 0, 2, (void *) &mode, sizeof(mode), 2000) == -1) {
fprintf(stderr, "Cannot query device.\n");
return -1;
}
sprintf(strbuf, "Device's USB mode is '%s'\n", (mode) ? "host" : "client");
printf("%s", strbuf);
return 0;
}
/*
* Boots the Kernel with the given command-line.
*/
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;
}
/*
* Reboots 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, NOLO_SET_RDFLAGS, 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;
}
/*
* query root device
*/
int get_hw_revision(char *str, int len)
{
unsigned char string[512];
char tmpstr[64];
int i = 0, j=0, mod=0;
if (str == NULL)
str = tmpstr;
memset(string,'\0',512);
if (usb_control_msg(dev, CMD_QUERY, NOLO_GET_HWVERSION, 0, 0, (char *)string, 512, 2000) == -1) {
fprintf(stderr, "Cannot query hw revision.\n");
return -1;
}
for(i=0;i<44&&i<len;i++) { // XXX ??
if (string[i]>19) {
if (i>0 && string[i-1]<19)
str[j++] = (++mod%2)?':':',';
str[j++] = string[i];
}
}
printf("HW revision string: '%s'\n", str);
return 0;
}
int get_rd_mode()
{
char isrd = 1;
strbuf[0]='\0';
if (usb_control_msg(dev, CMD_QUERY, NOLO_GET_RDFLAGS, 0, 0, (char *)&isrd, 1, 2000) == -1) {
fprintf(stderr, "Cannot query rd mode.\n");
return -1;
}
sprintf(strbuf, "RD mode is: %s\n", isrd?"on":"off");
return isrd;
}
int get_root_device()
{
unsigned char opcode;
if (usb_control_msg(dev, CMD_QUERY, NOLO_GET_RDFLAGS, 0, 1, (char *)&opcode, 1, 2000) < 0) {
fprintf(stderr, "Cannot query root device\n");
return -1;
}
if (opcode>2) { // use sizeof || enum
fprintf(stderr, "Invalid root device received from the device '%d'.\n", opcode);
return -1;
}
printf("Root device is: %s\n", root_devices[opcode]);
return 0;
}
/**
* request type: CMD_WRITE
* request : 16
* value : 0|1|2 (=> flash|mmc|usb)
* index : 1
*/
int set_root_device(unsigned short root_device)
{
if (root_device>2) {
printf("Invalid root device specified '%d'.\n", root_device);
return -1;
}
if (usb_control_msg(dev, CMD_WRITE, NOLO_SET_RDFLAGS, root_device, 1, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set root device\n");
return -1;
}
printf("Root device set to: %s\n", root_devices[root_device]);
return 0;
}
/**
* Set flags:
* request type: CMD_WRITE
* request : 16
* value : flags to set, see below
* index : 3
*
* Clear flags:
* request type: CMD_WRITE
* request : 16
* value : flags to clear, see below
* index : 4
* Flags are composed of:
* 0x02 - disable OMAP watchdog (possibly)
* 0x04 - disable RETU watchdog (possibly)
* 0x08 - disable lifeguard reset
* 0x10 - enable serial console
* 0x20 - disable USB timeout
*
* The function encapsule the NOLO API in a way that it works like
* a chmod 707. The bits that are not set will be cleared after the
* call. This is done by issuing a 'clear flags' command with all the
* non set bits.
*
*/
int set_rd_flags(unsigned short flags)
{
unsigned short reverse_flags = 0;
if (flags & ~(0x02 | 0x04 | 0x08 | 0x10 | 0x20)) {
printf("Invalid rd flags specified '%x'.\n", flags);
return -1;
}
if (!(flags & 0x02))
reverse_flags |= 0x02;
if (!(flags & 0x04))
reverse_flags |= 0x04;
if (!(flags & 0x08))
reverse_flags |= 0x08;
if (!(flags & 0x10))
reverse_flags |= 0x10;
if (!(flags & 0x20))
reverse_flags |= 0x20;
if (usb_control_msg(dev, CMD_WRITE, 16, flags, 3, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set rd flags\n");
return -1;
}
if (usb_control_msg(dev, CMD_WRITE, 16, reverse_flags, 4, 0, 0, 2000) == -1) {
fprintf(stderr, "Cannot set rd flags\n");
return -1;
}
printf("Set rd flags successfully!\n");
printf("disable OMAP watchdog : %s\n", (flags & 0x02) ? "set" : "not set");
printf("disable RETU watchdog : %s\n", (flags & 0x04) ? "set" : "not set");
printf("disable lifeguard reset: %s\n", (flags & 0x08) ? "set" : "not set");
printf("enable serial console : %s\n", (flags & 0x10) ? "set" : "not set");
printf("disable USB timeout : %s\n", (flags & 0x20) ? "set" : "not set");
return 0;
}
int get_rd_flags()
{
unsigned short flags = 0;
if (usb_control_msg (dev, CMD_QUERY, NOLO_GET_RDFLAGS, 0, 3, (void *) &flags,sizeof(flags), 2000) == -1) {
fprintf(stderr, "Cannot get rd flags\n");
sprintf(strbuf, "error: Cannot read rd flags\n");
return -1;
}
sprintf (strbuf,
"Current rd flag setting:\n"
"disable OMAP watchdog : %s\n"
"disable RETU watchdog : %s\n"
"disable lifeguard reset: %s\n"
"enable serial console : %s\n"
"disable USB timeout : %s\n"
, (flags & 0x02) ? "set" : "not set"
, (flags & 0x04) ? "set" : "not set"
, (flags & 0x08) ? "set" : "not set"
, (flags & 0x10) ? "set" : "not set"
, (flags & 0x20) ? "set" : "not set");
puts (strbuf);
return 0;
}
int get_nolo_version()
{
unsigned int version; // ensure uint is at least 32 bits
//if (usb_control_msg(dev, CMD_QUERY, 3, 0, 1, (char *)&version, 4 , 2000) < 0) {
if (usb_control_msg(dev, CMD_QUERY, NOLO_GET_VERSION, 0, 0, (char *)&version, 4 , 2000) < 0) {
fprintf(stderr, "Cannot query nolo version. Old bootloader version?\n");
sprintf(strbuf, "error: Cannot query nolo version. Old bootloader?");
return -1;
}
sprintf(strbuf,
"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;
}
int get_sw_version()
{
int ret;
char bytes[1024];
strcpy(bytes, "version:sw-release");
ret = usb_control_msg(dev, CMD_WRITE, 18, 0, 0, (char *)&bytes, 18, 2000);
if (ret<0) {
fprintf(stderr, "error: cannot write query 18\n");
return 0;
}
bytes[0]='\0';
ret = usb_control_msg(dev, CMD_QUERY, 20, 0, 0, (char *)&bytes, 512, 2000);
if (ret<0) {
fprintf(stderr, "error: b0rken swversion read!\n");
return 0;
}
if (bytes[0]) {
sprintf(strbuf, "Software Version: %s\n", bytes);
printf("Software Version: %s\n", bytes); //???+strlen(bytes)+1));
} else printf("No software version detected\n");
return 1;
}
#endif
-28
View File
@@ -1,28 +0,0 @@
#ifndef QUERY_H_
#define QUERY_H_
int boot_board(char *cmdline);
int reboot_board();
int get_status();
int get_usb_mode();
int set_usb_mode(unsigned int);
int get_rd_mode();
int set_rd_mode(unsigned short mode);
int get_rd_flags();
int set_rd_flags(unsigned short flags);
int get_hw_revision(char *str, int len);
int get_root_device();
int set_root_device(unsigned short);
int get_nolo_version();
int get_sw_version();
#endif /*QUERY_H_*/
-86
View File
@@ -1,86 +0,0 @@
/*
* 0xFFFF - Open Free Fiasco Firmware Flasher
* Copyright (C) 2007 pancake <pancake@youterm.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 <getopt.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <getopt.h>
int open_serial(const char *file)
{
struct termios tc;
int fd = open (file, O_RDWR | O_SYNC);
if (fd < 0) {
perror (file);
return -1;
}
// 115200 baud, 8n1, no flow control
tcgetattr(fd, &tc);
tc.c_iflag = IGNPAR;
tc.c_oflag = 0;
tc.c_cflag = CS8 | CREAD | CLOCAL;
tc.c_lflag = 0;
cfsetispeed(&tc, B115200);
cfsetospeed(&tc, B115200);
tcsetattr(fd, TCSANOW, &tc);
return fd;
}
int console(const char *device)
{
char str[513];
int fd = open_serial(device);
int pid;
if (fd == -1) {
fprintf(stderr, "Cannot open serial device %s\n", device);
return 1;
}
pid = fork();
if (pid) {
while(1) {
fgets(str, 512, stdin);
if (write(fd, str, strlen(str)-1) == -1) {
perror("write");
exit (1);
}
}
} else {
char buf;
while(1) {
if (read(fd, &buf,1) == -1) {
perror("read");
exit (1);
}
write(1, &buf, 1);
}
}
close(fd);
return 0;
}
+349
View File
@@ -0,0 +1,349 @@
/*
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 <stdint.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <usb.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"
static struct usb_flash_device usb_devices[] = {
{ 0x0421, 0x0105, 2, 1, -1, FLASH_NOLO, { DEVICE_SU_18, DEVICE_RX_44, DEVICE_RX_48, DEVICE_RX_51, 0 } },
{ 0x0421, 0x0106, 0, -1, -1, FLASH_COLD, { DEVICE_RX_51, 0 } },
/* { 0x0421, 0x01c7, 0, -1, -1, FLASH_DISK, { DEVICE_RX_51, 0 } }, */
/* { 0x0421, 0x01c8, 1, 1, -1, FLASH_MKII, { DEVICE_RX_51, 0 } }, */
/* { 0x0421, 0x0431, 0, -1, -1, FLASH_DISK, { DEVICE_SU_18, 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) )
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_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 defined(LIBUSB_HAS_GET_DRIVER_NP) && defined(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_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_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_close(udev);
return NULL;
}
}
ret = calloc(1, sizeof(struct usb_device_info));
if ( ! ret ) {
ALLOC_ERROR();
usb_close(udev);
return NULL;
}
if ( strstr(product, "N900") )
ret->device = DEVICE_RX_51;
else
ret->device = DEVICE_UNKNOWN;
/* TODO: Autodetect more devices */
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 ( ret->device ) {
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_close(udev);
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;
}
struct usb_device_info * usb_open_and_wait_for_device(void) {
struct usb_bus * bus;
struct usb_device_info * ret = NULL;
int i = 0;
static char progress[] = {'/','-','\\', '|'};
usb_init();
usb_find_busses();
PRINTF_BACK();
printf("\n");
while ( 1 ) {
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;
usleep(0xc350); // 0.5s
}
PRINTF_BACK();
printf("\n");
if ( ! ret )
return NULL;
return ret;
}
void usb_close_device(struct usb_device_info * dev) {
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);
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);
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_mkii(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_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 )
mkii_reboot_device(dev);
}
+62
View File
@@ -0,0 +1,62 @@
/*
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 <usb.h>
#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;
};
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_mkii(struct usb_device_info * dev);
void usb_switch_to_disk(struct usb_device_info * dev);
#endif