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;
+}
+