From ea623dfa61141f3c5307f2f3a3bad1e949913ff8 Mon Sep 17 00:00:00 2001 From: Valentin Verdier Date: Fri, 17 Apr 2020 17:44:23 +0200 Subject: [PATCH] Commit initial --- LICENCE | 675 +++++++++++++++++++++++ boot/Makefile | 14 + boot/bootloader/Makefile | 8 + boot/bootloader/bootsect.asm | 173 ++++++ boot/kernloader/Makefile | 33 ++ boot/kernloader/drivers/AHCI.c | 1 + boot/kernloader/drivers/AHCI.h | 1 + boot/kernloader/drivers/ATA.c | 150 ++++++ boot/kernloader/drivers/ATA.h | 57 ++ boot/kernloader/drivers/ATAPI.c | 1 + boot/kernloader/drivers/ATAPI.h | 1 + boot/kernloader/io.asm | 77 +++ boot/kernloader/kernldr.h | 209 ++++++++ boot/kernloader/kernldr_init.asm | 77 +++ boot/kernloader/kernldr_main.c | 268 +++++++++ boot/kernloader/kernldr_print.c | 187 +++++++ boot/kernloader/kernldr_utils.c | 92 ++++ boot/kernloader/startup.asm | 197 +++++++ boot/kernloader/types.h | 31 ++ kernel/Makefile | 39 ++ kernel/include/args.h | 50 ++ kernel/include/asm_x86.h | 51 ++ kernel/include/elf_loader.h | 32 ++ kernel/include/interrupt.h | 99 ++++ kernel/include/ipc.h | 31 ++ kernel/include/memory.h | 223 ++++++++ kernel/include/print.h | 58 ++ kernel/include/process.h | 126 +++++ kernel/include/signal.h | 40 ++ kernel/include/types.h | 31 ++ kernel/include/utils.h | 57 ++ kernel/src/asm/io.asm | 77 +++ kernel/src/asm/isr.asm | 94 ++++ kernel/src/asm/sched.asm | 88 +++ kernel/src/asm/syslib.asm | 133 +++++ kernel/src/elf_loader.c | 222 ++++++++ kernel/src/interrupt.c | 165 ++++++ kernel/src/ipc.c | 55 ++ kernel/src/main.c | 77 +++ kernel/src/memory.c | 790 +++++++++++++++++++++++++++ kernel/src/print.c | 129 +++++ kernel/src/process.c | 408 ++++++++++++++ kernel/src/scheduler.c | 173 ++++++ kernel/src/signal.c | 79 +++ kernel/src/systemCall.c | 72 +++ kernel/src/utils.c | 321 +++++++++++ test/bochsrc | 45 ++ test/bochsrc_model | 894 +++++++++++++++++++++++++++++++ test/init/Makefile | 19 + test/init/init.c | 12 + test/ndmt | 128 +++++ test/tools/readpt.c | 84 +++ test/tools/w_kernLdr.c | 77 +++ test/tools/w_mbr.c | 66 +++ 54 files changed, 7297 insertions(+) create mode 100644 LICENCE create mode 100644 boot/Makefile create mode 100644 boot/bootloader/Makefile create mode 100644 boot/bootloader/bootsect.asm create mode 100644 boot/kernloader/Makefile create mode 100644 boot/kernloader/drivers/AHCI.c create mode 100644 boot/kernloader/drivers/AHCI.h create mode 100644 boot/kernloader/drivers/ATA.c create mode 100644 boot/kernloader/drivers/ATA.h create mode 100644 boot/kernloader/drivers/ATAPI.c create mode 100644 boot/kernloader/drivers/ATAPI.h create mode 100644 boot/kernloader/io.asm create mode 100644 boot/kernloader/kernldr.h create mode 100644 boot/kernloader/kernldr_init.asm create mode 100644 boot/kernloader/kernldr_main.c create mode 100644 boot/kernloader/kernldr_print.c create mode 100644 boot/kernloader/kernldr_utils.c create mode 100644 boot/kernloader/startup.asm create mode 100644 boot/kernloader/types.h create mode 100644 kernel/Makefile create mode 100644 kernel/include/args.h create mode 100644 kernel/include/asm_x86.h create mode 100644 kernel/include/elf_loader.h create mode 100644 kernel/include/interrupt.h create mode 100644 kernel/include/ipc.h create mode 100644 kernel/include/memory.h create mode 100644 kernel/include/print.h create mode 100644 kernel/include/process.h create mode 100644 kernel/include/signal.h create mode 100644 kernel/include/types.h create mode 100644 kernel/include/utils.h create mode 100644 kernel/src/asm/io.asm create mode 100644 kernel/src/asm/isr.asm create mode 100644 kernel/src/asm/sched.asm create mode 100644 kernel/src/asm/syslib.asm create mode 100644 kernel/src/elf_loader.c create mode 100644 kernel/src/interrupt.c create mode 100644 kernel/src/ipc.c create mode 100644 kernel/src/main.c create mode 100644 kernel/src/memory.c create mode 100644 kernel/src/print.c create mode 100644 kernel/src/process.c create mode 100644 kernel/src/scheduler.c create mode 100644 kernel/src/signal.c create mode 100644 kernel/src/systemCall.c create mode 100644 kernel/src/utils.c create mode 100644 test/bochsrc create mode 100644 test/bochsrc_model create mode 100644 test/init/Makefile create mode 100644 test/init/init.c create mode 100755 test/ndmt create mode 100644 test/tools/readpt.c create mode 100644 test/tools/w_kernLdr.c create mode 100644 test/tools/w_mbr.c diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..10926e8 --- /dev/null +++ b/LICENCE @@ -0,0 +1,675 @@ + 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/boot/Makefile b/boot/Makefile new file mode 100644 index 0000000..e071c21 --- /dev/null +++ b/boot/Makefile @@ -0,0 +1,14 @@ +.PHONY: bin clean +all: bin + +bin: + make -C bootloader/ + make -C kernloader/ + -mkdir bin + mv bootloader/bootsect.bin bin/ + mv kernloader/NOS-kernldr.bin bin/ + +clean: + make -C bootloader/ clean + make -C kernloader/ clean + -rm -rf bin/ diff --git a/boot/bootloader/Makefile b/boot/bootloader/Makefile new file mode 100644 index 0000000..e1eb81c --- /dev/null +++ b/boot/bootloader/Makefile @@ -0,0 +1,8 @@ +.PHONY: clean +all: bootsect.bin + +bootsect.bin: bootsect.asm + nasm -f bin -o $@ $^ + +clean: + -rm -f bootsect.bin diff --git a/boot/bootloader/bootsect.asm b/boot/bootloader/bootsect.asm new file mode 100644 index 0000000..48a04db --- /dev/null +++ b/boot/bootloader/bootsect.asm @@ -0,0 +1,173 @@ +; bootsect.asm - This file is a part of NutsOS + +; NutsOS +; Copyright (C) 2013 Free Software Foundation, Inc. + +; NutsOS 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. + +; NutsOS 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 NutsOS; If not, see . + +; Valentin Verdier + + + +; Code placé dans le MBR du disque + +; #################################### +; BootLoader principal +; #################################### + +; Le code est copié par le BIOS à l'adresse 0x7C00, soit à la base du segment 0x07C0 +; 0x0:0x7C00 <=> 0x07C0:0000 0x07C0 x 0x10 = 0x7C00 +; adresse physique = segment x 16 + offset + +%define BOOT_SEG 0x07C0 +%define KERN_LDR_SEG 0x07E0 + +%define KERN_LDR_LBA_ADDR 1 + +[BITS 16] +[ORG 0] ; Par rapport au segment 0x07C0 + +boot: + ; On fait pointer les registres de segments sur le segment 0x07C0 + ; On ne fait rien pour CS car le bios s'en ait déjà occupé + mov ax, BOOT_SEG + mov ds, ax + + mov ax, 0x9F00 ; On définit l'adresse de base de la pile à la base du segment 0x9F00, soit à l'adresse 0x9F000 + mov ss, ax + + mov sp, 0xFFF ; On définit le pointeur de pile à l'offset 0xFFFF ce qui correspond à l'adresse 0x9FFFF + + mov [bootdisk], dl ; On sauvegarde le numéro de l'unité de disque utilisée par le BIOS + + xor ax, ax ; int 0x13 fonction 0x00 + int 0x13 + + call load_kern_ldr + + jmp KERN_LDR_SEG:0x0000 ; On saute vers le code de kernLdr + + +; Fonction load_kern_ldr +; Charge kernLdr qui commence au 30ème secteur du disque +load_kern_ldr: + push ax + push ebx + push dx + push di + + mov ax, 63 ; On charge 63 secteurs + mov dx, KERN_LDR_SEG + xor di, di + mov ebx, KERN_LDR_LBA_ADDR + + call build_DAPS + call read_sector + + pop di + pop dx + pop ebx + pop ax + ret + +; Fonction print +; Params : pointeur sur str -> ds:si +print: + push ax + push bx + +.top: + lodsb + cmp al, 0 + jz .end + + mov ah, 0x0E ; int 0x10 fonction 0x0E + mov bx, 0x07 ; attribut du caractère + int 0x10 + jmp .top + +.end: + pop bx + pop ax + ret + + +read_sector: + push ax + push dx + push si + + xor ax, ax + add ax, 0 ; On met le flag de retenue à 0 + mov si, DAPS + mov ah, 0x42 + mov dl, [bootdisk] + int 0x13 + jc .error + jmp .no_error + +.error: + mov si, error_int13h + call print + call stop + +.no_error: + pop si + pop dx + pop ax + ret + + +; Fonction build_DAPS +; Params: Nombre de secteur -> ax, Adresse LBA -> ebx, destination -> dx:di +build_DAPS: + mov [DAPS + 2], ax ; Nombre de secteurs + + mov [DAPS + 4], di ; Offset du segment de destination + mov [DAPS + 6], dx ; Segment de destination + + ; adresse LBA + mov [DAPS + 8], ebx + xor ax, ax + mov [DAPS + 12], ax + mov [DAPS + 14], ax + ret + +; Fonction Error +stop: +.loop: + hlt + jmp .loop + +; Variables +; ############################################ + +DAPS: ; Disk Address Packet Structure + db 16 ; Taille de la structure + db 0 ; Toujours à 0 + + dw 0 ; Nombre de secteurs à transfèrer + + dw 0 ; Offset du segment de buffer + dw 0 ; segment de buffer + + dd 0 ; Adresse LBA de début + dd 0 ; Partie haute de l'adresse LBA (pour LBA 48 bits) non utilisée ici + +error_int13h: db "BIOS 13H extension error !", 13, 10, 0 + +boot_disk: db 0 +; ############################################ + +times 446-($-$$) db 144 diff --git a/boot/kernloader/Makefile b/boot/kernloader/Makefile new file mode 100644 index 0000000..e0e23a3 --- /dev/null +++ b/boot/kernloader/Makefile @@ -0,0 +1,33 @@ +.PHONY: clean +CC=gcc +CFLAGS= -m32 -march=i486 -fno-stack-protector -fno-zero-initialized-in-bss + +kernldr_obj_core=kernldr_init.o \ +kernldr_main.o \ +kernldr_print.o \ +kernldr_utils.o \ +asm_utils.o + +kernldr_obj_drivers=drivers/ATA.o + +all: NOS-kernldr.bin + +NOS-kernldr.bin: kernldr_1 kernldr_2 + dd if=kernldr_1 of=$@ bs=512 count=1 + dd if=kernldr_2 of=$@ bs=512 seek=1 + rm kernldr_1 kernldr_2 + +kernldr_1: startup.asm + nasm -f bin -o $@ $^ + +kernldr_2: $(kernldr_obj_core) $(kernldr_obj_drivers) + ld -melf_i386 --oformat=binary --Ttext=8000 --entry=kernldr_init $^ -o $@ + +clean: + -rm -f NOS-kernldr.bin $(kernldr_obj_core) $(kernldr_obj_drivers) + +%.o:%.c + $(CC) $(CFLAGS) -c $^ -o $@ + +%.o:%.asm + nasm -f elf -o $@ $^ diff --git a/boot/kernloader/drivers/AHCI.c b/boot/kernloader/drivers/AHCI.c new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/boot/kernloader/drivers/AHCI.c @@ -0,0 +1 @@ + diff --git a/boot/kernloader/drivers/AHCI.h b/boot/kernloader/drivers/AHCI.h new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/boot/kernloader/drivers/AHCI.h @@ -0,0 +1 @@ + diff --git a/boot/kernloader/drivers/ATA.c b/boot/kernloader/drivers/ATA.c new file mode 100644 index 0000000..2ec8176 --- /dev/null +++ b/boot/kernloader/drivers/ATA.c @@ -0,0 +1,150 @@ +/* ATA.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "../types.h" +#include "../kernLdr.h" + +#include "ATA.h" + +int ATA_getDevice(unsigned int ataNumber, unsigned int drive, T_ATA_device* dev) { + ataNumber &= 0x3; + drive &= 0x1; + + print("-> Device : ATA %d ", DEFAULT_COLOR, ataNumber); + switch(ataNumber) { + case 0: + dev->ata_port = ATA_0_PORT; + dev->ata_ctrl_port = ATA_0_CTRL_PORT; + break; + + case 1: + dev->ata_port = ATA_1_PORT; + dev->ata_ctrl_port = ATA_1_CTRL_PORT; + break; + + case 2: + dev->ata_port = ATA_2_PORT; + dev->ata_ctrl_port = ATA_2_CTRL_PORT; + break; + + case 3: + dev->ata_port = ATA_3_PORT; + dev->ata_ctrl_port = ATA_3_CTRL_PORT; + break; + } + + if(drive) { + print("Slave drive\n", DEFAULT_COLOR); + dev->drive = ATA_SLAVE; + } else { + print("Master drive\n", DEFAULT_COLOR); + dev->drive = ATA_MASTER; + } + + /* On vérifie si les ports I/O sont reliés à un contrôleur */ + T_byte testByte; + _out(dev->ata_port + 2, 0x45); + _in(dev->ata_port + 2, &testByte); + + if(testByte == 0x45) { /* Le contrôleur éxiste */ + T_byte a, b, status; + + /* On se prépare à utiliser la commande IDENTIFY pour connaitre le type de disque ATA */ + _out(dev->ata_port + 6, ATA_CHS_MODE | dev->drive); /* On selectionne le disque */ + delay(1000); + + _out(dev->ata_port + 2, 0); + _out(dev->ata_port + 3, 0); + _out(dev->ata_port + 4, 0); + _out(dev->ata_port + 5, 0); + + _out(dev->ata_port + 7, ATA_CMD_IDENTIFY); /* envoie de la commande */ + + _in(dev->ata_port + 7, &status); + + if(status == 0) { /* Si le status est à 0, il n'y à pas de disque */ + print("-> ERROR : Drive doesn't exist !\n", DEFAULT_COLOR); + return 0; + } else { /* Sinon on attend que le disque soit prêt */ + while(status & 0x80) { + _in(dev->ata_port + 7, &status); + } + } + + /* On récupère les octets de signature */ + _in(dev->ata_port + 4, &a); + _in(dev->ata_port + 5, &b); + + if((a == 0) && (b == 0)) { /* Disque dur ATA */ + while(!(status & 0x08)) { /* On attend que le disque soit prêt pour la lecture des données d'identification */ + _in(dev->ata_port + 7, &status); + } + + unsigned int i; + T_word trash; + for(i = 0; i < 256; i++) { /* Pas besoin des info d'identification, mais on les transfert pour que le contrôleur termine la commande normalement */ + _inw(dev->ata_port, &trash); + } + + return 1; + } else { + print("-> ERROR : Drive is not ATA !\n", DEFAULT_COLOR); + } + } else { + print("-> ERROR : Controller doesn't exist !\n", DEFAULT_COLOR); + } + return 0; +} + + +void ATA_read(T_ATA_device dev, T_dword baseLBA, T_byte sectorCount, void* baddr) { + T_byte* buffer = baddr; + T_byte status = 0; + unsigned int i, j; + T_word word; + + _out(dev.ata_port + 1, 0); /* Octet nul */ + _out(dev.ata_port + 2, sectorCount); + _out(dev.ata_port + 3, (T_byte) (baseLBA & 0xFF)); /* 8 bits de poids faible de l'adresse LBA */ + _out(dev.ata_port + 4, (T_byte) ((baseLBA >> 8) & 0xFF)); + _out(dev.ata_port + 5, (T_byte) ((baseLBA >> 16) & 0xFF)); + + _out(dev.ata_port + 6, ATA_LBA_MODE | dev.drive | ((baseLBA >> 24) & 0x0F)); + for(i = 0; i < 4; i++) { + _in(dev.ata_port + 7, &status); + } + + _out(dev.ata_port + 7, ATA_CMD_READ); + + /* On attend que le contrôleur soit prêt */ + + for(i = 0; i < sectorCount; i++) { + do { + _in(dev.ata_port + 7, &status); + }while((status & 0x80) || !(status & 0x08)); + + for(j = 0; j < 256; j++) { + _inw(dev.ata_port, &word); + buffer[(i * 512) + (j * 2)] = (T_byte) (word & 0xFF); + buffer[(i * 512) + (j * 2) + 1] = (T_byte) ((word >> 8) & 0xFF); + } + } +} diff --git a/boot/kernloader/drivers/ATA.h b/boot/kernloader/drivers/ATA.h new file mode 100644 index 0000000..ec80ca6 --- /dev/null +++ b/boot/kernloader/drivers/ATA.h @@ -0,0 +1,57 @@ +/* ATA.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef NOS_ATA_H +#define NOS_ATA_H + +#include "../types.h" + +#define ATA_LBA_MODE 0xE0 +#define ATA_CHS_MODE 0xA0 + +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x10 + +#define ATA_0_PORT 0x1F0 +#define ATA_1_PORT 0x170 +#define ATA_2_PORT 0x1E8 +#define ATA_3_PORT 0x168 + +#define ATA_0_CTRL_PORT 0x3F6 +#define ATA_1_CTRL_PORT 0x376 +#define ATA_2_CTRL_PORT 0x3E6 +#define ATA_3_CTRL_PORT 0x366 + +#define ATA_CMD_READ 0x20 +#define ATA_CMD_IDENTIFY 0xEC + +typedef struct { + T_word ata_port; + T_word ata_ctrl_port; + T_byte drive; +} T_ATA_device; + + +int ata_select_drive(unsigned int, unsigned int, T_ATA_device*); +void ata_read(T_ATA_device, T_dword, T_byte, void*); + +#endif diff --git a/boot/kernloader/drivers/ATAPI.c b/boot/kernloader/drivers/ATAPI.c new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/boot/kernloader/drivers/ATAPI.c @@ -0,0 +1 @@ + diff --git a/boot/kernloader/drivers/ATAPI.h b/boot/kernloader/drivers/ATAPI.h new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/boot/kernloader/drivers/ATAPI.h @@ -0,0 +1 @@ + diff --git a/boot/kernloader/io.asm b/boot/kernloader/io.asm new file mode 100644 index 0000000..a3a25c9 --- /dev/null +++ b/boot/kernloader/io.asm @@ -0,0 +1,77 @@ +; io_port.asm - This file is a part of NutsOS + +; NutsOS +; Copyright (C) 2013 Free Software Foundation, Inc. + +; NutsOS 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. + +; NutsOS 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 NutsOS; If not, see . + +; Valentin Verdier + +[BITS 32] +[SECTION .text] + +global _out, _in, _outw, _inw, _outdw, _indw + +_out: + push eax + push edx + mov dx, [esp+12] + mov al, [esp+16] + out dx, al + pop edx + pop eax + ret + +_in: + push edx + xor eax, eax + mov dx, [esp+8] + in al, dx + pop edx + ret + +_outw: + push eax + push edx + mov dx, [esp+12] + mov ax, [esp+16] + out dx, ax + pop edx + pop eax + ret + +_inw: + push edx + xor eax, eax + mov dx, [esp+8] + in ax, dx + pop edx + ret + +_outdw: + push eax + push edx + mov dx, [esp+12] + mov eax, [esp+16] + out dx, eax + pop edx + pop eax + ret + +_indw: + push edx + mov dx, [esp+8] + in eax, dx + pop edx + ret diff --git a/boot/kernloader/kernldr.h b/boot/kernloader/kernldr.h new file mode 100644 index 0000000..785f5a3 --- /dev/null +++ b/boot/kernloader/kernldr.h @@ -0,0 +1,209 @@ +/* kernLdr.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef NOS_KERNLDR_H +#define NOS_KERNLDR_H + +#include +#include "types.h" +#include "drivers/ATA.h" + + +/* Structure de passage d'arguments */ +typedef struct { + T_dword low_addr; + T_dword high_addr; + T_dword low_size; + T_dword high_size; + T_dword type; + T_dword unused; +}__attribute__((packed)) T_mmap_entry; + +#define BOOT_ARGS_ADDR 0x1000 + +typedef struct { + T_byte cursor_x; + T_byte cursor_y; + T_byte mmap_entry_count; + T_mmap_entry mmap[30]; /* Taille fixée arbitrairement */ +}__attribute__((packed)) T_boot_args; + +#define KERNEL_ARGS_ADDR 0x1400 + +typedef struct { + T_byte cursor_x; + T_byte cursor_x; + T_dword pmem_size; + T_byte mmap_entry_count; + T_dword init_proc_addr; + T_dword init_proc_size; + T_mmap_entry* mmap; +}__attribute__((packed)) T_kernel_args; + +/* ############################## */ + + +/* ######### Affichage ########## */ +#define VIDEO_ADDR 0xB8000 +#define VIDEO_SIZE 0xFA0 +#define VIDEO_END_OFFSET 0xB8FA0 +#define DEFAULT_COLOR 0x0F + +char pos_x; +char pos_y; +int enable_cursor; + +void scrollup(int); +void write_char(char, char); +void print(char*, ...); +void clear(); +void show_cursor(); +void hide_cursor(); +void move_cursor(char, char); +/* ############################## */ + + +/* ####### Fonctions I/O ######## */ +void _out(T_word, T_byte); +T_byte _in(T_word); +void _outw(T_word, T_word); +T_word _inw(T_word); +void _outdw(T_word, T_dword); +T_dword _indw(T_word); +/* ############################## */ + + +/* ########### Divers ########### */ +void memcopy(char*, char*, unsigned int); +int strcmp(char*, char*); +void int_to_str(unsigned int, char*, int); +unsigned int expo(int, int); +void delay(unsigned int); +/* ############################## */ + + +/* ###### Structure MBR et Table de partition */ + +#define PARTITION_BOOT_SIGN 0x80 +#define VFAT32_PARTITION_ID 0x07 + +typedef struct { + T_byte bootsign; + T_byte chs_start_head; + T_byte chs_start_sector:6; + T_word chs_start_cylinder:10; + T_byte fs_id; + T_byte chs_end_head; + T_byte chs_end_sector:6; + T_word chs_end_cylinder:10; + T_dword lba_start_sector; + T_dword lba_sector_count; +}__attribute__((packed)) T_partition_entry; + +#define MBR_BOOT_SIGN 0xAA55 + +typedef struct { + T_byte bootcode[446]; + T_partition_entry pt[4]; + T_word bootsign; +}__attribute__((packed)) T_MBR; + +/* ########################################## */ + +/* ###### Fat32 structure ####### */ +typedef struct { + T_byte jumpcode[3]; + char OEM_identifier[8]; + T_word byte_per_sect; + T_byte sect_per_cluster; + T_word reserved_sect_count; + T_byte fat_count; + T_word unused_1; + T_word total_sect_count_16; + T_byte media_desc_type; + T_word unused_2; + T_word sect_per_track; + T_word head_count; + T_dword hidden_sect_lba; + T_dword total_sect_count_32; + T_dword sect_per_fat; + T_word fat_info; + T_word fat_ver; + T_dword rootdir_first_cluster; + T_word fs_info_sect; + T_word dbr_cpy_sect; + T_byte reserved[12]; + T_byte bios_disk_id; + T_byte reserved_NT; /* Windows NT flags */ + T_byte sign; + T_dword serial_num; + char label[11]; + char identifier_str[8]; + T_byte bootcode[420]; + T_word bootsign; +}__attribute__((packed)) T_FAT32_dbr; + +#define FAT32_DIR_ENTRY_SIZE 32 + +typedef struct { + T_byte entry_num; + char char_part1[10]; + T_byte attribute; + T_byte lfn_entry_type; + T_byte checksum; + char char_part2[12]; + T_word null; + char char_part3[4]; +}__attribute__((packed)) T_FAT32_lfn_entry; + +typedef struct { + char filename[8]; + char extention[3]; + T_byte attribute; + T_byte reserved; /* Windows NT */ + T_byte creation_time_1; + T_word creation_time_2; + T_word creation_date; + T_word last_acces; + T_word high_first_cluster; + T_word modif_time; + T_word modif_date; + T_word low_first_cluster; + T_dword file_size; +}__attribute__((packed)) T_FAT32_std_entry; + +typedef struct { + T_ATA_device device; + T_FAT32_dbr dbr; + + /* Buffer de lecture */ + unsigned int loaded_fat_sect; + T_dword fat_sect_buf[128]; /* 512 octets */ + T_dword* dir_cluster_buf; + + /* Adresses LBA des structures sur le disque */ + T_dword LBA_dbr; + T_dword LBA_fat; + T_dword LBA_first_sata_sect; /* cluster 2 */ +} T_FAT32_partition; + +#endif diff --git a/boot/kernloader/kernldr_init.asm b/boot/kernloader/kernldr_init.asm new file mode 100644 index 0000000..8678e12 --- /dev/null +++ b/boot/kernloader/kernldr_init.asm @@ -0,0 +1,77 @@ +; kernLdr_init.asm - This file is a part of NutsOS + +; NutsOS +; Copyright (C) 2013 Free Software Foundation, Inc. + +; NutsOS 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. + +; NutsOS 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 NutsOS; If not, see . + +; Valentin Verdier + +[BITS 32] +[SECTION .text] + +global kernLdr_init +extern kernLdr_main + +kernldr_init: + ; On initialise tous les segments de données pour le mode protégé + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + ; Segment de pile + mov ax, 0x18 + mov ss, ax + mov esp, 0xA0000 ; Pile à 0xA0000 + push eax + + ; on vérifie que la ligne a20 est activée + call check_a20_line + cmp eax, 0 + je .next ; Si activée, on passe + call enable_a20_line ; Sinon on l'active +.next: + + ; On appel le fonction principale qui : + ; - calcul la taille de la mémoire utilisable à partir de la liste de plage mémoire communiquée par kernldr_1 + ; - charge la partition FAT32 définit + ; - charge KERNEL32 à l'adresse 0x100000, et init à l'adresse 0x28000 depuis le répertoire /boot + ; - construit la structure de passage d'argument + call kernldr_main + + ; On saute vers le kernel + mov esp, 0xA0000 + jmp 0x08:0x100000 + + +; Retourne 0xFFFFFFFF si déactivée, 0 si activée +check_a20_line: + mov dword [0x500], 0 + mov dword [0x100500], 0xFFFFFFFF + mov eax, [0x500] + ret + +enable_a20_line: + push eax + in al, 0x92 + test al, 0x02 + jnz .end + or al, 0x02 + and al, 0xFE + out 0x92, al +.end: + pop eax + ret diff --git a/boot/kernloader/kernldr_main.c b/boot/kernloader/kernldr_main.c new file mode 100644 index 0000000..58820dc --- /dev/null +++ b/boot/kernloader/kernldr_main.c @@ -0,0 +1,268 @@ +/* kernLdr_main.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "types.h" +#include "kernLdr.h" +#include "drivers/ATA.h" + +static void detectMemory(T_bootArgs* bargs, T_kernelArgs* kargs) +{ + T_dword* test1 = (T_dword*) 0x500; + T_dword* test2 = (T_dword*) 0x100500; + *test1 = 0; + *test2 = 0xFFFFFFFF; + if(*test1 == 0) { + print("-> A20 line enabled\n", DEFAULT_COLOR); + } else { + print("-> A20 line disabled\n", DEFAULT_COLOR); + asm("hlt"); + } + + unsigned int i; + kargs->phyMemSize = 0; + for(i = 0; i < bargs->memListEntryCount; i++) { + //print("-> (0x%x - 0x%x) type=%d\n", DEFAULT_COLOR, bargs->memMap[i].baseAddr_1, bargs->memMap[i].baseAddr_1 + bargs->memMap[i].size_1, bargs->memMap[i].type); + if(bargs->memMap[i].type == 1) { + kargs->phyMemSize += bargs->memMap[i].size_1; + } + } + print("-> Physical memory size : %d Ko\n", DEFAULT_COLOR, (kargs->phyMemSize / 1024)); +} + +static int getPartition(unsigned int partNumber, T_ATA_device device, T_FAT32_partition* part) +{ + partNumber &= 0x3; + print("-> Partition : %d\n", DEFAULT_COLOR, partNumber); + + /* On récupère le MBR */ + T_mbr* mbr = (T_mbr*) 0x15000; + ATA_read(device, 0, 1, mbr); + if(mbr->partitionTable[partNumber].fileSytemID == VFAT32_PARTITION_ID) { + part->device = device; + part->LBA_dbr = mbr->partitionTable[partNumber].startingLBA; + // On charge le Dos Boot Record de la partition + ATA_read(part->device, part->LBA_dbr, 1, (void*) &part->dbr); + + // On calcul l'adresse de la FAT ainsi que l'adresse du premier cluster + if(part->dbr.fatInfo >> 7) { + unsigned int activeFAT = part->dbr.fatInfo & 0x0F; + part->LBA_fileAllocationTable = part->LBA_dbr + part->dbr.reservedSectors + (activeFAT * part->dbr.sectorsPerFat); + } else { + part->LBA_fileAllocationTable = part->LBA_dbr + part->dbr.reservedSectors; + } + ATA_read(part->device, part->LBA_fileAllocationTable, 1, part->fatSectorBuffer); + part->LBA_firstDataSector = part->LBA_dbr + part->dbr.reservedSectors + (part->dbr.fatNumber * part->dbr.sectorsPerFat); + + return 1; + } else { + print("-> ERROR : The partition is not VFAT32 type\n", DEFAULT_COLOR); + return 0; + } +} + +static T_dword getFat32ClusterLBA(unsigned int clusterNum, T_FAT32_partition* part) { + return ((clusterNum - 2) * part->dbr.sectorsPerCluster) + part->LBA_firstDataSector; +} + +static unsigned int getFat32NextClusterNum(unsigned int clusterNum, T_FAT32_partition* part) { + unsigned int nextCluster; + unsigned int sector = part->LBA_fileAllocationTable + ((clusterNum * 4) / 512); + + if(sector != part->loadedFatSector) { + ATA_read(part->device, sector, 1, part->fatSectorBuffer); + part->loadedFatSector = sector; + } + + nextCluster = part->fatSectorBuffer[((clusterNum * 4) % 512) / 4]; + + if(nextCluster >= 0x0FFFFFF8) { + return 0; + } else if(nextCluster == 0x0FFFFFF7) { + print("-> ERROR : A BAD CLUSTER WAS FOUND (PREVIOUS CLUSTER = %d)\n", DEFAULT_COLOR, clusterNum); + asm("hlt"); + } else { + return nextCluster; + } +} + +static unsigned int loadFile(char *target, T_dword destAddr, T_FAT32_partition* part) +{ + print("-> Loading '%s'\n", DEFAULT_COLOR, target); + unsigned int currentCluster = part->dbr.rootDirFirstCluster; /* Numéro d'un cluster du répertoire courant */ + T_FAT32_stdEntry* entry = (T_FAT32_stdEntry*) part->dirClusterBuffer; /* Buffer utilisé pour stocker un cluster du répertoire courant */ + ATA_read(part->device, getFat32ClusterLBA(currentCluster, part), part->dbr.sectorsPerCluster, entry); + + unsigned int i = 0; + while(target[i] != 0) { + char entity[256]; + unsigned int j; + char isDirectory = 0, isFile = 0; + + for(j = 0; target[i] != 0; i++, j++) { + if(j >= 256) { + print("-> ERROR : INVALID TARGET '%s'\n", DEFAULT_COLOR, target); + return 0; + } else if(target[i] == '/') { + isDirectory = 1; + i++; + break; + } else { + entity[j] = target[i]; + } + } + /* On ferme la chaine de caractères */ + entity[j] = '\0'; + + if(!isDirectory) { + isFile = 1; + } + + /* Chargement */ + if(entity[0] != '\0') { + unsigned int lfnAvailable = 0; + unsigned int stopLoop = 0; + while(currentCluster && (!stopLoop)) { + unsigned int k; + char *entityLFN = (char*) 0x4200; + + for(k = 0; k < ((part->dbr.sectorsPerCluster * 512) / FAT32_DIR_ENTRY_SIZE); k++) { + if((entry[k].fileName[0] != 0) && (entry[k].fileName[0] != 0xE5)) { /* Si l'entrée est valide */ + if(entry[k].attribute == 0x0F) { /* Si on trouve une entrée LFN */ + T_FAT32_lfnEntry* lfnEntry = (T_FAT32_lfnEntry*) &entry[k]; + lfnAvailable = 1; + + /* On récupère les parties de nom */ + unsigned int l; + unsigned int offset = ((lfnEntry->entryNum & 0x3F) - 1) * 13; /* offset de la section du nom dans la chaine finale */ + + for(l = 0; l < 13; l++) { + if(l < 5) { + entityLFN[offset + l] = lfnEntry->char_part1[l * 2]; + } else if(l < 11) { + entityLFN[offset + l] = lfnEntry->char_part2[(l - 5) * 2]; + } else if(l < 13) { + entityLFN[offset + l] = lfnEntry->char_part3[(l - 11) * 2]; + } + } + } else { /* Sinon c'est une entrée standard */ + char *entityNameCmp; + + if(lfnAvailable) { + entityNameCmp = entityLFN; + lfnAvailable = 0; + } else { + entityNameCmp = (char*) 0x4400; + unsigned int l, m; + + for(l = 0; l < 8 && entry[k].fileName[l] != ' '; l++) { + entityNameCmp[l] = entry[k].fileName[l]; + } + entityNameCmp[l] = '.'; + for(m = 0; m < 3 && entry[k].extention[m] != ' '; m++, l++) { + entityNameCmp[l] = entry[k].extention[m]; + } + entityNameCmp[l] = '\0'; + } + + if(isDirectory) { + if((strcmp(entity, entityNameCmp)) && (entry[k].attribute & 0x10)) { + currentCluster = ((T_dword) entry[k].firstCluster_high << 16) | entry[k].firstCluster_low; + ATA_read(part->device, getFat32ClusterLBA(currentCluster, part), part->dbr.sectorsPerCluster, part->dirClusterBuffer); + stopLoop = 1; + break; + } + } else if(isFile) { + if((strcmp(entity, entityNameCmp)) && (entry[k].attribute & 0x20)) { + unsigned int cluster = ((T_dword) entry[k].firstCluster_high << 16) | entry[k].firstCluster_low; + unsigned int size = 0; + while(cluster) { + ATA_read(part->device, getFat32ClusterLBA(cluster, part), part->dbr.sectorsPerCluster, (void*) destAddr); + destAddr += (part->dbr.sectorsPerCluster * 512); + cluster = getFat32NextClusterNum(cluster, part); + size += (part->dbr.sectorsPerCluster * 512); + } + return size; + } + } + } + } + } + if(!stopLoop) { + currentCluster = getFat32NextClusterNum(currentCluster, part); + } + } + if(!stopLoop) { + print("-> ERROR : UNABLE TO FIND '%s' FOR '%s'\n", DEFAULT_COLOR, entity, target); + return 0; + } + } + } +} + +void kernLdr_main() +{ + /* On définit les adresse des structure en mémoire */ + T_bootArgs* bootArgs = (T_bootArgs*) BOOT_ARGS_ADDR; + T_kernelArgs* kernelArgs = (T_kernelArgs*) KERNEL_ARGS_ADDR; + + /* Position du curseur */ + posX = bootArgs->cursor_X; + posY = bootArgs->cursor_Y; + + showCursor(); + print("Welcome to NutsOS KernelLoader v1.0.0\n", DEFAULT_COLOR); + + /* On affiche la memory map */ + print("[MEMORY DETECTION]\n", 0x02); + detectMemory(bootArgs, kernelArgs); + + T_ATA_device bootDevice; + T_FAT32_partition bootPartition; + bootPartition.loadedFatSector = 0; + bootPartition.dirClusterBuffer = (T_dword*) 0x2000; + + print("[FILES LOADING]\n", 0x02); + if(!ATA_getDevice(0, 0, &bootDevice)) { + asm("hlt"); + } + if(!getPartition(0, bootDevice, &bootPartition)) { + asm("hlt"); + } + if(loadFile("/boot/NOS-kernel32.bin", 0x100000, &bootPartition)) { /* On charge KERNEL32 à la bonne adresse et on passe les arguments */ + kernelArgs->initProcessAddr = 0x28000; + kernelArgs->initProcessSize = loadFile("/boot/init", kernelArgs->initProcessAddr, &bootPartition); + + if(!kernelArgs->initProcessSize) { + asm("hlt"); + } else if(kernelArgs->initProcessSize > 819200) { + print("ERROR : INIT PROCESS IS TOO LARGE\n", DEFAULT_COLOR); + asm("hlt"); + } else { + print("[BOOTING]\n", 0x02); + kernelArgs->cursor_X = posX; + kernelArgs->cursor_Y = posY; + kernelArgs->memListEntryCount = bootArgs->memListEntryCount; + kernelArgs->memMap = bootArgs->memMap; + } + } else { + asm("hlt"); + } +} diff --git a/boot/kernloader/kernldr_print.c b/boot/kernloader/kernldr_print.c new file mode 100644 index 0000000..be87cd4 --- /dev/null +++ b/boot/kernloader/kernldr_print.c @@ -0,0 +1,187 @@ +/* kernLdr_print.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "kernLdr.h" + +#define DEFAULT_COLOR 0x0F + +char color = (char) DEFAULT_COLOR; + +void scrollup(int lines) { + char* vid; + char* offset; + + for(vid = (char*) VIDEO_ADDR; vid < (char*) VIDEO_END_OFFSET; vid += 2) { + offset = (char*) (vid + lines * 160); + + if(offset < (char*) VIDEO_END_OFFSET) { + vid[0] = offset[0]; + vid[1] = offset[1]; + } else { + vid[0] = 0; + vid[1] = color; + } + } + + pos_y -= lines; + if(pos_y < 0) { + pos_y = 0; + } +} + +void write_char(char c_ascii) { + char* vid; + vid = (char*) (VIDEO_ADDR + pos_y * 160 + pos_x * 2); + + switch(c_ascii) { + case 0: + break; + + case 8: + vid[-2] = 0; + vid[-1] = color; + pos_x--; + break; + + case 10: // Ligne suivante + pos_x = 0; + pos_y++; + break; + + case 13: // Retour debut de ligne + pos_x = 0; + break; + + default: + vid[0] = c_ascii; + vid[1] = color; + pos_x++; + break; + } + + if(pos_x > 79) { + pos_x = 0; + pos_y++; + } + if(pos_y > 24) { + scrollup(1); + } + if(posX < 0) { + posX = 79; + posY--; + } + if(posY < 0) { + posX = 0; + posY = 0; + } + if(enable_cursor) { + move_cursor(pos_x, pos_y); + } +} + +static void print_dec(unsigned int a, char color) { + char str[11]; + int_to_str(a, str, 10); + + unsigned int i; + for(i = 0; str[i] != 0; i++) { + write_char(str[i]); + } +} + +static void print_hex(unsigned int a, char color) { + char str[9]; + int_to_str(a, str, 16); + + unsigned int i; + for(i = 0; str[i] != 0; i++) { + write_char(str[i]); + } +} + +static void print_bin(unsigned int a, char color) { + char str[33]; + int_to_str(a, str, 2); + + unsigned int i; + for(i = 0; str[i] != 0; i++) { + write_char(str[i]); + } +} + +void print(char *str, ...) { + va_list arg; + va_start(arg, str); + + while(str[0] != 0) { + if(str[0] == '%') { + if(str[1] == 'd') { + print_dec(va_arg(arg, T_dword), color); + str += 2; + } else if(str[1] == 'x') { + print_hex(va_arg(arg, T_dword), color); + str += 2; + } else if(str[1] == 'b') { + print_bin(va_arg(arg, T_dword), color); + str += 2; + } else if(str[1] == 's') { + print(va_arg(arg, char*), color); + str += 2; + } else if(str[1] == 'C') { + + } else { + write_char(*str, color); + str++; + } + } else { + write_char(*str, color); + str++; + } + } + va_end(arg); +} + +void clear() { + char* vid; + for(vid = (char*) VIDEO_ADDR; vid <= (char*) VIDEO_END_OFFSET; vid += 2) { + vid[0] = 0; + vid[1] = ; + } +} + +void show_cursor() { + enable_cursor = 1; + move_cursor(pos_x, pos_y); +} + +void hide_cursor() { + enable_cursor = 0; + move_cursor(-1, -1); +} + +void move_cursor(char x, char y) { + T_word c_pos = (T_word) (y * 80 + x); + + _out(0x3D4, 0x0F); + _out(0x3D5, (T_byte) cpos); + _out(0x3D4, 0x0E); + _out(0x3D5, (T_byte) (cpos >> 8)); +} diff --git a/boot/kernloader/kernldr_utils.c b/boot/kernloader/kernldr_utils.c new file mode 100644 index 0000000..3625ceb --- /dev/null +++ b/boot/kernloader/kernldr_utils.c @@ -0,0 +1,92 @@ +/* kernLdr_utils.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "drivers/ATA.h" + +#include "kernLdr.h" + +void memcopy(char *src, char *dst, unsigned int n) { + unsigned int i; + for(i = 0; i < n; i++) { + dst[i] = src[i]; + } +} + +int strcmp(char *str1, char *str2) { + int length1 = 0; + int length2 = 0; + int i; + + while(str1[length1] != 0) { + length1++; + } + + while(str2[length2] != 0) { + length2++; + } + + if(length1 == length2) { + for(i = 0; i < length1; i++) { + if(str1[i] != str2[i]) { + return 0; + } + } + } else { + return 0; + } + + return 1; +} + +void intToStr(T_dword num, char *str, int base) { + const char decimal[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + int i, j, a; + int length; + int tmp = 0; + int counter = 0; + + for(i = 0; i < 10; i++) { + if((num / (expo(base, i))) < base) { + length = i; + break; + } + } + + j = length; + + for(i = 0; i <= length; i++) { + a = num / expo(base, j); + str[counter] = decimal[a - (base * tmp)]; + tmp = a; + counter++; + j--; + } + str[counter] = 0; +} + +T_dword expo(int x, int y) { + return (y > 0) ? (x * expo(x, y-1)) : 1; +} + +void delay(unsigned int n) { + unsigned int i; + for(i = 0; i < n; i++); +} diff --git a/boot/kernloader/startup.asm b/boot/kernloader/startup.asm new file mode 100644 index 0000000..30ede84 --- /dev/null +++ b/boot/kernloader/startup.asm @@ -0,0 +1,197 @@ +; startup.asm - This file is a part of NutsOS + +; NutsOS +; Copyright (C) 2013 Free Software Foundation, Inc. + +; NutsOS 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. + +; NutsOS 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 NutsOS; If not, see . + +; Valentin Verdier + +%define ARGS_SEG 0x100 +%define KERN_LDR_SEG 0x07E0 + +%define ARGS_CURSOR_POSX_OFFSET 0 +%define ARGS_CURSOR_POSY_OFFSET 1 +%define ARGS_MEMMAP_ENTRY_COUNT_OFFSET 2 +%define ARGS_MEMMAP_OFFSET 3 + +[BITS 16] +[ORG 0] ; Par rapport au segment 0x07E0 + +startup: + mov ax, KERN_LDR_SEG + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + mov ax, 0x500 + mov ss, ax + mov sp, 0xFF0 + + mov si, start_msg + call print + + call build_args + + ; On passe en mode protégé + cli + lgdt [gdtreg] + mov eax, cr0 + or eax, 1 + mov cr0, eax + + ; Segment 0x07E0 en mode réel = adresse physique 0x7E00 + ; Le seconde partie du code de kernLdr est situé 512 octets plus loin + ; On saute dans le seconde partie de kernLdr et en même temps on réinitialise le segment de code + jmp 0x08:0x8000 + + +build_args: + push eax + push ebx + push ecx + push edx + push es + push di + + mov ax, ARGS_SEG + mov es, ax + + mov ah, 3 + xor bh, bh + int 0x10 ; On demande la position du curseur + + ; On passe la position du curseur en argument + mov [es:ARGS_CURSOR_POSX_OFFSET], dl + mov [es:ARGS_CURSOR_POSY_OFFSET], dh + + ; Memory map initialisation + mov di, ARGS_MEMMAP_OFFSET + + mov eax, 0xE820 + xor ebx, ebx + mov ecx, 24 + mov edx, 0x534D4150 + int 0x15 + + jc error + + cmp eax, 0x534D4150 + jne error + + cmp ebx, 0 + je error + + xor bp, bp + +; récupération des entrées de la Memory Map +.loop: + inc bp + add di, 24 + mov eax, 0xE820 + mov ecx, 24 + int 0x15 + + jc .end_loop + + cmp ebx, 0 + jne .loop + +.end_loop: + mov ax, bp + mov [es:ARGS_MEMMAP_ENTRY_COUNT_OFFSET], al + + pop di + pop es + pop edx + pop ecx + pop ebx + pop eax + ret + +; Fonction print +; Params : pointeur sur str -> ds:si +print: + push ax + push bx + +.top: + lodsb + cmp al, 0 + jz .end + + mov ah, 0x0E ; int 0x10 fonction 0x0E + mov bx, 0x07 ; attribut du caractère + int 0x10 + jmp .top + +.end: + pop bx + pop ax + ret + + +error: + mov si, error_msg + call print +.loop: + hlt + jmp .loop + +; Variables +; ################################# + +; kernLdrContext: +; - cursorX +; - cursorY +; - biosBootDisk +; - listSize +; - memStructureList + +start_msg: db "Starting NutsOS KernelLoader...", 13, 10, 0 +error_msg: db "Fatal Error !", 0 + +gdt_reg: + dw (gdt_end - gdt_start) ; taille de la gdt + dd (KERN_LDR_SEG << 4) + gdt_start ; adresse de base dur 32 bits + +gdt_start: +.null_seg: ; descripteur nul + times 8 db 0 +.code_seg: ; Segment de code [0x0 - 0xFFFFFFFF] + dw 0xFFFF ; limite0_15 + dw 0x0000 ; base0_15 + db 0x00 ; base16_23 + db 0x9A ; acces + db 0xCF ; Flags, limite16_19 + db 0x00 ; base24_31 +.data_seg: ; Segment de données [0x0 - 0xFFFFFFFF] + dw 0xFFFF ; limite0_15 + dw 0x0000 ; base0_15 + db 0x00 ; base16_23 + db 0x92 ; acces + db 0xCF ; Flags, limite16_19 + db 0x00 ; base24_31 +.stack_seg: ; Segment de pile [... - 0x9F000] + dw 0x0000 ; limite0_15, (0x009F + intel vt-x = O_o bug) + dw 0x0000 ; base0_15 + db 0x00 ; base16_23 + db 0x96 ; acces + db 0xC0 ; Flags, limite16_19 + db 0x00 ; base24_31 +gdt_end: +; ################################# + +times 512-($-$$) db 144 diff --git a/boot/kernloader/types.h b/boot/kernloader/types.h new file mode 100644 index 0000000..01da4ca --- /dev/null +++ b/boot/kernloader/types.h @@ -0,0 +1,31 @@ +/* types.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + + +#pragma once +#ifndef NOS_TYPES_H +#define NOS_TYPES_H + +typedef unsigned char T_byte; +typedef unsigned short T_word; +typedef unsigned int T_dword; + +#endif diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..f1e210d --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,39 @@ +.PHONY: clean +.SUFFIXES: + +include_dir=include/ + +CC=gcc +CFLAGS= -m32 -march=i486 -fno-stack-protector -fno-zero-initialized-in-bss -I $(include_dir) + +kobj_core=src/main.o \ +src/print.o \ +src/memory.o \ +src/interrupt.o \ +src/utils.o \ +src/systemCall.o \ +src/process.o \ +src/ipc.o \ +src/scheduler.o \ +src/elf_loader.o \ +src/signal.o + +kobj_asm_x86=src/asm/isr.o \ +src/asm/asm_utils.o \ +src/asm/io_port.o \ +src/asm/sched.o + +all: NOS-kernel32.bin + +NOS-kernel32.bin: $(kobj_core) $(kobj_asm_x86) + ld -melf_i386 --oformat=binary --Ttext=100000 --entry=main $^ -o $@ + +%.o: %.asm + nasm -f elf -o $@ $^ + +%.o: %.c + $(CC) $(CFLAGS) -c $^ -o $@ + +clean: + -rm -f $(kobj_core) $(kobj_asm_x86) + -rm -f NOS-kernel32.bin diff --git a/kernel/include/args.h b/kernel/include/args.h new file mode 100644 index 0000000..007228c --- /dev/null +++ b/kernel/include/args.h @@ -0,0 +1,50 @@ +/* args.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef ARGS_H +#define ARGS_H + +#include "types.h" + +/* Strcutres de récupération de contexte */ +typedef struct { + T_dword baseAddr_1; + T_dword baseAddr_2; + T_dword size_1; + T_dword size_2; + T_dword type; + T_dword unused; +}__attribute__((packed)) T_memMapEntry; + +typedef struct { + T_byte cursor_X; + T_byte cursor_Y; + T_dword phyMemSize; + T_byte memListEntryNumber; + T_dword initProcessAddr; + T_dword initProcessSize; + T_memMapEntry* memMap; +}__attribute__((packed)) T_kernelArgs; + +T_kernelArgs* args; + +#endif diff --git a/kernel/include/asm_x86.h b/kernel/include/asm_x86.h new file mode 100644 index 0000000..76c4220 --- /dev/null +++ b/kernel/include/asm_x86.h @@ -0,0 +1,51 @@ +/* asm_x86.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef ASM_X86_H +#define ASM_X86_H + +#include "types.h" +#include "memory.h" +#include "interrupt.h" + +void _loadGdtR(T_gdt*); +void _loadTaskRegister(); +void _loadIdtR(T_idt*); +void _clearInterrupt(); +void _startInterrupt(); +void _out(T_word, T_byte); +T_byte _in(T_word); +void _outw(T_word, T_word); +T_word _inw(T_word); +void _outdw(T_word, T_dword); +T_dword _indw(T_word); +void _enablePaging(); +void _emptyTLB(); +void _loadCr3(T_dword); +T_dword _readCr3(); +T_dword _readCr2(); +T_dword _saveEflags(); +T_dword _restoreEflags(T_dword); +T_dword _atomicTestAndSet(unsigned int*); +T_dword _getStackFrameAddr(unsigned int); + +#endif diff --git a/kernel/include/elf_loader.h b/kernel/include/elf_loader.h new file mode 100644 index 0000000..8b68f59 --- /dev/null +++ b/kernel/include/elf_loader.h @@ -0,0 +1,32 @@ +/* elf_loader.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef ELF_LOADER_H +#define ELF_LOADER_H + +#include "types.h" +#include "utils.h" + +int ELF32_checkFile(void*); +unsigned int ELF32_load(void*, T_list*); + +#endif diff --git a/kernel/include/interrupt.h b/kernel/include/interrupt.h new file mode 100644 index 0000000..5924248 --- /dev/null +++ b/kernel/include/interrupt.h @@ -0,0 +1,99 @@ +/* interrupt.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef INTERRUPT_H +#define INTERRUPT_H + +#include "types.h" + +/* === Configuration du PIC 8259A === */ + +#define PIC_MASTER_CMD_REG 0x20 +#define PIC_MASTER_DATA_REG 0x21 +#define PIC_MASTER_IDT_OFFSET 0x20 + +#define PIC_SLAVE_CMD_REG 0xA0 +#define PIC_SLAVE_DATA_REG 0xA1 +#define PIC_SLAVE_IDT_OFFSET 0x28 + +#define PIC_EOI 0x20 + +void PIC_init(); +void PIC_maskIRQ(T_byte); +void PIC_sendEOI(); + +/* ======================================================================== */ + + +/* ===== Manipulation de l'IDT ===== */ + +#define IDT_BASE 0x200800 +#define INT_DESC_SIZE 8 +#define IDT_SIZE 256 + +#define DIVIDE_BY_0_INT 0 +#define NMI_INT 2 +#define BREAKPOINT_INT 3 +#define OVERFLOW_INT 4 +#define INVALID_TSS_INT 10 + +#define SEG_FAULT_INT 11 +#define STACK_SEG_FAULT_INT 12 +#define GP_FAULT_INT 13 +#define PAGE_FAULT_INT 14 + +#define TIMER_INT 32 +#define KB_INT 33 +#define SYS_CALL_INT 64 + +typedef struct { + T_word offset0_15; + T_word segment; + T_word type; + T_word offset16_31; +}__attribute__((packed)) T_IDT_desc; + +typedef struct { + T_word limite; + T_dword base; +}__attribute__((packed)) T_IDT_reg; + + +void IDT_init(); +void IDT_createDesc(T_dword, T_word, T_word, unsigned int); + +/* ======================================================================== */ + + +/* Routine d'interruption en assembleur (redirection vers routines en C) */ + +void _defaultInt(); +void _SEG_fault(); +void _GP_fault(); +void _page_fault(); +void _clockInterrupt(); +void _syscall(); + +/* ======================================================================== */ + + +#endif diff --git a/kernel/include/ipc.h b/kernel/include/ipc.h new file mode 100644 index 0000000..f3cb316 --- /dev/null +++ b/kernel/include/ipc.h @@ -0,0 +1,31 @@ +/* ipc.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef IPC_H +#define IPC_H + +#include "types.h" + +void IPC_mutexLock(unsigned int*); +void IPC_mutexUnlock(unsigned int*); + +#endif diff --git a/kernel/include/memory.h b/kernel/include/memory.h new file mode 100644 index 0000000..09442b1 --- /dev/null +++ b/kernel/include/memory.h @@ -0,0 +1,223 @@ +/* memory.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef MEMORY_H +#define MEMORY_H + +#include "types.h" + +/* ###### Main Memory Management ###### */ +#define KERNEL_SPACE_SIZE 0x10000000 /* Mémoire potentiellement utilisable par le kernel, adresse virtuelle de fin de l'espace noyau, aligné sur 4 Mo */ + +/* Configation dynamique */ +#define KERNEL_SPACE_PT_COUNT (KERNEL_SPACE_SIZE / (PAGE_PER_PT * PAGE_SIZE)) +#define KERNEL_SPACE_PAGE_COUNT (KERNEL_SPACE_PT_COUNT * PAGE_PER_PT) + +#define KERNEL_PHY_SPACE_SIZE (KERNEL_PT_ADDR + (KERNEL_SPACE_PT_COUNT * PT_SIZE)) +#define KERNEL_PHY_SPACE_PAGE_COUNT (KERNEL_PHY_SPACE_SIZE / PAGE_SIZE) + +#define KERNEL_VM_SIZE (KERNEL_SPACE_SIZE - KERNEL_PHY_SPACE_SIZE) +#define KERNEL_VM_PAGE_COUNT (KERNEL_VM_SIZE / PAGE_SIZE) +/* ----------------------- */ + +/* Configation statique */ +#define KERNEL_PD_ADDR 0x303000 +#define KERNEL_PT_ADDR 0x304000 + +#define PD_SIZE 4096 +#define PT_SIZE 4096 +#define PAGE_SIZE 4096 + +#define MAX_PT_COUNT 1024 +#define MAX_PAGE_COUNT 1048576 + +#define PAGE_OFFSET_BITS 12 +#define PAGE_PER_PT 1024 +/* ----------------------- */ + +/* Special types */ +typedef T_dword T_page; +typedef T_Page* T_pageTable; +typedef T_pageTable* T_pageDir; +/* ----------------------- */ + +#ifdef MEMORY_PRIVATE + T_PageDirectory kpageDir; + T_PageTable kageTable; + unsigned int KernPageTableMutex; +#endif + +void kinitSpace(); +unsigned int kaddPage(T_Page); +void kremovePage(T_Page); +T_Page kgetPage(); +void* kgetPhyAddr(void*); + +/* ##################################### */ + + + +/* ###### Segment Management ###### */ + +#define GDT_BASE 0x200000 +#define SEG_DESC_SIZE 8 +#define SEG_DESC_NUMBER 256 + +#define MAIN_KERNEL_STACK 0xA0000 + +#define TSS_BASE 0x201000 + +struct MemSegDescriptor +{ + bits16 limite0_15; + bits16 base0_15; + bits8 base16_23; + bits8 acces; + bits8 limite16_19:4; + bits8 other:4; + bits8 base24_31; +}__attribute__((packed)); + +struct GdtReg +{ + bits16 limite; + bits32 base; +}__attribute__((packed)); + +struct TaskStateSegment +{ + bits16 prevTask; + bits16 reserved_1; + bits32 esp0; + bits16 ss0; + bits16 reserved_2; + bits32 esp1; + bits16 ss1; + bits16 reserved_3; + bits32 esp2; + bits16 ss2; + bits16 reserved_4; + bits32 cr3; + bits32 eip; + bits32 eflags; + bits32 eax; + bits32 ecx; + bits32 edx; + bits32 ebx; + bits32 esp; + bits32 ebp; + bits32 esi; + bits32 edi; + bits16 es; + bits16 reserved_5; + bits16 cs; + bits16 reserved_6; + bits16 ss; + bits16 reserved_7; + bits16 ds; + bits16 reserved_8; + bits16 fs; + bits16 reserved_9; + bits16 gs; + bits16 reserved_10; + bits16 ldtSegSelect; + bits16 reserved_11; + bits16 flagDebug; + bits16 io_map; +}__attribute__((packed)); + +/* Special types */ +typedef struct MemSegDescriptor T_GdtDesc; +typedef struct GdtReg T_GDT; +typedef struct TaskStateSegment T_TSS; +/* ----------------------- */ + +T_TSS *tss; + +void InitGDT(); +void CreateSegDescriptor(bits32, bits32, bits8, bits8, unsigned int); + +/* ##################################### */ + + + +/* ###### Page Management ###### */ + +#ifdef MEMORY_PRIVATE + #define PHY_PAGE_MAP_ADDR 0x203000 + + #define PAGE_FREE 0 + #define PAGE_USED 1 + #define PAGE_NOT_PRESENT 4 + bits8 *PageMap; + unsigned int PhyPageMapMutex; +#endif + +#define PAGE_FLAG_PRESENT 1 +#define PAGE_FLAG_RW 2 +#define PAGE_FLAG_USER 4 + +T_Page GetPhyPage(); +void ReleasePhyPage(T_Page); + +/* ##################################### */ + + + +/* ###### Alloc Management ###### */ + +#ifdef MEMORY_PRIVATE + #define FREE 0 + #define USED 1 + + unsigned int KERNEL_HEAP_BASE; + unsigned int KERNEL_HEAP_LIMIT; + + struct AllocAreaModel { + T_byte state; /* 1:used 0:free */ + struct AllocAreaModel *next; + }__attribute__((packed)); + + unsigned int AllocMutex; +#endif + +void* malloc(unsigned int); +void free(void*); +struct AllocAreaModel* EnlargeHeap(); + +/* ##################################### */ + + + +/* ###### Paging Management ###### */ + +T_PageDirectory CreateTaskPageDirectory(); +void DestroyTaskPageDirectory(T_PageDirectory); +unsigned int AddPage(T_Page, bits32); +void RemovePage(T_Page); +unsigned int LinkPhyPage(T_Page, T_Page, bits32); +void UnlinkPhyPage(T_Page); +void* GetPhyAddr(void*); + +/* ##################################### */ + +#endif diff --git a/kernel/include/print.h b/kernel/include/print.h new file mode 100644 index 0000000..fb1f84e --- /dev/null +++ b/kernel/include/print.h @@ -0,0 +1,58 @@ +/* print.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef PRINT_H +#define PRINT_H + +#include +#include "types.h" + +#define TEXTCOLOR_BLACK 0x0 +#define TEXTCOLOR_DARK_BLUE 0x1 +#define TEXTCOLOR_DARK_GREEN 0x2 +#define TEXTCOLOR_DARK_CYAN 0x3 +#define TEXTCOLOR_DARK_RED 0x4 +#define TEXTCOLOR_DARK_MAGENTA 0x5 +#define TEXTCOLOR_DARK_BROWN 0x6 +#define TEXTCOLOR_DARK_GRAY 0x8 +#define TEXTCOLOR_LIGHT_GRAY 0x7 +#define TEXTCOLOR_LIGHT_BLUE 0x9 +#define TEXTCOLOR_LIGHT_GREEN 0xA +#define TEXTCOLOR_LIGHT_CYAN 0xB +#define TEXTCOLOR_LIGHT_RED 0xC +#define TEXTCOLOR_LIGHT_MAGENTA 0xD +#define TEXTCOLOR_LIGHT_YELLOW 0xE +#define TEXTCOLOR_WHITE 0xF + +#define BACK_BLUE 0x1 +#define BACK_GREEN 0x2 +#define BACK_CYAN 0x3 +#define BACK_RED 0x4 +#define BACK_MAGENTA 0x5 +#define BACK_BROWN 0x6 +#define BACK_GRAY 0x7 + +void printError(char*, ...); +void print(char*, ...); +void printColor(char*, T_byte, ...); + +#endif diff --git a/kernel/include/process.h b/kernel/include/process.h new file mode 100644 index 0000000..b2a7d36 --- /dev/null +++ b/kernel/include/process.h @@ -0,0 +1,126 @@ +/* process.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef PROCESS_H +#define PROCESS_H + +#include "types.h" +#include "memory.h" +#include "utils.h" +#include "ipc.h" + + +#define USER_SPACE_BASE_ADDR (KERNEL_SPACE_SIZE) +#define USER_STACK_ADDR 0xFFBFF000 +#define USER_SPACE_END_ADDR 0xFFBFE000 + +#define PROCESS_STATUS_RUNNING 0 +#define PROCESS_STATUS_WAIT_MUTEX 1 +#define PROCESS_STATUS_SLEEP 2 +#define PROCESS_STATUS_ZOMBIE 3 + +struct ProcessModel +{ + struct ProcessModel* next; /* 0 */ + struct ProcessModel* prev; /* 4 */ + + bits32 reg_EAX; /* 8 */ + bits32 reg_EBX; /* 12 */ + bits32 reg_ECX; /* 16 */ + bits32 reg_EDX; /* 20 */ + bits32 reg_ESI; /* 24 */ + bits32 reg_EDI; /* 28 */ + bits32 reg_EBP; /* 32 */ + bits32 reg_ESP; /* 36 */ + bits32 reg_EIP; /* 40 */ + bits32 reg_EFLAGS; /* 44 */ + bits16 reg_CS; /* 48 */ + bits16 reg_DS; /* 50 */ + bits16 reg_ES; /* 52 */ + bits16 reg_FS; /* 54 */ + bits16 reg_GS; /* 56 */ + bits16 reg_SS; /* 58 */ + bits32 reg_CR3; /* 60 */ + + bits32 kernelStackPtr; + T_PageDirectory pageDir; + T_LinkedList processRegionsList; + + unsigned int pid; + struct ProcessModel* parent; + T_LinkedList processChildrenList; + unsigned int signal; + void* signalAction[32]; + + bits8 status; /* 0:actif 1:wait mutex 2:sleep 3:zombie */ + unsigned int* ipcWaitMutex; + unsigned int ipcInSection; +}; +typedef struct ProcessModel T_Process; + +#ifdef PROCESS_PRIVATE + #define PROCESS_REGION_RO 0 + #define PROCESS_REGION_RW 1 + #define PROCESS_REGION_HEAP 3 + + struct ProcessRegion + { + struct ProcessRegion* next; + struct ProcessRegion* prev; + T_Page startPage; + T_Page endPage; + unsigned char type; + }; + + struct ProcessChild + { + struct ProcessChild* next; + struct ProcessChild* prev; + T_Process* process; + }; + + unsigned int PidCounter; +#endif + +T_LinkedList Processes; +T_Process* CurrentProcess; +T_Process Process_0; + +void InitProcessManager(); +unsigned int CreateProcess(void*); + +/* Fonctions éxécutées par le processus lui meme */ +void DestroyProcess(); +unsigned int ProcessCreateRegion_RO(T_Page, T_Page*, unsigned int, T_LinkedList*); +unsigned int ProcessCreateRegion_RW(T_Page, unsigned int, T_LinkedList*); +void ProcessRemoveRegion(T_Page, unsigned int, T_LinkedList*); +/* ############################################# */ + +/* Fonctions d'ordonnancement */ +void _LoadContext(T_Process*); +bits32* _SaveContex(); +T_Process* SchedulingAlgorithm(); +void Schedule(); +void ScheduleAtClock(); +/* ############################################# */ + +#endif diff --git a/kernel/include/signal.h b/kernel/include/signal.h new file mode 100644 index 0000000..009f897 --- /dev/null +++ b/kernel/include/signal.h @@ -0,0 +1,40 @@ +/* signal.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + + +#pragma once +#ifndef SIGNAL_H +#define SIGNAL_H + +#include "process.h" + +/* Du plus important au moins important */ +#define SIGNAL_KILL 0 +#define SIGNAL_TERM 1 +#define SIGNAL_KCHILD 2 + +void SendSignal(unsigned int, T_Process*); +void ClearSignal(unsigned int, T_Process*); +unsigned int FetchSignal(unsigned int, T_Process*); + +void HandleSignal(unsigned int, T_Process*); + +#endif diff --git a/kernel/include/types.h b/kernel/include/types.h new file mode 100644 index 0000000..24dd965 --- /dev/null +++ b/kernel/include/types.h @@ -0,0 +1,31 @@ +/* types.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef TYPES_H +#define TYPES_H + +typedef unsigned char T_byte; +typedef unsigned short T_word; +typedef unsigned int T_dword; + +#endif + diff --git a/kernel/include/utils.h b/kernel/include/utils.h new file mode 100644 index 0000000..9ad4432 --- /dev/null +++ b/kernel/include/utils.h @@ -0,0 +1,57 @@ +/* utils.h - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#pragma once +#ifndef UTILS_H +#define UTILS_H + +#include "types.h" + +void memcopy(char*, char*, unsigned int); +int strcmp(char*, char*); +void IntToChar(bits32, char*, int); +unsigned int expo(unsigned int, unsigned int); + +struct List +{ + unsigned int entryCount; + struct ElementModel *firstEntry; + struct ElementModel *lastEntry; +}; + +typedef struct List T_LinkedList; + +struct ElementModel +{ + struct ElementModel *next; + struct ElementModel *prev; +}__attribute__((packed)); + +void LinkedListPushFront(void*, T_LinkedList*); +void LinkedListPopFront(T_LinkedList*); +void LinkedListPushBack(void*, T_LinkedList*); +void LinkedListPopBack(T_LinkedList*); +void LinkedListInsert(void*, void*, void*, T_LinkedList*); +void LinkedListRemove(void*, T_LinkedList*); + +void InsertElement(void*, void*, void*); +void RemoveElement(void*); +#endif diff --git a/kernel/src/asm/io.asm b/kernel/src/asm/io.asm new file mode 100644 index 0000000..a3a25c9 --- /dev/null +++ b/kernel/src/asm/io.asm @@ -0,0 +1,77 @@ +; io_port.asm - This file is a part of NutsOS + +; NutsOS +; Copyright (C) 2013 Free Software Foundation, Inc. + +; NutsOS 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. + +; NutsOS 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 NutsOS; If not, see . + +; Valentin Verdier + +[BITS 32] +[SECTION .text] + +global _out, _in, _outw, _inw, _outdw, _indw + +_out: + push eax + push edx + mov dx, [esp+12] + mov al, [esp+16] + out dx, al + pop edx + pop eax + ret + +_in: + push edx + xor eax, eax + mov dx, [esp+8] + in al, dx + pop edx + ret + +_outw: + push eax + push edx + mov dx, [esp+12] + mov ax, [esp+16] + out dx, ax + pop edx + pop eax + ret + +_inw: + push edx + xor eax, eax + mov dx, [esp+8] + in ax, dx + pop edx + ret + +_outdw: + push eax + push edx + mov dx, [esp+12] + mov eax, [esp+16] + out dx, eax + pop edx + pop eax + ret + +_indw: + push edx + mov dx, [esp+8] + in eax, dx + pop edx + ret diff --git a/kernel/src/asm/isr.asm b/kernel/src/asm/isr.asm new file mode 100644 index 0000000..6709bbe --- /dev/null +++ b/kernel/src/asm/isr.asm @@ -0,0 +1,94 @@ +; isr.asm - This file is a part of NutsOS + +; NutsOS +; Copyright (C) 2013 Free Software Foundation, Inc. + +; NutsOS 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. + +; NutsOS 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 NutsOS; If not, see . + +; Valentin Verdier + +[BITS 32] +[SECTION .text] + +extern IsrDefault, IsrGPFault, IsrSegFault, IsrPageFault, IsrClock, IsrKeyboard, ExecSystemCall, PIC_Send_EOI +global _DefaultInterrupt, _SEG_Fault, _GP_Fault, _Page_Fault, _KeyboardInterrupt, _ClockInterrupt, _SystemCall + +%macro REGS_SAVE 0 + pushad + push ds + push es + push fs + push gs + push ebx + mov bx, 0x10 + mov ds, bx + pop ebx +%endmacro + +%macro REGS_RESTORE 0 + pop gs + pop fs + pop es + pop ds + popad +%endmacro + +_DefaultInterrupt: + REGS_SAVE + call IsrDefault + call PIC_Send_EOI + REGS_RESTORE + iret + +_SEG_Fault: + REGS_SAVE + call IsrSegFault + REGS_RESTORE + iret + +_GP_Fault: + REGS_SAVE + call IsrGPFault + REGS_RESTORE + add esp, 4 ; Pour le décalage créé par le code d'erreur dans la pile + iret + +_Page_Fault: + REGS_SAVE + call IsrPageFault + REGS_RESTORE + add esp, 4 ; Pour le décalage créé par le code d'erreur dans la pile + iret + +_KeyboardInterrupt: + REGS_SAVE + call IsrKeyboard + call PIC_Send_EOI + REGS_RESTORE + iret + +_ClockInterrupt: + REGS_SAVE + call IsrClock + call PIC_Send_EOI + REGS_RESTORE + iret + +_SystemCall: + REGS_SAVE + push eax + call ExecSystemCall + pop eax + REGS_RESTORE + iret diff --git a/kernel/src/asm/sched.asm b/kernel/src/asm/sched.asm new file mode 100644 index 0000000..6006004 --- /dev/null +++ b/kernel/src/asm/sched.asm @@ -0,0 +1,88 @@ +; sched.asm - This file is a part of NutsOS + +; NutsOS +; Copyright (C) 2013 Free Software Foundation, Inc. + +; NutsOS 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. + +; NutsOS 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 NutsOS; If not, see . + +; Valentin Verdier + +[BITS 32] +[SECTION .text] + +global _LoadContext, _SaveContex + +_SaveContex: + pushfd + pushad + push dword ds + push dword es + push dword fs + push dword gs + mov eax, [esp + 52] ; On retrouve l'adresse de retour empilée lors de l'appel + push eax ; eip ret + mov eax, esp + add eax, 4 + ret + + + +_LoadContext: + mov esi, [esp + 4] + + mov ax, [esi + 48] ; cs + cmp ax, 0x08 + je .kernMode +.userMode: + mov ax, 0x18 + mov ss, ax + mov esp, [esi + 64] ; Kstack_ptr + push dword [esi + 58] ; ss + push dword [esi + 36] ; esp + jmp .next +.kernMode: + mov ax, [esi + 58] ; ss + mov ss, ax + mov esp, [esi + 36] ; esp +.next: + push dword [esi + 44] ; eflags + push dword [esi + 48] ; cs + push dword [esi + 40] ; eip + push dword [esi + 8] ; eax + push dword [esi + 12] ; ebx + push dword [esi + 16] ; ecx + push dword [esi + 20] ; edx + push dword [esi + 24] ; esi + push dword [esi + 28] ; edi + push dword [esi + 32] ; ebp + push dword [esi + 50] ; ds + push dword [esi + 52] ; es + push dword [esi + 54] ; fs + push dword [esi + 56] ; gs + + mov eax, [esi + 60] + mov cr3, eax + + pop gs + pop fs + pop es + pop ds + pop ebp + pop edi + pop esi + pop edx + pop ecx + pop ebx + pop eax + iret diff --git a/kernel/src/asm/syslib.asm b/kernel/src/asm/syslib.asm new file mode 100644 index 0000000..287a0d3 --- /dev/null +++ b/kernel/src/asm/syslib.asm @@ -0,0 +1,133 @@ +; asm_utils.asm - This file is a part of NutsOS + +; NutsOS +; Copyright (C) 2013 Free Software Foundation, Inc. + +; NutsOS 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. + +; NutsOS 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 NutsOS; If not, see . + +; Valentin Verdier + +[BITS 32] +[SECTION .text] +global _ClearInterrupt, _StartInterrupt, _EnablePaging, _LoadGdtR, _LoadIdtR, _LoadTaskRegister, _EmptyTLB, _LoadCr3, _ReadCr3, _ReadCr2, _SaveEflags, _RestoreEflags, _GetStackFrameAddr, _AtomicTestAndSet + +_ClearInterrupt: + cli + ret + +_StartInterrupt: + sti + ret + +_EnablePaging: + push eax + mov eax, 0x303000 + mov cr3, eax + mov eax, cr0 + or eax, 0x80000000 + mov cr0, eax + pop eax + ret + +_LoadGdtR: + mov eax, [esp+4] + lgdt [eax] + mov ax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ax, 0x18 + mov ss, ax + jmp 0x08:.next + .next: + ret + +_LoadIdtR: + push eax + mov eax, [esp+8] + lidt [eax] + pop eax + ret + +_LoadTaskRegister: + push ax + mov ax, 0x38 + ltr ax + pop ax + ret + +_EmptyTLB: + push eax + mov eax, cr3 + mov cr3, eax + pop eax + ret + +_LoadCr3: + push eax + mov eax, [esp+8] + mov cr3, eax + pop eax + ret + +_ReadCr3: + mov eax, cr3 + ret + +_ReadCr2: + mov eax, cr2 + ret + +_SaveEflags: + pushfd + pop eax + ret + +_RestoreEflags: + push eax + mov eax, [esp+8] + push eax + popfd + pop eax + ret + +_AtomicTestAndSet: + push ebx + push edx + xor eax, eax + mov edx, 1 + mov ebx, [esp + 12] + lock cmpxchg [ebx], edx + pop edx + pop ebx + ret + +_GetStackFrameAddr: + push ebx + push ecx + mov ecx, [esp + 12] + mov ebx, ebp +.loopTop: + cmp ecx, 0 + je .loopEnd + mov eax, [ebx] + mov ebx, eax + dec ecx + jmp .loopTop +.loopEnd: + mov eax, ebx + pop ecx + pop ebx + ret diff --git a/kernel/src/elf_loader.c b/kernel/src/elf_loader.c new file mode 100644 index 0000000..05175e3 --- /dev/null +++ b/kernel/src/elf_loader.c @@ -0,0 +1,222 @@ +/* elf_loader.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#define ELF_LOADER_PRIVATE +#include "elf_loader.h" + +#include "types.h" +#include "print.h" +#include "utils.h" +#include "memory.h" +#include "process.h" + +/* Index dans id[] */ +#define ID_MAG_0 0 +#define ID_MAG_1 1 +#define ID_MAG_2 2 +#define ID_MAG_3 3 +#define ID_CLASS 4 +#define ID_DATA 5 +#define ID_VERSION 6 +#define ID_PAD 7 + +/* Classes ELF */ +#define ELF_CLASS_NONE 0 +#define ELF_CLASS_32 1 +#define ELF_CLASS_64 2 + +/* Encodage des données */ +#define ELF_DATA_NONE 0 +#define ELF_DATA_LSB 1 +#define ELF_DATA_MSB 2 + +/* Types de fichier ELF */ +#define ELF_TYPE_NONE 0 +#define ELF_TYPE_RELOC 1 +#define ELF_TYPE_EXEC 2 +#define ELF_TYPE_DYN 3 +#define ELF_TYPE_CORE 4 + +/* Version */ +#define ELF_VERSION_NONE 0 +#define ELF_VERSION_CURRENT 1 + +/* Architectures cible */ +#define ELF_ARCH_NONE 0 +#define ELF_ARCH_M32 1 +#define ELF_ARCH_SPARC 2 +#define ELF_ARCH_386 3 +#define ELF_ARCH_68K 4 +#define ELF_ARCH_88K 5 +#define ELF_ARCH_860 7 +#define ELF_ARCH_MIPS 8 +#define ELF_ARCH_MIPS_RS4_BE 10 + +/* Structure de l'entête des fichier ELF32 */ +typedef struct { + T_byte id[16]; + T_word type; + T_word targetArch; + T_dword version; + T_dword entry; + T_dword prgHdrTblOff; + T_dword secHdrTblOff; /* Pas utilisé ici */ + T_dword flags; /* Pas utilisé ici */ + T_word hdrSize; + T_word prgHdrTblEntrySize; + T_word prgHdrTblEntryCount; + T_word secHdrTblEntrySize; /* Pas utilisé ici */ + T_word secHdrTblEntryCount; /* Pas utilisé ici */ + T_word strTblIndex; /* Pas utilisé ici */ +}__attribute__((packed)) T_ELF32_hdr; + +/* Types de segment */ +#define ELF_SEG_NULL 0 +#define ELF_SEG_LOAD 1 +#define ELF_SEG_DYNAMIC 2 +#define ELF_SEG_INTERP 3 +#define ELF_SEG_NOTE 4 +#define ELF_SEG_SHLIB 5 +#define ELF_SEG_PHDR 6 + +/* Permissions R|W|X */ +#define ELF_SEG_PERM_READ 4 +#define ELF_SEG_PERM_WRITE 2 +#define ELF_SEG_PERM_EXEC 1 + +/* Structure d'une entrée du Program header */ +typedef struct { + T_dword type; + T_dword offset; + T_dword vaddr; + T_dword paddr; + T_dword sizeInFile; + T_dword sizeInMem; + T_dword flags; + T_dword align; +}__attribute__((packed)) T_ELF32_prgHdrEntry; + +int ELF32_checkFile(void *file) +{ + T_ELF32_hdr* elfHdr = file; + if(elfHdr->id[ID_MAG_0] != 0x7F || elfHdr->id[ID_MAG_1] != 'E' || elfHdr->id[ID_MAG_2] != 'L' || elfHdr->id[ID_MAG_3] != 'F') { + print("[ELF Loader] : The file at 0x%x is not ELF type\n", DEFAULT_COLOR, file); + return 0; + } + if(elfHdr->id[ID_CLASS] != ELF_CLASS_32) { + print("[ELF Loader] : The file at 0x%x is not a 32 bits ELF\n", DEFAULT_COLOR, file); + return 0; + } + if(elfHdr->id[ID_DATA] != ELF_DATA_LSB) { + print("[ELF Loader] : The ELF file at 0x%x has a bad encoding\n", DEFAULT_COLOR, file); + return 0; + } + if(elfHdr->type == ELF_TYPE_EXEC) { + print("[ELF Loader] : The ELF file at 0x%x is not executable\n", DEFAULT_COLOR, file); + return 0; + } + if(elfHdr->targetArch == ELF_ARCH_386) { + print("[ELF_Loader] : The ELF file at 0x%x is not a x86 executable\n", DEFAULT_COLOR, file); + return 0; + } + if(elfHdr->entry >= KERNEL_SPACE_SIZE) { + return 1; + } else { + print("[ELF_Loader] : The ELF file at 0x%x has a bad entry point\n", DEFAULT_COLOR, file); + return 0; + } +} + + +unsigned int ELF32_Load(void *file, T_LinkedList* regionsList) +{ + if(ELF32_checkFile(file)) { + T_ELF32_hdr* elfHdr = file; + + unsigned int i, sc; + for(i = 0, sc = 0; i < elfHdr->prgHdrTblEntryCount; i++, sc++) { + T_ELF32_prgHdrEntry* prgHdrEntry = file + elfHdr->prgHdrTblOff + i * elfHdr->prgHdrTblEntrySize; + + if(prgHdrEntry->type == ELF_SEG_LOAD) { + if(!prgHdrEntry->sizeInMem) { + goto error; + } + + T_Page segStartPage = prgHdrEntry->vaddr & 0xFFFFF000; + unsigned int pageCount = prgHdrEntry->sizeInMem & 0xFFFFF000; + if(prgHdrEntry->sizeInMem & 0x00000FFF) { + pageCount++; + } + if((prgHdrEntry->vaddr & 0x00000FFF) >= PAGE_SIZE - (prgHdrEntry->sizeInMem & 0x00000FFF)) { + pageCount++; + } + + if(prgHdrEntry->flags == (ELF_SEG_PERM_READ | ELF_SEG_PERM_EXEC)) { + T_Page* pglist = malloc(sizeof(T_Page) * pageCount); + if(!pglist) { + goto error; + } + + unsigned int j; + for(j = 0; j < pageCount; j++) { + pglist[j] = ((T_Page) file + prgHdrEntry->offset & 0xFFFFF000) + (j << PAGE_OFFSET_BITS); + } + + if(!ProcessCreateRegion_RO(segStartPage, pglist, pageCount, regionsList)) { + free(pglist); + goto error; + } + free(pglist); + } else if(prgHdrEntry->flags == (ELF_SEG_PERM_READ | ELF_SEG_PERM_WRITE)) { + if(!ProcessCreateRegion_RW(segStartPage, pageCount, regionsList)) { + goto error; + } + + unsigned int j; + for(j = 0; j < pageCount; j++) { + memcopy((char*) (((unsigned int) file + prgHdrEntry->offset & 0xFFFFF000) + (j << PAGE_OFFSET_BITS)),(char*) (segStartPage + (j << PAGE_OFFSET_BITS)), PAGE_SIZE); + } + } + } + } + return elfHdr->entry; + + error: + for(i = 0; i < sc; i++) { + T_ELF32_prgHdrEntry* prgHdrEntry = file + elfHdr->prgHdrTblOff + i * elfHdr->prgHdrTblEntrySize; + if(prgHdrEntry->type == ELF_SEG_LOAD) { + T_Page segStartPage = prgHdrEntry->vaddr & 0xFFFFF000; + unsigned int pageCount; + if(prgHdrEntry->sizeInMem & 0x00000FFF) { + pageCount = (prgHdrEntry->sizeInMem & 0xFFFFF000) + 1; + } + if(prgHdrEntry->align > 0) { + pageCount++; + } + + ProcessRemoveRegion(segStartPage, pageCount, regionsList); + } + } + return 0; + } else { + return 0; + } +} diff --git a/kernel/src/interrupt.c b/kernel/src/interrupt.c new file mode 100644 index 0000000..4443834 --- /dev/null +++ b/kernel/src/interrupt.c @@ -0,0 +1,165 @@ +/* interrupt.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "interrupt.h" + +#include "types.h" +#include "asm_x86.h" +#include "print.h" +#include "process.h" + +/* ============ Configuration du PIC 8259A ============ */ + +void PIC_Init() +{ + _out(PIC_MASTER_CMD_REG, 0x11); + _out(PIC_SLAVE_CMD_REG, 0x11); + + _out(PIC_MASTER_DATA_REG, PIC_MASTER_IDT_OFFSET); + _out(PIC_SLAVE_DATA_REG, PIC_SLAVE_IDT_OFFSET); + + _out(PIC_MASTER_DATA_REG, 4); + _out(PIC_SLAVE_DATA_REG, 2); + + _out(PIC_MASTER_DATA_REG, 1); + _out(PIC_SLAVE_DATA_REG, 1); + + _out(PIC_MASTER_DATA_REG, 0); + _out(PIC_SLAVE_DATA_REG, 0); +} + +void PIC_MaskIRQ(bits8 irq) +{ + bits8 mask; + if(irq < 8) + { + mask = _in(PIC_MASTER_DATA_REG) & ~(1 << irq); + _out(PIC_MASTER_DATA_REG, mask); + } + else + { + mask = _in(PIC_SLAVE_DATA_REG) & ~(1 << (irq - 8)); + _out(PIC_SLAVE_DATA_REG, mask); + } +} + +void PIC_Send_EOI() +{ + _out(PIC_MASTER_CMD_REG, PIC_EOI); + _out(PIC_SLAVE_CMD_REG, PIC_EOI); +} + +/* ===================================================== */ + +/* ========= Manipulation de l'IDT ========= */ +void InitIDT() +{ + unsigned int i; + T_IDT IdtR; + PIC_Init(); + + /* Initialisation de l'IDT */ + for(i = 0; i < IDT_SIZE; i++) + { + CreateInterruptDescriptor((bits32) &_DefaultInterrupt, 0x08, 0x8E00, i); + } + /* Configuration de l'IDT */ + CreateInterruptDescriptor((bits32) &_SEG_Fault, 0x08, 0x8E00, SEG_FAULT_INT); + CreateInterruptDescriptor((bits32) &_SEG_Fault, 0x08, 0x8E00, STACK_SEG_FAULT_INT); + + CreateInterruptDescriptor((bits32) &_GP_Fault, 0x08, 0x8E00, GP_FAULT_INT); + CreateInterruptDescriptor((bits32) &_Page_Fault, 0x08, 0xEF00, PAGE_FAULT_INT); + + CreateInterruptDescriptor((bits32) &_ClockInterrupt, 0x08, 0x8E00, TIMER_INT); + CreateInterruptDescriptor((bits32) &_KeyboardInterrupt, 0x08, 0x8E00, KB_INT); + + CreateInterruptDescriptor((bits32) &_SystemCall, 0x08, 0xEF00, SYS_CALL_INT); + + /* Pointeur sur l'IDT pour lidt */ + IdtR.limite = (bits16) (INT_DESC_SIZE * IDT_SIZE); + IdtR.base = IDT_BASE; + + _LoadIdtR(&IdtR); +} + +void CreateInterruptDescriptor(bits32 offset, bits16 seg, bits16 type, unsigned int desc) +{ + T_IdtDesc *idt = (T_IdtDesc*) IDT_BASE; + + idt[desc].offset0_15 = (offset & 0xFFFF); + idt[desc].segment = seg; + idt[desc].type = type; + idt[desc].offset16_31 = (offset & 0xFFFF0000) >> 16; +} +/* ===================================================== */ + + +/* ========== Routines d'interruption en C ============ */ +void IsrDefault() +{ + //print("int\n", 0x47); + return; +} + +void IsrGPFault() +{ + print("ERROR : X86 GENERAL PROTECTION FAULT\n", 0x47); + _ClearInterrupt(); + while(1) + { + asm("hlt"); + } +} + +void IsrSegFault() +{ + print("ERROR : X86 SEGMENTATION FAULT\n", 0x47); + _ClearInterrupt(); + while(1) + { + asm("hlt"); + } +} + +void IsrPageFault() +{ + bits32 cr2 = _ReadCr2(); + /*if(CurrentProcess) + { + ProcessAddPage(cr2 & 0xFFFFF000); + } + else*/ + { + print("ERROR : PAGE FAULT (ADDR = %x)\n", 0x47, cr2); + _ClearInterrupt(); + while(1) + { + asm("hlt"); + } + } +} + +void IsrClock() +{ + KBD_LedsControl(7); + ScheduleAtClock(); +} +/* ========================================================= */ diff --git a/kernel/src/ipc.c b/kernel/src/ipc.c new file mode 100644 index 0000000..1b2ea0e --- /dev/null +++ b/kernel/src/ipc.c @@ -0,0 +1,55 @@ +/* ipc.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "ipc.h" + +#include "types.h" +#include "asm_x86.h" +#include "process.h" + +void IPC_MutexLock(unsigned int* mutex) +{ + if(CurrentProcess) + { + if(_AtomicTestAndSet(mutex)) + { + CurrentProcess->ipcWaitMutex = mutex; + CurrentProcess->status = 1; + Schedule(); + } + else + { + CurrentProcess->ipcInSection++; + } + } +} + +void IPC_MutexUnlock(unsigned int* mutex) +{ + if(CurrentProcess) + { + if(CurrentProcess->ipcInSection > 0) + { + *mutex = 0; + CurrentProcess->ipcInSection--; + } + } +} diff --git a/kernel/src/main.c b/kernel/src/main.c new file mode 100644 index 0000000..2d164d6 --- /dev/null +++ b/kernel/src/main.c @@ -0,0 +1,77 @@ +/* main.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "args.h" +#include "types.h" +#include "print.h" +#include "interrupt.h" +#include "utils.h" +#include "memory.h" +#include "asm_x86.h" +#include "process.h" + + +void main() +{ + arg = (struct ArgModel*) 0x1400; + CurrentProcess = 0; + + print("\nNutsOS Kernel ( NOS-kernel32.bin build 2013-12-01 )\n", 0x6F); + + print("[Kernel] useable memory -> %d Ko\n", DEFAULT_COLOR, (arg->phyMemSize / 1024)); + + if(arg->phyMemSize / 1024 < 10240) + { + print("ERROR : A USEABLE SYSTEM MUST HAVE MORE THAN 10 Mo", 0x47); + asm("hlt"); + } + + print("[Kernel] initializing memory managment...", DEFAULT_COLOR); + InitGDT(); + InitKernelSpace(); + _EnablePaging(); + print("ok\n", 0x02); + + print("[Kernel] setting up interrupts...", DEFAULT_COLOR); + InitIDT(); + //setTimerDivid(11932); /* (1193181Hz / div) div = 1193 pour 1KHz, div = 11932 pour 100Hz */ + print("ok\n", 0x02); + + print("[Kernel] setting up processes scheduler...", DEFAULT_COLOR); + InitProcessManager(); + print("ok\n", 0x02); + + print("[Kernel] end of initialisation, switch to the god process\n", DEFAULT_COLOR); + CurrentProcess = &Process_0; + tss->ss0 = 0x18; + tss->esp0 = CurrentProcess->kernelStackPtr; + _LoadContext(CurrentProcess); + + /*print("[Kernel] detect PCI devices...\n", DEFAULT_COLOR); + PciDetectDevices(); + print("done\n", DEFAULT_COLOR);*/ + + /* Normalement, c'est impossible d'arriver jusque ici */ + while(1) + { + asm("hlt"); + } +} diff --git a/kernel/src/memory.c b/kernel/src/memory.c new file mode 100644 index 0000000..3f602eb --- /dev/null +++ b/kernel/src/memory.c @@ -0,0 +1,790 @@ +/* memory.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#define MEMORY_PRIVATE +#include "memory.h" + +#include "types.h" +#include "print.h" +#include "args.h" +#include "asm_x86.h" +#include "ipc.h" + +/* Initialise les principaux segments utilisés par le kernel */ +void InitGDT() +{ + T_GDT GdtR; + + /* Adresse du TSS en mémoire */ + tss = (T_TSS*) TSS_BASE; + + /* Configuration du TSS */ + tss->flagDebug = 0x00; + tss->io_map = 0x00; + tss->esp0 = MAIN_KERNEL_STACK; + tss->ss0 = 0x18; + + /* Configuration de la GDT */ + CreateSegDescriptor(0x0, 0x0, 0x0, 0x0, 0); /* Segment nul */ + CreateSegDescriptor(0x0, 0xFFFFF, 0x9B, 0x0D, 1); /* Code noyau */ + CreateSegDescriptor(0x0, 0xFFFFF, 0x93, 0x0D, 2); /* Données noyau */ + CreateSegDescriptor(0x0, 0x0, 0x97, 0x0D, 3); /* Pile noyau */ + + CreateSegDescriptor(0x0, 0xFFFFF, 0xFF, 0x0D, 4); /* Code user */ + CreateSegDescriptor(0x0, 0xFFFFF, 0xF3, 0x0D, 5); /* Données user */ + CreateSegDescriptor(0x0, 0x0, 0xF7, 0x0D, 6); /* Pile user */ + + CreateSegDescriptor((bits32) tss, 0x67, 0xE9, 0x00, 7); /* TSS */ + + /* Pointeur sur GDT pour lgdt */ + GdtR.limite = (bits16) (SEG_DESC_NUMBER * SEG_DESC_SIZE); + GdtR.base = GDT_BASE; + + _LoadGdtR(&GdtR); + _LoadTaskRegister(); +} + +void CreateSegDescriptor(bits32 base, bits32 limite, bits8 acces, bits8 other, unsigned int desc) +{ + T_GdtDesc *gdt = (T_GdtDesc*) GDT_BASE; + + gdt[desc].limite0_15 = (limite & 0xFFFF); + gdt[desc].base0_15 = (base & 0xFFFF); + gdt[desc].base16_23 = (base & 0xFF0000) >> 16; + gdt[desc].acces = acces; + gdt[desc].limite16_19 = (limite & 0xF0000) >> 16; + gdt[desc].other = (other & 0xF); + gdt[desc].base24_31 = (base & 0xFF000000) >> 24; +} + +/* Créé l'espace virtuel linéaire du noyau qui couvre 4 Go */ +void InitKernelSpace() +{ + bits32 i, j, page, size; + + /* === On créé l'espace d'adressage du kernel (espace physique fixe : 7184 Ko, espace virtuel dynamique : 254960 Ko, total : 256 Mo) === */ + + PageDirectory = (T_PageDirectory) KERNEL_PD_ADDR; + PageTable = (T_PageTable) KERNEL_PT_ADDR; + + /* On initialise le PageDirectory du kernel */ + for(i = 0; i < MAX_PT_COUNT; i++) + { + if(i < KERNEL_SPACE_PT_COUNT) + { + PageDirectory[i] = KERNEL_PT_ADDR + i * PT_SIZE; + PageDirectory[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW; + } + else + { + PageDirectory[i] = 0; + } + } + + /* On initialise les tables de pages du kernel */ + for(i = 0; i < KERNEL_SPACE_PAGE_COUNT; i++) + { + if(i < KERNEL_PHY_SPACE_PAGE_COUNT) + { + PageTable[i] = i * PAGE_SIZE; + PageTable[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW; + } + else + { + PageTable[i] = 0; + } + } + + /* ============================================== */ + + + + /* ==== On initialise la table d'état des pages physiques en utilisant la Memory Map ==== */ + + PageMap = (bits8*) PHY_PAGE_MAP_ADDR; + + for(i = 0; i < MAX_PAGE_COUNT; i++) /* Initialisation */ + { + PageMap[i] = PAGE_NOT_PRESENT; + } + /* On parcout la Memory Map */ + for(i = 0; i < arg->memListEntryNumber; i++) + { + /* On calcul le numéro de la page de base puis la taille en nombre de page */ + page = arg->memMap[i].baseAddr_1 / PAGE_SIZE; + size = arg->memMap[i].size_1 / PAGE_SIZE; + + if(arg->memMap[i].size_1 % PAGE_SIZE > 0) + { + size++; + } + + /* Si la zone mémoire est utilisable */ + if(arg->memMap[i].type == 1) + { + /* On parcourt la section de la table d'état correspondant à la zone mémoire */ + for(j = page; j < page + size; j++) + { + PageMap[j] = FREE; + } + } + } + + /* =============================================================== */ + + + /* ===== Structures d'allocation ===== */ + + KERNEL_HEAP_BASE = KERNEL_PHY_SPACE_PAGE_COUNT << PAGE_OFFSET_BITS; + if(!KernelAddPage(KERNEL_HEAP_BASE)) + { + fatalError("MEGA ERROR OF DEATH !!"); + } + KERNEL_HEAP_LIMIT = KERNEL_HEAP_BASE + PAGE_SIZE; + + struct AllocAreaModel *firstArea = (struct AllocAreaModel*) KERNEL_HEAP_BASE; + firstArea->state = 0; + firstArea->next = 0; + + /* ================================================================= */ + + + PhyPageMapMutex = 0; + KernPageTableMutex = 0; + AllocMutex = 0; +} + +unsigned int KernelAddPage(T_Page addr) +{ + unsigned int vpage = addr >> PAGE_OFFSET_BITS; + unsigned int ret; + + if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT) + { + IPC_MutexLock(&KernPageTableMutex); + if(PageTable[vpage] == 0) + { + PageTable[vpage] = GetPhyPage(); + if(PageTable[vpage]) + { + PageTable[vpage] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW; + ret = 1; + } + else + { + ret = 0; + } + } + else + { + print("[KernelAddPage] vaddr = 0x%x is already used\n", 0x47, addr); + ret = 0; + } + IPC_MutexUnlock(&KernPageTableMutex); + } + else + { + print("[KernelAddPage] vaddr = 0x%x isn't in virtual kernel space\n", 0x47, addr); + ret = 0; + } + return ret; +} + +void KernelRemovePage(T_Page vaddr) +{ + unsigned int vpage = vaddr >> PAGE_OFFSET_BITS; + + if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT) + { + IPC_MutexLock(&KernPageTableMutex); + if(PageTable[vpage] != 0) + { + ReleasePhyPage(PageTable[vpage] & 0xFFFFF000); + PageTable[vpage] = 0; + _EmptyTLB(); + } + else + { + print("[KernelRemovePage] vaddr = 0x%x is already released\n", 0x47); + } + IPC_MutexUnlock(&KernPageTableMutex); + } + else + { + print("[KernelRemovePage] vaddr = 0x%x isn't in virtual kernel space\n", 0x47); + } +} + +T_Page KernelGetPage() +{ + unsigned int i; + T_Page ret; + + for(i = KERNEL_SPACE_PAGE_COUNT - 1; i >= KERNEL_HEAP_LIMIT >> PAGE_OFFSET_BITS; i--) + { + IPC_MutexLock(&KernPageTableMutex); + if(PageTable[i] == 0) + { + PageTable[i] = GetPhyPage(); + if(PageTable[i]) + { + PageTable[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW; + ret = i << PAGE_OFFSET_BITS; + } + else + { + ret = 0; + } + IPC_MutexUnlock(&KernPageTableMutex); + break; + } + else + { + ret = 0; + } + IPC_MutexUnlock(&KernPageTableMutex); + } + return ret; +} + +void* KernelGetPhyAddr(void *vaddr) +{ + unsigned int vpage = (unsigned int) vaddr >> PAGE_OFFSET_BITS; + void *ret; + + if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT) + { + IPC_MutexLock(&KernPageTableMutex); + if(PageTable[vpage]) + { + ret = (void*) (PageTable[vpage] & 0xFFFFF000 | (unsigned int) vaddr & 0x00000FFF); + } + else + { + ret = 0; + } + IPC_MutexUnlock(&KernPageTableMutex); + } + else + { + ret = 0; + } + return ret; +} + +T_Page GetPhyPage() +{ + unsigned int i; + for(i = KERNEL_PHY_SPACE_PAGE_COUNT; i < MAX_PAGE_COUNT; i++) + { + IPC_MutexLock(&PhyPageMapMutex); + if(PageMap[i] == FREE) + { + PageMap[i] = USED; + IPC_MutexUnlock(&PhyPageMapMutex); + return i << PAGE_OFFSET_BITS; + } + IPC_MutexUnlock(&PhyPageMapMutex); + } + print("[GetPhyPage] no enough physical pages\n", 0x47); + return 0; +} + +void ReleasePhyPage(T_Page addr) +{ + unsigned int page = addr >> PAGE_OFFSET_BITS; + + if(page >= KERNEL_PHY_SPACE_PAGE_COUNT) + { + IPC_MutexLock(&PhyPageMapMutex); + if(PageMap[page] != PAGE_NOT_PRESENT) + { + PageMap[page] = FREE; + } + else + { + print("[ReleasePhyPage] unable to release a not present page\n", 0x47); + } + IPC_MutexUnlock(&PhyPageMapMutex); + } + else + { + print("[ReleasePhyPage] unable to release a kernel physical page\n", 0x47); + } +} + +void* malloc(unsigned int size) +{ + IPC_MutexLock(&AllocMutex); + + struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE; + void *ptr = 0; + + start: + + while(area != 0) + { + if(((unsigned int) area + sizeof(struct AllocAreaModel) < KERNEL_HEAP_LIMIT)) + { + if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT) + { + fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED"); + } + + if(area->state == FREE) + { + unsigned int areaBase = (unsigned int) area + sizeof(struct AllocAreaModel); + unsigned int areaSize; + + if(area->next == 0) + { + areaSize = KERNEL_HEAP_LIMIT - areaBase; + } + else + { + areaSize = (unsigned int) area->next - areaBase; + } + + if(areaSize == size) + { + area->state = USED; + ptr = (void*) areaBase; + break; + } + else if(areaSize > size) + { + struct AllocAreaModel *newArea = (struct AllocAreaModel*) (areaBase + size); + + if(newArea + sizeof(struct AllocAreaModel) < (struct AllocAreaModel*) KERNEL_HEAP_LIMIT) + { + newArea->state = FREE; + newArea->next = area->next; + area->next = newArea; + } + else + { + area->next = 0; + } + area->state = USED; + ptr = (void*) areaBase; + break; + } + } + } + else + { + fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED"); + } + area = area->next; + } + + if(!ptr) + { + area = EnlargeHeap(); + if(area) + { + goto start; + } + } + + /*print("MALLOC -> ", 0x04); + area = KERNEL_HEAP_BASE; + while(area) + { + print("base : 0x%x, next : 0x%x, state : %d\n", 0x04, (unsigned int) area + sizeof(struct AllocAreaModel), area->next, area->state); + area = area->next; + }*/ + + IPC_MutexUnlock(&AllocMutex); + return ptr; +} + +void free(void *addr) +{ + IPC_MutexLock(&AllocMutex); + + struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE; + + while(area != 0) + { + if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT) + { + fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED"); + } + + if(area->state == USED) + { + unsigned int areaBase = (unsigned int) area + sizeof(struct AllocAreaModel); + if(areaBase == (unsigned int) addr) + { + area->state = FREE; + + while(area->next != 0) + { + if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT) + { + fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED"); + } + + if(area->next->state == FREE) + { + area->next = area->next->next; + } + else + { + break; + } + } + + IPC_MutexUnlock(&AllocMutex); + return; + } + } + area = area->next; + } + + /*print("FREE -> ", 0x04); + area = KERNEL_HEAP_BASE; + while(area) + { + print("base : 0x%x, next : 0x%x, state : %d\n", 0x04, (unsigned int) area + sizeof(struct AllocAreaModel), area->next, area->state); + area = area->next; + }*/ + fatalError("IMPOSSIBLE TO FREE MEMORY"); + IPC_MutexUnlock(&AllocMutex); +} + +struct AllocAreaModel* EnlargeHeap() +{ + if(KernelAddPage(KERNEL_HEAP_LIMIT)) + { + struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE; + while(area->next != 0) + { + area = area->next; + } + + struct AllocAreaModel *lastArea = area; + + if(area->state == USED) + { + lastArea = (struct AllocAreaModel*) KERNEL_HEAP_LIMIT; + lastArea->next = 0; + lastArea->state = FREE; + + area->next = lastArea; + } + KERNEL_HEAP_LIMIT += PAGE_SIZE; + return lastArea; + } + else + { + print("[EnlargeHeap] unable to enlarge kernel heap, no enough kernel pages\n", 0x47); + return 0; + } +} + +T_PageDirectory CreateTaskPageDirectory() +{ + /* #-----# 0xFFFFFFFF + * |-----| pageDir user + * | | + * | | + * | | + * | | + * | | + * |-----| + * | | + * #-----# espace noyau */ + + + unsigned int i; + T_PageDirectory PageDir = (T_PageDirectory) KernelGetPage(); + + if(PageDir) + { + for(i = 0; i < MAX_PT_COUNT; i++) /* Initialisation du répertoire de pages*/ + { + PageDir[i] = 0; + } + + for(i = 0; i < KERNEL_SPACE_PT_COUNT; i++) /* Construction de la partie noyau */ + { + PageDir[i] = PageDirectory[i]; + } + + /* La table de pages 1023 couvre le PageDir et les table de pages, de 0xFFC00000 à 0xFFFFFFFF */ + + PageDir[1023] = (T_Page) KernelGetPhyAddr(PageDir); + PageDir[1023] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW; + return PageDir; + } + else + { + return 0; + } +} + +void DestroyTaskPageDirectory(T_PageDirectory PageDir) +{ + unsigned int i; + for(i = KERNEL_SPACE_PAGE_COUNT; i < MAX_PT_COUNT; i++) + { + if(PageDir[i]) + { + ReleasePhyPage(PageDir[i] & 0xFFFFF000); + } + } + + KernelRemovePage((T_Page) PageDir); +} + +/* Alloue une nouvelle page physique et la fait correspondre à l'adresse virtuelle vaddr */ +unsigned int AddPage(T_Page vaddr, bits32 perm) +{ + unsigned int i; + + T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000; + T_PageTable PageTableAddr; + T_PageTable PageTableVaddr; + bits32 ptNum = (vaddr & 0xFFC00000) >> 22; + bits32 pgNum = (vaddr & 0x003FF000) >> 12; + + /* On regarde si la table de pages est créée */ + if(PageDir[ptNum] == 0) /* Si elle n'éxiste pas */ + { + /* On créé la table de pages */ + PageTableAddr = (T_PageTable) GetPhyPage(); /* Adresse physique, donc inaccessible ici */ + if(PageTableAddr) + { + /* On ajoute la table de pages crée dans le répertoire */ + PageDir[ptNum] = (T_Page) PageTableAddr; + PageDir[ptNum] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER; + + PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On accède à la table de pages depuis l'espace de mappage virtuel */ + + for(i = 0; i < 1024; i++) + { + PageTableVaddr[i] = 0; + } + + PageTableVaddr[pgNum] = GetPhyPage(); + if(PageTableVaddr[pgNum]) + { + PageTableVaddr[pgNum] |= perm; + return 1; + } + else + { + PageDir[ptNum] = 0; + ReleasePhyPage((T_Page) PageTableAddr); + _EmptyTLB(); + return 0; + } + } + else + { + return 0; + } + + } + else /* Si elle éxiste */ + { + PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On accède à la table de pages depuis l'espace de mappage virtuel */ + + /* On test pour savoir si la page voulue est déjà présente */ + if(PageTableVaddr[pgNum] == 0) + { + /* Si elle ne l'est pas on ajoute à la table de pages la page voulue */ + PageTableVaddr[pgNum] = GetPhyPage(); + if(PageTableVaddr[pgNum]) + { + PageTableVaddr[pgNum] |= perm; + return 1; + } + else + { + return 0; + } + } + else + { + return 0; + } + } +} + +void RemovePage(T_Page vaddr) +{ + unsigned int i; + + T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000; + T_PageTable PageTable; + int empty; + bits32 ptNum = (vaddr & 0xFFC00000) >> 22; + bits32 pgNum = (vaddr & 0x003FF000) >> 12; + + if(PageDir[ptNum] != 0) + { + PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); + if(PageTable[pgNum] != 0) + { + ReleasePhyPage(PageTable[pgNum] & 0xFFFFF000); + PageTable[pgNum] = 0; + + for(i = 0; i < PAGE_PER_PT; i++) + { + if(PageTable[i] == 0) + { + empty = 1; + } + else + { + empty = 0; + break; + } + } + + if(empty) + { + ReleasePhyPage(PageDir[ptNum] & 0xFFFFF000); + PageDir[ptNum] = 0; + } + _EmptyTLB(); + } + } +} + +unsigned int LinkPhyPage(T_Page vaddr, T_Page addr, bits32 perm) +{ + unsigned int i; + + T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000; + T_PageTable PageTableAddr; + T_PageTable PageTableVaddr; + bits32 ptNum = (vaddr & 0xFFC00000) >> 22; + bits32 pgNum = (vaddr & 0x003FF000) >> 12; + + /* On regarde si la table de pages est créée */ + if(PageDir[ptNum] == 0) /* Si elle n'éxiste pas */ + { + /* On créé la table de pages */ + PageTableAddr = (T_PageTable) GetPhyPage(); /* Adresse physique, donc inaccessible ici */ + if(PageTableAddr) + { + /* On ajoute la table de pages crée dans le répertoire */ + PageDir[ptNum] = (T_Page) PageTableAddr; + PageDir[ptNum] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER; + + PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On accède à la table de pages depuis l'espace de mappage virtuel */ + + for(i = 0; i < 1024; i++) + { + PageTableVaddr[i] = 0; + } + + PageTableVaddr[pgNum] = addr & 0xFFFFF000; + PageTableVaddr[pgNum] |= perm; + return 1; + } + else + { + return 0; + } + + } + else /* Si elle éxiste */ + { + PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On accède à la table de pages depuis l'espace de mappage virtuel */ + + /* On test pour savoir si la page voulue est déjà présente */ + if(PageTableVaddr[pgNum] == 0) + { + /* Si elle ne l'est pas on ajoute à la table de pages la page voulue */ + PageTableVaddr[pgNum] = addr & 0xFFFFF000; + PageTableVaddr[pgNum] |= perm; + return 1; + } + else + { + return 0; + } + } +} + +void UnlinkPhyPage(T_Page vaddr) +{ + unsigned int i; + + T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000; + T_PageTable PageTable; + int empty; + bits32 ptNum = (vaddr & 0xFFC00000) >> 22; + bits32 pgNum = (vaddr & 0x003FF000) >> 12; + + if(PageDir[ptNum] != 0) + { + PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); + if(PageTable[pgNum] != 0) + { + PageTable[pgNum] = 0; + for(i = 0; i < PAGE_PER_PT; i++) + { + if(PageTable[i] == 0) + { + empty = 1; + } + else + { + empty = 0; + break; + } + } + + if(empty) + { + ReleasePhyPage(PageDir[ptNum] & 0xFFFFF000); + PageDir[ptNum] = 0; + } + _EmptyTLB(); + } + } +} + +void* GetPhyAddr(void *vaddr) +{ + T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000; + T_PageTable PageTable; + bits32 ptNum = ((bits32) vaddr & 0xFFC00000) >> 22; + bits32 pgNum = ((bits32) vaddr & 0x003FF000) >> 12; + bits32 offset = (bits32) vaddr & 0x00000FFF; /* Offset par rapport au début de la page */ + + if(PageDir[ptNum] != 0) + { + PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); + if(PageTable[pgNum] != 0) + { + return (void*) (PageTable[pgNum] & 0xFFFFF000 | offset); + } + } + + return 0; +} diff --git a/kernel/src/print.c b/kernel/src/print.c new file mode 100644 index 0000000..293de5b --- /dev/null +++ b/kernel/src/print.c @@ -0,0 +1,129 @@ +/* print.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "print.h" + +#include "types.h" +#include "utils.h" +#include "asm_x86.h" + +#include + +static printArgs(char* str, T_byte color, va_list args) { +} + +void fatalError(char *str) +{ + print("FATAL ERROR : %s\n", 0x47, str); + _ClearInterrupt(); + asm("hlt"); +} + +void putc(char c) { + +} + +void print(char *str, char color, ...) +{ + va_list arg; + va_start(arg, color); + + while(*str != 0) + { + if(*str == '%') + { + if(str[1] == 'd') + { + printDec(va_arg(arg, bits32), color); + str+=2; + } + else if(str[1] == 'x') + { + printHex(va_arg(arg, bits32), color); + str+=2; + } + else if(str[1] == 'b') + { + printBin(va_arg(arg, bits32), color); + str+=2; + } + else if(str[1] == 's') + { + print(va_arg(arg, char*), color); + str+=2; + } + else + { + PutCharVterm('%', color, VirtualTerminal_0); + str++; + } + } + else + { + putcVterm(*str, color, VirtualTerminal_0); + str++; + } + } + + va_end(arg); +} + +void printDec(bits32 a, char color) +{ + char buffer[11]; + char *str = buffer; + + IntToChar(a, str, 10); + + while(*str != 0) + { + PutCharVterm(*str, color, VirtualTerminal_0); + str++; + } +} + +void printHex(bits32 a, char color) +{ + char buffer[9]; + char *str = buffer; + + IntToChar(a, str, 16); + + while(*str != 0) + { + PutCharVterm(*str, color, VirtualTerminal_0); + str++; + } +} + +void printBin(bits32 a, char color) +{ + char buffer[33]; + char *str = buffer; + + IntToChar(a, str, 2); + + while(*str != 0) + { + PutCharVterm(*str, color, VirtualTerminal_0); + str++; + } +} diff --git a/kernel/src/process.c b/kernel/src/process.c new file mode 100644 index 0000000..3e0ae53 --- /dev/null +++ b/kernel/src/process.c @@ -0,0 +1,408 @@ +/* process.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#define PROCESS_PRIVATE +#include "process.h" + +#include "types.h" +#include "display.h" +#include "asm_x86.h" +#include "memory.h" +#include "utils.h" +#include "args.h" +#include "elf_loader.h" + +void Process_0_Task(); + + +void InitProcessManager() +{ + Process_0.pid = 0; + Process_0.reg_EAX = 0x00; + Process_0.reg_EBX = 0x00; + Process_0.reg_ECX = 0x00; + Process_0.reg_EDX = 0x00; + Process_0.reg_ESI = 0x00; + Process_0.reg_EDI = 0x00; + Process_0.reg_EBP = 0x00; + Process_0.reg_ESP = MAIN_KERNEL_STACK; + Process_0.reg_CS = 0x08; + Process_0.reg_DS = 0x10; + Process_0.reg_ES = 0x10; + Process_0.reg_FS = 0x10; + Process_0.reg_GS = 0x10; + Process_0.reg_SS = 0x18; + Process_0.reg_EIP = (bits32) &Process_0_Task; + Process_0.reg_EFLAGS = 0x200; + Process_0.pageDir = (T_PageDirectory) KERNEL_PD_ADDR; + Process_0.reg_CR3 = KERNEL_PD_ADDR; + Process_0.kernelStackPtr = MAIN_KERNEL_STACK; + + /* Pas de mode user, donc pas de régions */ + Process_0.processRegionsList.firstEntry = 0; + Process_0.processRegionsList.lastEntry = 0; + Process_0.processRegionsList.entryCount = 0; + + Process_0.parent = 0; /* Pas de parent */ + Process_0.processChildrenList.firstEntry = 0; + Process_0.processChildrenList.lastEntry = 0; + Process_0.processChildrenList.entryCount = 0; + + Process_0.signal = 0; + + Process_0.status = PROCESS_STATUS_RUNNING; + Process_0.ipcWaitMutex = 0; + Process_0.ipcInSection = 0; + + Processes.firstEntry = 0; + Processes.lastEntry = 0; + Processes.entryCount = 0; + LinkedListPushBack(&Process_0, &Processes); + + PidCounter = 1; +} + +unsigned int CreateProcess(void *file) +{ + unsigned int i; + + /* On initialise une entrée dans la table des processus */ + T_Process* process = malloc(sizeof(T_Process)); + struct ProcessChild* child = malloc(sizeof(struct ProcessChild)); + if(!process || !child) + { + if(child) + { + free(child); + } + if(process) + { + free(process); + } + print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47); + return 0; + } + + process->pid = PidCounter; + process->status = PROCESS_STATUS_RUNNING; + process->ipcWaitMutex = 0; + process->ipcInSection = 0; + + process->processRegionsList.firstEntry = 0; + process->processRegionsList.lastEntry = 0; + process->processRegionsList.entryCount = 0; + + child->process = process; + process->parent = CurrentProcess; + process->processChildrenList.firstEntry = 0; + process->processChildrenList.lastEntry = 0; + process->processChildrenList.entryCount = 0; + + process->signal = 0; + + process->reg_EAX = 0x00; + process->reg_EBX = 0x00; + process->reg_ECX = 0x00; + process->reg_EDX = 0x00; + process->reg_ESI = 0x00; + process->reg_EDI = 0x00; + process->reg_EBP = 0x00; + process->reg_ESP = (bits32) USER_STACK_ADDR + PAGE_SIZE; + process->reg_CS = 0x23; + process->reg_DS = 0x2B; + process->reg_ES = 0x2B; + process->reg_FS = 0x2B; + process->reg_GS = 0x2B; + process->reg_SS = 0x33; + process->reg_EFLAGS = 0x200; + /* ======================================================= */ + + /* On créé le répertoire de pages */ + process->pageDir = CreateTaskPageDirectory(); + if(!process->pageDir) + { + free(process); + free(child); + print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47); + return 0; + } + + process->reg_CR3 = (bits32) KernelGetPhyAddr(process->pageDir); + /* ================================================= */ + + /* La pile noyau */ + process->kernelStackPtr = KernelGetPage(); + if(!process->kernelStackPtr) + { + DestroyTaskPageDirectory(process->pageDir); + free(process); + free(child); + print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47); + return 0; + } + process->kernelStackPtr += PAGE_SIZE; + /* ================================================== */ + + /* On change d'espace d'adressage */ + bits32 cr3 = _ReadCr3(); + CurrentProcess->reg_CR3 = process->reg_CR3; + _LoadCr3(process->reg_CR3); + + + /* On créé la pile utilisateur */ + if(!AddPage((T_Page) USER_STACK_ADDR, PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER)) + { + CurrentProcess->reg_CR3 = cr3; + _LoadCr3(cr3); + KernelRemovePage(process->kernelStackPtr - PAGE_SIZE); + DestroyTaskPageDirectory(process->pageDir); + free(process); + free(child); + print("[CreateProcess] unable to create process, not enough memory\n", 0x47); + return 0; + } + /* ====================================================== */ + + process->reg_EIP = ELF32_Load(file, &process->processRegionsList); + if(!process->reg_EIP) + { + RemovePage((T_Page) USER_STACK_ADDR); + CurrentProcess->reg_CR3 = cr3; + _LoadCr3(cr3); + KernelRemovePage(process->kernelStackPtr - PAGE_SIZE); + DestroyTaskPageDirectory(process->pageDir); + free(process); + free(child); + print("[CreateProcess] unable to create process, elf error\n", 0x47); + return 0; + } + + /* On restaure l'espace d'adressage */ + CurrentProcess->reg_CR3 = cr3; + _LoadCr3(cr3); + + /* On met à jour les tables */ + PidCounter++; + LinkedListPushBack(child, &CurrentProcess->processChildrenList); + LinkedListPushBack(process, &Processes); + + print("[CreateProcess] new process created with PID %d\n", DEFAULT_COLOR, process->pid); + return 1; +} + + +void DestroyProcess() +{ + + /*unsigned int i; + for(i = 0; i < ProcessNumber; i++) + { + struct ProcessModel *process = GetEntry(i, &Processes); + if(process == CurrentProcess) + { + unsigned int j; + print("Stopping process with PID %d\n", DEFAULT_COLOR, CurrentProcess->pid); + + for(j = 0; j < CurrentProcess->codePageCount; j++) + { + RemovePage((bits32) USER_SPACE_BASE_ADDR + (j * PAGE_SIZE)); + } + + + for(j = 0; j < CurrentProcess->allocatedPageCount; j++) + { + struct ProcessAllocatedPageModel *page = GetEntry(0, &CurrentProcess->allocatedPageList); + RemovePage(page->page_vaddr); + free(page); + RemoveEntry(0, &CurrentProcess->allocatedPageList); + } + + RemovePage((bits32) USER_STACK_ADDR); + CurrentProcess->status = PROCESS_STATUS_ZOMBIE; + while(1) + { + asm("hlt"); + } + KernelRemovePage(CurrentProcess->kernelStackPtr - PAGE_SIZE); + DestroyTaskPageDirectory(CurrentProcess->pageDir); + free(process); + + + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + RemoveEntry(i, &Processes); + ProcessNumber--; + _RestoreEflags(eflags) + } + }*/ +} + +void Process_0_Task() +{ + print("[God] create Init process with PID 1\n", DEFAULT_COLOR); + CreateProcess((void*) arg->initProcessAddr); + + while(1) + { + asm("hlt"); + } +} + + +unsigned int ProcessCreateRegion_RO(T_Page startPage, T_Page* pglist, unsigned int pageCount, T_LinkedList* regionsList) +{ + startPage &= 0xFFFFF000; + T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS); + + if(!pageCount || startPage < USER_SPACE_BASE_ADDR || startPage >= USER_SPACE_END_ADDR || endPage >= USER_SPACE_END_ADDR) + { + print("[ProcessCreateRegion_RO] invalid region location\n", 0x47); + return 0; + } + + struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry; + while(entry) + { + if(endPage > entry->startPage && endPage <= entry->endPage + || startPage >= entry->startPage && startPage < entry->endPage + || startPage <= entry->startPage && endPage >= entry->endPage) + { + print("[ProcessCreateRegion_RO] conflict between regions\n", 0x47); + return 0; + } + entry = entry->next; + } + + unsigned int i, pc; + for(i = 0, pc = 0; i < pageCount; i++, pc++) + { + if(!LinkPhyPage(startPage + (i << PAGE_OFFSET_BITS), pglist[i] & 0xFFFFF000, PAGE_FLAG_PRESENT | PAGE_FLAG_USER)) + { + goto error; + } + } + + struct ProcessRegion* region = malloc(sizeof(struct ProcessRegion)); + if(region) + { + region->startPage = startPage; + region->endPage = endPage; + region->type = (unsigned char) PROCESS_REGION_RO; + LinkedListPushBack(region, regionsList); + return 1; + } + + error: + print("[ProcessCreateRegion_RO] unable to add region\n", 0x47); + for(i = 0; i < pc; i++) + { + UnlinkPhyPage(startPage + (i << PAGE_OFFSET_BITS)); + } + return 0; +} + +unsigned int ProcessCreateRegion_RW(T_Page startPage, unsigned int pageCount, T_LinkedList* regionsList) +{ + startPage &= 0xFFFFF000; + T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS); + + if(!pageCount || startPage < USER_SPACE_BASE_ADDR || startPage >= USER_SPACE_END_ADDR || endPage >= USER_SPACE_END_ADDR) + { + print("[ProcessCreateRegion_RW] invalid region location\n", 0x47); + return 0; + } + + struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry; + while(entry) + { + if(endPage > entry->startPage && endPage <= entry->endPage + || startPage >= entry->startPage && startPage < entry->endPage + || startPage <= entry->startPage && endPage >= entry->endPage) + { + print("[ProcessCreateRegion_RW] conflict between regions\n", 0x47); + return 0; + } + entry = entry->next; + } + + unsigned int i, pc; + for(i = 0, pc = 0; i < pageCount; i++, pc++) + { + if(!AddPage(startPage + (i << PAGE_OFFSET_BITS), PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER)) + { + goto error; + } + } + + struct ProcessRegion* region = malloc(sizeof(struct ProcessRegion)); + if(region) + { + region->startPage = startPage; + region->endPage = endPage; + region->type = (unsigned char) PROCESS_REGION_RW; + LinkedListPushBack(region, regionsList); + return 1; + } + + error: + print("[ProcessCreateRegion_RW] unable to add region\n", 0x47); + for(i = 0; i < pc; i++) + { + RemovePage(startPage + (i << PAGE_OFFSET_BITS)); + } + return 0; +} + +void ProcessRemoveRegion(T_Page startPage, unsigned int pageCount, T_LinkedList* regionsList) +{ + startPage &= 0xFFFFF000; + T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS); + + struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry; + while(entry) + { + if(startPage == entry->startPage && endPage == entry->endPage) + { + unsigned int i; + if(entry->type == PROCESS_REGION_RO) + { + for(i = 0; i < pageCount; i++) + { + UnlinkPhyPage(startPage + (i << PAGE_OFFSET_BITS)); + } + LinkedListRemove(entry, regionsList); + free(entry); + break; + } + else if(entry->type == PROCESS_REGION_RW) + { + for(i = 0; i < pageCount; i++) + { + RemovePage(startPage + (i << PAGE_OFFSET_BITS)); + } + LinkedListRemove(entry, regionsList); + free(entry); + break; + } + } + entry = entry->next; + } +} diff --git a/kernel/src/scheduler.c b/kernel/src/scheduler.c new file mode 100644 index 0000000..40a8494 --- /dev/null +++ b/kernel/src/scheduler.c @@ -0,0 +1,173 @@ +/* scheduler.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "process.h" + +#include "types.h" +#include "asm_x86.h" +#include "interrupt.h" +#include "signal.h" + +T_Process* SchedulingAlgorithm() +{ + T_Process *process = CurrentProcess; + + do + { + if(process->next) + { + process = process->next; + } + else + { + process = (T_Process*) Processes.firstEntry; + } + + if(process != CurrentProcess) + { + unsigned int i; + for(i = 0; i < 32; i++) + { + if(FetchSignal(i, process)) + { + HandleSignal(i, process); + break; + } + } + + if(process->status == PROCESS_STATUS_RUNNING) + { + return process; + } + else if(process->status == PROCESS_STATUS_WAIT_MUTEX) /* Si on attend un mutex */ + { + /* On regard son etat */ + if(!(*process->ipcWaitMutex)) + { + process->status = PROCESS_STATUS_RUNNING; + *process->ipcWaitMutex = 1; + process->ipcWaitMutex = 0; + process->ipcInSection++; + return process; + } + } + /*else if(process->status == PROCESS_STATUS_SLEEP) si le processus est en sommeil + { + On regard si un wakeup à été envoyé + }*/ + } + else + { + break; + } + }while(1); + + if(Process_0.status == PROCESS_STATUS_RUNNING) + { + return &Process_0; + } + else + { + return CurrentProcess; + } +} + +void Schedule() +{ + bits32 *context = _SaveContex(); + bits32 *curStackFrame = (bits32*) _GetStackFrameAddr(0); + _ClearInterrupt(); + + CurrentProcess->reg_GS = (bits16) context[0]; + CurrentProcess->reg_FS = (bits16) context[1]; + CurrentProcess->reg_ES = (bits16) context[2]; + CurrentProcess->reg_DS = (bits16) context[3]; + CurrentProcess->reg_EDI = context[4]; + CurrentProcess->reg_ESI = context[5]; + CurrentProcess->reg_EBP = curStackFrame[0]; /* ebp de la fonction précédente */ + CurrentProcess->reg_EBX = context[8]; + CurrentProcess->reg_EDX = context[9]; + CurrentProcess->reg_ECX = context[10]; + CurrentProcess->reg_EAX = context[11]; + CurrentProcess->reg_EIP = curStackFrame[1]; /* eip de retour */ + CurrentProcess->reg_CS = 0x08; + CurrentProcess->reg_EFLAGS = (context[12] | 0x200) & 0xFFFFBFFF; + CurrentProcess->reg_ESP = (bits32) &curStackFrame[2]; + CurrentProcess->reg_SS = 0x18; + + CurrentProcess = SchedulingAlgorithm(); + + tss->ss0 = 0x18; + tss->esp0 = CurrentProcess->kernelStackPtr; + _LoadContext(CurrentProcess); +} + +void ScheduleAtClock() +{ + if(!CurrentProcess && Processes.entryCount > 0) + { + CurrentProcess = (T_Process*) Processes.firstEntry; + } + else if(Processes.entryCount <= 1) + { + return; + } + else if(Processes.entryCount > 1) + { + bits32 *context = (bits32*) (_GetStackFrameAddr(1) + 8); + + /* Registre empilés manuellement */ + CurrentProcess->reg_GS = (bits16) context[0]; + CurrentProcess->reg_FS = (bits16) context[1]; + CurrentProcess->reg_ES = (bits16) context[2]; + CurrentProcess->reg_DS = (bits16) context[3]; + CurrentProcess->reg_EDI = context[4]; + CurrentProcess->reg_ESI = context[5]; + CurrentProcess->reg_EBP = context[6]; + /* ESP context[7] inutile */ + CurrentProcess->reg_EBX = context[8]; + CurrentProcess->reg_EDX = context[9]; + CurrentProcess->reg_ECX = context[10]; + CurrentProcess->reg_EAX = context[11]; + + /* registres empliés automatiquement */ + CurrentProcess->reg_EIP = context[12]; + CurrentProcess->reg_CS = (bits16) context[13]; + CurrentProcess->reg_EFLAGS = (context[14] | 0x200) & 0xFFFFBFFF; + + if(CurrentProcess->reg_CS == 0x08) + { + CurrentProcess->reg_ESP = (bits32) &context[15]; + CurrentProcess->reg_SS = 0x18; + } + else + { + CurrentProcess->reg_ESP = context[15]; + CurrentProcess->reg_SS = (bits16) context[16]; + } + + CurrentProcess = SchedulingAlgorithm(); + } + tss->ss0 = 0x18; + tss->esp0 = CurrentProcess->kernelStackPtr; + PIC_Send_EOI(); + _LoadContext(CurrentProcess); +} diff --git a/kernel/src/signal.c b/kernel/src/signal.c new file mode 100644 index 0000000..a78e546 --- /dev/null +++ b/kernel/src/signal.c @@ -0,0 +1,79 @@ +/* signal.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "signal.h" + +#include "process.h" + +void SendSignal(unsigned int num, T_Process* process) +{ + if(num < 32) + { + process->signal |= (1 << num); + } +} + +void ClearSignal(unsigned int num, T_Process* process) +{ + if(num < 32) + { + process->signal &= ~(1 << num); + } +} + +unsigned int FetchSignal(unsigned int num, T_Process* process) +{ + if(num < 32) + { + if(process->signal & (1 << num)) + { + return 1; + } + else + { + return 0; + } + } +} + +void HandleSignal(unsigned int signal, T_Process* process) +{ + switch(signal) + { + case SIGNAL_KILL: + print("Process with PID %d received the signal 0 (KILL)\n", DEFAULT_COLOR, process->pid); + break; + + case SIGNAL_TERM: + print("Process with PID %d received the signal 1 (TERM)\n", DEFAULT_COLOR, process->pid); + break; + + case SIGNAL_KCHILD: + print("Process with PID %d received the signal 2 (KCHILD)\n", DEFAULT_COLOR, process->pid); + break; + + default: + print("Process with PID %d received an unknown signal\n", DEFAULT_COLOR, process->pid); + break; + } + + ClearSignal(signal, process); +} diff --git a/kernel/src/systemCall.c b/kernel/src/systemCall.c new file mode 100644 index 0000000..49e0181 --- /dev/null +++ b/kernel/src/systemCall.c @@ -0,0 +1,72 @@ +/* systemCall.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "types.h" +#include "print.h" +#include "process.h" +#include "asm_x86.h" + +void ExecSystemCall(int sc_num) +{ + bits8 *arg; + int i; + unsigned int a = 1; + switch(sc_num) + { + case 1: + asm("mov %%ebx, %0" :: "m" (arg)); + PutCharVterm(*arg, 0x0F, CurrentProcess->vterm); + break; + + case 2: + asm("mov %%ebx, %0" :: "m" (arg)); + ReadInputVterm(arg, CurrentProcess->vterm); + break; + + case 3: + /*asm("mov %%ebx, %0" :: "m" (arg)); + if(!CreateProcess(arg, 1)) + { + CurrentProcess->status = 2; + Schedule(); + }*/ + break; + + case 4: + DestroyProcess(); + + case 5: + CurrentProcess->status = 2; + Schedule(); + /*while(CurrentProcess->status == 2) + { + asm("hlt"); + }*/ + break; + + default: + print("ERREUR : UNKNOW SYSTEM CALL !\n", 0x47); + _ClearInterrupt(); + asm("hlt"); + break; + } + return; +} diff --git a/kernel/src/utils.c b/kernel/src/utils.c new file mode 100644 index 0000000..a7a6575 --- /dev/null +++ b/kernel/src/utils.c @@ -0,0 +1,321 @@ +/* utils.c - This file is a part of NutsOS + * + * NutsOS + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * NutsOS 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. + * + * NutsOS 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 NutsOS; If not, see . + * + * Valentin Verdier + */ + +#include "utils.h" + +#include "types.h" +#include "asm_x86.h" + +void memcopy(char *src, char *dst, unsigned int n) +{ + unsigned int i; + for(i = 0; i < n; i++) + { + dst[i] = src[i]; + } +} + +int strcmp(char *str1, char *str2) +{ + unsigned int i; + int length1 = 0; + int length2 = 0; + + + while(str1[length1] != 0) + { + length1++; + } + + while(str2[length2] != 0) + { + length2++; + } + + if(length1 == length2) + { + for(i = 0; i < length1; i++) + { + if(str1[i] != str2[i]) + { + return 0; + } + } + } + else + { + return 0; + } + + return 1; +} + +void IntToChar(bits32 num, char *str, int base) +{ + const char digit[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + int i, j, a; + int length; + int tmp = 0; + int counter = 0; + + for(i = 0; i < 10; i++) + { + if(num / expo(base, i) < base) + { + length = i; + break; + } + } + + j = length; + + for(i = 0; i <= length; i++) + { + a = num / expo(base, j); + str[counter] = digit[a - base * tmp]; + tmp = a; + counter++; + j--; + } + str[counter] = 0; +} + +unsigned int expo(unsigned int x, unsigned int y) +{ + if(y > 0) + { + unsigned int i, res = x; + for(i = 1; i < y; i++) + { + res *= x; + } + return res; + } + else + { + return 1; + } +} + +void LinkedListPushFront(void *addr, T_LinkedList *list) +{ + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + + struct ElementModel *entry = addr; + + if(list->entryCount > 0) + { + InsertElement(0, entry, list->firstEntry); + } + else + { + InsertElement(0, entry, 0); + list->lastEntry = entry; + } + list->firstEntry = entry; + list->entryCount++; + + _RestoreEflags(eflags); +} + +void LinkedListPopFront(T_LinkedList *list) +{ + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + + struct ElementModel *nextEntry = list->firstEntry->next; + if(list->entryCount > 1) + { + RemoveElement(list->firstEntry); + list->firstEntry = nextEntry; + } + else + { + list->firstEntry = 0; + list->lastEntry = 0; + } + list->entryCount--; + + _RestoreEflags(eflags); +} + +void LinkedListPushBack(void *addr, T_LinkedList *list) +{ + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + + struct ElementModel *entry = addr; + + if(list->entryCount > 0) + { + InsertElement(list->lastEntry, entry, 0); + } + else + { + InsertElement(0, entry, 0); + list->firstEntry = entry; + } + list->lastEntry = entry; + list->entryCount++; + + _RestoreEflags(eflags); +} + +void LinkedListPopBack(T_LinkedList *list) +{ + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + + struct ElementModel *previousEntry = list->lastEntry->prev; + if(list->entryCount > 1) + { + RemoveElement(list->lastEntry); + list->lastEntry = previousEntry; + } + else + { + list->firstEntry = 0; + list->lastEntry = 0; + } + list->entryCount--; + + _RestoreEflags(eflags); +} + +void LinkedListInsert(void *prev, void *addr, void *next, T_LinkedList *list) +{ + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + + struct ElementModel *previousEntry = prev; + struct ElementModel *entry = addr; + struct ElementModel *nextEntry = next; + + if(nextEntry == list->firstEntry) + { + LinkedListPushFront(entry, list); + } + else if(previousEntry == list->lastEntry) + { + LinkedListPushBack(entry, list); + } + else + { + InsertElement(previousEntry, entry, nextEntry); + list->entryCount++; + } + + _RestoreEflags(eflags); +} + +void LinkedListRemove(void *addr, T_LinkedList *list) +{ + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + + struct ElementModel *entry = addr; + + if(entry == list->firstEntry) + { + LinkedListPopFront(list); + } + else if(entry == list->lastEntry) + { + LinkedListPopBack(list); + } + else + { + RemoveElement(entry); + list->entryCount--; + } + + _RestoreEflags(eflags); +} + +void InsertElement(void *prev, void *addr, void *next) +{ + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + + struct ElementModel *previousEntry = prev; + struct ElementModel *entry = addr; + struct ElementModel *nextEntry = next; + + if(previousEntry) + { + entry->prev = previousEntry; + previousEntry->next = entry; + } + else + { + entry->prev = 0; + } + + if(nextEntry) + { + entry->next = nextEntry; + nextEntry->prev = entry; + } + else + { + entry->next = 0; + } + + _RestoreEflags(eflags); +} + +void RemoveElement(void *addr) +{ + bits32 eflags = _SaveEflags(); + _ClearInterrupt(); + + struct ElementModel *entry = addr; + struct ElementModel *previousEntry = entry->prev; + struct ElementModel *nextEntry = entry->next; + + if(previousEntry) + { + if(nextEntry) + { + previousEntry->next = nextEntry; + } + else + { + previousEntry->next = 0; + } + } + + if(nextEntry) + { + if(previousEntry) + { + nextEntry->prev = previousEntry; + } + else + { + nextEntry->prev = 0; + } + } + + _RestoreEflags(eflags); +} + diff --git a/test/bochsrc b/test/bochsrc new file mode 100644 index 0000000..5d72bd0 --- /dev/null +++ b/test/bochsrc @@ -0,0 +1,45 @@ +config_interface: textconfig +display_library: sdl, options="gui_debug" + +romimage: file="/usr/local/share/bochs/BIOS-bochs-latest" + +cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +#cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor" +#cpuid: mmx=1, apic=xapic, sse=sse2, sse4a=0, misaligned_sse=0, sep=1, movbe=0, adx=0 +#cpuid: aes=0, xsave=0, xsaveopt=0, x86_64=0, 1g_pages=0, pcid=0, fsgsbase=0, smep=0 +#cpuid: smap=0, mwait=0, vmx=0 + +memory: host=64, guest=128 + +vgaromimage: file="/usr/local/share/bochs/VGABIOS-lgpl-latest" +vga: extension=vbe, update_freq=5 + +boot: disk +floppy_bootsig_check: disabled=0 +# no floppya +# no floppyb + +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0 +ata3: enabled=0 + +ata0-master: type=disk, mode=flat, path="disk.img" +ata0-slave: type=none +ata1-master: type=none +ata1-slave: type=none + +pci: enabled=1, chipset=i440fx + +debugger_log: - +private_colormap: enabled=0 +clock: sync=slowdoown, time0=utc + +log: /dev/stdout +debug: action=ignore +info: action=report +error: action=report +panic: action=ask + +keyboard: serial_delay=250, paste_delay=100000 +keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/sdl-pc-us.map diff --git a/test/bochsrc_model b/test/bochsrc_model new file mode 100644 index 0000000..2273793 --- /dev/null +++ b/test/bochsrc_model @@ -0,0 +1,894 @@ +# You may now use double quotes around pathnames, in case +# your pathname includes spaces. + +#======================================================================= +# CONFIG_INTERFACE +# +# The configuration interface is a series of menus or dialog boxes that +# allows you to change all the settings that control Bochs's behavior. +# Depending on the platform there are up to 3 choices of configuration +# interface: a text mode version called "textconfig" and two graphical versions +# called "win32config" and "wx". The text mode version uses stdin/stdout and +# is always compiled in, unless Bochs is compiled for wx only. The choice +# "win32config" is only available on win32 and it is the default there. +# The choice "wx" is only available when you use "--with-wx" on the configure +# command. If you do not write a config_interface line, Bochs will +# choose a default for you. +# +# NOTE: if you use the "wx" configuration interface, you must also use +# the "wx" display library. +#======================================================================= +config_interface: textconfig +#config_interface: wx + +#======================================================================= +# DISPLAY_LIBRARY +# +# The display library is the code that displays the Bochs VGA screen. Bochs +# has a selection of about 10 different display library implementations for +# different platforms. If you run configure with multiple --with-* options, +# the display_library command lets you choose which one you want to run with. +# If you do not write a display_library line, Bochs will choose a default for +# you. +# +# The choices are: +# x use X windows interface, cross platform +# sdl use SDL library, cross platform +# svga use SVGALIB library for Linux, allows graphics without X11 +# term text only, uses curses/ncurses library, cross platform +# wx use wxWidgets library, cross platform +# nogui no display at all +# +# NOTE: if you use the "wx" configuration interface, you must also use +# the "wx" display library. +# +# Specific options: +# Some display libraries now support specific option to control their +# behaviour. See the examples below for currently supported options. +#======================================================================= +#display_library: nogui +#display_library: sdl, options="fullscreen" # startup in fullscreen mode +#display_library: term +#display_library: sdl +#display_library: x, options="hideIPS" # disable IPS output in status bar +display_library: sdl, options="gui_debug" # use GTK debugger gui + +#======================================================================= +# ROMIMAGE: +# The ROM BIOS controls what the PC does when it first powers on. +# Normally, you can use a precompiled BIOS in the source or binary +# distribution called BIOS-bochs-latest. The ROM BIOS is usually loaded +# starting at address 0xf0000, and it is exactly 64k long. Another option +# is 128k BIOS which is loaded at address 0xe0000. +# You can also use the environment variable $BXSHARE to specify the +# location of the BIOS. +# The usage of external large BIOS images (up to 512k) at memory top is +# now supported, but we still recommend to use the BIOS distributed with +# Bochs. The start address optional, since it can be calculated from image size. +#======================================================================= +romimage: file=/usr/local/share/bochs/BIOS-bochs-latest +#romimage: file=bios/seabios-0.5.1.bin +#romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top + +#======================================================================= +# CPU: +# This defines cpu-related parameters inside Bochs: +# +# COUNT: +# Set the number of processors:cores per processor:threads per core +# when Bochs is compiled for SMP emulation. +# Bochs currently supports up to 8 threads running simultaniosly. +# If Bochs is compiled without SMP support, it won't accept values +# different from 1. +# +# QUANTUM: +# Maximum amount of instructions allowed to execute by processor before +# returning control to another cpu. This option exists only in Bochs +# binary compiled with SMP support. +# +# RESET_ON_TRIPLE_FAULT: +# Reset the CPU when triple fault occur (highly recommended) rather than +# PANIC. Remember that if you trying to continue after triple fault the +# simulation will be completely bogus ! +# +# MSRS: +# Define path to user CPU Model Specific Registers (MSRs) specification. +# See example in msrs.def. +# +# IGNORE_BAD_MSRS: +# Ignore MSR references that Bochs does not understand; print a warning +# message instead of generating #GP exception. This option is enabled +# by default but will not be avaiable if configurable MSRs are enabled. +# +# IPS: +# Emulated Instructions Per Second. This is the number of IPS that bochs +# is capable of running on your machine. You can recompile Bochs with +# --enable-show-ips option enabled, to find your host's capability. +# Measured IPS value will then be logged into your log file or shown +# in the status bar (if supported by the gui). +# +# IPS is used to calibrate many time-dependent events within the bochs +# simulation. For example, changing IPS affects the frequency of VGA +# updates, the duration of time before a key starts to autorepeat, and +# the measurement of BogoMips and other benchmarks. +# +# Examples: +# +# Bochs Machine/Compiler Mips +# ____________________________________________________________________ +# 2.3.7 3.2Ghz Intel Core 2 Q9770 with WinXP/g++ 3.4 50 to 55 Mips +# 2.3.7 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 38 to 43 Mips +# 2.2.6 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 21 to 25 Mips +# 2.2.6 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips +# 2.0.1 1.6Ghz Intel P4 with Win2000/g++ 3.3 5 to 7 Mips +#======================================================================= +cpu: count=1, ips=19000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def" + +#======================================================================= +# CPUID: +# +# This defines features and functionality supported by Bochs emulated CPU: +# +# MMX: +# Select MMX instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. +# +# SEP: +# Select SYSENTER/SYSEXIT instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# SSE: +# Select SSE instruction set support. +# Any of NONE/SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2 could be selected. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# XAPIC: +# Select XAPIC extensions support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# AES: +# Select AES instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# MOVBE: +# Select MOVBE Intel(R) Atom instruction support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# XSAVE: +# Select XSAVE extensions support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# 1G_PAGES: +# Enable 1G page size support in long mode. +# This option exists only if Bochs compiled with x86-64 support. +# +# MWAIT_IS_NOP: +# When this option is enabled MWAIT will not put the CPU into a sleep state. +# This option exists only if Bochs compiled with --enable-monitor-mwait. +# +# VENDOR_STRING: +# Set the CPUID vendor string returned by CPUID(0x0). This should be a +# twelve-character ASCII string. +# +# BRAND_STRING: +# Set the CPUID vendor string returned by CPUID(0x80000002 .. 0x80000004). +# This should be at most a forty-eight-character ASCII string. +# +# CPUID_LIMIT_WINNT: +# Determine whether to limit maximum CPUID function to 3. This mode is +# required to workaround WinNT installation and boot issues. +#======================================================================= +cpuid: mmx=1, sep=1, sse=sse4_2, aes=1, movbe=1, xsave=1 + +#======================================================================= +# MEMORY +# Set the amount of physical memory you want to emulate. +# +# GUEST: +# Set amount of guest physical memory to emulate. The default is 32MB, +# the maximum amount limited only by physical address space limitations. +# +# HOST: +# Set amount of host memory you want to allocate for guest RAM emulation. +# It is possible to allocate less memory than you want to emulate in guest +# system. This will fake guest to see the non-existing memory. Once guest +# system touches new memory block it will be dynamically taken from the +# memory pool. You will be warned (by FATAL PANIC) in case guest already +# used all allocated host memory and wants more. +# +#======================================================================= +memory: guest=64, host=128 + +#======================================================================= +# OPTROMIMAGE[1-4]: +# You may now load up to 4 optional ROM images. Be sure to use a +# read-only area, typically between C8000 and EFFFF. These optional +# ROM images should not overwrite the rombios (located at +# F0000-FFFFF) and the videobios (located at C0000-C7FFF). +# Those ROM images will be initialized by the bios if they contain +# the right signature (0x55AA) and a valid checksum. +# It can also be a convenient way to upload some arbitrary code/data +# in the simulation, that can be retrieved by the boot loader +#======================================================================= +#optromimage1: file=optionalrom.bin, address=0xd0000 +#optromimage2: file=optionalrom.bin, address=0xd1000 +#optromimage3: file=optionalrom.bin, address=0xd2000 +#optromimage4: file=optionalrom.bin, address=0xd3000 + +#optramimage1: file=/path/file1.img, address=0x0010000 +#optramimage2: file=/path/file2.img, address=0x0020000 +#optramimage3: file=/path/file3.img, address=0x0030000 +#optramimage4: file=/path/file4.img, address=0x0040000 + +#======================================================================= +# VGAROMIMAGE +# You now need to load a VGA ROM BIOS into C0000. +#======================================================================= +vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest +#vgaromimage: file=/usr/share/vgabios/vgabios.debug.bin + +#======================================================================= +# VGA: +# Here you can specify the display extension to be used. With the value +# 'none' you can use standard VGA with no extension. Other supported +# values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support. +#======================================================================= +#vga: extension=cirrus +vga: extension=vbe + +#======================================================================= +# FLOPPYA: +# Point this to pathname of floppy image file or device +# This should be of a bootable floppy(image/device) if you're +# booting from 'a' (or 'floppy'). +# +# You can set the initial status of the media to 'ejected' or 'inserted'. +# floppya: 2_88=path, status=ejected (2.88M 3.5" media) +# floppya: 1_44=path, status=inserted (1.44M 3.5" media) +# floppya: 1_2=path, status=ejected (1.2M 5.25" media) +# floppya: 720k=path, status=inserted (720K 3.5" media) +# floppya: 360k=path, status=inserted (360K 5.25" media) +# floppya: 320k=path, status=inserted (320K 5.25" media) +# floppya: 180k=path, status=inserted (180K 5.25" media) +# floppya: 160k=path, status=inserted (160K 5.25" media) +# floppya: image=path, status=inserted (guess media type from image size) +# floppya: type=1_44 (1.44M 3.5" floppy drive, no media) +# +# The path should be the name of a disk image file. On Unix, you can use a raw +# device name such as /dev/fd0 on Linux. On win32 platforms, use drive letters +# such as a: or b: as the path. The parameter 'image' works with image files +# only. In that case the size must match one of the supported types. +# The parameter 'type' can be used to enable the floppy drive without media +# and status specified. Usually the drive type is set up based on the media type. +#======================================================================= +#floppya: 1_44=/dev/fd0, status=inserted +#floppya: image=../1.44, status=inserted +#floppya: 1_44=/dev/fd0H1440, status=inserted +#floppya: 1_2=../1_2, status=inserted +#floppya: 1_44=a:, status=inserted +#floppya: 2_88=floppyA.img, status=inserted +#floppya: 1_44=/dev/rfd0a, status=inserted + +#======================================================================= +# FLOPPYB: +# See FLOPPYA above for syntax +#======================================================================= +#floppyb: 1_44=b:, status=inserted +#floppyb: 1_44=b.img, status=inserted + +#======================================================================= +# ATA0, ATA1, ATA2, ATA3 +# ATA controller for hard disks and cdroms +# +# ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number +# +# These options enables up to 4 ata channels. For each channel +# the two base io addresses and the irq must be specified. +# +# ata0 and ata1 are enabled by default with the values shown below +# +# Examples: +# ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +# ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +# ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 +# ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9 +#======================================================================= +ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 +ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 + +#======================================================================= +# ATA[0-3]-MASTER, ATA[0-3]-SLAVE +# +# This defines the type and characteristics of all attached ata devices: +# type= type of attached device [disk|cdrom] +# mode= only valid for disks [flat|concat|external|dll|sparse|vmware3] +# mode= only valid for disks [undoable|growing|volatile] +# path= path of the image +# cylinders= only valid for disks +# heads= only valid for disks +# spt= only valid for disks +# status= only valid for cdroms [inserted|ejected] +# biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos] +# translation=type of translation of the bios, only for disks [none|lba|large|rechs|auto] +# model= string returned by identify device command +# journal= optional filename of the redolog for undoable and volatile disks +# +# Point this at a hard disk image file, cdrom iso file, or physical cdrom +# device. To create a hard disk image, try running bximage. It will help you +# choose the size and then suggest a line that works with it. +# +# In UNIX it may be possible to use a raw device as a Bochs hard disk, +# but WE DON'T RECOMMEND IT. In Windows there is no easy way. +# +# In windows, the drive letter + colon notation should be used for cdroms. +# Depending on versions of windows and drivers, you may only be able to +# access the "first" cdrom in the system. On MacOSX, use path="drive" +# to access the physical drive. +# +# The path is mandatory for hard disks. Disk geometry autodetection works with +# images created by bximage if CHS is set to 0/0/0 (cylinders are calculated +# using heads=16 and spt=63). For other hard disk images and modes the +# cylinders, heads, and spt are mandatory. In all cases the disk size reported +# from the image must be exactly C*H*S*512. +# +# Default values are: +# mode=flat, biosdetect=auto, translation=auto, model="Generic 1234" +# +# The biosdetect option has currently no effect on the bios +# +# Examples: +# ata0-master: type=disk, mode=flat, path=10M.sample, cylinders=306, heads=4, spt=17 +# ata0-slave: type=disk, mode=flat, path=20M.sample, cylinders=615, heads=4, spt=17 +# ata1-master: type=disk, mode=flat, path=30M.sample, cylinders=615, heads=6, spt=17 +# ata1-slave: type=disk, mode=flat, path=46M.sample, cylinders=940, heads=6, spt=17 +# ata2-master: type=disk, mode=flat, path=62M.sample, cylinders=940, heads=8, spt=17 +# ata2-slave: type=disk, mode=flat, path=112M.sample, cylinders=900, heads=15, spt=17 +# ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63 +# ata3-slave: type=cdrom, path=iso.sample, status=inserted +#======================================================================= +#ata0-master: type=disk, mode=flat, path="disk.img" +ata1-slave: type=disk, mode=flat, path="disk.img" +#ata0-slave: type=cdrom, path=/dev/sr0, status=inserted +#ata0-slave: type=cdrom, path=BOOTCD.iso, status=inserted + +#======================================================================= +# BOOT: +# This defines the boot sequence. Now you can specify up to 3 boot drives, +# which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM). +# Legacy 'a' and 'c' are also supported. +# Examples: +# boot: floppy +# boot: cdrom, disk +# boot: network, disk +# boot: cdrom, floppy, disk +#======================================================================= +#boot: floppy +boot: disk +#boot: cdrom + +#======================================================================= +# CLOCK: +# This defines the parameters of the clock inside Bochs: +# +# SYNC: +# This defines the method how to synchronize the Bochs internal time +# with realtime. With the value 'none' the Bochs time relies on the IPS +# value and no host time synchronization is used. The 'slowdown' method +# sacrifices performance to preserve reproducibility while allowing host +# time correlation. The 'realtime' method sacrifices reproducibility to +# preserve performance and host-time correlation. +# It is possible to enable both synchronization methods. +# +# TIME0: +# Specifies the start (boot) time of the virtual machine. Use a time +# value as returned by the time(2) system call. If no time0 value is +# set or if time0 equal to 1 (special case) or if time0 equal 'local', +# the simulation will be started at the current local host time. +# If time0 equal to 2 (special case) or if time0 equal 'utc', +# the simulation will be started at the current utc time. +# +# Syntax: +# clock: sync=[none|slowdown|realtime|both], time0=[timeValue|local|utc] +# +# Example: +# clock: sync=none, time0=local # Now (localtime) +# clock: sync=slowdown, time0=315529200 # Tue Jan 1 00:00:00 1980 +# clock: sync=none, time0=631148400 # Mon Jan 1 00:00:00 1990 +# clock: sync=realtime, time0=938581955 # Wed Sep 29 07:12:35 1999 +# clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000 +# clock: sync=none, time0=1 # Now (localtime) +# clock: sync=none, time0=utc # Now (utc/gmt) +# +# Default value are sync=none, time0=local +#======================================================================= +clock: sync=none, time0=utc + + +#======================================================================= +# FLOPPY_BOOTSIG_CHECK: disabled=[0|1] +# Enables or disables the 0xaa55 signature check on boot floppies +# Defaults to disabled=0 +# Examples: +# floppy_bootsig_check: disabled=0 +# floppy_bootsig_check: disabled=1 +#======================================================================= +floppy_bootsig_check: disabled=0 + +#======================================================================= +# LOG: +# Give the path of the log file you'd like Bochs debug and misc. verbiage +# to be written to. If you don't use this option or set the filename to +# '-' the output is written to the console. If you really don't want it, +# make it "/dev/null" (Unix) or "nul" (win32). :^( +# +# Examples: +# log: ./bochs.out +# log: /dev/tty +#======================================================================= +log: /dev/stdout +#log: /dev/null +#log: /tmp/bochsout.txt + +#======================================================================= +# LOGPREFIX: +# This handles the format of the string prepended to each log line. +# You may use those special tokens : +# %t : 11 decimal digits timer tick +# %i : 8 hexadecimal digits of cpu current eip (ignored in SMP configuration) +# %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror) +# %d : 5 characters string of the device, between brackets +# +# Default : %t%e%d +# Examples: +# logprefix: %t-%e-@%i-%d +# logprefix: %i%e%d +#======================================================================= +#logprefix: %t%e%d + +#======================================================================= +# LOG CONTROLS +# +# Bochs now has four severity levels for event logging. +# panic: cannot proceed. If you choose to continue after a panic, +# don't be surprised if you get strange behavior or crashes. +# error: something went wrong, but it is probably safe to continue the +# simulation. +# info: interesting or useful messages. +# debug: messages useful only when debugging the code. This may +# spit out thousands per second. +# +# For events of each level, you can choose to crash, report, or ignore. +# TODO: allow choice based on the facility: e.g. crash on panics from +# everything except the cdrom, and only report those. +# +# If you are experiencing many panics, it can be helpful to change +# the panic action to report instead of fatal. However, be aware +# that anything executed after a panic is uncharted territory and can +# cause bochs to become unstable. The panic is a "graceful exit," so +# if you disable it you may get a spectacular disaster instead. +#======================================================================= +panic: action=ask +error: action=report +info: action=report +debug: action=ignore +#pass: action=fatal + +#======================================================================= +# DEBUGGER_LOG: +# Give the path of the log file you'd like Bochs to log debugger output. +# If you really don't want it, make it /dev/null or '-'. :^( +# +# Examples: +# debugger_log: ./debugger.out +#======================================================================= +#debugger_log: /dev/null +#debugger_log: debugger.out +debugger_log: - + +#======================================================================= +# COM1, COM2, COM3, COM4: +# This defines a serial port (UART type 16550A). In the 'term' you can specify +# a device to use as com1. This can be a real serial line, or a pty. To use +# a pty (under X/Unix), create two windows (xterms, usually). One of them will +# run bochs, and the other will act as com1. Find out the tty the com1 +# window using the `tty' command, and use that as the `dev' parameter. +# Then do `sleep 1000000' in the com1 window to keep the shell from +# messing with things, and run bochs in the other window. Serial I/O to +# com1 (port 0x3f8) will all go to the other window. +# In socket* and pipe* (win32 only) modes Bochs becomes either socket/named pipe +# client or server. In client mode it connects to an already running server (if +# connection fails Bochs treats com port as not connected). In server mode it +# opens socket/named pipe and waits until a client application connects to it +# before starting simulation. This mode is useful for remote debugging (e.g. +# with gdb's "target remote host:port" command or windbg's command line option +# -k com:pipe,port=\\.\pipe\pipename). Note: 'socket' is a shorthand for +# 'socket-client' and 'pipe' for 'pipe-client'. Socket modes use simple TCP +# communication, pipe modes use duplex byte mode pipes. +# Other serial modes are 'null' (no input/output), 'file' (output to a file +# specified as the 'dev' parameter), 'raw' (use the real serial port - under +# construction for win32), 'mouse' (standard serial mouse - requires +# mouse option setting 'type=serial', 'type=serial_wheel' or 'type=serial_msys'). +# +# Examples: +# com1: enabled=1, mode=null +# com1: enabled=1, mode=mouse +# com2: enabled=1, mode=file, dev=serial.out +# com3: enabled=1, mode=raw, dev=com1 +# com3: enabled=1, mode=socket-client, dev=localhost:8888 +# com3: enabled=1, mode=socket-server, dev=localhost:8888 +# com4: enabled=1, mode=pipe-client, dev=\\.\pipe\mypipe +# com4: enabled=1, mode=pipe-server, dev=\\.\pipe\mypipe +#======================================================================= +#com1: enabled=1, mode=term, dev=/dev/ttyS0 + + +#======================================================================= +# PARPORT1, PARPORT2: +# This defines a parallel (printer) port. When turned on and an output file is +# defined the emulated printer port sends characters printed by the guest OS +# into the output file. On some platforms a device filename can be used to +# send the data to the real parallel port (e.g. "/dev/lp0" on Linux, "lpt1" on +# win32 platforms). +# +# Examples: +# parport1: enabled=1, file="parport.out" +# parport2: enabled=1, file="/dev/lp0" +# parport1: enabled=0 +#======================================================================= +#parport1: enabled=1, file="/dev/lp0" + +#======================================================================= +# SB16: +# This defines the SB16 sound emulation. It can have several of the +# following properties. +# All properties are in the format sb16: property=value +# midi: The filename is where the midi data is sent. This can be a +# device or just a file if you want to record the midi data. +# midimode: +# 0=no data +# 1=output to device (system dependent. midi denotes the device driver) +# 2=SMF file output, including headers +# 3=output the midi data stream to the file (no midi headers and no +# delta times, just command and data bytes) +# wave: This is the device/file where wave output is stored +# wavemode: +# 0=no data +# 1=output to device (system dependent. wave denotes the device driver) +# 2=VOC file output, incl. headers +# 3=output the raw wave stream to the file +# log: The file to write the sb16 emulator messages to. +# loglevel: +# 0=no log +# 1=resource changes, midi program and bank changes +# 2=severe errors +# 3=all errors +# 4=all errors plus all port accesses +# 5=all errors and port accesses plus a lot of extra info +# dmatimer: +# microseconds per second for a DMA cycle. Make it smaller to fix +# non-continuous sound. 750000 is usually a good value. This needs a +# reasonably correct setting for the IPS parameter of the CPU option. +# +# Examples for output devices: +# sb16: midimode=1, midi="", wavemode=1, wave="" # win32 +# sb16: midimode=1, midi=alsa:128:0, wavemode=1, wave=alsa # Linux with ALSA +#======================================================================= +#sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=/dev/stdout, dmatimer=600000 + +#======================================================================= +# VGA_UPDATE_INTERVAL: +# Video memory is scanned for updates and screen updated every so many +# virtual seconds. The default is 50000, about 20Hz. Keep in mind that +# you must tweak the 'cpu: ips=N' directive to be as close to the number +# of emulated instructions-per-second your workstation can do, for this +# to be accurate. +# +# Examples: +# vga_update_interval: 250000 +#======================================================================= +#vga_update_interval: 50000 + +#using for Winstone '98 tests +#vga_update_interval: 40000 + +#======================================================================= +# KEYBOARD_SERIAL_DELAY: +# Approximate time in microseconds that it takes one character to +# be transfered from the keyboard to controller over the serial path. +# Examples: +# keyboard_serial_delay: 200 +#======================================================================= +keyboard_serial_delay: 250 + +#======================================================================= +# KEYBOARD_PASTE_DELAY: +# Approximate time in microseconds between attempts to paste +# characters to the keyboard controller. This leaves time for the +# guest os to deal with the flow of characters. The ideal setting +# depends on how your operating system processes characters. The +# default of 100000 usec (.1 seconds) was chosen because it works +# consistently in Windows. +# +# If your OS is losing characters during a paste, increase the paste +# delay until it stops losing characters. +# +# Examples: +# keyboard_paste_delay: 100000 +#======================================================================= +keyboard_paste_delay: 100000 + +#======================================================================= +# MOUSE: +# The Bochs gui creates mouse "events" unless the 'enabled' option is +# set to 0. The hardware emulation itself is not disabled by this. +# Unless you have a particular reason for enabling the mouse by default, +# it is recommended that you leave it off. You can also toggle the mouse +# usage at runtime (control key + middle mouse button on X11, SDL, +# wxWidgets and Win32). +# With the mouse type option you can select the type of mouse to emulate. +# The default value is 'ps2'. The other choices are 'imps2' (wheel mouse +# on PS/2), 'serial', 'serial_wheel' and 'serial_msys' (one com port requires +# setting 'mode=mouse'). To connect a mouse to an USB port, see the 'usb_uhci' +# or 'usb_ohci' option (requires PCI and USB support). +# +# Examples: +# mouse: enabled=1 +# mouse: enabled=1, type=imps2 +# mouse: enabled=1, type=serial +# mouse: enabled=0 +#======================================================================= +mouse: enabled=0 + +#======================================================================= +# private_colormap: Request that the GUI create and use it's own +# non-shared colormap. This colormap will be used +# when in the bochs window. If not enabled, a +# shared colormap scheme may be used. Not implemented +# on all GUI's. +# +# Examples: +# private_colormap: enabled=1 +# private_colormap: enabled=0 +#======================================================================= +private_colormap: enabled=0 + +#======================================================================= +# ne2k: NE2000 compatible ethernet adapter +# +# Examples: +# ne2k: ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT +# +# ioaddr, irq: You probably won't need to change ioaddr and irq, unless there +# are IRQ conflicts. These arguments are ignored when assign the ne2k to a +# PCI slot. +# +# mac: The MAC address MUST NOT match the address of any machine on the net. +# Also, the first byte must be an even number (bit 0 set means a multicast +# address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast +# address. For the ethertap module, you must use fe:fd:00:00:00:01. There may +# be other restrictions too. To be safe, just use the b0:c4... address. +# +# ethdev: The ethdev value is the name of the network interface on your host +# platform. On UNIX machines, you can get the name by running ifconfig. On +# Windows machines, you must run niclist to get the name of the ethdev. +# Niclist source code is in misc/niclist.c and it is included in Windows +# binary releases. +# +# script: The script value is optional, and is the name of a script that +# is executed after bochs initialize the network interface. You can use +# this script to configure this network interface, or enable masquerading. +# This is mainly useful for the tun/tap devices that only exist during +# Bochs execution. The network interface name is supplied to the script +# as first parameter +# +# If you don't want to make connections to any physical networks, +# you can use the following 'ethmod's to simulate a virtual network. +# null: All packets are discarded, but logged to a few files. +# arpback: ARP is simulated. Disabled by default. +# vde: Virtual Distributed Ethernet +# vnet: ARP, ICMP-echo(ping), DHCP and read/write TFTP are simulated. +# The virtual host uses 192.168.10.1. +# DHCP assigns 192.168.10.2 to the guest. +# TFTP uses the ethdev value for the root directory and doesn't +# overwrite files. +# +#======================================================================= +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 +# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 +# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0 +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl" +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp" + +#======================================================================= +# pnic: Bochs/Etherboot pseudo-NIC +# +# Example: +# pnic: enabled=1, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT +# +# The pseudo-NIC accepts the same syntax (for mac, ethmod, ethdev, script) and +# supports the same networking modules as the NE2000 adapter. In addition to +# this, it must be assigned to a PCI slot. +#======================================================================= +#pnic: enabled=1, mac=b0:c4:20:00:00:00, ethmod=vnet + +#======================================================================= +# KEYBOARD_MAPPING: +# This enables a remap of a physical localized keyboard to a +# virtualized us keyboard, as the PC architecture expects. +# If enabled, the keymap file must be specified. +# +# Examples: +# keyboard_mapping: enabled=1, map=gui/keymaps/x11-pc-de.map +#======================================================================= +keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/sdl-pc-us.map + +#======================================================================= +# KEYBOARD_TYPE: +# Type of keyboard return by a "identify keyboard" command to the +# keyboard controler. It must be one of "xt", "at" or "mf". +# Defaults to "mf". It should be ok for almost everybody. A known +# exception is french macs, that do have a "at"-like keyboard. +# +# Examples: +# keyboard_type: mf +#======================================================================= +#keyboard_type: mf + +#======================================================================= +# USER_SHORTCUT: +# This defines the keyboard shortcut to be sent when you press the "user" +# button in the headerbar. The shortcut string is a combination of maximum +# 3 key names (listed below) separated with a '-' character. +# Valid key names: +# "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc", +# "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup", +# "plus", "right", "shift", "space", "tab", "up", "win", "print" and "power". +# +# Example: +# user_shortcut: keys=ctrl-alt-del +#======================================================================= +#user_shortcut: keys=ctrl-alt-del + +#======================================================================= +# I440FXSUPPORT: +# This option controls the presence of the i440FX PCI chipset. You can +# also specify the devices connected to PCI slots. Up to 5 slots are +# available now. These devices are currently supported: ne2k, pcivga, +# pcidev, pcipnic and usb_ohci. If Bochs is compiled with Cirrus SVGA +# support you'll have the additional choice 'cirrus'. +# +# Example: +# i440fxsupport: enabled=1, slot1=pcivga, slot2=ne2k +#======================================================================= +#i440fxsupport: enabled=1 + +#======================================================================= +# USB_UHCI: +# This option controls the presence of the USB root hub which is a part +# of the i440FX PCI chipset. With the portX option you can connect devices +# to the hub (currently supported: 'mouse', 'tablet', 'keypad', 'disk', 'cdrom' +# 'hub' and 'printer'). +# +# If you connect the mouse or tablet to one of the ports, Bochs forwards the +# mouse movement data to the USB device instead of the selected mouse type. +# When connecting the keypad to one of the ports, Bochs forwards the input of +# the numeric keypad to the USB device instead of the PS/2 keyboard. +# +# To connect a flat image as an USB hardisk you can use the 'disk' device with +# the path to the image separated with a colon (see below). To emulate an USB +# cdrom you can use the 'cdrom' device name and the path to an ISO image or raw +# device name also separated with a colon. +# +# The device name 'hub' connects an external hub with max. 8 ports (default: 4) +# to the root hub. To specify the number of ports you have to add the value +# separated with a colon. Connecting devices to the external hub ports is only +# available in the runtime configuration. +# +# The device 'printer' emulates the HP Deskjet 920C printer. The PCL data is +# sent to a file specified in bochsrc.txt. The current code appends the PCL +# code to the file if the file already existed. It would probably be nice to +# overwrite the file instead, asking user first. +#======================================================================= +#usb_uhci: enabled=1 +#usb_uhci: enabled=1, port1=mouse, port2=disk:usbdisk.img +#usb_uhci: enabled=1, port1=hub:7, port2=cdrom:image.iso + +#======================================================================= +# USB_OHCI: +# This option controls the presence of the USB OHCI host controller with a +# 2-port hub. The portX option accepts the same device types with the same +# syntax as the UHCI controller (see above). The OHCI HC must be assigned to +# a PCI slot. +#======================================================================= +#usb_ohci: enabled=1 +#usb_ohci: enabled=1, port1=printer:usbprinter.bin + +#======================================================================= +# CMOSIMAGE: +# This defines image file that can be loaded into the CMOS RAM at startup. +# The rtc_init parameter controls whether initialize the RTC with values stored +# in the image. By default the time0 argument given to the clock option is used. +# With 'rtc_init=image' the image is the source for the initial time. +# +# Example: +# cmosimage: file=cmos.img, rtc_init=image +#======================================================================= +#cmosimage: file=cmos.img, rtc_init=time0 + +#======================================================================= +# MAGIC_BREAK: +# This enables the "magic breakpoint" feature when using the debugger. +# The useless cpu instruction XCHG BX, BX causes Bochs to enter the +# debugger mode. This might be useful for software development. +# +# Example: +# magic_break: enabled=1 +#======================================================================= +#magic_break: enabled=1 + +#======================================================================= +# PORT_E9_HACK: +# The 0xE9 port doesn't exists in normal ISA architecture. However, we +# define a convention here, to display on the console of the system running +# Bochs anything that is written to it. The idea is to provide debug output +# very early when writing BIOS or OS code for example, without having to +# bother with setting up a serial port or etc. Reading from port 0xE9 will +# will return 0xe9 to let you know if the feature is available. +# Leave this 0 unless you have a reason to use it. +# +# Example: +# port_e9_hack: enabled=1 +#======================================================================= +#port_e9_hack: enabled=1 + +#======================================================================= +# DEBUG_SYMBOLS: +# This loads symbols from the specified file for use in Bochs' internal +# debugger. Symbols are loaded into global context. This is equivalent to +# issuing ldsym debugger command at start up. +# +# Example: +# debug_symbols: file="kernel.sym" +# debug_symbols: file="kernel.sym", offset=0x80000000 +#======================================================================= +#debug_symbols: file="kernel.sym" + +#======================================================================= +# other stuff +#======================================================================= +#load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log +#load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img +#text_snapshot_check: enabled=1 +#print_timestamps: enabled=1 + +#------------------------- +# PCI host device mapping +#------------------------- +#pcidev: vendor=0x1234, device=0x5678 + +#======================================================================= +# GDBSTUB: +# Enable GDB stub. See user documentation for details. +# Default value is enabled=0. +#======================================================================= +#gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0 + +#======================================================================= +# PLUGIN_CTRL: +# Controls the presence of optional plugins without a separate option. +# By default all existing plugins are enabled. These plugins are currently +# supported: 'acpi', 'biosdev', 'extfpuirq', 'gameport', 'iodebug', +# 'pci_ide', 'speaker' and 'unmapped'. +#======================================================================= +#plugin_ctrl: biosdev=0, speaker=0 + +#======================================================================= +# USER_PLUGIN: +# Load user-defined plugin. This option is available only if Bochs is +# compiled with plugin support. Maximum 8 different plugins are supported. +# See the example in the Bochs sources how to write a plugin device. +#======================================================================= +#user_plugin: name=testdev diff --git a/test/init/Makefile b/test/init/Makefile new file mode 100644 index 0000000..3a6e983 --- /dev/null +++ b/test/init/Makefile @@ -0,0 +1,19 @@ +.PHONY: clean + +CC=gcc +CFLAGS=-m32 -march=i486 -fno-zero-initialized-in-bss + +LINKER=ld +LDFLAGS=-melf_i386 -Ttext=10000000 --entry=main + +all: init + +init: init.o + $(LINKER) $(LDFLAGS) $^ -o $@ + + +%.o: %.c + $(CC) $(CFLAGS) -c $^ -o $@ + +clean: + -rm -f *.o init diff --git a/test/init/init.c b/test/init/init.c new file mode 100644 index 0000000..bf0d1f0 --- /dev/null +++ b/test/init/init.c @@ -0,0 +1,12 @@ +void main() +{ + char *msg1 = "NutsOS Init program\n"; + + while(*msg1 != 0) + { + asm("mov $1, %%eax; mov %0, %%ebx; int $0x40" :: "m"(msg1)); + msg1++; + } + + asm("mov $5, %eax; int $0x40"); +} diff --git a/test/ndmt b/test/ndmt new file mode 100755 index 0000000..dae3e2e --- /dev/null +++ b/test/ndmt @@ -0,0 +1,128 @@ +#!/usr/bin/python + +import os +import subprocess +import time + +# Variables globales +selectedDiskPath = "" +selectedMountPoint = "" +mountFlag = False + + +# Fonction SelectDisk : sélectionne une image disque +def SelectDisk(diskPath): + global selectedDiskPath + global mountFlag + + if mountFlag == True: + print("Error : you must umount the current partition before select a new disk") + return -1 + + if os.path.isfile(diskPath) == True: + selectedDiskPath = diskPath + return 0 + else: + print("Error : invalid disk path") + return -2 + + +# Fonction SelectMountPoint : sélectionne un répertoire pour le montage +def SelectMountPoint(dirPath): + global selectedMountPoint + global mountFlag + + if mountFlag == True: + print("Error : you must umount the current partition before select a new mount point") + return -1 + + if os.path.isdir(dirPath) == True: + selectedMountPoint = dirPath + return 0 + else: + print("Error : invalid dir path") + return -2 + + +# Fonction MountPart : Monte dans le répertoire sélectionné la partition du disque sélectionné +def MountPart(partNum): + global selectedDiskPath + global selectedMountPoint + global mountFlag + + if mountFlag == True: + print("Error : a partition is aready mounted") + return -1 + + if partNum >= 0 and partNum < 4: + uid = str(os.getuid()) + gid = str(os.getgid()) + off = subprocess.check_output(["tools/readpt", selectedDiskPath, str(partNum), "start_LBA"], stderr=None) + partOffset = str(int(off) * 512) + mountOptions = "loop,rw,offset={0},users,uid={1},gid={2}".format(partOffset, uid, gid) + if subprocess.call(["/usr/bin/sudo", "/bin/mount", "-o", mountOptions, selectedDiskPath, selectedMountPoint], stdin=None, stdout=None, stderr=None) == 0: + time.sleep(1) + print("Partition ", partNum, " mounted") + mountFlag = True + return 0 + else: + print("Error : unable to mount partition ", partNum) + return -3 + else: + return -2 + + +# Fonction UmountPart : Démonte la partition montée +def UmountPart(): + global selectedMountPoint + global mountFlag + + if mountFlag == False: + print("Error : no partition mounted") + return -1 + + if subprocess.call(["/usr/bin/sudo", "/bin/umount", selectedMountPoint], stdin=None, stdout=None, stderr=None) == 0: + time.sleep(1) + print("Umount partition") + mountFlag = False + return 0 + else: + print("Error : unable to umount partition") + return -2 + + + +# Programme principal +print("\n########################################") +print("### NutsOS Disk Management Tool v1.0 ###") +print("########################################\n") +quit = False +while quit != True: + cmd = input("#> ") + args = cmd.split(sep=' ') + if args[0] == "seldisk": + if len(args) == 2: + SelectDisk(args[1]) + else: + print("Command error : seldisk ") + elif args[0] == "selmnt": + if len(args) == 2: + SelectMountPoint(args[1]) + else: + print("Command error : selmnt ") + elif args[0] == "mount": + if len(args) == 2: + MountPart(int(args[1])) + else: + print("Command error : mount ") + elif args[0] == "umount": + if len(args) == 1: + UmountPart() + else: + print("Command error : umount") + elif args[0] == "quit": + quit = True + if mountFlag == True: + UmountPart() + else: + print("Command error : unknown command") diff --git a/test/tools/readpt.c b/test/tools/readpt.c new file mode 100644 index 0000000..7897504 --- /dev/null +++ b/test/tools/readpt.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include + +#define HD_SECTOR_SIZE 512 +#define PARTITION_TABLE_START 0x1BE +#define PARTITION_TABLE_SIZE 64 + +typedef struct { + uint8_t bootSign; + uint8_t startHead; + uint8_t startSector:6; + uint16_t startCylinder:10; + uint8_t fsID; + uint8_t endHead; + uint8_t endSector:6; + uint16_t endCylinder:10; + uint32_t startLBA; + uint32_t sectorCount; +}__attribute__((packed)) T_PartitionTable; + +int main(int argc, char* argv[]) { + if(argc == 4) { + char *diskPath = argv[1]; + int partNum = atoi(argv[2]); + char* field = argv[3]; + + T_PartitionTable pt[4]; + + if(partNum < 0 || partNum > 3) { + fprintf(stderr, "Invalid partiton number\n"); + return -1; + } + + int fd = open(diskPath, O_RDONLY, 0664); + if(fd == -1) { + close(fd); + fprintf(stderr, "Error when openning the file <%s>\n", diskPath); + return -2; + } + + lseek(fd, PARTITION_TABLE_START, SEEK_SET); + + int bytesRead = read(fd, pt, PARTITION_TABLE_SIZE); + if(bytesRead == -1) { + close(fd); + fprintf(stderr, "Error when reading the file <%s>\n", diskPath); + return -3; + } + close(fd); + + if(!strcmp(field, "boot_sign")) + printf("%u", pt[partNum].bootSign); + else if(!strcmp(field, "start_head")) + printf("%u", pt[partNum].startHead); + else if(!strcmp(field, "start_sector")) + printf("%u", pt[partNum].startSector); + else if(!strcmp(field, "start_cylinder")) + printf("%u", pt[partNum].startCylinder); + else if(!strcmp(field, "fs_ID")) + printf("%u", pt[partNum].fsID); + else if(!strcmp(field, "end_head")) + printf("%u", pt[partNum].endHead); + else if(!strcmp(field, "end_sector")) + printf("%u", pt[partNum].endSector); + else if(!strcmp(field, "end_cylinder")) + printf("%u", pt[partNum].endCylinder); + else if(!strcmp(field, "start_LBA")) + printf("%u", pt[partNum].startLBA); + else if(!strcmp(field, "sector_count")) + printf("%u", pt[partNum].sectorCount); + else { + perror("Invalid field name\n"); + return -4; + } + } else { + fprintf(stderr, "[help] : readpt \n"); + fprintf(stderr, "Valid field names : boot_sign,start_head,start_sector,start_cylinder,fs_ID,end_head,end_sector,end_cylinder,start_LBA,sectorCount\n"); + return -5; + } + return 0; +} diff --git a/test/tools/w_kernLdr.c b/test/tools/w_kernLdr.c new file mode 100644 index 0000000..5602d31 --- /dev/null +++ b/test/tools/w_kernLdr.c @@ -0,0 +1,77 @@ +#include +#include +#include + +#define KERNLDR_START_SECTOR 1 +#define HD_SECTOR_SIZE 512 + +int main(int argc, char* argv[]) +{ + if(argc == 3) + { + char *input = argv[1]; + char *output = argv[2]; + printf("Copy kernLdr from <%s> to <%s> :\n", input, output); + + int inputFile = open(input, O_RDONLY , 0664); + if(inputFile == -1) + { + fprintf(stderr, "Error when openning file <%s>\n", input); + return 1; + } + + int outputFile = open(output, O_WRONLY | O_CREAT, 0664); + if(outputFile == -1) + { + fprintf(stderr, "Error when openning file <%s>\n", output); + return 1; + } + + lseek(inputFile, 0, SEEK_SET); + lseek(outputFile, HD_SECTOR_SIZE * KERNLDR_START_SECTOR, SEEK_SET); + + struct stat info; + fstat(inputFile, &info); + unsigned int kernLdrCodeSize = info.st_size; + + if(kernLdrCodeSize >= 32256) + { + perror("Error kernLdr is too large\n"); + close(inputFile); + close(outputFile); + return 2; + } + + unsigned char *kernLdrCode = malloc(kernLdrCodeSize); + int bytesRead = read(inputFile, kernLdrCode, kernLdrCodeSize); + if(bytesRead == -1) + { + perror("Reading error\n"); + free(kernLdrCode); + close(inputFile); + close(outputFile); + return 3; + } + + int bytesWrite = write(outputFile, kernLdrCode, kernLdrCodeSize); + if(bytesWrite == -1) + { + perror("Writing error\n"); + free(kernLdrCode); + close(inputFile); + close(outputFile); + return 3; + } + + free(kernLdrCode); + close(inputFile); + close(outputFile); + printf("done\n"); + } + else + { + perror("[help] : w_kernLdr \n"); + return 4; + } + return 0; +} diff --git a/test/tools/w_mbr.c b/test/tools/w_mbr.c new file mode 100644 index 0000000..3998ea8 --- /dev/null +++ b/test/tools/w_mbr.c @@ -0,0 +1,66 @@ +#include +#include +#include + +#define BOOT_CODE_SIZE 446 + +int main(int argc, char* argv[]) +{ + if(argc == 3) + { + char *input = argv[1]; + char *output = argv[2]; + printf("Copy bootcode from <%s> to <%s> :\n", input, output); + + int inputFile = open(input, O_RDONLY , 0664); + if(inputFile == -1) + { + fprintf(stderr, "Error when openning file <%s>\n", input); + close(inputFile); + return 1; + } + + int outputFile = open(output, O_WRONLY | O_CREAT, 0664); + if(outputFile == -1) + { + fprintf(stderr, "Error when openning file <%s>\n", output); + close(outputFile); + return 1; + } + + lseek(inputFile, 0, SEEK_SET); + lseek(outputFile, 0, SEEK_SET); + + unsigned char *bootCode = malloc(BOOT_CODE_SIZE); + int bytesRead = read(inputFile, bootCode, BOOT_CODE_SIZE); + if(bytesRead == -1) + { + perror("Reading error\n"); + free(bootCode); + close(inputFile); + close(outputFile); + return 2; + } + + int bytesWrite = write(outputFile, bootCode, BOOT_CODE_SIZE); + if(bytesWrite == -1) + { + perror("Writing error\n"); + free(bootCode); + close(inputFile); + close(outputFile); + return 2; + } + + free(bootCode); + close(inputFile); + close(outputFile); + printf("done\n"); + } + else + { + fprintf(stderr, "[help] : w_mbr \n"); + return 3; + } + return 0; +}