diff options
author | madmonkey <madfkingmonkey@gmail.com> | 2017-01-01 06:14:20 +0300 |
---|---|---|
committer | madmonkey <madfkingmonkey@gmail.com> | 2017-01-03 14:17:58 +0300 |
commit | de29903f48d7428c982e3bc80950b043a0d518e0 (patch) | |
tree | a97dd47f6edd272bcf85f82c071d01f9fff347b6 |
Initial commitv1.0
47 files changed, 3242 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2ef27f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +*.pro.user +*.img +bin/mkbootimg +bin/sntool +bin/sunxi-fel +bin/unpackbootimg +build*/ +kernel*/ +data/ +dump/ +mod/bin/busybox +mod/hakchi/transfer/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8bc2372 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "3rdparty/mkbootimg"] + path = 3rdparty/mkbootimg + url = git@github.com:osm0sis/mkbootimg.git +[submodule "3rdparty/sunxi-tools"] + path = 3rdparty/sunxi-tools + url = git@github.com:linux-sunxi/sunxi-tools.git diff --git a/3rdparty/busybox.url b/3rdparty/busybox.url new file mode 100644 index 0000000..96fedc5 --- /dev/null +++ b/3rdparty/busybox.url @@ -0,0 +1 @@ +https://busybox.net/downloads/binaries/latest/busybox-armv7l diff --git a/3rdparty/mkbootimg b/3rdparty/mkbootimg new file mode 160000 +Subproject f7472523d6195fa756db4e2cdac7bdeecec8bad diff --git a/3rdparty/sunxi-tools b/3rdparty/sunxi-tools new file mode 160000 +Subproject 1e219c0bb9051cb6252e7fb9e52c552e4aa21a2 diff --git a/3rdparty/sunxi-tools.diff b/3rdparty/sunxi-tools.diff new file mode 100644 index 0000000..887b755 --- /dev/null +++ b/3rdparty/sunxi-tools.diff @@ -0,0 +1,28 @@ +diff --git a/fel_lib.c b/fel_lib.c +index a484b4c..8d4d651 100644 +--- a/fel_lib.c ++++ b/fel_lib.c +@@ -42,8 +42,14 @@ struct _felusb_handle { + bool iface_detached; + }; + ++void no_exit(int ec) ++{ ++ (void)ec; ++} ++#define exit(x) {no_exit(x);return 0;} ++ + /* a helper function to report libusb errors */ +-void usb_error(int rc, const char *caption, int exitcode) ++void no_usb_error(int rc, const char *caption, int exitcode) + { + if (caption) + fprintf(stderr, "%s ", caption); +@@ -58,6 +64,7 @@ void usb_error(int rc, const char *caption, int exitcode) + if (exitcode != 0) + exit(exitcode); + } ++#define usb_error(x,y,z) {no_usb_error(x,y,z);if(z!=0)return 0;} + + /* + * AW_USB_MAX_BULK_SEND and the timeout constant USB_TIMEOUT are related. @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + 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/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU 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 Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0bef372 --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +all: bin/sunxi-fel bin/mkbootimg bin/unpackbootimg mod/bin/busybox build/hakchi-gui bin/sntool + +bin/sunxi-fel: 3rdparty/sunxi-tools/sunxi-fel + @cp 3rdparty/sunxi-tools/sunxi-fel bin/ + +3rdparty/sunxi-tools/sunxi-fel: 3rdparty/sunxi-tools/fel.c + @make -C 3rdparty/sunxi-tools sunxi-fel + +bin/mkbootimg: 3rdparty/mkbootimg/mkbootimg + @cp 3rdparty/mkbootimg/mkbootimg bin/ + +3rdparty/mkbootimg/mkbootimg: 3rdparty/mkbootimg/mkbootimg.c + @make -C 3rdparty/mkbootimg + +bin/unpackbootimg: 3rdparty/mkbootimg/unpackbootimg + @cp 3rdparty/mkbootimg/unpackbootimg bin/ + +3rdparty/mkbootimg/unpackbootimg: 3rdparty/mkbootimg/unpackbootimg.c + @make -C 3rdparty/mkbootimg + +mod/bin/busybox: 3rdparty/busybox.url + wget --no-use-server-timestamps $(shell cat $<) -O $@ && chmod +x $@ && upx -qq --best $@ + +build/hakchi-gui: build/Makefile hakchi-gui/src/* + @make -C build + +build/Makefile: hakchi-gui/hakchi-gui.pro + @mkdir -p build && (cd build; qmake ../$< CONFIG+=release) + +bin/sntool: sntool/sntool.cpp + @g++ -std=gnu++11 -Wall -Wextra $< -o $@ diff --git a/bin/extractimg b/bin/extractimg new file mode 100755 index 0000000..8d5d631 --- /dev/null +++ b/bin/extractimg @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +img=$1 +if [ -z "$img" ]; then + img=./dump/kernel.img +fi + +infile=$(basename "$img") +inpath=./$(basename "$infile" .img) + +rm -rf "$inpath" +mkdir "$inpath" +unpackbootimg -i "$img" -o "$inpath" +lzop -d "$inpath/$infile-ramdisk.gz" -o "$inpath/initramfs.cpio" +mkdir "$inpath/initramfs" +(cd "$inpath/initramfs";cpio -imd --no-preserve-owner --quiet -I "../initramfs.cpio") diff --git a/bin/extractimg.bat b/bin/extractimg.bat new file mode 100644 index 0000000..c6c7a2c --- /dev/null +++ b/bin/extractimg.bat @@ -0,0 +1,35 @@ +@echo off + +set img=%~f1 +if "%img%"=="" goto error + +set infile=%~nx1 +set inpath=.\%~n1 + +if exist "%inpath%" rd /s /q "%inpath%" +if %errorlevel% neq 0 goto error + +md "%inpath%" +if %errorlevel% neq 0 goto error + +unpackbootimg -i "%img%" -o "%inpath%" +if %errorlevel% neq 0 goto error + +lzop -d "%inpath%\%infile%-ramdisk.gz" -o "%inpath%\initramfs.cpio" +if %errorlevel% neq 0 goto error + +md "%inpath%\initramfs" +if %errorlevel% neq 0 goto error + +cd "%inpath%\initramfs" +if %errorlevel% neq 0 goto error + +cpio -imd --no-preserve-owner --quiet -I "..\initramfs.cpio" +if %errorlevel% neq 0 goto error + +exit /b %errorlevel% + +:error +if %errorlevel% equ 0 set errorlevel=7 +echo %0 %1 -^> exit %errorlevel% ?!? +exit /b %errorlevel% diff --git a/bin/felboot b/bin/felboot new file mode 100755 index 0000000..9c22814 --- /dev/null +++ b/bin/felboot @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +sunxi-fel version + +sunxi-fel write 0x2000 data/fes1.bin +sunxi-fel exe 0x2000 + +sunxi-fel -p write 0x43800000 kernel.img +sunxi-fel -p write 0x47000000 data/uboot.bin +sunxi-fel exe 0x47000000 diff --git a/bin/makeimg b/bin/makeimg new file mode 100755 index 0000000..4f3a5f4 --- /dev/null +++ b/bin/makeimg @@ -0,0 +1,31 @@ +#!/bin/bash +set -e + +inpath=$1 +if [ -z "$inpath" ]; then + inpath=./kernel +fi + +infile=$(basename "$inpath").img +img=./$infile + +rm -rf "$inpath/initramfs/hakchi/transfer" +(cd "$inpath/../mod";cp -a * "../$inpath/initramfs/") +if [ "$2" == "notx" ]; then + rm -rf "$inpath/initramfs/hakchi/transfer" +fi +upx -qq --best "$inpath/initramfs/sbin/cryptsetup" || true +(cd "$inpath/initramfs";find . -print0 | sort -z | cpio -0o -H newc -R root:root --quiet > ../initramfs.cpio) +lzop --best -f -o "$inpath/$infile-ramdisk.gz" "$inpath/initramfs.cpio" + +mkbootimg \ +--kernel "$inpath/$infile-zImage" \ +--ramdisk "$inpath/$infile-ramdisk.gz" \ +--cmdline "$(cat $inpath/$infile-cmdline)" \ +--board "$(cat $inpath/$infile-board)" \ +--base "$(cat $inpath/$infile-base)" \ +--pagesize "$(cat $inpath/$infile-pagesize)" \ +--kernel_offset "$(cat $inpath/$infile-kerneloff)" \ +--ramdisk_offset "$(cat $inpath/$infile-ramdiskoff)" \ +--tags_offset "$(cat $inpath/$infile-tagsoff)" \ +-o "$img" diff --git a/bin/makeimg.bat b/bin/makeimg.bat new file mode 100644 index 0000000..8d7959d --- /dev/null +++ b/bin/makeimg.bat @@ -0,0 +1,38 @@ +@echo off + +set inpath=%~f1 +if "%inpath%"=="" goto error + +set infile=%~nx1.img +set img=.\%~nx1.img + +if exist "%inpath%\initramfs\hakchi\transfer" rd /s /q "%inpath%\initramfs\hakchi\transfer" +xcopy "%inpath%\..\mod" "%inpath%\initramfs" /h /y /c /r /s /q || cd >nul +if "%2"=="notx" if exist "%inpath%\initramfs\hakchi\transfer" rd /s /q "%inpath%\initramfs\hakchi\transfer" +if %errorlevel% neq 0 goto error + +upx -qq --best "%inpath%\initramfs\sbin\cryptsetup" || cd >nul + +mkbootfs "%inpath%\initramfs" > "%inpath%\initramfs.cpio" +if %errorlevel% neq 0 goto error + +lzop --best -f -o "%inpath%\%infile%-ramdisk.gz" "%inpath%\initramfs.cpio" +if %errorlevel% neq 0 goto error + +set /p cmdline=<"%inpath%\%infile%-cmdline" +set /p board=<"%inpath%\%infile%-board" +set /p base=<"%inpath%\%infile%-base" +set /p pagesize=<"%inpath%\%infile%-pagesize" +set /p kerneloff=<"%inpath%\%infile%-kerneloff" +set /p ramdiskoff=<"%inpath%\%infile%-ramdiskoff" +set /p tagsoff=<"%inpath%\%infile%-tagsoff" + +mkbootimg --kernel "%inpath%\%infile%-zImage" --ramdisk "%inpath%\%infile%-ramdisk.gz" --cmdline "%cmdline%" --board "%board%" --base "%base%" --pagesize "%pagesize%" --kernel_offset "%kerneloff%" --ramdisk_offset "%ramdiskoff%" --tags_offset "%tagsoff%" -o "%img%" +if %errorlevel% neq 0 goto error + +exit /b %errorlevel% + +:error +if %errorlevel% equ 0 set errorlevel=7 +echo %0 %1 %2 -^> exit %errorlevel% ?!? +exit /b %errorlevel% diff --git a/hakchi-gui/hakchi-gui.pro b/hakchi-gui/hakchi-gui.pro new file mode 100644 index 0000000..8505b8a --- /dev/null +++ b/hakchi-gui/hakchi-gui.pro @@ -0,0 +1,17 @@ +QT+=core gui +greaterThan(QT_MAJOR_VERSION,4):QT+=widgets +TARGET=hakchi-gui +TEMPLATE=app + +INCLUDEPATH+=$${PWD}/../3rdparty/sunxi-tools $${PWD}/../3rdparty/sunxi-tools/include $${PWD}/../3rdparty/mkbootimg +DEPENDPATH+=$${PWD}/src $${PWD}/../3rdparty/sunxi-tools $${PWD}/../3rdparty/sunxi-tools/include +LIBS += $$system(pkg-config --libs \"libusb-1.0 >= 1.0.0\" --static) +QMAKE_CFLAGS += $$system(pkg-config --cflags \"libusb-1.0 >= 1.0.0\") -std=gnu99 -DNDEBUG -Wall -Wextra +QMAKE_CXXFLAGS += $$system(pkg-config --cflags \"libusb-1.0 >= 1.0.0\") -Wall -Wextra + +SOURCES += fel_lib.c soc_info.c progress.c + +SOURCES += $${PWD}/src/*.cpp +SOURCES += $${PWD}/src/*.c +HEADERS += $${PWD}/src/*.h +FORMS += $${PWD}/src/*.ui diff --git a/hakchi-gui/src/fel.cpp b/hakchi-gui/src/fel.cpp new file mode 100644 index 0000000..67387b8 --- /dev/null +++ b/hakchi-gui/src/fel.cpp @@ -0,0 +1,299 @@ +#include "fel.h" +#include <QScopedPointer> +extern "C" { +#include "fel_lib.h" +} +#include "md5int.h" +#include <stdio.h> + +struct FeldevHandle:public feldev_handle{}; +static const char*fastboot="fastboot_test"; + +struct spFree +{ + static inline void cleanup(void*pointer) + { + free(pointer); + } +}; + +uboot_t::uboot_t() +{ + memset(&md5,0,sizeof(md5)); + cmdOffset=0; +} + +void uboot_t::init(const QByteArray&ba) +{ + data=ba; + md5calc(data.data(),data.size(),md5); + cmdOffset=0; + QByteArray pattern("bootcmd="); + for(int i=0;i<(data.size()-pattern.size());i++) + { + if(memcmp(data.data()+i,pattern.data(),pattern.size())==0) + { + cmdOffset=i+pattern.size(); + cmd=QByteArray(data.data()+cmdOffset); + break; + } + } + if(cmdOffset==0) + { + *this=uboot_t(); + } +} + +void uboot_t::doCmd(const char*str) +{ + size_t size=strlen(str); + Q_ASSERT(size<(size_t)cmd.size()); + memset(data.data()+cmdOffset,0,cmd.size()); + memcpy(data.data()+cmdOffset,str,size); +} + +Fel::Fel(QObject*parent):QObject(parent) +{ + dev=0; + dramInitOk=false; + feldev_init(); +} + +Fel::~Fel() +{ + feldev_done(dev); +} + +bool Fel::init() +{ + if(dev==0) + { +#if 0 + size_t size=0; + QScopedPointer<feldev_list_entry,spFree>devs(list_fel_devices(&size)); + if(size==0) + { + return false; + } + if(size>1) + { + return false; + } +#endif + dev=static_cast<FeldevHandle*>(feldev_open(-1,-1,AW_USB_VENDOR_ID,AW_USB_PRODUCT_ID)); + while((dev!=0)&&(dev->soc_info->soc_id!=0x1667)) + { + release(); + sleep(2); + dev=static_cast<FeldevHandle*>(feldev_open(-1,-1,AW_USB_VENDOR_ID,AW_USB_PRODUCT_ID)); + } + } + return dev!=0; +} + +bool Fel::initDram(bool force) +{ + if(dramInitOk&&!force) + return true; + + uint8_t buf[0x80]; + if((size_t)fes1bin.size()<sizeof(buf)) + return false; + if(!force)emit dataFlow(-sizeof(buf)); + if((force)||(readMemory(fes1_base_m+fes1bin.size()-sizeof(buf),sizeof(buf),buf)==sizeof(buf))) + { + if((!force)&&(memcmp(buf,fes1bin.data()+fes1bin.size()-sizeof(buf),sizeof(buf))==0)) + { + dramInitOk=true; + return true; + } + printf("uploading fes1.bin ..."); + emit dataFlow(-fes1bin.size()); + if(writeMemory(fes1_base_m,fes1bin.size(),fes1bin.data())==(size_t)fes1bin.size()) + { + printf(" done\n"); + dramInitOk=true; + return runCode(fes1_base_m,2); + } + printf(" failed\n"); + } + return false; +} + +void Fel::release() +{ + feldev_close(dev); + dev=0; +} + +void Fel::setFes1bin(const QByteArray&data) +{ + fes1bin=data; +} + +void Fel::setUboot(const QByteArray&data) +{ + uboot.init(data); +} + +bool Fel::haveUboot()const +{ + return uboot.cmdOffset>0; +} + +bool Fel::runCode(uint32_t addr,uint32_t s) +{ + if(init()) + { + aw_fel_execute(dev,addr); + release(); + if(s==0xffffffff) + { + dramInitOk=false; + return true; + } + sleep(s); + for(int i=0;i<8;i++) + if(init()) + break; + return init(); + } + return false; +} + +bool Fel::runUbootCmd(const char*str,bool noreturn) +{ + if(init()&&haveUboot()) + { + uboot.doCmd(str); + uint8_t buf[0x20]; + emit dataFlow(-sizeof(buf)); + if(!readMemory(uboot_base_m,sizeof(buf),buf)==sizeof(buf)) + return false; + if(memcmp(buf,uboot.data.data(),sizeof(buf))==0) + { + size_t size=(uboot.cmd.size()+3)/4; + size*=4; + emit dataFlow(-size); + if(writeMemory(uboot_base_m+uboot.cmdOffset,size,uboot.data.data()+uboot.cmdOffset)!=size) + return false; + } + else + { + printf("uploading uboot.bin ..."); + emit dataFlow(-uboot.data.size()); + if(writeMemory(uboot_base_m,uboot.data.size(),uboot.data.data())!=(size_t)uboot.data.size()) + { + printf(" failed\n"); + return false; + } + printf(" done\n"); + } + printf("%s\n",str); + return runCode(uboot_base_m,noreturn?0xffffffff:10); + } + return false; +} + +static const size_t maxTransfer=0x10000; + +size_t Fel::readMemory(uint32_t addr,size_t size,void*buf) +{ + if(init()) + { + if((addr>=dram_base)&&(!initDram())) + return 0; + size&=(~3); + size_t transfer=size; + while(transfer) + { + size_t b=qMin(transfer,maxTransfer); + aw_fel_read(dev,addr,buf,b); + emit dataFlow(b); + addr+=b; + buf=((uint8_t*)buf)+b; + transfer-=b; + } + return size; + } + return 0; +} + +size_t Fel::writeMemory(uint32_t addr,size_t size,void*buf) +{ + if(init()) + { + if((addr>=dram_base)&&(!initDram())) + return 0; + size&=(~3); + size_t transfer=size; + while(transfer) + { + size_t b=qMin(transfer,maxTransfer); + aw_fel_write(dev,buf,addr,b); + emit dataFlow(b); + addr+=b; + buf=((uint8_t*)buf)+b; + transfer-=b; + } + return size; + } + return 0; +} + +size_t Fel::readFlash(uint32_t addr,size_t size,void*buf) +{ + if((!init())||(!haveUboot())) + return 0; + if(((size+addr%sector_size+sector_size-1)/sector_size)>flash_mem_size) + { + size_t sectors=(size+addr%sector_size+sector_size-1)/sector_size-flash_mem_size; + size_t read=readFlash(addr,sectors*sector_size-addr%sector_size,buf); + addr+=read; + size-=read; + buf=static_cast<uint8_t*>(buf)+read; + } + if(((size+addr%sector_size+sector_size-1)/sector_size)>flash_mem_size) + { + return 0; + } + char cmd[1024]; + sprintf(cmd,"sunxi_flash phy_read %x %x %x;%s",flash_mem_base,addr/sector_size,(size+addr%sector_size+sector_size-1)/sector_size,fastboot); + if(runUbootCmd(cmd)) + { + return readMemory(flash_mem_base+addr%sector_size,size,buf); + } + return 0; +} + +size_t Fel::writeFlash(uint32_t addr,size_t size,void*buf) +{ + if((!init())||(!haveUboot())) + return 0; + if((addr%sector_size)!=0) + return 0; + if((size%sector_size)!=0) + return 0; + if((size/sector_size)>flash_mem_size) + { + size_t sectors=(size/sector_size)-flash_mem_size; + size_t write=writeFlash(addr,sectors*sector_size,buf); + if((write%sector_size)!=0) + return 0; + addr+=write; + size-=write; + buf=static_cast<uint8_t*>(buf)+write; + } + if((size/sector_size)>flash_mem_size) + { + return 0; + } + if(writeMemory(flash_mem_base,size,buf)==size) + { + char cmd[1024]; + sprintf(cmd,"sunxi_flash phy_write %x %x %x;%s",flash_mem_base,addr/sector_size,size/sector_size,fastboot); + if(runUbootCmd(cmd)) + return size; + } + return 0; +} diff --git a/hakchi-gui/src/fel.h b/hakchi-gui/src/fel.h new file mode 100644 index 0000000..2bebb4a --- /dev/null +++ b/hakchi-gui/src/fel.h @@ -0,0 +1,62 @@ +#ifndef FEL_H +#define FEL_H + +#include <stdint.h> +#include <unistd.h> +#include <QObject> +#include <QByteArray> + +struct FeldevHandle; + +struct uboot_t +{ + QByteArray data; + uint8_t md5[16]; + QByteArray cmd; + uint32_t cmdOffset; + + uboot_t(); + void init(const QByteArray&ba); + void doCmd(const char*str); +}; + +#define fes1_base_m 0x2000u +#define dram_base 0x40000000u +#define uboot_base_m 0x47000000u +#define uboot_base_f 0x100000u +#define flash_mem_base 0x43800000u +#define flash_mem_size 0x20u +#define sector_size 0x20000u +#define kernel_base_f (sector_size*0x30) +#define kernel_base_m flash_mem_base +#define kernel_max_size (uboot_base_m-flash_mem_base) +#define kernel_max_flash_size (sector_size*0x20) + +class Fel:public QObject +{ + Q_OBJECT +public: + Fel(QObject*parent=0); + ~Fel(); + bool init(); + bool initDram(bool force=false); + void release(); + void setFes1bin(const QByteArray&data); + void setUboot(const QByteArray&data); + bool haveUboot()const; + bool runCode(uint32_t addr,uint32_t s); + bool runUbootCmd(const char*str,bool noreturn=false); + size_t readMemory(uint32_t addr,size_t size,void*buf); + size_t writeMemory(uint32_t addr,size_t size,void*buf); + size_t readFlash(uint32_t addr,size_t size,void*buf); + size_t writeFlash(uint32_t addr,size_t size,void*buf); +signals: + void dataFlow(int flow); +private: + FeldevHandle*dev; + QByteArray fes1bin; + uboot_t uboot; + bool dramInitOk; +}; + +#endif // FEL_H diff --git a/hakchi-gui/src/main.cpp b/hakchi-gui/src/main.cpp new file mode 100644 index 0000000..d41a131 --- /dev/null +++ b/hakchi-gui/src/main.cpp @@ -0,0 +1,31 @@ +#include "mainwindow.h" +#include <QApplication> +#include <QDir> +#include <stdlib.h> + +int main(int argc,char*argv[]) +{ + QDir dir("."); + for(int i=0;i<4;i++) + { + if(dir.exists("bin")) + break; + else + dir.cdUp(); + } + if(dir.exists("bin")) + dir.setCurrent(dir.absolutePath()); + QString path=QString::fromLocal8Bit(getenv("PATH")); +#ifdef WIN32 + path=QString("PATH=%1\\bin;%2").arg(dir.absolutePath()).arg(path); + _putenv(path.toLocal8Bit()); +#else + path=QString("%1/bin:%2").arg(dir.absolutePath()).arg(path); + setenv("PATH",path.toLocal8Bit(),1); +#endif + + QApplication a(argc,argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/hakchi-gui/src/mainwindow.cpp b/hakchi-gui/src/mainwindow.cpp new file mode 100644 index 0000000..810acdb --- /dev/null +++ b/hakchi-gui/src/mainwindow.cpp @@ -0,0 +1,141 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include <QTimer> +#include <QThread> +#include <QPointer> +#include <QMessageBox> +#include <QElapsedTimer> +#include "worker.h" +#include "wincon.h" + +class CThreadWaiter +{ +public: + CThreadWaiter(QObject*o) + { + obj=o; + thread=new QThread(); + thread->start(); + o->moveToThread(thread); + QObject::connect(o,SIGNAL(destroyed()),thread,SLOT(quit())); + } + ~CThreadWaiter() + { + QElapsedTimer timer; + timer.start(); + static const qint64 maxWait=0x600,i1=0x100; + if(!obj.isNull()) + { + obj->deleteLater(); + while((!obj.isNull())&&(timer.elapsed()<maxWait)) + if(thread->wait(10)) + break; + } + thread->quit(); + if(!thread->wait(qMax(maxWait-timer.elapsed(),i1))) + exit(1); + delete thread; + } +private: + QPointer<QObject> obj; + QThread*thread; +}; + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + ui->progressBar->setVisible(false); + Worker*worker=new Worker(); + waiter[0]=new CThreadWaiter(worker); + connect(worker,SIGNAL(busy(bool)),ui->mainToolBar,SLOT(setDisabled(bool))); + connect(worker,SIGNAL(progress(int)),this,SLOT(progress(int))); + connect(this,SIGNAL(doWork(int)),worker,SLOT(doWork(int))); + + CWinCon*winCon=new CWinCon(); + waiter[1]=new CThreadWaiter(winCon); + connect(winCon,SIGNAL(msg(QString)),this,SLOT(showMessage(QString))); + connect(this,SIGNAL(readNext()),winCon,SLOT(readOutput())); + QTimer::singleShot(256,this,SIGNAL(readNext())); + + srand(0); + printf("Knock, knock "); +} + +MainWindow::~MainWindow() +{ + disconnect(SIGNAL(readNext())); + printf("bye!\n"); + delete waiter[0]; + delete waiter[1]; + delete ui; +} + +void MainWindow::progress(int p) +{ + bool visible=false; + if((p>0)&&(p<100)) + visible=true; + if(ui->progressBar->isVisible()!=visible) + ui->progressBar->setVisible(visible); + if((visible)&&(ui->progressBar->value()!=p)) + ui->progressBar->setValue(p); +} + +void MainWindow::showMessage(const QString&msg) +{ + static int mm[2]={0x18,0x60}; + static int knock=14; + if(knock<32) + { + if(--knock==0) + { + knock=32; + mm[0]/=6; + mm[1]/=6; + ui->plainTextEdit->clear(); + } + } + ui->plainTextEdit->moveCursor(QTextCursor::End); + ui->plainTextEdit->insertPlainText(msg); + QTimer::singleShot(mm[0]+(rand()%(mm[1]-mm[0])),this,SIGNAL(readNext())); +} + +void MainWindow::on_actionDump_uboot_triggered() +{ + emit doWork(Worker::dumpUboot); +} + +void MainWindow::on_actionDump_kernel_img_triggered() +{ + emit doWork(Worker::dumpKernel); +} + +void MainWindow::on_actionUnpack_kernel_img_triggered() +{ + emit doWork(Worker::unpackKernel); +} + +void MainWindow::on_actionRebuild_kernel_img_triggered() +{ + emit doWork(Worker::packKernel); +} + +void MainWindow::on_actionFlash_kernel_triggered() +{ + if(QMessageBox::warning(this,"","sure?",QMessageBox::Yes|QMessageBox::Abort,QMessageBox::Abort)!=QMessageBox::Yes) + return; + emit doWork(Worker::flashKernel); +} + +void MainWindow::on_actionMemboot_triggered() +{ + emit doWork(Worker::memboot); +} + +void MainWindow::on_actionShutdown_triggered() +{ + emit doWork(Worker::shutdown); +} diff --git a/hakchi-gui/src/mainwindow.h b/hakchi-gui/src/mainwindow.h new file mode 100644 index 0000000..1ca2917 --- /dev/null +++ b/hakchi-gui/src/mainwindow.h @@ -0,0 +1,39 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> + +namespace Ui { +class MainWindow; +} + +class CThreadWaiter; + +class MainWindow:public QMainWindow +{ + Q_OBJECT +public: + explicit MainWindow(QWidget*parent=0); + ~MainWindow(); + +signals: + void doWork(int work); + void readNext(); + +private slots: + void progress(int p); + void showMessage(const QString&msg); + void on_actionDump_uboot_triggered(); + void on_actionDump_kernel_img_triggered(); + void on_actionUnpack_kernel_img_triggered(); + void on_actionRebuild_kernel_img_triggered(); + void on_actionFlash_kernel_triggered(); + void on_actionMemboot_triggered(); + void on_actionShutdown_triggered(); + +private: + Ui::MainWindow*ui; + CThreadWaiter*waiter[2]; +}; + +#endif // MAINWINDOW_H diff --git a/hakchi-gui/src/mainwindow.ui b/hakchi-gui/src/mainwindow.ui new file mode 100644 index 0000000..d7ade2c --- /dev/null +++ b/hakchi-gui/src/mainwindow.ui @@ -0,0 +1,265 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>860</width> + <height>480</height> + </rect> + </property> + <widget class="QWidget" name="centralWidget"> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="spacing"> + <number>2</number> + </property> + <property name="leftMargin"> + <number>3</number> + </property> + <property name="topMargin"> + <number>3</number> + </property> + <property name="rightMargin"> + <number>3</number> + </property> + <property name="bottomMargin"> + <number>3</number> + </property> + <item> + <widget class="QGroupBox" name="groupBox"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="spacing"> + <number>2</number> + </property> + <property name="leftMargin"> + <number>3</number> + </property> + <property name="topMargin"> + <number>3</number> + </property> + <property name="rightMargin"> + <number>3</number> + </property> + <property name="bottomMargin"> + <number>3</number> + </property> + <item> + <widget class="QPlainTextEdit" name="plainTextEdit"> + <property name="palette"> + <palette> + <active> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>14</red> + <green>186</green> + <blue>14</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>14</red> + <green>186</green> + <blue>14</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="Text"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>14</red> + <green>185</green> + <blue>14</blue> + </color> + </brush> + </colorrole> + <colorrole role="Base"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QProgressBar" name="progressBar"> + <property name="palette"> + <palette> + <active> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>14</red> + <green>185</green> + <blue>14</blue> + </color> + </brush> + </colorrole> + </active> + <inactive> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>14</red> + <green>185</green> + <blue>14</blue> + </color> + </brush> + </colorrole> + </inactive> + <disabled> + <colorrole role="Window"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>0</red> + <green>0</green> + <blue>0</blue> + </color> + </brush> + </colorrole> + <colorrole role="Highlight"> + <brush brushstyle="SolidPattern"> + <color alpha="255"> + <red>14</red> + <green>185</green> + <blue>14</blue> + </color> + </brush> + </colorrole> + </disabled> + </palette> + </property> + <property name="value"> + <number>50</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QToolBar" name="mainToolBar"> + <property name="movable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextOnly</enum> + </property> + <property name="floatable"> + <bool>false</bool> + </property> + <attribute name="toolBarArea"> + <enum>RightToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="actionDump_uboot"/> + <addaction name="actionDump_kernel_img"/> + <addaction name="actionUnpack_kernel_img"/> + <addaction name="actionRebuild_kernel_img"/> + <addaction name="actionFlash_kernel"/> + <addaction name="actionMemboot"/> + <addaction name="actionShutdown"/> + </widget> + <widget class="QStatusBar" name="statusBar"/> + <action name="actionDump_uboot"> + <property name="text"> + <string>dump uboot</string> + </property> + </action> + <action name="actionDump_kernel_img"> + <property name="text"> + <string>dump kernel.img</string> + </property> + </action> + <action name="actionRebuild_kernel_img"> + <property name="text"> + <string>rebuild kernel.img</string> + </property> + </action> + <action name="actionMemboot"> + <property name="text"> + <string>memboot</string> + </property> + </action> + <action name="actionUnpack_kernel_img"> + <property name="text"> + <string>unpack kernel.img</string> + </property> + </action> + <action name="actionFlash_kernel"> + <property name="text"> + <string>flash kernel</string> + </property> + </action> + <action name="actionShutdown"> + <property name="text"> + <string>shutdown</string> + </property> + </action> + </widget> + <layoutdefault spacing="6" margin="11"/> + <resources/> + <connections/> +</ui> diff --git a/hakchi-gui/src/md5int.c b/hakchi-gui/src/md5int.c new file mode 100644 index 0000000..716862f --- /dev/null +++ b/hakchi-gui/src/md5int.c @@ -0,0 +1,211 @@ +#include "md5int.h" +#include <string.h> +#include <stdio.h> + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +#define F(x,y,z) (((x)&(y))|((~x)&(z))) +#define G(x,y,z) (((x)&(z))|((y)&(~z))) +#define H(x,y,z) ((x)^(y)^(z)) +#define I(x,y,z) ((y)^((x)|(~z))) + +#define _lrotl(x,n) ((((unsigned long)(x)) << ((int) ((n) & 31))) | (((unsigned long)(x)) >> ((int) ((-(n)) & 31)))) +#define ROTATE_LEFT(x,n) _lrotl(x,n) + +#define FF(a,b,c,d,x,s,ac) {\ + (a)+=F((b),(c),(d))+(x)+(uint32_t)(ac);\ + (a)=ROTATE_LEFT((a),(s));\ + (a)+=(b);} +#define GG(a,b,c,d,x,s,ac) {\ + (a)+=G((b),(c),(d))+(x)+(uint32_t)(ac);\ + (a)=ROTATE_LEFT((a),(s));\ + (a)+=(b);} +#define HH(a,b,c,d,x,s,ac) {\ + (a)+=H((b),(c),(d))+(x)+(uint32_t)(ac);\ + (a)=ROTATE_LEFT((a),(s));\ + (a)+=(b);} +#define II(a,b,c,d,x,s,ac) {\ + (a)+=I((b),(c),(d))+(x)+(uint32_t)(ac);\ + (a)=ROTATE_LEFT((a),(s));\ + (a)+=(b);} + +void md5init(md5context*context) +{ + context->count[0]=context->count[1]=0; + context->state[0]=0x67452301; + context->state[1]=0xefcdab89; + context->state[2]=0x98badcfe; + context->state[3]=0x10325476; +} + +void md5final(md5context*context,void*_digest_) +{ + uint8_t*digest=(uint8_t*)_digest_; + + uint8_t bits[8]; + uint8_t PADDING[64]; + uint32_t index, padLen; + + /* Save number of bits */ + memcpy (bits, context->count, 8); + + /* Pad out to 56 mod 64. */ + index = (uint32_t)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + memset(PADDING,0,64); + PADDING[0]=0x80; + md5update (context, PADDING, padLen); + + /* Append length (before padding) */ + md5update (context, bits, 8); + + /* Store state in digest */ + memcpy (digest, context->state, 16); + + /* Zeroize sensitive information. */ + memset ((uint8_t*)context, 0, sizeof (*context)); +} + +static void md5transform(uint32_t state[4],const uint8_t block[64]) +{ + uint32_t a=state[0],b=state[1],c=state[2],d=state[3]; + const uint32_t*x=(const uint32_t*)(&block[0]); + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + state[0]+=a; + state[1]+=b; + state[2]+=c; + state[3]+=d; +} + +void md5update(md5context*context,const void*_input_,uint32_t inputLen) +{ + const uint8_t*const input=(const uint8_t*)_input_; + + uint32_t i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (uint32_t)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((uint32_t)inputLen << 3)) < ((uint32_t)inputLen << 3)) + context->count[1]++; + + context->count[1] += ((uint32_t)inputLen >> 29); + partLen = 64 - index; + + /* Transform as many times as possible.*/ + if (inputLen >= partLen) + { + memcpy(&context->buffer[index], input, partLen); + md5transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + md5transform (context->state, &input[i]); + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + memcpy(&context->buffer[index], &input[i], inputLen-i); +} + +void md5calc(const void*_input_,uint32_t inputLen,void*_digest_) +{ + md5context context; + md5init(&context); + md5update(&context,_input_,inputLen); + md5final(&context,_digest_); +} + +char*md5print(const void*md5,char*str) +{ + const uint8_t*src=md5; + for(int i=0;i<16;i++) + { + str+=sprintf(str,"%.2x",*src++); + } + return str-32; +} diff --git a/hakchi-gui/src/md5int.h b/hakchi-gui/src/md5int.h new file mode 100644 index 0000000..719abc5 --- /dev/null +++ b/hakchi-gui/src/md5int.h @@ -0,0 +1,27 @@ +#ifndef MD5INT_H +#define MD5INT_H + +#include <stdint.h> + +typedef struct +{ + uint8_t buffer[64]; + uint32_t state[4]; + uint32_t count[2]; +} md5context; + +#ifdef __cplusplus +extern "C" { +#endif + +void md5init(md5context*); +void md5update(md5context*,const void*,uint32_t); +void md5final(md5context*,void*); +void md5calc(const void*,uint32_t,void*); +char*md5print(const void*md5,char*str); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hakchi-gui/src/wincon.cpp b/hakchi-gui/src/wincon.cpp new file mode 100644 index 0000000..bce5a3a --- /dev/null +++ b/hakchi-gui/src/wincon.cpp @@ -0,0 +1,59 @@ +#include "wincon.h" +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#ifdef WIN32 +#include <io.h> +#endif + +CWinCon::CWinCon(QObject*parent):QObject(parent) +{ + con=0; + int filedes[2]; +#ifdef WIN32 + if(_pipe(filedes,0x10000,O_BINARY|O_NOINHERIT)>=0) +#else + if(pipe(filedes)>=0) +#endif + { + fflush(stdout); + fflush(stderr); +#ifdef WIN32 + while((_dup2(filedes[1],STDOUT_FILENO)<0)&&(errno==EINTR)){} + while((_dup2(filedes[1],STDERR_FILENO)<0)&&(errno==EINTR)){} + _close(filedes[1]); + *stdout=*_fdopen(STDOUT_FILENO,"wb"); + *stderr=*_fdopen(STDERR_FILENO,"wb"); + con=_fdopen(filedes[0],"rb"); +#else + while((dup2(filedes[1],STDOUT_FILENO)<0)&&(errno==EINTR)){} + while((dup2(filedes[1],STDERR_FILENO)<0)&&(errno==EINTR)){} + ::close(filedes[1]); + con=fdopen(filedes[0],"rb"); +#endif + setvbuf(stdout,0,_IONBF,0); + setvbuf(stderr,0,_IONBF,0); + } +} + +CWinCon::~CWinCon() +{ + if(con) + { + fclose(con); + con=0; + } +} + +void CWinCon::readOutput() +{ + if(con) + { + //fucking windows + char buffer[1]; + ssize_t size=fread(buffer,1,sizeof(buffer),con); + if(size>0) + emit msg(QString::fromLocal8Bit(buffer,size)); + } +} diff --git a/hakchi-gui/src/wincon.h b/hakchi-gui/src/wincon.h new file mode 100644 index 0000000..a51a857 --- /dev/null +++ b/hakchi-gui/src/wincon.h @@ -0,0 +1,20 @@ +#ifndef WINCON_H +#define WINCON_H + +#include <QObject> + +class CWinCon:public QObject +{ + Q_OBJECT +public: + explicit CWinCon(QObject*parent=0); + ~CWinCon(); +signals: + void msg(const QString&msg); +public slots: + void readOutput(); +private: + FILE*con; +}; + +#endif // WINCON_H diff --git a/hakchi-gui/src/worker.cpp b/hakchi-gui/src/worker.cpp new file mode 100644 index 0000000..4b9d3bb --- /dev/null +++ b/hakchi-gui/src/worker.cpp @@ -0,0 +1,408 @@ +#include "worker.h" +#include "fel.h" +#include <QDir> +#include "bootimg.h" +#include "md5int.h" + +#ifdef WIN32 +#include <windows.h> +#define le32toh(x) (x) +#endif + +static const QString kernelFile("dump/kernel.img"); + +#ifdef WIN32 +int system_hidden(const char*cmd) +{ + int result=7; + STARTUPINFOA si; + PROCESS_INFORMATION pi; + memset(&si,0,sizeof(si)); + memset(&pi,0,sizeof(pi)); + si.cb=sizeof(STARTUPINFO); + si.dwFlags=STARTF_USESTDHANDLES; + si.hStdOutput=(HANDLE)_get_osfhandle(_fileno(stdout)); + si.hStdError=(HANDLE)_get_osfhandle(_fileno(stderr)); + QString cmdl("cmd /c "); + cmdl+=QString::fromLocal8Bit(cmd).replace('/','\\'); + if(CreateProcessA(getenv("COMSPEC"),cmdl.toLocal8Bit().data(),0,0,TRUE,NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&si,&pi)) + { + CloseHandle(pi.hThread); + WaitForSingleObject(pi.hProcess,INFINITE); + GetExitCodeProcess(pi.hProcess,(LPDWORD)&result); + CloseHandle(pi.hProcess); + } + return result; +} +#define system(x) system_hidden(x) +#endif + +int saveFile(const char*fileName,void*X,size_t fs) +{ + int rv=0; + FILE*hf=fopen(fileName,"wb"); + if(hf) + { + if(fwrite(X,1,fs,hf)==fs) + { + rv=1; + } + fclose(hf); + } + return rv; +} + +size_t loadFile(const char*fileName,void*X) +{ + size_t fs=0; + FILE*hf=fopen(fileName,"rb"); + if(hf) + { + fseek(hf,0,SEEK_END); + fs=ftell(hf); + if(X) + { + fseek(hf,0,SEEK_SET); + if(fread(X,1,fs,hf)!=fs) + { + fs=0; + } + } + fclose(hf); + } + return fs; +} + +QByteArray loadFile(const char*fileName) +{ + size_t fs=loadFile(fileName,0); + if(fs) + { + QByteArray data(fs,Qt::Uninitialized); + if(loadFile(fileName,data.data())==fs) + return data; + } + return QByteArray(); +} + +Worker::Worker(QObject*parent):QObject(parent) +{ + fel=0; + progressFlow=0; + progressTotal=0; +} + +Worker::~Worker() +{ + delete fel; +} + +void flushOutput() +{ + fflush(stdout); + fflush(stderr); +#ifdef WIN32 + FlushFileBuffers((HANDLE)_get_osfhandle(STDOUT_FILENO)); + FlushFileBuffers((HANDLE)_get_osfhandle(STDERR_FILENO)); +#endif +} + +void Worker::doWork(int work) +{ + progressFlow=0; + progressTotal=0; + emit busy(true); + emit progress(0); + flushOutput(); + switch(work) + { + case dumpUboot: + do_dumpUboot(); + break; + case dumpKernel: + do_dumpKernel(); + break; + case unpackKernel: + do_unpackKernel(); + break; + case packKernel: + do_packKernel(); + break; + case flashKernel: + do_flashKernel(); + break; + case memboot: + do_memboot(); + break; + case shutdown: + do_shutdown(); + break; + default: + Q_ASSERT(false); + break; + } + printf("\n"); + flushOutput(); + emit progress(100); + emit busy(false); +} + +void Worker::calcProgress(int flow) +{ + if(flow<0) + { + progressTotal-=flow; + return; + } + progressFlow+=flow; + if((progressFlow>0)&&(progressTotal>0)) + { + int p=qMin(100*progressFlow/progressTotal,100); + emit progress(p); + } +} + +bool Worker::init() +{ + if(fel) + return fel->init(); + fel=new Fel(this); + connect(fel,SIGNAL(dataFlow(int)),this,SLOT(calcProgress(int))); + QByteArray data=loadFile("data/fes1.bin"); + if(data.size()) + fel->setFes1bin(data); + else + printf("fes1.bin not found\n"); + data=loadFile("data/uboot.bin"); + if(data.size()) + fel->setUboot(data); + else + printf("uboot.bin not found\n"); + return fel->init(); +} + +void Worker::do_dumpUboot() +{ + if((!init())||(!fel->haveUboot())) + { + return; + } + size_t size=0; + QByteArray buf(sector_size*6,Qt::Uninitialized); + calcProgress(-buf.size()); + if(fel->readFlash(uboot_base_f,buf.size(),buf.data())==(size_t)buf.size()) + size=le32toh(*reinterpret_cast<uint32_t*>(buf.data()+0x14u)); + else + return; + if((size==0)||(size>kernel_max_size)) + { + printf("uboot: invalid size in header\n"); + return; + } + if(size>(size_t)buf.size()) + { + size_t oldSize=buf.size(); + buf.resize(size); + calcProgress(-(size-oldSize)); + if(fel->readFlash(uboot_base_f+oldSize,size-oldSize,buf.data()+oldSize)!=(size-oldSize)) + { + printf("uboot: read error\n"); + return; + } + } + QDir(".").mkdir("dump"); + saveFile("dump/uboot.bin",buf.data(),size); + uint8_t md5[16]; + md5calc(buf.data(),size,md5); + char md5str[40]; + printf("%s\n",md5print(md5,md5str)); + printf("%s - OK\n",Q_FUNC_INFO); +} + +static size_t kernelSize(const QByteArray&data) +{ + size_t size=0; + const boot_img_hdr*h=reinterpret_cast<const boot_img_hdr*>(data.constData()); + if(memcmp(h->magic,BOOT_MAGIC,BOOT_MAGIC_SIZE)==0) + { + size_t pages=1; + pages+=(h->kernel_size+h->page_size-1)/h->page_size; + pages+=(h->ramdisk_size+h->page_size-1)/h->page_size; + pages+=(h->second_size+h->page_size-1)/h->page_size; + pages+=(h->dt_size+h->page_size-1)/h->page_size; + size_t ks=pages*h->page_size; + if(ks<=kernel_max_size) + size=ks; + } + return size; +} + +void Worker::do_dumpKernel() +{ + if((!init())||(!fel->haveUboot())) + { + return; + } + size_t size=0; + QByteArray buf(sector_size*0x20,Qt::Uninitialized); + calcProgress(-buf.size()); + if(fel->readFlash(kernel_base_f,buf.size(),buf.data())==(size_t)buf.size()) + size=kernelSize(buf); + else + return; + if((size==0)||(size>kernel_max_size)) + { + printf("kernel: invalid size in header\n"); + return; + } + if(size>(size_t)buf.size()) + { + size_t oldSize=buf.size(); + buf.resize(size); + calcProgress(-(size-oldSize)); + if(fel->readFlash(kernel_base_f+oldSize,size-oldSize,buf.data()+oldSize)!=(size-oldSize)) + { + printf("kernel: read error\n"); + return; + } + } + QDir(".").mkdir("dump"); + saveFile(kernelFile.toLocal8Bit(),buf.data(),size); + uint8_t md5[16]; + md5calc(buf.data(),size,md5); + char md5str[40]; + printf("%s\n",md5print(md5,md5str)); + printf("%s - OK\n",Q_FUNC_INFO); +} + +void Worker::do_unpackKernel() +{ + if(::system(QString("extractimg \"%1\"").arg(kernelFile).toLocal8Bit())==0) + printf("%s - OK\n",Q_FUNC_INFO); +} + +void Worker::do_packKernel() +{ + if(::system(QString("makeimg kernel").toLocal8Bit())==0) + printf("%s - OK\n",Q_FUNC_INFO); +} + +void Worker::do_flashKernel() +{ + if((!init())||(!fel->haveUboot())) + { + return; + } + if(::system(QString("makeimg kernel notx").toLocal8Bit())!=0) + { + printf("cannot build kernel.img\n"); + return; + } + QByteArray k=loadFile("kernel.img"); + if(k.size()==0) + { + printf("kernel.img not found\n"); + return; + } + size_t ksize=kernelSize(k); + if((ksize>(size_t)k.size())||((size_t)k.size()>kernel_max_flash_size)) + { + printf("kernel: invalid size in header\n"); + return; + } + ksize=(ksize+sector_size-1)/sector_size; + ksize=ksize*sector_size; + if((size_t)k.size()!=ksize) + { + const size_t oldSize=k.size(); + k.resize(ksize); + memset(k.data()+oldSize,0,k.size()-oldSize); + } + calcProgress(-k.size()*2); + if(fel->writeFlash(kernel_base_f,k.size(),k.data())!=(size_t)k.size()) + { + printf("kernel: write error\n"); + return; + } + printf("kernel: write ok\n"); + QByteArray baver(k.size(),Qt::Uninitialized); + if(fel->readFlash(kernel_base_f,k.size(),baver.data())!=(size_t)k.size()) + { + printf("kernel: read error\n"); + return; + } + if(memcmp(k.data(),baver.data(),k.size())==0) + printf("kernel: verify ok\n"); + else + printf("kernel: verify fuck\n"); +#if 0 + if(fel->writeFlash(sector_size*(0x30+0x20-2),sector_size,k.data())==sector_size) + { + QByteArray baver(sector_size,Qt::Uninitialized); + if(fel->readFlash(sector_size*(0x30+0x20-2),sector_size,baver.data())==sector_size) + { + if(memcmp(k.data(),baver.data(),sector_size)==0) + f_printf("kernel: ok\n"); + else + f_printf("kernel: fuck\n"); + } + return; + } +#endif + char cmd[1024]; + sprintf(cmd,"boota %x",kernel_base_m); + if(!fel->runUbootCmd(cmd,true)) + { + printf("kernel: runcmd error\n"); + return; + } + printf("%s - OK\n",Q_FUNC_INFO); +} + +void Worker::do_memboot() +{ + if((!init())||(!fel->haveUboot())) + { + return; + } + QByteArray k=loadFile("kernel.img"); + if(k.size()==0) + { + printf("kernel.img not found\n"); + return; + } + const size_t ksize=kernelSize(k); + if((ksize>(size_t)k.size())||((size_t)k.size()>kernel_max_size)) + { + printf("kernel: invalid size in header\n"); + return; + } + calcProgress(-k.size()); + if(fel->writeMemory(kernel_base_m,k.size(),k.data())!=(size_t)k.size()) + { + printf("kernel: write error\n"); + return; + } + char cmd[1024]; + sprintf(cmd,"boota %x",kernel_base_m); + if(!fel->runUbootCmd(cmd,true)) + { + printf("kernel: runcmd error\n"); + return; + } + printf("%s - OK\n",Q_FUNC_INFO); +} + +void Worker::do_shutdown() +{ + if((!init())||(!fel->haveUboot())) + { + return; + } + if(!fel->runUbootCmd("shutdown",true)) + { + printf("shutdown: runcmd error\n"); + return; + } + printf("%s - OK\n",Q_FUNC_INFO); +} diff --git a/hakchi-gui/src/worker.h b/hakchi-gui/src/worker.h new file mode 100644 index 0000000..121177f --- /dev/null +++ b/hakchi-gui/src/worker.h @@ -0,0 +1,51 @@ +#ifndef WORKER_H +#define WORKER_H + +#include <QObject> +#include <QString> +#include "fel.h" + +class Worker:public QObject +{ + Q_OBJECT +public: + enum Work + { + dumpUboot, + dumpKernel, + unpackKernel, + packKernel, + flashKernel, + memboot, + shutdown + }; + explicit Worker(QObject*parent=0); + ~Worker(); + +signals: + void busy(bool b); + void progress(int p); + +public slots: + void doWork(int work); + +private slots: + void calcProgress(int flow); + +private: + bool init(); + void do_dumpUboot(); + void do_dumpKernel(); + void do_unpackKernel(); + void do_packKernel(); + void do_flashKernel(); + void do_memboot(); + void do_shutdown(); + +private: + Fel*fel; + int progressFlow; + int progressTotal; +}; + +#endif // WORKER_H diff --git a/importpath b/importpath new file mode 100644 index 0000000..36ebba7 --- /dev/null +++ b/importpath @@ -0,0 +1,4 @@ +if [ -z "$(which felboot)" ]; then + export PATH=$(pwd)/bin:$(pwd)/build:$PATH + echo PATH=$PATH +fi diff --git a/mod/bin/chroot b/mod/bin/chroot new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/chroot @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/bin/cp b/mod/bin/cp new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/cp @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/bin/dd b/mod/bin/dd new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/dd @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/bin/gzip b/mod/bin/gzip new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/gzip @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/bin/ls b/mod/bin/ls new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/ls @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/bin/mkdir b/mod/bin/mkdir new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/mkdir @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/bin/mv b/mod/bin/mv new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/mv @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/bin/poweroff b/mod/bin/poweroff new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/poweroff @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/bin/rm b/mod/bin/rm new file mode 120000 index 0000000..c3fa810 --- /dev/null +++ b/mod/bin/rm @@ -0,0 +1 @@ +busybox
\ No newline at end of file diff --git a/mod/hakchi/backup b/mod/hakchi/backup new file mode 100644 index 0000000..4325fe4 --- /dev/null +++ b/mod/hakchi/backup @@ -0,0 +1,39 @@ +backup_nandc(){ + if [ "$cf_backup_nandc" == "y" ]; then + echo backup nandc + dd if=/dev/nandc bs=128K | gzip > /nandc.gz + fi + return 0 +} + +backup(){ + backupdir=$installdir/backup + if [ -f /nandc.gz ]; then + if [ ! -f $backupdir/nandc.gz ]; then + echo move nandc + mkdir -p $backupdir + mv /nandc.gz $backupdir/ + fi + fi + if [ "$cf_backup" != "y" ]; then + return 0 + fi + mkdir -p $backupdir + if [ ! -f $backupdir/nanda.gz ]; then + echo backup nanda + dd if=/dev/nanda bs=128K | gzip > $backupdir/nanda.gz + fi + if [ ! -f $backupdir/nandb ]; then + echo backup nandb + dd if=/dev/nandb bs=128K > $backupdir/nandb + fi + if [ ! -f $backupdir/nandd.gz ]; then + echo backup nandd + dd if=/dev/nandd bs=128K | gzip > $backupdir/nandd.gz + fi + if [ ! -f $backupdir/nande.gz ]; then + echo backup nande + dd if=/dev/nande bs=128K | gzip > $backupdir/nande.gz + fi + return 0 +} diff --git a/mod/hakchi/config b/mod/hakchi/config new file mode 100644 index 0000000..13dbd9c --- /dev/null +++ b/mod/hakchi/config @@ -0,0 +1,3 @@ +cf_shutdown=y +cf_backup=n +cf_backup_nandc=n diff --git a/mod/hakchi/init b/mod/hakchi/init new file mode 100644 index 0000000..41f2dfe --- /dev/null +++ b/mod/hakchi/init @@ -0,0 +1,80 @@ +init(){ +echo + +modname=hakchi +mountpoint=/newroot +installdir=$mountpoint/var/lib/$modname +rootfs=$installdir/rootfs + +. /$modname/config +. /$modname/backup + +backup_nandc + +mount -t tmpfs -o mode=0755,nosuid,nodev tmpfs $mountpoint/var +mkdir $mountpoint/var/lib +mount -o defaults,nosuid,nodev,noatime /dev/nandc $mountpoint/var/lib + +if [ ! -f $rootfs/etc/preinit ]; then + backup + + echo installing $modname... + + rm -rf $rootfs + mkdir -p $rootfs/usr/share/games/nes + + cp -a $mountpoint/bin $rootfs/ + cp -a $mountpoint/etc $rootfs/ + cp -a $mountpoint/usr/share/games/nes/kachikachi $rootfs/usr/share/games/nes/ + + cp -a /$modname/rootfs/* $rootfs/ + cp -a /bin/busybox $rootfs/bin/ + cp -a /sbin/cryptsetup $rootfs/bin/ + + chroot $rootfs /bin/busybox --install -s /bin/ + + if [ "$cf_shutdown" == "y" ]; then + cf_shutdown=yy + fi +else + echo $modname already installed +fi + +if [ -d $modname/transfer ]; then + echo transferring data... + if [ -f $modname/transfer/transfer ]; then + . $modname/transfer/transfer + rm $modname/transfer/transfer + else + docopy=y + fi + if [ "$docopy" == "y" ]; then + cp -a $modname/transfer/* $installdir/ + fi + if [ "$cf_shutdown" == "y" ]; then + cf_shutdown=yy + fi +fi + +if [ "$cf_shutdown" == "yy" ]; then + echo shutting down... + umount $mountpoint/var/lib + umount $mountpoint/var + poweroff -f + return 0 +fi + +if [ ! -f $mountpoint/var/lib/clover/profiles/0/CLV-P-NAAAE/1.state ]; then + echo loading stock shell + umount $mountpoint/var/lib + umount $mountpoint/var + return 0 +fi + +echo loading $modname +. $rootfs/etc/preinit +preinit +return $? +} + +init diff --git a/mod/hakchi/rootfs/etc/inittab b/mod/hakchi/rootfs/etc/inittab new file mode 100644 index 0000000..8bba354 --- /dev/null +++ b/mod/hakchi/rootfs/etc/inittab @@ -0,0 +1,16 @@ +null::sysinit:/bin/mount -t proc proc /proc +null::sysinit:/bin/mkdir -p /dev/pts /dev/shm +null::sysinit:/bin/mount -a +null::sysinit:/bin/mkdir -p /var/cache /var/lock /var/log /var/spool +null::sysinit:/bin/ln -s /tmp /var/tmp +null::sysinit:/bin/ln -s /run /var/run + +null::sysinit:/bin/mkdir -p /var/cache/clover/reed-libs/tmp /var/lib/clover/profiles/0/home-menu /var/lib/clover/config/reed-libs + +null::sysinit:/etc/init.d/rcS + +null::respawn:/sbin/getty 115200 ttyS0 + +null::ctrlaltdel:/sbin/reboot +null::shutdown:/etc/init.d/rcK +null::shutdown:/bin/umount -a -r diff --git a/mod/hakchi/rootfs/etc/preinit b/mod/hakchi/rootfs/etc/preinit new file mode 100644 index 0000000..f908ebc --- /dev/null +++ b/mod/hakchi/rootfs/etc/preinit @@ -0,0 +1,8 @@ +preinit(){ + +mount -o bind $rootfs/bin $mountpoint/bin +mount -o bind $rootfs/etc $mountpoint/etc +mount -o bind $rootfs/usr/share/games/nes/kachikachi $mountpoint/usr/share/games/nes/kachikachi + +return 0 +} diff --git a/mod/hakchi/rootfs/etc/profile b/mod/hakchi/rootfs/etc/profile new file mode 100644 index 0000000..b719793 --- /dev/null +++ b/mod/hakchi/rootfs/etc/profile @@ -0,0 +1,35 @@ +# /etc/profile: system-wide .profile file for the Bourne shell (sh(1)) +# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...). + +PATH="/usr/local/bin:/usr/bin:/bin" +EDITOR="vi" # needed for packages like cron, git-commit +test -z "$TERM" && TERM="vt100" # Basic terminal capab. For screen etc. + +if [ "$HOME" = "/root" ]; then + PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin +fi +if [ "$PS1" ]; then +# works for bash and ash (no other shells known to be in use here) + PS1='\u@\h:\w\$ ' +fi + +if [ -d /etc/profile.d ]; then + for i in /etc/profile.d/*.sh ; do + if [ -f $i -a -r $i ]; then + . $i + fi + done + unset i +fi + +if [ -x /usr/bin/resize ] && termpath="`tty`"; then + # Make sure we are on a serial console (i.e. the device used starts with /dev/tty), + # otherwise we confuse e.g. the eclipse launcher which tries do use ssh + case "$termpath" in + /dev/tty*) resize >/dev/null + esac +fi + +export PATH PS1 OPIEDIR QPEDIR QTDIR EDITOR TERM + +umask 022 diff --git a/mod/sbin/init b/mod/sbin/init new file mode 100755 index 0000000..52cc5fa --- /dev/null +++ b/mod/sbin/init @@ -0,0 +1,39 @@ +#!/bin/sh + +/bin/mount -t proc proc /proc +/bin/mount -t sysfs sys /sys + +for i in $(cat /proc/cmdline); do + if [ "$i" = "ro" ] ; then + READONLY="y" + elif [ "${i#root=}" != "$i" ] ; then + ROOTFS="${i#root=}" + elif [ "$i" = "decrypt" ] ; then + DECRYPT="y" + fi +done + +MOUNT_OPTS="noatime" +if [ "${DECRYPT}" = "y" ]; then + if [ "${READONLY}" == "y" ]; then + READONLY="--readonly" + else + READONLY="" + fi + + /sbin/cryptsetup open ${ROOTFS} root-crypt ${READONLY} --type plain --cipher aes-xts-plain --key-file /key-file + /bin/mount -o "${MOUNT_OPTS}" /dev/mapper/root-crypt /newroot +else + if [ "${READONLY}" == "y" ]; then + MOUNT_OPTS="ro,${MOUNT_OPTS}" + fi + + /bin/mount -o "${MOUNT_OPTS}" ${ROOTFS} /newroot +fi + +. /hakchi/init + +/bin/mount --move /dev /newroot/dev +/bin/umount /proc +/bin/umount /sys +exec /sbin/switch_root /newroot /sbin/init diff --git a/r16-uboot/r16-uboot.diff b/r16-uboot/r16-uboot.diff new file mode 100644 index 0000000..2c7d6de --- /dev/null +++ b/r16-uboot/r16-uboot.diff @@ -0,0 +1,243 @@ +diff --git a/Makefile b/Makefile +index 1c696db..f911894 100644 +--- a/Makefile ++++ b/Makefile +@@ -441,7 +441,7 @@ $(obj)u-boot.ubl: $(obj)u-boot-nand.bin + -e $(CONFIG_SYS_TEXT_BASE) -d $< $@ + + $(obj)u-boot-$(TARGET).bin: $(obj)u-boot.bin +- @git show HEAD --pretty=format:"%H" | head -n 1 > cur.log ++ @$(TOPDIR)/fake_git show HEAD --pretty=format:"%H" | head -n 1 > cur.log + @./add_hash.sh -f u-boot.bin -m uboot + + GEN_UBOOT = \ +@@ -466,30 +466,30 @@ spl_lib: $(TIMESTAMP_FILE) $(VERSION_FILE) depend + + fes: spl_lib depend + $(MAKE) -C sunxi_spl/fes_init all +- @git show HEAD --pretty=format:"%H" | head -n 1 > cur.log ++ @$(TOPDIR)/fake_git show HEAD --pretty=format:"%H" | head -n 1 > cur.log + @./add_hash.sh -f sunxi_spl/fes_init/fes1.bin -m boot0 + @$(TOPDIR)/tools/gen_check_sum sunxi_spl/fes_init/fes1.bin fes1.bin > /dev/null + + boot0: spl_lib depend + $(MAKE) -C sunxi_spl/boot0 all + ifdef CONFIG_STORAGE_MEDIA_NAND +- @git show HEAD --pretty=format:"%H" | head -n 1 > cur.log ++ @$(TOPDIR)/fake_git show HEAD --pretty=format:"%H" | head -n 1 > cur.log + @./add_hash.sh -f sunxi_spl/boot0/boot0_nand.bin -m boot0 + @$(TOPDIR)/tools/gen_check_sum sunxi_spl/boot0/boot0_nand.bin boot0_nand.bin > /dev/null + endif + ifdef CONFIG_STORAGE_MEDIA_MMC +- @git show HEAD --pretty=format:"%H" | head -n 1 > cur.log ++ @$(TOPDIR)/fake_git show HEAD --pretty=format:"%H" | head -n 1 > cur.log + @./add_hash.sh -f sunxi_spl/boot0/boot0_sdcard.bin -m boot0 + @$(TOPDIR)/tools/gen_check_sum sunxi_spl/boot0/boot0_sdcard.bin boot0_sdcard.bin > /dev/null + endif + ifdef CONFIG_STORAGE_MEDIA_SPINOR +- @git show HEAD --pretty=format:"%H" | head -n 1 > cur.log ++ @$(TOPDIR)/fake_git show HEAD --pretty=format:"%H" | head -n 1 > cur.log + @./add_hash.sh -f sunxi_spl/boot0/boot0_spinor.bin -m boot0 + @$(TOPDIR)/tools/gen_check_sum sunxi_spl/boot0/boot0_spinor.bin boot0_spinor.bin > /dev/null + endif + sboot: spl_lib depend + $(MAKE) -C sunxi_spl/sbrom all +- @git show HEAD --pretty=format:"%H" | head -n 1 > cur.log ++ @$(TOPDIR)/fake_git show HEAD --pretty=format:"%H" | head -n 1 > cur.log + @./add_hash.sh -f sunxi_spl/sbrom/sboot.bin -m sboot + @$(TOPDIR)/tools/gen_check_sum sunxi_spl/sbrom/sboot.bin sboot.bin > /dev/null + +@@ -671,7 +671,7 @@ tools-all: easylogo env gdb $(VERSION_FILE) + + .PHONY : CHANGELOG + CHANGELOG: +- git log --no-merges U-Boot-1_1_5.. | \ ++ $(TOPDIR)/fake_git log --no-merges U-Boot-1_1_5.. | \ + unexpand -a | sed -e 's/\s\s*$$//' > $@ + + include/license.h: tools/bin2header COPYING +diff --git a/board/sunxi/load_check.c b/board/sunxi/load_check.c +old mode 100755 +new mode 100644 +diff --git a/build.sh b/build.sh +index 98ebdbb..3c3a86e 100755 +--- a/build.sh ++++ b/build.sh +@@ -16,10 +16,10 @@ show_help() + + build_uboot() + { +- make ARCH=arm CROSS_COMPILE=arm-clover-linux-gnueabihf- distclean +- make ARCH=arm CROSS_COMPILE=arm-clover-linux-gnueabihf- ${PLATFORM}_config +- make ARCH=arm CROSS_COMPILE=arm-clover-linux-gnueabihf- CONFIG_SPL=y spl fes -j16 +- make ARCH=arm CROSS_COMPILE=arm-clover-linux-gnueabihf- -B -j16 ++ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean ++ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- ${PLATFORM}_config ++ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- CONFIG_SPL=y spl fes -j1 ++ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -B -j1 + } + + while getopts p:m: OPTION +diff --git a/common/cmd_sunxi_flash.c b/common/cmd_sunxi_flash.c +index 77e5580..863f492 100644 +--- a/common/cmd_sunxi_flash.c ++++ b/common/cmd_sunxi_flash.c +@@ -176,6 +176,27 @@ int do_sunxi_flash(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) + + return ret == 0 ? 1 : 0; + } ++ else if(strncmp(cmd, "phy_write", strlen("phy_write")) == 0) ++ { ++ skip_init = 1; ++ sunxi_flash_handle_init(); ++ ++ u32 start_block; ++ u32 rblock; ++ ++ printf("write physical\n"); ++ ++ addr = (ulong)simple_strtoul(argv[2], NULL, 16); ++ start_block = (ulong)simple_strtoul(argv[3], NULL, 16); ++ rblock = (ulong)simple_strtoul(argv[4], NULL, 16); ++ ++ ret = sunxi_flash_phywrite(start_block, rblock, (void *)addr); ++ ++ tick_printf("sunxi flash phy_write :offset %x, %d sectors %s\n", start_block, rblock, ++ ret ? "OK" : "ERROR"); ++ ++ return ret == 0 ? 1 : 0; ++ } + + usage: + return cmd_usage(cmdtp); +diff --git a/config.mk b/config.mk +index 42849d5..e560a94 100644 +--- a/config.mk ++++ b/config.mk +@@ -115,8 +115,8 @@ cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \ + # + AS = $(CROSS_COMPILE)as + LD = $(CROSS_COMPILE)ld +-CC = $(CROSS_COMPILE)gcc +-CPP = $(CC) -E ++CC = $(CROSS_COMPILE)gcc -std=gnu89 ++CPP = $(CROSS_COMPILE)gcc -E + AR = $(CROSS_COMPILE)ar + NM = $(CROSS_COMPILE)nm + LDR = $(CROSS_COMPILE)ldr +diff --git a/fake_git b/fake_git +new file mode 100755 +index 0000000..beb8867 +--- /dev/null ++++ b/fake_git +@@ -0,0 +1,2 @@ ++#!/bin/bash ++echo fc3061df4dbd4153819b2d2f141d82b88fea51cf +diff --git a/include/configs/clover.h b/include/configs/clover.h +index a79af7e..467c34f 100644 +--- a/include/configs/clover.h ++++ b/include/configs/clover.h +@@ -29,6 +29,8 @@ + #define __KERNEL__ + #endif + ++#define CONFIG_FINAL ++ + #define LINUX_MACHINE_ID 4137 + + #define UBOOT_VERSION "1.1.0" +diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h +new file mode 100644 +index 0000000..94dea3f +--- /dev/null ++++ b/include/linux/compiler-gcc5.h +@@ -0,0 +1,61 @@ ++#ifndef __LINUX_COMPILER_H ++#error "Please don't include <linux/compiler-gcc4.h> directly, include <linux/compiler.h> instead." ++#endif ++ ++/* GCC 4.1.[01] miscompiles __weak */ ++#ifdef __KERNEL__ ++# if __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ <= 1 ++# error Your version of gcc miscompiles the __weak directive ++# endif ++#endif ++ ++#define __used __attribute__((__used__)) ++#define __must_check __attribute__((warn_unused_result)) ++#define __compiler_offsetof(a,b) __builtin_offsetof(a,b) ++#define __always_inline inline __attribute__((always_inline)) ++ ++/* ++ * A trick to suppress uninitialized variable warning without generating any ++ * code ++ */ ++#define uninitialized_var(x) x = x ++ ++#if __GNUC_MINOR__ >= 3 ++/* Mark functions as cold. gcc will assume any path leading to a call ++ to them will be unlikely. This means a lot of manual unlikely()s ++ are unnecessary now for any paths leading to the usual suspects ++ like BUG(), printk(), panic() etc. [but let's keep them for now for ++ older compilers] ++ ++ Early snapshots of gcc 4.3 don't support this and we can't detect this ++ in the preprocessor, but we can live with this because they're unreleased. ++ Maketime probing would be overkill here. ++ ++ gcc also has a __attribute__((__hot__)) to move hot functions into ++ a special section, but I don't see any sense in this right now in ++ the kernel context */ ++#define __cold __attribute__((__cold__)) ++ ++ ++#if __GNUC_MINOR__ >= 5 ++/* ++ * Mark a position in code as unreachable. This can be used to ++ * suppress control flow warnings after asm blocks that transfer ++ * control elsewhere. ++ * ++ * Early snapshots of gcc 4.5 don't support this and we can't detect ++ * this in the preprocessor, but we can live with this because they're ++ * unreleased. Really, we need to have autoconf for the kernel. ++ */ ++#define unreachable() __builtin_unreachable() ++#endif ++ ++#endif ++ ++#if __GNUC_MINOR__ > 0 ++#define __compiletime_object_size(obj) __builtin_object_size(obj, 0) ++#endif ++#if __GNUC_MINOR__ >= 4 ++#define __compiletime_warning(message) __attribute__((warning(message))) ++#define __compiletime_error(message) __attribute__((error(message))) ++#endif +diff --git a/sunxi_spl/boot0/main/boot0_main.c b/sunxi_spl/boot0/main/boot0_main.c +old mode 100755 +new mode 100644 +diff --git a/sunxi_spl/fes_init/main/fes_head.c b/sunxi_spl/fes_init/main/fes_head.c +index 3cee7f6..0f647d3 100644 +--- a/sunxi_spl/fes_init/main/fes_head.c ++++ b/sunxi_spl/fes_init/main/fes_head.c +@@ -50,6 +50,17 @@ const boot0_file_head_t fes1_head = { + 0, 0, '3','.','0','.','0',0 + }, + }, ++ { ++ sizeof(boot0_private_head_t), ++ 0, ++ { ++ 600,3,0x3bbb,1, ++ 283246848,0, ++ 7280,64,24,0, ++ 0x47a14f,0x1c2294c,0x69049,0x0,0x0,0x0,0x0, ++ 0x0,0x0,0x0,0x0,0x0,0xa8,0x10901 ++ } ++ } + }; + + +diff --git a/tools/gen_check_sum b/tools/gen_check_sum +index 6af1447..5040838 100755 +Binary files a/tools/gen_check_sum and b/tools/gen_check_sum differ diff --git a/r16-uboot/readme.md b/r16-uboot/readme.md new file mode 100644 index 0000000..65d5315 --- /dev/null +++ b/r16-uboot/readme.md @@ -0,0 +1,5 @@ +1. get r16-uboot-fc3061df4dbd4153819b2d2f141d82b88fea51cf.tar.gz from http://data.nintendo.co.jp/oss/NintendoEntertainmentSystemNESClassicEdition_OSS.zip +2. apply patch +3. ./build.sh +4. use sntool check -f to set checksum in fes1.bin +5. use sntool split/join to cut script.bin from stock uboot and paste into freshly compiled one diff --git a/sntool/sntool.cpp b/sntool/sntool.cpp new file mode 100644 index 0000000..27d3703 --- /dev/null +++ b/sntool/sntool.cpp @@ -0,0 +1,245 @@ +// ######################################################################### + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <memory.h> + +// ######################################################################### + +int saveFile(const char*fileName,uint8_t*X,size_t fs) +{ + int rv=0; + FILE*hf=fopen(fileName,"wb"); + if(hf) + { + if(fwrite(X,1,fs,hf)==fs) + { + rv=1; + } + fclose(hf); + } + return rv; +} + +// ######################################################################### + +size_t loadFile(const char*fileName,uint8_t*X) +{ + size_t fs=0; + FILE*hf=fopen(fileName,"rb"); + if(hf) + { + fseek(hf,0,SEEK_END); + fs=ftell(hf); + if(X) + { + fseek(hf,0,SEEK_SET); + if(fread(X,1,fs,hf)!=fs) + { + fs=0; + } + } + fclose(hf); + } + return fs; +} + +// ######################################################################### +// dd if=/dev/mapper/root-crypt | gzip | hexdump -v -e '64/1 "%02x""\n"' +int dehex(const char*in,const char*out) +{ + size_t fs=loadFile(in,0); + if(fs) + { + printf("input: %s, fs: %u\n",in,fs); + uint8_t b_in[fs+16]; + uint8_t b_out[fs+16]; + uint8_t b_tmp[4*1024]; + fs=loadFile(in,b_in); + size_t outLen=0; + size_t lineLen=0; + uint8_t octet=0,value=0; + int fileNumber=0; + for(size_t i=0;i<fs;++i) + { + uint8_t c=b_in[i]; + switch(c) + { + case 'A'...'F': + c=c-'A'+'a'; + case 'a'...'f': + c=c-'a'+'0'+10; + case '0'...'9': + c=c-'0'; + octet=1-octet; + value=(value<<4)|(c&0xf); + if(octet==0) + { + b_tmp[lineLen++]=value; + } + break; + case '\n': + if(lineLen) + { + memcpy(b_out+outLen,b_tmp,lineLen); + outLen+=lineLen; + } + case ':': + lineLen=0; + case ' ': + octet=0; + break; + default: + if(outLen) + { + char fout[1024]; + sprintf(fout,"%s_%i.bin",out,++fileNumber); + printf("output: %s, fs: %u\n",fout,outLen); + saveFile(fout,b_out,outLen); + outLen=0; + } + lineLen=0; + octet=2; + break; + } + } + } + return 0; +} + +// ######################################################################### + +int checksum(const char*in,int fix) +{ + size_t fs=loadFile(in,0); + if(fs) + { + printf("input: %s, fs: %u\n",in,fs); + uint8_t data[fs+3]; + fs=loadFile(in,data); + uint32_t*data32=reinterpret_cast<uint32_t*>(data); + + if((fs<32)||(memcmp(data+4,"eGON.BT",7)!=0)) + { + printf("eGON header is not found\n"); + return 1; + } + + uint32_t l=le32toh(data32[4]); + if((l>fs)||((l%4)!=0)) + { + printf("bad length in the eGON header\n"); + return 1; + } + l/=4; + + uint32_t c=0x5F0A6C39-le32toh(data32[3]); + for(uint32_t i=0;i<l;++i) + c+=le32toh(data32[i]); + + if(c!=le32toh(data32[3])) + { + if(fix!=0) + { + data32[3]=htole32(c); + saveFile(in,data,fs); + printf("checksum updated\n"); + return 0; + } + printf("checksum check failed\n"); + return 1; + } + + printf("checksum OK\n"); + return 0; + } + return 1; +} + +// ######################################################################### + +int split(const char*in) +{ + size_t fs=loadFile(in,0); + if(fs) + { + printf("input: %s, fs: %u\n",in,fs); + uint8_t data[fs+3]; + fs=loadFile(in,data); + while(data[fs-1]==0xff) + --fs; + uint32_t*data32=reinterpret_cast<uint32_t*>(data); + uint32_t offs=le32toh(data32[6]); + saveFile("script.bin",data+offs,fs-offs); + fs=offs; + while(data[fs-1]==0xff) + --fs; + data32[5]=0; + data32[6]=0; + saveFile(in,data,fs); + return 0; + } + return 1; +} + +// ######################################################################### + +int join(const char*in0,const char*in1) +{ + size_t fs0=loadFile(in0,0); + size_t fs1=loadFile(in1,0); + if(fs0&&fs1) + { + printf("input: %s, fs: %u\n",in0,fs0); + printf("input: %s, fs: %u\n",in1,fs1); + uint8_t data[fs0*2+fs1]; + fs0=loadFile(in0,data); + while(fs0&(0x10000-1)) + data[fs0++]=0xff; + uint32_t*data32=reinterpret_cast<uint32_t*>(data); + data32[6]=htole32(fs0); + fs0+=loadFile(in1,data+fs0); + while(fs0&(0x2000-1)) + data[fs0++]=0xff; + data32[5]=htole32(fs0); + saveFile(in0,data,fs0); + return 0; + } + return 1; +} + +// ######################################################################### + +int main(int argc,const char*argv[]) +{ + int ret=0; + for(int i=1;i<argc;++i) + { + if(strcmp(argv[i],"dehex")==0) + { + const char*in=(argc>(i+1))?(++i,argv[i]):"capture"; + const char*out=(argc>(i+1))?(++i,argv[i]):"dehexout"; + ret+=dehex(in,out); + } + if(strcmp(argv[i],"check")==0) + { + const int fix=((argc>(i+1))&&(strcmp(argv[i+1],"-f")==0))?++i:0; + const char*in=(argc>(i+1))?(++i,argv[i]):"fes1.bin"; + ret+=in?checksum(in,fix):1; + } + if(strcmp(argv[i],"split")==0) + { + const char*in=(argc>(i+1))?(++i,argv[i]):"uboot.bin"; + ret+=split(in); + } + if(strcmp(argv[i],"join")==0) + { + const char*in0=(argc>(i+1))?(++i,argv[i]):"uboot.bin"; + const char*in1=(argc>(i+1))?(++i,argv[i]):"script.bin"; + ret+=join(in0,in1); + } + } +} + +// ######################################################################### diff --git a/udev/50-sunxi-fel.rules b/udev/50-sunxi-fel.rules new file mode 100644 index 0000000..d4545e7 --- /dev/null +++ b/udev/50-sunxi-fel.rules @@ -0,0 +1,2 @@ +# /etc/udev/rules.d/ +SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f3a", ATTRS{idProduct}=="efe8", MODE:="0666" |