diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..94a9ed024d3859793618152ea559a168bbcbb5e2 --- /dev/null +++ b/LICENSE @@ -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 index 43308d9e409196f65390ba106350f7f1b681a854..8ba1c362450b2550d5e1eac5bc9b0024dbad1e6e 100644 --- a/Makefile +++ b/Makefile @@ -1,20 +1,35 @@ -AS := as -#LD := ld -m elf_i386 -LD := ld -m elf_x86_64 - -LDFLAG := -Ttext 0x0 -s --oformat binary - -image : linux.img - -linux.img : bootsect - cat bootsect > linux.img - -bootsect : bootsect.o - $(LD) $(LDFLAG) -o $@ $< - -bootsect.o : bootsect.S - $(AS) -o $@ $< - -clean: - rm *.o - rm bootsect +AS := as +LD := ld -m elf_x86_64 + +LDFLAG := -Ttext 0x0 -s --oformat binary + +image : linux.img + +linux.img : tools/build bootsect setup kernel/system + ./tools/build bootsect setup kernel/system > $@ + +tools/build : tools/build.c + gcc -o $@ $< + +kernel/system : kernel/head.S kernel/*.c mm/*.c + cd kernel; make system; cd .. + +bootsect : bootsect.o + $(LD) $(LDFLAG) -o $@ $< + +bootsect.o : bootsect.S + $(AS) -o $@ $< + +setup : setup.o + $(LD) $(LDFLAG) -e _start_setup -o $@ $< + +setup.o : setup.S + $(AS) -o $@ $< +clean: + rm *.o + rm bootsect + rm setup + rm tools/build + rm linux.img + cd kernel; make clean; cd .. + diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..7d3cef93b3de786fae204f8997ddfff9a07ec984 --- /dev/null +++ b/README.en.md @@ -0,0 +1,36 @@ +# linux_kernel_011 + +#### Description +从0开始写Linux Kernel 0.11。做为最古老的Linux内核,0.11短小精悍,但是由于早期的代码所使用的编译器都比较老了,我们使用现代的编译器从0开始,一步步实现linux kernel. + +#### Software Architecture +Software architecture description + +#### Installation + +1. xxxx +2. xxxx +3. xxxx + +#### Instructions + +1. xxxx +2. xxxx +3. xxxx + +#### Contribution + +1. Fork the repository +2. Create Feat_xxx branch +3. Commit your code +4. Create Pull Request + + +#### Gitee Feature + +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md +2. Gitee blog [blog.gitee.com](https://blog.gitee.com) +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) +4. The most valuable open source project [GVP](https://gitee.com/gvp) +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..17771b10329b91c56f6241758b8f6e94eeb892fb --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# linux_kernel_011 + +#### 介绍 +从0开始写Linux Kernel 0.11。做为最古老的Linux内核,0.11短小精悍,但是由于早期的代码所使用的编译器都比较老了,我们使用现代的编译器从0开始,一步步实现linux kernel. + +#### 软件架构 +软件架构说明 + + +#### 安装教程 + +1. xxxx +2. xxxx +3. xxxx + +#### 使用说明 + +1. xxxx +2. xxxx +3. xxxx + +#### 参与贡献 + +1. Fork 本仓库 +2. 新建 Feat_xxx 分支 +3. 提交代码 +4. 新建 Pull Request + + +#### 特技 + +1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md +2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) +3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 +4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 +5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) +6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/bootsect.S b/bootsect.S index 4a38516f36eb79ab205886a92b71ff69881a5233..b3fa63ecd646433a19e47411b2808cb9e7fe4ced 100644 --- a/bootsect.S +++ b/bootsect.S @@ -1,37 +1,211 @@ -BOOTSEG = 0x7c0 +SYSSIZE = 2426 -ROOT_DEV = 0x000 +SETUPLEN = 4 + +BOOTSEG = 0x7c0 + +INITSEG = 0x9000 + +SETUPSEG = 0x9020 + +SYSSEG = 0x1000 + +ENDSEG = SYSSEG + SYSSIZE + +ROOT_DEV = 0x000 .code16 .text .global _start _start: - jmpl $BOOTSEG, $start2 - + + jmpl $BOOTSEG, $start2 + start2: - movw $BOOTSEG, %ax + movw $BOOTSEG, %ax + movw %ax, %ds + movw $INITSEG, %ax + movw %ax, %es + movw $256, %cx + subw %si, %si + subw %di, %di + + rep + movsw + + jmpl $INITSEG, $go + +go: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw $0xFF00, %sp + +load_setup: + movw $0x0000, %dx + movw $0x0002, %cx + movw $0x0200, %bx + movb $0x02, %ah + movb $SETUPLEN, %al + int $0x13 + jnc ok_load_setup + movw $0x0000, %dx + movw $0x0000, %ax + int $0x13 + jmp load_setup + +ok_load_setup: + movb $0x00, %dl + movw $0x0800, %ax + int $0x13 + movb $0x00, %ch + movw %cx, %cs:sectors + movw $INITSEG, %ax + movw %ax, %es + + movw $SYSSEG, %ax + movw %ax, %es + call read_it + call kill_motor + + movw %cs:root_dev, %ax + cmpw $0, %ax + jne root_defined + movw %cs:sectors, %bx + movw $0x0208, %ax + cmpw $15, %bx + je root_defined + movw $0x021c, %ax + cmpw $18, %bx + je root_defined +undef_root: + jmp undef_root +root_defined: + mov %ax, %cs:root_dev + + movw %cs, %ax movw %ax, %ds movw %ax, %es - movw %ax, %fs - movw %ax, %gs + + movw $0x600, %ax + movw $0x700, %bx + movw $0x0, %cx + movw $0x184f,%dx + int $0x10 movw $msg, %ax movw %ax, %bp movw $0x01301, %ax movw $0x0c, %bx - movw $12, %cx - movb $0, %dl - int $0x010 + movw $23, %cx + movw $0, %dx + int $0x010 -loop: - jmp loop + jmpl $SETUPSEG, $0 -msg: -.ascii "Hello World!" +sread: + .word 1+SETUPLEN +head: + .word 0 +track: + .word 0 +read_it: + movw %es, %ax + testw $0x0fff, %ax +die: + jne die + xor %bx, %bx +rp_read: + movw %es, %ax + cmpw $ENDSEG, %ax + jb ok1_read + ret +ok1_read: + movw %cs:sectors, %ax + subw sread, %ax + movw %ax, %cx + shlw $9, %cx + addw %bx, %cx + jnc ok2_read + je ok2_read + xorw %ax, %ax + subw %bx, %ax + shrw $9, %ax +ok2_read: + call read_track + movw %ax, %cx + addw sread, %ax + cmpw %cs:sectors, %ax + jne ok3_read + movw $1, %ax + subw head, %ax + jne ok4_read + incw track +ok4_read: + movw %ax, head + xorw %ax, %ax +ok3_read: + movw %ax, sread + shlw $9, %cx + addw %cx, %bx + jnc rp_read + movw %es, %ax + addw $0x1000, %ax + movw %ax, %es + xorw %bx, %bx + jmp rp_read + +read_track: + pushw %ax + pushw %bx + pushw %cx + pushw %dx + movw track, %dx + movw sread, %cx + incw %cx + movb %dl, %ch + movw head, %dx + movb %dl, %dh + movb $0, %dl + andw $0x0100, %dx + movb $2, %ah + int $0x13 + jc bad_rt + popw %dx + popw %cx + popw %bx + popw %ax + ret +bad_rt: + movw $0x0, %ax + movw $0x0, %dx + int $0x13 + popw %dx + popw %cx + popw %bx + popw %ax + jmp read_track +kill_motor: + pushw %dx + movw $0x3f2, %dx + movb $0, %al + outb %al, %dx + popw %dx + ret + +sectors: + .word 0 + +msg: +.byte 13, 10 +.ascii "Linux is booting..." +.byte 13, 10 .org 508 root_dev: .word ROOT_DEV boot_flag: .word 0xaa55 + diff --git a/fs/Makefile b/fs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a843017d97b836aebec3ed76ec2bcc8ee9bf7e16 --- /dev/null +++ b/fs/Makefile @@ -0,0 +1,16 @@ +GCC := gcc +LD := ld +CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -fno-stack-protector -c -m32 +LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 +INCDIR := ../include +OBJS := read_write.o + +fs.o : $(OBJS) + $(LD) -m elf_i386 -r -o $@ $^ + +read_write.o : read_write.c + $(GCC) $(CCFLAG) -o $@ $< + +clean : + rm *.o + diff --git a/fs/read_write.c b/fs/read_write.c new file mode 100644 index 0000000000000000000000000000000000000000..bfe0317bb6d139a4c5fd472b4107c1e9aa77432b --- /dev/null +++ b/fs/read_write.c @@ -0,0 +1,17 @@ +#include +#include +#include + +#include +#include + +extern int tty_write(int channel, const char* buf, int count); + +int sys_write(unsigned int fd,char * buf,int count) { + if (fd == 1) { + return tty_write(0, buf, count); + } + + return 0; +} + diff --git a/include/asm/io.h b/include/asm/io.h new file mode 100644 index 0000000000000000000000000000000000000000..b2f16c15bae528f9efb79f34f814c3f4a0be53ad --- /dev/null +++ b/include/asm/io.h @@ -0,0 +1,31 @@ +#ifndef _IO_H +#define _IO_H + +#define outb(value,port) \ +__asm__ ("outb %%al,%%dx"::"a" (value),"d" (port)) + + +#define inb(port) ({ \ +i unsigned char _v; \ + __asm__ volatile ("inb %%dx,%%al":"=a" (_v):"d" (port)); \ + _v; \ +}) + + +#define outb_p(value, port) \ +__asm__("outb %%al, %%dx\n" \ + "\tjmp 1f\n" \ + "1:\tjmp 1f\n" \ + "1:" :: "a"(value), "d"(port)) + + +#define inb_p(port) ({ \ +unsigned char _v; \ +__asm__ volatile ("inb %%dx,%%al\n" \ + "\tjmp 1f\n" \ + "1:\tjmp 1f\n" \ + "1:":"=a" (_v):"d" (port)); \ +_v; \ +}) + +#endif diff --git a/include/asm/segment.h b/include/asm/segment.h new file mode 100644 index 0000000000000000000000000000000000000000..4e111aa282798dd9be28aa657ab1eae9ba1f533c --- /dev/null +++ b/include/asm/segment.h @@ -0,0 +1,11 @@ +#ifndef _SEGMENT_H +#define _SEGMENT_H + +extern inline unsigned char get_fs_byte(const char * addr) { + unsigned register char _v; + __asm__ ("movb %%fs:%1,%0":"=r" (_v):"m" (*addr)); + return _v; +} + +#endif + diff --git a/include/asm/system.h b/include/asm/system.h new file mode 100644 index 0000000000000000000000000000000000000000..c1e67bc963998d4e9f1118252da33764b022ca2d --- /dev/null +++ b/include/asm/system.h @@ -0,0 +1,60 @@ +#ifndef _SYSTEM_H +#define _SYSTEM_H + +#define move_to_user_mode() \ +__asm__("movl %%esp, %%eax\n\t" \ + "pushl $0x17\n\t" \ + "pushl %%eax\n\t" \ + "pushfl\n\t" \ + "pushl $0x0f\n\t" \ + "pushl $1f\n\t" \ + "iret\n\t" \ + "1:\tmovl $0x17, %%eax\n\t" \ + "movw %%ax, %%ds\n\t" \ + "movw %%ax, %%es\n\t" \ + "movw %%ax, %%fs\n\t" \ + "movw %%ax, %%gs\n\t" \ + :::"ax") + + +#define sti() __asm__("sti"::) +#define cli() __asm__("cli"::) +#define nop() __asm__("nop"::) +#define iret() __asm__("iret"::) + +#define _set_gate(gate_addr, type, dpl, addr) \ +__asm__("movw %%dx, %%ax\n\t" \ + "movw %0, %%dx\n\t" \ + "movl %%eax, %1\n\t" \ + "movl %%edx, %2" \ + : \ + :"i"((short)(0x8000 + (dpl << 13) + (type << 8))), \ + "o"(*((char*)(gate_addr))), \ + "o"(*(4 + (char*)(gate_addr))), \ + "d"((char*)(addr)), "a" (0x00080000)) + +#define set_trap_gate(n, addr) \ + _set_gate(&idt[n], 15, 0, addr) + +#define set_intr_gate(n, addr) \ + _set_gate(&idt[n], 14, 0, addr) + +#define set_system_gate(n, addr) \ + _set_gate(&idt[n], 15, 3, addr) + +#define _set_tssldt_desc(n, addr, type) \ +__asm__("movw $104, %1\n\t" \ + "movw %%ax, %2\n\t" \ + "rorl $16, %%eax\n\t" \ + "movb %%al, %3\n\t" \ + "movb $" type ", %4\n\t" \ + "movb $0x00, %5\n\t" \ + "movb %%ah, %6\n\t" \ + "rorl $16, %%eax\n\t" \ + ::"a"(addr), "m"(*(n)), "m"(*(n+2)), "m"(*(n+4)), \ + "m"(*(n+5)), "m"(*(n+6)), "m"(*(n+7)) \ + ) + +#define set_tss_desc(n, addr) _set_tssldt_desc(((char*)(n)), addr, "0x89") +#define set_ldt_desc(n, addr) _set_tssldt_desc(((char*)(n)), addr, "0x82") +#endif diff --git a/include/ctype.h b/include/ctype.h new file mode 100644 index 0000000000000000000000000000000000000000..974b192c6cd3e93aa765bea3f36c11a37cfb6718 --- /dev/null +++ b/include/ctype.h @@ -0,0 +1,21 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + + +extern unsigned char _ctype[]; +extern char _ctmp; + +#define islower(c) ((_ctype+1)[c]&(_L)) + +#define toupper(c) (_ctmp=c,islower(_ctmp)?_ctmp-('a'-'A'):_ctmp) + +#endif diff --git a/include/errno.h b/include/errno.h new file mode 100644 index 0000000000000000000000000000000000000000..45b1818d35f6121ed7e4642b307bd6e737c9bf46 --- /dev/null +++ b/include/errno.h @@ -0,0 +1,51 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +extern int errno; + +#define ERROR 99 +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EDEADLK 35 +#define ENAMETOOLONG 36 +#define ENOLCK 37 +#define ENOSYS 38 +#define ENOTEMPTY 39 + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 + +#endif diff --git a/include/linux/head.h b/include/linux/head.h new file mode 100644 index 0000000000000000000000000000000000000000..7bf5f67e2fa3522331d330f4437fc3d5706595e5 --- /dev/null +++ b/include/linux/head.h @@ -0,0 +1,11 @@ +#ifndef _HEAD_H +#define _HEAD_H + +typedef struct desc_struct { + unsigned long a, b; +} desc_table[256]; + +extern unsigned long pg_dir[1024]; +extern desc_table idt,gdt; + +#endif diff --git a/include/linux/kernel.h b/include/linux/kernel.h new file mode 100644 index 0000000000000000000000000000000000000000..f7ddbda71c3827f82813e9c208c13c91a3b142a7 --- /dev/null +++ b/include/linux/kernel.h @@ -0,0 +1,7 @@ +#ifndef _KERNEL_H +#define _KERNEL_H + +int printk(const char* fmt, ...); + +#endif + diff --git a/include/linux/mm.h b/include/linux/mm.h new file mode 100644 index 0000000000000000000000000000000000000000..7030a243bdd688ec03d0557415e7c57f33504980 --- /dev/null +++ b/include/linux/mm.h @@ -0,0 +1,23 @@ +#ifndef _MM_H +#define _MM_H + +#include + +#define PAGE_SIZE 4096 + +extern unsigned long get_free_page(); +extern void free_page(unsigned long addr); + +#define invalidate() \ +__asm__("movl %%eax,%%cr3"::"a" (0)) + +#define LOW_MEM 0x100000 +extern unsigned long HIGH_MEMORY; +#define PAGING_MEMORY (15*1024*1024) +#define PAGING_PAGES (PAGING_MEMORY>>12) +#define MAP_NR(addr) (((addr)-LOW_MEM)>>12) +#define USED 100 + +extern unsigned char mem_map [ PAGING_PAGES ]; + +#endif diff --git a/include/linux/sched.h b/include/linux/sched.h new file mode 100644 index 0000000000000000000000000000000000000000..fc6d7ea310f2168be77c3e2103473ed2e3b3056e --- /dev/null +++ b/include/linux/sched.h @@ -0,0 +1,165 @@ +#ifndef _SCHED_H +#define _SCHED_H + +#define HZ 100 + +#define NR_TASKS 64 +#define TASK_SIZE 0x04000000 + +#if (TASK_SIZE & 0x3fffff) +#error "TASK_SIZE must be multiple of 4M" +#endif + +#if (((TASK_SIZE>>16)*NR_TASKS) != 0x10000) +#error "TASK_SIZE*NR_TASKS must be 4GB" +#endif + +#define FIRST_TASK task[0] +#define LAST_TASK task[NR_TASKS-1] + +#include +#include + +#define TASK_RUNNING 0 +#define TASK_INTERRUPTIBLE 1 +#define TASK_UNINTERRUPTIBLE 2 +#define TASK_ZOMBIE 3 +#define TASK_STOPPED 4 + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +extern int copy_page_tables(unsigned long from, unsigned long to, long size); +extern int free_page_tables(unsigned long from, unsigned long size); + +void trap_init(); +void sched_init(); +void test_a(); +void test_b(); + +extern struct task_struct *task[NR_TASKS]; +extern struct task_struct *current; + +typedef int (*fn_ptr)(); + +struct tss_struct { + long back_link; + long esp0; + long ss0; + long esp1; + long ss1; + long esp2; + long ss2; + long cr3; + long eip; + long eflags; + long eax, ecx, edx, ebx; + long esp; + long ebp; + long esi; + long edi; + long es; + long cs; + long ss; + long ds; + long fs; + long gs; + long ldt; + long trace_bitmap; +}; + +struct task_struct { + long state; + long pid; + struct task_struct *p_pptr; + struct desc_struct ldt[3]; + struct tss_struct tss; +}; + +#define INIT_TASK \ +{ \ + 0, \ + 0, \ + &init_task.task,\ + { \ + {0, 0}, \ + {0xfff, 0xc0fa00}, \ + {0xfff, 0xc0f200}, \ + }, \ + {0, PAGE_SIZE + (long)&init_task, 0x10, 0, 0, 0, 0, (long)&pg_dir, \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, \ + _LDT(0), 0x80000000, \ + }, \ +} + +/* + * In linux is 4, because we add video selector, + * so, it is 5 here. + * */ +#define FIRST_TSS_ENTRY 5 +#define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY + 1) +#define _TSS(n) ((((unsigned long)n) << 4) + (FIRST_TSS_ENTRY << 3)) +#define _LDT(n) ((((unsigned long)n) << 4) + (FIRST_LDT_ENTRY << 3)) +#define ltr(n) __asm__("ltr %%ax"::"a"(_TSS(n))) +#define lldt(n) __asm__("lldt %%ax"::"a"(_LDT(n))) + +#define switch_to(n) {\ + struct {long a,b;} __tmp; \ + __asm__("cmpl %%ecx,current\n\t" \ + "je 1f\n\t" \ + "movw %%dx,%1\n\t" \ + "xchgl %%ecx,current\n\t" \ + "ljmp *%0\n\t" \ + "1:" \ + ::"m" (*&__tmp.a),"m" (*&__tmp.b), \ + "d" (_TSS(n)),"c" ((long) task[n])); \ +} + +#define _set_base(addr,base) \ +__asm__("movw %%dx,%0\n\t" \ + "rorl $16,%%edx\n\t" \ + "movb %%dl,%1\n\t" \ + "movb %%dh,%2" \ + ::"m" (*((addr)+2)), \ + "m" (*((addr)+4)), \ + "m" (*((addr)+7)), \ + "d" (base) \ + :) + +#define _set_limit(addr,limit) \ +__asm__("movw %%dx,%0\n\t" \ + "rorl $16,%%edx\n\t" \ + "movb %1,%%dh\n\t" \ + "andb $0xf0,%%dh\n\t" \ + "orb %%dh,%%dl\n\t" \ + "movb %%dl,%1" \ + ::"m" (*(addr)), \ + "m" (*((addr)+6)), \ + "d" (limit) \ + :"dx") + +#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base ) +#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 ) + +#define _get_base(addr) ({\ +unsigned long __base; \ +__asm__("movb %3,%%dh\n\t" \ + "movb %2,%%dl\n\t" \ + "shll $16,%%edx\n\t" \ + "movw %1,%%dx" \ + :"=d" (__base) \ + :"m" (*((addr)+2)), \ + "m" (*((addr)+4)), \ + "m" (*((addr)+7))); \ +__base;}) + +#define get_base(ldt) _get_base( ((char *)&(ldt)) ) + +#define get_limit(segment) ({ \ +unsigned long __limit; \ +__asm__("lsll %1,%0\n\tincl %0":"=r" (__limit):"r" (segment)); \ +__limit;}) + +#endif diff --git a/include/linux/sys.h b/include/linux/sys.h new file mode 100644 index 0000000000000000000000000000000000000000..69cd49b04b628f851d02e373231aa519124af5f3 --- /dev/null +++ b/include/linux/sys.h @@ -0,0 +1,191 @@ +//extern int sys_setup(); +//extern int sys_exit(); +extern int sys_fork(); +//extern int sys_read(); +extern int sys_write(); +//extern int sys_open(); +//extern int sys_close(); +//extern int sys_waitpid(); +//extern int sys_creat(); +//extern int sys_link(); +//extern int sys_unlink(); +//extern int sys_execve(); +//extern int sys_chdir(); +//extern int sys_time(); +//extern int sys_mknod(); +//extern int sys_chmod(); +//extern int sys_chown(); +//extern int sys_break(); +//extern int sys_stat(); +//extern int sys_lseek(); +//extern int sys_getpid(); +//extern int sys_mount(); +//extern int sys_umount(); +//extern int sys_setuid(); +//extern int sys_getuid(); +//extern int sys_stime(); +//extern int sys_ptrace(); +//extern int sys_alarm(); +//extern int sys_fstat(); +//extern int sys_pause(); +//extern int sys_utime(); +//extern int sys_stty(); +//extern int sys_gtty(); +//extern int sys_access(); +//extern int sys_nice(); +//extern int sys_ftime(); +//extern int sys_sync(); +//extern int sys_kill(); +//extern int sys_rename(); +//extern int sys_mkdir(); +//extern int sys_rmdir(); +//extern int sys_dup(); +//extern int sys_pipe(); +//extern int sys_times(); +//extern int sys_prof(); +//extern int sys_brk(); +//extern int sys_setgid(); +//extern int sys_getgid(); +//extern int sys_signal(); +//extern int sys_geteuid(); +//extern int sys_getegid(); +//extern int sys_acct(); +//extern int sys_phys(); +//extern int sys_lock(); +//extern int sys_ioctl(); +//extern int sys_fcntl(); +//extern int sys_mpx(); +//extern int sys_setpgid(); +//extern int sys_ulimit(); +//extern int sys_uname(); +//extern int sys_umask(); +//extern int sys_chroot(); +//extern int sys_ustat(); +//extern int sys_dup2(); +//extern int sys_getppid(); +//extern int sys_getpgrp(); +//extern int sys_setsid(); +//extern int sys_sigaction(); +//extern int sys_sgetmask(); +//extern int sys_ssetmask(); +//extern int sys_setreuid(); +//extern int sys_setregid(); +//extern int sys_sigpending(); +//extern int sys_sigsuspend(); +//extern int sys_sethostname(); +//extern int sys_setrlimit(); +//extern int sys_getrlimit(); +//extern int sys_getrusage(); +//extern int sys_gettimeofday(); +//extern int sys_settimeofday(); +//extern int sys_getgroups(); +//extern int sys_setgroups(); +//extern int sys_select(); +//extern int sys_symlink(); +//extern int sys_lstat(); +//extern int sys_readlink(); +//extern int sys_uselib(); + +fn_ptr sys_call_table[] = { + 0, /*sys_setup*/ + 0, /*sys_exit*/ + sys_fork, + 0, /*sys_read,*/ + sys_write, +// sys_open, +// sys_close, +// sys_waitpid, +// sys_creat, +// sys_link, +// +// sys_unlink, +// sys_execve, +// sys_chdir, +// sys_time, +// sys_mknod, +// sys_chmod, +// +// sys_chown, +// sys_break, +// sys_stat, +// sys_lseek, +// sys_getpid, +// sys_mount, +// +// sys_umount, +// sys_setuid, +// sys_getuid, +// sys_stime, +// sys_ptrace, +// sys_alarm, +// +// sys_fstat, +// sys_pause, +// sys_utime, +// sys_stty, +// sys_gtty, +// sys_access, +// +// sys_nice, +// sys_ftime, +// sys_sync, +// sys_kill, +// sys_rename, +// sys_mkdir, +// +// sys_rmdir, +// sys_dup, +// sys_pipe, +// sys_times, +// sys_prof, +// sys_brk, +// sys_setgid, +// +// sys_getgid, +// sys_signal, +// sys_geteuid, +// sys_getegid, +// sys_acct, +// sys_phys, +// +// sys_lock, +// sys_ioctl, +// sys_fcntl, +// sys_mpx, +// sys_setpgid, +// sys_ulimit, +// +// sys_uname, +// sys_umask, +// sys_chroot, +// sys_ustat, +// sys_dup2, +// sys_getppid, +// +// sys_getpgrp, +// sys_setsid, +// sys_sigaction, +// sys_sgetmask, +// sys_ssetmask, +// +// sys_setreuid, +// sys_setregid, +// sys_sigsuspend, +// sys_sigpending, +// sys_sethostname, +// sys_setrlimit, +// sys_getrlimit, +// sys_getrusage, +// sys_gettimeofday, +// sys_settimeofday, +// sys_getgroups, +// sys_setgroups, +// sys_select, +// sys_symlink, +// sys_lstat, +// sys_readlink, +// sys_uselib +}; + +int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr); + diff --git a/include/linux/tty.h b/include/linux/tty.h new file mode 100644 index 0000000000000000000000000000000000000000..839c5765b57ac5127d410325c88d99fc0c55b81f --- /dev/null +++ b/include/linux/tty.h @@ -0,0 +1,46 @@ +#ifndef _TTY_H +#define _TTY_H + +#include + +#define TTY_BUF_SIZE 1024 + +struct tty_queue { + unsigned long data; + unsigned long head; + unsigned long tail; + struct task_struct * proc_list; + char buf[TTY_BUF_SIZE]; +}; + +#define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1)) +#define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1)) +#define EMPTY(a) ((a).head == (a).tail) +#define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1)) +#define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)]) +#define FULL(a) (!LEFT(a)) +#define CHARS(a) (((a).head-(a).tail)&(TTY_BUF_SIZE-1)) +#define GETCH(queue,c) \ +(void)({c=(queue).buf[(queue).tail];INC((queue).tail);}) +#define PUTCH(c,queue) \ +(void)({(queue).buf[(queue).head]=(c);INC((queue).head);}) + +struct tty_struct { + struct termios termios; + int pgrp; + int stopped; + void (*write)(struct tty_struct * tty); + struct tty_queue read_q; + struct tty_queue write_q; + struct tty_queue secondary; +}; + +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" + +void con_init(); +void tty_init(); + +int tty_write(unsigned c, char * buf, int n); +void con_write(struct tty_struct * tty); + +#endif diff --git a/include/stdarg.h b/include/stdarg.h new file mode 100644 index 0000000000000000000000000000000000000000..ebb37ccc2b12ba032eed3d9ffd8adb2573629ad9 --- /dev/null +++ b/include/stdarg.h @@ -0,0 +1,29 @@ +#ifndef _STDARG_H +#define _STDARG_H + +typedef char *va_list; + +/* Amount of space required in an argument list for an arg of type TYPE. + * TYPE may alternatively be an expression whose type is used. */ + +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) + +#ifndef __sparc__ +#define va_start(AP, LASTARG) \ + (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) +#else +#define va_start(AP, LASTARG) \ + (__builtin_saveregs (), \ + AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) +#endif + +void va_end (va_list); /* Defined in gnulib */ +#define va_end(AP) + +#define va_arg(AP, TYPE) \ + (AP += __va_rounded_size (TYPE), \ + *((TYPE *) (AP - __va_rounded_size (TYPE)))) + +#endif /* _STDARG_H */ + diff --git a/include/stddef.h b/include/stddef.h new file mode 100644 index 0000000000000000000000000000000000000000..c340e05fb2b43243450038c8b8ca792552b59952 --- /dev/null +++ b/include/stddef.h @@ -0,0 +1,19 @@ +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef long ptrdiff_t; +#endif + +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned long size_t; +#endif + +#undef NULL +#define NULL ((void *)0) + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000000000000000000000000000000000000..8ebb2025ee55a9cada7368f385fe3836785468e4 --- /dev/null +++ b/include/string.h @@ -0,0 +1,402 @@ +#ifndef _STRING_H_ +#define _STRING_H_ + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned int size_t; +#endif + +extern char * strerror(int errno); + +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * (C) 1991 Linus Torvalds + */ + +extern inline char * strcpy(char * dest,const char *src) +{ +__asm__("cld\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + ::"S" (src),"D" (dest):"si","di","ax"); +return dest; +} + +extern inline char * strncpy(char * dest,const char *src,int count) +{ +__asm__("cld\n" + "1:\tdecl %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "rep\n\t" + "stosb\n" + "2:" + ::"S" (src),"D" (dest),"c" (count):"si","di","ax","cx"); +return dest; +} + +extern inline char * strcat(char * dest,const char * src) +{ +__asm__("cld\n\t" + "repne\n\t" + "scasb\n\t" + "decl %1\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff):"si","di","ax","cx"); +return dest; +} + +extern inline char * strncat(char * dest,const char * src,int count) +{ +__asm__("cld\n\t" + "repne\n\t" + "scasb\n\t" + "decl %1\n\t" + "movl %4,%3\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %2,%2\n\t" + "stosb" + ::"S" (src),"D" (dest),"a" (0),"c" (0xffffffff),"g" (count) + :"si","di","ax","cx"); +return dest; +} + +extern inline int strcmp(const char * cs,const char * ct) +{ +register int __res __asm__("ax"); +__asm__("cld\n" + "1:\tlodsb\n\t" + "scasb\n\t" + "jne 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 3f\n" + "2:\tmovl $1,%%eax\n\t" + "jl 3f\n\t" + "negl %%eax\n" + "3:" + :"=a" (__res):"D" (cs),"S" (ct):"si","di"); +return __res; +} + +extern inline int strncmp(const char * cs,const char * ct,int count) +{ +register int __res __asm__("ax"); +__asm__("cld\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %%eax,%%eax\n\t" + "jmp 4f\n" + "3:\tmovl $1,%%eax\n\t" + "jl 4f\n\t" + "negl %%eax\n" + "4:" + :"=a" (__res):"D" (cs),"S" (ct),"c" (count):"si","di","cx"); +return __res; +} + +extern inline char * strchr(const char * s,char c) +{ +register char * __res __asm__("ax"); +__asm__("cld\n\t" + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "movl $1,%1\n" + "2:\tmovl %1,%0\n\t" + "decl %0" + :"=a" (__res):"S" (s),"0" (c):"si"); +return __res; +} + +extern inline char * strrchr(const char * s,char c) +{ +register char * __res __asm__("dx"); +__asm__("cld\n\t" + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "jne 2f\n\t" + "movl %%esi,%0\n\t" + "decl %0\n" + "2:\ttestb %%al,%%al\n\t" + "jne 1b" + :"=d" (__res):"0" (0),"S" (s),"a" (c):"ax","si"); +return __res; +} + +extern inline int strspn(const char * cs, const char * ct) +{ +register char * __res __asm__("si"); +__asm__("cld\n\t" + "movl %4,%%edi\n\t" + "repne\n\t" + "scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%edx\n" + "1:\tlodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %4,%%edi\n\t" + "movl %%edx,%%ecx\n\t" + "repne\n\t" + "scasb\n\t" + "je 1b\n" + "2:\tdecl %0" + :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) + :"ax","cx","dx","di"); +return __res-cs; +} + +extern inline int strcspn(const char * cs, const char * ct) +{ +register char * __res __asm__("si"); +__asm__("cld\n\t" + "movl %4,%%edi\n\t" + "repne\n\t" + "scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%edx\n" + "1:\tlodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %4,%%edi\n\t" + "movl %%edx,%%ecx\n\t" + "repne\n\t" + "scasb\n\t" + "jne 1b\n" + "2:\tdecl %0" + :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) + :"ax","cx","dx","di"); +return __res-cs; +} + +extern inline char * strpbrk(const char * cs,const char * ct) +{ +register char * __res __asm__("si"); +__asm__("cld\n\t" + "movl %4,%%edi\n\t" + "repne\n\t" + "scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "movl %%ecx,%%edx\n" + "1:\tlodsb\n\t" + "testb %%al,%%al\n\t" + "je 2f\n\t" + "movl %4,%%edi\n\t" + "movl %%edx,%%ecx\n\t" + "repne\n\t" + "scasb\n\t" + "jne 1b\n\t" + "decl %0\n\t" + "jmp 3f\n" + "2:\txorl %0,%0\n" + "3:" + :"=S" (__res):"a" (0),"c" (0xffffffff),"0" (cs),"g" (ct) + :"ax","cx","dx","di"); +return __res; +} + +extern inline char * strstr(const char * cs,const char * ct) +{ +register char * __res __asm__("ax"); +__asm__("cld\n\t" \ + "movl %4,%%edi\n\t" + "repne\n\t" + "scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" /* NOTE! This also sets Z if searchstring='' */ + "movl %%ecx,%%edx\n" + "1:\tmovl %4,%%edi\n\t" + "movl %%esi,%%eax\n\t" + "movl %%edx,%%ecx\n\t" + "repe\n\t" + "cmpsb\n\t" + "je 2f\n\t" /* also works for empty string, see above */ + "xchgl %%eax,%%esi\n\t" + "incl %%esi\n\t" + "cmpb $0,-1(%%eax)\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "2:" + :"=a" (__res):"0" (0),"c" (0xffffffff),"S" (cs),"g" (ct) + :"cx","dx","di","si"); +return __res; +} + +inline int strlen(const char * s) +{ + int i = 0; + char* p = s; + while (*p) p++; + return p - s; +} + +extern char * ___strtok; + +extern inline char * strtok(char * s,const char * ct) +{ +register char * __res __asm__("si"); +__asm__("testl %1,%1\n\t" + "jne 1f\n\t" + "testl %0,%0\n\t" + "je 8f\n\t" + "movl %0,%1\n" + "1:\txorl %0,%0\n\t" + "movl $-1,%%ecx\n\t" + "xorl %%eax,%%eax\n\t" + "cld\n\t" + "movl %4,%%edi\n\t" + "repne\n\t" + "scasb\n\t" + "notl %%ecx\n\t" + "decl %%ecx\n\t" + "je 7f\n\t" /* empty delimeter-string */ + "movl %%ecx,%%edx\n" + "2:\tlodsb\n\t" + "testb %%al,%%al\n\t" + "je 7f\n\t" + "movl %4,%%edi\n\t" + "movl %%edx,%%ecx\n\t" + "repne\n\t" + "scasb\n\t" + "je 2b\n\t" + "decl %1\n\t" + "cmpb $0,(%1)\n\t" + "je 7f\n\t" + "movl %1,%0\n" + "3:\tlodsb\n\t" + "testb %%al,%%al\n\t" + "je 5f\n\t" + "movl %4,%%edi\n\t" + "movl %%edx,%%ecx\n\t" + "repne\n\t" + "scasb\n\t" + "jne 3b\n\t" + "decl %1\n\t" + "cmpb $0,(%1)\n\t" + "je 5f\n\t" + "movb $0,(%1)\n\t" + "incl %1\n\t" + "jmp 6f\n" + "5:\txorl %1,%1\n" + "6:\tcmpb $0,(%0)\n\t" + "jne 7f\n\t" + "xorl %0,%0\n" + "7:\ttestl %0,%0\n\t" + "jne 8f\n\t" + "movl %0,%1\n" + "8:" + :"=b" (__res),"=S" (___strtok) + :"0" (___strtok),"1" (s),"g" (ct) + :"ax","cx","dx","di"); +return __res; +} + +extern inline void * memcpy(void * dest,const void * src, int n) +{ +__asm__("cld\n\t" + "rep\n\t" + "movsb" + ::"c" (n),"S" (src),"D" (dest) + :"cx","si","di"); +return dest; +} + +extern inline void * memmove(void * dest,const void * src, int n) +{ +if (dest + +#endif diff --git a/include/sys/types.h b/include/sys/types.h new file mode 100644 index 0000000000000000000000000000000000000000..b667b459c6b3cc7546351a349f315398d9cdab8e --- /dev/null +++ b/include/sys/types.h @@ -0,0 +1,10 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +typedef long off_t; + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned long tcflag_t; + +#endif diff --git a/include/termios.h b/include/termios.h new file mode 100644 index 0000000000000000000000000000000000000000..b39ce107cca976ef1e4af51d0fc08711b14b183a --- /dev/null +++ b/include/termios.h @@ -0,0 +1,46 @@ +#ifndef _TERMIOS_H +#define _TERMIOS_H + +#define TTY_BUF_SIZE 1024 + +#define NCCS 17 +struct termios { + unsigned short c_iflag; + unsigned short c_oflag; + unsigned short c_cflag; + unsigned short c_lflag; + unsigned char c_line; + unsigned char c_cc[NCCS]; +}; + + +// iflag +#define ICRNL 0000400 + +// oflag +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 + + +// lflag +#define ISIG 0000001 +#define ICANON 0000002 +#define XCASE 0000004 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define IEXTEN 0100000 + +#endif diff --git a/include/unistd.h b/include/unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..060344121161ff06ee8155e260783722f0c560c5 --- /dev/null +++ b/include/unistd.h @@ -0,0 +1,133 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#ifdef __LIBRARY__ + +#define __NR_setup 0 /* used only by init, to get system going */ +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_chown 16 +#define __NR_break 17 +#define __NR_stat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_fstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_phys 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +#define __NR_uname 59 +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_lstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 + +#define _syscall0(type, name) \ +type name() { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name)); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + +#define _syscall3(type,name,atype,a,btype,b,ctype,c) \ +type name(atype a, btype b, ctype c) { \ + long __res; \ +__asm__ volatile("int $0x80\n\r"\ + : "=a"(__res) \ + : "a"(__NR_##name), "b"((long)a), "c"((long)b), "d"((long)c)); \ + if (__res >= 0) \ + return (type)__res; \ + errno = -__res; \ + return -1; \ +} + + + +#endif /* __LIBRARY__ */ + +extern int errno; + +int fork(); +int write(int fildes, const char * buf, off_t count); + +#endif diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..528e366fd6cb0cc37de1ae51efb602fddd53f9c4 --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,58 @@ +GCC := gcc +CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -fno-stack-protector -c -m32 +LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 +INCDIR := ../include +OBJS := head.o main.o sys_call.o asm.o sched.o printk.o vsprintf.o traps.o fork.o chr_drv/chr_drv.a ../mm/mm.o + ../lib/lib.a ../fs/fs.o + +system: $(OBJS) + $(LD) $(LDFLAG) -M -e startup_32 -o $@ $^ > System.map + +head.o : head.S + $(GCC) -m32 -traditional -c -o $@ $< + +sys_call.o : sys_call.S + $(GCC) -m32 -traditional -c -o $@ $< + +asm.o : asm.S + $(GCC) -m32 -traditional -c -o $@ $< + +main.o : main.c + $(GCC) $(CCFLAG) -o $@ $< + +sched.o : sched.c + $(GCC) $(CCFLAG) -o $@ $< + +printk.o : printk.c + $(GCC) $(CCFLAG) -o $@ $< + +vsprintf.o : vsprintf.c + $(GCC) $(CCFLAG) -o $@ $< + +traps.o : traps.c + $(GCC) $(CCFLAG) -o $@ $< + +fork.o : fork.c + $(GCC) $(CCFLAG) -o $@ $< + +chr_drv/chr_drv.a: chr_drv/*.c + cd chr_drv; make chr_drv.a; cd .. + +../mm/mm.o : ../mm/*.c + cd ../mm; make mm.o; cd ../kernel + +../lib/lib.a : ../lib/*.c + cd ../lib; make lib.a; cd ../kernel + +../fs/fs.o : ../fs/*.c + cd ../fs; make fs.o; cd ../kernel + +clean : + rm *.o + rm system + rm System.map + cd chr_drv; make clean; cd .. + cd ../mm; make clean; cd ../kernel + cd ../lib; make clean; cd ../kernel + cd ../fs; make clean; cd ../kernel + diff --git a/kernel/asm.S b/kernel/asm.S new file mode 100644 index 0000000000000000000000000000000000000000..c6e39b1e7db9c0ef6a40fb11037e6ed875d43c37 --- /dev/null +++ b/kernel/asm.S @@ -0,0 +1,90 @@ +.code32 +.globl divide_error, +.globl invalid_TSS, segment_not_present, stack_segment +.globl general_protection + +divide_error: + pushl $do_divide_error +no_error_code: + xchgl %eax, (%esp) + pushl %ebx + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + push %ds + push %es + push %fs + pushl $0 + leal 44(%esp), %edx + pushl %edx + movl $0x10, %edx + movw %dx, %ds + movw %dx, %es + movw %dx, %fs + call *%eax + addl $8, %esp + pop %fs + pop %es + pop %ds + popl %ebp + popl %esi + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %eax + iret + + +double_fault: + pushl $do_double_fault +error_code: + xchgl %eax, 4(%esp) + xchgl %ebx, (%esp) + pushl %ecx + pushl %edx + pushl %edi + pushl %esi + pushl %ebp + push %ds + push %es + push %fs + pushl %eax + leal 44(%esp), %eax + pushl %eax + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + call *%ebx + addl $8, %esp + pop %fs + pop %es + pop %ds + popl %ebp + popl %esi + popl %edi + popl %edx + popl %ecx + popl %ebx + popl %eax + iret + +invalid_TSS: + pushl $do_invalid_TSS + jmp error_code + +segment_not_present: + pushl $do_segment_not_present + jmp error_code + +stack_segment: + pushl $do_stack_segment + jmp error_code + +general_protection: + pushl $do_general_protection + jmp error_code + diff --git a/kernel/chr_drv/Makefile b/kernel/chr_drv/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..727b55694e372349df13f83fe893cf700c6d3a7f --- /dev/null +++ b/kernel/chr_drv/Makefile @@ -0,0 +1,26 @@ +AR := ar +LD := ld +GCC := gcc +CCFLAG := -m32 -I../../include -nostdinc -Wall -fomit-frame-pointer -fno-stack-protector -c +OBJS := tty_io.o console.o keyboard.o kboard.o + +chr_drv.a : $(OBJS) + $(AR) rcs $@ $^ + sync + +tty_io.o : tty_io.c + $(GCC) $(CCFLAG) -o $@ $< + +kboard.o : kboard.c + $(GCC) $(CCFLAG) -o $@ $< + +keyboard.o : keyboard.S + $(GCC) -m32 -traditional -c -o $@ $< + +console.o : console.c + $(GCC) $(CCFLAG) -o $@ $< + +clean : + rm *.o + rm chr_drv.a + diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c new file mode 100644 index 0000000000000000000000000000000000000000..6ce868ceedc9d700e3ed820bf12ca58b1417fe07 --- /dev/null +++ b/kernel/chr_drv/console.c @@ -0,0 +1,212 @@ +#include +#include + +#include +#include + +#define ORIG_X (*(unsigned char *)0x90000) +#define ORIG_Y (*(unsigned char *)0x90001) +#define ORIG_VIDEO_PAGE (*(unsigned short *)0x90004) +#define ORIG_VIDEO_MODE ((*(unsigned short *)0x90006) & 0xff) +#define ORIG_VIDEO_COLS (((*(unsigned short *)0x90006) & 0xff00) >> 8) +#define ORIG_VIDEO_LINES ((*(unsigned short *)0x9000e) & 0xff) +#define ORIG_VIDEO_EGA_AX (*(unsigned short *)0x90008) +#define ORIG_VIDEO_EGA_BX (*(unsigned short *)0x9000a) +#define ORIG_VIDEO_EGA_CX (*(unsigned short *)0x9000c) + +#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */ +#define VIDEO_TYPE_CGA 0x11 /* CGA Display */ +#define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */ +#define VIDEO_TYPE_EGAC 0x21 /* EGA/VGA in Color Mode */ + +extern void keyboard_interrupt(void); + +static unsigned char video_type; /* Type of display being used */ +static unsigned long video_num_columns; /* Number of text columns */ +static unsigned long video_num_lines; /* Number of test lines */ +static unsigned long video_mem_base; /* Base of video memory */ +static unsigned long video_mem_term; /* End of video memory */ +static unsigned long video_size_row; /* Bytes per row */ +static unsigned char video_page; /* Initial video page */ +static unsigned short video_port_reg; /* Video register select port */ +static unsigned short video_port_val; /* Video register value port */ +static unsigned short video_erase_char; + +static unsigned long origin; +static unsigned long scr_end; +static unsigned long pos; +static unsigned long x, y; +static unsigned long top, bottom; +static unsigned long attr = 0x07; + +static char buf[8]; + + +static inline void gotoxy(int new_x,unsigned int new_y) { + if (new_x > video_num_columns || new_y >= video_num_lines) + return; + + x = new_x; + y = new_y; + pos = origin + y*video_size_row + (x << 1); +} + +static inline void set_origin() { + cli(); + outb_p(12, video_port_reg); + outb_p(0xff & ((origin - video_mem_base) >> 9), video_port_val); + outb_p(13, video_port_reg); + outb_p(0xff & ((origin - video_mem_base) >> 1), video_port_val); + sti(); +} + +static inline void set_cursor() { + cli(); + outb_p(14, video_port_reg); + outb_p(0xff&((pos-video_mem_base)>>9), video_port_val); + outb_p(15, video_port_reg); + outb_p(0xff&((pos-video_mem_base)>>1), video_port_val); + sti(); +} + +static void scrup() { + if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM) { + if (!top && bottom == video_num_lines) { + origin += video_size_row; + pos += video_size_row; + scr_end += video_size_row; + + if (scr_end > video_mem_term) { + + } + + } + } +} + +static void lf() { + if (y + 1 < bottom) { + y++; + pos += video_size_row; + return; + } + scrup(); +} + +static void cr() { + pos -= x << 1; + x = 0; +} + +static void del() { + if (x) { + pos -= 2; + x--; + *(unsigned short*)pos = video_erase_char; + } +} + +void con_init() { + register unsigned char a; + char * display_desc = "????"; + char * display_ptr; + + video_num_columns = ORIG_VIDEO_COLS; + video_size_row = video_num_columns * 2; + video_num_lines = ORIG_VIDEO_LINES; + video_page = ORIG_VIDEO_PAGE; + video_erase_char = 0x0720; + + /* Is this a monochrome display? */ + if (ORIG_VIDEO_MODE == 7) { + video_mem_base = 0xb0000; + video_port_reg = 0x3b4; + video_port_val = 0x3b5; + if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { + video_type = VIDEO_TYPE_EGAM; + video_mem_term = 0xb8000; + display_desc = "EGAm"; + } + else { + video_type = VIDEO_TYPE_MDA; + video_mem_term = 0xb2000; + display_desc = "*MDA"; + } + } + else { /* color display */ + video_mem_base = 0xb8000; + video_port_reg = 0x3d4; + video_port_val = 0x3d5; + + if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { + video_type = VIDEO_TYPE_EGAC; + video_mem_term = 0xc0000; + display_desc = "EGAc"; + } + else { + video_type = VIDEO_TYPE_CGA; + video_mem_term = 0xba000; + display_desc = "*CGA"; + } + } + + display_ptr = ((char *)video_mem_base) + video_size_row - 8; + while (*display_desc) { + *display_ptr++ = *display_desc++; + display_ptr++; + } + + origin = video_mem_base; + scr_end = video_mem_base + video_num_lines * video_size_row; + top = 0; + bottom = video_num_lines; + + gotoxy(ORIG_X, ORIG_Y); + set_cursor(); + + set_trap_gate(0x21,&keyboard_interrupt); + outb_p(inb_p(0x21)&0xfd,0x21); + a=inb_p(0x61); + outb_p(a|0x80,0x61); + outb_p(a,0x61); +} + +void con_write(struct tty_struct* tty) { + int nr; + char c; + + nr = CHARS(tty->write_q); + + while(nr--) { + GETCH(tty->write_q, c); + if (c > 31 && c < 127) { + if (x >= video_num_columns) { + x -= video_num_columns; + pos -= video_size_row; + lf(); + } + + *(char *)pos = c; + *(((char*)pos) + 1) = attr; + pos += 2; + x++; + } + else if (c == 10 || c == 11 || c == 12) + lf(); + else if (c == 13) + cr(); + else if (c == 127) { + del(); + } + else if (c == 8) { + if (x) { + x--; + pos -= 2; + } + } + } + + gotoxy(x, y); + set_cursor(); +} + diff --git a/kernel/chr_drv/kboard.c b/kernel/chr_drv/kboard.c new file mode 100644 index 0000000000000000000000000000000000000000..552204b2701330a42ff2f1ca056db7211bfda853 --- /dev/null +++ b/kernel/chr_drv/kboard.c @@ -0,0 +1,80 @@ +#include +#include +#include + +int cursor = 0x1e0; + +static char key_map[0x7f] = { + 0, 27, + '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', + 127, 9, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', + 10, 0, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', + '`', 0, + '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', + 0, '*', 0, 32, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '-', 0, 0, 0, '+', + 0,0,0,0,0,0,0, + '>', + 0,0,0,0,0,0,0,0,0,0}; + +static char shift_map[0x7f] = { + 0,27, + '!', '@', '#', '$', '%', '^', '&', '*','(',')','_','+', + 127,9, + 'Q','W','E','R','T','Y','U','I','O','P','{','}', + 10,0, + 'A','S','D','F','G','H','J','K','L',':','\"', + '~',0, + '|','Z','X','C','V','B','N','M','<','>','?', + 0,'*',0,32, //36h-39h + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, //3Ah-49h + '-',0,0,0,'+', //4A-4E + 0,0,0,0,0,0,0, //4F-55 + '>', + 0,0,0,0,0,0,0,0,0,0}; + +#define showh(tmp) \ + __asm__("movl cursor, %%edx\n\r" \ + "movb $0x0f, %%ah \n\r" \ + "movw %%ax, %%gs:(%%edx)\n\r" \ + "addl $0x02, cursor\n\r" \ + ::"a"(tmp):"edx", "memory"); + +char mode = 0; +char e0 = 0; + +void keyboard_handler(void) +{ + unsigned char a, scan_code; + + scan_code = inb_p(0x60); + a = inb_p(0x61); + outb_p(a | 0x80, 0x61); + outb(a & 0x7f, 0x61); + outb(0x20, 0x20); + + if (scan_code == 0xE0) + { + e0 = 1; + } + else if (scan_code == 0x1d) // left ctrl + { + mode = 3; + } + else if (scan_code == 0x2a) + { + mode = 5; + } + else + { + if (scan_code & 0x80) + { + showh(key_map[scan_code & 0x7f]); + } + } +} + + diff --git a/kernel/chr_drv/keyboard.S b/kernel/chr_drv/keyboard.S new file mode 100644 index 0000000000000000000000000000000000000000..caa9060a05c0395f4287b56cd072693e940b4e44 --- /dev/null +++ b/kernel/chr_drv/keyboard.S @@ -0,0 +1,30 @@ +.code32 +.text +.globl keyboard_interrupt + +.align 4 +keyboard_interrupt: + pushw %ds + pushw %es + pushw %fs + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movl $0x17, %eax + movw %ax, %fs + pushl %eax + call keyboard_handler + popl %eax + popl %eax + popl %ebx + popl %ecx + popl %edx + popw %fs + popw %es + popw %ds + iret + diff --git a/kernel/chr_drv/tty_io.c b/kernel/chr_drv/tty_io.c new file mode 100644 index 0000000000000000000000000000000000000000..b93f4780874e9d9fbdcfc9a65a165e08063b5df0 --- /dev/null +++ b/kernel/chr_drv/tty_io.c @@ -0,0 +1,73 @@ +#include +#include +#include + +#define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f) + +#define O_POST(tty) _O_FLAG((tty),OPOST) +#define O_NLCR(tty) _O_FLAG((tty),ONLCR) +#define O_CRNL(tty) _O_FLAG((tty),OCRNL) +#define O_NLRET(tty) _O_FLAG((tty),ONLRET) +#define O_LCUC(tty) _O_FLAG((tty),OLCUC) + +struct tty_struct tty_table[] = { + { + { + ICRNL, + OPOST | ONLCR, + 0, + ISIG | ICANON | ECHO | ECHOCTL | ECHOKE, + 0, + INIT_C_CC + }, + 0, + 0, + con_write, + {0, 0, 0, 0, ""}, + {0, 0, 0, 0, ""}, + {0, 0, 0, 0, ""}, + } +}; + + +void tty_init() { + con_init(); +} + +int tty_write(unsigned channel, char* buf, int nr) { + static int cr_flag = 0; + struct tty_struct * tty; + char c, *b=buf; + + if (channel > 2 || nr < 0) + return -1; + + tty = tty_table + channel; + while (nr > 0) { + c = get_fs_byte(b); + if (O_POST(tty)) { + if (c=='\r' && O_CRNL(tty)) + c = '\n'; + else if (c=='\n' && O_NLRET(tty)) + c = '\r'; + + if (c=='\n' && !cr_flag && O_NLCR(tty)) { + cr_flag = 1; + PUTCH(13,tty->write_q); + continue; + } + + if (O_LCUC(tty)) { + c = toupper(c); + } + } + + b++; nr--; + cr_flag = 0; + PUTCH(c,tty->write_q); + } + + tty->write(tty); + return (b-buf); +} + diff --git a/kernel/fork.c b/kernel/fork.c new file mode 100644 index 0000000000000000000000000000000000000000..82eeeb45dcac8375a9a7fb1664426191f46b5df6 --- /dev/null +++ b/kernel/fork.c @@ -0,0 +1,104 @@ +#include + +#include +#include + +long last_pid = 0; + +int copy_mem(int nr, struct task_struct* p) { + unsigned long old_data_base,new_data_base,data_limit; + unsigned long old_code_base,new_code_base,code_limit; + + code_limit = get_limit(0x0f); + data_limit = get_limit(0x17); + old_code_base = get_base(current->ldt[1]); + old_data_base = get_base(current->ldt[2]); + if (old_data_base != old_code_base) + printk("We don't support separate I&D"); + if (data_limit < code_limit) + printk("Bad data_limit"); + + new_data_base = new_code_base = nr * TASK_SIZE; + set_base(p->ldt[1],new_code_base); + set_base(p->ldt[2],new_data_base); + if (copy_page_tables(old_data_base,new_data_base,data_limit)) { + free_page_tables(new_data_base,data_limit); + return -ENOMEM; + } + + return 0; +} + +int copy_process(int nr,long ebp,long edi,long esi,long gs,long none, + long ebx,long ecx,long edx, long orig_eax, + long fs,long es,long ds, + long eip,long cs,long eflags,long esp,long ss) { + struct task_struct *p; + + p = (struct task_struct *) get_free_page(); + if (!p) + return -EAGAIN; + + task[nr] = p; + *p = *current; + + p->pid = last_pid; + p->p_pptr = current; + + p->ldt[0] = current->ldt[0]; + p->ldt[1] = current->ldt[1]; + p->ldt[2] = current->ldt[2]; + + p->tss.back_link = 0; + p->tss.esp0 = PAGE_SIZE + (long)p - 8; + p->tss.ss0 = 0x10; + p->tss.cr3 = current->tss.cr3; + p->tss.eip = eip; + p->tss.eflags = eflags; + p->tss.eax = 0; + p->tss.ecx = ecx; + p->tss.edx = edx; + p->tss.ebx = ebx; + p->tss.esp = esp; + p->tss.ebp = ebp; + p->tss.esi = esi; + p->tss.edi = edi; + p->tss.es = es & 0xffff; + p->tss.cs = cs & 0xffff; + p->tss.ss = ss & 0xffff; + p->tss.ds = ds & 0xffff; + p->tss.fs = fs & 0xffff; + p->tss.gs = gs & 0xffff; + p->tss.ldt = _LDT(nr); + p->tss.trace_bitmap = 0x80000000; + + if (copy_mem(nr, p)) { + task[nr] = NULL; + free_page((long)p); + return -EAGAIN; + } + + set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss)); + set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt)); + + return last_pid; +} + +int find_empty_process() { + int i; +repeat: + if ((++last_pid)<0) last_pid=1; + + for(i=0 ; ipid == last_pid)) + goto repeat; + } + + for (i = 1; i < NR_TASKS; i++) { + if (!task[i]) + return i; + } + + return -EAGAIN; +} + diff --git a/kernel/head.S b/kernel/head.S new file mode 100644 index 0000000000000000000000000000000000000000..b0643b4207b5c7cf1d0882310ce321e6692c224c --- /dev/null +++ b/kernel/head.S @@ -0,0 +1,158 @@ +.code32 +.text +.globl startup_32, idt, gdt, pg_dir, tmp_floppy_area +pg_dir: +startup_32: + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + lss stack_start, %esp + call setup_idt + call setup_gdt + + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + + movl $0x18, %eax + movw %ax, %gs + + xorl %eax, %eax +1: + incl %eax + movl %eax, 0x000000 + cmpl %eax, 0x100000 + je 1b + + + jmp after_page_tables + + +setup_idt: + leal ignore_int, %edx + movl $0x00080000, %eax + movw %dx, %ax + movw $0x8e00, %dx + leal idt, %edi + movl $256, %ecx +rp_sidt: + movl %eax, (%edi) + movl %edx, 4(%edi) + addl $8, %edi + decl %ecx + jne rp_sidt + lidt idt_descr + ret + +setup_gdt: + lgdt gdt_descr + ret + +.org 0x1000 +pg0: + +.org 0x2000 +pg1: + +.org 0x3000 +pg2: + +.org 0x4000 +pg3: + +.org 0x5000 + +tmp_floppy_area: +.fill 1024, 1, 0 + +after_page_tables: +/*we call jump to main at this*/ + pushl $0 + pushl $0 + pushl $0 + pushl $L6 + pushl $main + jmp setup_paging +L6: + jmp L6 + +ignore_int: + /* we do not have function _printk now, so trick it */ + pushl %eax + pushl %ecx + pushl %edx + pushw %ds + pushw %es + pushw %fs + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + /* call _printk */ + movl $0x96, %edi + movb $'I', %al + movb $0x0c, %ah + movw %ax, %gs:(%edi) + popw %fs + popw %es + popw %ds + popl %edx + popl %ecx + popl %eax + iret + +.align 4 +setup_paging: + movl $1024*5, %ecx + xorl %eax, %eax + xorl %edi, %edi + cld + rep + stosl + + movl $pg0 + 7, pg_dir + movl $pg1 + 7, pg_dir + 4 + movl $pg2 + 7, pg_dir + 8 + movl $pg3 + 7, pg_dir + 12 + movl $pg3 + 4092, %edi + movl $0xfff007, %eax + std +1: + stosl + subl $0x1000, %eax + jge 1b + xorl %eax, %eax + movl %eax, %cr3 + movl %cr0, %eax + orl $0x80000000, %eax + movl %eax, %cr0 + + ret + +.align 4 +.word 0 +idt_descr: + .word 256*8-1 + .long idt + +.align 4 +.word 0 +gdt_descr: + .word 256 * 8 - 1 + .long gdt + +.align 8 +idt: + .fill 256, 8, 0 + +gdt: + .quad 0x0000000000000000 + .quad 0x00c09a0000000fff + .quad 0x00c0920000000fff + .quad 0x00c0f20b8000ffff + .quad 0x0000000000000000 + .fill 251, 8,0 diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000000000000000000000000000000000000..ff2c3381ffc2bbff6f811f7167a20c557ab4bb63 --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,91 @@ +#define __LIBRARY__ + +#include + +inline _syscall0(int, fork); + +int errno; + +#include + +#include +#include +#include + +#include + +static char printbuf[1024]; + +int printf(const char* fmt, ...); + +extern int vsprintf(char* buf, const char* fmt, va_list args); +extern void mem_init(long start, long end); + +#define EXT_MEM_K (*(unsigned short *)0x90002) + +static long memory_end = 0; +static long buffer_memory_end = 0; +static long main_memory_start = 0; + +void main(void) +{ + /* + char* p1 = "hello world!\0"; + short* p = (short*)0xb8000; + while(*p1) { + *p++ = 0xf00 | (*p1++); + } + */ + + //__asm__("int $0x80\n\r"::); + + memory_end = (1<<20) + (EXT_MEM_K<<10); + memory_end &= 0xfffff000; + if (memory_end > 16*1024*1024) + memory_end = 16*1024*1024; + if (memory_end > 12*1024*1024) + buffer_memory_end = 4*1024*1024; + else if (memory_end > 6*1024*1024) + buffer_memory_end = 2*1024*1024; + else + buffer_memory_end = 1*1024*1024; + + main_memory_start = buffer_memory_end; + mem_init(main_memory_start, memory_end); + + trap_init(); + sched_init(); + + tty_init(); + + printk("\nmemory start at 0x%x, end at 0x%x\n", main_memory_start, memory_end); + + move_to_user_mode(); + + if (!fork()) { + printf("In second process, user mode!\n"); + test_b(); + while(1) {} + } + + __asm__("movl $0x0, %edi\n\r" + "movw $0x18, %ax\n\t" + "movw %ax, %gs \n\t" + "movb $0x0c, %ah\n\r" + "movb $'A', %al\n\r" + "movw %ax, %gs:(%edi)\n\r"); + + for(;;); +} + +int printf(const char* fmt, ...) { + va_list args; + int i; + + va_start(args, fmt); + write(1, printbuf, i = vsprintf(printbuf, fmt, args)); + va_end(args); + + return i; +} + diff --git a/kernel/printk.c b/kernel/printk.c new file mode 100644 index 0000000000000000000000000000000000000000..8b247b77505ae4cd9bb57bf4377835c81b6ed8e7 --- /dev/null +++ b/kernel/printk.c @@ -0,0 +1,31 @@ +#include +#include +#include + +static char buf[1024]; + +extern int vsprintf(char* buf, const char* fmt, va_list args); + +int printk(const char* fmt, ...) { + va_list args; + int i; + + va_start(args, fmt); + i = vsprintf(buf, fmt, args); + va_end(args); + + __asm__("pushw %%fs\n\t" + "pushw %%ds\n\t" + "popw %%fs\n\t" + "pushl %0\n\t" + "pushl $buf\n\t" + "pushl $0\n\t" + "call tty_write\n\t" + "addl $8, %%esp\n\t" + "popl %0\n\t" + "popw %%fs" + ::"r"(i):"ax", "cx", "dx"); + + return i; +} + diff --git a/kernel/sched.c b/kernel/sched.c new file mode 100644 index 0000000000000000000000000000000000000000..45c060dfb6aa87bd780de81bfbf7a35a8bf85e6b --- /dev/null +++ b/kernel/sched.c @@ -0,0 +1,97 @@ +#include +#include +#include + +#include +#include + +#define COUNTER 100 + +#define LATCH (1193180/HZ) +#define PAGE_SIZE 4096 + +extern int system_call(); +extern void timer_interrupt(); + +union task_union { + struct task_struct task; + char stack[PAGE_SIZE]; +}; + +static union task_union init_task = {INIT_TASK, }; +//static union task_union second_task; + +struct task_struct * current = &(init_task.task); +struct task_struct * task[NR_TASKS] = {&(init_task.task), }; + +long user_stack[PAGE_SIZE >> 2]; + +struct +{ + long *a; + short b; +} stack_start = {&user_stack[PAGE_SIZE >> 2], 0x10}; + +void schedule() { + if (current == task[0] && task[1]) { + switch_to(1); + } + else if (current == task[1]) { + switch_to(0); + } +} + +int clock = COUNTER; + +void do_timer(long cpl) { + if (clock >0 && clock <= COUNTER) { + clock--; + } + else if (clock == 0) { + schedule(); + } + else { + clock = COUNTER; + } +} + +void sched_init() { + int i; + struct desc_struct * p; + + set_tss_desc(gdt + FIRST_TSS_ENTRY, &(init_task.task.tss)); + set_ldt_desc(gdt + FIRST_LDT_ENTRY, &(init_task.task.ldt)); + + p = gdt+2+FIRST_TSS_ENTRY; + + for(i=1;ia = p->b = 0; + p++; + p->a = p->b = 0; + p++; + } + + __asm__("pushfl; andl $0xffffbfff, (%esp); popfl"); + ltr(0); + lldt(0); + + /* open the clock interruption! */ + outb_p(0x36, 0x43); + outb_p(LATCH & 0xff, 0x40); + outb(LATCH >> 8, 0x40); + set_intr_gate(0x20, &timer_interrupt); + outb(inb_p(0x21) & ~0x01, 0x21); + + set_system_gate(0x80, &system_call); +} + +void test_b(void) { +__asm__("movl $0x30, %edi\n\r" + "movw $0x18, %ax\n\t" + "movw %ax, %gs \n\t" + "movb $0x0f, %ah\n\r" + "movb $'B', %al\n\r" + "movw %ax, %gs:(%edi)\n\r"); +} + diff --git a/kernel/sys_call.S b/kernel/sys_call.S new file mode 100644 index 0000000000000000000000000000000000000000..7ea146f0e96e73bba2aad760a71947457b8c4d59 --- /dev/null +++ b/kernel/sys_call.S @@ -0,0 +1,87 @@ +.code32 +.text +.globl system_call, timer_interrupt, sys_fork + +EAX = 0x00 +EBX = 0x04 +ECX = 0x08 +EDX = 0x0C +FS = 0x10 +ES = 0x14 +DS = 0x18 +EIP = 0x1c +CS = 0x20 +EFLAGS = 0x24 +OLDESP = 0x28 +OLDSS = 0x2c + +int_msg: + .asciz "In kernel interrupt\n\r" + +system_call: + pushl %ds + pushl %es + pushl %fs + pushl %eax + pushl %edx + pushl %ecx + pushl %ebx + movl $0x10, %edx + movw %dx, %ds + movw %dx, %es + movl $0x17, %edx + movw %dx, %fs + + call sys_call_table(, %eax, 4) + pushl %eax + + +ret_from_sys_call: + popl %eax + popl %ebx + popl %ecx + popl %edx + addl $4, %esp + popl %fs + popl %es + popl %ds + iret + +.align 4 +timer_interrupt: + pushl %ds + pushl %es + pushl %fs + pushl $-1 + pushl %edx + pushl %ecx + pushl %ebx + pushl %eax + movl $0x10, %eax + movw %ax, %ds + movw %ax, %es + movl $0x17, %eax + movw %ax, %fs + movb $0x20, %al + outb %al, $0x20 + movl CS(%esp), %eax + andl $3, %eax + pushl %eax + call do_timer + addl $4, %esp + jmp ret_from_sys_call + +.align 4 +sys_fork: + call find_empty_process + testl %eax, %eax + js 1f + pushl %gs + pushl %esi + pushl %edi + pushl %ebp + pushl %eax + call copy_process + addl $20, %esp +1: ret + diff --git a/kernel/traps.c b/kernel/traps.c new file mode 100644 index 0000000000000000000000000000000000000000..f10cce22138dd7596ab6c3cfa24fd03635be5ae1 --- /dev/null +++ b/kernel/traps.c @@ -0,0 +1,87 @@ +#include +#include +#include + +#define get_seg_byte(seg,addr) ({ \ +register char __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + +#define get_seg_long(seg,addr) ({ \ +register unsigned long __res; \ +__asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ + :"=a" (__res):"0" (seg),"m" (*(addr))); \ +__res;}) + + +#define _fs() ({ \ +register unsigned short __res; \ +__asm__("mov %%fs,%%ax":"=a" (__res):); \ +__res;}) + +void divide_error(); +void invalid_TSS(); +void segment_not_present(); +void stack_segment(); +void general_protection(); +void page_fault(); + +static void die(char* str, long esp_ptr, long nr) { + int i = 0; + long* esp = (long*)esp_ptr; + + printk("\n\r%s: %04x\n\r", str, nr & 0xffff); + printk("EIP:\t%04x:%p\n\rEFLAGS:\t%p\n\rESP:\t%04x:%p\n\r", + esp[1],esp[0],esp[2],esp[4],esp[3]); + + printk("fs: %04x\n\r",_fs()); + printk("base: %p, limit: %p\n\r",get_base(current->ldt[1]),get_limit(0x17)); + if (esp[4] == 0x17) { + printk("Stack: "); + for (i=0;i<4;i++) + printk("%p ",get_seg_long(0x17,i+(long *)esp[3])); + printk("\n\r"); + } + + for(i=0;i<10;i++) + printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); + printk("\n\r"); + + while (1) { + } +} + +void do_divide_error(long esp, long error_code) { + die("divide error", esp, error_code); +} + +void do_double_fault(long esp, long error_code) { + die("double fault", esp, error_code); +} + +void do_segment_not_present(long esp, long error_code) { + die("segment not present", esp, error_code); +} + +void do_invalid_TSS(long esp, long error_code) { + die("invalid tss", esp, error_code); +} + +void do_stack_segment(long esp, long error_code) { + die("stack segment", esp, error_code); +} + +void do_general_protection(long esp, long error_code) { + die("general protection", esp, error_code); +} + +void trap_init() { + set_trap_gate(0, ÷_error); + set_trap_gate(10, &invalid_TSS); + set_trap_gate(11, &segment_not_present); + set_trap_gate(12, &stack_segment); + set_trap_gate(13, &general_protection); + set_trap_gate(14, &page_fault); +} + diff --git a/kernel/vsprintf.c b/kernel/vsprintf.c new file mode 100644 index 0000000000000000000000000000000000000000..64aa7bc6266d70fc36d4e0458ad849001ecd5dab --- /dev/null +++ b/kernel/vsprintf.c @@ -0,0 +1,243 @@ +#include +#include + +#define is_digit(c) ((c) >= '0' && (c) <= '9') + +static int skip_atoi(const char **s) { + int i=0; + + while (is_digit(**s)) { + i = i*10 + *((*s)++) - '0'; + } + + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ + +#define do_div(n,base) ({ \ + int __res; \ + __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \ + __res; }) + +static char * number(char * str, int num, int base, int size, int precision + ,int type) { + char c,sign,tmp[36]; + const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i = 0; + + if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; + if (type&LEFT) type &= ~ZEROPAD; + if (base<2 || base>36) + return 0; + + c = (type & ZEROPAD) ? '0' : ' ' ; + if (type&SIGN && num<0) { + sign = '-'; + num = -num; + } + else { + sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0); + } + + if (sign) size--; + if (type&SPECIAL) { + if (base==16) size -= 2; + else if (base==8) size--; + } + + if (num==0) + tmp[i++]='0'; + else { + while (num!=0) { + tmp[i++]=digits[do_div(num,base)]; + } + } + + if (i>precision) precision=i; + size -= precision; + + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) + *str++ = ' '; + } + + if (sign) + *str++ = sign; + + if (type&SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + + if (!(type&LEFT)) { + while(size-->0) + *str++ = c; + } + + while(i0) + *str++ = tmp[i]; + + while(size-->0) + *str++ = ' '; + + return str; +} + +int vsprintf(char *buf, const char *fmt, va_list args) { + int len; + int i; + char * str; + char *s; + int *ip; + + int flags; /* flags to number() */ + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + + for (str = buf; *fmt; fmt++) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (is_digit(*fmt)) { + field_width = skip_atoi(&fmt); + } + else if (*fmt == '*') { + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + /* it's the next argument */ + precision = va_arg(args, int); + } + + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { + qualifier = *fmt; + ++fmt; + } + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + break; + case 's': + s = va_arg(args, char *); + len = strlen(s); + + if (precision < 0) + precision = len; + else if (len > precision) + len = precision; + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + break; + + case 'o': + str = number(str, va_arg(args, unsigned long), 8, + field_width, precision, flags); + break; + + case 'p': + if (field_width == -1) { + field_width = 8; + flags |= ZEROPAD; + } + str = number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + break; + + case 'x': + flags |= SMALL; + case 'X': + str = number(str, va_arg(args, unsigned long), 16, + field_width, precision, flags); + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + str = number(str, va_arg(args, unsigned long), 10, + field_width, precision, flags); + break; + + case 'n': + ip = va_arg(args, int *); + *ip = (str - buf); + break; + + default: + if (*fmt != '%') + *str++ = '%'; + + if (*fmt) + *str++ = *fmt; + else + --fmt; + break; + } + } + + *str = '\0'; + return str-buf; +} + diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f25f2c46bc8b9ee44eeb33a208797b6c15f62dd8 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,20 @@ +AR := ar +LD := ld +GCC := gcc +CCFLAG := -m32 -I../include -nostdinc -Wall -fomit-frame-pointer -fno-stack-protector -c +OBJS := ctype.o write.o + +lib.a : $(OBJS) + $(AR) rcs $@ $^ + sync + +ctype.o : ctype.c + $(GCC) $(CCFLAG) -o $@ $< + +write.o : write.c + $(GCC) $(CCFLAG) -o $@ $< + +clean : + rm *.o + rm lib.a + diff --git a/lib/ctype.c b/lib/ctype.c new file mode 100644 index 0000000000000000000000000000000000000000..a9379e959bb1d77d1f58c4c6dfcd9a33ee9bfbe5 --- /dev/null +++ b/lib/ctype.c @@ -0,0 +1,30 @@ +#include + +char _ctmp; + +unsigned char _ctype[] = {0x00, + _C,_C,_C,_C,_C,_C,_C,_C, + _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, + _C,_C,_C,_C,_C,_C,_C,_C, + _C,_C,_C,_C,_C,_C,_C,_C, + _S|_SP,_P,_P,_P,_P,_P,_P,_P, + _P,_P,_P,_P,_P,_P,_P,_P, + _D,_D,_D,_D,_D,_D,_D,_D, + _D,_D,_P,_P,_P,_P,_P,_P, + _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, + _U,_U,_U,_U,_U,_U,_U,_U, + _U,_U,_U,_U,_U,_U,_U,_U, + _U,_U,_U,_P,_P,_P,_P,_P, + _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, + _L,_L,_L,_L,_L,_L,_L,_L, + _L,_L,_L,_L,_L,_L,_L,_L, + _L,_L,_L,_P,_P,_P,_P,_C, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + diff --git a/lib/write.c b/lib/write.c new file mode 100644 index 0000000000000000000000000000000000000000..102f7518ca053c4a3d91421bc937e85562165e82 --- /dev/null +++ b/lib/write.c @@ -0,0 +1,5 @@ +#define __LIBRARY__ +#include + +_syscall3(int,write,int,fd,const char *,buf,off_t,count) + diff --git a/mm/Makefile b/mm/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6c1850df2a430f7781a26de4a3b6d31e7057d5d7 --- /dev/null +++ b/mm/Makefile @@ -0,0 +1,22 @@ +GCC := gcc +LD := ld +CCFLAG := -I../include -nostdinc -Wall -fomit-frame-pointer -fno-stack-protector -c -m32 +LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 +INCDIR := ../include +OBJS := swap.o memory.o page.o + +mm.o : $(OBJS) + $(LD) -m elf_i386 -r -o $@ $^ + +memory.o : memory.c + $(GCC) $(CCFLAG) -o $@ $< + +swap.o : swap.c + $(GCC) $(CCFLAG) -o $@ $< + +page.o : page.S + $(GCC) -m32 -traditional -c -o $@ $< + +clean : + rm *.o + diff --git a/mm/memory.c b/mm/memory.c new file mode 100644 index 0000000000000000000000000000000000000000..f45963f90302d913cdff77aa80f858ef586038a8 --- /dev/null +++ b/mm/memory.c @@ -0,0 +1,147 @@ +#include + +unsigned long HIGH_MEMORY = 0; + +unsigned char mem_map [ PAGING_PAGES ] = {0,}; + +#define copy_page(from,to) \ +__asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):) + +void free_page(unsigned long addr) { + if (addr < LOW_MEM) return; + if (addr >= HIGH_MEMORY) + printk("trying to free nonexistent page"); + + addr -= LOW_MEM; + addr >>= 12; + if (mem_map[addr]--) return; + mem_map[addr]=0; + printk("trying to free free page"); +} + +int free_page_tables(unsigned long from,unsigned long size) { + unsigned long *pg_table; + unsigned long * dir, nr; + + if (from & 0x3fffff) + printk("free_page_tables called with wrong alignment"); + if (!from) + printk("Trying to free up swapper memory space"); + size = (size + 0x3fffff) >> 22; + dir = (unsigned long *) ((from>>20) & 0xffc); + + for ( ; size-->0 ; dir++) { + if (!(1 & *dir)) + continue; + pg_table = (unsigned long *) (0xfffff000 & *dir); + for (nr=0 ; nr<1024 ; nr++) { + if (*pg_table) { + if (1 & *pg_table) + free_page(0xfffff000 & *pg_table); + *pg_table = 0; + } + pg_table++; + } + free_page(0xfffff000 & *dir); + *dir = 0; + } + invalidate(); + return 0; +} + +int copy_page_tables(unsigned long from,unsigned long to,long size) { + unsigned long * from_page_table; + unsigned long * to_page_table; + unsigned long this_page; + unsigned long * from_dir, * to_dir; + unsigned long nr; + + if ((from&0x3fffff) || (to&0x3fffff)) { + printk("copy_page_tables called with wrong alignment"); + } + + /* Get high 10 bits. As PDE is 4 byts, so right shift 20.*/ + from_dir = (unsigned long *) ((from>>20) & 0xffc); + to_dir = (unsigned long *) ((to>>20) & 0xffc); + + size = ((unsigned) (size+0x3fffff)) >> 22; + for( ; size-->0 ; from_dir++,to_dir++) { + if (1 & *to_dir) + printk("copy_page_tables: already exist"); + if (!(1 & *from_dir)) + continue; + + from_page_table = (unsigned long *) (0xfffff000 & *from_dir); + if (!(to_page_table = (unsigned long *) get_free_page())) + return -1; + + *to_dir = ((unsigned long) to_page_table) | 7; + nr = (from==0)?0xA0:1024; + + for ( ; nr-- > 0 ; from_page_table++,to_page_table++) { + this_page = *from_page_table; + if (!this_page) + continue; + if (!(1 & this_page)) + continue; + + this_page &= ~2; + *to_page_table = this_page; + + if (this_page > LOW_MEM) { + *from_page_table = this_page; + this_page -= LOW_MEM; + this_page >>= 12; + mem_map[this_page]++; + } + } + } + invalidate(); + return 0; +} + +void un_wp_page(unsigned long * table_entry) { + unsigned long old_page,new_page; + old_page = 0xfffff000 & *table_entry; + + if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) { + *table_entry |= 2; + invalidate(); + return; + } + + new_page=get_free_page(); + if (old_page >= LOW_MEM) + mem_map[MAP_NR(old_page)]--; + copy_page(old_page,new_page); + *table_entry = new_page | 7; + invalidate(); +} + +void do_wp_page(unsigned long error_code, unsigned long address) { + if (address < TASK_SIZE) + printk("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r"); + + un_wp_page((unsigned long *) + (((address>>10) & 0xffc) + (0xfffff000 & + *((unsigned long *) ((address>>20) &0xffc))))); +} + +void mem_init(long start_mem, long end_mem) { + int i; + + HIGH_MEMORY = end_mem; + + for (i = 0; i < PAGING_PAGES; i++) { + mem_map[i] = USED; + } + + i = MAP_NR(start_mem); + end_mem -= start_mem; + end_mem >>= 12; + while (end_mem--) { + mem_map[i++] = 0; + } + +} + diff --git a/mm/page.S b/mm/page.S new file mode 100644 index 0000000000000000000000000000000000000000..6f8d7a6d3bb4a33ea39124014f051ecec955fead --- /dev/null +++ b/mm/page.S @@ -0,0 +1,30 @@ +.globl page_fault + +page_fault: + xchgl %eax, (%esp) + pushl %ecx + pushl %edx + pushl %ds + pushl %es + pushl %fs + movl $0x10, %edx + movw %dx, %ds + movw %dx, %es + movw %dx, %fs + movl %cr2, %edx + pushl %edx + pushl %eax + testl $1, %eax + jne 1f + jmp 2f +1: call do_wp_page +2: addl $8, %esp + popl %fs + popl %es + popl %ds + popl %edx + popl %ecx + popl %eax + iret + + diff --git a/mm/swap.c b/mm/swap.c new file mode 100644 index 0000000000000000000000000000000000000000..187cb880451a5c5799bfed21f90e2ba35b26e280 --- /dev/null +++ b/mm/swap.c @@ -0,0 +1,27 @@ +#include + +unsigned long get_free_page() { + register unsigned long __res asm("ax") = 0; + +repeat: +__asm__("std ; repne ; scasb\n\t" + "jne 1f\n\t" + "movb $1,1(%%edi)\n\t" + "sall $12, %%ecx\n\t" + "addl %2, %%ecx\n\t" + "movl %%ecx, %%edx\n\t" + "movl $1024, %%ecx\n\t" + "leal 4092(%%edx), %%edi\n\t" + "xor %%eax, %%eax\n\t" + "rep; stosl;\n\t" + "movl %%edx,%%eax\n" + "1:" + :"=a"(__res) + :""(0), "i"(LOW_MEM), "c"(PAGING_PAGES), + "D"(mem_map+PAGING_PAGES-1) + :"dx"); + + if (__res >= HIGH_MEMORY) + goto repeat; + return __res; +} diff --git a/setup.S b/setup.S new file mode 100644 index 0000000000000000000000000000000000000000..33a28fc7532eed252363a6b868c51ee67e776754 --- /dev/null +++ b/setup.S @@ -0,0 +1,189 @@ +INITSEG = 0x9000 +SYSSEG = 0x1000 +SETUPSEG = 0x9020 + +.code16 +.text +.globl _start_setup + +_start_setup: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + + movw $setup_msg, %ax + movw %ax, %bp + movw $0x01301, %ax + movw $0x0c, %bx + movw $16, %cx + movb $3, %dh + movb $0, %dl + int $0x010 + + movw $INITSEG, %ax + movw %ax, %ds + movb $0x03, %ah + xor %bh, %bh + int $0x10 + movw %dx, (0) + movb $0x88, %ah + int $0x15 + movw %ax, (2) + + movb $0x0f, %ah + int $0x10 + movw %bx, (4) + movw %ax, (6) + movb $0x12, %ah + movb $0x10, %bl + int $0x10 + movw %ax, (8) + movw %bx, (10) + movw %cx, (12) + movw $0x5019, (14) + + movw $0x0000, %ax + movw %ax, %ds + ldsw (4 * 0x41), %si + movw $INITSEG, %ax + movw %ax, %es + movw $0x0080, %di + movw $0x10, %cx + rep + movsb + + /* get hd1 data */ + movw $0x0000, %ax + movw %ax, %ds + ldsw (4 * 0x46), %si + movw $INITSEG, %ax + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + rep + movsb + + movw $0x1500, %ax + movb $0x81, %dl + int $0x13 + jc no_disk1 + cmpb $3, %ah + je is_disk1 +no_disk1: + movw $INITSEG, %ax + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + movw $0x00, %ax + rep + stosb +is_disk1: + /* prepare for protection mode */ + cli + + movw $0x0000, %ax + cld +do_move: + movw %ax, %es + addw $0x1000, %ax + cmpw $0x9000, %ax + jz end_move + movw %ax, %ds + subw %di, %di + subw %si, %si + movw $0x8000, %cx + rep + movsw + jmp do_move + +end_move: + movw $0xb800, %ax + movw %ax, %gs + movb $0xf, %ah + movb $0x41, %al + movl $0x100, %edi + movw %ax, %gs:(%di) + + movw $SETUPSEG, %ax + movw %ax, %ds + lidt idt_48 + lgdt gdt_48 + + call empty_8042 + movb $0xD1, %al + outb %al, $0x64 + call empty_8042 + movb $0xDF, %al + outb %al, $0x60 + call empty_8042 + + movb $0x11, %al + outb %al, $0x20 + .word 0x00eb, 0x00eb + outb %al, $0xA0 + .word 0x00eb, 0x00eb + movb $0x20, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + movb $0x28, %al + outb %al, $0xA1 + .word 0x00eb, 0x00eb + movb $0x04, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + movb $0x02, %al + outb %al, $0xA1 + + .word 0x00eb, 0x00eb + movb $0x01, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + outb %al, $0xA1 + .word 0x00eb, 0x00eb + movb $0xff, %al + outb %al, $0x21 + .word 0x00eb, 0x00eb + outb %al, $0xA1 + + movl %cr0, %eax + xorb $1, %al + movl %eax, %cr0 + + .byte 0x66, 0xea + .long 0x0 + .word 0x8 + +empty_8042: + .word 0x00eb, 0x00eb + inb $0x64, %al + testb $2, %al + jnz empty_8042 + ret + +gdt: + .word 0,0,0,0 + + .word 0x07ff + .word 0x0000 + .word 0x9A00 + .word 0x00C0 + + .word 0x07ff + .word 0x0000 + .word 0x9200 + .word 0x00c0 + + .word 0xffff + .word 0x8000 + .word 0x920b + .word 0x00c0 +idt_48: + .word 0 + .word 0,0 +gdt_48: + .word 0x800 + .word 512+gdt, 0x9 + +setup_msg: + .ascii "setup is running" + diff --git a/tools/build.c b/tools/build.c new file mode 100644 index 0000000000000000000000000000000000000000..e321f9f64b88a93c0e413c15d7b065cfb464fa5b --- /dev/null +++ b/tools/build.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MINIX_HEADER 32 +#define GCC_HEADER 1024 + +#define SYS_SIZE 0x2000 + +#define DEFAULT_MAJOR_ROOT 3 +#define DEFAULT_MINOR_ROOT 6 + +#define SETUP_SECTS 4 + +#define STRINGIFY(x) #x + +#define ARG_LEN 4 + +void die(char * str) +{ + fprintf(stderr, "%s\n", str); + exit(1); +} + +void usage(void) +{ + die("Usage: build bootsect setup system [rootdev] [> image]"); +} + +int main(int argc, char **argv) +{ + int i, c, id; + char buf[1024]; + char major_root, minor_root; + struct stat sb; + + if ((argc != ARG_LEN) && (argc != ARG_LEN + 1)) + usage(); + + if (argc == ARG_LEN + 1) + { + if (strcmp(argv[ARG_LEN], "FLOPPY")) + { + if (stat(argv[ARG_LEN], &sb)) + { + perror(argv[ARG_LEN]); + die("Couldn't stat root device"); + } + major_root = sb.st_rdev & 0xff00; + minor_root = sb.st_rdev & 0x00ff; + } + else + { + major_root = 0; + minor_root = 0; + } + } + else + { + major_root = DEFAULT_MAJOR_ROOT; + minor_root = DEFAULT_MINOR_ROOT; + } + fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); + if ((major_root != 2) && (major_root != 3) && (major_root != 0)) + { + fprintf(stderr, "Illegal root device (major = %d)\n", major_root); + die("Bad root device --- major #"); + } + + for (i = 0; i < sizeof(buf); i++) + buf[i] = 0; + + if ((id = open(argv[1], O_RDONLY, 0)) < 0) + die("Unable to open 'boot'"); + + i = read(id, buf, sizeof(buf)); + fprintf(stderr, "Boot sector %d bytes.\n", i); + if (i != 512) + die("Boot block must be exactly 512 bytes"); + + buf[508] = (char) minor_root; + buf[509] = (char) major_root; + i = write(1, buf, 512); + if (i != 512) + die("Write call failed"); + close(id); + + if ((id = open(argv[2], O_RDONLY, 0)) < 0) + die("Unable to open 'setup'"); + + for (i = 0; (c = read(id, buf, sizeof(buf))) > 0; i += c) + if (write(1, buf, c) != c) + die("Write call failed"); + + close(id); + + if (i > SETUP_SECTS * 512) + die("Setup exceeds" STRINGIFY(SETUP_SECTS) " sectors - rewrite build/boot/setup"); + fprintf(stderr, "Setup is %d bytes.\n", i); + for (c = 0; c < sizeof(buf); c++) + buf[c] ='\0'; + while (i < SETUP_SECTS * 512) + { + c = SETUP_SECTS * 512 - i; + if (c > sizeof(buf)) + c = sizeof(buf); + + if (write(1, buf, c) != c) + die("Write call failed"); + i+=c; + } + + if ((id = open(argv[3], O_RDONLY, 0)) < 0) + die("Unable to open 'system'"); + for (i = 0; (c = read(id, buf, sizeof(buf))) > 0; i += c) + if (write(1, buf, c) != c) + die("Write call failed"); + close(id); + fprintf(stderr, "System is %d bytes.\n", i); + if (i > SYS_SIZE * 16) + die("System is too big"); + + return 0; +} +