commit 301f0c660521885ad885bed404c9d2ad2023e977 Author: Sergey Gridassov Date: Sat Dec 4 04:14:23 2010 +0300 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7735af4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +jzboot +*.o +*.d diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b438b7f --- /dev/null +++ b/COPYING @@ -0,0 +1,4 @@ +fw.bin is (c) Ingenic Semiconductor Co., Ltd. +ingenic.h is based on code by Ingenic Semiconductor Co.,Ltd. + +All other files have their authors and licenses described at their beginning. diff --git a/COPYING.GPL3 b/COPYING.GPL3 new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING.GPL3 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b664f86 --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +READLINE ?= 0 + + +ifneq (${READLINE},0) + LIBS += -lreadline + CPPFLAGS += -DWITH_READLINE +endif + +CC = gcc +TARGET = jzboot +SOURCES = debug.c devmgr.c ingenic.c main.c shell_lex.c usbdev.c shell.c config.c spl_cmdset.c +CFLAGS = --std=gnu99 -Wall -Werror -O2 $(shell pkg-config libusb-1.0 --cflags) +LIBS += $(shell pkg-config libusb-1.0 --libs) + +OBJECTS = ${SOURCES:.c=.o} + +all: ${TARGET} + +${TARGET}: ${OBJECTS} + ${CC} ${LDFLAGS} -o $@ $^ ${LIBS} + +clean: + rm -f ${TARGET} ${OBJECTS} ${SOURCES:.c=.d} + +%.o: %.c + ${CC} ${CPPFLAGS} ${CFLAGS} -o $@ -MD -c $< + +%.c: %.l + flex -o $@ $< + +-include ${SOURCES:.c=.d} diff --git a/config.c b/config.c new file mode 100644 index 0000000..cc94566 --- /dev/null +++ b/config.c @@ -0,0 +1,110 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#include +#include +#include +#include + +#include "config.h" +#include "debug.h" + +char **cfg_environ = NULL; + +static int env_size() { + int size = 0; + + if(cfg_environ == NULL) + return 0; + + for(int i = 0; cfg_environ[i] != NULL; i++) + size++; + + return size; +} + +char *cfg_getenv(const char *variable) { + if(cfg_environ == NULL) + return NULL; + + size_t len = strlen(variable); + + for(int i = 0; cfg_environ[i] != NULL; i++) { + char *str = cfg_environ[i], *sep = strchr(str, '='); + + if(sep - str == len && memcmp(str, variable, len) == 0) { + return sep + 1; + } + } + + return NULL; +} + +void cfg_unsetenv(const char *variable) { + int size = env_size(); + + if(size == 0) + return; + + size_t len = strlen(variable); + + for(int i = 0; cfg_environ[i] != NULL; i++) { + char *str = cfg_environ[i], *sep = strchr(str, '='); + + if(sep - str == len && memcmp(str, variable, len) == 0) { + free(str); + + memcpy(cfg_environ + i, cfg_environ + i + 1, sizeof(char *) * (size - i)); + + cfg_environ = realloc(cfg_environ, sizeof(char *) * size); + + return; + } + } +} + +void cfg_setenv(const char *variable, const char *newval) { + int size = env_size(); + + size_t len = strlen(variable); + + char *newstr = malloc(len + 1 + strlen(newval) + 1); + + strcpy(newstr, variable); + strcat(newstr, "="); + strcat(newstr, newval); + + if(size > 0) { + for(int i = 0; cfg_environ[i] != NULL; i++) { + char *str = cfg_environ[i], *sep = strchr(str, '='); + + if(sep - str == len && memcmp(str, variable, len) == 0) { + free(str); + + cfg_environ[i] = newstr; + + return; + } + } + } + + cfg_environ = realloc(cfg_environ, sizeof(char *) * (size + 2)); + + cfg_environ[size] = newstr; + cfg_environ[size + 1] = NULL; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..dd4307b --- /dev/null +++ b/config.h @@ -0,0 +1,28 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#ifndef __CONFIG__H__ +#define __CONFIG__H__ + +char *cfg_getenv(const char *variable); +void cfg_setenv(const char *variable, const char *newval); +void cfg_unsetenv(const char *variable); + +extern char **cfg_environ; + +#endif diff --git a/debug.c b/debug.c new file mode 100644 index 0000000..8506073 --- /dev/null +++ b/debug.c @@ -0,0 +1,47 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#include +#include + +#include "debug.h" + +static int debug_level = LEVEL_ERROR; + +void set_debug_level(int level) { + debug_level = level; +} + +int get_debug_level() { + return debug_level; +} + +void debug(int level, const char *fmt, ...) { + va_list list; + + va_start(list, fmt); + + if(level <= debug_level) { + if(level <= LEVEL_ERROR) + vfprintf(stderr, fmt, list); + else + vprintf(fmt, list); + } + + va_end(list); +} diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..3998e84 --- /dev/null +++ b/debug.h @@ -0,0 +1,33 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#ifndef __DEBUG__H__ +#define __DEBUG__H__ + +void set_debug_level(int level); +int get_debug_level(); + +void debug(int level, const char *fmt, ...); + +#define LEVEL_SILENT 0 +#define LEVEL_ERROR 1 +#define LEVEL_WARNING 2 +#define LEVEL_INFO 3 +#define LEVEL_DEBUG 4 + +#endif diff --git a/devmgr.c b/devmgr.c new file mode 100644 index 0000000..6e83ac4 --- /dev/null +++ b/devmgr.c @@ -0,0 +1,77 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#include + +#include "devmgr.h" +#include "debug.h" + +typedef struct device { + struct device *next; + uint16_t vid; + uint16_t pid; + void *data; +} usb_device_t; + +static const struct { + uint16_t vid; + uint16_t pid; +} devices[] = { + { 0x601a, 0x4740 }, + { 0x601a, 0x4750 }, + { 0x601a, 0x4760 }, + { 0, 0 } +}; + +static usb_device_t *list = NULL; + +int is_ingenic(uint16_t vid, uint16_t pid) { + for(int i = 0; devices[i].vid != 0; i++) + if(devices[i].vid == vid && devices[i].pid == pid) + return 1; + + return 0; +} + +void add_device(uint16_t vid, uint16_t pid, void *data) { + usb_device_t *newdev = malloc(sizeof(usb_device_t)); + + newdev->next = list; + newdev->vid = vid; + newdev->pid = pid; + newdev->data = data; + + list = newdev; + + debug(LEVEL_DEBUG, "Device manager: registered %04hX:%04hX with data %p\n", vid, pid, data); +} + +void enum_devices(void (*handler)(int idx, uint16_t vid, uint16_t pid, void *data)) { + int idx = 0; + + for(usb_device_t *dev = list; dev; dev = dev->next) + handler(idx++, dev->vid, dev->pid, dev->data); +} + +void *get_device(int idx) { + for(usb_device_t *dev = list; dev; dev = dev->next) + if(idx-- == 0) + return dev->data; + + return NULL; +} diff --git a/devmgr.h b/devmgr.h new file mode 100644 index 0000000..49a92c4 --- /dev/null +++ b/devmgr.h @@ -0,0 +1,34 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#ifndef __DEVMGR__H__ +#define __DEVMGR__H__ + +#include + +#define INTERFACE_BOOT 0 +#define ENDPOINT_OUT 0x01 +#define ENDPOINT_IN 0x81 + +int is_ingenic(uint16_t vid, uint16_t pid); + +void add_device(uint16_t vid, uint16_t pid, void *data); +void enum_devices(void (*handler)(int idx, uint16_t vid, uint16_t pid, void *data)); +void *get_device(int idx); + +#endif diff --git a/fw.bin b/fw.bin new file mode 100755 index 0000000..cfdcd02 Binary files /dev/null and b/fw.bin differ diff --git a/ingenic.c b/ingenic.c new file mode 100644 index 0000000..63e4a08 --- /dev/null +++ b/ingenic.c @@ -0,0 +1,286 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include + +#include "ingenic.h" +#include "usbdev.h" +#include "debug.h" +#include "config.h" + +#define HANDLE ingenic_handle_t *handle = hndl +#define BUILDTYPE(cmdset, id) (((cmdset) << 16) | (0x##id & 0xFFFF)) +#define CPUID(id) ((id) & 0xFFFF) +#define CMDSET(id) (((id) & 0xFFFF0000) >> 16) + +typedef struct { + void *usb; + uint32_t type; + + const ingenic_callbacks_t *callbacks; + void *callbacks_data; + + firmware_config_t cfg; +} ingenic_handle_t; + +static const struct { + const char * const magic; + uint32_t id; +} magic_list[] = { + { "JZ4740V1", BUILDTYPE(CMDSET_SPL, 4740) }, + { "JZ4750V1", BUILDTYPE(CMDSET_SPL, 4750) }, + { "JZ4760V1", BUILDTYPE(CMDSET_SPL, 4760) }, + + { "Boot4740", BUILDTYPE(CMDSET_USBBOOT, 4740) }, + { "Boot4750", BUILDTYPE(CMDSET_USBBOOT, 4750) }, + { "Boot4760", BUILDTYPE(CMDSET_USBBOOT, 4760) }, + + { NULL, 0 } +}; + +static void hexdump(const void *data, size_t size) { + const unsigned char *bytes = data; + + for(int i = 0; i < size; i+= 16) { + debug(LEVEL_DEBUG, "%04X ", i); + + int chunk_size = size - i; + if(chunk_size > 16) + chunk_size = 16; + + for(int j = 0; j < chunk_size; j++) { + debug(LEVEL_DEBUG, "%02X ", bytes[i + j]); + + if(j == 7) + debug(LEVEL_DEBUG, " "); + } + + for(int j = 0; j < 16 - chunk_size; j++) { + debug(LEVEL_DEBUG, " "); + + if(j == 8) + debug(LEVEL_DEBUG, " "); + } + + debug(LEVEL_DEBUG, "|"); + + for(int j = 0; j < chunk_size; j++) { + debug(LEVEL_DEBUG, "%c", isprint(bytes[i + j]) ? bytes[i + j] : '.'); + } + + debug(LEVEL_DEBUG, "|\n"); + } +} + +static uint32_t ingenic_probe(void *usb_hndl) { + char magic[9]; + + if(usbdev_vendor(usb_hndl, USBDEV_FROMDEV, VR_GET_CPU_INFO, 0, 0, magic, 8) == -1) { + if(errno == EFAULT) { + debug(LEVEL_DEBUG, "Stage detected\n"); + } else + return 0; + } + + magic[8] = 0; + + for(int i = 0; magic_list[i].magic != NULL; i++) + if(strcmp(magic_list[i].magic, magic) == 0) { + debug(LEVEL_DEBUG, "Magic: '%s', type: %08X\n", magic, magic_list[i].id); + + return magic_list[i].id; + } + + debug(LEVEL_ERROR, "Unknown CPU: '%s'\n", magic); + errno = EINVAL; + return 0; +} + +void *ingenic_open(void *usb_hndl) { + uint32_t type = ingenic_probe(usb_hndl); + + if(type == 0) + return NULL; + + ingenic_handle_t *ret = malloc(sizeof(ingenic_handle_t)); + ret->usb = usb_hndl; + ret->type = type; + ret->callbacks = NULL; + + return ret; +} + +int ingenic_redetect(void *hndl) { + HANDLE; + + uint32_t type = ingenic_probe(handle->usb); + + if(type == 0) + return -1; + + uint32_t prev = handle->type; + + handle->type = type; + + if(CMDSET(prev) != CMDSET(type) && handle->callbacks && handle->callbacks->cmdset_change) + handle->callbacks->cmdset_change(handle->callbacks_data); + + return 0; +} + +void ingenic_set_callbacks(void *hndl, const ingenic_callbacks_t *callbacks, void *arg) { + HANDLE; + + handle->callbacks = callbacks; + handle->callbacks_data = arg; +} + +int ingenic_cmdset(void *hndl) { + HANDLE; + + return CMDSET(handle->type); +} + +int ingenic_type(void *hndl) { + HANDLE; + + return CPUID(handle->type); +} + +void ingenic_close(void *hndl) { + HANDLE; + + free(handle); +} + +#define CFGOPT(name, var, exp) { char *str = cfg_getenv(name); if(str == NULL) { debug(LEVEL_ERROR, "%s is not set\n", name); errno = EINVAL; return -1; }; int v = atoi(str); if(!(exp)) { debug(LEVEL_ERROR, "%s must be in %s\n", name, #exp); return -1; }; handle->cfg.var = v; } + +int ingenic_rebuild(void *hndl) { + HANDLE; + + handle->cfg.cpu_id = 0x4750; //CPUID(handle->type); + + CFGOPT("EXTCLK", ext_clk, v <= 27 && v >= 12); + CFGOPT("CPUSPEED", cpu_speed, (v % 12) == 0); + handle->cfg.cpu_speed /= handle->cfg.ext_clk; + CFGOPT("PHMDIV", phm_div, v <= 32 && v >= 2); + CFGOPT("USEUART", use_uart, 1); + CFGOPT("BAUDRATE", baudrate, 1); + + CFGOPT("SDRAM_BUSWIDTH", bus_width, (v == 16) || (v == 32)); + handle->cfg.bus_width = handle->cfg.bus_width == 16 ? 1 : 0; + CFGOPT("SDRAM_BANKS", bank_num, (v >= 4) && ((v % 4) == 0)); + handle->cfg.bank_num /= 4; + CFGOPT("SDRAM_ROWADDR", row_addr, 1); + CFGOPT("SDRAM_COLADDR", col_addr, 1); + CFGOPT("SDRAM_ISMOBILE", is_mobile, v == 0 || v == 1); + CFGOPT("SDRAM_ISBUSSHARE", is_busshare, v == 0 || v == 1); + CFGOPT("DEBUGOPS", debug_ops, 1); + CFGOPT("PINNUM", pin_num, 1); + CFGOPT("START", start, 1); + CFGOPT("SIZE", size, 1); + + + + debug(LEVEL_DEBUG, "Firmware configuration dump:\n"); + + hexdump(&handle->cfg, sizeof(firmware_config_t)); + + return 0; +} + +static int ingenic_address(void *usb, uint32_t base) { + debug(LEVEL_DEBUG, "Ingenic: address 0x%08X\n", base); + + return usbdev_vendor(usb, USBDEV_TODEV, VR_SET_DATA_ADDRESS, (base >> 16), base & 0xFFFF, 0, 0); +} + +int ingenic_loadstage(void *hndl, int id, const char *file) { + HANDLE; + + if(file == NULL) { + errno = EINVAL; + + return -1; + } + + uint32_t base; + int cmd; + + switch(id) { + case INGENIC_STAGE1: + base = SDRAM_BASE + STAGE1_BASE; + cmd = VR_PROGRAM_START1; + + break; + + default: + errno = EINVAL; + + return -1; + } + + FILE *fd = fopen(file, "rb"); + + if(fd == NULL) + return -1; + + fseek(fd, 0, SEEK_END); + int size = ftell(fd); + fseek(fd, 0, SEEK_SET); + + void *data = malloc(size); + fread(data, size, 1, fd); + + fclose(fd); + + memcpy(data + 8, &handle->cfg, sizeof(firmware_config_t)); + + debug(LEVEL_DEBUG, "Ingenic: loading stage%d to 0x%08X, %d bytes\n", id, base, size); + + if(ingenic_address(handle->usb, base) == -1) { + free(data); + + return -1; + } + + hexdump(data, size); + + int ret = usbdev_sendbulk(handle->usb, data, size); + + free(data); + + if(ret == -1) + return -1; + + debug(LEVEL_DEBUG, "Ingenic: stage written\n"); + + debug(LEVEL_DEBUG, "Starting stage!\n"); + + ret = usbdev_vendor(handle->usb, USBDEV_TODEV, cmd, (base >> 16), base & 0xFFFF, 0, 0); + + if(ret == -1) + return -1; + + return ingenic_redetect(hndl); +} diff --git a/ingenic.h b/ingenic.h new file mode 100644 index 0000000..32f2ea4 --- /dev/null +++ b/ingenic.h @@ -0,0 +1,70 @@ +/* This file is based on code by Ingenic Semiconductor Co., Ltd. */ + +#ifndef __INGENIC__H__ +#define __INGENIC__H__ + +#include + +#define VR_GET_CPU_INFO 0x00 +#define VR_SET_DATA_ADDRESS 0x01 +#define VR_SET_DATA_LENGTH 0x02 +#define VR_FLUSH_CACHES 0x03 +#define VR_PROGRAM_START1 0x04 +#define VR_PROGRAM_START2 0x05 +#define VR_NOR_OPS 0x06 +#define VR_NAND_OPS 0x07 +#define VR_SDRAM_OPS 0x08 +#define VR_CONFIGRATION 0x09 +#define VR_GET_NUM 0x0a + +typedef struct { + void (*cmdset_change)(void *arg); +} ingenic_callbacks_t; + +void *ingenic_open(void *usb_hndl); +void ingenic_close(void *hndl); +void ingenic_set_callbacks(void *hndl, const ingenic_callbacks_t *callbacks, void *arg); + +int ingenic_redetect(void *hndl); +int ingenic_cmdset(void *hndl); +int ingenic_type(void *hndl); + +int ingenic_rebuild(void *hndl); +int ingenic_loadstage(void *hndl, int id, const char *filename); + +#define CMDSET_SPL 1 +#define CMDSET_USBBOOT 2 + +#define INGENIC_STAGE1 1 +#define INGENIC_STAGE2 2 + +#define STAGE1_BASE 0x2000 +#define SDRAM_BASE 0x80000000 + +typedef struct { + /* CPU ID */ + uint32_t cpu_id; + + /* PLL args */ + uint8_t ext_clk; + uint8_t cpu_speed; + uint8_t phm_div; + uint8_t use_uart; + uint32_t baudrate; + + /* SDRAM args */ + uint8_t bus_width; + uint8_t bank_num; + uint8_t row_addr; + uint8_t col_addr; + uint8_t is_mobile; + uint8_t is_busshare; + + /* debug args */ + uint8_t debug_ops; + uint8_t pin_num; + uint32_t start; + uint32_t size; +} __attribute__((packed)) firmware_config_t; + +#endif diff --git a/initial.cfg b/initial.cfg new file mode 100644 index 0000000..19aef7d --- /dev/null +++ b/initial.cfg @@ -0,0 +1,40 @@ +# Configuration variables: +# STAGE1_FILE + +set STAGE1_FILE fw.bin + +set EXTCLK 12 # Define the external crystal in MHz +set CPUSPEED 252 # Define the PLL output frequency +set PHMDIV 3 # Define the frequency divider ratio of PLL=CCLK:PCLK=HCLK=MCLK +set BAUDRATE 57600 # Define the uart baudrate +set USEUART 0 # UART number + +set SDRAM_BUSWIDTH 16 # The bus width of the SDRAM in bits (16|32) +set SDRAM_BANKS 4 # The bank number (2|4) +set SDRAM_ROWADDR 13 # Row address width in bits (11-13) +set SDRAM_COLADDR 9 # Column address width in bits (8-12) +set SDRAM_ISMOBILE 0 # Define whether SDRAM is mobile SDRAM (only or Jz4750), 1: yes 0: no +set SDRAM_ISBUSSHARE 1 # Define whether SDRAM bus share with NAND 1:shared 0:unshared + +set NAND_BUSWIDTH 8 # The width of the NAND flash chip in bits (8|16|32) +set NAND_ROWCYCLES 3 # The row address cycles (2|3) +set NAND_PAGESIZE 2048 # The page size of the NAND chip in bytes(512|2048|4096) +set NAND_PAGEPERBLOCK 128 # The page number per block +set NAND_FORCEERASE 1 # The force to erase flag (0|1) +set NAND_OOBSIZE 64 # OOB size in byte +set NAND_ECCPOS 8 # Specify the ECC offset inside the oob data (0-[oobsize-1]) +set NAND_BADBLACKPOS 0 # Specify the badblock flag offset inside the oob (0-[oobsize-1]) +set NAND_BADBLOCKPAGE 0 # Specify the page number of badblock flag inside a block(0-[PAGEPERBLOCK-1]) +set NAND_PLANENUM 1 # The planes number of target nand flash +set NAND_BCHBIT 8 # Specify the hardware BCH algorithm for 4750 (4|8) +set NAND_WPPIN 0 # Specify the write protect pin number +set NAND_BLOCKPERCHIP 4096 # Specify the block number per chip,0 means ignore + +# DEBUG +set DEBUGOPS 0 +set PINNUM 0 +set START 0 +set SIZE 0 + + +rebuildcfg diff --git a/main.c b/main.c new file mode 100644 index 0000000..916abeb --- /dev/null +++ b/main.c @@ -0,0 +1,187 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#include +#include +#include +#include "usbdev.h" +#include "debug.h" +#include "devmgr.h" +#include "ingenic.h" +#include "shell.h" + +static void usage(const char *app) { + printf( + "Usage: \n" + " Enumeration: %1$s -e\n" + " Interactive mode: %1$s -i \n" + " Batch mode (with script): %1$s -i -b \n" + " Batch mode (command list): %1$s -i -c \n\n" + + "USB loader tool for Ingenic Semiconductor XBurst-based SoC\n\n" + " -e Enumerate devices only\n" + " -i Open device with index INDEX in interactive or batch mode\n" + " -c Run semicolon-separated commands and exit\n" + " -d Set output level (0 - no reporting, 4 - max reporting), default = 1 (errors only)\n" + " -C Execute configuration script FILE before anything else\n" + " -b Execute script in FILE\n\n", app); +} + +static void dev_handler(int idx, uint16_t vid, uint16_t pid, void *data) { + printf(" Device %d: %04hX:%04hX\n", idx, vid, pid); +} + +int main(int argc, char *argv[]) { + int ch; + int idx = -1, enumerate = 0; + char *cmd = NULL, *script = NULL, *config = NULL; + + while((ch = getopt(argc, argv, "b:i:ec:d:C:")) != -1) { + switch(ch) { + case 'e': + enumerate = 1; + + break; + + case 'i': + idx = atoi(optarg); + + break; + + case 'c': + cmd = optarg; + + break; + + case 'b': + script = optarg; + + break; + + case 'C': + config = optarg; + + break; + + case 'd': + set_debug_level(atoi(optarg)); + + break; + + default: + usage(argv[0]); + + return 1; + } + } + + if(!enumerate && idx < 0) { + usage(argv[0]); + + return 1; + } + + if(usbdev_init() == -1) { + perror("usbdev_init"); + + return 1; + } + + atexit(usbdev_fini); + + if(usbdev_enumerate() == -1) { + perror("usbdev_enumerate"); + + return 1; + } + + if(enumerate) { + printf("Ingenic devices list:\n"); + + enum_devices(dev_handler); + + return 0; + } + + void *data = get_device(idx); + + if(data == NULL) { + fprintf(stderr, "Device with index %d not found\n", idx); + + return 1; + } + + void *hndl = usbdev_open(data); + + if(hndl == NULL) { + perror("usbdev_open"); + + return 1; + } + + int ret = 0; + + void *ingenic = ingenic_open(hndl); + + if(ingenic == NULL) { + perror("ingenic_open"); + + ret = 1; + + goto exit_usb; + } + + if(shell_init(ingenic) == -1) { + perror("shell_init"); + + ret = 1; + + goto exit_ingenic; + } + + if(config) + if(shell_source(config) == -1) { + perror("shell_source"); + } + + if(cmd != NULL) { + if(shell_execute(cmd) == -1) { + perror("shell_execute"); + + ret = 1; + } + + } else if(script != NULL) { + if(shell_source(script) == -1) { + perror("shell_source"); + + ret = 1; + } + } else + shell_interactive(); + + shell_fini(); + +exit_ingenic: + ingenic_close(ingenic); + +exit_usb: + usbdev_close(hndl); + + return ret; +} diff --git a/shell.c b/shell.c new file mode 100644 index 0000000..66dc964 --- /dev/null +++ b/shell.c @@ -0,0 +1,379 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#include +#include +#ifdef WITH_READLINE +#include +#include +#endif +#include +#include + +#include "shell.h" +#include "debug.h" +#include "ingenic.h" +#include "config.h" + +static void *device = NULL; +static char linebuf[512]; +char *strval = NULL, *line = NULL; + +int yylex(); +void yyrestart(FILE *new_file); + +static int builtin_help(int argc, char *argv[]); +static int builtin_exit(int argc, char *argv[]); +static int builtin_source(int argc, char *argv[]); +static int builtin_echo(int argc, char *argv[]); +static int builtin_redetect(int argc, char *argv[]); +static int builtin_rebuildcfg(int argc, char *argv[]); +static int builtin_set(int argc, char *argv[]); + +static const shell_command_t commands[] = { + { "help", "- Display this message", builtin_help }, + { "exit", "- Batch: stop current script, interactive: end session", builtin_exit }, + { "source", " - run specified script", builtin_source }, + { "echo", " - output specified string", builtin_echo }, + { "set", "[VARIABLE] [VALUE] - print or set configuraton variables", builtin_set }, + + { "redetect", " - Redetect CPU", builtin_redetect }, + { "rebuildcfg", " - Rebuild firmware configuration data", builtin_rebuildcfg }, + + { NULL, NULL, NULL } +}; + +static void shell_update_cmdset(void *arg); + +static const ingenic_callbacks_t shell_callbacks = { + shell_update_cmdset, +}; + +static const shell_command_t *set_cmds = NULL; +static int shell_exit = 0; + +int shell_init(void *ingenic) { +#ifdef WITH_READLINE + rl_initialize(); +#endif + + debug(LEVEL_DEBUG, "Initializing shell\n"); + + device = ingenic; + + ingenic_set_callbacks(ingenic, &shell_callbacks, NULL); + + shell_update_cmdset(NULL); + + return 0; +} + +#define STATE_WANTSTR 0 +#define STATE_WANTSPACE 1 + +int shell_run(int argc, char *argv[]) { + for(int i = 0; commands[i].cmd != NULL; i++) + if(strcmp(commands[i].cmd, argv[0]) == 0) + return commands[i].handler(argc, argv); + + if(set_cmds) { + for(int i = 0; set_cmds[i].cmd != NULL; i++) + if(strcmp(set_cmds[i].cmd, argv[0]) == 0) + return set_cmds[i].handler(argc, argv); + } + + debug(LEVEL_ERROR, "Bad command '%s'\n", argv[0]); + + errno = EINVAL; + return -1; +} + +int shell_execute(const char *cmd) { + line = strdup(cmd); + char *ptr = line; + + int token; + int state = STATE_WANTSTR; + int argc = 0; + char **argv = NULL; + + yyrestart(NULL); + + do { + int noway = 0; + + token = yylex(); + + if((token == TOK_SEPARATOR || token == TOK_COMMENT || token == 0)) { + if(argc > 0) { + int ret = shell_run(argc, argv); + + for(int i = 0; i < argc; i++) { + free(argv[i]); + } + + free(argv); + + argv = NULL; + argc = 0; + + if(ret == -1) { + free(ptr); + + return -1; + } + } + + state = STATE_WANTSTR; + } else { + switch(state) { + case STATE_WANTSTR: + if(token == TOK_SPACE) { + state = STATE_WANTSTR; + } else if(token == TOK_STRING) { + int oargc = argc++; + + argv = realloc(argv, sizeof(char *) * argc); + + argv[oargc] = strval; + + state = STATE_WANTSPACE; + } else { + noway = 1; + } + + break; + + case STATE_WANTSPACE: + if(token == TOK_STRING) { + free(strval); + + noway = 1; + } else if(token == TOK_SPACE) { + state = STATE_WANTSTR; + } else + noway = 1; + } + + if(noway) { + debug(LEVEL_ERROR, "No way from state %d by token %d\n", state, token); + + for(int i = 0; i < argc; i++) + free(argv[i]); + + free(argv); + free(ptr); + + return -1; + } + } + + } while(token && token != TOK_COMMENT); + + free(ptr); + + return 0; +} + +int shell_pull(char *buf, int maxlen) { + size_t len = strlen(line); + + if(len < maxlen) + maxlen = len; + + memcpy(buf, line, maxlen); + + line += maxlen; + + return maxlen; +} + +void shell_fini() { + device = NULL; +} + +int shell_source(const char *filename) { + shell_exit = 0; + + FILE *file = fopen(filename, "r"); + + if(file == NULL) { + return -1; + } + + char *line; + + while((line = fgets(linebuf, sizeof(linebuf), file)) && !shell_exit) { + if(shell_execute(line) == -1) { + fclose(file); + + return -1; + } + } + + fclose(file); + + return 0; +} + +void shell_interactive() { + shell_exit = 0; + +#ifndef WITH_READLINE + char *line; + + while(1) { + fputs("jzboot> ", stdout); + fflush(stdout); + + line = fgets(linebuf, sizeof(linebuf), stdin); + + if(line == NULL) + break; + + shell_execute(line); + } +#else + + rl_set_signals(); + + while(!shell_exit) { + char *line = readline("jzboot> "); + + if(line == NULL) { + printf("line null, EOP\n"); + break; + } + + add_history(line); + + shell_execute(line); + + free(line); + } + + rl_clear_signals(); +#endif +} + +static int builtin_help(int argc, char *argv[]) { + for(int i = 0; commands[i].cmd != NULL; i++) { + printf("%s %s\n", commands[i].cmd, commands[i].description); + } + + if(set_cmds) { + for(int i = 0; set_cmds[i].cmd != NULL; i++) + printf("%s %s\n", set_cmds[i].cmd, set_cmds[i].description); + } + + return 0; +} + +static int builtin_exit(int argc, char *argv[]) { + shell_exit = 1; + + return 0; +} + +static int builtin_source(int argc, char *argv[]) { + if(argc < 2) { + printf("Usage: %s \n", argv[0]); + + return -1; + } + + int ret = shell_source(argv[1]); + + shell_exit = 0; + + return ret; +} + +static int builtin_echo(int argc, char *argv[]) { + if(argc < 2) { + printf("Usage: %s \n", argv[0]); + + return -1; + } + + puts(argv[1]); + + return 0; +} + +static int builtin_redetect(int argc, char *argv[]) { + if(ingenic_redetect(device) == -1) { + perror("ingenic_redetect"); + + return -1; + } else + return 0; +} + + +static int builtin_set(int argc, char *argv[]) { + if(argc == 1 && cfg_environ) { + for(int i = 0; cfg_environ[i] != NULL; i++) + printf("%s\n", cfg_environ[i]); + + } else if(argc == 2) { + cfg_unsetenv(argv[1]); + + } else if(argc >= 3) { + cfg_setenv(argv[1], argv[2]); + + } + + return 0; +} + + +static int builtin_rebuildcfg(int argc, char *argv[]) { + return ingenic_rebuild(device); +} + +static const struct { + int set; + const char *name; + const shell_command_t *commands; +} cmdsets[] = { + { CMDSET_SPL, "SPL", spl_cmdset }, + { 0, NULL, NULL } +}; + +static void shell_update_cmdset(void *arg) { + set_cmds = NULL; + + int set = ingenic_cmdset(device); + + for(int i = 0; cmdsets[i].name != NULL; i++) { + if(cmdsets[i].set == set) { + printf("Shell: using command set '%s', run 'help' for command list. CPU: %04X\n", cmdsets[i].name, ingenic_type(device)); + + set_cmds = cmdsets[i].commands; + + return; + } + } + + debug(LEVEL_ERROR, "Shell: unknown cmdset %d\n", set); +} + +void *shell_device() { + return device; +} diff --git a/shell.h b/shell.h new file mode 100644 index 0000000..6a7b429 --- /dev/null +++ b/shell.h @@ -0,0 +1,49 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#ifndef __SHELL__H__ +#define __SHELL__H__ + +typedef struct { + const char *cmd; + const char *description; + int (*handler)(int argc, char *argv[]); +} shell_command_t; + +int shell_init(void *ingenic); +void shell_fini(); + +void shell_interactive(); +int shell_source(const char *filename); +int shell_execute(const char *input); + +void *shell_device(); + +// lexer interface +extern char *strval; + +#define TOK_SEPARATOR 1 +#define TOK_STRING 2 +#define TOK_SPACE 3 +#define TOK_COMMENT 4 + +int shell_pull(char *buf, int maxlen); + +extern const shell_command_t spl_cmdset[]; + +#endif diff --git a/shell_lex.c b/shell_lex.c new file mode 100644 index 0000000..eea7de3 --- /dev/null +++ b/shell_lex.c @@ -0,0 +1,1793 @@ +#line 2 "shell_lex.c" + +#line 4 "shell_lex.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +#define yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 10 +#define YY_END_OF_BUFFER 11 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[19] = + { 0, + 0, 0, 0, 0, 11, 5, 3, 1, 4, 2, + 6, 9, 8, 5, 3, 6, 7, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 3, 4, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[7] = + { 0, + 1, 2, 3, 4, 4, 5 + } ; + +static yyconst flex_int16_t yy_base[24] = + { 0, + 0, 0, 4, 8, 12, 0, 0, 29, 29, 29, + 0, 29, 0, 0, 0, 0, 29, 29, 14, 19, + 7, 24, 5 + } ; + +static yyconst flex_int16_t yy_def[24] = + { 0, + 18, 1, 19, 19, 18, 20, 21, 18, 18, 18, + 22, 18, 23, 20, 21, 22, 18, 0, 18, 18, + 18, 18, 18 + } ; + +static yyconst flex_int16_t yy_nxt[36] = + { 0, + 6, 7, 8, 9, 10, 6, 12, 17, 15, 13, + 12, 18, 18, 13, 11, 11, 11, 11, 11, 14, + 18, 18, 18, 14, 16, 16, 18, 16, 5, 18, + 18, 18, 18, 18, 18 + } ; + +static yyconst flex_int16_t yy_chk[36] = + { 0, + 1, 1, 1, 1, 1, 1, 3, 23, 21, 3, + 4, 5, 0, 4, 19, 19, 19, 19, 19, 20, + 0, 0, 0, 20, 22, 22, 0, 22, 18, 18, + 18, 18, 18, 18, 18 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "shell_lex.l" +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ +#line 20 "shell_lex.l" +#include "shell.h" +#include +#include + +#define YY_INPUT(buf, result, max_size) result = shell_pull(buf, max_size); + +static char *str_append(char *str, const char *src) { + if(str) { + size_t newlen = strlen(str) + strlen(src) + 1; + + char *newstr = malloc(newlen); + + strcpy(newstr, str); + strcat(newstr, src); + + free(str); + + return newstr; + } else + return strdup(src); +} +#define YY_NO_INPUT 1 + +#line 512 "shell_lex.c" + +#define INITIAL 0 +#define STR 1 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 45 "shell_lex.l" + +#line 700 "shell_lex.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 19 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 18 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 46 "shell_lex.l" +{ strval = NULL; BEGIN(STR); } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 47 "shell_lex.l" +return TOK_SEPARATOR; + YY_BREAK +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +#line 48 "shell_lex.l" +return TOK_SPACE; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 49 "shell_lex.l" +return TOK_COMMENT; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 50 "shell_lex.l" +{ strval = strdup(yytext); return TOK_STRING; } + YY_BREAK +case 6: +/* rule 6 can match eol */ +YY_RULE_SETUP +#line 51 "shell_lex.l" +strval = str_append(strval, yytext); + YY_BREAK +case 7: +YY_RULE_SETUP +#line 52 "shell_lex.l" +strval = str_append(strval, "\""); + YY_BREAK +case 8: +YY_RULE_SETUP +#line 53 "shell_lex.l" +strval = str_append(strval, "\\"); + YY_BREAK +case 9: +YY_RULE_SETUP +#line 54 "shell_lex.l" +{ BEGIN(INITIAL); return TOK_STRING; } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 55 "shell_lex.l" +ECHO; + YY_BREAK +#line 831 "shell_lex.c" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(STR): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 19 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 19 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 18); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 55 "shell_lex.l" diff --git a/shell_lex.l b/shell_lex.l new file mode 100644 index 0000000..240b1ef --- /dev/null +++ b/shell_lex.l @@ -0,0 +1,54 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +%{ +#include "shell.h" +#include +#include + +#define YY_INPUT(buf, result, max_size) result = shell_pull(buf, max_size); + +static char *str_append(char *str, const char *src) { + if(str) { + size_t newlen = strlen(str) + strlen(src) + 1; + + char *newstr = malloc(newlen); + + strcpy(newstr, str); + strcat(newstr, src); + + free(str); + + return newstr; + } else + return strdup(src); +} +%} +%option noyywrap nounput noinput batch + +%x STR +%% +["] { strval = NULL; BEGIN(STR); } +; return TOK_SEPARATOR; +[[:space:]]+ return TOK_SPACE; +[#] return TOK_COMMENT; +[^[:space:];"#]+ { strval = strdup(yytext); return TOK_STRING; } +[^\\"]+ strval = str_append(strval, yytext); +\\["] strval = str_append(strval, "\""); +\\ strval = str_append(strval, "\\"); +["] { BEGIN(INITIAL); return TOK_STRING; } diff --git a/spl_cmdset.c b/spl_cmdset.c new file mode 100644 index 0000000..c26d3f3 --- /dev/null +++ b/spl_cmdset.c @@ -0,0 +1,39 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#include +#include + +#include "shell.h" +#include "config.h" +#include "ingenic.h" + +static int spl_memtest(int argc, char *argv[]); + +const shell_command_t spl_cmdset[] = { + { "memtest", "[BASE ] - SDRAM test", spl_memtest }, + { NULL, NULL, NULL } +}; + +static int spl_memtest(int argc, char *argv[]) { + if(argc != 1 && argc != 3) { + printf("Usage: %s [BASE ]\n", argv[0]); + } + + return ingenic_loadstage(shell_device(), INGENIC_STAGE1, cfg_getenv("STAGE1_FILE")); +} diff --git a/usbdev.c b/usbdev.c new file mode 100644 index 0000000..d8b10a5 --- /dev/null +++ b/usbdev.c @@ -0,0 +1,216 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#include +#include + +#include "usbdev.h" +#include "debug.h" +#include "devmgr.h" + +#define CONTROL_TIMEOUT 1000 + +static libusb_context *ctx = NULL; + +static int translate_libusb(int code); + +int usbdev_enumerate() { + libusb_device **list; + ssize_t devices_count = libusb_get_device_list(ctx, &list); + + if(devices_count < 0) + return translate_libusb(devices_count); + + for(int i = 0; i < devices_count; i++) { + struct libusb_device_descriptor descr; + + int ret = libusb_get_device_descriptor(list[i], &descr); + + if(ret != LIBUSB_SUCCESS) { + libusb_free_device_list(list, 1); + + return translate_libusb(ret); + } + + if(is_ingenic(descr.idVendor, descr.idProduct)) { + add_device(descr.idVendor, descr.idProduct, libusb_ref_device(list[i])); + } + } + + libusb_free_device_list(list, 1); + + return 0; +} + +int usbdev_init() { + if(translate_libusb(libusb_init(&ctx)) == -1) + return -1; + + libusb_set_debug(ctx, get_debug_level()); + + return 0; +} + +void usbdev_fini() { + libusb_exit(ctx); + ctx = NULL; +} + +void *usbdev_open(void *dev) { + libusb_device_handle *hndl; + + if(translate_libusb(libusb_open(dev, &hndl)) == -1) + return NULL; + + int ret = libusb_kernel_driver_active(hndl, INTERFACE_BOOT); + + if(ret < 0) { + libusb_close(hndl); + + translate_libusb(ret); + + return NULL; + + } else if(ret == 1) { + debug(LEVEL_INFO, "Deactivating kernel driver\n"); + + if(translate_libusb(libusb_detach_kernel_driver(hndl, INTERFACE_BOOT)) == -1) { + libusb_close(hndl); + + return NULL; + } + } + + if(translate_libusb(libusb_claim_interface(hndl, INTERFACE_BOOT)) == -1) { + libusb_close(hndl); + + return NULL; + } + + debug(LEVEL_DEBUG, "Device open\n"); + + return hndl; +} + +void usbdev_close(void *_hndl) { + libusb_device_handle *hndl = _hndl; + + libusb_release_interface(hndl, INTERFACE_BOOT); + + libusb_close(hndl); + + debug(LEVEL_DEBUG, "Device closed\n"); +} + +int usbdev_vendor(void *_hndl, int direction, uint8_t req, uint16_t value, uint16_t index, void *data, uint16_t size) { + libusb_device_handle *hndl = _hndl; + + uint8_t type = LIBUSB_REQUEST_TYPE_VENDOR; + + if(direction == USBDEV_FROMDEV) + type |= LIBUSB_ENDPOINT_IN; + + debug(LEVEL_DEBUG, "Control: type %02hhX, request %hhu, value %hu, index %hu, data %p, size %hu\n", type, req, value, index, data, size); + + int ret = libusb_control_transfer(hndl, type, req, value, index, data, size, CONTROL_TIMEOUT); + + if(ret >= 0) + return ret; + else + return translate_libusb(ret); +} + +int usbdev_sendbulk(void *hndl, void *data, int size) { + int trans; + + debug(LEVEL_DEBUG, "Bulk: writing data %p, size %d\n", data, size); + + return translate_libusb(libusb_bulk_transfer(hndl, ENDPOINT_OUT, data, size, &trans, CONTROL_TIMEOUT)); +} + +static int translate_libusb(int code) { + switch(code) { + case LIBUSB_SUCCESS: + return 0; + + case LIBUSB_ERROR_IO: + errno = EIO; + + break; + + case LIBUSB_ERROR_INVALID_PARAM: + errno = EINVAL; + + break; + + case LIBUSB_ERROR_ACCESS: + errno = EACCES; + + break; + + case LIBUSB_ERROR_NO_DEVICE: + case LIBUSB_ERROR_NOT_FOUND: + errno = ENOENT; + + break; + + case LIBUSB_ERROR_BUSY: + errno = EBUSY; + + break; + + case LIBUSB_ERROR_TIMEOUT: + errno = ETIMEDOUT; + + break; + + case LIBUSB_ERROR_OVERFLOW: + errno = EOVERFLOW; + + break; + + case LIBUSB_ERROR_PIPE: + errno = EPIPE; + + break; + + case LIBUSB_ERROR_INTERRUPTED: + errno = EINTR; + + break; + + case LIBUSB_ERROR_NO_MEM: + errno = ENOMEM; + + break; + + case LIBUSB_ERROR_NOT_SUPPORTED: + errno = ENOTSUP; + + break; + + + case LIBUSB_ERROR_OTHER: + default: + errno = EFAULT; + } + + debug(LEVEL_DEBUG, "Translated libusb return %d to %d\n", code, errno); + + return -1; +} diff --git a/usbdev.h b/usbdev.h new file mode 100644 index 0000000..772308e --- /dev/null +++ b/usbdev.h @@ -0,0 +1,36 @@ +/* + * JzBoot: an USB bootloader for JZ series of Ingenic(R) microprocessors. + * Copyright (C) 2010 Sergey Gridassov + * + * 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 . + */ + +#ifndef __USBDEV__H__ +#define __USBDEV__H__ + +#include + +int usbdev_init(); +void usbdev_fini(); + +#define USBDEV_FROMDEV 0 +#define USBDEV_TODEV 1 + +int usbdev_enumerate(); +void *usbdev_open(void *dev); +void usbdev_close(void *hndl); +int usbdev_vendor(void *hndl, int direction, uint8_t req, uint16_t value, uint16_t index, void *data, uint16_t size); +int usbdev_sendbulk(void *hndl, void *data, int size); + +#endif