From b1d0ce2848a79664374f802954b1e4390b11da6d Mon Sep 17 00:00:00 2001 From: pancake Date: Fri, 20 Apr 2007 18:20:22 +0200 Subject: * Initial commit of 0xFFFF. This tree contains the same as the 0.1 tarball --- COPYING | 340 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ README | 31 ++++++ doc/dumping | 45 ++++++++ doc/faq | 70 ++++++++++++ doc/nokia-tips | 105 ++++++++++++++++++ doc/oops | 2 + doc/pieces | 6 + doc/usage | 54 +++++++++ src/Makefile | 11 ++ src/dump.c | 145 ++++++++++++++++++++++++ src/fiasco.c | 136 +++++++++++++++++++++++ src/flash.c | 167 ++++++++++++++++++++++++++++ src/fpid.c | 75 +++++++++++++ src/hash.c | 62 +++++++++++ src/hash.h | 10 ++ src/hexdump.c | 67 +++++++++++ src/hexdump.h | 3 + src/main.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.h | 60 ++++++++++ src/pieces.c | 78 +++++++++++++ src/query.c | 193 ++++++++++++++++++++++++++++++++ src/utils.c | 57 ++++++++++ 22 files changed, 2060 insertions(+) create mode 100644 COPYING create mode 100644 README create mode 100644 doc/dumping create mode 100644 doc/faq create mode 100644 doc/nokia-tips create mode 100644 doc/oops create mode 100644 doc/pieces create mode 100644 doc/usage create mode 100644 src/Makefile create mode 100644 src/dump.c create mode 100644 src/fiasco.c create mode 100644 src/flash.c create mode 100644 src/fpid.c create mode 100644 src/hash.c create mode 100644 src/hash.h create mode 100644 src/hexdump.c create mode 100644 src/hexdump.h create mode 100644 src/main.c create mode 100644 src/main.h create mode 100644 src/pieces.c create mode 100644 src/query.c create mode 100644 src/utils.c diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/README b/README new file mode 100644 index 0000000..64ca4fc --- /dev/null +++ b/README @@ -0,0 +1,31 @@ + + + + ------. ,---------.--.--. + / | ___ | | | \\------------ -- . + | .__ / \/ . ____/ _/ _/ The 0pen + | / . < | | | Free Fiasco + | '- > ^ ___| _| .' Firmware Flasher + | | ' | - -- --- ----------------\\ + \_____/7_/\______ : I 0xFFFF + _/ ___|_.|__| + '` + +The 'Free Fiasco Firmware Flasher' aka 0xFFFF utility tries to implement +a free (GPL'd) userspace handler for the NOLO bootloader. + +Use it with CARE. This is an experimental tool and it can brick your device. +It's not suposed to be stable, so nokia will probably release incompatible +bootloaders to break this tool. USE IT AT YOUR OWN RISK. + +This tool has been designed and tested on n770. The n800 flash should work +but it's not tested and is known to use different request codes. + +PLEASE. Read carefully all the documentation inside doc/* for more information +before building or using the flasher to avoid questions, problems or so. + + +Have phun! + + + --pancake diff --git a/doc/dumping b/doc/dumping new file mode 100644 index 0000000..0017a33 --- /dev/null +++ b/doc/dumping @@ -0,0 +1,45 @@ +Dumping the firmware + +This technique consists on reconstructing a firmware image dumping +pieces at certains offsets of the device internal memory. + + +End user details: + + * Extract the firmware pieces from a running device + * + * This functionality is useful to extract backups of your system + * firmware. This is really useful when you're on a desert island + * without an internet connection. + * + * This tool needs more testing, so take care and don't blame me if + * it breaks your system. It *is* to your responsability, use at + * your own risk + * + * NOTE: It's theorically possible to flash the device on the fly from + * the running OS, but this has not yet been tested. Keep tuned for + * updates and newz. + * + * Have fun! + + +Technical details: + + * The internal flash memory is exposed to the system as MTD devices. So it's + * possible to dump the individual sections of a flashed firmware. + * + * READ src/dump.c for detailed information. + + mtd0 - contains xloader and sencodary pieces of the bootloaders + 0x00000 - xloader.bin (size is 0x03600) + 0x04000 - secondary.bin (size is 0x15400) + 0x1FFFF - eof + + mtd1 - looks like there's a pool ConF structures + + mtd2 - starts with NOLO img\x5c\x13 and \x00 padding + 0x00800 - zImage + + mtd3 - rootfs.jffs2 (20M) aka 0x200000 vs 0x3900000 + + mtd4 - rootfs.jffs2 (a fucking copy of the above rootfs?) diff --git a/doc/faq b/doc/faq new file mode 100644 index 0000000..1d0b805 --- /dev/null +++ b/doc/faq @@ -0,0 +1,70 @@ +FAQ + +This file tries to collect a bunch of common questions/answers about flashing + +*) Why implement a free software flasher? + + The Nokia Internet Tablets are based on Free Software (software libre), but + not everything included *is* free software, for instance, the firmware flasher + tool. + + The 0xFFFF project aims to feed the minds of those who really want to + understand how these gadgets work internally, free the knowledge to + avoid the restrictions and fill the lack of information on the most + important part of the system. + + That's it, now you can build and run this flasher on *BSD, w32, MacOSX on ARM, + powerpc, x86, mips, etc... + + +*) Can I brick my device? + + Of course! You're free to do what you want with your device :) + + Seriously. Flashing a device is not a safe thing, so I give no warranty + of what will happen to your device when using this tool. + + BTW, after a huge number of tests I can say that these devices are hard + to brick, but if you are scared about bricking your device you should + use the flasher provided by Nokia, it's better for your heart's health. + + +*) What can I do with 0xFFFF? + + Actually 0xFFFF allows you to: + + - flash separated pieces of the firmware. + - retrieve information about the device + - reboot de mother board + - extract the current firmware pieces from the device (reverse flash) + - set the USB host/slave mode + - set the R&R mode + - identify firmware pieces + + +*) What is NOLO? + + NOLO is the 'server-side' part of the flasher from Nokia. NOLO means + NOkia LOader and it's composed by two pieces of the firmware that are + flashed together. + + On the n800 firmwares, these two pieces are distributed in a single + file, but when flashing a n770, NOLO requires to provide the xloader + (without commiting) and then the secondary piece. + + This piece of software is closed source and is the responsable of + handling the requests from the client-side flasher. It provides a + query-like interface via usb control messages for doing different + actions on the device. + + +*) How can I identify my device? + + Theorically n770 and n800 have different USB device ID, but this is not + true at all. The first series of the n800 comes with the same usb-id + than n770. That's weird! + + So, the only way to identify the device is by asking nolo for the version + information of different pieces of the firmware. This can be faked, because + you can flash n770 stuff on n800 and viceversa, but it's not recommended + because it wouldn't work :) diff --git a/doc/nokia-tips b/doc/nokia-tips new file mode 100644 index 0000000..468c1a1 --- /dev/null +++ b/doc/nokia-tips @@ -0,0 +1,105 @@ +Nokia tips + +When developing this tool I've found some bugs and misfeatures that +should be fixed to make flashing safer and cleaner. + +Before reading the list of the following items I would like to say that +Nokia has done a wonderful work on this device on the flashing/nolo parts, +it's really hard to break the device and it works pretty nice. BTW I +think that there are some things that should be fixed. + + +*) Flashing at low battery level + + When the device is under a certain limit of battery it will not start, + this is done by initfs, without any warning message or so, this really + scares end users, because the battery level check is done in the initfs + boot stage, not inside NOLO, so it's possible to flash the device on + low level batteries. + + This is *really* dangerous and not very user friendly. + + +*) Internal nolo state not reset'd + + It's possible to get nolo on a strange state that always returns error + when flashing pieces, it's mandatory to reboot the device to recover + the original nolo state and be able to flash again. + + This is an strange and not very clear to me. + + +*) Buffer overflows + + The original nokia flasher has some buffer overflow bugs that should + be fixed. They're safe for 99.9% of cases, but bofs on critical programs + like this one should not be there. + + If nokia releases the source of the flasher it would be easier to make it + better and safer. BTW the original flasher is much more secure and reliable + than this one. + + +*) Missing stuff + + There are some flashing options that are not working like passing arguments + to the kernel, set the hw revision or do a cold flash (the most critical + part is undocumented). + + +*) Weird firmware format + + The (new and old) FIASCO firmware format is not a very clean format, it + doesn't provide any checksumming facility to ensure that the contents of + the firmware have been modified or incorrect, so i'll rather encourage + to design and create a standard firmware format for embedded devices with + checksumming, signatures, handling libraries, documentation and so. + + I'll happilly collaborate on the design of this open firmware format, and + it would be used on all the open source-based devices to aim interoperability + between devices and flashers, providing a more standard and reliable way of + flashing devices. + + This will ease the development on new devices, so the information and the + code could be revised and enhaced by zillions of eyes. + + +*) Poor checksumming + + The only checksum is a 16 bit xor of the whole firmware piece and it's only + checked after sending the piece to the device. + + This is not very safe, because 16 bit checksum is a very low-quality + algorithm. It currently performs a unique check at the end, it could be + better to check each data block to avoid errors or invalid flashing, isn't it ? + +*) No validation of pieces before flashing + + I've implemented a minimal check of the pieces to avoid flashing invalid + pieces on the wrong place. This is done in fpid.c (firmware piece identifier). + + This should avoid end users to flash initfs on the kernel or weird things + that can (pseudo)brick the device. + + +*) Reverse flashing + + If you want to test a new firmware, but you don't want to loose all the + contents of your device. The only way to do that (afaik) is from the + device. That's done with `0xFFFF -e [path]`. + + IMHO the reverse flashing (dump) should be implemented inside the bootloader + (NOLO in this case), and allow to retrieve (at least) the most critical + pieces of the firmware before flashing a new ones, and restore them in + case of a wrong checksumming (for example) + + +*) Documentation + + The nokia flasher comes as is, without documentation. This is not good + to anybody, because the lack of information is always the root of problems, + fear and ignorance. + + So giving a minimal documentation about how to use the flasher (not only + the basic usage stuff (like the maemo community has done in the wiki) + would be good for everybody. diff --git a/doc/oops b/doc/oops new file mode 100644 index 0000000..947a31e --- /dev/null +++ b/doc/oops @@ -0,0 +1,2 @@ +Consequences of a weird flashing :)
+ diff --git a/doc/pieces b/doc/pieces new file mode 100644 index 0000000..2ef2f47 --- /dev/null +++ b/doc/pieces @@ -0,0 +1,6 @@ +Fiasco firmware pieces +====================== + +The firmware for the maemo devices is composed by a set of pieces containing +the required parts to update the whole system following a partition layout +defined by NOLO on the internal flash memory. diff --git a/doc/usage b/doc/usage new file mode 100644 index 0000000..59caa17 --- /dev/null +++ b/doc/usage @@ -0,0 +1,54 @@ +Usage guide + +0xFFFF is a free software implementation of the flasher for the Nokia Internet +Tablets (n770 and n800). +
+  - flash separated pieces of the firmware.
+  - retrieve information about the device
+  - reboot de mother board
+  - extract the current firmware pieces from the device (dump)
+  - set the USB host/slave mode
+  - set the R&R mode
+  - identify firmware pieces
+  
+This is the help message of the tool: +
+~$ 0xFFFF -h
+0xFFFF v0.1  - The Open Free Fiasco Firmware Flasher
+ -b [arg]      boots the kernel with arguments
+ -e [path]     dump the firmware pieces into the path
+ -p [[p:]file] piece-of-firmware : file-where-this-piece-is
+ -r [0|1]      disable/enable R&D mode
+ -u [fiasco]   unpack target fiasco image
+ -U [0|1]      disable/enable the usb host mode
+ -h            show this help message
+ -i            show device information (let standby mode)
+ -I [piece]    identify a firmware piece
+ -l            list supported usb device ids
+ -d [vid:pid]  injects a usb device into the supported list
+ -R            reboot the omap board
+ -v            be verbose and noisy
+ -V            show 0xFFFF version information
+Pieces are: xloader secondary kernel initfs rootfs omap-nand 
+
+ +Before anything we can execute failsafe queries like getting device information: +
 ~$ 0xFFFF -i
+This command will put the bootloader in standby mode, so you can now send other +commands without having to reboot the tablet manually. To reboot the mother +board via USB type: +
 ~$ 0xFFFF -R
+You can run 'offline' commands to identify the type of the firmware pieces: +
 ~$ 0xFFFF -I zImage -I xloader.bin -I initfs.jffs2.orig
+ kernel: zImage
+ xloader: xloader.bin
+ initfs: initfs.jffs2.orig
+If you want to backup your device firmware you can crosscompile the 0xFFFF +utility and type this on the terminal: +
 ~$ sudo gainroot
+ ~# mkdir /media/mmc1/firmware
+ ~# ./0xFFFF -e /media/mmc1/firmware
+Now is time to flash something :) By default the flasher identifies the type +of the piece automatically, but you can force't prefixing the filename with +the piece-type name. To do this is just as simple as typing: +
 ~$ 0xFFFF -p zImage
diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..ec48974 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,11 @@ +VERSION=0.1 +OBJ=main.o fiasco.o hexdump.o dump.o flash.o +OBJ+=hash.o fpid.o query.o pieces.o utils.o +BIN=0xFFFF +CFLAGS+=-DVERSION=\"${VERSION}\" -Wall -g + +main: ${OBJ} + ${CC} ${LDFLAGS} -o ${BIN} ${OBJ} -lusb + +clean: + -rm -f ${OBJ} ${BIN} diff --git a/src/dump.c b/src/dump.c new file mode 100644 index 0000000..ca6842c --- /dev/null +++ b/src/dump.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2007 + * pancake + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "main.h" +#include +#include +#include +#include + +int rf_extract(char *dev, off_t from, off_t to, char *file) +{ + off_t i, blk = 0xfffff; + char buf[0xfffff]; + FILE *fs = fopen(dev, "rb"); + FILE *fd = fopen(file, "wb+"); + + if (from>to) { + printf("Bad range %lld - %lld for %s\n", from, to, file); + goto __rf_extract_exit; + } + if (fs == NULL) { perror(dev); goto __rf_extract_exit; } + if (fd == NULL) { perror(file); goto __rf_extract_exit; } + + printf("%s: extracting...", file); + fflush(stdout); + fseek(fs, from, SEEK_SET); + + for(i=from;ito) blk = to-i; + ret = fread(buf, blk, 1, fs); + if (feof(fs)) break; + fwrite(buf, blk, 1, fd); + } + + printf("\r%s: %lld bytes dumped from %s\n", + file, to-from, dev); + +__rf_extract_exit: + if (fs) fclose(fs); + if (fd) fclose(fd); + + + return 1; +} + +int rf_strip(char *file) +{ + FILE *fd = fopen(file, "rw"); + unsigned char buf[4096]; + int ret; + off_t eof = 0; + + if (!fd) { + fprintf(stderr, "Weird! can't open %s???\n", file); + exit(0); + } + printf("Stripping padding from %s... ", file); + fflush(stdout); + fseek(fd, 0, SEEK_END); + + do { + fseek(fd, -4096, SEEK_CUR); + ret = fread(buf, 1, 4096, fd); + fseek(fd, -4096, SEEK_CUR); + for(ret--;ret>0;ret--) + if (buf[ret]!=0xff) { + fseek(fd, ret+1, SEEK_CUR); + eof = ftell(fd); + goto __done; + } + } while(1); + +__done: + fclose(fd); + if (eof) truncate(file, eof); + printf("done at %d\n", (int)eof); + + return 1; +} + +int is_n800() +{ + int n800 = 0; + unsigned char buf[4]; + FILE *fd = fopen("/dev/mtd0", "rb"); + + if (!fd) { + fprintf(stderr, "Cannot open /dev/mtd0.\n"); + exit(1); + } + fread(buf, 4, 1,fd); + if (!memcmp("\xff\xff\xff\xff", buf, 4)) + n800 = 1; + + fclose(fd); + + return n800; +} + + +int reverse_extract_pieces(char *dir) +{ + char reply; + chdir(dir); + + rf_extract("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin"); + rf_extract("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin"); + rf_extract("/dev/mtd2", 0x000800, 0x200000, "zImage"); + rf_extract("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2"); + printf("\nWARNING: the rootfs extraction on n800 is known to be buggy! feedback is welcome.\n\n"); + printf("Extract rootfs? (Y/n): "); fflush(stdout); + read(0, &reply, 1); + if (reply=='y'||reply=='Y') + rf_extract("/dev/mtd4", 0x000000, 0xffffff, "rootfs.jffs2"); + else printf("*** Ignoring rootfs\n"); + rf_strip("xloader.bin"); + rf_strip("secondary.bin"); + rf_strip("zImage"); + rf_strip("initfs.jffs2"); + printf("Identifying extracted files...\n"); + printf("%s: xloader\n", fpid_file("xloader.bin")); + printf("%s: secondary.bin\n", fpid_file("secondary.bin")); + printf("%s: zImage\n", fpid_file("zImage")); + printf("%s: initfs.jffs2\n", fpid_file("initfs.jffs2")); + + return 1; +} diff --git a/src/fiasco.c b/src/fiasco.c new file mode 100644 index 0000000..4c49911 --- /dev/null +++ b/src/fiasco.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2007 + * pancake + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "main.h" +#include +#include +#include +#include +#include +#include +#include + +#warning The FIASCO format is not yet fully implemented. + +off_t piece_header_to_size(unsigned char *header) +{ + off_t sz = 0; + sz += header[0x15+3]; + sz += header[0x15+2] << 8; + sz += header[0x15+1] << 16; + sz += header[0x15+0] << 24; + return sz; +} + +int piece_header_is_valid(unsigned char *header) +{ + if (header[0]=='T' && header[1]=='\x02') + return 1; + return 0; +} + +#define piece_header_to_name(x) x+0x9; + +/* + * Teh Fiasco firmware parser lives here! + */ +int fiasco_read_image(char *file) +{ + int fd; + unsigned char header[5]; + unsigned char version[55]; + char *version2; + + fd = open(file, O_RDONLY); + + printf("WARNING: Fiasco firmware is not yet fully supported. Don't relay on it ATM.\n"); + + if (fd == -1) { + printf("Cannot open fiasco image.\n"); + return -1; + } + + // b4 00 00 00 00 36 + if (read(fd, header, 5) != 5) { + printf("Error reading fiasco header\n"); + goto __fiasco_read_image_end; + } + + if (header[0] != 0xb4) { + printf("Invalid fiasco signature.\n"); + goto __fiasco_read_image_end; + } + // skip 6 bytes + read(fd, version, 6); + + // print version header + if (read(fd, version, 55) != 55) { + printf("Error reading fiasco version.\n"); + goto __fiasco_read_image_end; + } + + printf("# Fiasco header information:\n"); + printf("# ==========================\n"); + printf("# firmware type: %s\n", version); + version2 = version+strlen((char *)version)+3; + if (*version2=='.') + printf("firmware version: (null) (old firmware? no version string found?)\n"); + else printf("firmware version: %s\n", version2); + + // pieces: + // after the version2 string starts the header-body loop love + lseek(fd, 0xf + strlen(version2) + strlen(version), SEEK_SET); + do { + char piece_header[30]; + char description[256]; + unsigned char desc_len; + char *name; + off_t size; + off_t tmp = lseek(fd, 0, SEEK_CUR); + + size = read(fd, piece_header, 30); + if (size != 30) { + fprintf(stderr, "Unexpected end of file\n"); + break; + } + dump_bytes(piece_header,30); + if (!piece_header_is_valid(piece_header)) { + fprintf(stderr, "Oops. Invalid piece header.\n"); + break; + } + size = piece_header_to_size(piece_header); + name = piece_header_to_name(piece_header); + printf("# %s is %lld bytes\n", name, size); + + read(fd, description, 255); + printf("# version: %s\n", description); + /* lseek foreach subimage */ + lseek(fd, tmp, SEEK_SET); + lseek(fd, strlen(description) + 0x20, SEEK_CUR); + printf("rsc '%s' %lld '%s.bin' 0 %lld\n", file, lseek(fd,0,SEEK_CUR), name, size); + lseek(fd, size, SEEK_CUR); + } while(1); + + //printf("Image '%s', size %d bytes.\n", image, size); + +__fiasco_read_image_end: + close(fd); + return 0; +} diff --git a/src/flash.c b/src/flash.c new file mode 100644 index 0000000..7a8ddd1 --- /dev/null +++ b/src/flash.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2007 + * pancake + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "main.h" +#include "hash.h" +#include +#include +#include +#include + +void check_nolo_order_failed() +{ + fprintf(stderr, "\nERROR: Provide xloader before the secondary. NOLO disagrees anything else.\n"); + fprintf(stderr, "Use: -p xloader.bin -p secondary.bin\n"); + exit(1); +} + +void check_nolo_order() +{ + int i, xlo = 0; + + for(i=0;i> 24; + bsize[1] = (size & 0x00ff0000) >> 16; + bsize[2] = (size & 0x0000ff00) >> 8; + bsize[3] = (size & 0x000000ff); + printf("size: %lld (%02x %02x %02x %02x)\n", + size, bsize[0], bsize[1], bsize[2], bsize[3]); + memcpy(fquery+0x13, &bsize, 4); + if (vlen) memcpy(fquery+27, version, vlen); + + if (!strcmp(piece, "rootfs")) + request = 85; + else request = 68; + + //dump_bytes(fquery, 27+vlen); + if (usb_control_msg(dev, CMD_WRITE, request, 0, 0, (char *)fquery, 27+vlen, 2000) <0) { + perror("flash_image.header"); + exit(1); + } + + /*/ cook and bulk nollo filler */ + memset(&nolofiller, '\xff', 128); + memcpy(nolofiller+0x00, "NOLO filler", 11); + memcpy(nolofiller+0x40, "NOLO filler", 11); + usb_bulk_write(dev, 2, (char *)nolofiller, 128, 5000); + usb_bulk_write(dev, 2, (char *)nolofiller, 0, 5000); + + /*/ bulk write image here */ + printf("[=] Bulkwriting the %s piece...\n", piece); + fflush(stdout); + + for(off = 0; offBSIZE) bsize = BSIZE; + bread = fread(buf, bsize, 1, fd); + if (bread != 1) + printf("WARNING: Oops wrong read %d vs %d \n", bread, bsize); + bread = usb_bulk_write(dev, 2, buf, bsize, 5000); + progressbar(off, size); + if (bread<0) perror(" -ee- "); + fflush(stdout); + } + fclose(fd); + /*/ EOF */ + usb_bulk_write(dev, 2, (char *)nolofiller, 0, 1000); + progressbar(1, 1); + printf("\n"); + + // index = 4???? + if (!strcmp(piece, "rootfs")) { + if (usb_control_msg(dev, CMD_WRITE, 82, 0, 0, (char *)fquery, 0, 30000)<0) { + fprintf(stderr, "Oops. Invalid checksum?\n"); + exit(1); + } + } else { + int t = 0; + if (!strcmp(piece, "secondary")) + t = 1; + else + if (!strcmp(piece, "kernel")) + t = 3; + else + if (!strcmp(piece, "initfs")) + t = 4; + if (!strcmp(piece, "xloader")) + printf("xloader flashed not commiting until secondary arrives...\n"); + else + if (usb_control_msg(dev, CMD_WRITE, 80, 0, t, (char *)fquery, 0, 10000)<0) { + fprintf(stderr, "Oops. Invalid checksum?\n"); + exit(1); + } + } + + // unknown query !! :"" + if (usb_control_msg(dev, CMD_WRITE, 67, 0, 0, (char *)fquery, 0, 2000)<0) { + fprintf(stderr, "Oops, the flash was denied or so :/\n"); + exit(1); + } + printf("Flash done succesfully.\n"); +} diff --git a/src/fpid.c b/src/fpid.c new file mode 100644 index 0000000..93bf205 --- /dev/null +++ b/src/fpid.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007 + * pancake + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "main.h" +#include +#include + +char *fpid_file(char *filename) +{ + FILE *fd; + char buf[512]; + unsigned char *b = (unsigned char *)&buf; + char *piece = NULL; + long size; + + // 2nd : +0x34 = 2NDAPE + // secondary: +0x04 = NOLOScnd + // x-loader : +0x14 = X-LOADER + // xloader8 : +0x0c = NOLOXldr + // kernel : +0x00 = 0000 a0e1 0000 a0e1 + // initfs : <2M...be sure with 3M 0x300000 + + fd = fopen(filename, "r"); + if (fd == NULL) { + printf("Cannot open file '%s'\n", filename); + return NULL; + } + fread(buf, 512, 1, fd); + fseek(fd, 0, SEEK_END); + size = ftell(fd); + fclose(fd); + +#if 0 + if (!memcmp(b+0x34, "2NDAPE", 6)) + return PIECE_2ND; + else +#endif + if (!memcmp(b+0x04, "NOLOScnd", 8)) + return pieces[PIECE_SECONDARY]; + else + if (!memcmp(b+0x14, "X-LOADER", 8)) + return pieces[PIECE_XLOADER]; + else + if (!memcmp(b+0x0c, "NOLOXldr", 8)) // TODO: this is xloader800, not valid on 770? + return pieces[PIECE_XLOADER]; + else + if (!memcmp(b+0x00, "\x00\x00\xa0\xe1\x00\x00\xa0\xe1", 8)) + return pieces[PIECE_KERNEL]; + else + if (!memcmp(b+0x00, "\x85\x19\x01\xe0", 4)) { + /*/ is jffs2 */ + if (size < 0x300000) + return pieces[PIECE_INITFS]; + return pieces[PIECE_ROOTFS]; + } + + return piece; +} diff --git a/src/hash.c b/src/hash.c new file mode 100644 index 0000000..53a3542 --- /dev/null +++ b/src/hash.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 + * pancake + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include "hash.h" + +usho do_hash(usho *b, int len) +{ + usho result = 0; + for(len>>=1;len--;b=b+1) + result^=b[0]; + return result; +} + +usho do_hash_file(char *filename) +{ + unsigned char buf[BSIZE]; + FILE *fd = fopen(filename, "r"); + usho hash = 0; + int ret; + + if (fd == NULL) { + fprintf(stderr, "ERROR: File '%s' not found.\n", filename); + return -1; + } + + do { ret = fread(&buf, 1, BSIZE, fd); + if (ret == -1) + return 0; + hash ^= do_hash((usho *)&buf, ret); + } while(ret); + + fclose(fd); + + return hash; +} + +#if 0 +main() +{ + usho us = do_hash_file("zImage"); + unsigned char *h= (unsigned char *)&us; + printf("%x %x\n",h[0],h[1]); +} +#endif diff --git a/src/hash.h b/src/hash.h new file mode 100644 index 0000000..b7de788 --- /dev/null +++ b/src/hash.h @@ -0,0 +1,10 @@ +#ifndef _INCLUDE_HASH_H_ +#define _INCLUDE_HASH_H_ + +#define usho unsigned short +#define BSIZE 0x20000 + +usho do_hash(usho *b, int len); +usho do_hash_file(char *filename); + +#endif diff --git a/src/hexdump.c b/src/hexdump.c new file mode 100644 index 0000000..6718d82 --- /dev/null +++ b/src/hexdump.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2006-2007 + * pancake + * + * radare is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * radare is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with radare; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#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) { + fprintf(stderr, " "); + continue; + } + fprintf(stderr, "%02x ", buf[j]); + } + fprintf(stderr, " "); + for(j=i; j= len) + fprintf(stderr, " "); + else + if ( is_printable(buf[j]) ) + fprintf(stderr, "%c", buf[j]); + else fprintf(stderr, "."); + } + fprintf(stderr, "\n"); + } + fflush(stderr); +} diff --git a/src/hexdump.h b/src/hexdump.h new file mode 100644 index 0000000..b28462c --- /dev/null +++ b/src/hexdump.h @@ -0,0 +1,3 @@ +char getprintablechar(char a); +int is_printable (int c); +void dump_bytes(unsigned char *buf, int len); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..7812ae1 --- /dev/null +++ b/src/main.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2007 + * pancake + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "main.h" +#include +#include +#include +#include +#include + +/* global pr0n */ +struct usb_device *device = NULL; +struct usb_dev_handle *dev = NULL; +char *fiasco_image = NULL; +char *boot_cmdline = NULL; +char *reverseto = NULL; +int rdflags = -1; +int usb_mode = -1; +int verbose = 0; +int identify = 0; +int reboot = 0; +int unpack = 0; +int info = 0; + +/* global structs */ +char *pieces[] = { + "xloader", // xloader.bin + "secondary", // secondary.bin + "kernel", // zImage + "initfs", // jffs'd initfs + "rootfs", // 80mB of blob + "omap-nand", // 8kB of food for the nand + NULL +}; + +char *modes[]={ + "host", + "peripheral", + NULL +}; + +char *root_devices[] = { + "flash", + "mmc", + "usb", + NULL +}; + +struct devices { + char *name; + unsigned short vendor_id; + unsigned short product_id; + unsigned short flags; +}; + +#define SUPPORTED_DEVICES 5 +struct devices supported_devices[SUPPORTED_DEVICES] = { + { "unkn", 0x421, 0x3f00, 0x0000 }, // probably a development board + { "n770", 0x421, 0x0105, 0x0001 }, // my n770 + { "n800", 0x421, 0x04c3, 0x0001 }, // a n800 + { 0 }, + { 0 } +}; + +int is_valid_device(struct usb_device_descriptor *udd) +{ + int i; + struct devices ptr = supported_devices[0]; + + for(i=0 ; ptr.vendor_id; ptr = supported_devices[++i]) + if ((udd->idVendor == ptr.vendor_id) + && (udd->idProduct == ptr.product_id)) { + printf("found %s (%04x:%04x)\n", + ptr.name, ptr.vendor_id, ptr.product_id); + return 1; + } + + return 0; +} + +void list_valid_devices() +{ + int i; + struct devices ptr = supported_devices[0]; + + for(i=0; ptr.vendor_id; ptr = supported_devices[++i]) + printf("%04x:%04x %s\n", ptr.vendor_id, ptr.product_id, ptr.name); +} + +int usb_device_found(struct usb_device_descriptor *udd) +{ + if (usb_find_busses() < 0) { + fprintf(stderr, "error: no usb busses found.\n"); + exit(1); + } else { + if (usb_find_devices() < 0) { + fprintf(stderr, "error: no devices found.\n"); + exit(1); + } else { + struct usb_bus *bus; + 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 (is_valid_device(udd)) { + device = dev; + return 1; + } + } + } + } + } + + return 0; +} +/*------------- devices -----------------------*/ + +void show_title() +{ + printf("0xFFFF v%s - The Free Fiasco Firmware Flasher\n", VERSION); +} + +void show_usage() +{ + int i; + show_title(); + + printf(" -b [arg] boots the kernel with arguments\n"); + printf(" -e [path] dump and extract pieces to path\n"); + printf(" -p [[p%%]file] piece-of-firmware %% file-where-this-piece-is\n"); + printf(" -r [0|1] disable/enable R&D mode\n"); + printf(" -u [fiasco] unpack target fiasco image\n"); + printf(" -U [0|1] disable/enable the usb host mode\n"); + printf(" -h show this help message\n"); + printf(" -i show device information (let standby mode)\n"); + printf(" -I [piece] identify a firmware piece\n"); + printf(" -l list supported usb device ids\n"); + printf(" -d [vid:pid] injects a usb device into the supported list\n"); + printf(" -R reboot the omap board\n"); + printf(" -v be verbose and noisy\n"); + printf(" -V show 0xFFFF version information\n"); + printf("Pieces are: "); + for(i=0;pieces[i];i++) printf("%s ", pieces[i]); printf("\n"); + // serial port support is not yet done (cold flash is for flashing the 8kB nand) + // TODO: commandline shell prompt for nolo comm + + exit(0); +} + +void unpack_fiasco_image(char *file) +{ + fiasco_read_image(file); + // TODO +} + +int query_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; + } + 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; + } + printf("SWVERSION GOT: %s\n", bytes); //???+strlen(bytes)+1)); + return 1; +} + +int main(int argc, char **argv) +{ + struct usb_device_descriptor udd; + int c; + + while((c = getopt(argc, argv, "p:vVhRu:ib:U:r:e:ld:I:")) != -1) { + switch(c) { + case 'd': + sscanf(optarg, "%04hx:%04hx", + &supported_devices[SUPPORTED_DEVICES-2].vendor_id, + &supported_devices[SUPPORTED_DEVICES-2].product_id); + supported_devices[SUPPORTED_DEVICES-2].name = strdup("user"); + break; + case 'e': + reverseto = optarg; + break; + case 'U': + usb_mode = atoi(optarg); + break; + case 'r': + rdflags = atoi(optarg); + break; + case 'b': + boot_cmdline = optarg; + break; + case 'u': + fiasco_image = optarg; + unpack = 1; + break; + case 'p': + add_piece(optarg); + break; + case 'l': + list_valid_devices(); + return 0; + case 'I': + printf("%s: %s\n", fpid_file(optarg), optarg); + identify = 1; + break; + case 'i': + info = 1; + break; + case 'v': + verbose = 1; + break; + case 'h': + show_usage(); + break; + case 'V': + printf("%s\n", VERSION); + return 0; + case 'R': + reboot = 1; + break; + } + } + + if (identify) + return 0; + + // flags ok? + if ( (fiasco_image == NULL) + && (boot_cmdline == NULL) + && (reverseto == NULL) + && (pcs_n == 0) + && (rdflags == -1) + && (info == 0) + && (reboot == 0) + && (usb_mode == -1)) + { + printf("Usage: 0xFFFF [-hvVRi] [-e path] [-U 0|1] [-p [piece%]file [-p ...]]\n"); + printf(" [-b boot-args] [-I piece [-I ...]] [-u fiasco-image]\n"); + return 1; + } + + if (unpack) { + unpack_fiasco_image(fiasco_image); + return 0; + } + + if (reverseto) { + reverse_extract_pieces(reverseto); + return 0; + } + + // usb_set_debug(5); + usb_init(); + + while(!usb_device_found(&udd)) { + char pbc[]={'/','-','\\', '|'}; + usleep(0xc350); // 0.5s + printf("\rWaiting for device... %c", pbc[++c%4]); + fflush(stdout); + } + + /*/ open device */ + dev = usb_open(device); + if (dev == NULL) { + perror("usb_open"); + return 1; + } + // TODO + if ( usb_claim_interface(dev, 2) < 0) { // 2 or 0 + perror("usb_claim_interface"); + return 1; + } + + if (usb_set_altinterface(dev, 1) < 0) { + perror("usb_set_altinterface"); + return 1; + } + + set_rd_mode(rdflags); + + /* go go go! */ + while(get_status()); + + // if (info) + sleep(1); // take breath + query_root_device(); // only for flashing + query_rdmode_device(); + query_hw_revision(); // get hardware revision: + + if (pcs_n) { + int c; + + check_nolo_order(); + query_sw_version(); + query_nolo_version(); + + for(c=0;c + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "main.h" +#include +#include +#include + +int pcs_n = 0; +struct piece_t pcs[10]; + +int add_piece(char *piece) +{ + int i,ok = 0; + char *file; + + if (pcs_n==9) { + fprintf(stderr, "Oops...cannot add more pieces. no sense operation!\n"); + return 0; + } + + file = strchr(piece, '%'); + if (file) { + file[0]='\0'; + file = file + 1; + for(i=0;pieces[i];i++) + if (!strcmp(pieces[i], piece)) + ok = 1; + if (!ok) { + printf("Invalid piece name.\n"); + printf("Pieces: "); + for(i=0;pieces[i];i++) + printf("%s ", pieces[i]); + printf("\n"); + exit(1); + } + + pcs[pcs_n].name = strdup(file); + pcs[pcs_n].type = strdup(piece); + pcs[pcs_n].vers = NULL; // TODO version string not yet supported + } else { + /*/ autodetect piece type */ + pcs[pcs_n].type = fpid_file(piece); + if (pcs[pcs_n].type == NULL) { + printf("Use -p [piece]:[file]\n"); + printf("Pieces: "); + for(i=0;pieces[i];i++) + printf("%s ", pieces[i]); + printf("\n"); + exit(1); + } else { + pcs[pcs_n].name = strdup(piece); + pcs[pcs_n].type = strdup(pcs[pcs_n].type); + pcs[pcs_n].vers = NULL; + } + } + + pcs_n++; + + return 1; +} diff --git a/src/query.c b/src/query.c new file mode 100644 index 0000000..bdbcf69 --- /dev/null +++ b/src/query.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2007 + * pancake + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "main.h" +#include +#include +#include +#include + +/* wait for status = 0 */ +int get_status() +{ + int ret = 0; + if (usb_control_msg(dev, 192, 1, 0, 0, (char *)&ret, 4, 2000) == -1) { + fprintf(stderr, "Cannot get device status.\n"); + exit(1); + } + + return ret; +} + +int get_peripheral_host_mode(int foo) +{ + //unsigned short mode = 0; + + // XXX BROKEN +#if 0 + if (usb_control_msg(dev, 64, 16, 2, 0, 2, 0, 0, 2000)) { + fprintf(stderr, "Cannot query device.\n"); + return -1; + } + + printf("Device is in \"%s\" mode (%hd)\n", (mode)?"host":"peripheral", mode); +#endif + + return 0; +} +/* + * boot the omap mobo + */ + +int boot_board(char *cmdline) +{ + if (usb_control_msg(dev, CMD_WRITE, 130, 0, 0, cmdline, strlen(cmdline), 2000) == -1) { + fprintf(stderr, "Cannot boot kernel.\n"); + perror("boot_board"); + return -1; + } + + printf("Booting kernel with arguments: '%s'.\n", cmdline); + + return 0; +} + +/* + * reboot the omap mobo + */ +int reboot_board() +{ + // 131 = reboot + if (usb_control_msg(dev, CMD_WRITE, 131, 0, 0, 0, 0, 2000) == -1) { + fprintf(stderr, "Cannot reboot board.\n"); + return -1; + } + + printf("Mobo rebooted!\n"); + + return 0; +} + +int set_rd_mode(unsigned short mode) +{ + if (((short)mode)==-1) + return 1; + + if (usb_control_msg(dev, CMD_WRITE, 16, mode, 0, 0, 0, 2000) == -1) { + fprintf(stderr, "Cannot set R&D flags.\n"); + return 1; + } + + printf("rd mode changed to %s\n", mode?"on":"off"); + + return 0; +} + +// mode = 1 || 0 +int set_usb_host_mode(unsigned short mode) +{ + if (usb_control_msg(dev, CMD_WRITE, 16, mode, 2, 0, 0, 2000) == -1) { + fprintf(stderr, "Cannot change the usb-host mode.\n"); + return -1; + } + + printf("USB host mode is %s.\n", mode?"enabled":"disabled"); + + return 0; +} + +/* + * query root device + */ +int query_hw_revision() +{ + unsigned char string[512]; + int i = 0; + + if (usb_control_msg(dev, CMD_QUERY, 4, 0, 0, (char *)string, 512, 2000) == -1) { + fprintf(stderr, "Cannot query hw revision.\n"); + return -1; + } + + printf("HW revision string: '"); + for(i=0;i<44;i++) { // XXX ?? + if (string[i]==0) { + printf(" "); + } else { + if (string[i]>19) + printf("%c", string[i]); + } + } + printf("'\n"); + + return 0; +} + +int query_rdmode_device() +{ + char isrd = 1; + + if (usb_control_msg(dev, CMD_QUERY, 17, 0, 0, (char *)&isrd, 1, 2000) == -1) { + fprintf(stderr, "Cannot query rd mode.\n"); + return -1; + } + printf("RD mode is: %s\n", isrd?"on":"off"); + + return isrd; +} + +int query_root_device() +{ + unsigned char opcode; + + if (usb_control_msg(dev, 192, 17, 0, 1, (char *)&opcode, 1, 2000) < 0) { + fprintf(stderr, "Cannot query root device\n"); + return -1; + } + + if (opcode>2) { // use sizeof || enum + printf("Invalid root device received from the device '%d'.\n", opcode); + } + + printf("Root device is: %s\n", root_devices[opcode]); + + return 0; +} + +int query_nolo_version() +{ + unsigned int version; // ensure uint is at least 32 bits + + //if (usb_control_msg(dev, 192, 3, 0, 1, (char *)&version, 4 , 2000) < 0) { + if (usb_control_msg(dev, 192, 3, 0, 0, (char *)&version, 4 , 2000) < 0) { + fprintf(stderr, "Cannot query nolo version. Old bootloader version?\n"); + exit(1); + } + + printf("NOLO Version %d.%d.%d\n", + version >> 20 & 15, + version >> 16 & 15, + version >> 8 & 255); + + if ((version & 255)> 1) + printf("Invalid API version (%d)\n", version&255); + + return 0; +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..67808de --- /dev/null +++ b/src/utils.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007 + * pancake + * + * 0xFFFF is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 0xFFFF is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0xFFFF; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "main.h" +#include +#include +#include +#include + +unsigned long get_file_size(char *file) +{ + FILE *fd = fopen(file, "r"); + unsigned long len = 0; + if (fd == NULL) { + fprintf(stderr, "Cannot open file '%s'\n", file); + exit(1); + } + fseek(fd, 0, SEEK_END); + len = ftell(fd); + fclose(fd); + return len; +} + +void progressbar(unsigned long long part, unsigned long long total) +{ + char *columns = getenv("COLUMNS"); + int pc; + int tmp, cols = 80; + + pc = (int)(part*100/total); + (pc<0)?pc=0:(pc>100)?pc=100:0; + printf("\e[K %3d%% [", pc); + if (columns) + cols = atoi(columns); + cols-=15; + for(tmp=cols*pc/100;tmp;tmp--) printf("#"); + for(tmp=cols-(cols*pc/100);tmp;tmp--) printf("-"); + printf("]\r"); + fflush(stdout); +} -- cgit v1.2.3