diff --git a/.gitignore b/.gitignore
index a683549..e92c619 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,54 +1,54 @@
-# Prerequisites
-*.d
-
-# Object files
-*.o
-*.ko
-*.obj
-*.elf
-
-# Linker output
-*.ilk
-*.map
-*.exp
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Libraries
-*.lib
-*.a
-*.la
-*.lo
-
-# Shared objects (inc. Windows DLLs)
-*.dll
-*.so
-*.so.*
-*.dylib
-
-# Executables
-*.exe
-*.out
-*.app
-*.i*86
-*.x86_64
-*.hex
-
-# Debug files
-*.dSYM/
-*.su
-*.idb
-*.pdb
-
-# Kernel Module Compile Results
-*.mod*
-*.cmd
-.tmp_versions/
-modules.order
-Module.symvers
-Mkfile.old
-dkms.conf
-.vscode/*
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
+.vscode/*
TODO.md
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 23b5225..2e3cbc7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,9 @@
-language: C
-
-before_install:
- - sudo apt-get update
- - sudo apt-get install -y nasm grub-pc-bin
- - sudo ln -s /usr/bin/gcc /usr/bin/i686-elf-gcc
- - sudo ln -s /usr/bin/ld /usr/bin/i686-elf-ld
-
-script: make clean all
+language: C
+
+before_install:
+ - sudo apt-get update
+ - sudo apt-get install -y nasm grub-pc-bin
+ - sudo ln -s /usr/bin/gcc /usr/bin/i686-elf-gcc
+ - sudo ln -s /usr/bin/ld /usr/bin/i686-elf-ld
+
+script: make clean all
diff --git a/LICENSE b/LICENSE
index ac929ed..c601388 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,674 +1,674 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- iceOS
- Copyright (C) 2019 Marco Cetica
-
- 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:
-
- iceOS Copyright (C) 2019 Marco Cetica
- 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
-.
+ 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.
+
+ iceOS
+ Copyright (C) 2019 Marco Cetica
+
+ 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:
+
+ iceOS Copyright (C) 2019 Marco Cetica
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/Makefile b/Makefile
index 102b5d3..2fe8394 100644
--- a/Makefile
+++ b/Makefile
@@ -1,57 +1,57 @@
-LD = i686-elf-ld
-LFLAGS = -melf_i386 -nostdlib -O2 -T link.ld
-
-all: prepare cpu kernel_code drivers libc userspace mem link iso
-
-prepare:
- mkdir -p obj/
- mkdir -p isodir/boot/grub/
- cp grub.cfg isodir/boot/grub/grub.cfg
-
-cpu:
- make -C kernel/cpu
- cp kernel/cpu/*.o obj/
-
-kernel_code:
- make -C kernel
- cp kernel/*.o obj/
-
-drivers:
- make -C kernel/drivers/
- cp kernel/drivers/*.o obj/
-
-libc:
- make -C kernel/libc
- cp kernel/libc/*.o obj/
-
-userspace:
- make -C kernel/userspace
- cp kernel/userspace/*.o obj/
-
-mem:
- make -C kernel/mem
- cp kernel/mem/*.o obj/
-
-link:
- $(LD) $(LFLAGS) -o isodir/boot/vulcanos.bin obj/*.o
-
-iso:
- grub-mkrescue isodir -o vulcanos.iso
-
-clean:
- rm -rf obj/ kernel/*.o kernel/cpu/*.o
- rm -rf kernel/userspace/*.o kernel/mem/*.o
- rm -rf kernel/drivers/*.o kernel/libc/*.o
- rm -rf vulcanos.iso bochslog.txt commands isodir
-
-bochs:
- bochs -f bochs_cfg -q
-
-run:
- qemu-system-x86_64 -cdrom vulcanos.iso -cpu qemu32
-
-run-debug:
- qemu-system-x86_64 -cdrom vulcanos.iso -d exec,cpu
-
-run-curses:
- qemu-system-x86_64 -cdrom vulcanos.iso -curses -cpu qemu32
+LD = i686-elf-ld
+LFLAGS = -melf_i386 -nostdlib -O2 -T link.ld
+
+all: prepare cpu kernel_code drivers libc userspace mem link iso
+
+prepare:
+ mkdir -p obj/
+ mkdir -p isodir/boot/grub/
+ cp grub.cfg isodir/boot/grub/grub.cfg
+
+cpu:
+ make -C kernel/cpu
+ cp kernel/cpu/*.o obj/
+
+kernel_code:
+ make -C kernel
+ cp kernel/*.o obj/
+
+drivers:
+ make -C kernel/drivers/
+ cp kernel/drivers/*.o obj/
+
+libc:
+ make -C kernel/libc
+ cp kernel/libc/*.o obj/
+
+userspace:
+ make -C kernel/userspace
+ cp kernel/userspace/*.o obj/
+
+mem:
+ make -C kernel/mem
+ cp kernel/mem/*.o obj/
+
+link:
+ $(LD) $(LFLAGS) -o isodir/boot/vulcanos.bin obj/*.o
+
+iso:
+ grub-mkrescue isodir -o vulcanos.iso
+
+clean:
+ rm -rf obj/ kernel/*.o kernel/cpu/*.o
+ rm -rf kernel/userspace/*.o kernel/mem/*.o
+ rm -rf kernel/drivers/*.o kernel/libc/*.o
+ rm -rf vulcanos.iso bochslog.txt commands isodir
+
+bochs:
+ bochs -f bochs_cfg -q
+
+run:
+ qemu-system-x86_64 -cdrom vulcanos.iso -cpu qemu32
+
+run-debug:
+ qemu-system-x86_64 -cdrom vulcanos.iso -d exec,cpu
+
+run-curses:
+ qemu-system-x86_64 -cdrom vulcanos.iso -curses -cpu qemu32
diff --git a/README.md b/README.md
index 5df1ec0..cfef72f 100644
--- a/README.md
+++ b/README.md
@@ -1,37 +1,37 @@
-# VulcanOS [![Build Status](https://travis-ci.com/ice-bit/vulcanos.svg?branch=master)](https://travis-ci.com/ice-bit/vulcanos)
-**VulcanOS** is a x86 monolithic kernel written in C from scratch following the UNIX philosophy. This project is just a student learning tool to know more about operating systems, do not expect nothing more than a toy.
-
-
-
VulcanOS running under QEMU
-
-
-## Installation
-### Requirements
-Before building this project you need to setup a [cross compiler](https://wiki.osdev.org/GCC_Cross-Compiler). Also install the following packages:
-
-- nasm
-- bochs
-- grub
-- mtools(only for Arch Linux)
-
-After that, you can build iceOS just by running the command listed below.
-1. Type `make all` to compile the system and to create an ISO
-2. Type `make run` to start it in QEMU or `make bochs` to start it with bochs(only for debug purposes).
-
-You can also find a ISO file
-[here](https://github.com/ice-bit/vulcanos/raw/master/imgs/vulcanos.iso)(md5sum: `a706cdfeea573e08550e599717d3f519`)
-
-## Features
-iceOS has the following features:
-- [x] VGA driver
-- [x] Interrupts
-- [x] PIC & PIT driver
-- [x] PS/2 driver
-- [x] Heap
-- [x] Paging
-- [ ] VFS driver
-- [ ] Usermode
-
-
-## License
-VulcanOS is released under GPLv3, you can obtain a copy of this license by cloning this repository or by visiting [this](https://opensource.org/licenses/GPL-3.0) page.
+# VulcanOS [![Build Status](https://travis-ci.com/ice-bit/vulcanos.svg?branch=master)](https://travis-ci.com/ice-bit/vulcanos)
+**VulcanOS** is a x86 monolithic kernel written in C from scratch following the UNIX philosophy. This project is just a student learning tool to know more about operating systems, do not expect nothing more than a toy.
+
+
+
VulcanOS running under QEMU
+
+
+## Installation
+### Requirements
+Before building this project you need to setup a [cross compiler](https://wiki.osdev.org/GCC_Cross-Compiler). Also install the following packages:
+
+- nasm
+- bochs
+- grub
+- mtools(only for Arch Linux)
+
+After that, you can build iceOS just by running the command listed below.
+1. Type `make all` to compile the system and to create an ISO
+2. Type `make run` to start it in QEMU or `make bochs` to start it with bochs(only for debug purposes).
+
+You can also find a ISO file
+[here](https://github.com/ice-bit/vulcanos/raw/master/imgs/vulcanos.iso)(md5sum: `a706cdfeea573e08550e599717d3f519`)
+
+## Features
+iceOS has the following features:
+- [x] VGA driver
+- [x] Interrupts
+- [x] PIC & PIT driver
+- [x] PS/2 driver
+- [x] Heap
+- [x] Paging
+- [ ] VFS driver
+- [ ] Usermode
+
+
+## License
+VulcanOS is released under GPLv3, you can obtain a copy of this license by cloning this repository or by visiting [this](https://opensource.org/licenses/GPL-3.0) page.
diff --git a/bochs_cfg b/bochs_cfg
index df47b6c..6cb55c1 100644
--- a/bochs_cfg
+++ b/bochs_cfg
@@ -1,12 +1,12 @@
-# System configuration.
-romimage: file=$BXSHARE/BIOS-bochs-latest
-vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
-cpu: model=corei7_ivy_bridge_3770k, ips=120000000
-clock: sync=slowdown
-megs: 256
-boot: cdrom, disk
-
-
-# CDROM
-ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
+# System configuration.
+romimage: file=$BXSHARE/BIOS-bochs-latest
+vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
+cpu: model=corei7_ivy_bridge_3770k, ips=120000000
+clock: sync=slowdown
+megs: 256
+boot: cdrom, disk
+
+
+# CDROM
+ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=cdrom, path="iceOS.iso", status=inserted
\ No newline at end of file
diff --git a/fs_generator.c b/fs_generator.c
index 243479e..869b0ef 100644
--- a/fs_generator.c
+++ b/fs_generator.c
@@ -1,55 +1,55 @@
-/* This program comes from James Molloy tutorial
- * on how to create an UNIX clone You can find the original code at:
- * http://www.jamesmolloy.co.uk/tutorial_html/8.-The%20VFS%20and%20the%20initrd.html */
-
-#include
-#include
-#include
-
-struct initrd_header {
- unsigned char magic; // Magic number for consistency
- char name[64];
- unsigned int offset; // Offset of the file start
- unsigned int length;
-};
-
-int main(int argc, char **argv) {
- int heads = (argc - 1) / 2;
- struct initrd_header headers[64];
- printf("Size of header(in bytes): %ld\n", sizeof(struct initrd_header));
- unsigned int off = sizeof(struct initrd_header) * 64 + sizeof(int);
- for(int i = 0; i < heads; i++) {
- printf("Writing file %s->%s at 0x%d\n", argv[i*2+1], argv[i*2+2], off);
- strcpy(headers[i].name, argv[i*2+2]);
- headers[i].offset = off;
- FILE *stream = fopen(argv[i*2+1], "r");
- if(stream == 0) {
- puts("Error, file not found!");
- return 1;
- }
- fseek(stream, 0, SEEK_END);
- headers[i].length = ftell(stream);
- off += headers[i].length;
- fclose(stream);
- headers[i].magic = 0xBF;
- }
-
- FILE *wstream = fopen("./initrd.img", "w");
- unsigned char *data = (unsigned char*)malloc(off);
- fwrite(&heads, sizeof(int), 1, wstream);
- fwrite(&heads, sizeof(struct initrd_header), 64, wstream);
-
- for(int i = 0; i < heads; i++) {
- FILE *stream = fopen(argv[i*2+1], "r");
- unsigned char *buf = (unsigned char*)malloc(headers[i].length);
- fread(buf, 1, headers[i].length, stream);
- fread(buf, 1, headers[i].length, wstream);
- fclose(stream);
- free(buf);
- }
-
- fclose(wstream);
- free(data);
-
- return 0;
+/* This program comes from James Molloy tutorial
+ * on how to create an UNIX clone You can find the original code at:
+ * http://www.jamesmolloy.co.uk/tutorial_html/8.-The%20VFS%20and%20the%20initrd.html */
+
+#include
+#include
+#include
+
+struct initrd_header {
+ unsigned char magic; // Magic number for consistency
+ char name[64];
+ unsigned int offset; // Offset of the file start
+ unsigned int length;
+};
+
+int main(int argc, char **argv) {
+ int heads = (argc - 1) / 2;
+ struct initrd_header headers[64];
+ printf("Size of header(in bytes): %ld\n", sizeof(struct initrd_header));
+ unsigned int off = sizeof(struct initrd_header) * 64 + sizeof(int);
+ for(int i = 0; i < heads; i++) {
+ printf("Writing file %s->%s at 0x%d\n", argv[i*2+1], argv[i*2+2], off);
+ strcpy(headers[i].name, argv[i*2+2]);
+ headers[i].offset = off;
+ FILE *stream = fopen(argv[i*2+1], "r");
+ if(stream == 0) {
+ puts("Error, file not found!");
+ return 1;
+ }
+ fseek(stream, 0, SEEK_END);
+ headers[i].length = ftell(stream);
+ off += headers[i].length;
+ fclose(stream);
+ headers[i].magic = 0xBF;
+ }
+
+ FILE *wstream = fopen("./initrd.img", "w");
+ unsigned char *data = (unsigned char*)malloc(off);
+ fwrite(&heads, sizeof(int), 1, wstream);
+ fwrite(&heads, sizeof(struct initrd_header), 64, wstream);
+
+ for(int i = 0; i < heads; i++) {
+ FILE *stream = fopen(argv[i*2+1], "r");
+ unsigned char *buf = (unsigned char*)malloc(headers[i].length);
+ fread(buf, 1, headers[i].length, stream);
+ fread(buf, 1, headers[i].length, wstream);
+ fclose(stream);
+ free(buf);
+ }
+
+ fclose(wstream);
+ free(data);
+
+ return 0;
}
\ No newline at end of file
diff --git a/grub.cfg b/grub.cfg
index 86afc3c..fe822fc 100644
--- a/grub.cfg
+++ b/grub.cfg
@@ -1,7 +1,7 @@
-set timeout = 0
-set default = 0
-
-menuentry "VulcanOS" {
- multiboot2 /boot/vulcanos.bin
- boot
-}
+set timeout = 0
+set default = 0
+
+menuentry "VulcanOS" {
+ multiboot2 /boot/vulcanos.bin
+ boot
+}
diff --git a/kernel/Makefile b/kernel/Makefile
index abcec33..cbe85cf 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -1,10 +1,10 @@
-OBJS = kernel_main.o
-
-CC = i686-elf-gcc # cross-compiler
-CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
-
-
-all: ${OBJS}
-
-%.o: %.c
+OBJS = kernel_main.o
+
+CC = i686-elf-gcc # cross-compiler
+CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
+
+
+all: ${OBJS}
+
+%.o: %.c
$(CC) $(CFLAGS) $< -o $@
\ No newline at end of file
diff --git a/kernel/cpu/Makefile b/kernel/cpu/Makefile
index 339e604..38757eb 100644
--- a/kernel/cpu/Makefile
+++ b/kernel/cpu/Makefile
@@ -1,8 +1,9 @@
-OBJS = kernel_loader.asm.o ports.asm.o \
- gdt.asm.o idt.asm.o interrupts.asm.o
-
-ASM = nasm
-ASMFLAGS = -f elf32
-all: $(OBJS)
-%.asm.o: %.asm
- $(ASM) $(ASMFLAGS) $< -o $@
+OBJS = main.asm.o ports.asm.o \
+ gdt.asm.o idt.asm.o \
+ interrupts.asm.o header.asm.o
+
+ASM = nasm
+ASMFLAGS = -f elf32
+all: $(OBJS)
+%.asm.o: %.asm
+ $(ASM) $(ASMFLAGS) $< -o $@
diff --git a/kernel/cpu/gdt.asm b/kernel/cpu/gdt.asm
index b3ca5ef..d8a919f 100644
--- a/kernel/cpu/gdt.asm
+++ b/kernel/cpu/gdt.asm
@@ -1,22 +1,22 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; vulcanOS Kernel ;
-; Developed by Marco 'icebit' Cetica ;
-; (c) 2019-2021 ;
-; Released under GPLv3 ;
-; https://github.com/ice-bit/iceOS ;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-global gdt_flush ; for drivers/gdt.c
-
-section .text
-gdt_flush:
- mov eax, [esp+4] ; get address of gdt_ptr_t
- lgdt [eax] ; Load GDT
- mov ax, 0x10 ; offset in the GDT of the data segment
- mov ds, ax ; Load data segment selectors
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- jmp 0x08:.flush ; offset in the GDT of the code segment
-.flush:
- ret
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; vulcanOS Kernel ;
+; Developed by Marco 'icebit' Cetica ;
+; (c) 2019-2021 ;
+; Released under GPLv3 ;
+; https://github.com/ice-bit/vulcanos ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global gdt_flush ; for drivers/gdt.c
+
+section .text
+gdt_flush:
+ mov eax, [esp+4] ; get address of gdt_ptr_t
+ lgdt [eax] ; Load GDT
+ mov ax, 0x10 ; offset in the GDT of the data segment
+ mov ds, ax ; Load data segment selectors
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ jmp 0x08:.flush ; offset in the GDT of the code segment
+.flush:
+ ret
diff --git a/kernel/cpu/header.asm b/kernel/cpu/header.asm
new file mode 100644
index 0000000..bec5032
--- /dev/null
+++ b/kernel/cpu/header.asm
@@ -0,0 +1,19 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; vulcanOS Kernel ;
+; Developed by Marco 'icebit' Cetica ;
+; (c) 2019-2021 ;
+; Released under GPLv3 ;
+; https://github.com/ice-bit/vulcanos ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+section .multiboot_header
+header_s:
+ dd 0xE85250D6 ; Magic number for multiboot
+ dd 0 ; Protected mode flag
+ dd header_e - header_s ; Header length
+ dd 0x100000000 - (0xE85250D6 + 0 + (header_e - header_s)) ; Checksum
+
+ ; Other flags
+ dw 0 ; Type
+ dw 0 ; Flags
+ dw 0 ; Size
+header_e:
\ No newline at end of file
diff --git a/kernel/cpu/idt.asm b/kernel/cpu/idt.asm
index 9846d3a..d26fe87 100644
--- a/kernel/cpu/idt.asm
+++ b/kernel/cpu/idt.asm
@@ -1,14 +1,14 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; vulcanOS Kernel ;
-; Developed by Marco 'icebit' Cetica ;
-; (c) 2019-2021 ;
-; Released under GPLv3 ;
-; https://github.com/ice-bit/iceOS ;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-global idt_flush ; for drivers/idt.c
-
-section .text
-idt_flush:
- mov eax, [esp+4] ; Retrieve idt_ptr_t*
- lidt [eax]
- ret
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; vulcanOS Kernel ;
+; Developed by Marco 'icebit' Cetica ;
+; (c) 2019-2021 ;
+; Released under GPLv3 ;
+; https://github.com/ice-bit/vulcanos ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+global idt_flush ; for drivers/idt.c
+
+section .text
+idt_flush:
+ mov eax, [esp+4] ; Retrieve idt_ptr_t*
+ lidt [eax]
+ ret
diff --git a/kernel/cpu/interrupts.asm b/kernel/cpu/interrupts.asm
index 7225ca2..ff8d8b3 100644
--- a/kernel/cpu/interrupts.asm
+++ b/kernel/cpu/interrupts.asm
@@ -1,159 +1,159 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; vulcanOS Kernel ;
-; Developed by Marco 'icebit' Cetica ;
-; (c) 2019-2021 ;
-; Released under GPLv3 ;
-; https://github.com/ice-bit/iceOS ;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-extern isr_handler ; Defined in drivers/isr.h
-extern irq_handler ; Defined in drivers/isr.h
-
-; Let's implement all ISR in a very handy way
-%macro ISR_NOERRCODE 1
- global isr%1
- isr%1:
- cli ; Disable interrupts
- push byte 0 ; Push dummy error code
- push byte %1 ; Push interrupt number
- jmp isr_common ; goto ISR handler
-%endmacro
-
-%macro ISR_ERRCODE 1
- global isr%1
- isr%1:
- cli ; Disable interrupts
- push byte %1 ; Push interrupt number
- jmp isr_common ; goto ISR handler
-%endmacro
-
-; Now we have to do the same thing for Interrupt Requests,
-; in this case the first parameter is the IRQ number while
-; the second one is the ISR number to be remapped to
-%macro IRQ 2
- global irq%1
- irq%1:
- cli ; Disable interrupts
- push byte 0 ; Push dummy error code
- push byte %2 ; Push interrupt number
- jmp irq_common ; goto IRQ handler
-%endmacro
-
-; isr_common is a common handler for all
-; Interrupt Service Routines declared in the system
-; It's main scope is to save current register's states
-; into the stack, call the C high level handler
-; and restore the register's original values from
-; the stack
-isr_common:
- ;; Save register's content into the stack ;;
- pusha ; Push edi,esi,ebp,esp,ebx,edx,ecx,eax
-
- mov ax, ds ; Get 16 bits of eax(e.g ds)
- push eax
-
- mov ax, 0x10 ; Load the kernel data segment descriptor
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
- ;; Call C handler ;;
- call isr_handler ; Call C handler
-
- ;; Restore register's content from the stack ;;
- pop eax ; Restore original data segment selector
-
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
- popa ; Pop edi,esi,ebp,esp,ebx,edx,ecx,eax
- add esp, 8 ; Cleans up pushed error code and ISR number
- sti ; Re-enable interrupts
- iret ; Pops 5 things: CS, EIP, EFLAGS, SS and ESp
-
-
-; irq_common is a common handler for all
-; Interrupt Requests, it's very similar to the
-; ISR one
-irq_common:
- ;; Save register's content into the stack ;;
- pusha ; Push edi,esi,ebp,esp,ebx,edx,ecx,eax
-
- mov ax, ds ; Get 16 bits of eax(e.g ds)
- push eax
-
- mov ax, 0x10 ; Load the kernel data segment descriptor
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
- ;; Call C handler ;;
- call irq_handler ; Call C handler
-
- ;; Restore register's content from the stack ;;
- pop ebx ; Restore original data segment selector
-
- mov ds, bx
- mov es, bx
- mov fs, bx
- mov gs, bx
-
- popa ; Pop edi,esi,ebp,esp,ebx,edx,ecx,eax
- add esp, 8 ; Cleans up pushed error code and ISR number
- sti ; Re-enable interrupts
- iret ; Pops 5 things: CS, EIP, EFLAGS, SS and ESp
-
-; Standard x86 ISRs (only 8,10-14 and 17 requires to push error codes to the stack)
-ISR_NOERRCODE 0
-ISR_NOERRCODE 1
-ISR_NOERRCODE 2
-ISR_NOERRCODE 3
-ISR_NOERRCODE 4
-ISR_NOERRCODE 5
-ISR_NOERRCODE 6
-ISR_NOERRCODE 7
-ISR_ERRCODE 8
-ISR_NOERRCODE 9
-ISR_ERRCODE 10
-ISR_ERRCODE 11
-ISR_ERRCODE 12
-ISR_ERRCODE 13
-ISR_ERRCODE 14
-ISR_NOERRCODE 15
-ISR_NOERRCODE 16
-ISR_NOERRCODE 17
-ISR_NOERRCODE 18
-ISR_NOERRCODE 19
-ISR_NOERRCODE 20
-ISR_NOERRCODE 21
-ISR_NOERRCODE 22
-ISR_NOERRCODE 23
-ISR_NOERRCODE 24
-ISR_NOERRCODE 25
-ISR_NOERRCODE 26
-ISR_NOERRCODE 27
-ISR_NOERRCODE 28
-ISR_NOERRCODE 29
-ISR_NOERRCODE 30
-ISR_NOERRCODE 31
-
-IRQ 0, 32
-IRQ 1, 33
-IRQ 2, 34
-IRQ 3, 35
-IRQ 4, 36
-IRQ 5, 37
-IRQ 6, 38
-IRQ 7, 39
-IRQ 8, 40
-IRQ 9, 41
-IRQ 10, 42
-IRQ 11, 43
-IRQ 12, 44
-IRQ 13, 45
-IRQ 14, 46
-IRQ 15, 47
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; vulcanOS Kernel ;
+; Developed by Marco 'icebit' Cetica ;
+; (c) 2019-2021 ;
+; Released under GPLv3 ;
+; https://github.com/ice-bit/vulcanos ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+extern isr_handler ; Defined in drivers/isr.h
+extern irq_handler ; Defined in drivers/isr.h
+
+; Let's implement all ISR in a very handy way
+%macro ISR_NOERRCODE 1
+ global isr%1
+ isr%1:
+ cli ; Disable interrupts
+ push byte 0 ; Push dummy error code
+ push byte %1 ; Push interrupt number
+ jmp isr_common ; goto ISR handler
+%endmacro
+
+%macro ISR_ERRCODE 1
+ global isr%1
+ isr%1:
+ cli ; Disable interrupts
+ push byte %1 ; Push interrupt number
+ jmp isr_common ; goto ISR handler
+%endmacro
+
+; Now we have to do the same thing for Interrupt Requests,
+; in this case the first parameter is the IRQ number while
+; the second one is the ISR number to be remapped to
+%macro IRQ 2
+ global irq%1
+ irq%1:
+ cli ; Disable interrupts
+ push byte 0 ; Push dummy error code
+ push byte %2 ; Push interrupt number
+ jmp irq_common ; goto IRQ handler
+%endmacro
+
+; isr_common is a common handler for all
+; Interrupt Service Routines declared in the system
+; It's main scope is to save current register's states
+; into the stack, call the C high level handler
+; and restore the register's original values from
+; the stack
+isr_common:
+ ;; Save register's content into the stack ;;
+ pusha ; Push edi,esi,ebp,esp,ebx,edx,ecx,eax
+
+ mov ax, ds ; Get 16 bits of eax(e.g ds)
+ push eax
+
+ mov ax, 0x10 ; Load the kernel data segment descriptor
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ ;; Call C handler ;;
+ call isr_handler ; Call C handler
+
+ ;; Restore register's content from the stack ;;
+ pop eax ; Restore original data segment selector
+
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ popa ; Pop edi,esi,ebp,esp,ebx,edx,ecx,eax
+ add esp, 8 ; Cleans up pushed error code and ISR number
+ sti ; Re-enable interrupts
+ iret ; Pops 5 things: CS, EIP, EFLAGS, SS and ESp
+
+
+; irq_common is a common handler for all
+; Interrupt Requests, it's very similar to the
+; ISR one
+irq_common:
+ ;; Save register's content into the stack ;;
+ pusha ; Push edi,esi,ebp,esp,ebx,edx,ecx,eax
+
+ mov ax, ds ; Get 16 bits of eax(e.g ds)
+ push eax
+
+ mov ax, 0x10 ; Load the kernel data segment descriptor
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ ;; Call C handler ;;
+ call irq_handler ; Call C handler
+
+ ;; Restore register's content from the stack ;;
+ pop ebx ; Restore original data segment selector
+
+ mov ds, bx
+ mov es, bx
+ mov fs, bx
+ mov gs, bx
+
+ popa ; Pop edi,esi,ebp,esp,ebx,edx,ecx,eax
+ add esp, 8 ; Cleans up pushed error code and ISR number
+ sti ; Re-enable interrupts
+ iret ; Pops 5 things: CS, EIP, EFLAGS, SS and ESp
+
+; Standard x86 ISRs (only 8,10-14 and 17 requires to push error codes to the stack)
+ISR_NOERRCODE 0
+ISR_NOERRCODE 1
+ISR_NOERRCODE 2
+ISR_NOERRCODE 3
+ISR_NOERRCODE 4
+ISR_NOERRCODE 5
+ISR_NOERRCODE 6
+ISR_NOERRCODE 7
+ISR_ERRCODE 8
+ISR_NOERRCODE 9
+ISR_ERRCODE 10
+ISR_ERRCODE 11
+ISR_ERRCODE 12
+ISR_ERRCODE 13
+ISR_ERRCODE 14
+ISR_NOERRCODE 15
+ISR_NOERRCODE 16
+ISR_NOERRCODE 17
+ISR_NOERRCODE 18
+ISR_NOERRCODE 19
+ISR_NOERRCODE 20
+ISR_NOERRCODE 21
+ISR_NOERRCODE 22
+ISR_NOERRCODE 23
+ISR_NOERRCODE 24
+ISR_NOERRCODE 25
+ISR_NOERRCODE 26
+ISR_NOERRCODE 27
+ISR_NOERRCODE 28
+ISR_NOERRCODE 29
+ISR_NOERRCODE 30
+ISR_NOERRCODE 31
+
+IRQ 0, 32
+IRQ 1, 33
+IRQ 2, 34
+IRQ 3, 35
+IRQ 4, 36
+IRQ 5, 37
+IRQ 6, 38
+IRQ 7, 39
+IRQ 8, 40
+IRQ 9, 41
+IRQ 10, 42
+IRQ 11, 43
+IRQ 12, 44
+IRQ 13, 45
+IRQ 14, 46
+IRQ 15, 47
diff --git a/kernel/cpu/kernel_loader.asm b/kernel/cpu/kernel_loader.asm
deleted file mode 100644
index eb08d1e..0000000
--- a/kernel/cpu/kernel_loader.asm
+++ /dev/null
@@ -1,43 +0,0 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; vulcanOS Kernel ;
-; Developed by Marco 'icebit' Cetica ;
-; (c) 2019-2021 ;
-; Released under GPLv3 ;
-; https://github.com/ice-bit/iceOS ;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-[BITS 32] ; We should be in protected mode
-section .multiboot
-
-head_s:
- dd 0xE85250D6 ; Multiboot header magic number
- dd 0 ; Protected mode flag
- dd head_e - head_s ; Header length
- dd 0x100000000 - (0xE85250D6 + 0 + (head_e - head_s)) ; Checksum of above
-
- ; Other flags
- dw 0 ; type
- dw 0 ; flags
- dd 0 ; size
-
-head_e:
-
-GLOBAL kernel_loader
-EXTERN kernel_main
-
-section .text
-kernel_loader:
- mov esp, kernel_stack + KERNEL_STACK_SZ ; Define stack pointer
- push eax ; Set multiboot header
- call kernel_main ; Jump into kernel's main function
-.loop:
- jmp .loop ; If the kernel returns, go into an infinite loop.
- ; This will prevent the CPU to run non-kernel instructions
- ; from the memory
-
-KERNEL_STACK_SZ equ 4096 ; Stack size(4KiB)
-
-section .bss
-align 4
-kernel_stack:
- resb KERNEL_STACK_SZ ; Reserve 4 KiB
diff --git a/kernel/cpu/main.asm b/kernel/cpu/main.asm
new file mode 100644
index 0000000..d107ace
--- /dev/null
+++ b/kernel/cpu/main.asm
@@ -0,0 +1,27 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; vulcanOS Kernel ;
+; Developed by Marco 'icebit' Cetica ;
+; (c) 2019-2021 ;
+; Released under GPLv3 ;
+; https://github.com/ice-bit/vulcanos ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+GLOBAL kernel_loader
+EXTERN kernel_main
+[BITS 32] ; Ensure we are in protected mode
+
+section .text
+kernel_loader:
+ mov esp, kernel_stack + KERNEL_STACK_SZ ; Define stack pointer
+ push eax ; Set multiboot header register
+ call kernel_main ; Call kernel's main function
+.loop:
+ jmp .loop ; If the kernel returns, go into an endless loop
+ ; This will prevent the CPU to execure any non-kernel
+ ; instructions.
+
+KERNEL_STACK_SZ equ 4096 ; Stack size(4KiB)
+
+section .bss
+align 4
+kernel_stack:
+ resb KERNEL_STACK_SZ ; Reserver 4KiB for kernel's stack
\ No newline at end of file
diff --git a/kernel/cpu/ports.asm b/kernel/cpu/ports.asm
index 1652e34..9f494e2 100644
--- a/kernel/cpu/ports.asm
+++ b/kernel/cpu/ports.asm
@@ -1,21 +1,21 @@
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; vulcanOS Kernel ;
-; Developed by Marco 'icebit' Cetica ;
-; (c) 2019-2021 ;
-; Released under GPLv3 ;
-; https://github.com/ice-bit/iceOS ;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-global outb ; Output from port
-global inb ; Input to port
-
-outb:
- mov al, [esp + 8]
- mov dx, [esp + 4]
- out dx, al
- ret
-
-inb:
- mov dx, [esp + 4]
- in al, dx
- ret
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; vulcanOS Kernel ;
+; Developed by Marco 'icebit' Cetica ;
+; (c) 2019-2021 ;
+; Released under GPLv3 ;
+; https://github.com/ice-bit/vulcanos ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+global outb ; Output from port
+global inb ; Input to port
+
+outb:
+ mov al, [esp + 8]
+ mov dx, [esp + 4]
+ out dx, al
+ ret
+
+inb:
+ mov dx, [esp + 4]
+ in al, dx
+ ret
diff --git a/kernel/drivers/Makefile b/kernel/drivers/Makefile
index 24cd3ff..da29a61 100644
--- a/kernel/drivers/Makefile
+++ b/kernel/drivers/Makefile
@@ -1,11 +1,11 @@
-OBJS = tty.o gdt.o idt.o isr.o timer.o keyboard.o \
- fs.o cpuid.o
-
-CC = i686-elf-gcc # cross-compiler
-CFLAGS = -m32 -fno-stack-protector -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -ffreestanding -Wall -Wextra -Werror -g -c
-
-
-all:${OBJS}
-
-%.o: %.c
- $(CC) $(CFLAGS) $< -o $@
+OBJS = tty.o gdt.o idt.o isr.o timer.o keyboard.o \
+ fs.o cpuid.o
+
+CC = i686-elf-gcc # cross-compiler
+CFLAGS = -m32 -fno-stack-protector -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -ffreestanding -Wall -Wextra -Werror -g -c
+
+
+all:${OBJS}
+
+%.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
diff --git a/kernel/drivers/cpuid.c b/kernel/drivers/cpuid.c
index 921ccab..cbb9e33 100644
--- a/kernel/drivers/cpuid.c
+++ b/kernel/drivers/cpuid.c
@@ -1,195 +1,195 @@
-#include "cpuid.h"
-#include "../libc/string.h"
-#define INTEL_MAGIC_NUMBER 0x756e6547
-#define AMD_MAGIC_NUMBER 0x68747541
-#define UNRECOGNIZED_CPU 0xBADFF
-
-static cpuid_t get_cpuid(icpuid_t cpu);
-static icpuid_t detect_cpu(void);
-static icpuid_t intel_cpu(void);
-static icpuid_t amd_cpu(void);
-static icpuid_t generic_cpu(void);
-
-icpuid_t detect_cpu(void) {
- uint32_t ebx, null;
- icpuid_t i_cpu;
-
- cpuid(0, null, ebx, null, null);
-
- // Select CPU brand
- switch(ebx) {
- case INTEL_MAGIC_NUMBER:
- i_cpu = intel_cpu();
- break;
- case AMD_MAGIC_NUMBER:
- i_cpu = amd_cpu();
- break;
- default:
- i_cpu = generic_cpu();
- break;
- }
-
- return i_cpu;
-}
-
-icpuid_t intel_cpu(void) {
- uint32_t eax, ebx, null;
- icpuid_t icpu;
-
- // Fill the structure
- cpuid(1, eax, ebx, null, null);
- icpu.model = (eax >> 4) & 0xF;
- icpu.family = (eax >> 8) & 0xF;
- icpu.type = (eax >> 12) & 0xF;
- icpu.brand = INTEL_MAGIC_NUMBER;
- icpu.stepping = eax & 0xF;
- icpu.reserved = eax >> 14;
-
- return icpu;
-}
-
-icpuid_t amd_cpu(void) {
- uint32_t eax, null;
- icpuid_t icpu;
-
- // Fill the structure
- cpuid(1, eax, null, null, null);
- icpu.model = (eax >> 4) & 0xF;
- icpu.family = (eax >> 8) & 0xF;
- icpu.stepping = eax & 0xF;
- icpu.reserved = eax >> 12;
- icpu.brand = AMD_MAGIC_NUMBER;
-
- return icpu;
-}
-
-icpuid_t generic_cpu(void) {
- icpuid_t icpu;
-
- icpu.brand = UNRECOGNIZED_CPU; // Magic number for unknown CPUs
-
- return icpu;
-}
-
-cpuid_t get_cpuid(icpuid_t cpu) {
- cpuid_t cpuid;
- uint8_t model[64];
-
- // Recognize CPU brand
- if(cpu.brand == AMD_MAGIC_NUMBER) {
- switch(cpu.family) {
- case 4:
- strcpy(model, (uint8_t*)"486 model "); // Set model name
- strcat(model, (void*)cpu.model); // Set model version
- cpuid.model = model;
- break;
- case 5:
- switch(cpu.model) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- strcpy(model, (uint8_t*)"K6 model "); // Set model name
- strcat(model, (void*)cpu.model); // Set model version
- cpuid.model = model;
- break;
- case 8:
- strcpy(model, (uint8_t*)"K6-2 model "); // Set model name
- strcat(model, (void*)cpu.model); // Set model version
- cpuid.model = model;
- break;
- case 9:
- strcpy(model, (uint8_t*)"K6-III model "); // Set model name
- strcat(model, (void*)cpu.model); // Set model version
- cpuid.model = model;
- break;
- default:
- strcpy(model, (uint8_t*)"K5/K6 model "); // Set model name
- strcat(model, (void*)cpu.model); // Set model version
- cpuid.model = model;
- break;
- }
- break;
- case 6:
- switch(cpu.model) {
- case 1:
- case 2:
- case 3:
- cpuid.model = (uint8_t*)"Duron model 3";
- break;
- case 4:
- strcpy(model, (uint8_t*)"Athlon model ");
- strcat(model, (void*)cpu.model);
- cpuid.model = model;
- break;
- case 6:
- cpuid.model = (uint8_t*)"Athlon MP/Mobile Athlon Model 6";
- break;
- case 7:
- cpuid.model = (uint8_t*)"Mobile Duron Model 7";
- break;
- default:
- strcpy(model, (uint8_t*)"Duron/Athlon model ");
- strcat(model, (void*)cpu.model);
- cpuid.model = model;
- break;
- }
- break;
- }
- } else if(cpu.brand == INTEL_MAGIC_NUMBER) {
- switch(cpu.type) {
- case 0:
- cpuid.type =(uint8_t*)"Original OEM";
- break;
- case 1:
- cpuid.type = (uint8_t*)"Overdrive";
- break;
- case 2:
- cpuid.type = (uint8_t*)"Dual-capable";
- break;
- case 3:
- cpuid.type = (uint8_t*)"Reserved";
- break;
- }
-
- switch(cpu.family) {
- case 3:
- cpuid.family = (uint8_t*)"i386";
- break;
- case 4:
- cpuid.family = (uint8_t*)"i486";
- break;
- case 5:
- cpuid.family = (uint8_t*)"Pentium II Model 5/Xeon/Celeron";
- break;
- case 6:
- cpuid.family = (uint8_t*)"Pentium Pro";
- break;
- case 15:
- cpuid.family = (uint8_t*)"Pentium 4";
- break;
- }
- } else if(cpu.brand == UNRECOGNIZED_CPU)
- cpuid.family = (uint8_t*)"Generic (x86) CPU";
-
- return cpuid;
-}
-
-uint8_t *get_cpu_type() {
- icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
- cpuid_t cpu_type = get_cpuid(icpu);
-
- return (uint8_t*)cpu_type.type;
-}
-
-uint8_t *get_cpu_family() {
- icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
- cpuid_t cpu_family = get_cpuid(icpu);
-
- return (uint8_t*)cpu_family.family;
-
-}
+#include "cpuid.h"
+#include "../libc/string.h"
+#define INTEL_MAGIC_NUMBER 0x756e6547
+#define AMD_MAGIC_NUMBER 0x68747541
+#define UNRECOGNIZED_CPU 0xBADFF
+
+static cpuid_t get_cpuid(icpuid_t cpu);
+static icpuid_t detect_cpu(void);
+static icpuid_t intel_cpu(void);
+static icpuid_t amd_cpu(void);
+static icpuid_t generic_cpu(void);
+
+icpuid_t detect_cpu(void) {
+ uint32_t ebx, null;
+ icpuid_t i_cpu;
+
+ cpuid(0, null, ebx, null, null);
+
+ // Select CPU brand
+ switch(ebx) {
+ case INTEL_MAGIC_NUMBER:
+ i_cpu = intel_cpu();
+ break;
+ case AMD_MAGIC_NUMBER:
+ i_cpu = amd_cpu();
+ break;
+ default:
+ i_cpu = generic_cpu();
+ break;
+ }
+
+ return i_cpu;
+}
+
+icpuid_t intel_cpu(void) {
+ uint32_t eax, ebx, null;
+ icpuid_t icpu;
+
+ // Fill the structure
+ cpuid(1, eax, ebx, null, null);
+ icpu.model = (eax >> 4) & 0xF;
+ icpu.family = (eax >> 8) & 0xF;
+ icpu.type = (eax >> 12) & 0xF;
+ icpu.brand = INTEL_MAGIC_NUMBER;
+ icpu.stepping = eax & 0xF;
+ icpu.reserved = eax >> 14;
+
+ return icpu;
+}
+
+icpuid_t amd_cpu(void) {
+ uint32_t eax, null;
+ icpuid_t icpu;
+
+ // Fill the structure
+ cpuid(1, eax, null, null, null);
+ icpu.model = (eax >> 4) & 0xF;
+ icpu.family = (eax >> 8) & 0xF;
+ icpu.stepping = eax & 0xF;
+ icpu.reserved = eax >> 12;
+ icpu.brand = AMD_MAGIC_NUMBER;
+
+ return icpu;
+}
+
+icpuid_t generic_cpu(void) {
+ icpuid_t icpu;
+
+ icpu.brand = UNRECOGNIZED_CPU; // Magic number for unknown CPUs
+
+ return icpu;
+}
+
+cpuid_t get_cpuid(icpuid_t cpu) {
+ cpuid_t cpuid;
+ uint8_t model[64];
+
+ // Recognize CPU brand
+ if(cpu.brand == AMD_MAGIC_NUMBER) {
+ switch(cpu.family) {
+ case 4:
+ strcpy(model, (uint8_t*)"486 model "); // Set model name
+ strcat(model, (void*)cpu.model); // Set model version
+ cpuid.model = model;
+ break;
+ case 5:
+ switch(cpu.model) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ strcpy(model, (uint8_t*)"K6 model "); // Set model name
+ strcat(model, (void*)cpu.model); // Set model version
+ cpuid.model = model;
+ break;
+ case 8:
+ strcpy(model, (uint8_t*)"K6-2 model "); // Set model name
+ strcat(model, (void*)cpu.model); // Set model version
+ cpuid.model = model;
+ break;
+ case 9:
+ strcpy(model, (uint8_t*)"K6-III model "); // Set model name
+ strcat(model, (void*)cpu.model); // Set model version
+ cpuid.model = model;
+ break;
+ default:
+ strcpy(model, (uint8_t*)"K5/K6 model "); // Set model name
+ strcat(model, (void*)cpu.model); // Set model version
+ cpuid.model = model;
+ break;
+ }
+ break;
+ case 6:
+ switch(cpu.model) {
+ case 1:
+ case 2:
+ case 3:
+ cpuid.model = (uint8_t*)"Duron model 3";
+ break;
+ case 4:
+ strcpy(model, (uint8_t*)"Athlon model ");
+ strcat(model, (void*)cpu.model);
+ cpuid.model = model;
+ break;
+ case 6:
+ cpuid.model = (uint8_t*)"Athlon MP/Mobile Athlon Model 6";
+ break;
+ case 7:
+ cpuid.model = (uint8_t*)"Mobile Duron Model 7";
+ break;
+ default:
+ strcpy(model, (uint8_t*)"Duron/Athlon model ");
+ strcat(model, (void*)cpu.model);
+ cpuid.model = model;
+ break;
+ }
+ break;
+ }
+ } else if(cpu.brand == INTEL_MAGIC_NUMBER) {
+ switch(cpu.type) {
+ case 0:
+ cpuid.type =(uint8_t*)"Original OEM";
+ break;
+ case 1:
+ cpuid.type = (uint8_t*)"Overdrive";
+ break;
+ case 2:
+ cpuid.type = (uint8_t*)"Dual-capable";
+ break;
+ case 3:
+ cpuid.type = (uint8_t*)"Reserved";
+ break;
+ }
+
+ switch(cpu.family) {
+ case 3:
+ cpuid.family = (uint8_t*)"i386";
+ break;
+ case 4:
+ cpuid.family = (uint8_t*)"i486";
+ break;
+ case 5:
+ cpuid.family = (uint8_t*)"Pentium II Model 5/Xeon/Celeron";
+ break;
+ case 6:
+ cpuid.family = (uint8_t*)"Pentium Pro";
+ break;
+ case 15:
+ cpuid.family = (uint8_t*)"Pentium 4";
+ break;
+ }
+ } else if(cpu.brand == UNRECOGNIZED_CPU)
+ cpuid.family = (uint8_t*)"Generic (x86) CPU";
+
+ return cpuid;
+}
+
+uint8_t *get_cpu_type() {
+ icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
+ cpuid_t cpu_type = get_cpuid(icpu);
+
+ return (uint8_t*)cpu_type.type;
+}
+
+uint8_t *get_cpu_family() {
+ icpuid_t icpu = detect_cpu(); // Detect CPU brand(Intel, AMD or generic x86)
+ cpuid_t cpu_family = get_cpuid(icpu);
+
+ return (uint8_t*)cpu_family.family;
+
+}
diff --git a/kernel/drivers/cpuid.h b/kernel/drivers/cpuid.h
index ab11068..4198821 100644
--- a/kernel/drivers/cpuid.h
+++ b/kernel/drivers/cpuid.h
@@ -1,36 +1,36 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef CPUID_H
-#define CPUID_H
-
-#include
-#define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b"(b), "=d" (d) : "a" (in));
-
-typedef struct {
- uint32_t model;
- uint32_t family;
- uint32_t type;
- uint32_t brand;
- uint32_t stepping;
- uint32_t reserved;
-} icpuid_t;
-
-typedef struct {
- uint8_t *model;
- uint8_t *family;
- uint8_t *type;
- uint8_t *brand;
- uint8_t *stepping;
- uint8_t *reserved;
-} cpuid_t;
-
-// return type and family processor
-uint8_t *get_cpu_type();
-uint8_t *get_cpu_family();
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef CPUID_H
+#define CPUID_H
+
+#include
+#define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b"(b), "=d" (d) : "a" (in));
+
+typedef struct {
+ uint32_t model;
+ uint32_t family;
+ uint32_t type;
+ uint32_t brand;
+ uint32_t stepping;
+ uint32_t reserved;
+} icpuid_t;
+
+typedef struct {
+ uint8_t *model;
+ uint8_t *family;
+ uint8_t *type;
+ uint8_t *brand;
+ uint8_t *stepping;
+ uint8_t *reserved;
+} cpuid_t;
+
+// return type and family processor
+uint8_t *get_cpu_type();
+uint8_t *get_cpu_family();
+
+#endif
diff --git a/kernel/drivers/fs.c b/kernel/drivers/fs.c
index 7a49a6a..3ceb824 100644
--- a/kernel/drivers/fs.c
+++ b/kernel/drivers/fs.c
@@ -1,47 +1,47 @@
-#include "fs.h"
-
-fs_node_t *fs_root = 0; // Initialize the root of the filesystem
-
-uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
- // Check if inode got a read callback from the kernel
- if(node->read != 0)
- return node->read(node, offset, size, buffer);
- else
- return 0;
-}
-
-uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
- // Check if inode got a write callback from the kernel
- if(node->write != 0)
- return node->write(node, offset, size, buffer);
- else
- return 0;
-}
-
-void open_fs(fs_node_t *node) {
- // Check if inode got a open callback from the kernel
- if(node->open != 0)
- return node->open(node);
-}
-
-void close_fs(fs_node_t *node) {
- // Check if inode got a close callback from the kernel
- if(node->close != 0)
- return node->close(node);
-}
-
-struct dirent *readdir_fs(fs_node_t *node, uint32_t index) {
- // Read dir content(only if file descriptor is FS_DIRECTORY)
- if((node->flags&0x7) == FS_DIRECTORY && node->readdir != 0)
- return node->readdir(node, index);
- else
- return 0;
-}
-
-fs_node_t *finddir_fs(fs_node_t *node, char *name) {
- // Check if an inode is a directory
- if((node->flags&0x7) == FS_DIRECTORY && node->finddir != 0)
- return node->finddir(node, name);
- else
- return 0;
+#include "fs.h"
+
+fs_node_t *fs_root = 0; // Initialize the root of the filesystem
+
+uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ // Check if inode got a read callback from the kernel
+ if(node->read != 0)
+ return node->read(node, offset, size, buffer);
+ else
+ return 0;
+}
+
+uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ // Check if inode got a write callback from the kernel
+ if(node->write != 0)
+ return node->write(node, offset, size, buffer);
+ else
+ return 0;
+}
+
+void open_fs(fs_node_t *node) {
+ // Check if inode got a open callback from the kernel
+ if(node->open != 0)
+ return node->open(node);
+}
+
+void close_fs(fs_node_t *node) {
+ // Check if inode got a close callback from the kernel
+ if(node->close != 0)
+ return node->close(node);
+}
+
+struct dirent *readdir_fs(fs_node_t *node, uint32_t index) {
+ // Read dir content(only if file descriptor is FS_DIRECTORY)
+ if((node->flags&0x7) == FS_DIRECTORY && node->readdir != 0)
+ return node->readdir(node, index);
+ else
+ return 0;
+}
+
+fs_node_t *finddir_fs(fs_node_t *node, char *name) {
+ // Check if an inode is a directory
+ if((node->flags&0x7) == FS_DIRECTORY && node->finddir != 0)
+ return node->finddir(node, name);
+ else
+ return 0;
}
\ No newline at end of file
diff --git a/kernel/drivers/fs.h b/kernel/drivers/fs.h
index cc5385d..5af137e 100644
--- a/kernel/drivers/fs.h
+++ b/kernel/drivers/fs.h
@@ -1,84 +1,84 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef FS_H
-#define FS_H
-
-#include
-/* This Virtual File System(VFS) is a simplified version of
- * standard UNIX VFS where all files comes organized in a graph
- * of nodes. Keeping in mind the concept of "everything is a file" we can
- * store a file, a directory, a serial device or anything else just by adding
- * a new node to the data structure.
- * And this is a list of common operations:
- * - Open: Initialize a new node as a file descriptor
- * - Close: CLose a node
- * - Read: return the content of a node
- * - Write: set content to node
- * - Readdir: Return directory content
- * - Finddir: Given a specific name find the corresponding child node.*/
-
-// Define some standard node types
-#define FS_FILE 0x01
-#define FS_DIRECTORY 0x02
-#define FS_CHARDEVICE 0x03
-#define FS_BLOCKDEVICE 0x04
-#define FS_PIPE 0x05
-#define FS_SYMLINK 0x06
-#define FS_MOUNTPOINT 0x08
-
-struct fs_node;
-
-/* Define some callbacks to be called when read/write/open/close
- * operations are called */
-typedef uint32_t (*read_type_t)(struct fs_node*, uint32_t, uint32_t, uint8_t*);
-typedef uint32_t (*write_type_t)(struct fs_node*, uint32_t, uint32_t, uint8_t*);
-typedef void (*open_type_t)(struct fs_node*);
-typedef void (*close_type_t)(struct fs_node*);
-typedef struct dirent*(*readdir_type_t)(struct fs_node*, uint32_t);
-typedef struct fs_node*(*finddir_type_t)(struct fs_node*, char *name);
-
-// This define the structure of a node
-typedef struct fs_node {
- uint8_t name[128]; // File name
- uint32_t mask; // Permission mask
- uint32_t uid; // Owning user
- uint32_t gid; // Owning group
- uint32_t flags; // Node type
- uint32_t inode; // used by file systems to identify files
- uint32_t length; // Length of the file, in bytes.
- uint32_t impl;
- // Callback section
- read_type_t read;
- write_type_t write;
- open_type_t open;
- close_type_t close;
- readdir_type_t readdir;
- finddir_type_t finddir;
- struct fs_node *ptr; // Used by mountpoints and symlinks
-} fs_node_t;
-
-struct dirent {
- uint8_t name[120]; // File name
- uint32_t ino; // POSIX standard requires inode number;
-};
-
-// Filesystem root
-extern fs_node_t *fs_root;
-
-/* Write/Read/Open/Close operations
- * NOTE: those functions are NOT like the Callback
- * functions; the first one deals with inodes while
- * the second one deals with file descriptors. */
-uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
-uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
-void open_fs(fs_node_t *node);
-void close_fs(fs_node_t *node);
-struct dirent *readdir_fs(fs_node_t *node, uint32_t index);
-fs_node_t *finddir_fs(fs_node_t *node, char *name);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef FS_H
+#define FS_H
+
+#include
+/* This Virtual File System(VFS) is a simplified version of
+ * standard UNIX VFS where all files comes organized in a graph
+ * of nodes. Keeping in mind the concept of "everything is a file" we can
+ * store a file, a directory, a serial device or anything else just by adding
+ * a new node to the data structure.
+ * And this is a list of common operations:
+ * - Open: Initialize a new node as a file descriptor
+ * - Close: CLose a node
+ * - Read: return the content of a node
+ * - Write: set content to node
+ * - Readdir: Return directory content
+ * - Finddir: Given a specific name find the corresponding child node.*/
+
+// Define some standard node types
+#define FS_FILE 0x01
+#define FS_DIRECTORY 0x02
+#define FS_CHARDEVICE 0x03
+#define FS_BLOCKDEVICE 0x04
+#define FS_PIPE 0x05
+#define FS_SYMLINK 0x06
+#define FS_MOUNTPOINT 0x08
+
+struct fs_node;
+
+/* Define some callbacks to be called when read/write/open/close
+ * operations are called */
+typedef uint32_t (*read_type_t)(struct fs_node*, uint32_t, uint32_t, uint8_t*);
+typedef uint32_t (*write_type_t)(struct fs_node*, uint32_t, uint32_t, uint8_t*);
+typedef void (*open_type_t)(struct fs_node*);
+typedef void (*close_type_t)(struct fs_node*);
+typedef struct dirent*(*readdir_type_t)(struct fs_node*, uint32_t);
+typedef struct fs_node*(*finddir_type_t)(struct fs_node*, char *name);
+
+// This define the structure of a node
+typedef struct fs_node {
+ uint8_t name[128]; // File name
+ uint32_t mask; // Permission mask
+ uint32_t uid; // Owning user
+ uint32_t gid; // Owning group
+ uint32_t flags; // Node type
+ uint32_t inode; // used by file systems to identify files
+ uint32_t length; // Length of the file, in bytes.
+ uint32_t impl;
+ // Callback section
+ read_type_t read;
+ write_type_t write;
+ open_type_t open;
+ close_type_t close;
+ readdir_type_t readdir;
+ finddir_type_t finddir;
+ struct fs_node *ptr; // Used by mountpoints and symlinks
+} fs_node_t;
+
+struct dirent {
+ uint8_t name[120]; // File name
+ uint32_t ino; // POSIX standard requires inode number;
+};
+
+// Filesystem root
+extern fs_node_t *fs_root;
+
+/* Write/Read/Open/Close operations
+ * NOTE: those functions are NOT like the Callback
+ * functions; the first one deals with inodes while
+ * the second one deals with file descriptors. */
+uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
+uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
+void open_fs(fs_node_t *node);
+void close_fs(fs_node_t *node);
+struct dirent *readdir_fs(fs_node_t *node, uint32_t index);
+fs_node_t *finddir_fs(fs_node_t *node, char *name);
+
+#endif
diff --git a/kernel/drivers/gdt.c b/kernel/drivers/gdt.c
index c675d4b..ab40ac6 100644
--- a/kernel/drivers/gdt.c
+++ b/kernel/drivers/gdt.c
@@ -1,103 +1,103 @@
-#include "gdt.h"
-
-// Internal method
-extern void gdt_flush(uint32_t); // Defined on cpu/gdt.asm
-static gdt_entry_t construct_null_entry();
-static gdt_entry_t construct_entry(gdt_access_t access);
-static void init_gdt();
-
-gdt_entry_t gdt_entries[5];
-gdt_ptr_t gdt_ptr;
-
-
-// This method will be called by the kernel
-void gdt_setup() {
- init_gdt();
-}
-
-static void init_gdt() {
- gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
- gdt_ptr.base = (uint32_t)&gdt_entries;
-
- gdt_entry_t null_segment = construct_null_entry();
- gdt_entry_t kernel_mode_code_segment = construct_entry(
- (struct gdt_access){
- .type = GDT_CODE_TYPE_EXEC_READ,
- .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
- .dpl = GDT_RING0,
- .p = GDT_SEGMENT_PRESENT
- }
- );
- gdt_entry_t kernel_mode_data_segment = construct_entry(
- (struct gdt_access){
- .type = GDT_DATA_TYPE_READ_WRITE,
- .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
- .dpl = GDT_RING0,
- .p = GDT_SEGMENT_PRESENT
- }
- );
- gdt_entry_t user_mode_code_segment = construct_entry(
- (struct gdt_access){
- .type = GDT_CODE_TYPE_EXEC_READ,
- .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
- .dpl = GDT_RING3,
- .p = GDT_SEGMENT_PRESENT
- }
- );
- gdt_entry_t user_mode_data_segment = construct_entry(
- (struct gdt_access){
- .type = GDT_DATA_TYPE_READ_WRITE,
- .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
- .dpl = GDT_RING3,
- .p = GDT_SEGMENT_PRESENT
- }
- );
-
- gdt_entries[0] = null_segment;
- gdt_entries[1] = kernel_mode_code_segment;
- gdt_entries[2] = kernel_mode_data_segment;
- gdt_entries[3] = user_mode_code_segment;
- gdt_entries[4] = user_mode_data_segment;
-
- gdt_flush((uint32_t)&gdt_ptr);
-}
-
-static gdt_entry_t construct_entry(gdt_access_t access) {
- gdt_entry_t entry = (struct gdt_entry_struct) {
- .base_low = GDT_BASE & 0xFFFF,
- .base_middle = (GDT_BASE >> 16) & 0xFF,
- .base_high = (GDT_BASE >> 24) & 0xFF,
- .limit_low = (GDT_LIMIT & 0xFFFF),
- .access = access,
- .granularity = (struct gdt_granularity) {
- .g = GDT_GRANULARITY_4K,
- .d = GDT_OPERAND_SIZE_32,
- .zero = 0,
- .seglen = GDT_SEGMENT_LENGTH
- }
- };
- return entry;
-}
-
-// The only difference is in the access
-static gdt_entry_t construct_null_entry() {
- gdt_entry_t null_entry = (struct gdt_entry_struct) {
- .base_low = 0,
- .base_middle = 0,
- .base_high = 0,
- .limit_low = 0,
- .access = (struct gdt_access) {
- .p = 0,
- .dpl = 0,
- .dt = 0,
- .type = 0
- },
- .granularity = (struct gdt_granularity) {
- .g = 0,
- .d = 0,
- .zero = 0,
- .seglen = 0
- }
- };
- return null_entry;
+#include "gdt.h"
+
+// Internal method
+extern void gdt_flush(uint32_t); // Defined on cpu/gdt.asm
+static gdt_entry_t construct_null_entry();
+static gdt_entry_t construct_entry(gdt_access_t access);
+static void init_gdt();
+
+gdt_entry_t gdt_entries[5];
+gdt_ptr_t gdt_ptr;
+
+
+// This method will be called by the kernel
+void gdt_setup() {
+ init_gdt();
+}
+
+static void init_gdt() {
+ gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
+ gdt_ptr.base = (uint32_t)&gdt_entries;
+
+ gdt_entry_t null_segment = construct_null_entry();
+ gdt_entry_t kernel_mode_code_segment = construct_entry(
+ (struct gdt_access){
+ .type = GDT_CODE_TYPE_EXEC_READ,
+ .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
+ .dpl = GDT_RING0,
+ .p = GDT_SEGMENT_PRESENT
+ }
+ );
+ gdt_entry_t kernel_mode_data_segment = construct_entry(
+ (struct gdt_access){
+ .type = GDT_DATA_TYPE_READ_WRITE,
+ .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
+ .dpl = GDT_RING0,
+ .p = GDT_SEGMENT_PRESENT
+ }
+ );
+ gdt_entry_t user_mode_code_segment = construct_entry(
+ (struct gdt_access){
+ .type = GDT_CODE_TYPE_EXEC_READ,
+ .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
+ .dpl = GDT_RING3,
+ .p = GDT_SEGMENT_PRESENT
+ }
+ );
+ gdt_entry_t user_mode_data_segment = construct_entry(
+ (struct gdt_access){
+ .type = GDT_DATA_TYPE_READ_WRITE,
+ .dt = GDT_CODE_AND_DATA_DESCRIPTOR,
+ .dpl = GDT_RING3,
+ .p = GDT_SEGMENT_PRESENT
+ }
+ );
+
+ gdt_entries[0] = null_segment;
+ gdt_entries[1] = kernel_mode_code_segment;
+ gdt_entries[2] = kernel_mode_data_segment;
+ gdt_entries[3] = user_mode_code_segment;
+ gdt_entries[4] = user_mode_data_segment;
+
+ gdt_flush((uint32_t)&gdt_ptr);
+}
+
+static gdt_entry_t construct_entry(gdt_access_t access) {
+ gdt_entry_t entry = (struct gdt_entry_struct) {
+ .base_low = GDT_BASE & 0xFFFF,
+ .base_middle = (GDT_BASE >> 16) & 0xFF,
+ .base_high = (GDT_BASE >> 24) & 0xFF,
+ .limit_low = (GDT_LIMIT & 0xFFFF),
+ .access = access,
+ .granularity = (struct gdt_granularity) {
+ .g = GDT_GRANULARITY_4K,
+ .d = GDT_OPERAND_SIZE_32,
+ .zero = 0,
+ .seglen = GDT_SEGMENT_LENGTH
+ }
+ };
+ return entry;
+}
+
+// The only difference is in the access
+static gdt_entry_t construct_null_entry() {
+ gdt_entry_t null_entry = (struct gdt_entry_struct) {
+ .base_low = 0,
+ .base_middle = 0,
+ .base_high = 0,
+ .limit_low = 0,
+ .access = (struct gdt_access) {
+ .p = 0,
+ .dpl = 0,
+ .dt = 0,
+ .type = 0
+ },
+ .granularity = (struct gdt_granularity) {
+ .g = 0,
+ .d = 0,
+ .zero = 0,
+ .seglen = 0
+ }
+ };
+ return null_entry;
}
\ No newline at end of file
diff --git a/kernel/drivers/gdt.h b/kernel/drivers/gdt.h
index d105985..a7fa647 100644
--- a/kernel/drivers/gdt.h
+++ b/kernel/drivers/gdt.h
@@ -1,139 +1,139 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _GDT_H_
-#define _GDT_H_
-
-#include
-/*
- * First a bit of theory:
- * GDT(Global Descriptor Table) is a complex data structure used in x86 systems
- * to define memory areas.
- * Technically speaking GDT is formed by an array of 8-bytes segment descriptors,
- * the first descriptor of the GDT is always a NULL one and CANNOT be used to allocate
- * memory; so we need at least two descriptors(plus the null descriptor) to successfully allocate
- * data on our memory.
- * In x86 architecture there're two methods to provide virtual memory: Segmentation and Paging:
- * With the first one every memory access is done within his own segment, so each address(of a process)
- * is added to the segment's base address and checked against the segment's length.
- * With paging, however, the address space is split into blocks(usually of 4KiB) called pages.
- * Each page can be mapped to physical memory or it can be unmapped(to create virtual memory).
- * Segmentation is a built-in functionality of x86 architecture, so to get around this we need to
- * define our own GDT. A cool thing segmentation can do for us is to set Ring Level:
- * a privilege level to allow our process to run in a 'unprivileged' mode(called user mode, ring 3)
- * and to allow drivers(or kernel related stuff) to run in a 'supervisor-mode'(called kernel mode, ring 0).
- * Usually bootloader(such as GRUB) sets up GDT for us, the problem is that we cannot known where it is or
- * if it is has been overwritten during some other tasks. So it's a good idea to implement
- * a new GDT ourself.
- */
-
-/* Those values were taken from Intel's developer manual */
-
-// GDT fields
-#define GDT_BASE 0x00000000
-#define GDT_LIMIT 0xFFFFFFFF
-// GDT granularity
-#define GDT_SEGMENT_LENGTH 0xF
-#define GDT_OPERAND_SIZE_16 0
-#define GDT_OPERAND_SIZE_32 1
-#define GDT_GRANULARITY_1K 0
-#define GDT_GRANULARITY_4K 1
-// GDT access type fields
-#define GDT_DATA_TYPE_READ_ONLY 0x0
-#define GDT_DATA_TYPE_READ_ONLY_ACCESSED 0x1
-#define GDT_DATA_TYPE_READ_WRITE 0x2
-#define GDT_DATA_TYPE_READ_WRITE_ACCESSED 0x3
-#define GDT_DATA_TYPE_READ_ONLY_EXPAND_DOWN 0x4
-#define GDT_DATA_TYPE_READ_ONLY_EXPAND_DOWN_ACCESSED 0x5
-#define GDT_DATA_TYPE_READ_WRITE_EXPAND_DOWN 0x6
-#define GDT_DATA_TYPE_READ_WRITE_EXPAND_DOWN_ACCESSED 0x7
-#define GDT_DATA_TYPE_EXEC_ONLY 0x8
-#define GDT_CODE_TYPE_EXEC_ONLY_ACCESSED 0x9
-#define GDT_CODE_TYPE_EXEC_READ 0xA
-#define GDT_CODE_TYPE_EXEC_READ_ACCESSED 0xB
-#define GDT_CODE_TYPE_EXEC_CONFORMING 0xC
-#define GDT_CODE_TYPE_EXEC_CONFORMING_ACCESSED 0xD
-#define GDT_CODE_TYPE_EXEC_READ_CONFORMING 0xE
-#define GDT_CODE_TYPE_EXEC_READ_CONFORMING_ACCESSED 0xF
-// Descriptor type fields
-#define GDT_SYSTEM_DESCRIPTOR 0
-#define GDT_CODE_AND_DATA_DESCRIPTOR 1
-// GDT Ring number
-#define GDT_RING0 0
-#define GDT_RING1 1
-#define GDT_RING2 2
-#define GDT_RING3 3
-// 'Present' field
-#define GDT_SEGMENT_NOT_PRESENT 0
-#define GDT_SEGMENT_PRESENT 1
-
-
-/* Global Descriptor Table (GDT) implementation */
-/* gdt_access is used to access portion of the GDT
- * | 0 - 3 | 4 | 3 - 6 | 7 |
- * | Type | DT | DPL | P |
- * Type: Which type
- * DT: descriptor type
- * DPL: Kernel ring(0-3)
- * P: is segment present? (bool)
- */
-struct gdt_access {
- uint8_t type: 4; // 4 Bits
- uint8_t dt: 1; // 1 Bit
- uint8_t dpl: 2; // 2 Bits
- uint8_t p: 1; // 1 Bits
-}__attribute__((packed));
-typedef struct gdt_access gdt_access_t;
-
-/* gdt_granularity is used to get portion of GDT entry
- * | 0 - 3 | 4 | 5 | 6 | 7 |
- * | seglen | 0 | D | G |
- * seglen: segment length
- * 0: Always zero
- * D: Operand size (0 = 16 bit, 1 = 32 bit)
- * G: granularity (0 = 1 Byte, 1 = 4KiB)
- */
-struct gdt_granularity {
- uint8_t seglen: 4;
- uint8_t zero: 2;
- uint8_t d: 1;
- uint8_t g: 1;
-}__attribute__((packed));
-typedef struct gdt_granularity gdt_gran_t;
-
-/* gdt_entry_struct contains the value of a single GDT entry
- * Each slice is 64 bits.
- * | 0 - 15 | 16 - 31 | 32 - 39 | 40 - 47 | 48 - 55 | 56 - 63 |
- * | lim low| base low|base mid | access | gran | base hg |
- * lim low: Lower 16 bits of the limit
- * base low: Lower 16 bits of the base
- * base mid: Next 8 bits of the base
- * access: access flag, e.g. which ring this segment can be used in.
- * gran.
-*/
-struct gdt_entry_struct {
- uint16_t limit_low;
- uint16_t base_low;
- uint8_t base_middle;
- gdt_access_t access;
- gdt_gran_t granularity;
- uint8_t base_high;
-}__attribute__((packed));
-typedef struct gdt_entry_struct gdt_entry_t;
-
-/* Also we have to define a pointer to the data structure
- * This is needed to locate it later */
-struct gdt_ptr {
- uint16_t limit;
- uint32_t base;
-}__attribute__((packed));
-typedef struct gdt_ptr gdt_ptr_t;
-
-/* GDT Kernel API */
-void gdt_setup();
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _GDT_H_
+#define _GDT_H_
+
+#include
+/*
+ * First a bit of theory:
+ * GDT(Global Descriptor Table) is a complex data structure used in x86 systems
+ * to define memory areas.
+ * Technically speaking GDT is formed by an array of 8-bytes segment descriptors,
+ * the first descriptor of the GDT is always a NULL one and CANNOT be used to allocate
+ * memory; so we need at least two descriptors(plus the null descriptor) to successfully allocate
+ * data on our memory.
+ * In x86 architecture there're two methods to provide virtual memory: Segmentation and Paging:
+ * With the first one every memory access is done within his own segment, so each address(of a process)
+ * is added to the segment's base address and checked against the segment's length.
+ * With paging, however, the address space is split into blocks(usually of 4KiB) called pages.
+ * Each page can be mapped to physical memory or it can be unmapped(to create virtual memory).
+ * Segmentation is a built-in functionality of x86 architecture, so to get around this we need to
+ * define our own GDT. A cool thing segmentation can do for us is to set Ring Level:
+ * a privilege level to allow our process to run in a 'unprivileged' mode(called user mode, ring 3)
+ * and to allow drivers(or kernel related stuff) to run in a 'supervisor-mode'(called kernel mode, ring 0).
+ * Usually bootloader(such as GRUB) sets up GDT for us, the problem is that we cannot known where it is or
+ * if it is has been overwritten during some other tasks. So it's a good idea to implement
+ * a new GDT ourself.
+ */
+
+/* Those values were taken from Intel's developer manual */
+
+// GDT fields
+#define GDT_BASE 0x00000000
+#define GDT_LIMIT 0xFFFFFFFF
+// GDT granularity
+#define GDT_SEGMENT_LENGTH 0xF
+#define GDT_OPERAND_SIZE_16 0
+#define GDT_OPERAND_SIZE_32 1
+#define GDT_GRANULARITY_1K 0
+#define GDT_GRANULARITY_4K 1
+// GDT access type fields
+#define GDT_DATA_TYPE_READ_ONLY 0x0
+#define GDT_DATA_TYPE_READ_ONLY_ACCESSED 0x1
+#define GDT_DATA_TYPE_READ_WRITE 0x2
+#define GDT_DATA_TYPE_READ_WRITE_ACCESSED 0x3
+#define GDT_DATA_TYPE_READ_ONLY_EXPAND_DOWN 0x4
+#define GDT_DATA_TYPE_READ_ONLY_EXPAND_DOWN_ACCESSED 0x5
+#define GDT_DATA_TYPE_READ_WRITE_EXPAND_DOWN 0x6
+#define GDT_DATA_TYPE_READ_WRITE_EXPAND_DOWN_ACCESSED 0x7
+#define GDT_DATA_TYPE_EXEC_ONLY 0x8
+#define GDT_CODE_TYPE_EXEC_ONLY_ACCESSED 0x9
+#define GDT_CODE_TYPE_EXEC_READ 0xA
+#define GDT_CODE_TYPE_EXEC_READ_ACCESSED 0xB
+#define GDT_CODE_TYPE_EXEC_CONFORMING 0xC
+#define GDT_CODE_TYPE_EXEC_CONFORMING_ACCESSED 0xD
+#define GDT_CODE_TYPE_EXEC_READ_CONFORMING 0xE
+#define GDT_CODE_TYPE_EXEC_READ_CONFORMING_ACCESSED 0xF
+// Descriptor type fields
+#define GDT_SYSTEM_DESCRIPTOR 0
+#define GDT_CODE_AND_DATA_DESCRIPTOR 1
+// GDT Ring number
+#define GDT_RING0 0
+#define GDT_RING1 1
+#define GDT_RING2 2
+#define GDT_RING3 3
+// 'Present' field
+#define GDT_SEGMENT_NOT_PRESENT 0
+#define GDT_SEGMENT_PRESENT 1
+
+
+/* Global Descriptor Table (GDT) implementation */
+/* gdt_access is used to access portion of the GDT
+ * | 0 - 3 | 4 | 3 - 6 | 7 |
+ * | Type | DT | DPL | P |
+ * Type: Which type
+ * DT: descriptor type
+ * DPL: Kernel ring(0-3)
+ * P: is segment present? (bool)
+ */
+struct gdt_access {
+ uint8_t type: 4; // 4 Bits
+ uint8_t dt: 1; // 1 Bit
+ uint8_t dpl: 2; // 2 Bits
+ uint8_t p: 1; // 1 Bits
+}__attribute__((packed));
+typedef struct gdt_access gdt_access_t;
+
+/* gdt_granularity is used to get portion of GDT entry
+ * | 0 - 3 | 4 | 5 | 6 | 7 |
+ * | seglen | 0 | D | G |
+ * seglen: segment length
+ * 0: Always zero
+ * D: Operand size (0 = 16 bit, 1 = 32 bit)
+ * G: granularity (0 = 1 Byte, 1 = 4KiB)
+ */
+struct gdt_granularity {
+ uint8_t seglen: 4;
+ uint8_t zero: 2;
+ uint8_t d: 1;
+ uint8_t g: 1;
+}__attribute__((packed));
+typedef struct gdt_granularity gdt_gran_t;
+
+/* gdt_entry_struct contains the value of a single GDT entry
+ * Each slice is 64 bits.
+ * | 0 - 15 | 16 - 31 | 32 - 39 | 40 - 47 | 48 - 55 | 56 - 63 |
+ * | lim low| base low|base mid | access | gran | base hg |
+ * lim low: Lower 16 bits of the limit
+ * base low: Lower 16 bits of the base
+ * base mid: Next 8 bits of the base
+ * access: access flag, e.g. which ring this segment can be used in.
+ * gran.
+*/
+struct gdt_entry_struct {
+ uint16_t limit_low;
+ uint16_t base_low;
+ uint8_t base_middle;
+ gdt_access_t access;
+ gdt_gran_t granularity;
+ uint8_t base_high;
+}__attribute__((packed));
+typedef struct gdt_entry_struct gdt_entry_t;
+
+/* Also we have to define a pointer to the data structure
+ * This is needed to locate it later */
+struct gdt_ptr {
+ uint16_t limit;
+ uint32_t base;
+}__attribute__((packed));
+typedef struct gdt_ptr gdt_ptr_t;
+
+/* GDT Kernel API */
+void gdt_setup();
+
+#endif
diff --git a/kernel/drivers/idt.c b/kernel/drivers/idt.c
index 4ca3936..ee5033c 100644
--- a/kernel/drivers/idt.c
+++ b/kernel/drivers/idt.c
@@ -1,122 +1,122 @@
-#include "idt.h"
-#include "../libc/string.h"
-#include "ports.h"
-
-// Internal method
-extern void idt_flush(idt_ptr_t*); // defined on cpu/idt.asm
-static void init_idt();
-static void idt_set_gate(uint8_t idx, void(*base), uint16_t selector, idt_flags_t flags);
-static void pic_remap(uint8_t offset1, uint8_t offset2);
-
-idt_entry_t idt_entries[256]; // 256 interrupts
-idt_ptr_t idt_ptr;
-
-// This method will be called by the kernel
-void idt_setup() {
- init_idt();
-}
-
-static void idt_set_gate(uint8_t idx, void(*base), uint16_t selector, idt_flags_t flags) {
- idt_entries[idx] = (struct idt_entry) {
- .base_low = (uint32_t)base & 0xFFFF,
- .base_high = ((uint32_t)base >> 16) & 0xFFFF,
- .seg_sel = selector,
- .flags = flags
- };
-}
-
-static void init_idt() {
- idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
- idt_ptr.base = idt_entries;
-
- memset(&idt_entries, 0, sizeof(idt_entry_t) * 256);
-
- idt_flags_t flags = {
- .reserved = IDT_FLAG_RESERVED, // Always 0x0E
- .dpl = 0,
- .p = 1
- };
- // Remap IDT with ISRs
- idt_set_gate(0, isr0, 0x08, flags);
- idt_set_gate(1, isr1, 0x08, flags);
- idt_set_gate(2, isr2, 0x08, flags);
- idt_set_gate(3, isr3, 0x08, flags);
- idt_set_gate(4, isr4, 0x08, flags);
- idt_set_gate(5, isr5, 0x08, flags);
- idt_set_gate(6, isr6, 0x08, flags);
- idt_set_gate(7, isr7, 0x08, flags);
- idt_set_gate(8, isr8, 0x08, flags);
- idt_set_gate(9, isr9, 0x08, flags);
- idt_set_gate(10, isr10, 0x08, flags);
- idt_set_gate(11, isr11, 0x08, flags);
- idt_set_gate(12, isr12, 0x08, flags);
- idt_set_gate(13, isr13, 0x08, flags);
- idt_set_gate(14, isr14, 0x08, flags);
- idt_set_gate(15, isr15, 0x08, flags);
- idt_set_gate(16, isr16, 0x08, flags);
- idt_set_gate(17, isr17, 0x08, flags);
- idt_set_gate(18, isr18, 0x08, flags);
- idt_set_gate(19, isr19, 0x08, flags);
- idt_set_gate(20, isr20, 0x08, flags);
- idt_set_gate(21, isr21, 0x08, flags);
- idt_set_gate(22, isr22, 0x08, flags);
- idt_set_gate(23, isr23, 0x08, flags);
- idt_set_gate(24, isr24, 0x08, flags);
- idt_set_gate(25, isr25, 0x08, flags);
- idt_set_gate(26, isr26, 0x08, flags);
- idt_set_gate(27, isr27, 0x08, flags);
- idt_set_gate(28, isr28, 0x08, flags);
- idt_set_gate(29, isr29, 0x08, flags);
- idt_set_gate(30, isr30, 0x08, flags);
- idt_set_gate(31, isr31, 0x08, flags);
-
- // Remap PIC
- pic_remap(PIC1_START_INTERRUPT, PIC2_START_INTERRUPT);
-
- // Also remap 15 entries for IRQs
- idt_set_gate(32, irq0, 0x08, flags);
- idt_set_gate(33, irq1, 0x08, flags);
- idt_set_gate(34, irq2, 0x08, flags);
- idt_set_gate(35, irq3, 0x08, flags);
- idt_set_gate(36, irq4, 0x08, flags);
- idt_set_gate(37, irq5, 0x08, flags);
- idt_set_gate(38, irq6, 0x08, flags);
- idt_set_gate(39, irq7, 0x08, flags);
- idt_set_gate(40, irq8, 0x08, flags);
- idt_set_gate(41, irq9, 0x08, flags);
- idt_set_gate(42, irq10, 0x08, flags);
- idt_set_gate(43, irq11, 0x08, flags);
- idt_set_gate(44, irq12, 0x08, flags);
- idt_set_gate(45, irq13, 0x08, flags);
- idt_set_gate(46, irq14, 0x08, flags);
- idt_set_gate(47, irq15, 0x08, flags);
-
- idt_flush(&idt_ptr);
-
- // Finally enable hardware interrupts with an assembly instruction
- __asm__ __volatile__ ("sti");
-}
-
-// Taken from: http://wiki.osdev.org/8259_PIC
-static void pic_remap(uint8_t offset1, uint8_t offset2) {
- uint8_t a1, a2;
-
- a1 = inb(PIC1_DATA); // Save masks
- a2 = inb(PIC2_DATA);
-
- outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // Start init sequence
- outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
-
- outb(PIC1_DATA, offset1);
- outb(PIC2_DATA, offset2);
-
- outb(PIC1_DATA, 4); // Tell master PIC that there is a slave PIC at IRQ2
- outb(PIC1_DATA, 2); // Tell salve PIC it's cascade identity
-
- outb(PIC1_DATA, ICW4_8086);
- outb(PIC2_DATA, ICW4_8086);
-
- // Restore saved masks
- outb(PIC1_DATA, a1);
- outb(PIC2_DATA, a2);
+#include "idt.h"
+#include "../libc/string.h"
+#include "ports.h"
+
+// Internal method
+extern void idt_flush(idt_ptr_t*); // defined on cpu/idt.asm
+static void init_idt();
+static void idt_set_gate(uint8_t idx, void(*base), uint16_t selector, idt_flags_t flags);
+static void pic_remap(uint8_t offset1, uint8_t offset2);
+
+idt_entry_t idt_entries[256]; // 256 interrupts
+idt_ptr_t idt_ptr;
+
+// This method will be called by the kernel
+void idt_setup() {
+ init_idt();
+}
+
+static void idt_set_gate(uint8_t idx, void(*base), uint16_t selector, idt_flags_t flags) {
+ idt_entries[idx] = (struct idt_entry) {
+ .base_low = (uint32_t)base & 0xFFFF,
+ .base_high = ((uint32_t)base >> 16) & 0xFFFF,
+ .seg_sel = selector,
+ .flags = flags
+ };
+}
+
+static void init_idt() {
+ idt_ptr.limit = sizeof(idt_entry_t) * 256 - 1;
+ idt_ptr.base = idt_entries;
+
+ memset(&idt_entries, 0, sizeof(idt_entry_t) * 256);
+
+ idt_flags_t flags = {
+ .reserved = IDT_FLAG_RESERVED, // Always 0x0E
+ .dpl = 0,
+ .p = 1
+ };
+ // Remap IDT with ISRs
+ idt_set_gate(0, isr0, 0x08, flags);
+ idt_set_gate(1, isr1, 0x08, flags);
+ idt_set_gate(2, isr2, 0x08, flags);
+ idt_set_gate(3, isr3, 0x08, flags);
+ idt_set_gate(4, isr4, 0x08, flags);
+ idt_set_gate(5, isr5, 0x08, flags);
+ idt_set_gate(6, isr6, 0x08, flags);
+ idt_set_gate(7, isr7, 0x08, flags);
+ idt_set_gate(8, isr8, 0x08, flags);
+ idt_set_gate(9, isr9, 0x08, flags);
+ idt_set_gate(10, isr10, 0x08, flags);
+ idt_set_gate(11, isr11, 0x08, flags);
+ idt_set_gate(12, isr12, 0x08, flags);
+ idt_set_gate(13, isr13, 0x08, flags);
+ idt_set_gate(14, isr14, 0x08, flags);
+ idt_set_gate(15, isr15, 0x08, flags);
+ idt_set_gate(16, isr16, 0x08, flags);
+ idt_set_gate(17, isr17, 0x08, flags);
+ idt_set_gate(18, isr18, 0x08, flags);
+ idt_set_gate(19, isr19, 0x08, flags);
+ idt_set_gate(20, isr20, 0x08, flags);
+ idt_set_gate(21, isr21, 0x08, flags);
+ idt_set_gate(22, isr22, 0x08, flags);
+ idt_set_gate(23, isr23, 0x08, flags);
+ idt_set_gate(24, isr24, 0x08, flags);
+ idt_set_gate(25, isr25, 0x08, flags);
+ idt_set_gate(26, isr26, 0x08, flags);
+ idt_set_gate(27, isr27, 0x08, flags);
+ idt_set_gate(28, isr28, 0x08, flags);
+ idt_set_gate(29, isr29, 0x08, flags);
+ idt_set_gate(30, isr30, 0x08, flags);
+ idt_set_gate(31, isr31, 0x08, flags);
+
+ // Remap PIC
+ pic_remap(PIC1_START_INTERRUPT, PIC2_START_INTERRUPT);
+
+ // Also remap 15 entries for IRQs
+ idt_set_gate(32, irq0, 0x08, flags);
+ idt_set_gate(33, irq1, 0x08, flags);
+ idt_set_gate(34, irq2, 0x08, flags);
+ idt_set_gate(35, irq3, 0x08, flags);
+ idt_set_gate(36, irq4, 0x08, flags);
+ idt_set_gate(37, irq5, 0x08, flags);
+ idt_set_gate(38, irq6, 0x08, flags);
+ idt_set_gate(39, irq7, 0x08, flags);
+ idt_set_gate(40, irq8, 0x08, flags);
+ idt_set_gate(41, irq9, 0x08, flags);
+ idt_set_gate(42, irq10, 0x08, flags);
+ idt_set_gate(43, irq11, 0x08, flags);
+ idt_set_gate(44, irq12, 0x08, flags);
+ idt_set_gate(45, irq13, 0x08, flags);
+ idt_set_gate(46, irq14, 0x08, flags);
+ idt_set_gate(47, irq15, 0x08, flags);
+
+ idt_flush(&idt_ptr);
+
+ // Finally enable hardware interrupts with an assembly instruction
+ __asm__ __volatile__ ("sti");
+}
+
+// Taken from: http://wiki.osdev.org/8259_PIC
+static void pic_remap(uint8_t offset1, uint8_t offset2) {
+ uint8_t a1, a2;
+
+ a1 = inb(PIC1_DATA); // Save masks
+ a2 = inb(PIC2_DATA);
+
+ outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // Start init sequence
+ outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4);
+
+ outb(PIC1_DATA, offset1);
+ outb(PIC2_DATA, offset2);
+
+ outb(PIC1_DATA, 4); // Tell master PIC that there is a slave PIC at IRQ2
+ outb(PIC1_DATA, 2); // Tell salve PIC it's cascade identity
+
+ outb(PIC1_DATA, ICW4_8086);
+ outb(PIC2_DATA, ICW4_8086);
+
+ // Restore saved masks
+ outb(PIC1_DATA, a1);
+ outb(PIC2_DATA, a2);
}
\ No newline at end of file
diff --git a/kernel/drivers/idt.h b/kernel/drivers/idt.h
index 0bd042f..dff263f 100644
--- a/kernel/drivers/idt.h
+++ b/kernel/drivers/idt.h
@@ -1,144 +1,144 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _IDT_H_
-#define _IDT_H_
-
-#include
-/*
- * First a bit of theory:
- * Sometimes you want to interrupt the processor from what it is currently doing
- * and force it to do something more "critical", such as a timer update or a keyboard interrupt
- * request(IRQ) fires. The processor, then, will handle those IRQs activating an
- * interrupt handler(ISR, Interrupt Service Routines). In order to know where to find those
- * ISRs, the CPU will use the IDT. So we can say that the Interrupt Description Table
- * is another data structure(organized the same way as the GDT) that will provide a list
- * of interrupts handlers(ISRs) to the CPU.
- */
-
-// Reserved bits in IDT entries
-#define IDT_FLAG_RESERVED 0x0E
-
-// PIC
-#define PIC1 0x20 // I/O address for master PIC
-#define PIC2 0xA0 // I/O address for slave PIC
-#define PIC1_COMMAND PIC1
-#define PIC1_DATA (PIC1+1)
-#define PIC2_COMMAND PIC2
-#define PIC2_DATA (PIC2+1)
-#define PIC1_START_INTERRUPT 0x20 // Master PIC after remapping
-#define PIC2_START_INTERRUPT 0x28 // Slave PIC after remapping
-#define PIC_EOI 0x20 // End of interrupt
-#define ICW1_ICW4 0x01
-#define ICW1_SINGLE 0x02
-#define ICW1_INTERVAL4 0x04
-#define ICW1_LEVEL 0x08
-#define ICW1_INIT 0x10
-#define ICW4_8086 0x01 // 8086/88 (MCS-80/85) mode
-#define ICW4_AUTO 0x02
-#define ICW4_BUF_SLAVE 0x08
-#define ICW4_BUF_MASTER 0x0C
-#define ICW4_SFNM 0x10
-
-/* Interrupt Descriptor Table */
-/* idt_flags contains access flag of a single IDT entry
- * | 0 - 4 | 5 - 6 | 7 |
- * | res | dpl | p |
- * res: always 0x0E
- * dpl: ring num (0 - 3)
- * p: segment present (bool)
-*/
-struct idt_flags {
- uint8_t reserved: 5;
- uint8_t dpl: 2;
- uint8_t p: 1;
-}__attribute__((packed));
-typedef struct idt_flags idt_flags_t;
-
-
-/* idt_entry contains the value of an IDT entry
- * Each entry is 64 bits(like GDT entry)
- * | 0 - 15 | 16 - 31 | 32 - 39 | 40 - 47 | 48 - 63 |
- * | b low | seg sel | res | flags | b high |
- * b low: Lower 16 bits of the base
- * seg sel: Segment selector for code segment
- * res: always 0
- * flags: idt_flags struct
- * b high: Higher 16 bits of the base
-*/
-struct idt_entry {
- uint16_t base_low;
- uint16_t seg_sel;
- uint8_t reserved;
- idt_flags_t flags;
- uint16_t base_high;
-}__attribute__((packed));
-typedef struct idt_entry idt_entry_t;
-
-/* Also we have to define a pointer to the data structure
- * This is needed to locate it later */
-struct idt_ptr {
- uint16_t limit;
- idt_entry_t *base;
-}__attribute__((packed));
-typedef struct idt_ptr idt_ptr_t;
-
-/* IDT Kernel API */
-void idt_setup();
-
-// ISRs method declaration
-extern void isr0();
-extern void isr1();
-extern void isr2();
-extern void isr3();
-extern void isr4();
-extern void isr5();
-extern void isr6();
-extern void isr7();
-extern void isr8();
-extern void isr9();
-extern void isr10();
-extern void isr11();
-extern void isr12();
-extern void isr13();
-extern void isr14();
-extern void isr15();
-extern void isr16();
-extern void isr17();
-extern void isr18();
-extern void isr19();
-extern void isr20();
-extern void isr21();
-extern void isr22();
-extern void isr23();
-extern void isr24();
-extern void isr25();
-extern void isr26();
-extern void isr27();
-extern void isr28();
-extern void isr29();
-extern void isr30();
-extern void isr31();
-
-extern void irq0();
-extern void irq1();
-extern void irq2();
-extern void irq3();
-extern void irq4();
-extern void irq5();
-extern void irq6();
-extern void irq7();
-extern void irq8();
-extern void irq9();
-extern void irq10();
-extern void irq11();
-extern void irq12();
-extern void irq13();
-extern void irq14();
-extern void irq15();
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _IDT_H_
+#define _IDT_H_
+
+#include
+/*
+ * First a bit of theory:
+ * Sometimes you want to interrupt the processor from what it is currently doing
+ * and force it to do something more "critical", such as a timer update or a keyboard interrupt
+ * request(IRQ) fires. The processor, then, will handle those IRQs activating an
+ * interrupt handler(ISR, Interrupt Service Routines). In order to know where to find those
+ * ISRs, the CPU will use the IDT. So we can say that the Interrupt Description Table
+ * is another data structure(organized the same way as the GDT) that will provide a list
+ * of interrupts handlers(ISRs) to the CPU.
+ */
+
+// Reserved bits in IDT entries
+#define IDT_FLAG_RESERVED 0x0E
+
+// PIC
+#define PIC1 0x20 // I/O address for master PIC
+#define PIC2 0xA0 // I/O address for slave PIC
+#define PIC1_COMMAND PIC1
+#define PIC1_DATA (PIC1+1)
+#define PIC2_COMMAND PIC2
+#define PIC2_DATA (PIC2+1)
+#define PIC1_START_INTERRUPT 0x20 // Master PIC after remapping
+#define PIC2_START_INTERRUPT 0x28 // Slave PIC after remapping
+#define PIC_EOI 0x20 // End of interrupt
+#define ICW1_ICW4 0x01
+#define ICW1_SINGLE 0x02
+#define ICW1_INTERVAL4 0x04
+#define ICW1_LEVEL 0x08
+#define ICW1_INIT 0x10
+#define ICW4_8086 0x01 // 8086/88 (MCS-80/85) mode
+#define ICW4_AUTO 0x02
+#define ICW4_BUF_SLAVE 0x08
+#define ICW4_BUF_MASTER 0x0C
+#define ICW4_SFNM 0x10
+
+/* Interrupt Descriptor Table */
+/* idt_flags contains access flag of a single IDT entry
+ * | 0 - 4 | 5 - 6 | 7 |
+ * | res | dpl | p |
+ * res: always 0x0E
+ * dpl: ring num (0 - 3)
+ * p: segment present (bool)
+*/
+struct idt_flags {
+ uint8_t reserved: 5;
+ uint8_t dpl: 2;
+ uint8_t p: 1;
+}__attribute__((packed));
+typedef struct idt_flags idt_flags_t;
+
+
+/* idt_entry contains the value of an IDT entry
+ * Each entry is 64 bits(like GDT entry)
+ * | 0 - 15 | 16 - 31 | 32 - 39 | 40 - 47 | 48 - 63 |
+ * | b low | seg sel | res | flags | b high |
+ * b low: Lower 16 bits of the base
+ * seg sel: Segment selector for code segment
+ * res: always 0
+ * flags: idt_flags struct
+ * b high: Higher 16 bits of the base
+*/
+struct idt_entry {
+ uint16_t base_low;
+ uint16_t seg_sel;
+ uint8_t reserved;
+ idt_flags_t flags;
+ uint16_t base_high;
+}__attribute__((packed));
+typedef struct idt_entry idt_entry_t;
+
+/* Also we have to define a pointer to the data structure
+ * This is needed to locate it later */
+struct idt_ptr {
+ uint16_t limit;
+ idt_entry_t *base;
+}__attribute__((packed));
+typedef struct idt_ptr idt_ptr_t;
+
+/* IDT Kernel API */
+void idt_setup();
+
+// ISRs method declaration
+extern void isr0();
+extern void isr1();
+extern void isr2();
+extern void isr3();
+extern void isr4();
+extern void isr5();
+extern void isr6();
+extern void isr7();
+extern void isr8();
+extern void isr9();
+extern void isr10();
+extern void isr11();
+extern void isr12();
+extern void isr13();
+extern void isr14();
+extern void isr15();
+extern void isr16();
+extern void isr17();
+extern void isr18();
+extern void isr19();
+extern void isr20();
+extern void isr21();
+extern void isr22();
+extern void isr23();
+extern void isr24();
+extern void isr25();
+extern void isr26();
+extern void isr27();
+extern void isr28();
+extern void isr29();
+extern void isr30();
+extern void isr31();
+
+extern void irq0();
+extern void irq1();
+extern void irq2();
+extern void irq3();
+extern void irq4();
+extern void irq5();
+extern void irq6();
+extern void irq7();
+extern void irq8();
+extern void irq9();
+extern void irq10();
+extern void irq11();
+extern void irq12();
+extern void irq13();
+extern void irq14();
+extern void irq15();
+
+#endif
diff --git a/kernel/drivers/initrd.c b/kernel/drivers/initrd.c
index c168398..488856c 100644
--- a/kernel/drivers/initrd.c
+++ b/kernel/drivers/initrd.c
@@ -1,56 +1,56 @@
-#include "initrd.h"
-
-// Declare various things
-initrd_header_t *initrd_header; // Header
-initrd_file_header_t *file_header; // List of headers
-fs_node_t *initrd_root; // Directory root node
-fs_node_t *initrd_dev; // Directory dev node(/dev)
-fs_node_t *root_nodes; // List of file nodes
-uint32_t nroot_nodes;
-
-struct dirent dirent;
-
-fs_node_t *init_ramdisk(uint32_t multiboot_location) {
- // Initialize main and file headers
- initrd_header = (initrd_header_t*)multiboot_location;
- file_header = (initrd_file_header_t*)(multiboot_location+sizeof(initrd_header_t));
- // Initialize root directory
- initrd_root = (fs_node_t*)
-
-}
-
-static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
- initrd_file_header_t header = file_header[node->inode];
- if(offset > header.length)
- return 0;
- if(offset+size > header.length)
- size = header.length-offset;
- memcpy(buffer, (uint8_t*) (header.offset+offset), size);
- return size;
-}
-
-static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) {
- if(node == initrd_root && index == 0) {
- strcpy(dirent.name, "dev");
- dirent.name[3] = 0; // Add null terminator to the string
- dirent.ino = 0;
- return &dirent;
- }
-
- if(index-1 >= &root_nodes)
- return 0;
- strcpy(dirent.name, root_nodes[index-1].name);
- dirent.name[strlen(root_nodes[index-1].name)] = 0; // Add null terminator
- dirent.ino = root_nodes[index-1].inode;
- return &dirent;
-}
-
-static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name) {
- if(node == initrd_root && !strcmp(name, "dev"))
- return initrd_dev;
-
- for(uint32_t i = 0; i < nroot_nodes; i++)
- if(!strcmp(name, root_nodes[i].name))
- return &root_nodes[i];
- return 0;
+#include "initrd.h"
+
+// Declare various things
+initrd_header_t *initrd_header; // Header
+initrd_file_header_t *file_header; // List of headers
+fs_node_t *initrd_root; // Directory root node
+fs_node_t *initrd_dev; // Directory dev node(/dev)
+fs_node_t *root_nodes; // List of file nodes
+uint32_t nroot_nodes;
+
+struct dirent dirent;
+
+fs_node_t *init_ramdisk(uint32_t multiboot_location) {
+ // Initialize main and file headers
+ initrd_header = (initrd_header_t*)multiboot_location;
+ file_header = (initrd_file_header_t*)(multiboot_location+sizeof(initrd_header_t));
+ // Initialize root directory
+ initrd_root = (fs_node_t*)
+
+}
+
+static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
+ initrd_file_header_t header = file_header[node->inode];
+ if(offset > header.length)
+ return 0;
+ if(offset+size > header.length)
+ size = header.length-offset;
+ memcpy(buffer, (uint8_t*) (header.offset+offset), size);
+ return size;
+}
+
+static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index) {
+ if(node == initrd_root && index == 0) {
+ strcpy(dirent.name, "dev");
+ dirent.name[3] = 0; // Add null terminator to the string
+ dirent.ino = 0;
+ return &dirent;
+ }
+
+ if(index-1 >= &root_nodes)
+ return 0;
+ strcpy(dirent.name, root_nodes[index-1].name);
+ dirent.name[strlen(root_nodes[index-1].name)] = 0; // Add null terminator
+ dirent.ino = root_nodes[index-1].inode;
+ return &dirent;
+}
+
+static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name) {
+ if(node == initrd_root && !strcmp(name, "dev"))
+ return initrd_dev;
+
+ for(uint32_t i = 0; i < nroot_nodes; i++)
+ if(!strcmp(name, root_nodes[i].name))
+ return &root_nodes[i];
+ return 0;
}
\ No newline at end of file
diff --git a/kernel/drivers/initrd.h b/kernel/drivers/initrd.h
index 83fb7a9..80fd6c1 100644
--- a/kernel/drivers/initrd.h
+++ b/kernel/drivers/initrd.h
@@ -1,36 +1,36 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef INITRD_H
-#define INITRD_H
-/* Ramdisk is a file system that is loaded along with the kernel
- * and it usually contains configuration files or file system drivers.
- * It is used BEFORE partitions are being mounted*/
-
-#include
-#include "../libc/string.h"
-#include "fs.h"
-
-typedef struct {
- uint32_t nfiles; // Number of files in the ramdisk
-} initrd_header_t;
-
-typedef struct {
- uint8_t magic; // Magic number for error checking
- int8_t name[64]; // Filename
- uint32_t offset;
- uint32_t length; // Length of the file
-} initrd_file_header_t;
-
-// Function to initialize initrd, we'll pass the multiboot
-// module as parameter
-fs_node_t *init_ramdisk(uint32_t multiboot_location);
-static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
-static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index);
-static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef INITRD_H
+#define INITRD_H
+/* Ramdisk is a file system that is loaded along with the kernel
+ * and it usually contains configuration files or file system drivers.
+ * It is used BEFORE partitions are being mounted*/
+
+#include
+#include "../libc/string.h"
+#include "fs.h"
+
+typedef struct {
+ uint32_t nfiles; // Number of files in the ramdisk
+} initrd_header_t;
+
+typedef struct {
+ uint8_t magic; // Magic number for error checking
+ int8_t name[64]; // Filename
+ uint32_t offset;
+ uint32_t length; // Length of the file
+} initrd_file_header_t;
+
+// Function to initialize initrd, we'll pass the multiboot
+// module as parameter
+fs_node_t *init_ramdisk(uint32_t multiboot_location);
+static uint32_t initrd_read(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
+static struct dirent *initrd_readdir(fs_node_t *node, uint32_t index);
+static fs_node_t *initrd_finddir(fs_node_t *node, uint8_t *name);
+
+#endif
diff --git a/kernel/drivers/isr.c b/kernel/drivers/isr.c
index f65e7b6..a8ba5fb 100644
--- a/kernel/drivers/isr.c
+++ b/kernel/drivers/isr.c
@@ -1,87 +1,87 @@
-#include
-#include "isr.h"
-#include "tty.h"
-#include "../libc/string.h"
-#include "ports.h"
-
-#define PIC1 0x20 // I/O address for master PIC
-#define PIC2 0xA0 // I/O address for slave PIC
-#define PIC1_COMMAND PIC1
-#define PIC1_DATA (PIC1+1)
-#define PIC2_COMMAND PIC2
-#define PIC2_DATA (PIC2+1)
-#define PIC_EOI 0x20 // End Of Interrupt command
-
-
-// List of messages for known interrupts
-uint8_t *interrupts_messages[] = {
- (uint8_t*)"Division by Zero", // 0
- (uint8_t*)"Debug",
- (uint8_t*)"Non-maskable interrupt",
- (uint8_t*)"Breakpoint",
- (uint8_t*)"Detected overflow",
- (uint8_t*)"Out-of-bounds", // 5
- (uint8_t*)"Invalid opcode",
- (uint8_t*)"No coprocessor",
- (uint8_t*)"Double fault",
- (uint8_t*)"Coprocessor segment overrun",
- (uint8_t*)"Bad TSS", // 10
- (uint8_t*)"Segment not present",
- (uint8_t*)"Stack fault",
- (uint8_t*)"General protection fault",
- (uint8_t*)"Page fault",
- (uint8_t*)"Unknown interrupt", // 15
- (uint8_t*)"Coprocessor fault",
- (uint8_t*)"Alignment check",
- (uint8_t*)"Machine check",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved",
- (uint8_t*)"Reserved"
-};
-
-isr_t interrupt_handler[256];
-
-void isr_handler(registers_t regs) {
- if(interrupt_handler[regs.int_num] != 0) {
- isr_t handler = interrupt_handler[regs.int_num];
- handler(regs);
- } else {
- uint8_t *buf = (uint8_t*)"\nReceived interrupt: ";
- kprint_c((uint8_t*)buf,strlen(buf), LIGHT_BROWN, BLACK);
- kprint_c(interrupts_messages[(uint8_t)regs.int_num],
- strlen(interrupts_messages[(uint8_t)regs.int_num]),
- WHITE,
- BLACK
- );
- }
-}
-
-void ack_irq(uint32_t int_num) {
- // Send and End Of Interrupt(EOF) at the PICs.
- if(int_num >= 40)
- outb(PIC2_COMMAND, PIC_EOI); // Send reset signal to slave
- outb(PIC1_COMMAND, PIC_EOI); // In any case, reset the master
-}
-
-void irq_handler(registers_t regs) {
- ack_irq(regs.int_num);
-
- if(interrupt_handler[regs.int_num] != 0) {
- isr_t handler = interrupt_handler[regs.int_num];
- handler(regs);
- }
-}
-
-void register_interrupt_handler(uint8_t n, isr_t handler) {
- interrupt_handler[n] = handler;
+#include
+#include "isr.h"
+#include "tty.h"
+#include "../libc/string.h"
+#include "ports.h"
+
+#define PIC1 0x20 // I/O address for master PIC
+#define PIC2 0xA0 // I/O address for slave PIC
+#define PIC1_COMMAND PIC1
+#define PIC1_DATA (PIC1+1)
+#define PIC2_COMMAND PIC2
+#define PIC2_DATA (PIC2+1)
+#define PIC_EOI 0x20 // End Of Interrupt command
+
+
+// List of messages for known interrupts
+uint8_t *interrupts_messages[] = {
+ (uint8_t*)"Division by Zero", // 0
+ (uint8_t*)"Debug",
+ (uint8_t*)"Non-maskable interrupt",
+ (uint8_t*)"Breakpoint",
+ (uint8_t*)"Detected overflow",
+ (uint8_t*)"Out-of-bounds", // 5
+ (uint8_t*)"Invalid opcode",
+ (uint8_t*)"No coprocessor",
+ (uint8_t*)"Double fault",
+ (uint8_t*)"Coprocessor segment overrun",
+ (uint8_t*)"Bad TSS", // 10
+ (uint8_t*)"Segment not present",
+ (uint8_t*)"Stack fault",
+ (uint8_t*)"General protection fault",
+ (uint8_t*)"Page fault",
+ (uint8_t*)"Unknown interrupt", // 15
+ (uint8_t*)"Coprocessor fault",
+ (uint8_t*)"Alignment check",
+ (uint8_t*)"Machine check",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved",
+ (uint8_t*)"Reserved"
+};
+
+isr_t interrupt_handler[256];
+
+void isr_handler(registers_t regs) {
+ if(interrupt_handler[regs.int_num] != 0) {
+ isr_t handler = interrupt_handler[regs.int_num];
+ handler(regs);
+ } else {
+ uint8_t *buf = (uint8_t*)"\nReceived interrupt: ";
+ kprint_c((uint8_t*)buf,strlen(buf), LIGHT_BROWN, BLACK);
+ kprint_c(interrupts_messages[(uint8_t)regs.int_num],
+ strlen(interrupts_messages[(uint8_t)regs.int_num]),
+ WHITE,
+ BLACK
+ );
+ }
+}
+
+void ack_irq(uint32_t int_num) {
+ // Send and End Of Interrupt(EOF) at the PICs.
+ if(int_num >= 40)
+ outb(PIC2_COMMAND, PIC_EOI); // Send reset signal to slave
+ outb(PIC1_COMMAND, PIC_EOI); // In any case, reset the master
+}
+
+void irq_handler(registers_t regs) {
+ ack_irq(regs.int_num);
+
+ if(interrupt_handler[regs.int_num] != 0) {
+ isr_t handler = interrupt_handler[regs.int_num];
+ handler(regs);
+ }
+}
+
+void register_interrupt_handler(uint8_t n, isr_t handler) {
+ interrupt_handler[n] = handler;
}
\ No newline at end of file
diff --git a/kernel/drivers/isr.h b/kernel/drivers/isr.h
index 68c8dc9..b3fb47f 100644
--- a/kernel/drivers/isr.h
+++ b/kernel/drivers/isr.h
@@ -1,72 +1,72 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _ISR_H_
-#define _ISR_H_
-
-#include
-
-/*
- * When we implement ISRs we have to keep in mind that the first 32 interrupts(and so the
- * first 32 ISRs) are reserved by the CPU to signal the kernel about critical actions,
- * such as divide-by-zero or a stack overflow/buffer overflow.
- *
- * Below ther's a list of the first, reserved, interrupts...and yeah, we have to implement
- * all of them by ourself(btw in Assembly) :D
- *
- * 0 - Division by zero exception
- * 1 - Debug exception
- * 2 - Non maskable interrupt
- * 3 - Breakpoint exception
- * 4 - Into detected overflow
- * 5 - Out of bounds exception
- * 6 - Invalid opcode exception
- * 7 - No coprocessor exception
- * 8 - Double fault (pushes an error code)
- * 9 - Coprocessor segment overrun
- * 10 - Bad TSS (pushes an error code)
- * 11 - Segment not present (pushes an error code)
- * 12 - Stack fault (pushes an error code)
- * 13 - General protection fault (pushes an error code)
- * 14 - Page fault (pushes an error code)
- * 15 - Unknown interrupt exception
- * 16 - Coprocessor fault
- * 17 - Alignment check exception
- * 18 - Machine check exception
- * 19-31 - Reserved */
-
-#define IRQ0 32
-#define IRQ1 33
-#define IRQ2 34
-#define IRQ3 35
-#define IRQ4 36
-#define IRQ5 37
-#define IRQ6 38
-#define IRQ7 39
-#define IRQ8 40
-#define IRQ9 41
-#define IRQ10 42
-#define IRQ11 43
-#define IRQ12 44
-#define IRQ13 45
-#define IRQ14 46
-#define IRQ15 47
-
-typedef struct registers {
- uint32_t ds; // Data segment
- uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed with pusha
- uint32_t int_num, err_code; // Interrupt number and error code
- uint32_t eip, cs, eflags, usereap, ss; // Pushed by CPU
-} registers_t;
-
-typedef void (*isr_t)(registers_t);
-
-void ack_irq(uint32_t int_num);
-void register_interrupt_handler(uint8_t n, isr_t handler);
-
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _ISR_H_
+#define _ISR_H_
+
+#include
+
+/*
+ * When we implement ISRs we have to keep in mind that the first 32 interrupts(and so the
+ * first 32 ISRs) are reserved by the CPU to signal the kernel about critical actions,
+ * such as divide-by-zero or a stack overflow/buffer overflow.
+ *
+ * Below ther's a list of the first, reserved, interrupts...and yeah, we have to implement
+ * all of them by ourself(btw in Assembly) :D
+ *
+ * 0 - Division by zero exception
+ * 1 - Debug exception
+ * 2 - Non maskable interrupt
+ * 3 - Breakpoint exception
+ * 4 - Into detected overflow
+ * 5 - Out of bounds exception
+ * 6 - Invalid opcode exception
+ * 7 - No coprocessor exception
+ * 8 - Double fault (pushes an error code)
+ * 9 - Coprocessor segment overrun
+ * 10 - Bad TSS (pushes an error code)
+ * 11 - Segment not present (pushes an error code)
+ * 12 - Stack fault (pushes an error code)
+ * 13 - General protection fault (pushes an error code)
+ * 14 - Page fault (pushes an error code)
+ * 15 - Unknown interrupt exception
+ * 16 - Coprocessor fault
+ * 17 - Alignment check exception
+ * 18 - Machine check exception
+ * 19-31 - Reserved */
+
+#define IRQ0 32
+#define IRQ1 33
+#define IRQ2 34
+#define IRQ3 35
+#define IRQ4 36
+#define IRQ5 37
+#define IRQ6 38
+#define IRQ7 39
+#define IRQ8 40
+#define IRQ9 41
+#define IRQ10 42
+#define IRQ11 43
+#define IRQ12 44
+#define IRQ13 45
+#define IRQ14 46
+#define IRQ15 47
+
+typedef struct registers {
+ uint32_t ds; // Data segment
+ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed with pusha
+ uint32_t int_num, err_code; // Interrupt number and error code
+ uint32_t eip, cs, eflags, usereap, ss; // Pushed by CPU
+} registers_t;
+
+typedef void (*isr_t)(registers_t);
+
+void ack_irq(uint32_t int_num);
+void register_interrupt_handler(uint8_t n, isr_t handler);
+
+
+#endif
diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c
index 8915afe..3f3f0a0 100644
--- a/kernel/drivers/keyboard.c
+++ b/kernel/drivers/keyboard.c
@@ -1,118 +1,118 @@
-/* The keyboard driver works with a device called PS/2: to talk with this
- * controller we can use serial communication(e.g. ports.h). The actual flow of
- * data is made with "commands", each command is one byte and the keyboard's
- * controller can send two type of response:
- * ACK(Acknowledge): to acknowledge the previous command
- * Resend: to resend the previous command due to an error.
- * We have also to wait between the command, the data and the response of
- * the PS/2 controller.
- * This device should not exists anymore in any modern computer
- * motherboard; however the CPU(or the motherboard?) should be able to
- * simulate it even if we're using some USB keyboard.
- * Apart of that the keyboard will be listen on IRQ1(33),
- * so we have to register an ISR for that.
-*/
-
-#include "keyboard.h"
-#include "isr.h"
-#include "ports.h"
-#include "tty.h"
-#include "../userspace/shell.h"
-#include "../libc/stdio.h"
-
-static void keyboard_callback();
-
-/* Keyboard scan codes map , layout is: standard US keyboard */
-uint8_t keyboard_scan_codes[] = {
- 0, (uint8_t)27, (uint8_t)'1', (uint8_t)'2', (uint8_t)'3', (uint8_t)'4', (uint8_t)'5', (uint8_t)'6', (uint8_t)'7', (uint8_t)'8',
- (uint8_t)'0', (uint8_t)'0', (uint8_t)'-', (uint8_t)'=', (uint8_t)'\b',
- (uint8_t)'\t',
- (uint8_t)'q', (uint8_t)'w', (uint8_t)'e', (uint8_t)'r',
- (uint8_t)'t', (uint8_t)'y', (uint8_t)'u', (uint8_t)'i', (uint8_t)'o', (uint8_t)'p', (uint8_t)'[', (uint8_t)']', (uint8_t)'\n',
- 0,
- (uint8_t)'a', (uint8_t)'s', (uint8_t)'d', (uint8_t)'f', (uint8_t)'g', (uint8_t)'h', (uint8_t)'j', (uint8_t)'k', (uint8_t)'l', (uint8_t)';',
- (uint8_t)'\'', (uint8_t)'`', 0,
- (uint8_t)'\\', (uint8_t)'z', (uint8_t)'x', (uint8_t)'c', (uint8_t)'v', (uint8_t)'b', (uint8_t)'n',
- (uint8_t)'m', (uint8_t)',', (uint8_t)'.', (uint8_t)'/', 0,
- (uint8_t)'*',
-
- 0, // Alt
- (uint8_t)' ', // Spacebar
- 0, // Caps lock
- 0, // 59 - F1 key
- 0, // 59 - F1 key
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, // F10
- 0, // 69 - Num lock
- 0, // Scroll lock
- 0, // Home key
- 0, // Up arrow
- 0, // Page up
- (uint8_t)'-',
- 0, // Left arrow
- 0,
- 0, // Right arrow
- (uint8_t)'+',
- 0, // 79 End key
- 0, // Down arrow
- 0, // Page down
- 0, // Insert key
- 0, // Delete key
- 0, 0, 0,
- 0, // F11 key
- 0, // F12 key
- 0 // Others key are undefined
-};
-
-uint8_t command[512]; // Max length of a single command
-uint8_t temp[512];
-uint32_t cmd_index = 0;
-uint32_t shiftdown = 0;
-
-void clear() {
- for(uint16_t i = 0; i < 512; i++)
- command[i] = 0;
-}
-
-void clear_tmp(void) {
- for(uint16_t i = 0; i < 512; i++)
- command[i] = 0;
-}
-
-static void keyboard_callback() {
- uint8_t scan_code = inb(KB_DATA_PORT); // Read from keyboard
- uint8_t keycode = keyboard_scan_codes[scan_code]; // Get ASCII value
-
- if(scan_code & 0x80) {
- if(scan_code == 0xAA || scan_code == 0x86)
- shiftdown = 0;
- } else {
- // Handle backspace
- if(keycode == 0x08) {
- if(cmd_index <= 0) // If at start of the prompt
- return; // Do not delete it.
- cmd_index--; // Otherwise go back
-
- for(uint32_t i = 0; i < cmd_index; ++i)
- temp[i] = command[i];
- clear();
- for(uint32_t i = 0; i < cmd_index; ++i)
- command[i] = temp[i];
- clear_tmp();
- backspace();
- } else if(keycode == 0x0A) { // Handle Enter
- processCommand(command);
- cmd_index = 0;
- clear();
- init_prompt();
- } else {
- printf("%c", keycode);
- command[cmd_index] = keycode;
- cmd_index++;
- }
- }
-}
-
-void init_keyboard() {
- register_interrupt_handler(IRQ1, &keyboard_callback);
-}
+/* The keyboard driver works with a device called PS/2: to talk with this
+ * controller we can use serial communication(e.g. ports.h). The actual flow of
+ * data is made with "commands", each command is one byte and the keyboard's
+ * controller can send two type of response:
+ * ACK(Acknowledge): to acknowledge the previous command
+ * Resend: to resend the previous command due to an error.
+ * We have also to wait between the command, the data and the response of
+ * the PS/2 controller.
+ * This device should not exists anymore in any modern computer
+ * motherboard; however the CPU(or the motherboard?) should be able to
+ * simulate it even if we're using some USB keyboard.
+ * Apart of that the keyboard will be listen on IRQ1(33),
+ * so we have to register an ISR for that.
+*/
+
+#include "keyboard.h"
+#include "isr.h"
+#include "ports.h"
+#include "tty.h"
+#include "../userspace/shell.h"
+#include "../libc/stdio.h"
+
+static void keyboard_callback();
+
+/* Keyboard scan codes map , layout is: standard US keyboard */
+uint8_t keyboard_scan_codes[] = {
+ 0, (uint8_t)27, (uint8_t)'1', (uint8_t)'2', (uint8_t)'3', (uint8_t)'4', (uint8_t)'5', (uint8_t)'6', (uint8_t)'7', (uint8_t)'8',
+ (uint8_t)'0', (uint8_t)'0', (uint8_t)'-', (uint8_t)'=', (uint8_t)'\b',
+ (uint8_t)'\t',
+ (uint8_t)'q', (uint8_t)'w', (uint8_t)'e', (uint8_t)'r',
+ (uint8_t)'t', (uint8_t)'y', (uint8_t)'u', (uint8_t)'i', (uint8_t)'o', (uint8_t)'p', (uint8_t)'[', (uint8_t)']', (uint8_t)'\n',
+ 0,
+ (uint8_t)'a', (uint8_t)'s', (uint8_t)'d', (uint8_t)'f', (uint8_t)'g', (uint8_t)'h', (uint8_t)'j', (uint8_t)'k', (uint8_t)'l', (uint8_t)';',
+ (uint8_t)'\'', (uint8_t)'`', 0,
+ (uint8_t)'\\', (uint8_t)'z', (uint8_t)'x', (uint8_t)'c', (uint8_t)'v', (uint8_t)'b', (uint8_t)'n',
+ (uint8_t)'m', (uint8_t)',', (uint8_t)'.', (uint8_t)'/', 0,
+ (uint8_t)'*',
+
+ 0, // Alt
+ (uint8_t)' ', // Spacebar
+ 0, // Caps lock
+ 0, // 59 - F1 key
+ 0, // 59 - F1 key
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, // F10
+ 0, // 69 - Num lock
+ 0, // Scroll lock
+ 0, // Home key
+ 0, // Up arrow
+ 0, // Page up
+ (uint8_t)'-',
+ 0, // Left arrow
+ 0,
+ 0, // Right arrow
+ (uint8_t)'+',
+ 0, // 79 End key
+ 0, // Down arrow
+ 0, // Page down
+ 0, // Insert key
+ 0, // Delete key
+ 0, 0, 0,
+ 0, // F11 key
+ 0, // F12 key
+ 0 // Others key are undefined
+};
+
+uint8_t command[512]; // Max length of a single command
+uint8_t temp[512];
+uint32_t cmd_index = 0;
+uint32_t shiftdown = 0;
+
+void clear() {
+ for(uint16_t i = 0; i < 512; i++)
+ command[i] = 0;
+}
+
+void clear_tmp(void) {
+ for(uint16_t i = 0; i < 512; i++)
+ command[i] = 0;
+}
+
+static void keyboard_callback() {
+ uint8_t scan_code = inb(KB_DATA_PORT); // Read from keyboard
+ uint8_t keycode = keyboard_scan_codes[scan_code]; // Get ASCII value
+
+ if(scan_code & 0x80) {
+ if(scan_code == 0xAA || scan_code == 0x86)
+ shiftdown = 0;
+ } else {
+ // Handle backspace
+ if(keycode == 0x08) {
+ if(cmd_index <= 0) // If at start of the prompt
+ return; // Do not delete it.
+ cmd_index--; // Otherwise go back
+
+ for(uint32_t i = 0; i < cmd_index; ++i)
+ temp[i] = command[i];
+ clear();
+ for(uint32_t i = 0; i < cmd_index; ++i)
+ command[i] = temp[i];
+ clear_tmp();
+ backspace();
+ } else if(keycode == 0x0A) { // Handle Enter
+ processCommand(command);
+ cmd_index = 0;
+ clear();
+ init_prompt();
+ } else {
+ printf("%c", keycode);
+ command[cmd_index] = keycode;
+ cmd_index++;
+ }
+ }
+}
+
+void init_keyboard() {
+ register_interrupt_handler(IRQ1, &keyboard_callback);
+}
diff --git a/kernel/drivers/keyboard.h b/kernel/drivers/keyboard.h
index 63cec50..882e0d8 100644
--- a/kernel/drivers/keyboard.h
+++ b/kernel/drivers/keyboard.h
@@ -1,17 +1,17 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _KEYBOARD_H_
-#define _KEYBOARD_H_
-
-#include
-
-#define KB_DATA_PORT 0x60 // Keyboard serial port
-
-void init_keyboard();
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _KEYBOARD_H_
+#define _KEYBOARD_H_
+
+#include
+
+#define KB_DATA_PORT 0x60 // Keyboard serial port
+
+void init_keyboard();
+
+#endif
diff --git a/kernel/drivers/ports.h b/kernel/drivers/ports.h
index 4b697d8..2dc7f6d 100644
--- a/kernel/drivers/ports.h
+++ b/kernel/drivers/ports.h
@@ -1,27 +1,27 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _PORTS_H
-#define _PORTS_H
-
-#include
-
-/* outb:
- * Redirect data to port(high level interface for ports.asm)
- * @param port: Output port to send data to.
- * @param data: The actual data to send to port
-*/
-void outb(uint16_t port, uint16_t data);
-
-/* inb:
- * Fetch data from a port, return a char
- * @param port: Input port to read data from.
-*/
-uint8_t inb(uint16_t port);
-
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _PORTS_H
+#define _PORTS_H
+
+#include
+
+/* outb:
+ * Redirect data to port(high level interface for ports.asm)
+ * @param port: Output port to send data to.
+ * @param data: The actual data to send to port
+*/
+void outb(uint16_t port, uint16_t data);
+
+/* inb:
+ * Fetch data from a port, return a char
+ * @param port: Input port to read data from.
+*/
+uint8_t inb(uint16_t port);
+
+
+#endif
diff --git a/kernel/drivers/timer.c b/kernel/drivers/timer.c
index 553e45b..c1d6209 100644
--- a/kernel/drivers/timer.c
+++ b/kernel/drivers/timer.c
@@ -1,39 +1,39 @@
-#include "timer.h"
-#include "isr.h"
-#include "tty.h"
-#include "../libc/string.h"
-#include "ports.h"
-
-// Start tick at zero
-uint32_t tick = 0;
-static void timer_callback(registers_t regs) {
- tick++;
- /* uint8_t buf[8];
- itoa(tick, buf, 10);
- kprint((uint8_t*)"Time: ");
- uitoa(tick, buf, 10);
- kprint((uint8_t*)buf);
- kprint((uint8_t*)"\n");*/
- // Cast to void unused parameter
- UNUSED_PAR(regs);
-}
-
-void init_timer(uint32_t frequency) {
- // Register a new ISR for IRQ0
- register_interrupt_handler(IRQ0, &timer_callback);
-
- /* As mentioned before, we'll send to PIT a value to divide for
- * his system clock(1.1931 MHz). We have to keep in mind that
- * this value must fit into a 16 bits variable */
- uint32_t divisor = 1193180 / frequency;
-
- // Send command to the right port
- outb(0x43, 0x36);
- // The two divisor has to be sent byte-wise, to do this we split them in two parts
- uint8_t low = (uint8_t)(divisor & 0xFF);
- uint8_t high = (uint8_t)((divisor >> 8) & 0xFF);
-
- // Send the frequency divisor
- outb(0x40, low);
- outb(0x40, high);
-}
+#include "timer.h"
+#include "isr.h"
+#include "tty.h"
+#include "../libc/string.h"
+#include "ports.h"
+
+// Start tick at zero
+uint32_t tick = 0;
+static void timer_callback(registers_t regs) {
+ tick++;
+ /* uint8_t buf[8];
+ itoa(tick, buf, 10);
+ kprint((uint8_t*)"Time: ");
+ uitoa(tick, buf, 10);
+ kprint((uint8_t*)buf);
+ kprint((uint8_t*)"\n");*/
+ // Cast to void unused parameter
+ UNUSED_PAR(regs);
+}
+
+void init_timer(uint32_t frequency) {
+ // Register a new ISR for IRQ0
+ register_interrupt_handler(IRQ0, &timer_callback);
+
+ /* As mentioned before, we'll send to PIT a value to divide for
+ * his system clock(1.1931 MHz). We have to keep in mind that
+ * this value must fit into a 16 bits variable */
+ uint32_t divisor = 1193180 / frequency;
+
+ // Send command to the right port
+ outb(0x43, 0x36);
+ // The two divisor has to be sent byte-wise, to do this we split them in two parts
+ uint8_t low = (uint8_t)(divisor & 0xFF);
+ uint8_t high = (uint8_t)((divisor >> 8) & 0xFF);
+
+ // Send the frequency divisor
+ outb(0x40, low);
+ outb(0x40, high);
+}
diff --git a/kernel/drivers/timer.h b/kernel/drivers/timer.h
index ad3e556..0208907 100644
--- a/kernel/drivers/timer.h
+++ b/kernel/drivers/timer.h
@@ -1,41 +1,41 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _TIMER_H_
-#define _TIMER_H_
-
-#include
-/*
- * The PIT(Programmable Interval Timer) is a chip that consist of an oscillator
- * It's connected to IRQ0 and it can be configure at a user-defined rate
- * between 10.Hz to 1.1931 MHz. The PIT is the primary method used to implement
- * a system clock and for implement multitasking.
- * The PIT's internal clock(~1.1931 MHz) is fed through a frequency divider that
- * modulate the final signal. This chip has 3 channel, each with his own
- * frequency divider:
- * Channel 0: The most useful, it's output is connected to IRQ0
- * Channel 1: It were used to control refresh rates on DRAM(RAMs with capacitors)
- * Channel 2: Controls the PC speakers.
- *
- * In our case, we will use only channel 0.
- * So we have to set up PIT at a frequency 'f', so it interrupts us at regular
- * intervals. We'll set the frequency to 100Hz(once every 10 ms); to do this
- * we'll send the PIT a divisor that will be divided for it's input frequency.
- * E.g. -> divisor = 1193180 Hz(1.1931MHz) / 100 Hz
- *
- * Apart of that, the PIT has 4 registers: 0x40-0x42(data ports) and 0x43(command port)
- */
-
-void init_timer(uint32_t frequency);
-extern uint32_t tick;
-/* Since regs parameter(from timer_callback) will be unused
- * GCC(with -Werror flag) will throw an error, so we can avoid this
- * using the following macro
- */
-#define UNUSED_PAR(x) (void)(x)
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+#include
+/*
+ * The PIT(Programmable Interval Timer) is a chip that consist of an oscillator
+ * It's connected to IRQ0 and it can be configure at a user-defined rate
+ * between 10.Hz to 1.1931 MHz. The PIT is the primary method used to implement
+ * a system clock and for implement multitasking.
+ * The PIT's internal clock(~1.1931 MHz) is fed through a frequency divider that
+ * modulate the final signal. This chip has 3 channel, each with his own
+ * frequency divider:
+ * Channel 0: The most useful, it's output is connected to IRQ0
+ * Channel 1: It were used to control refresh rates on DRAM(RAMs with capacitors)
+ * Channel 2: Controls the PC speakers.
+ *
+ * In our case, we will use only channel 0.
+ * So we have to set up PIT at a frequency 'f', so it interrupts us at regular
+ * intervals. We'll set the frequency to 100Hz(once every 10 ms); to do this
+ * we'll send the PIT a divisor that will be divided for it's input frequency.
+ * E.g. -> divisor = 1193180 Hz(1.1931MHz) / 100 Hz
+ *
+ * Apart of that, the PIT has 4 registers: 0x40-0x42(data ports) and 0x43(command port)
+ */
+
+void init_timer(uint32_t frequency);
+extern uint32_t tick;
+/* Since regs parameter(from timer_callback) will be unused
+ * GCC(with -Werror flag) will throw an error, so we can avoid this
+ * using the following macro
+ */
+#define UNUSED_PAR(x) (void)(x)
+
+#endif
diff --git a/kernel/drivers/tty.c b/kernel/drivers/tty.c
index 0257b7b..ec688df 100644
--- a/kernel/drivers/tty.c
+++ b/kernel/drivers/tty.c
@@ -1,153 +1,153 @@
-#include "tty.h"
-#include "../libc/string.h"
-#include "ports.h"
-
-#define VGA_PTR ((uint8_t*) VIDEO_MEM_ADDR) // Pointer to frame buffer
-// Also define a 2 byte pointer because cells are 16 bits wide
-#define UVGA_PTR ((uint16_t *)VIDEO_MEM_ADDR)
-#define STRINGIZE(x) #x
-#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
-
-static uint32_t fb_col = 1; // X
-static uint32_t fb_row = 0; // Y
-
-void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg) {
- uint8_t *fb = VGA_PTR;
- fb[i*2] = c;
- fb[i*2 + 1] = ((bg & 0x0F) << 4) | (fg & 0x0F);
-}
-
-void move_cursor(uint16_t pos) {
- outb(VGA_CMD_PORT, VGA_HIGH_BYTE);
- outb(VGA_DATA_PORT, ((pos >> 8) & 0x00FF));
- outb(VGA_CMD_PORT, VGA_LOW_BYTE);
- outb(VGA_DATA_PORT, pos & 0x00FF);
-}
-
-void cursor_adv() { // TODO: specify number of adv. with a parameter
- if(fb_col < VGA_WIDTH - 1)
- fb_col++;
- else
- newline();
-
- move_cursor(fb_col + (fb_row * VGA_WIDTH));
-}
-
-void cursor_prev() {
- if(fb_col == 0) {
- if(fb_row == 0)
- return; // If first row do not do anything
- fb_col = VGA_WIDTH - 1;
- fb_row--;
- } else
- fb_col--;
- move_cursor(fb_col + (fb_row * VGA_WIDTH));
-}
-
-void backspace() {
- uint16_t pos;
- uint8_t c = ' ';
-
- fb_col--;
- pos = fb_col + (fb_row * VGA_WIDTH);
- write_cell(pos, c, WHITE, BLACK);
-}
-
-void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg) {
- uint16_t pos;
- for(uint32_t i = 0; i < len; i++) {
- uint8_t c = buf[i];
- if(c == '\n' || c == '\r')
- newline();
- else if(c == '\t')
- tab();
- else {
- pos = fb_col + (fb_row * VGA_WIDTH);
- write_cell(pos, (uint8_t)c, fg, bg);
- cursor_adv();
- }
- }
-}
-
-void kprint(uint8_t *buf) {
- kprint_c(buf, strlen(buf), WHITE, BLACK);
-}
-
-void kprint_dec(uint32_t num) {
- if(num == 0) {
- uint8_t *buf = (uint8_t*)'0';
- kprint_c(buf, strlen(buf), WHITE, BLACK);;
- return;
- }
- int32_t acc = num;
- uint8_t c[32];
- int32_t i = 0;
- while(acc > 0) {
- c[i] = '0' + acc%10;
- acc /= 10;
- i++;
- }
- c[i] = 0;
- uint8_t c2[32];
- c2[i--] = 0;
- uint32_t j = 0;
- while(i >= 0)
- c2[i--] = c[j++];
- kprint(c2);
-}
-
-void init_prompt() {
- uint8_t user[64], hostname[64];
-#ifdef DEFAULT_USER
- strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER));
-#else
- #error "-DDEFAULT_USER flag not set"
-#endif
-
-#ifdef DEFAULT_HOSTNAME
- strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME));
-#else
- #error "-DDEFAULT_HOSTNAME flag not set"
-#endif
-
- newline();
- kprint_c(user, strlen(user), LIGHT_CYAN, BLACK);
- kprint_c((uint8_t*)"@", 1, LIGHT_RED, BLACK);
- kprint_c(hostname, strlen(hostname), LIGHT_MAGENTA, BLACK);
- kprint_c((uint8_t*)" #> ", 4, LIGHT_BLUE, BLACK);
-}
-
-void clear_prompt() {
- fb_col = 1;
- fb_row = 0;
-
- for(uint32_t i = 0; i < (VGA_WIDTH * VGA_HEIGHT); i++)
- write_cell(i, ' ', WHITE, BLACK);
- move_cursor(0);
-}
-
-void clear_row(uint8_t row) {
- for(size_t i = 0; i < VGA_WIDTH; i++)
- write_cell((row*VGA_WIDTH)+i, ' ', WHITE, BLACK);
-}
-
-void scroll() {
- uint16_t *fb = UVGA_PTR;
- memmove(fb, fb+VGA_WIDTH, VGA_WIDTH*2*(VGA_HEIGHT*2-1));
- clear_row(VGA_HEIGHT - 1);
-}
-
-void newline() {
- if(fb_row < VGA_HEIGHT - 1) // If there's at least one cell add it
- fb_row++;
- else // Otherwise scroll framebuffer
- scroll();
-
- fb_col = 1;
- move_cursor(fb_col + (fb_row * VGA_WIDTH));
-}
-
-void tab() {
- for(uint8_t i = 0; i < 4; i++)
- cursor_adv(); // Increment cursor 4 times
-}
+#include "tty.h"
+#include "../libc/string.h"
+#include "ports.h"
+
+#define VGA_PTR ((uint8_t*) VIDEO_MEM_ADDR) // Pointer to frame buffer
+// Also define a 2 byte pointer because cells are 16 bits wide
+#define UVGA_PTR ((uint16_t *)VIDEO_MEM_ADDR)
+#define STRINGIZE(x) #x
+#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
+
+static uint32_t fb_col = 1; // X
+static uint32_t fb_row = 0; // Y
+
+void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg) {
+ uint8_t *fb = VGA_PTR;
+ fb[i*2] = c;
+ fb[i*2 + 1] = ((bg & 0x0F) << 4) | (fg & 0x0F);
+}
+
+void move_cursor(uint16_t pos) {
+ outb(VGA_CMD_PORT, VGA_HIGH_BYTE);
+ outb(VGA_DATA_PORT, ((pos >> 8) & 0x00FF));
+ outb(VGA_CMD_PORT, VGA_LOW_BYTE);
+ outb(VGA_DATA_PORT, pos & 0x00FF);
+}
+
+void cursor_adv() { // TODO: specify number of adv. with a parameter
+ if(fb_col < VGA_WIDTH - 1)
+ fb_col++;
+ else
+ newline();
+
+ move_cursor(fb_col + (fb_row * VGA_WIDTH));
+}
+
+void cursor_prev() {
+ if(fb_col == 0) {
+ if(fb_row == 0)
+ return; // If first row do not do anything
+ fb_col = VGA_WIDTH - 1;
+ fb_row--;
+ } else
+ fb_col--;
+ move_cursor(fb_col + (fb_row * VGA_WIDTH));
+}
+
+void backspace() {
+ uint16_t pos;
+ uint8_t c = ' ';
+
+ fb_col--;
+ pos = fb_col + (fb_row * VGA_WIDTH);
+ write_cell(pos, c, WHITE, BLACK);
+}
+
+void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg) {
+ uint16_t pos;
+ for(uint32_t i = 0; i < len; i++) {
+ uint8_t c = buf[i];
+ if(c == '\n' || c == '\r')
+ newline();
+ else if(c == '\t')
+ tab();
+ else {
+ pos = fb_col + (fb_row * VGA_WIDTH);
+ write_cell(pos, (uint8_t)c, fg, bg);
+ cursor_adv();
+ }
+ }
+}
+
+void kprint(uint8_t *buf) {
+ kprint_c(buf, strlen(buf), WHITE, BLACK);
+}
+
+void kprint_dec(uint32_t num) {
+ if(num == 0) {
+ uint8_t *buf = (uint8_t*)'0';
+ kprint_c(buf, strlen(buf), WHITE, BLACK);;
+ return;
+ }
+ int32_t acc = num;
+ uint8_t c[32];
+ int32_t i = 0;
+ while(acc > 0) {
+ c[i] = '0' + acc%10;
+ acc /= 10;
+ i++;
+ }
+ c[i] = 0;
+ uint8_t c2[32];
+ c2[i--] = 0;
+ uint32_t j = 0;
+ while(i >= 0)
+ c2[i--] = c[j++];
+ kprint(c2);
+}
+
+void init_prompt() {
+ uint8_t user[64], hostname[64];
+#ifdef DEFAULT_USER
+ strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER));
+#else
+ #error "-DDEFAULT_USER flag not set"
+#endif
+
+#ifdef DEFAULT_HOSTNAME
+ strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME));
+#else
+ #error "-DDEFAULT_HOSTNAME flag not set"
+#endif
+
+ newline();
+ kprint_c(user, strlen(user), LIGHT_CYAN, BLACK);
+ kprint_c((uint8_t*)"@", 1, LIGHT_RED, BLACK);
+ kprint_c(hostname, strlen(hostname), LIGHT_MAGENTA, BLACK);
+ kprint_c((uint8_t*)" #> ", 4, LIGHT_BLUE, BLACK);
+}
+
+void clear_prompt() {
+ fb_col = 1;
+ fb_row = 0;
+
+ for(uint32_t i = 0; i < (VGA_WIDTH * VGA_HEIGHT); i++)
+ write_cell(i, ' ', WHITE, BLACK);
+ move_cursor(0);
+}
+
+void clear_row(uint8_t row) {
+ for(size_t i = 0; i < VGA_WIDTH; i++)
+ write_cell((row*VGA_WIDTH)+i, ' ', WHITE, BLACK);
+}
+
+void scroll() {
+ uint16_t *fb = UVGA_PTR;
+ memmove(fb, fb+VGA_WIDTH, VGA_WIDTH*2*(VGA_HEIGHT*2-1));
+ clear_row(VGA_HEIGHT - 1);
+}
+
+void newline() {
+ if(fb_row < VGA_HEIGHT - 1) // If there's at least one cell add it
+ fb_row++;
+ else // Otherwise scroll framebuffer
+ scroll();
+
+ fb_col = 1;
+ move_cursor(fb_col + (fb_row * VGA_WIDTH));
+}
+
+void tab() {
+ for(uint8_t i = 0; i < 4; i++)
+ cursor_adv(); // Increment cursor 4 times
+}
diff --git a/kernel/drivers/tty.h b/kernel/drivers/tty.h
index 9aec33a..1b0f267 100644
--- a/kernel/drivers/tty.h
+++ b/kernel/drivers/tty.h
@@ -1,63 +1,63 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _TTY_H_
-#define _TTY_H_
-
-#include
-
-// TODO: write something about Frame Buffer
-
-// VGA colors
-enum TTY_COLORS {
- BLACK, // 0
- BLUE,
- GREEN,
- CYAN,
- RED,
- MAGENTA,
- BROWN,
- LIGHT_GREY,
- DARK_GREY,
- LIGHT_BLUE,
- LIGHT_GREEN,
- LIGHT_CYAN,
- LIGHT_RED,
- LIGHT_MAGENTA,
- LIGHT_BROWN,
- WHITE // 15
-};
-
-/* Framebuffer properties */
-#define VIDEO_MEM_ADDR 0x000B8000 // frame buffer address
-#define VGA_WIDTH 80
-#define VGA_HEIGHT 25
-
-/* VGA I/O ports */
-#define VGA_CMD_PORT 0x3D4
-#define VGA_DATA_PORT 0x3D5
-
-/* VGA I/O ports commands */
-#define VGA_HIGH_BYTE 14
-#define VGA_LOW_BYTE 15
-
-/* Kernel's VGA API */
-void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg);
-void move_cursor(uint16_t pos);
-void cursor_adv();
-void backspace();
-void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg);
-void kprint(uint8_t *buf);
-void kprint_dec(uint32_t num);
-void init_prompt();
-void clear_prompt();
-void clear_row(uint8_t row);
-void scroll(); // Scroll one row
-void newline();
-void tab();
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _TTY_H_
+#define _TTY_H_
+
+#include
+
+// TODO: write something about Frame Buffer
+
+// VGA colors
+enum TTY_COLORS {
+ BLACK, // 0
+ BLUE,
+ GREEN,
+ CYAN,
+ RED,
+ MAGENTA,
+ BROWN,
+ LIGHT_GREY,
+ DARK_GREY,
+ LIGHT_BLUE,
+ LIGHT_GREEN,
+ LIGHT_CYAN,
+ LIGHT_RED,
+ LIGHT_MAGENTA,
+ LIGHT_BROWN,
+ WHITE // 15
+};
+
+/* Framebuffer properties */
+#define VIDEO_MEM_ADDR 0x000B8000 // frame buffer address
+#define VGA_WIDTH 80
+#define VGA_HEIGHT 25
+
+/* VGA I/O ports */
+#define VGA_CMD_PORT 0x3D4
+#define VGA_DATA_PORT 0x3D5
+
+/* VGA I/O ports commands */
+#define VGA_HIGH_BYTE 14
+#define VGA_LOW_BYTE 15
+
+/* Kernel's VGA API */
+void write_cell(int16_t i, uint8_t c, uint8_t fg, uint8_t bg);
+void move_cursor(uint16_t pos);
+void cursor_adv();
+void backspace();
+void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg);
+void kprint(uint8_t *buf);
+void kprint_dec(uint32_t num);
+void init_prompt();
+void clear_prompt();
+void clear_row(uint8_t row);
+void scroll(); // Scroll one row
+void newline();
+void tab();
+
+#endif
diff --git a/kernel/kernel_main.c b/kernel/kernel_main.c
index f927ddd..597a9dd 100644
--- a/kernel/kernel_main.c
+++ b/kernel/kernel_main.c
@@ -1,79 +1,79 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#include "drivers/tty.h"
-#include "drivers/gdt.h"
-#include "drivers/idt.h"
-#include "drivers/timer.h"
-#include "drivers/keyboard.h"
-#include "mem/paging.h"
-#include "mem/kheap.h"
-#include "mem/multiboot.h"
-#include "userspace/shell.h"
-#include "libc/stdio.h"
-#include "libc/panic.h"
-
-#include
-
-#define PRTOK printf("\n["); printf_color(" OK ", LIGHT_GREEN, BLACK); printf("]"); // Ugly hack to print "[ OK ]"
-#define PRTAT printf("\n["); printf_color(" ** ", LIGHT_BROWN, BLACK); printf("]"); // Ugly hack to print "[ * ]"
-#define PRTER printf("\n["); printf_color(" ERR ", LIGHT_RED, BLACK); printf("]"); // Ugly hack to print "[ ER ]"
-
-
-void kernel_main(unsigned long magic, uint32_t addr) {
- // First of all, check if we're booted by a Multiboot-compliant boot loader
- if(magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
- PRTER
- printf(" - Invalid magic number: %x\n", (unsigned)magic);
- PANIC("Invalid multiboot magic number");
- }
-
- if(addr & 7) {
- PRTER
- printf(" - Unaligned mbi: %x\n", addr);
- PANIC("Unaligned multiboot MBI");
- }
-
-
- printf("Loading kernel, wait please...");
-
- gdt_setup(); // Setup Global Descriptor Table
- PRTOK
- printf(" - Loaded GDT");
-
- idt_setup(); // Setup Interrupt Descriptor Table
- PRTOK
- printf(" - Loaded IDT");
-
- init_timer(1); // Initialize PIT driver
- PRTOK
- printf(" - Loaded PIT");
-
- init_keyboard(); // Initialize keyboard driver
- PRTOK
- printf(" - Loaded PS/2 driver");
-
- init_paging(); // Initialize paging
- PRTOK
- printf(" - Loaded Paging");
-
- PRTAT
- printf(" - Testing heap...\t");
-
- uint32_t x = kmalloc(32), y = kmalloc(32);
- printf("x: %x, y: %x", x, y);
- kfree((void*)y);
- uint32_t z = kmalloc(8);
- printf(", z: %x", z); // If z is equal to y, heap's anti-fragmentation algorithm works
- ASSERT(z == y);
- kfree((void*)z), kfree((void*)x);
-
- PRTOK
- printf(" - Heap works!");
-
- init_prompt(); // Initialize frame buffer
-}
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#include "drivers/tty.h"
+#include "drivers/gdt.h"
+#include "drivers/idt.h"
+#include "drivers/timer.h"
+#include "drivers/keyboard.h"
+#include "mem/paging.h"
+#include "mem/kheap.h"
+#include "mem/multiboot.h"
+#include "userspace/shell.h"
+#include "libc/stdio.h"
+#include "libc/panic.h"
+
+#include
+
+#define PRTOK printf("\n["); printf_color(" OK ", LIGHT_GREEN, BLACK); printf("]"); // Ugly hack to print "[ OK ]"
+#define PRTAT printf("\n["); printf_color(" ** ", LIGHT_BROWN, BLACK); printf("]"); // Ugly hack to print "[ * ]"
+#define PRTER printf("\n["); printf_color(" ERR ", LIGHT_RED, BLACK); printf("]"); // Ugly hack to print "[ ER ]"
+
+
+void kernel_main(unsigned long magic, uint32_t addr) {
+ // First of all, check if we're booted by a Multiboot-compliant boot loader
+ if(magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
+ PRTER
+ printf(" - Invalid magic number: %x\n", (unsigned)magic);
+ PANIC("Invalid multiboot magic number");
+ }
+
+ if(addr & 7) {
+ PRTER
+ printf(" - Unaligned mbi: %x\n", addr);
+ PANIC("Unaligned multiboot MBI");
+ }
+
+
+ printf("Loading kernel, wait please...");
+
+ gdt_setup(); // Setup Global Descriptor Table
+ PRTOK
+ printf(" - Loaded GDT");
+
+ idt_setup(); // Setup Interrupt Descriptor Table
+ PRTOK
+ printf(" - Loaded IDT");
+
+ init_timer(1); // Initialize PIT driver
+ PRTOK
+ printf(" - Loaded PIT");
+
+ init_keyboard(); // Initialize keyboard driver
+ PRTOK
+ printf(" - Loaded PS/2 driver");
+
+ init_paging(); // Initialize paging
+ PRTOK
+ printf(" - Loaded Paging");
+
+ PRTAT
+ printf(" - Testing heap...\t");
+
+ uint32_t x = kmalloc(32), y = kmalloc(32);
+ printf("x: %x, y: %x", x, y);
+ kfree((void*)y);
+ uint32_t z = kmalloc(8);
+ printf(", z: %x", z); // If z is equal to y, heap's anti-fragmentation algorithm works
+ ASSERT(z == y);
+ kfree((void*)z), kfree((void*)x);
+
+ PRTOK
+ printf(" - Heap works!");
+
+ init_prompt(); // Initialize frame buffer
+}
diff --git a/kernel/libc/Makefile b/kernel/libc/Makefile
index 31b2a1d..4b5621a 100644
--- a/kernel/libc/Makefile
+++ b/kernel/libc/Makefile
@@ -1,11 +1,11 @@
-OBJS = stdio.o string.o panic.o time.o
-VER := $(shell git rev-parse --short HEAD)
-
-CC = i686-elf-gcc # cross-compiler
-CFLAGS = -DVULCAN_VERSION=$(VER) -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
-
-
-all:${OBJS}
-
-%.o: %.c
- $(CC) $(CFLAGS) $< -o $@
+OBJS = stdio.o string.o panic.o time.o
+VER := $(shell git rev-parse --short HEAD)
+
+CC = i686-elf-gcc # cross-compiler
+CFLAGS = -DVULCAN_VERSION=$(VER) -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
+
+
+all:${OBJS}
+
+%.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
diff --git a/kernel/libc/panic.c b/kernel/libc/panic.c
index d1153e1..4370e4d 100644
--- a/kernel/libc/panic.c
+++ b/kernel/libc/panic.c
@@ -1,51 +1,51 @@
-#include "panic.h"
-#include "../drivers/cpuid.h"
-#include "../libc/stdio.h"
-#include "../libc/string.h"
-
-#define KINFO printf("["); printf_color(" I ", LIGHT_RED, BLACK); printf("]: ");
-#define STRINGIZE(x) #x
-#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
-
-
-// We panic when we find a critical error, this function is called by assert macro
-extern void panic(const char *message, const char *file, uint32_t line) {
- uint8_t version[64];
-#ifdef VULCAN_VERSION
- strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION));
-#else
- #error "-DVULCAN_VERSION flag not set"
-#endif
- printf_color("=============================================\n", LIGHT_MAGENTA, BLACK);
- printf_color(" .:: KERNEL PANIC ::. \n", LIGHT_RED, BLACK);
- printf_color("Reason: ", LIGHT_BROWN, BLACK);
- printf("'%s' at '%s':%d\n", message, file, line);
- KINFO
- printf_color("Disabling interrupts\n", LIGHT_GREEN, BLACK);
- asm volatile("cli"); // Disable interrupts
- KINFO
- printf_color("Dropping you into an endless loop\n", LIGHT_GREEN, BLACK);
- KINFO
- printf_color("Your are on your own now...good luck.\n", LIGHT_GREEN, BLACK);
- KINFO
- printf_color("VulcanOS version: ", LIGHT_GREEN, BLACK);
- printf_color((char*)version, LIGHT_CYAN, BLACK);
- printf_color("\n\t\t (c) 2019-2021 Marco Cetica", LIGHT_BROWN, BLACK);
- printf_color("\n=============================================\n", LIGHT_MAGENTA, BLACK);
- for(;;);
-}
-
-// Check for assertion failed, this function is called by assert macro
-extern void panic_assert(const char *file, uint32_t line, const char *desc) {
- asm volatile("cli"); // Disable interrupts
-
- kprint((uint8_t*)"ASSERTION-FAILED(");
- kprint((uint8_t*)desc);
- kprint((uint8_t*)") at ");
- kprint((uint8_t*)file);
- kprint((uint8_t*)":");
- kprint_dec(line);
- kprint((uint8_t*)"\n");
- // Now hang on forever
- for(;;);
-}
+#include "panic.h"
+#include "../drivers/cpuid.h"
+#include "../libc/stdio.h"
+#include "../libc/string.h"
+
+#define KINFO printf("["); printf_color(" I ", LIGHT_RED, BLACK); printf("]: ");
+#define STRINGIZE(x) #x
+#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
+
+
+// We panic when we find a critical error, this function is called by assert macro
+extern void panic(const char *message, const char *file, uint32_t line) {
+ uint8_t version[64];
+#ifdef VULCAN_VERSION
+ strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION));
+#else
+ #error "-DVULCAN_VERSION flag not set"
+#endif
+ printf_color("=============================================\n", LIGHT_MAGENTA, BLACK);
+ printf_color(" .:: KERNEL PANIC ::. \n", LIGHT_RED, BLACK);
+ printf_color("Reason: ", LIGHT_BROWN, BLACK);
+ printf("'%s' at '%s':%d\n", message, file, line);
+ KINFO
+ printf_color("Disabling interrupts\n", LIGHT_GREEN, BLACK);
+ asm volatile("cli"); // Disable interrupts
+ KINFO
+ printf_color("Dropping you into an endless loop\n", LIGHT_GREEN, BLACK);
+ KINFO
+ printf_color("Your are on your own now...good luck.\n", LIGHT_GREEN, BLACK);
+ KINFO
+ printf_color("VulcanOS version: ", LIGHT_GREEN, BLACK);
+ printf_color((char*)version, LIGHT_CYAN, BLACK);
+ printf_color("\n\t\t (c) 2019-2021 Marco Cetica", LIGHT_BROWN, BLACK);
+ printf_color("\n=============================================\n", LIGHT_MAGENTA, BLACK);
+ for(;;);
+}
+
+// Check for assertion failed, this function is called by assert macro
+extern void panic_assert(const char *file, uint32_t line, const char *desc) {
+ asm volatile("cli"); // Disable interrupts
+
+ kprint((uint8_t*)"ASSERTION-FAILED(");
+ kprint((uint8_t*)desc);
+ kprint((uint8_t*)") at ");
+ kprint((uint8_t*)file);
+ kprint((uint8_t*)":");
+ kprint_dec(line);
+ kprint((uint8_t*)"\n");
+ // Now hang on forever
+ for(;;);
+}
diff --git a/kernel/libc/panic.h b/kernel/libc/panic.h
index 61a0da9..7123395 100644
--- a/kernel/libc/panic.h
+++ b/kernel/libc/panic.h
@@ -1,20 +1,20 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef PANIC_H
-#define PANIC_H
-
-#include
-#include "../drivers/tty.h"
-
-#define PANIC(msg) panic(msg, __FILE__, __LINE__);
-#define ASSERT(b) ((b) ? (void)0 : panic_assert(__FILE__, __LINE__, #b))
-
-extern void panic(const char *message, const char *file, uint32_t line);
-extern void panic_assert(const char *file, uint32_t line, const char *desc);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef PANIC_H
+#define PANIC_H
+
+#include
+#include "../drivers/tty.h"
+
+#define PANIC(msg) panic(msg, __FILE__, __LINE__);
+#define ASSERT(b) ((b) ? (void)0 : panic_assert(__FILE__, __LINE__, #b))
+
+extern void panic(const char *message, const char *file, uint32_t line);
+extern void panic_assert(const char *file, uint32_t line, const char *desc);
+
+#endif
diff --git a/kernel/libc/stdio.c b/kernel/libc/stdio.c
index e1d9225..2173385 100644
--- a/kernel/libc/stdio.c
+++ b/kernel/libc/stdio.c
@@ -1,59 +1,59 @@
-#include "stdio.h"
-#include "string.h"
-#include "../drivers/tty.h"
-
-int printf(const char *format, ...) {
- uint8_t buf[20],c,*s;
- int val;
- int32_t uval;
- va_list ap;
- va_start(ap, format);
-
- for(size_t i = 0; i < strlen((uint8_t*)format); i++) {
- if(format[i] == '%') {
- i++;
- while(format[i] == ' ')
- i++;
-
- switch(format[i]) {
- case 'i':
- val = va_arg(ap, int);
- itoa(val, buf, 10);
- kprint(buf);
- break;
- case 'x':
- uval = va_arg(ap, uint32_t);
- uitoa(uval, buf, 16);
- kprint(buf);
- break;
- case 'd':
- uval = va_arg(ap, uint32_t);
- uitoa(uval, buf, 10);
- kprint(buf);
- break;
- case 'c':
- c = (uint8_t)va_arg(ap, uint32_t);
- kprint_c(&c, 1, WHITE, BLACK);
- break;
- case 's':
- s = va_arg(ap, uint8_t*);
- kprint(s);
- break;
- default:
- kprint_c((uint8_t*)format+i, 1, WHITE, BLACK);
- }
- } else
- kprint_c((uint8_t*)format+i, 1, WHITE, BLACK);
- }
- va_end(ap);
- return 0;
-}
-
-int printf_color(const char *format, uint8_t fg, uint8_t bg) {
- kprint_c((uint8_t*)format, strlen((uint8_t*)format), fg, bg);
- return 0;
-}
-
-void puts(const char *buf) {
- printf("%s\n", buf);
-}
+#include "stdio.h"
+#include "string.h"
+#include "../drivers/tty.h"
+
+int printf(const char *format, ...) {
+ uint8_t buf[20],c,*s;
+ int val;
+ int32_t uval;
+ va_list ap;
+ va_start(ap, format);
+
+ for(size_t i = 0; i < strlen((uint8_t*)format); i++) {
+ if(format[i] == '%') {
+ i++;
+ while(format[i] == ' ')
+ i++;
+
+ switch(format[i]) {
+ case 'i':
+ val = va_arg(ap, int);
+ itoa(val, buf, 10);
+ kprint(buf);
+ break;
+ case 'x':
+ uval = va_arg(ap, uint32_t);
+ uitoa(uval, buf, 16);
+ kprint(buf);
+ break;
+ case 'd':
+ uval = va_arg(ap, uint32_t);
+ uitoa(uval, buf, 10);
+ kprint(buf);
+ break;
+ case 'c':
+ c = (uint8_t)va_arg(ap, uint32_t);
+ kprint_c(&c, 1, WHITE, BLACK);
+ break;
+ case 's':
+ s = va_arg(ap, uint8_t*);
+ kprint(s);
+ break;
+ default:
+ kprint_c((uint8_t*)format+i, 1, WHITE, BLACK);
+ }
+ } else
+ kprint_c((uint8_t*)format+i, 1, WHITE, BLACK);
+ }
+ va_end(ap);
+ return 0;
+}
+
+int printf_color(const char *format, uint8_t fg, uint8_t bg) {
+ kprint_c((uint8_t*)format, strlen((uint8_t*)format), fg, bg);
+ return 0;
+}
+
+void puts(const char *buf) {
+ printf("%s\n", buf);
+}
diff --git a/kernel/libc/stdio.h b/kernel/libc/stdio.h
index ee7f5f2..0533171 100644
--- a/kernel/libc/stdio.h
+++ b/kernel/libc/stdio.h
@@ -1,19 +1,19 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _STDIO_H_
-#define _STDIO_H_
-
-#include
-#include
-#include
-
-int printf(const char *format, ...);
-int printf_color(const char *format, uint8_t fg, uint8_t bg); // Only for string for now
-void puts(const char *buf);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _STDIO_H_
+#define _STDIO_H_
+
+#include
+#include
+#include
+
+int printf(const char *format, ...);
+int printf_color(const char *format, uint8_t fg, uint8_t bg); // Only for string for now
+void puts(const char *buf);
+
+#endif
diff --git a/kernel/libc/string.c b/kernel/libc/string.c
index 0a30117..c5c506c 100644
--- a/kernel/libc/string.c
+++ b/kernel/libc/string.c
@@ -1,150 +1,150 @@
-#include "string.h"
-
-// C library implementation
-
-int32_t strcmp(const uint8_t *s1, const uint8_t *s2) {
- while ((*s1) && (*s1 == *s2)) {
- s1++;
- s2++;
- }
- return (*(uint8_t*)s1 - *(uint8_t*)s2);
-}
-uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix) {
- uint32_t i = 0;
- uint32_t start = i;
-
- if(val < 0 && radix == 10) {
- buf[i++] = '-';
- start = i;
- }
-
- if(radix == 10) {
- buf[i++] = '0';
- buf[i++] = 'x';
- start = i;
- }
-
- int x = val;
- do {
- int a = x % radix;
- if(a < 10)
- buf[i++] = a + '0';
- else
- buf[i++]= a + 'a' - 10;
- } while(x /= radix);
-
- uint8_t *s = buf+start;
- uint8_t *e = buf+(i-1);
-
- while(s < e) {
- uint8_t t = *s;
- *s = *e;
- *e = t;
- i++;
- e--;
- }
- buf[i] = 0;
- return buf;
-}
-
-uint8_t *uitoa(uint32_t val, uint8_t *buf, uint32_t radix) {
- uint32_t i = 0;
- uint32_t start = i;
- uint32_t x = val;
-
- if(radix == 16) {
- buf[i++] = '0';
- buf[i++] = 'x';
- start = i;
- }
-
- do {
- uint32_t a = x % radix;
- if(a < 10)
- buf[i++] = a + '0';
- else
- buf[i++] = a + 'a' - 10;
- } while(x /= radix);
-
- uint8_t *s = buf+start;
- uint8_t *e = buf+(i-1);
-
- while(s < e) {
- uint8_t t = *s;
- *s = *e;
- *e = t;
- s++;
- e--;
- }
-
- buf[i] = 0;
- return buf;
-}
-
-size_t strlen(const uint8_t *buf) {
- uint32_t i = 0;
- while(buf[i] != 0)
- i++;
- return i;
-}
-
-uint8_t *strcpy(uint8_t *dst, const uint8_t *src) {
- uint8_t *dst_p = dst;
- while((*dst++ = *src++));
-
- return dst_p;
-}
-
-void strcat(void *dest, const void *src) {
- uint8_t *end = (uint8_t*)dest + strlen(dest);
- memcpy((uint8_t*)end, (uint8_t*)src, strlen((uint8_t*)src));
- end += strlen((uint8_t*)src);
- *end = '\0';
-}
-
-/* Worst memset implementation
- * i could find on the net.
- * however it works so... */
-void *memset(void *s, uint32_t c, size_t n) {
- char *mem = (char*)s;
-
- for(size_t i = 0; i < n; i++)
- mem[i] = (uint8_t)c;
-
- return s;
-}
-
-void *memcpy(void *dst, void const *src, uint32_t n) {
- uint8_t *ret = dst;
- uint8_t *p = dst;
- const uint8_t *q = src;
-
- while(n--)
- *p++ = *q++;
-
- return ret;
-}
-
-void *memmove(void *dst, const void *src, size_t len) {
- char *dstmem = (char*)dst;
- char *srcmem = (char*)src;
-
- for(size_t i = 0; i < len; i++)
- dstmem[i] = srcmem[i];
-
- return dstmem;
-}
-
-void strupper(uint8_t *str) {
- for(unsigned int i = 0; i < strlen(str); i++) {
- if(str[i] == 'a' && str[i] < 'z')
- str[i] &= 0x4F;
- }
-}
-
-void strlower(uint8_t *str) {
- for(unsigned int i = 0; i < strlen(str); i++) {
- if(str[i] == 'A' && str[i] < 'Z')
- str[i] |= 0x60;
- }
-}
+#include "string.h"
+
+// C library implementation
+
+int32_t strcmp(const uint8_t *s1, const uint8_t *s2) {
+ while ((*s1) && (*s1 == *s2)) {
+ s1++;
+ s2++;
+ }
+ return (*(uint8_t*)s1 - *(uint8_t*)s2);
+}
+uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix) {
+ uint32_t i = 0;
+ uint32_t start = i;
+
+ if(val < 0 && radix == 10) {
+ buf[i++] = '-';
+ start = i;
+ }
+
+ if(radix == 10) {
+ buf[i++] = '0';
+ buf[i++] = 'x';
+ start = i;
+ }
+
+ int x = val;
+ do {
+ int a = x % radix;
+ if(a < 10)
+ buf[i++] = a + '0';
+ else
+ buf[i++]= a + 'a' - 10;
+ } while(x /= radix);
+
+ uint8_t *s = buf+start;
+ uint8_t *e = buf+(i-1);
+
+ while(s < e) {
+ uint8_t t = *s;
+ *s = *e;
+ *e = t;
+ i++;
+ e--;
+ }
+ buf[i] = 0;
+ return buf;
+}
+
+uint8_t *uitoa(uint32_t val, uint8_t *buf, uint32_t radix) {
+ uint32_t i = 0;
+ uint32_t start = i;
+ uint32_t x = val;
+
+ if(radix == 16) {
+ buf[i++] = '0';
+ buf[i++] = 'x';
+ start = i;
+ }
+
+ do {
+ uint32_t a = x % radix;
+ if(a < 10)
+ buf[i++] = a + '0';
+ else
+ buf[i++] = a + 'a' - 10;
+ } while(x /= radix);
+
+ uint8_t *s = buf+start;
+ uint8_t *e = buf+(i-1);
+
+ while(s < e) {
+ uint8_t t = *s;
+ *s = *e;
+ *e = t;
+ s++;
+ e--;
+ }
+
+ buf[i] = 0;
+ return buf;
+}
+
+size_t strlen(const uint8_t *buf) {
+ uint32_t i = 0;
+ while(buf[i] != 0)
+ i++;
+ return i;
+}
+
+uint8_t *strcpy(uint8_t *dst, const uint8_t *src) {
+ uint8_t *dst_p = dst;
+ while((*dst++ = *src++));
+
+ return dst_p;
+}
+
+void strcat(void *dest, const void *src) {
+ uint8_t *end = (uint8_t*)dest + strlen(dest);
+ memcpy((uint8_t*)end, (uint8_t*)src, strlen((uint8_t*)src));
+ end += strlen((uint8_t*)src);
+ *end = '\0';
+}
+
+/* Worst memset implementation
+ * i could find on the net.
+ * however it works so... */
+void *memset(void *s, uint32_t c, size_t n) {
+ char *mem = (char*)s;
+
+ for(size_t i = 0; i < n; i++)
+ mem[i] = (uint8_t)c;
+
+ return s;
+}
+
+void *memcpy(void *dst, void const *src, uint32_t n) {
+ uint8_t *ret = dst;
+ uint8_t *p = dst;
+ const uint8_t *q = src;
+
+ while(n--)
+ *p++ = *q++;
+
+ return ret;
+}
+
+void *memmove(void *dst, const void *src, size_t len) {
+ char *dstmem = (char*)dst;
+ char *srcmem = (char*)src;
+
+ for(size_t i = 0; i < len; i++)
+ dstmem[i] = srcmem[i];
+
+ return dstmem;
+}
+
+void strupper(uint8_t *str) {
+ for(unsigned int i = 0; i < strlen(str); i++) {
+ if(str[i] == 'a' && str[i] < 'z')
+ str[i] &= 0x4F;
+ }
+}
+
+void strlower(uint8_t *str) {
+ for(unsigned int i = 0; i < strlen(str); i++) {
+ if(str[i] == 'A' && str[i] < 'Z')
+ str[i] |= 0x60;
+ }
+}
diff --git a/kernel/libc/string.h b/kernel/libc/string.h
index fc50891..13d8378 100644
--- a/kernel/libc/string.h
+++ b/kernel/libc/string.h
@@ -1,26 +1,26 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _STRING_H_
-#define _STRING_H_
-
-#include // For uinx_t
-#include // For size_t
-
-int32_t strcmp(const uint8_t *s1, const uint8_t *s2);
-uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix);
-uint8_t *uitoa(uint32_t val, uint8_t *buf, uint32_t radix);
-size_t strlen(const uint8_t *buf);
-uint8_t *strcpy(uint8_t *dst, const uint8_t *src);
-void strcat(void *dest, const void *src);
-void *memset(void *s, uint32_t c, size_t n);
-void *memmove(void *dst, const void *src, size_t len);
-void *memcpy(void *dst, void const *src, uint32_t n);
-void strupper(uint8_t *str);
-void strlower(uint8_t *str);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef _STRING_H_
+#define _STRING_H_
+
+#include // For uinx_t
+#include // For size_t
+
+int32_t strcmp(const uint8_t *s1, const uint8_t *s2);
+uint8_t *itoa(int32_t val, uint8_t *buf, uint32_t radix);
+uint8_t *uitoa(uint32_t val, uint8_t *buf, uint32_t radix);
+size_t strlen(const uint8_t *buf);
+uint8_t *strcpy(uint8_t *dst, const uint8_t *src);
+void strcat(void *dest, const void *src);
+void *memset(void *s, uint32_t c, size_t n);
+void *memmove(void *dst, const void *src, size_t len);
+void *memcpy(void *dst, void const *src, uint32_t n);
+void strupper(uint8_t *str);
+void strlower(uint8_t *str);
+
+#endif
diff --git a/kernel/libc/time.c b/kernel/libc/time.c
index a92994c..4bf653b 100644
--- a/kernel/libc/time.c
+++ b/kernel/libc/time.c
@@ -1,38 +1,38 @@
-#include "time.h"
-#include "../drivers/ports.h"
-
-// Check whether CMOS is updated or not
-static uint8_t is_cmos_updated() {
- outb(CMOS_ADDRESS, 0x0A);
-
- return (inb(CMOS_DATA) & 0x80);
-}
-
-// Get CMOS register's status
-static uint8_t reg_status(int32_t reg) {
- outb(CMOS_ADDRESS, reg);
-
- return inb(CMOS_DATA);
-}
-
-
-time_t cmos_reader() {
- while(is_cmos_updated()); // Wait until the CMOS is being updated
-
- time_t tm;
-
- tm.second = BCD_CONVERTER(reg_status(TIME_R_SECOND));
- tm.minute = BCD_CONVERTER(reg_status(TIME_R_MINUTE));
- tm.hour = BCD_CONVERTER(reg_status(TIME_R_HOUR));
- tm.day = BCD_CONVERTER(reg_status(TIME_R_DAY));
- tm.month = BCD_CONVERTER(reg_status(TIME_R_MONTH));
- tm.year = BCD_CONVERTER(reg_status(TIME_R_YEAR));
-
- return tm;
-}
-
-uint32_t get_time(uint32_t field) {
- while(is_cmos_updated()); // Wait the CMOS is being updated
-
- return BCD_CONVERTER(reg_status(field));
-}
+#include "time.h"
+#include "../drivers/ports.h"
+
+// Check whether CMOS is updated or not
+static uint8_t is_cmos_updated() {
+ outb(CMOS_ADDRESS, 0x0A);
+
+ return (inb(CMOS_DATA) & 0x80);
+}
+
+// Get CMOS register's status
+static uint8_t reg_status(int32_t reg) {
+ outb(CMOS_ADDRESS, reg);
+
+ return inb(CMOS_DATA);
+}
+
+
+time_t cmos_reader() {
+ while(is_cmos_updated()); // Wait until the CMOS is being updated
+
+ time_t tm;
+
+ tm.second = BCD_CONVERTER(reg_status(TIME_R_SECOND));
+ tm.minute = BCD_CONVERTER(reg_status(TIME_R_MINUTE));
+ tm.hour = BCD_CONVERTER(reg_status(TIME_R_HOUR));
+ tm.day = BCD_CONVERTER(reg_status(TIME_R_DAY));
+ tm.month = BCD_CONVERTER(reg_status(TIME_R_MONTH));
+ tm.year = BCD_CONVERTER(reg_status(TIME_R_YEAR));
+
+ return tm;
+}
+
+uint32_t get_time(uint32_t field) {
+ while(is_cmos_updated()); // Wait the CMOS is being updated
+
+ return BCD_CONVERTER(reg_status(field));
+}
diff --git a/kernel/libc/time.h b/kernel/libc/time.h
index 2c284a4..ac838bd 100644
--- a/kernel/libc/time.h
+++ b/kernel/libc/time.h
@@ -1,42 +1,42 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-/* Get time reading the RTC(real time clock) CMOS on the motherboard */
-#ifndef TIME_H
-#define TIME_H
-
-#include
-
-// Define RTC field registers
-#define TIME_R_YEAR 0x09
-#define TIME_R_MONTH 0x08
-#define TIME_R_DAY 0x07
-#define TIME_R_HOUR 0x06
-#define TIME_R_MINUTE 0x05
-#define TIME_R_SECOND 0x04
-//#define TIME_R_CENTURY 0x32
-
-// Define RTC address
-#define CMOS_ADDRESS 0x70
-#define CMOS_DATA 0x71
-
-// Convert BCD encoed values to binary
-#define BCD_CONVERTER(n) ((n / 16) * 10 + (n & 0xF))
-
-typedef struct {
- uint8_t second;
- uint8_t minute;
- uint8_t hour;
- uint8_t day;
- uint8_t month;
- uint8_t year;
-} time_t;
-
-time_t cmos_reader();
-uint32_t get_time(uint32_t field);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+/* Get time reading the RTC(real time clock) CMOS on the motherboard */
+#ifndef TIME_H
+#define TIME_H
+
+#include
+
+// Define RTC field registers
+#define TIME_R_YEAR 0x09
+#define TIME_R_MONTH 0x08
+#define TIME_R_DAY 0x07
+#define TIME_R_HOUR 0x06
+#define TIME_R_MINUTE 0x05
+#define TIME_R_SECOND 0x04
+//#define TIME_R_CENTURY 0x32
+
+// Define RTC address
+#define CMOS_ADDRESS 0x70
+#define CMOS_DATA 0x71
+
+// Convert BCD encoed values to binary
+#define BCD_CONVERTER(n) ((n / 16) * 10 + (n & 0xF))
+
+typedef struct {
+ uint8_t second;
+ uint8_t minute;
+ uint8_t hour;
+ uint8_t day;
+ uint8_t month;
+ uint8_t year;
+} time_t;
+
+time_t cmos_reader();
+uint32_t get_time(uint32_t field);
+
+#endif
diff --git a/kernel/mem/Makefile b/kernel/mem/Makefile
index ba06a1c..73b9ae4 100644
--- a/kernel/mem/Makefile
+++ b/kernel/mem/Makefile
@@ -1,9 +1,9 @@
-OBJS = paging.o kheap.o ordered_array.o
-
-CC = i686-elf-gcc # cross-compiler
-CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
-
-all:${OBJS}
-
-%.o: %.c
+OBJS = paging.o kheap.o ordered_array.o
+
+CC = i686-elf-gcc # cross-compiler
+CFLAGS = -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
+
+all:${OBJS}
+
+%.o: %.c
${CC} ${CFLAGS} $< -o $@
\ No newline at end of file
diff --git a/kernel/mem/kheap.c b/kernel/mem/kheap.c
index 122654f..7095d08 100644
--- a/kernel/mem/kheap.c
+++ b/kernel/mem/kheap.c
@@ -1,329 +1,329 @@
-#include "kheap.h"
-#include "paging.h"
-#include "../libc/panic.h"
-
-extern uint32_t end;
-uint32_t placement_addr = (uint32_t)&end;
-extern page_directory_t *kernel_directory;
-heap_t *kheap = 0;
-
-uint32_t kmalloc_int(uint32_t sz, int32_t align, uint32_t *phys) {
- if(kheap != 0) {
- void *addr = alloc(sz, (uint8_t)align, kheap);
- if(phys != 0) {
- page_t *page = get_page((uint32_t)addr, 0, kernel_directory);
- *phys = page->fr*0x1000 + ((uint32_t)addr&0xFFF);
- }
- return (uint32_t)addr;
- } else {
- if(align == 1 && (placement_addr & 0xFFFFF000)) {
- placement_addr &= 0xFFFFF000;
- placement_addr += 0x1000;
- }
- if(phys)
- *phys = placement_addr;
- uint32_t tmp = placement_addr;
- placement_addr += sz;
- return tmp;
- }
-}
-
-void kfree(void *p) {
- free(p, kheap);
-}
-
-uint32_t kmalloc_a(uint32_t sz) {
- return kmalloc_int(sz, 1, 0);
-}
-
-uint32_t kmalloc_p(uint32_t sz, uint32_t *phys) {
- return kmalloc_int(sz, 0, phys);
-}
-
-uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys) {
- return kmalloc_int(sz, 1, phys);
-}
-
-uint32_t kmalloc(uint32_t sz) {
- return kmalloc_int(sz, 0, 0);
-}
-
-static void expand(uint32_t new_size, heap_t *heap) {
- // First check if new size is greater than older one
- ASSERT(new_size > heap->end_address - heap->start_address);
-
- // Get nearest page boundary
- if((new_size&0xFFFFF000) != 0) {
- new_size &= 0xFFFFF000;
- new_size += 0x1000;
- }
- // Check if new size is not greater than maximum size
- ASSERT(heap->start_address+new_size <= heap->max_address);
-
- uint32_t old_size = heap->end_address - heap->start_address;
-
- uint32_t it = old_size;
- while(it < new_size) {
- alloc_frame(get_page(heap->start_address+it, 1, kernel_directory),
- (heap->supervisor) ? 1 : 0, (heap->readonly) ? 0 : 1);
- it += 0x1000; // Page size
- }
- heap->end_address = heap->start_address+new_size;
-}
-
-static uint32_t contract(uint32_t new_size, heap_t *heap) {
- ASSERT(new_size < heap->end_address-heap->start_address);
-
- if(new_size&0x1000) {
- new_size &= 0x1000;
- new_size += 0x1000;
- }
-
- if(new_size < HEAP_MIN_SIZE)
- new_size = HEAP_MIN_SIZE;
-
- uint32_t old_size = heap->end_address - heap->start_address;
- uint32_t it = old_size - 0x1000;
- while(new_size < it) {
- free_frame(get_page(heap->start_address+it, 0, kernel_directory));
- it -= 0x1000;
- }
-
- heap->end_address = heap->start_address + new_size;
- return new_size;
-}
-
-static uint32_t find_smallest_hole(uint32_t size, uint8_t page_align, heap_t *heap) {
- uint32_t it = 0;
-
- // Find smallest hole that fit our request
- while(it < heap->index.size) {
- header_t *head = (header_t*)lookup_ordered_array(it, &heap->index);
- if(page_align > 0) {
- // page must be aligned?
- uint32_t location = (uint32_t)head;
- uint32_t offset = 0;
- if(((location+sizeof(header_t)) & 0xFFFFF000) != 0)
- offset = 0x1000 - (location+sizeof(header_t))%0x1000;
- uint32_t hole_size = (uint32_t)head->size - offset;
- // Check if we can fit this page in that hole
- if(hole_size >= (uint32_t)size)
- break;
- } else if(head->size >= size)
- break;
- it++;
- }
-
- // If we didn't find anything
- if(it == heap->index.size)
- return -1;
- else
- return it;
-}
-
-static uint8_t header_t_less_than(void *a, void *b) {
- return (((header_t*)a)->size < ((header_t*)b)->size)?1:0;
-}
-
-heap_t *create_heap(uint32_t start, uint32_t end_addr, uint32_t max, uint8_t supervisor, uint8_t readonly) {
- heap_t *heap = (heap_t*)kmalloc(sizeof(heap_t));
-
- ASSERT(start%0x1000 == 0);
- ASSERT(end_addr%0x1000 == 0);
-
- // Initialize the index
- heap->index = place_ordered_array((void*)start, HEAP_INDEX_SIZE, &header_t_less_than);
- // Shift start address to the right
- start += sizeof(type_t) * HEAP_INDEX_SIZE;
-
- // Check if start address is page-aligned
- if ((start & 0xFFFFF000) != 0) {
- start &= 0xFFFFF000;
- start += 0x1000;
- }
- // Store vars into heap
- heap->start_address = start;
- heap->end_address = end_addr;
- heap->max_address = max;
- heap->supervisor = supervisor;
- heap->readonly = readonly;
-
- header_t *hole = (header_t*)start;
- hole->size = end_addr - start;
- hole->magic = HEAP_MAGIC;
- hole->is_hole = 1;
- insert_ordered_array((void*)hole, &heap->index);
-
- return heap;
-}
-
-void *alloc(uint32_t size, uint8_t page_align, heap_t *heap) {
- uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t);
- // Find smallest hole suitable
- uint32_t it = find_smallest_hole(new_size, page_align, heap);
-
- if((int32_t)it == -1) {
- uint32_t old_len = heap->end_address - heap->start_address;
- uint32_t old_end_addr = heap->end_address;
-
- // Allocate more space
- expand(old_len+new_size, heap);
- uint32_t new_len = heap->end_address - heap->start_address;
-
- it = 0;
- uint32_t idx = -1; uint32_t value = 0x0;
- while(it < heap->index.size) {
- uint32_t tmp = (uint32_t)lookup_ordered_array(it, &heap->index);
- if(tmp > value) {
- value = tmp;
- idx = it;
- }
- it++;
- }
-
- // If no headers has been found, add a new one
- if((int32_t)idx == -1) {
- header_t *head = (header_t*)old_end_addr;
- head->magic = HEAP_MAGIC;
- head->size = new_len - old_len;
- head->is_hole = 1;
-
- footer_t *foot = (footer_t*)(old_end_addr + head->size - sizeof(footer_t));
- foot->magic = HEAP_MAGIC;
- foot->header = head;
- insert_ordered_array((void*)head, &heap->index);
- } else {
- header_t *head = lookup_ordered_array(idx, &heap->index);
- head->size += new_len - old_len;
- // Update the footer
- footer_t *foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
- foot->header = head;
- foot->magic = HEAP_MAGIC;
- }
- // Now we have enough space, so recall this function again
- return alloc(size, page_align, heap);
- }
-
- header_t *origin_hole_head = (header_t*)lookup_ordered_array(it, &heap->index);
- uint32_t origin_hole_p = (uint32_t)origin_hole_head;
- uint32_t origin_hole_s = origin_hole_head->size;
- // Check if we should split the hole into two parts
- if(origin_hole_s-new_size < sizeof(header_t)+sizeof(footer_t)) {
- // Increase the requested size to the size of the hole we found
- size += origin_hole_s-new_size;
- new_size = origin_hole_s;
- }
-
- // Check if we need to page-align data
- if(page_align && origin_hole_p&0xFFFFF000) {
- uint32_t new_loc = origin_hole_p + 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t);
- header_t *hole_header = (header_t*)origin_hole_p;
- hole_header->size = 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t);
- hole_header->magic = HEAP_MAGIC;
- hole_header->is_hole = 1;
- footer_t *hole_footer = (footer_t*)((uint32_t)new_loc - sizeof(header_t));
- hole_footer->magic = HEAP_MAGIC;
- hole_footer->header = hole_header;
- origin_hole_p = new_loc;
- origin_hole_s = origin_hole_s - hole_header->size;
- } else
- remove_ordered_array(it, &heap->index); // Remove hole, since we don't need it anymore
-
- // Rewrite original header
- header_t *block_head = (header_t*)origin_hole_p;
- block_head->magic = HEAP_MAGIC;
- block_head->is_hole = 0;
- block_head->size = new_size;
- // and the footer
- footer_t *block_foot = (footer_t*)(origin_hole_p + sizeof(header_t) + size);
- block_foot->magic = HEAP_MAGIC;
- block_foot->header = block_head;
-
- // Check if we need to write a new hole after the allocated block
- if(origin_hole_s - new_size > 0) {
- header_t *hole_head = (header_t*)(origin_hole_p + sizeof(header_t) + size + sizeof(footer_t));
- hole_head->magic = HEAP_MAGIC;
- hole_head->is_hole = 1;
- hole_head->size = origin_hole_s - new_size;
- footer_t *hole_foot = (footer_t*)((uint32_t)hole_head + origin_hole_s - new_size - sizeof(footer_t));
- if((uint32_t)hole_foot < heap->end_address) {
- hole_foot->magic = HEAP_MAGIC;
- hole_foot->header = hole_head;
- }
- // Add new hole to the data structure
- insert_ordered_array((void*)hole_head, &heap->index);
- }
-
- // Return the block header
- return (void*)((uint32_t)block_head+sizeof(header_t));
-}
-
-void free(void *p, heap_t *heap) {
- // Check null pointers
- if(p == 0)
- return;
-
- // Retrieve data
- header_t *head = (header_t*)((uint32_t)p - sizeof(header_t));
- footer_t *foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
-
- ASSERT(head->magic == HEAP_MAGIC);
- ASSERT(foot->magic == HEAP_MAGIC);
-
- head->is_hole = 1; // Make this a hole
- int8_t add_to_free_hole = 1; // Add this header to free holes
-
- // Left unify
- footer_t *test_foot = (footer_t*)((uint32_t)head - sizeof(footer_t));
- if(test_foot->magic == HEAP_MAGIC && test_foot->header->is_hole == 1 ) {
- uint32_t cache_s = head->size; // Store current size
- head = test_foot->header; // Rewrite header into new one
- foot->header = head; // Point footer to the new header
- head->size += cache_s; // Increase size
- add_to_free_hole = 0; // Header already in the structure.
- }
-
- // Right unify
- header_t *test_head = (header_t*)((uint32_t)foot + sizeof(footer_t));
- if(test_head->magic == HEAP_MAGIC && test_head->is_hole) {
- head->size += test_head->size; // Increase size
- test_foot = (footer_t*)((uint32_t)test_foot + test_head->size - sizeof(footer_t));
- foot = test_foot;
- // Find and remove this header from the structure
- uint32_t it = 0;
- while((it < heap->index.size) && (lookup_ordered_array(it, &heap->index) != (void*)test_head))
- it++;
-
- // Check if we actually found something
- ASSERT(it < heap->index.size);
-
- // Remove that item
- remove_ordered_array(it, &heap->index);
- }
-
- // If footer is located at the end, we can contract the heap
- if((uint32_t)foot+sizeof(footer_t) == heap->end_address) {
- uint32_t old_len = heap->end_address-heap->start_address;
- uint32_t new_len = contract((uint32_t)head - heap->start_address, heap);
- // Check dimensions after resizing
- if(head->size - (old_len-new_len) > 0) {
- // Dimensions is still a positive value, so we can resize
- head->size -= old_len-new_len;
- foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
- foot->magic = HEAP_MAGIC;
- foot->header = head;
- } else {
- // Remove block from the structure
- uint32_t it = 0;
- while((it < heap->index.size) && (lookup_ordered_array(it, &heap->index) != (void*)test_head))
- it++;
- // If we didn't find that block we haven't nothing to remove
- if(it < heap->index.size)
- remove_ordered_array(it, &heap->index);
- }
- }
-
- // If required by the user, add that block to the structure
- if(add_to_free_hole == 1)
- insert_ordered_array((void*)head, &heap->index);
-}
+#include "kheap.h"
+#include "paging.h"
+#include "../libc/panic.h"
+
+extern uint32_t end;
+uint32_t placement_addr = (uint32_t)&end;
+extern page_directory_t *kernel_directory;
+heap_t *kheap = 0;
+
+uint32_t kmalloc_int(uint32_t sz, int32_t align, uint32_t *phys) {
+ if(kheap != 0) {
+ void *addr = alloc(sz, (uint8_t)align, kheap);
+ if(phys != 0) {
+ page_t *page = get_page((uint32_t)addr, 0, kernel_directory);
+ *phys = page->fr*0x1000 + ((uint32_t)addr&0xFFF);
+ }
+ return (uint32_t)addr;
+ } else {
+ if(align == 1 && (placement_addr & 0xFFFFF000)) {
+ placement_addr &= 0xFFFFF000;
+ placement_addr += 0x1000;
+ }
+ if(phys)
+ *phys = placement_addr;
+ uint32_t tmp = placement_addr;
+ placement_addr += sz;
+ return tmp;
+ }
+}
+
+void kfree(void *p) {
+ free(p, kheap);
+}
+
+uint32_t kmalloc_a(uint32_t sz) {
+ return kmalloc_int(sz, 1, 0);
+}
+
+uint32_t kmalloc_p(uint32_t sz, uint32_t *phys) {
+ return kmalloc_int(sz, 0, phys);
+}
+
+uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys) {
+ return kmalloc_int(sz, 1, phys);
+}
+
+uint32_t kmalloc(uint32_t sz) {
+ return kmalloc_int(sz, 0, 0);
+}
+
+static void expand(uint32_t new_size, heap_t *heap) {
+ // First check if new size is greater than older one
+ ASSERT(new_size > heap->end_address - heap->start_address);
+
+ // Get nearest page boundary
+ if((new_size&0xFFFFF000) != 0) {
+ new_size &= 0xFFFFF000;
+ new_size += 0x1000;
+ }
+ // Check if new size is not greater than maximum size
+ ASSERT(heap->start_address+new_size <= heap->max_address);
+
+ uint32_t old_size = heap->end_address - heap->start_address;
+
+ uint32_t it = old_size;
+ while(it < new_size) {
+ alloc_frame(get_page(heap->start_address+it, 1, kernel_directory),
+ (heap->supervisor) ? 1 : 0, (heap->readonly) ? 0 : 1);
+ it += 0x1000; // Page size
+ }
+ heap->end_address = heap->start_address+new_size;
+}
+
+static uint32_t contract(uint32_t new_size, heap_t *heap) {
+ ASSERT(new_size < heap->end_address-heap->start_address);
+
+ if(new_size&0x1000) {
+ new_size &= 0x1000;
+ new_size += 0x1000;
+ }
+
+ if(new_size < HEAP_MIN_SIZE)
+ new_size = HEAP_MIN_SIZE;
+
+ uint32_t old_size = heap->end_address - heap->start_address;
+ uint32_t it = old_size - 0x1000;
+ while(new_size < it) {
+ free_frame(get_page(heap->start_address+it, 0, kernel_directory));
+ it -= 0x1000;
+ }
+
+ heap->end_address = heap->start_address + new_size;
+ return new_size;
+}
+
+static uint32_t find_smallest_hole(uint32_t size, uint8_t page_align, heap_t *heap) {
+ uint32_t it = 0;
+
+ // Find smallest hole that fit our request
+ while(it < heap->index.size) {
+ header_t *head = (header_t*)lookup_ordered_array(it, &heap->index);
+ if(page_align > 0) {
+ // page must be aligned?
+ uint32_t location = (uint32_t)head;
+ uint32_t offset = 0;
+ if(((location+sizeof(header_t)) & 0xFFFFF000) != 0)
+ offset = 0x1000 - (location+sizeof(header_t))%0x1000;
+ uint32_t hole_size = (uint32_t)head->size - offset;
+ // Check if we can fit this page in that hole
+ if(hole_size >= (uint32_t)size)
+ break;
+ } else if(head->size >= size)
+ break;
+ it++;
+ }
+
+ // If we didn't find anything
+ if(it == heap->index.size)
+ return -1;
+ else
+ return it;
+}
+
+static uint8_t header_t_less_than(void *a, void *b) {
+ return (((header_t*)a)->size < ((header_t*)b)->size)?1:0;
+}
+
+heap_t *create_heap(uint32_t start, uint32_t end_addr, uint32_t max, uint8_t supervisor, uint8_t readonly) {
+ heap_t *heap = (heap_t*)kmalloc(sizeof(heap_t));
+
+ ASSERT(start%0x1000 == 0);
+ ASSERT(end_addr%0x1000 == 0);
+
+ // Initialize the index
+ heap->index = place_ordered_array((void*)start, HEAP_INDEX_SIZE, &header_t_less_than);
+ // Shift start address to the right
+ start += sizeof(type_t) * HEAP_INDEX_SIZE;
+
+ // Check if start address is page-aligned
+ if ((start & 0xFFFFF000) != 0) {
+ start &= 0xFFFFF000;
+ start += 0x1000;
+ }
+ // Store vars into heap
+ heap->start_address = start;
+ heap->end_address = end_addr;
+ heap->max_address = max;
+ heap->supervisor = supervisor;
+ heap->readonly = readonly;
+
+ header_t *hole = (header_t*)start;
+ hole->size = end_addr - start;
+ hole->magic = HEAP_MAGIC;
+ hole->is_hole = 1;
+ insert_ordered_array((void*)hole, &heap->index);
+
+ return heap;
+}
+
+void *alloc(uint32_t size, uint8_t page_align, heap_t *heap) {
+ uint32_t new_size = size + sizeof(header_t) + sizeof(footer_t);
+ // Find smallest hole suitable
+ uint32_t it = find_smallest_hole(new_size, page_align, heap);
+
+ if((int32_t)it == -1) {
+ uint32_t old_len = heap->end_address - heap->start_address;
+ uint32_t old_end_addr = heap->end_address;
+
+ // Allocate more space
+ expand(old_len+new_size, heap);
+ uint32_t new_len = heap->end_address - heap->start_address;
+
+ it = 0;
+ uint32_t idx = -1; uint32_t value = 0x0;
+ while(it < heap->index.size) {
+ uint32_t tmp = (uint32_t)lookup_ordered_array(it, &heap->index);
+ if(tmp > value) {
+ value = tmp;
+ idx = it;
+ }
+ it++;
+ }
+
+ // If no headers has been found, add a new one
+ if((int32_t)idx == -1) {
+ header_t *head = (header_t*)old_end_addr;
+ head->magic = HEAP_MAGIC;
+ head->size = new_len - old_len;
+ head->is_hole = 1;
+
+ footer_t *foot = (footer_t*)(old_end_addr + head->size - sizeof(footer_t));
+ foot->magic = HEAP_MAGIC;
+ foot->header = head;
+ insert_ordered_array((void*)head, &heap->index);
+ } else {
+ header_t *head = lookup_ordered_array(idx, &heap->index);
+ head->size += new_len - old_len;
+ // Update the footer
+ footer_t *foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
+ foot->header = head;
+ foot->magic = HEAP_MAGIC;
+ }
+ // Now we have enough space, so recall this function again
+ return alloc(size, page_align, heap);
+ }
+
+ header_t *origin_hole_head = (header_t*)lookup_ordered_array(it, &heap->index);
+ uint32_t origin_hole_p = (uint32_t)origin_hole_head;
+ uint32_t origin_hole_s = origin_hole_head->size;
+ // Check if we should split the hole into two parts
+ if(origin_hole_s-new_size < sizeof(header_t)+sizeof(footer_t)) {
+ // Increase the requested size to the size of the hole we found
+ size += origin_hole_s-new_size;
+ new_size = origin_hole_s;
+ }
+
+ // Check if we need to page-align data
+ if(page_align && origin_hole_p&0xFFFFF000) {
+ uint32_t new_loc = origin_hole_p + 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t);
+ header_t *hole_header = (header_t*)origin_hole_p;
+ hole_header->size = 0x1000 - (origin_hole_p&0xFFF) - sizeof(header_t);
+ hole_header->magic = HEAP_MAGIC;
+ hole_header->is_hole = 1;
+ footer_t *hole_footer = (footer_t*)((uint32_t)new_loc - sizeof(header_t));
+ hole_footer->magic = HEAP_MAGIC;
+ hole_footer->header = hole_header;
+ origin_hole_p = new_loc;
+ origin_hole_s = origin_hole_s - hole_header->size;
+ } else
+ remove_ordered_array(it, &heap->index); // Remove hole, since we don't need it anymore
+
+ // Rewrite original header
+ header_t *block_head = (header_t*)origin_hole_p;
+ block_head->magic = HEAP_MAGIC;
+ block_head->is_hole = 0;
+ block_head->size = new_size;
+ // and the footer
+ footer_t *block_foot = (footer_t*)(origin_hole_p + sizeof(header_t) + size);
+ block_foot->magic = HEAP_MAGIC;
+ block_foot->header = block_head;
+
+ // Check if we need to write a new hole after the allocated block
+ if(origin_hole_s - new_size > 0) {
+ header_t *hole_head = (header_t*)(origin_hole_p + sizeof(header_t) + size + sizeof(footer_t));
+ hole_head->magic = HEAP_MAGIC;
+ hole_head->is_hole = 1;
+ hole_head->size = origin_hole_s - new_size;
+ footer_t *hole_foot = (footer_t*)((uint32_t)hole_head + origin_hole_s - new_size - sizeof(footer_t));
+ if((uint32_t)hole_foot < heap->end_address) {
+ hole_foot->magic = HEAP_MAGIC;
+ hole_foot->header = hole_head;
+ }
+ // Add new hole to the data structure
+ insert_ordered_array((void*)hole_head, &heap->index);
+ }
+
+ // Return the block header
+ return (void*)((uint32_t)block_head+sizeof(header_t));
+}
+
+void free(void *p, heap_t *heap) {
+ // Check null pointers
+ if(p == 0)
+ return;
+
+ // Retrieve data
+ header_t *head = (header_t*)((uint32_t)p - sizeof(header_t));
+ footer_t *foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
+
+ ASSERT(head->magic == HEAP_MAGIC);
+ ASSERT(foot->magic == HEAP_MAGIC);
+
+ head->is_hole = 1; // Make this a hole
+ int8_t add_to_free_hole = 1; // Add this header to free holes
+
+ // Left unify
+ footer_t *test_foot = (footer_t*)((uint32_t)head - sizeof(footer_t));
+ if(test_foot->magic == HEAP_MAGIC && test_foot->header->is_hole == 1 ) {
+ uint32_t cache_s = head->size; // Store current size
+ head = test_foot->header; // Rewrite header into new one
+ foot->header = head; // Point footer to the new header
+ head->size += cache_s; // Increase size
+ add_to_free_hole = 0; // Header already in the structure.
+ }
+
+ // Right unify
+ header_t *test_head = (header_t*)((uint32_t)foot + sizeof(footer_t));
+ if(test_head->magic == HEAP_MAGIC && test_head->is_hole) {
+ head->size += test_head->size; // Increase size
+ test_foot = (footer_t*)((uint32_t)test_foot + test_head->size - sizeof(footer_t));
+ foot = test_foot;
+ // Find and remove this header from the structure
+ uint32_t it = 0;
+ while((it < heap->index.size) && (lookup_ordered_array(it, &heap->index) != (void*)test_head))
+ it++;
+
+ // Check if we actually found something
+ ASSERT(it < heap->index.size);
+
+ // Remove that item
+ remove_ordered_array(it, &heap->index);
+ }
+
+ // If footer is located at the end, we can contract the heap
+ if((uint32_t)foot+sizeof(footer_t) == heap->end_address) {
+ uint32_t old_len = heap->end_address-heap->start_address;
+ uint32_t new_len = contract((uint32_t)head - heap->start_address, heap);
+ // Check dimensions after resizing
+ if(head->size - (old_len-new_len) > 0) {
+ // Dimensions is still a positive value, so we can resize
+ head->size -= old_len-new_len;
+ foot = (footer_t*)((uint32_t)head + head->size - sizeof(footer_t));
+ foot->magic = HEAP_MAGIC;
+ foot->header = head;
+ } else {
+ // Remove block from the structure
+ uint32_t it = 0;
+ while((it < heap->index.size) && (lookup_ordered_array(it, &heap->index) != (void*)test_head))
+ it++;
+ // If we didn't find that block we haven't nothing to remove
+ if(it < heap->index.size)
+ remove_ordered_array(it, &heap->index);
+ }
+ }
+
+ // If required by the user, add that block to the structure
+ if(add_to_free_hole == 1)
+ insert_ordered_array((void*)head, &heap->index);
+}
diff --git a/kernel/mem/kheap.h b/kernel/mem/kheap.h
index 570d1a0..ed28d8d 100644
--- a/kernel/mem/kheap.h
+++ b/kernel/mem/kheap.h
@@ -1,70 +1,70 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-
-/*** Heap implementation from James Molloy's tutorial:
- http://www.jamesmolloy.co.uk/tutorial_html/7.-The%20Heap.html ***/
-
-/* This heap algorithm uses two different data structures: blocks and holes.
- * Blocks: Contiguous areas of memory containing user data
- * Holes: Special kind of blocks that are not in use, this is the result
- * of free() operation. Those spaces lend to a common problem called "Fragmentation";
- * where malloc() cannot use those spaces anymore because they are too small for any
- * kind of program. Any modern OS must have a solution to avoid this problem, but to keep
- * things simple as possible i wont implement anything like that.
- * Blocks/holes contains informations like the magic number(error checking), the type of
- * chunk(hole or block) and the size, while the footer contains only a pointer to the header
- * (and obviously an error checking flag).
- */
-#ifndef KHEAP_H
-#define KHEAP_H
-
-#define KHEAP_START 0xC0000000
-#define KHEAP_INITIAL_SIZE 0x100000
-
-#define HEAP_INDEX_SIZE 0x20000
-#define HEAP_MAGIC 0x123890AB
-#define HEAP_MIN_SIZE 0x70000
-
-#include
-#include "ordered_array.h"
-
-// Data structure for single hole/block
-typedef struct {
- uint32_t magic; // Magic number for error checking
- uint8_t is_hole; // 1 if it's an hole, 0 for a block
- uint32_t size; // Size of block
-} header_t;
-
-typedef struct {
- uint32_t magic; // Same as above
- header_t *header; // Pointer to the header block
-} footer_t;
-
-typedef struct {
- ordered_array_t index;
- uint32_t start_address; // Begin of allocated space
- uint32_t end_address; // End of allocated space
- uint32_t max_address; // Maximum size heap can be expanded to
- uint8_t supervisor;
- uint8_t readonly;
-} heap_t;
-
-// Create a new heap
-heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly);
-// Allocates a contigious region of memory in size
-void *alloc(uint32_t size, uint8_t page_align, heap_t *heap);
-// Free a block allocated with alloc
-void free(void *p, heap_t *heap);
-uint32_t kmalloc_int(uint32_t sz, int32_t align, uint32_t *phys);
-uint32_t kmalloc_a(uint32_t sz);
-uint32_t kmalloc_p(uint32_t sz, uint32_t *phys);
-uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys);
-uint32_t kmalloc(uint32_t sz);
-void kfree(void *p);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+
+/*** Heap implementation from James Molloy's tutorial:
+ http://www.jamesmolloy.co.uk/tutorial_html/7.-The%20Heap.html ***/
+
+/* This heap algorithm uses two different data structures: blocks and holes.
+ * Blocks: Contiguous areas of memory containing user data
+ * Holes: Special kind of blocks that are not in use, this is the result
+ * of free() operation. Those spaces lend to a common problem called "Fragmentation";
+ * where malloc() cannot use those spaces anymore because they are too small for any
+ * kind of program. Any modern OS must have a solution to avoid this problem, but to keep
+ * things simple as possible i wont implement anything like that.
+ * Blocks/holes contains informations like the magic number(error checking), the type of
+ * chunk(hole or block) and the size, while the footer contains only a pointer to the header
+ * (and obviously an error checking flag).
+ */
+#ifndef KHEAP_H
+#define KHEAP_H
+
+#define KHEAP_START 0xC0000000
+#define KHEAP_INITIAL_SIZE 0x100000
+
+#define HEAP_INDEX_SIZE 0x20000
+#define HEAP_MAGIC 0x123890AB
+#define HEAP_MIN_SIZE 0x70000
+
+#include
+#include "ordered_array.h"
+
+// Data structure for single hole/block
+typedef struct {
+ uint32_t magic; // Magic number for error checking
+ uint8_t is_hole; // 1 if it's an hole, 0 for a block
+ uint32_t size; // Size of block
+} header_t;
+
+typedef struct {
+ uint32_t magic; // Same as above
+ header_t *header; // Pointer to the header block
+} footer_t;
+
+typedef struct {
+ ordered_array_t index;
+ uint32_t start_address; // Begin of allocated space
+ uint32_t end_address; // End of allocated space
+ uint32_t max_address; // Maximum size heap can be expanded to
+ uint8_t supervisor;
+ uint8_t readonly;
+} heap_t;
+
+// Create a new heap
+heap_t *create_heap(uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly);
+// Allocates a contigious region of memory in size
+void *alloc(uint32_t size, uint8_t page_align, heap_t *heap);
+// Free a block allocated with alloc
+void free(void *p, heap_t *heap);
+uint32_t kmalloc_int(uint32_t sz, int32_t align, uint32_t *phys);
+uint32_t kmalloc_a(uint32_t sz);
+uint32_t kmalloc_p(uint32_t sz, uint32_t *phys);
+uint32_t kmalloc_ap(uint32_t sz, uint32_t *phys);
+uint32_t kmalloc(uint32_t sz);
+void kfree(void *p);
+
+#endif
diff --git a/kernel/mem/multiboot.h b/kernel/mem/multiboot.h
index 6169c96..5c31e0a 100644
--- a/kernel/mem/multiboot.h
+++ b/kernel/mem/multiboot.h
@@ -1,518 +1,518 @@
-/* multiboot2.h - Multiboot 2 header file. */
-/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
- * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
- * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef MULTIBOOT_HEADER
-#define MULTIBOOT_HEADER 1
-
-/* How many bytes from the start of the file we search for the header. */
-#define MULTIBOOT_SEARCH 32768
-#define MULTIBOOT_HEADER_ALIGN 8
-
-/* The magic field should contain this. */
-#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
-
-/* This should be in %eax. */
-#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
-
-/* Alignment of multiboot modules. */
-#define MULTIBOOT_MOD_ALIGN 0x00001000
-
-/* Alignment of the multiboot info structure. */
-#define MULTIBOOT_INFO_ALIGN 0x00000008
-
-/* Flags set in the ’flags’ member of the multiboot header. */
-
-#define MULTIBOOT_TAG_ALIGN 8
-#define MULTIBOOT_TAG_TYPE_END 0
-#define MULTIBOOT_TAG_TYPE_CMDLINE 1
-#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
-#define MULTIBOOT_TAG_TYPE_MODULE 3
-#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
-#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
-#define MULTIBOOT_TAG_TYPE_MMAP 6
-#define MULTIBOOT_TAG_TYPE_VBE 7
-#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
-#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
-#define MULTIBOOT_TAG_TYPE_APM 10
-#define MULTIBOOT_TAG_TYPE_EFI32 11
-#define MULTIBOOT_TAG_TYPE_EFI64 12
-#define MULTIBOOT_TAG_TYPE_SMBIOS 13
-#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
-#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
-#define MULTIBOOT_TAG_TYPE_NETWORK 16
-#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
-#define MULTIBOOT_TAG_TYPE_EFI_BS 18
-#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
-#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
-#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
-
-#define MULTIBOOT_HEADER_TAG_END 0
-#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
-#define MULTIBOOT_HEADER_TAG_ADDRESS 2
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
-#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
-#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
-#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
-#define MULTIBOOT_HEADER_TAG_EFI_BS 7
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
-#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
-
-#define MULTIBOOT_ARCHITECTURE_I386 0
-#define MULTIBOOT_ARCHITECTURE_MIPS32 4
-#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
-
-#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
-#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
-#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
-
-#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
-#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
-
-#ifndef ASM_FILE
-
-typedef unsigned char multiboot_uint8_t;
-typedef unsigned short multiboot_uint16_t;
-typedef unsigned int multiboot_uint32_t;
-typedef unsigned long long multiboot_uint64_t;
-
-struct multiboot_header
-{
- /* Must be MULTIBOOT_MAGIC - see above. */
- multiboot_uint32_t magic;
-
- /* ISA */
- multiboot_uint32_t architecture;
-
- /* Total header length. */
- multiboot_uint32_t header_length;
-
- /* The above fields plus this one must equal 0 mod 2^32. */
- multiboot_uint32_t checksum;
-};
-
-struct multiboot_header_tag
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
-};
-
-struct multiboot_header_tag_information_request
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t requests[0];
-};
-
-struct multiboot_header_tag_address
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t header_addr;
- multiboot_uint32_t load_addr;
- multiboot_uint32_t load_end_addr;
- multiboot_uint32_t bss_end_addr;
-};
-
-struct multiboot_header_tag_entry_address
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t entry_addr;
-};
-
-struct multiboot_header_tag_console_flags
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t console_flags;
-};
-
-struct multiboot_header_tag_framebuffer
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t width;
- multiboot_uint32_t height;
- multiboot_uint32_t depth;
-};
-
-struct multiboot_header_tag_module_align
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
-};
-
-/* The symbol table for a.out. */
-struct multiboot_aout_symbol_table
-{
- multiboot_uint32_t tabsize;
- multiboot_uint32_t strsize;
- multiboot_uint32_t addr;
- multiboot_uint32_t reserved;
-};
-typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
-
-/* The section header table for ELF. */
-struct multiboot_elf_section_header_table
-{
- multiboot_uint32_t num;
- multiboot_uint32_t size;
- multiboot_uint32_t addr;
- multiboot_uint32_t shndx;
-};
-typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
-
-struct multiboot_info
-{
- /* Multiboot info version number */
- multiboot_uint32_t flags;
-
- /* Available memory from BIOS */
- multiboot_uint32_t mem_lower;
- multiboot_uint32_t mem_upper;
-
- /* "root" partition */
- multiboot_uint32_t boot_device;
-
- /* Kernel command line */
- multiboot_uint32_t cmdline;
-
- /* Boot-Module list */
- multiboot_uint32_t mods_count;
- multiboot_uint32_t mods_addr;
-
- union
- {
- multiboot_aout_symbol_table_t aout_sym;
- multiboot_elf_section_header_table_t elf_sec;
- } u;
-
- /* Memory Mapping buffer */
- multiboot_uint32_t mmap_length;
- multiboot_uint32_t mmap_addr;
-
- /* Drive Info buffer */
- multiboot_uint32_t drives_length;
- multiboot_uint32_t drives_addr;
-
- /* ROM configuration table */
- multiboot_uint32_t config_table;
-
- /* Boot Loader Name */
- multiboot_uint32_t boot_loader_name;
-
- /* APM table */
- multiboot_uint32_t apm_table;
-
- /* Video */
- multiboot_uint32_t vbe_control_info;
- multiboot_uint32_t vbe_mode_info;
- multiboot_uint16_t vbe_mode;
- multiboot_uint16_t vbe_interface_seg;
- multiboot_uint16_t vbe_interface_off;
- multiboot_uint16_t vbe_interface_len;
-
- multiboot_uint64_t framebuffer_addr;
- multiboot_uint32_t framebuffer_pitch;
- multiboot_uint32_t framebuffer_width;
- multiboot_uint32_t framebuffer_height;
- multiboot_uint8_t framebuffer_bpp;
-#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
-#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
-#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
- multiboot_uint8_t framebuffer_type;
- union
- {
- struct
- {
- multiboot_uint32_t framebuffer_palette_addr;
- multiboot_uint16_t framebuffer_palette_num_colors;
- };
- struct
- {
- multiboot_uint8_t framebuffer_red_field_position;
- multiboot_uint8_t framebuffer_red_mask_size;
- multiboot_uint8_t framebuffer_green_field_position;
- multiboot_uint8_t framebuffer_green_mask_size;
- multiboot_uint8_t framebuffer_blue_field_position;
- multiboot_uint8_t framebuffer_blue_mask_size;
- };
- };
-};
-typedef struct multiboot_info multiboot_info_t;
-
-
-struct multiboot_header_tag_relocatable
-{
- multiboot_uint16_t type;
- multiboot_uint16_t flags;
- multiboot_uint32_t size;
- multiboot_uint32_t min_addr;
- multiboot_uint32_t max_addr;
- multiboot_uint32_t align;
- multiboot_uint32_t preference;
-};
-
-struct multiboot_color
-{
- multiboot_uint8_t red;
- multiboot_uint8_t green;
- multiboot_uint8_t blue;
-};
-
-struct multiboot_mmap_entry
-{
- multiboot_uint32_t size;
- multiboot_uint64_t addr;
- multiboot_uint64_t len;
-#define MULTIBOOT_MEMORY_AVAILABLE 1
-#define MULTIBOOT_MEMORY_RESERVED 2
-#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
-#define MULTIBOOT_MEMORY_NVS 4
-#define MULTIBOOT_MEMORY_BADRAM 5
- multiboot_uint32_t type;
- multiboot_uint32_t zero;
-};
-typedef struct multiboot_mmap_entry multiboot_memory_map_t;
-
-struct multiboot_tag
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
-};
-
-struct multiboot_tag_string
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- char string[0];
-};
-
-struct multiboot_tag_module
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t mod_start;
- multiboot_uint32_t mod_end;
- char cmdline[0];
-};
-
-struct multiboot_tag_basic_meminfo
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t mem_lower;
- multiboot_uint32_t mem_upper;
-};
-
-struct multiboot_tag_bootdev
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t biosdev;
- multiboot_uint32_t slice;
- multiboot_uint32_t part;
-};
-
-struct multiboot_tag_mmap
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t entry_size;
- multiboot_uint32_t entry_version;
- struct multiboot_mmap_entry entries[0];
-};
-
-struct multiboot_vbe_info_block
-{
- multiboot_uint8_t external_specification[512];
-};
-
-struct multiboot_vbe_mode_info_block
-{
- multiboot_uint8_t external_specification[256];
-};
-
-struct multiboot_tag_vbe
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
-
- multiboot_uint16_t vbe_mode;
- multiboot_uint16_t vbe_interface_seg;
- multiboot_uint16_t vbe_interface_off;
- multiboot_uint16_t vbe_interface_len;
-
- struct multiboot_vbe_info_block vbe_control_info;
- struct multiboot_vbe_mode_info_block vbe_mode_info;
-};
-
-struct multiboot_tag_framebuffer_common
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
-
- multiboot_uint64_t framebuffer_addr;
- multiboot_uint32_t framebuffer_pitch;
- multiboot_uint32_t framebuffer_width;
- multiboot_uint32_t framebuffer_height;
- multiboot_uint8_t framebuffer_bpp;
-#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
-#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
-#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
- multiboot_uint8_t framebuffer_type;
- multiboot_uint16_t reserved;
-};
-
-struct multiboot_tag_framebuffer
-{
- struct multiboot_tag_framebuffer_common common;
-
- union
- {
- struct
- {
- multiboot_uint16_t framebuffer_palette_num_colors;
- struct multiboot_color framebuffer_palette[0];
- };
- struct
- {
- multiboot_uint8_t framebuffer_red_field_position;
- multiboot_uint8_t framebuffer_red_mask_size;
- multiboot_uint8_t framebuffer_green_field_position;
- multiboot_uint8_t framebuffer_green_mask_size;
- multiboot_uint8_t framebuffer_blue_field_position;
- multiboot_uint8_t framebuffer_blue_mask_size;
- };
- };
-};
-
-struct multiboot_tag_elf_sections
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t num;
- multiboot_uint32_t entsize;
- multiboot_uint32_t shndx;
- char sections[0];
-};
-
-struct multiboot_tag_apm
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint16_t version;
- multiboot_uint16_t cseg;
- multiboot_uint32_t offset;
- multiboot_uint16_t cseg_16;
- multiboot_uint16_t dseg;
- multiboot_uint16_t flags;
- multiboot_uint16_t cseg_len;
- multiboot_uint16_t cseg_16_len;
- multiboot_uint16_t dseg_len;
-};
-
-struct multiboot_tag_efi32
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t pointer;
-};
-
-struct multiboot_tag_efi64
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint64_t pointer;
-};
-
-struct multiboot_tag_smbios
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint8_t major;
- multiboot_uint8_t minor;
- multiboot_uint8_t reserved[6];
- multiboot_uint8_t tables[0];
-};
-
-struct multiboot_tag_old_acpi
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint8_t rsdp[0];
-};
-
-struct multiboot_tag_new_acpi
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint8_t rsdp[0];
-};
-
-struct multiboot_tag_network
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint8_t dhcpack[0];
-};
-
-struct multiboot_tag_efi_mmap
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t descr_size;
- multiboot_uint32_t descr_vers;
- multiboot_uint8_t efi_mmap[0];
-};
-
-struct multiboot_tag_efi32_ih
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t pointer;
-};
-
-struct multiboot_tag_efi64_ih
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint64_t pointer;
-};
-
-struct multiboot_tag_load_base_addr
-{
- multiboot_uint32_t type;
- multiboot_uint32_t size;
- multiboot_uint32_t load_base_addr;
-};
-
-#endif /* ! ASM_FILE */
-
-#endif /* ! MULTIBOOT_HEADER */
+/* multiboot2.h - Multiboot 2 header file. */
+/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
+ * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 32768
+#define MULTIBOOT_HEADER_ALIGN 8
+
+/* The magic field should contain this. */
+#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
+
+/* This should be in %eax. */
+#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+/* Alignment of the multiboot info structure. */
+#define MULTIBOOT_INFO_ALIGN 0x00000008
+
+/* Flags set in the ’flags’ member of the multiboot header. */
+
+#define MULTIBOOT_TAG_ALIGN 8
+#define MULTIBOOT_TAG_TYPE_END 0
+#define MULTIBOOT_TAG_TYPE_CMDLINE 1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
+#define MULTIBOOT_TAG_TYPE_MODULE 3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
+#define MULTIBOOT_TAG_TYPE_MMAP 6
+#define MULTIBOOT_TAG_TYPE_VBE 7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
+#define MULTIBOOT_TAG_TYPE_APM 10
+#define MULTIBOOT_TAG_TYPE_EFI32 11
+#define MULTIBOOT_TAG_TYPE_EFI64 12
+#define MULTIBOOT_TAG_TYPE_SMBIOS 13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
+#define MULTIBOOT_TAG_TYPE_NETWORK 16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
+#define MULTIBOOT_TAG_TYPE_EFI_BS 18
+#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
+#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
+
+#define MULTIBOOT_HEADER_TAG_END 0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+#define MULTIBOOT_HEADER_TAG_ADDRESS 2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+#define MULTIBOOT_HEADER_TAG_EFI_BS 7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
+
+#define MULTIBOOT_ARCHITECTURE_I386 0
+#define MULTIBOOT_ARCHITECTURE_MIPS32 4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+
+#ifndef ASM_FILE
+
+typedef unsigned char multiboot_uint8_t;
+typedef unsigned short multiboot_uint16_t;
+typedef unsigned int multiboot_uint32_t;
+typedef unsigned long long multiboot_uint64_t;
+
+struct multiboot_header
+{
+ /* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+ /* ISA */
+ multiboot_uint32_t architecture;
+
+ /* Total header length. */
+ multiboot_uint32_t header_length;
+
+ /* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+};
+
+struct multiboot_header_tag
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_header_tag_information_request
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t requests[0];
+};
+
+struct multiboot_header_tag_address
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+};
+
+struct multiboot_header_tag_entry_address
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_addr;
+};
+
+struct multiboot_header_tag_console_flags
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t console_flags;
+};
+
+struct multiboot_header_tag_framebuffer
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+struct multiboot_header_tag_module_align
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+};
+
+/* The symbol table for a.out. */
+struct multiboot_aout_symbol_table
+{
+ multiboot_uint32_t tabsize;
+ multiboot_uint32_t strsize;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t reserved;
+};
+typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
+
+/* The section header table for ELF. */
+struct multiboot_elf_section_header_table
+{
+ multiboot_uint32_t num;
+ multiboot_uint32_t size;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t shndx;
+};
+typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
+
+struct multiboot_info
+{
+ /* Multiboot info version number */
+ multiboot_uint32_t flags;
+
+ /* Available memory from BIOS */
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+
+ /* "root" partition */
+ multiboot_uint32_t boot_device;
+
+ /* Kernel command line */
+ multiboot_uint32_t cmdline;
+
+ /* Boot-Module list */
+ multiboot_uint32_t mods_count;
+ multiboot_uint32_t mods_addr;
+
+ union
+ {
+ multiboot_aout_symbol_table_t aout_sym;
+ multiboot_elf_section_header_table_t elf_sec;
+ } u;
+
+ /* Memory Mapping buffer */
+ multiboot_uint32_t mmap_length;
+ multiboot_uint32_t mmap_addr;
+
+ /* Drive Info buffer */
+ multiboot_uint32_t drives_length;
+ multiboot_uint32_t drives_addr;
+
+ /* ROM configuration table */
+ multiboot_uint32_t config_table;
+
+ /* Boot Loader Name */
+ multiboot_uint32_t boot_loader_name;
+
+ /* APM table */
+ multiboot_uint32_t apm_table;
+
+ /* Video */
+ multiboot_uint32_t vbe_control_info;
+ multiboot_uint32_t vbe_mode_info;
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
+ multiboot_uint8_t framebuffer_type;
+ union
+ {
+ struct
+ {
+ multiboot_uint32_t framebuffer_palette_addr;
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ };
+ struct
+ {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
+};
+typedef struct multiboot_info multiboot_info_t;
+
+
+struct multiboot_header_tag_relocatable
+{
+ multiboot_uint16_t type;
+ multiboot_uint16_t flags;
+ multiboot_uint32_t size;
+ multiboot_uint32_t min_addr;
+ multiboot_uint32_t max_addr;
+ multiboot_uint32_t align;
+ multiboot_uint32_t preference;
+};
+
+struct multiboot_color
+{
+ multiboot_uint8_t red;
+ multiboot_uint8_t green;
+ multiboot_uint8_t blue;
+};
+
+struct multiboot_mmap_entry
+{
+ multiboot_uint32_t size;
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
+#define MULTIBOOT_MEMORY_NVS 4
+#define MULTIBOOT_MEMORY_BADRAM 5
+ multiboot_uint32_t type;
+ multiboot_uint32_t zero;
+};
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_tag
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+};
+
+struct multiboot_tag_string
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ char string[0];
+};
+
+struct multiboot_tag_module
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+ char cmdline[0];
+};
+
+struct multiboot_tag_basic_meminfo
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+};
+
+struct multiboot_tag_bootdev
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t biosdev;
+ multiboot_uint32_t slice;
+ multiboot_uint32_t part;
+};
+
+struct multiboot_tag_mmap
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t entry_size;
+ multiboot_uint32_t entry_version;
+ struct multiboot_mmap_entry entries[0];
+};
+
+struct multiboot_vbe_info_block
+{
+ multiboot_uint8_t external_specification[512];
+};
+
+struct multiboot_vbe_mode_info_block
+{
+ multiboot_uint8_t external_specification[256];
+};
+
+struct multiboot_tag_vbe
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+
+ struct multiboot_vbe_info_block vbe_control_info;
+ struct multiboot_vbe_mode_info_block vbe_mode_info;
+};
+
+struct multiboot_tag_framebuffer_common
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+
+ multiboot_uint64_t framebuffer_addr;
+ multiboot_uint32_t framebuffer_pitch;
+ multiboot_uint32_t framebuffer_width;
+ multiboot_uint32_t framebuffer_height;
+ multiboot_uint8_t framebuffer_bpp;
+#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
+#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
+#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
+ multiboot_uint8_t framebuffer_type;
+ multiboot_uint16_t reserved;
+};
+
+struct multiboot_tag_framebuffer
+{
+ struct multiboot_tag_framebuffer_common common;
+
+ union
+ {
+ struct
+ {
+ multiboot_uint16_t framebuffer_palette_num_colors;
+ struct multiboot_color framebuffer_palette[0];
+ };
+ struct
+ {
+ multiboot_uint8_t framebuffer_red_field_position;
+ multiboot_uint8_t framebuffer_red_mask_size;
+ multiboot_uint8_t framebuffer_green_field_position;
+ multiboot_uint8_t framebuffer_green_mask_size;
+ multiboot_uint8_t framebuffer_blue_field_position;
+ multiboot_uint8_t framebuffer_blue_mask_size;
+ };
+ };
+};
+
+struct multiboot_tag_elf_sections
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t num;
+ multiboot_uint32_t entsize;
+ multiboot_uint32_t shndx;
+ char sections[0];
+};
+
+struct multiboot_tag_apm
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint16_t version;
+ multiboot_uint16_t cseg;
+ multiboot_uint32_t offset;
+ multiboot_uint16_t cseg_16;
+ multiboot_uint16_t dseg;
+ multiboot_uint16_t flags;
+ multiboot_uint16_t cseg_len;
+ multiboot_uint16_t cseg_16_len;
+ multiboot_uint16_t dseg_len;
+};
+
+struct multiboot_tag_efi32
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_smbios
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t major;
+ multiboot_uint8_t minor;
+ multiboot_uint8_t reserved[6];
+ multiboot_uint8_t tables[0];
+};
+
+struct multiboot_tag_old_acpi
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_new_acpi
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t rsdp[0];
+};
+
+struct multiboot_tag_network
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint8_t dhcpack[0];
+};
+
+struct multiboot_tag_efi_mmap
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t descr_size;
+ multiboot_uint32_t descr_vers;
+ multiboot_uint8_t efi_mmap[0];
+};
+
+struct multiboot_tag_efi32_ih
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t pointer;
+};
+
+struct multiboot_tag_efi64_ih
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint64_t pointer;
+};
+
+struct multiboot_tag_load_base_addr
+{
+ multiboot_uint32_t type;
+ multiboot_uint32_t size;
+ multiboot_uint32_t load_base_addr;
+};
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */
diff --git a/kernel/mem/ordered_array.c b/kernel/mem/ordered_array.c
index 521e4d1..c576f92 100644
--- a/kernel/mem/ordered_array.c
+++ b/kernel/mem/ordered_array.c
@@ -1,66 +1,66 @@
-#include "ordered_array.h"
-#include "kheap.h"
-#include "../libc/panic.h"
-#include "../libc/string.h"
-
-uint8_t standard_lessthan_predicate(type_t a, type_t b) {
- if (a < b)
- return 1;
- else
- return 0;
-}
-
-ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than) {
- ordered_array_t to_ret;
- to_ret.array = (void*)kmalloc(max_size*sizeof(type_t));
- memset(to_ret.array, 0, max_size*sizeof(type_t));
- to_ret.size = 0;
- to_ret.max_size = max_size;
- to_ret.less_than = less_than;
- return to_ret;
-}
-
-ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than) {
- ordered_array_t to_ret;
- to_ret.array = (type_t*)addr;
- memset(to_ret.array, 0, max_size*sizeof(type_t));
- to_ret.size = 0;
- to_ret.max_size = max_size;
- to_ret.less_than = less_than;
- return to_ret;
-}
-
-void destroy_ordered_array(ordered_array_t *array) {
- kfree(array->array);
-}
-
-void insert_ordered_array(type_t item, ordered_array_t *array) {
- uint32_t it = 0;
- while(it < array->size && array->less_than(array->array[it], item))
- it++;
- if(it == array->size)
- array->array[array->size++] = item;
- else {
- type_t tmp = array->array[it];
- array->array[it] = item;
- while(it < array->size) {
- it++;
- type_t tmp2 = array->array[it];
- array->array[it] = tmp;
- tmp = tmp2;
- }
- array->size++;
- }
-}
-
-type_t lookup_ordered_array(uint32_t i, ordered_array_t *array) {
- return array->array[i];
-}
-
-void remove_ordered_array(uint32_t i, ordered_array_t *array) {
- while(i < array->size) {
- array->array[i] = array->array[i+1];
- i++;
- }
- array->size--;
-}
+#include "ordered_array.h"
+#include "kheap.h"
+#include "../libc/panic.h"
+#include "../libc/string.h"
+
+uint8_t standard_lessthan_predicate(type_t a, type_t b) {
+ if (a < b)
+ return 1;
+ else
+ return 0;
+}
+
+ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than) {
+ ordered_array_t to_ret;
+ to_ret.array = (void*)kmalloc(max_size*sizeof(type_t));
+ memset(to_ret.array, 0, max_size*sizeof(type_t));
+ to_ret.size = 0;
+ to_ret.max_size = max_size;
+ to_ret.less_than = less_than;
+ return to_ret;
+}
+
+ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than) {
+ ordered_array_t to_ret;
+ to_ret.array = (type_t*)addr;
+ memset(to_ret.array, 0, max_size*sizeof(type_t));
+ to_ret.size = 0;
+ to_ret.max_size = max_size;
+ to_ret.less_than = less_than;
+ return to_ret;
+}
+
+void destroy_ordered_array(ordered_array_t *array) {
+ kfree(array->array);
+}
+
+void insert_ordered_array(type_t item, ordered_array_t *array) {
+ uint32_t it = 0;
+ while(it < array->size && array->less_than(array->array[it], item))
+ it++;
+ if(it == array->size)
+ array->array[array->size++] = item;
+ else {
+ type_t tmp = array->array[it];
+ array->array[it] = item;
+ while(it < array->size) {
+ it++;
+ type_t tmp2 = array->array[it];
+ array->array[it] = tmp;
+ tmp = tmp2;
+ }
+ array->size++;
+ }
+}
+
+type_t lookup_ordered_array(uint32_t i, ordered_array_t *array) {
+ return array->array[i];
+}
+
+void remove_ordered_array(uint32_t i, ordered_array_t *array) {
+ while(i < array->size) {
+ array->array[i] = array->array[i+1];
+ i++;
+ }
+ array->size--;
+}
diff --git a/kernel/mem/ordered_array.h b/kernel/mem/ordered_array.h
index ca5ba88..5b39f6e 100644
--- a/kernel/mem/ordered_array.h
+++ b/kernel/mem/ordered_array.h
@@ -1,39 +1,39 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef ORDERED_ARRAY_H
-#define ORDERED_ARRAY_H
-
-#include
-
-/* Our list is always in a 'sorted state',
- * it can store anything that can be casted
- * to void* */
-typedef void* type_t;
-/* The following predicate should return non-zero
- * if the first argument is less than the second */
-typedef uint8_t (*lessthan_predicate_t)(type_t,type_t);
-typedef struct {
- type_t *array;
- uint32_t size;
- uint32_t max_size;
- lessthan_predicate_t less_than;
-} ordered_array_t;
-
-uint8_t standard_lessthan_predicate(type_t a, type_t b);
-
-// Create a new ordered array
-ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than);
-ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than);
-// Destroy an ordered array
-void destroy_ordered_array(ordered_array_t *array);
-// Add an item into the array
-void insert_ordered_array(type_t item, ordered_array_t *array);
-type_t lookup_ordered_array(uint32_t i, ordered_array_t *array);
-void remove_ordered_array(uint32_t i, ordered_array_t *array);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef ORDERED_ARRAY_H
+#define ORDERED_ARRAY_H
+
+#include
+
+/* Our list is always in a 'sorted state',
+ * it can store anything that can be casted
+ * to void* */
+typedef void* type_t;
+/* The following predicate should return non-zero
+ * if the first argument is less than the second */
+typedef uint8_t (*lessthan_predicate_t)(type_t,type_t);
+typedef struct {
+ type_t *array;
+ uint32_t size;
+ uint32_t max_size;
+ lessthan_predicate_t less_than;
+} ordered_array_t;
+
+uint8_t standard_lessthan_predicate(type_t a, type_t b);
+
+// Create a new ordered array
+ordered_array_t create_ordered_array(uint32_t max_size, lessthan_predicate_t less_than);
+ordered_array_t place_ordered_array(void *addr, uint32_t max_size, lessthan_predicate_t less_than);
+// Destroy an ordered array
+void destroy_ordered_array(ordered_array_t *array);
+// Add an item into the array
+void insert_ordered_array(type_t item, ordered_array_t *array);
+type_t lookup_ordered_array(uint32_t i, ordered_array_t *array);
+void remove_ordered_array(uint32_t i, ordered_array_t *array);
+
+#endif
diff --git a/kernel/mem/paging.c b/kernel/mem/paging.c
index 7225b9c..97cc0eb 100644
--- a/kernel/mem/paging.c
+++ b/kernel/mem/paging.c
@@ -1,141 +1,141 @@
-#include "paging.h"
-#include "../libc/string.h"
-#include "../libc/panic.h"
-#include "../libc/stdio.h"
-#include "../drivers/tty.h"
-
-// External definitions from kheap.c
-extern uint32_t placement_addr;
-extern heap_t *kheap;
-
-// Bitset of frames, used or free
-uint32_t *frame_allocations;
-uint32_t nframes; // Number of physical frames
-page_directory_t *kernel_directory = 0;
-page_directory_t *current_directory = 0;
-
-static void set_frame(uint32_t addr) {
- uint32_t frame = FRAME(addr);
- uint32_t frame_alloc_s = FRAME_SECTION(frame);
- uint32_t frame_alloc_o = FRAME_OFFSET(frame);
- frame_allocations[frame_alloc_s] |= (1 << frame_alloc_o);
-}
-
-static void clear_frame(uint32_t addr) {
- uint32_t frame = FRAME(addr);
- uint32_t frame_alloc_s = FRAME_SECTION(frame);
- uint32_t frame_alloc_o = FRAME_OFFSET(frame);
- frame_allocations[frame_alloc_s] &= ~(1 << frame_alloc_o);
-}
-
-static uint32_t first_frame() {
- uint32_t nsections = nframes / FRAME_ALLOCATIONS_SECTION_SIZE;
- for(uint32_t sec = 0; sec < nsections; sec++)
- if(frame_allocations[sec] != USED_FRAME_SECTION)
- for(uint32_t idx = 0; idx < FRAME_ALLOCATIONS_SECTION_SIZE; idx++)
- if(!(frame_allocations[sec] & (0x1 << idx)))
- return (sec*FRAME_ALLOCATIONS_SECTION_SIZE) + idx;
- return nsections * FRAME_ALLOCATIONS_SECTION_SIZE;
-}
-
-void alloc_frame(page_t *page, int32_t is_super, int32_t is_write) {
- if(page->fr != 0)
- return;
- else {
- uint32_t fframe = first_frame();
- if(fframe == (uint32_t)-1) {
- PANIC("No free frames availables!");
- } else {
- // Set free frames to the page
- page->pr = PAGE_PRESENT;
- page->rw = (is_write) ? PAGE_READ_WRITE : PAGE_READ_ONLY;
- page->us = (is_super) ? PAGE_SUPERVISOR : PAGE_USER;
- page->fr = fframe;
- // Set new frames as used
- uint32_t physical_addr = fframe * FRAME_SIZE;
- set_frame(physical_addr);
- }
- }
-}
-
-void free_frame(page_t *page) {
- uint32_t frame;
- if(!(frame=page->fr))
- return; // page doesn't have a frame in first place
- else {
- clear_frame(frame);
- page->fr = 0x0;
- }
-}
-
-void init_paging() {
- // Setup frame allocation
- nframes = PHYSICAL_MEM_SIZE / FRAME_SIZE;
- frame_allocations = (uint32_t*)kmalloc(nframes/FRAME_ALLOCATIONS_SECTION_SIZE);
- memset(frame_allocations, 0, nframes/FRAME_ALLOCATIONS_SECTION_SIZE);
-
- // Setup page directory
- kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
- memset(kernel_directory, 0, sizeof(page_directory_t));
- current_directory = kernel_directory;
-
- // Map heap pages
- for(uint32_t i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += FRAME_SIZE)
- get_page(i, 1, kernel_directory);
-
- // Setup identity map
- for(uint32_t i = 0; i < placement_addr + FRAME_SIZE; i += FRAME_SIZE)
- alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
-
- // Allocate heap pages
- for(uint32_t i = KHEAP_START; i < KHEAP_START+KHEAP_INITIAL_SIZE; i += FRAME_SIZE)
- alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
-
- // Register a new ISR to listen to IRQ 14
- register_interrupt_handler(14, page_fault);
- enable_paging(kernel_directory);
- kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
-}
-
-void enable_paging(page_directory_t *dir) {
- current_directory = dir;
- asm volatile("mov %0, %%cr3" :: "r"(&dir->page_tables_physical));
- uint32_t cr0;
- asm volatile("mov %%cr0, %0" : "=r"(cr0));
- cr0 |= 0x80000000; // Correct code to enable paging
- asm volatile("mov %0, %%cr0" :: "r"(cr0));
-}
-
-page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir) {
- address /= 0x1000; // turn address into an index
- uint32_t table_idx = address / 1024; // Find page that contains the address
- if(dir->page_tables_virtual[table_idx])
- return &dir->page_tables_virtual[table_idx]->pages[address%1024];
- else if(make) {
- uint32_t tmp;
- dir->page_tables_virtual[table_idx] = (page_table_t*)kmalloc_ap(sizeof(page_table_t), &tmp);
- memset(dir->page_tables_virtual[table_idx], 0, 0x1000);
- dir->page_tables_physical[table_idx] = tmp | 0x7;
- return &dir->page_tables_virtual[table_idx]->pages[address%1024];
- } else
- return 0;
-}
-
-void page_fault(registers_t regs) {
- // Handle a page fault
- uint32_t faulting_addr;
- asm volatile("mov %%cr2, %0" : "=r" (faulting_addr));
-
- // Gracefully print the error
- kprint((uint8_t*)"\nPage fault! ( ");
- if(!(regs.err_code & 0x1))
- kprint((uint8_t*)"Present ");
- if(regs.err_code & 0x2)
- kprint((uint8_t*)"Read-Only ");
- if(regs.err_code & 0x4)
- kprint((uint8_t*)"User-Mode ");
- if(regs.err_code & 0x8)
- kprint((uint8_t*)"Reserved");
- printf(") at %x\n", faulting_addr);
- PANIC("Page fault");
-}
+#include "paging.h"
+#include "../libc/string.h"
+#include "../libc/panic.h"
+#include "../libc/stdio.h"
+#include "../drivers/tty.h"
+
+// External definitions from kheap.c
+extern uint32_t placement_addr;
+extern heap_t *kheap;
+
+// Bitset of frames, used or free
+uint32_t *frame_allocations;
+uint32_t nframes; // Number of physical frames
+page_directory_t *kernel_directory = 0;
+page_directory_t *current_directory = 0;
+
+static void set_frame(uint32_t addr) {
+ uint32_t frame = FRAME(addr);
+ uint32_t frame_alloc_s = FRAME_SECTION(frame);
+ uint32_t frame_alloc_o = FRAME_OFFSET(frame);
+ frame_allocations[frame_alloc_s] |= (1 << frame_alloc_o);
+}
+
+static void clear_frame(uint32_t addr) {
+ uint32_t frame = FRAME(addr);
+ uint32_t frame_alloc_s = FRAME_SECTION(frame);
+ uint32_t frame_alloc_o = FRAME_OFFSET(frame);
+ frame_allocations[frame_alloc_s] &= ~(1 << frame_alloc_o);
+}
+
+static uint32_t first_frame() {
+ uint32_t nsections = nframes / FRAME_ALLOCATIONS_SECTION_SIZE;
+ for(uint32_t sec = 0; sec < nsections; sec++)
+ if(frame_allocations[sec] != USED_FRAME_SECTION)
+ for(uint32_t idx = 0; idx < FRAME_ALLOCATIONS_SECTION_SIZE; idx++)
+ if(!(frame_allocations[sec] & (0x1 << idx)))
+ return (sec*FRAME_ALLOCATIONS_SECTION_SIZE) + idx;
+ return nsections * FRAME_ALLOCATIONS_SECTION_SIZE;
+}
+
+void alloc_frame(page_t *page, int32_t is_super, int32_t is_write) {
+ if(page->fr != 0)
+ return;
+ else {
+ uint32_t fframe = first_frame();
+ if(fframe == (uint32_t)-1) {
+ PANIC("No free frames availables!");
+ } else {
+ // Set free frames to the page
+ page->pr = PAGE_PRESENT;
+ page->rw = (is_write) ? PAGE_READ_WRITE : PAGE_READ_ONLY;
+ page->us = (is_super) ? PAGE_SUPERVISOR : PAGE_USER;
+ page->fr = fframe;
+ // Set new frames as used
+ uint32_t physical_addr = fframe * FRAME_SIZE;
+ set_frame(physical_addr);
+ }
+ }
+}
+
+void free_frame(page_t *page) {
+ uint32_t frame;
+ if(!(frame=page->fr))
+ return; // page doesn't have a frame in first place
+ else {
+ clear_frame(frame);
+ page->fr = 0x0;
+ }
+}
+
+void init_paging() {
+ // Setup frame allocation
+ nframes = PHYSICAL_MEM_SIZE / FRAME_SIZE;
+ frame_allocations = (uint32_t*)kmalloc(nframes/FRAME_ALLOCATIONS_SECTION_SIZE);
+ memset(frame_allocations, 0, nframes/FRAME_ALLOCATIONS_SECTION_SIZE);
+
+ // Setup page directory
+ kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
+ memset(kernel_directory, 0, sizeof(page_directory_t));
+ current_directory = kernel_directory;
+
+ // Map heap pages
+ for(uint32_t i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += FRAME_SIZE)
+ get_page(i, 1, kernel_directory);
+
+ // Setup identity map
+ for(uint32_t i = 0; i < placement_addr + FRAME_SIZE; i += FRAME_SIZE)
+ alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
+
+ // Allocate heap pages
+ for(uint32_t i = KHEAP_START; i < KHEAP_START+KHEAP_INITIAL_SIZE; i += FRAME_SIZE)
+ alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
+
+ // Register a new ISR to listen to IRQ 14
+ register_interrupt_handler(14, page_fault);
+ enable_paging(kernel_directory);
+ kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
+}
+
+void enable_paging(page_directory_t *dir) {
+ current_directory = dir;
+ asm volatile("mov %0, %%cr3" :: "r"(&dir->page_tables_physical));
+ uint32_t cr0;
+ asm volatile("mov %%cr0, %0" : "=r"(cr0));
+ cr0 |= 0x80000000; // Correct code to enable paging
+ asm volatile("mov %0, %%cr0" :: "r"(cr0));
+}
+
+page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir) {
+ address /= 0x1000; // turn address into an index
+ uint32_t table_idx = address / 1024; // Find page that contains the address
+ if(dir->page_tables_virtual[table_idx])
+ return &dir->page_tables_virtual[table_idx]->pages[address%1024];
+ else if(make) {
+ uint32_t tmp;
+ dir->page_tables_virtual[table_idx] = (page_table_t*)kmalloc_ap(sizeof(page_table_t), &tmp);
+ memset(dir->page_tables_virtual[table_idx], 0, 0x1000);
+ dir->page_tables_physical[table_idx] = tmp | 0x7;
+ return &dir->page_tables_virtual[table_idx]->pages[address%1024];
+ } else
+ return 0;
+}
+
+void page_fault(registers_t regs) {
+ // Handle a page fault
+ uint32_t faulting_addr;
+ asm volatile("mov %%cr2, %0" : "=r" (faulting_addr));
+
+ // Gracefully print the error
+ kprint((uint8_t*)"\nPage fault! ( ");
+ if(!(regs.err_code & 0x1))
+ kprint((uint8_t*)"Present ");
+ if(regs.err_code & 0x2)
+ kprint((uint8_t*)"Read-Only ");
+ if(regs.err_code & 0x4)
+ kprint((uint8_t*)"User-Mode ");
+ if(regs.err_code & 0x8)
+ kprint((uint8_t*)"Reserved");
+ printf(") at %x\n", faulting_addr);
+ PANIC("Page fault");
+}
diff --git a/kernel/mem/paging.h b/kernel/mem/paging.h
index ebe616e..cab5e14 100644
--- a/kernel/mem/paging.h
+++ b/kernel/mem/paging.h
@@ -1,81 +1,81 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef PAGING_H
-#define PAGING_H
-
-#include
-#include "../drivers/isr.h"
-#include "kheap.h"
-
-#define FRAME_SIZE 4096
-#define PAGE_TABLE_SIZE 1024
-#define PAGE_DIRECTORY_SIZE 1024
-#define PAGE_NOT_PRESENT 0
-#define PAGE_PRESENT 1
-#define PAGE_READ_ONLY 0
-#define PAGE_READ_WRITE 1
-#define PAGE_USER 0
-#define PAGE_SUPERVISOR 0
-#define PAGE_SIZE_4KB 0
-#define PAGE_SIZE_4MB 1
-// Frames macros
-#define FRAME_ALLOCATIONS_SECTION_SIZE 32
-#define USED_FRAME_SECTION 0xFFFFFFFF
-#define FREE_FRAME_SECTION 0x00000000
-
-#define FRAME(addr) (addr/FRAME_SIZE)
-#define FRAME_SECTION(frame) (frame/FRAME_ALLOCATIONS_SECTION_SIZE)
-#define FRAME_OFFSET(frame) (frame%FRAME_ALLOCATIONS_SECTION_SIZE)
-
-// Set physical memory to 15 MiB
-#define PHYSICAL_MEM_SIZE 0x10000000
-
-struct page { // Single page structure, from intel's developer manual
- uint8_t pr : 1; // Present: 1 to map 4KB page
- uint8_t rw : 1; // Read/Write mode
- uint8_t us : 1; // if 0, user mode access aren't allowed to the page
- uint8_t pw : 1; // Page-level write through
- uint8_t pc : 1; // Page-level cache disable
- uint8_t ac : 1; // 1 if we have accessed 4kb page
- uint8_t di : 1; // 1 if page has been written(dirty)
- uint8_t pa : 1; // Unused bit
- uint8_t gl : 1; // 1 if page is global
- uint8_t ig : 3; // Unused bit
- uint32_t fr: 20; // Physical address of frame
-} __attribute__((packed));
-typedef struct page page_t;
-
-typedef struct page_table {
- page_t pages[PAGE_TABLE_SIZE];
-} page_table_t;
-
-/* Holds 2 arrays for each page directory
- * one holds the physical address, while
- * the other one holds the virtual address
- * (to write/read to it) */
-typedef struct page_directory {
- page_table_t *page_tables_virtual[PAGE_DIRECTORY_SIZE];
- uint32_t page_tables_physical[PAGE_DIRECTORY_SIZE];
-} page_directory_t;
-
-// Setup environment, page directories and enable paging
-void init_paging();
-// Perform the "enable-paging" operation to the right register
-void enable_paging(page_directory_t *dir);
-// Retrieve a pointer from the given page
-page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir);
-// Identity map(phys = virtual addr) to access it as if paging wasn't enabled
-void identity_map();
-// Delete a frame
-void free_frame(page_t *page);
-// Allocate a new frame
-void alloc_frame(page_t *page, int32_t is_super, int32_t is_write);
-// Page faults handler(ISR recorder)
-void page_fault(registers_t regs);
-
-#endif
+/*****************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/vulcanos *
+ *****************************************/
+#ifndef PAGING_H
+#define PAGING_H
+
+#include
+#include "../drivers/isr.h"
+#include "kheap.h"
+
+#define FRAME_SIZE 4096
+#define PAGE_TABLE_SIZE 1024
+#define PAGE_DIRECTORY_SIZE 1024
+#define PAGE_NOT_PRESENT 0
+#define PAGE_PRESENT 1
+#define PAGE_READ_ONLY 0
+#define PAGE_READ_WRITE 1
+#define PAGE_USER 0
+#define PAGE_SUPERVISOR 0
+#define PAGE_SIZE_4KB 0
+#define PAGE_SIZE_4MB 1
+// Frames macros
+#define FRAME_ALLOCATIONS_SECTION_SIZE 32
+#define USED_FRAME_SECTION 0xFFFFFFFF
+#define FREE_FRAME_SECTION 0x00000000
+
+#define FRAME(addr) (addr/FRAME_SIZE)
+#define FRAME_SECTION(frame) (frame/FRAME_ALLOCATIONS_SECTION_SIZE)
+#define FRAME_OFFSET(frame) (frame%FRAME_ALLOCATIONS_SECTION_SIZE)
+
+// Set physical memory to 15 MiB
+#define PHYSICAL_MEM_SIZE 0x10000000
+
+struct page { // Single page structure, from intel's developer manual
+ uint8_t pr : 1; // Present: 1 to map 4KB page
+ uint8_t rw : 1; // Read/Write mode
+ uint8_t us : 1; // if 0, user mode access aren't allowed to the page
+ uint8_t pw : 1; // Page-level write through
+ uint8_t pc : 1; // Page-level cache disable
+ uint8_t ac : 1; // 1 if we have accessed 4kb page
+ uint8_t di : 1; // 1 if page has been written(dirty)
+ uint8_t pa : 1; // Unused bit
+ uint8_t gl : 1; // 1 if page is global
+ uint8_t ig : 3; // Unused bit
+ uint32_t fr: 20; // Physical address of frame
+} __attribute__((packed));
+typedef struct page page_t;
+
+typedef struct page_table {
+ page_t pages[PAGE_TABLE_SIZE];
+} page_table_t;
+
+/* Holds 2 arrays for each page directory
+ * one holds the physical address, while
+ * the other one holds the virtual address
+ * (to write/read to it) */
+typedef struct page_directory {
+ page_table_t *page_tables_virtual[PAGE_DIRECTORY_SIZE];
+ uint32_t page_tables_physical[PAGE_DIRECTORY_SIZE];
+} page_directory_t;
+
+// Setup environment, page directories and enable paging
+void init_paging();
+// Perform the "enable-paging" operation to the right register
+void enable_paging(page_directory_t *dir);
+// Retrieve a pointer from the given page
+page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir);
+// Identity map(phys = virtual addr) to access it as if paging wasn't enabled
+void identity_map();
+// Delete a frame
+void free_frame(page_t *page);
+// Allocate a new frame
+void alloc_frame(page_t *page, int32_t is_super, int32_t is_write);
+// Page faults handler(ISR recorder)
+void page_fault(registers_t regs);
+
+#endif
diff --git a/kernel/userspace/Makefile b/kernel/userspace/Makefile
index bf4f717..fb310a7 100644
--- a/kernel/userspace/Makefile
+++ b/kernel/userspace/Makefile
@@ -1,10 +1,10 @@
-OBJS = shell.o fetch.o
-VER := $(shell git rev-parse --short HEAD)
-
-CC = i686-elf-gcc # cross-compiler
-CFLAGS = -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -DVULCAN_VERSION=$(VER) -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
-
-all:${OBJS}
-
-%.o: %.c
- $(CC) $(CFLAGS) $< -o $@
+OBJS = shell.o fetch.o
+VER := $(shell git rev-parse --short HEAD)
+
+CC = i686-elf-gcc # cross-compiler
+CFLAGS = -DDEFAULT_USER=root -DDEFAULT_HOSTNAME=vulcan -DVULCAN_VERSION=$(VER) -m32 -fno-stack-protector -ffreestanding -Wall -Wextra -Werror -g -c
+
+all:${OBJS}
+
+%.o: %.c
+ $(CC) $(CFLAGS) $< -o $@
diff --git a/kernel/userspace/fetch.c b/kernel/userspace/fetch.c
index e461b6b..44254df 100644
--- a/kernel/userspace/fetch.c
+++ b/kernel/userspace/fetch.c
@@ -1,75 +1,75 @@
-#include "fetch.h"
-#include "../libc/stdio.h"
-#include "../libc/string.h"
-#include "../libc/time.h"
-#include "../drivers/tty.h"
-#include "../drivers/cpuid.h"
-#define STRINGIZE(x) #x
-#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
-
-static void get_date();
-static void get_cpuid();
-static void get_version();
-
-void system_fetcher() {
- uint8_t user[64], hostname[64];
-#ifdef DEFAULT_USER
- strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER));
-#else
- #error "-DDEFAULT_USER flag not set"
-#endif
-
-#ifdef DEFAULT_HOSTNAME
- strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME));
-#else
- #error "-DDEFAULT_HOSTNAME flag not set"
-#endif
- // print first line
- printf_color("\n __ __ ___ ___ ", LIGHT_RED, BLACK);
- printf_color((char*)user, LIGHT_CYAN, BLACK);
- printf_color("@", LIGHT_RED, BLACK);
- printf_color((char*)hostname, LIGHT_CYAN, BLACK);
- // print second line
- printf_color("\n \\ \\ / / / _ \\/ __| ", LIGHT_RED, BLACK);
- printf_color("-----------", LIGHT_RED, BLACK);
- // print third line
- printf_color("\n \\ V / | (_) \\__ \\ ", LIGHT_RED, BLACK);
- printf_color("Date: ", LIGHT_CYAN, BLACK);
- get_date();
- // print fourth line
- printf_color("\n \\_/ \\___/|___/ ", LIGHT_RED, BLACK);
- get_cpuid();
- // print VulcanOS version
- get_version();
-}
-
-// Date format is D/M/YY
-void get_date() {
- printf("%d", get_time(TIME_R_DAY)); // Day
- printf_color("/", LIGHT_BLUE, BLACK);
-
- printf("%d", get_time(TIME_R_MONTH)); // Month
- printf_color("/", LIGHT_BLUE, BLACK);
-
- printf("%d", get_time(TIME_R_YEAR)); // Year
-}
-
-
-void get_cpuid() {
- printf_color("CPU type: ", LIGHT_CYAN, BLACK);
- printf("%s", (char*)get_cpu_type()); // Print CPU type
- printf("%s%s%c", " (", (char*)get_cpu_family(), ')');
-}
-
-
-void get_version() {
- uint8_t version[64];
-#ifdef VULCAN_VERSION
- strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION));
-#else
- #error "-DVULCAN_VERSION flag not set"
-#endif
-
- printf_color("\n\t\t\t\t\t Version: ", LIGHT_CYAN, BLACK);
- printf_color((char*)version, LIGHT_GREEN, BLACK);
-}
+#include "fetch.h"
+#include "../libc/stdio.h"
+#include "../libc/string.h"
+#include "../libc/time.h"
+#include "../drivers/tty.h"
+#include "../drivers/cpuid.h"
+#define STRINGIZE(x) #x
+#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
+
+static void get_date();
+static void get_cpuid();
+static void get_version();
+
+void system_fetcher() {
+ uint8_t user[64], hostname[64];
+#ifdef DEFAULT_USER
+ strcpy(user, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_USER));
+#else
+ #error "-DDEFAULT_USER flag not set"
+#endif
+
+#ifdef DEFAULT_HOSTNAME
+ strcpy(hostname, (uint8_t*)STRINGIZE_VALUE_OF(DEFAULT_HOSTNAME));
+#else
+ #error "-DDEFAULT_HOSTNAME flag not set"
+#endif
+ // print first line
+ printf_color("\n __ __ ___ ___ ", LIGHT_RED, BLACK);
+ printf_color((char*)user, LIGHT_CYAN, BLACK);
+ printf_color("@", LIGHT_RED, BLACK);
+ printf_color((char*)hostname, LIGHT_CYAN, BLACK);
+ // print second line
+ printf_color("\n \\ \\ / / / _ \\/ __| ", LIGHT_RED, BLACK);
+ printf_color("-----------", LIGHT_RED, BLACK);
+ // print third line
+ printf_color("\n \\ V / | (_) \\__ \\ ", LIGHT_RED, BLACK);
+ printf_color("Date: ", LIGHT_CYAN, BLACK);
+ get_date();
+ // print fourth line
+ printf_color("\n \\_/ \\___/|___/ ", LIGHT_RED, BLACK);
+ get_cpuid();
+ // print VulcanOS version
+ get_version();
+}
+
+// Date format is D/M/YY
+void get_date() {
+ printf("%d", get_time(TIME_R_DAY)); // Day
+ printf_color("/", LIGHT_BLUE, BLACK);
+
+ printf("%d", get_time(TIME_R_MONTH)); // Month
+ printf_color("/", LIGHT_BLUE, BLACK);
+
+ printf("%d", get_time(TIME_R_YEAR)); // Year
+}
+
+
+void get_cpuid() {
+ printf_color("CPU type: ", LIGHT_CYAN, BLACK);
+ printf("%s", (char*)get_cpu_type()); // Print CPU type
+ printf("%s%s%c", " (", (char*)get_cpu_family(), ')');
+}
+
+
+void get_version() {
+ uint8_t version[64];
+#ifdef VULCAN_VERSION
+ strcpy(version, (uint8_t*)STRINGIZE_VALUE_OF(VULCAN_VERSION));
+#else
+ #error "-DVULCAN_VERSION flag not set"
+#endif
+
+ printf_color("\n\t\t\t\t\t Version: ", LIGHT_CYAN, BLACK);
+ printf_color((char*)version, LIGHT_GREEN, BLACK);
+}
diff --git a/kernel/userspace/fetch.h b/kernel/userspace/fetch.h
index 39f2103..1fd0880 100644
--- a/kernel/userspace/fetch.h
+++ b/kernel/userspace/fetch.h
@@ -1,15 +1,15 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef FETCH_H
-#define FETCH_H
-
-#include
-
-void system_fetcher();
-
-#endif
+/**************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/iceOS *
+ ***************************************/
+#ifndef FETCH_H
+#define FETCH_H
+
+#include
+
+void system_fetcher();
+
+#endif
diff --git a/kernel/userspace/shell.c b/kernel/userspace/shell.c
index 73cde48..f01234f 100644
--- a/kernel/userspace/shell.c
+++ b/kernel/userspace/shell.c
@@ -1,122 +1,122 @@
-#include "shell.h"
-#include "fetch.h"
-#include "../libc/string.h"
-#include "../libc/stdio.h"
-#include "../drivers/tty.h"
-#include "../drivers/ports.h"
-#include "../drivers/timer.h"
-
-void helper() {
- puts("\nList of available commands:\n"
- "\nhelp - Print this helper"
- "\nint - Test some interrupts"
- "\nbanner - Show banner"
- "\nclear, cls - Clear the screen"
- "\nregs - Prints register dump"
- "\ntimer - Prints timer tick"
- "\nabout - About this kernel"
- "\nreboot - Reboot the system"
- );
-}
-
-void test_interrupts() {
- // Testing some interrupts
- asm("int $0"); // Division by zero
- asm("int $4"); // Stack overflow
- asm("int $1"); // Page fault
-}
-
-void about() {
- printf_color("\n====== IceOS v0.0.1 (c) 2019 Marco 'icebit' Cetica ======\n\n",
- LIGHT_CYAN, BLACK);
- printf_color(
- "iceOS is a x86 monolithic kernel written in C from scratch.\n"
- "This project doesn't aim to be a fully functional operating system\n"
- "with tons of drivers and graphical applications,\nit's just a learning tool "
- "to teach myself concepts like\nOperating Systems, Computer Architecture and Digital Electronics.\n"
- "\n\n"
- "iceOS comes with the following features:\n"
- "- Bare metal booting;\n"
- "- VGA driver;\n"
- "- Interrupts implementation;\n"
- "- PIC & PIT implementation;\n"
- "- PS2 driver;\n"
- "- Support for x86 architecture;\n"
- "- GRUB as bootloader;\n",
- LIGHT_GREEN, BLACK);
-}
-
-void register_dump() {
- register uint32_t eax_v asm("eax");
- register uint32_t ebx_v asm("ebx");
- register uint32_t ecx_v asm("ecx");
- register uint32_t edx_v asm("edx");
- register uint32_t esx_v asm("esi");
- register uint32_t edi_v asm("edi");
- register uint32_t ebp_v asm("ebp");
- register uint32_t esp_v asm("esp");
-
- printf_color("\n===================================\n"
- " BEGIN 32 BITS CPU REGISTER DUMP \n"
- "===================================\n",
- LIGHT_BROWN, BLACK);
- printf(" EAX: %x\n"
- " EBX: %x\n"
- " ECX: %x\n"
- " EDX: %x\n"
- " ESX: %x\n"
- " EDI: %x\n"
- " EBP: %x\n"
- " ESP: %x\n",
- eax_v, ebx_v, ecx_v, edx_v, esx_v, edi_v, ebp_v, esp_v);
- printf_color("\n==================================\n"
- " END 32 BITS CPU REGISTER DUMP \n"
- "==================================\n",
- LIGHT_BROWN, BLACK);
-}
-
-void timer_dump() {
- uint8_t buf[8];
- uitoa(tick, buf, 10);
-
- printf_color("\nTicks since boot: ",
- LIGHT_GREEN, BLACK);
- printf_color((const char*)buf,
- LIGHT_CYAN, BLACK);
-}
-void reboot() {
- uint8_t tmp;
- asm("cli"); // First disable all interrupts
-
- // Clear keyboard buffers
- do {
- tmp = inb(0x64); // Keyboard interface
- if(check_flag(tmp, 0) != 0)
- inb(0x60); // Clear keyboard data
- } while(check_flag(tmp, 1) != 0);
-
- outb(0x64, 0xFE); // Reset the CPU
-}
-
-void processCommand(uint8_t *cmd) {
- if(strcmp(cmd, (uint8_t*)"help") == 0)
- helper();
- else if(strcmp(cmd, (uint8_t*)"int") == 0)
- test_interrupts();
- else if(strcmp(cmd, (uint8_t*)"clear") == 0 || strcmp(cmd, (uint8_t*)"cls") == 0)
- clear_prompt();
- else if(strcmp(cmd, (uint8_t*)"about") == 0)
- about();
- else if(strcmp(cmd, (uint8_t*)"regs") == 0)
- register_dump();
- else if(strcmp(cmd, (uint8_t*)"timer") == 0)
- timer_dump();
- else if(strcmp(cmd, (uint8_t*)"fetch") == 0)
- system_fetcher();
- else if(strcmp(cmd, (uint8_t*)"reboot") == 0)
- reboot();
- else if(strcmp(cmd, (uint8_t*)"") == 0)
- puts("");
- else
- puts("\nCommand not found!");
-}
+#include "shell.h"
+#include "fetch.h"
+#include "../libc/string.h"
+#include "../libc/stdio.h"
+#include "../drivers/tty.h"
+#include "../drivers/ports.h"
+#include "../drivers/timer.h"
+
+void helper() {
+ puts("\nList of available commands:\n"
+ "\nhelp - Print this helper"
+ "\nint - Test some interrupts"
+ "\nbanner - Show banner"
+ "\nclear, cls - Clear the screen"
+ "\nregs - Prints register dump"
+ "\ntimer - Prints timer tick"
+ "\nabout - About this kernel"
+ "\nreboot - Reboot the system"
+ );
+}
+
+void test_interrupts() {
+ // Testing some interrupts
+ asm("int $0"); // Division by zero
+ asm("int $4"); // Stack overflow
+ asm("int $1"); // Page fault
+}
+
+void about() {
+ printf_color("\n====== IceOS v0.0.1 (c) 2019 Marco 'icebit' Cetica ======\n\n",
+ LIGHT_CYAN, BLACK);
+ printf_color(
+ "iceOS is a x86 monolithic kernel written in C from scratch.\n"
+ "This project doesn't aim to be a fully functional operating system\n"
+ "with tons of drivers and graphical applications,\nit's just a learning tool "
+ "to teach myself concepts like\nOperating Systems, Computer Architecture and Digital Electronics.\n"
+ "\n\n"
+ "iceOS comes with the following features:\n"
+ "- Bare metal booting;\n"
+ "- VGA driver;\n"
+ "- Interrupts implementation;\n"
+ "- PIC & PIT implementation;\n"
+ "- PS2 driver;\n"
+ "- Support for x86 architecture;\n"
+ "- GRUB as bootloader;\n",
+ LIGHT_GREEN, BLACK);
+}
+
+void register_dump() {
+ register uint32_t eax_v asm("eax");
+ register uint32_t ebx_v asm("ebx");
+ register uint32_t ecx_v asm("ecx");
+ register uint32_t edx_v asm("edx");
+ register uint32_t esx_v asm("esi");
+ register uint32_t edi_v asm("edi");
+ register uint32_t ebp_v asm("ebp");
+ register uint32_t esp_v asm("esp");
+
+ printf_color("\n===================================\n"
+ " BEGIN 32 BITS CPU REGISTER DUMP \n"
+ "===================================\n",
+ LIGHT_BROWN, BLACK);
+ printf(" EAX: %x\n"
+ " EBX: %x\n"
+ " ECX: %x\n"
+ " EDX: %x\n"
+ " ESX: %x\n"
+ " EDI: %x\n"
+ " EBP: %x\n"
+ " ESP: %x\n",
+ eax_v, ebx_v, ecx_v, edx_v, esx_v, edi_v, ebp_v, esp_v);
+ printf_color("\n==================================\n"
+ " END 32 BITS CPU REGISTER DUMP \n"
+ "==================================\n",
+ LIGHT_BROWN, BLACK);
+}
+
+void timer_dump() {
+ uint8_t buf[8];
+ uitoa(tick, buf, 10);
+
+ printf_color("\nTicks since boot: ",
+ LIGHT_GREEN, BLACK);
+ printf_color((const char*)buf,
+ LIGHT_CYAN, BLACK);
+}
+void reboot() {
+ uint8_t tmp;
+ asm("cli"); // First disable all interrupts
+
+ // Clear keyboard buffers
+ do {
+ tmp = inb(0x64); // Keyboard interface
+ if(check_flag(tmp, 0) != 0)
+ inb(0x60); // Clear keyboard data
+ } while(check_flag(tmp, 1) != 0);
+
+ outb(0x64, 0xFE); // Reset the CPU
+}
+
+void processCommand(uint8_t *cmd) {
+ if(strcmp(cmd, (uint8_t*)"help") == 0)
+ helper();
+ else if(strcmp(cmd, (uint8_t*)"int") == 0)
+ test_interrupts();
+ else if(strcmp(cmd, (uint8_t*)"clear") == 0 || strcmp(cmd, (uint8_t*)"cls") == 0)
+ clear_prompt();
+ else if(strcmp(cmd, (uint8_t*)"about") == 0)
+ about();
+ else if(strcmp(cmd, (uint8_t*)"regs") == 0)
+ register_dump();
+ else if(strcmp(cmd, (uint8_t*)"timer") == 0)
+ timer_dump();
+ else if(strcmp(cmd, (uint8_t*)"fetch") == 0)
+ system_fetcher();
+ else if(strcmp(cmd, (uint8_t*)"reboot") == 0)
+ reboot();
+ else if(strcmp(cmd, (uint8_t*)"") == 0)
+ puts("");
+ else
+ puts("\nCommand not found!");
+}
diff --git a/kernel/userspace/shell.h b/kernel/userspace/shell.h
index a69cf0c..4581295 100644
--- a/kernel/userspace/shell.h
+++ b/kernel/userspace/shell.h
@@ -1,19 +1,19 @@
-/**************************************
- * VulcanOS Kernel *
- * Developed by Marco 'icebit' Cetica *
- * (c) 2019-2021 *
- * Released under GPLv3 *
- * https://github.com/ice-bit/iceOS *
- ***************************************/
-#ifndef _SHELL_H_
-#define _SHELL_H_
-
-#include
-
-#define bit(n) (1 << (n))
-#define check_flag(flags, n) ((flags) & bit(n))
-
-void helper();
-void processCommand(uint8_t *cmd);
-
-#endif
+/**************************************
+ * VulcanOS Kernel *
+ * Developed by Marco 'icebit' Cetica *
+ * (c) 2019-2021 *
+ * Released under GPLv3 *
+ * https://github.com/ice-bit/iceOS *
+ ***************************************/
+#ifndef _SHELL_H_
+#define _SHELL_H_
+
+#include
+
+#define bit(n) (1 << (n))
+#define check_flag(flags, n) ((flags) & bit(n))
+
+void helper();
+void processCommand(uint8_t *cmd);
+
+#endif
diff --git a/link.ld b/link.ld
index 201e2dc..5af9144 100644
--- a/link.ld
+++ b/link.ld
@@ -1,28 +1,27 @@
-ENTRY(kernel_loader)
-SECTIONS
-{
-
- .text 0x100000 :
- {
- code = .; _code = .; __code = .;
- *(.text)
- . = ALIGN(4096);
- }
-
- .data :
- {
- data = .; _data = .; __data = .;
- *(.data)
- *(.rodata)
- . = ALIGN(4096);
- }
-
- .bss :
- {
- bss = .; _bss = .; __bss = .;
- *(.bss)
- . = ALIGN(4096);
- }
-
- end = .; _end = .; __end = .;
-}
+ENTRY(kernel_loader)
+
+SECTIONS
+{
+ . = 1M;
+
+ .boot :
+ {
+ KEEP(*(.multiboot_header))
+ . = ALIGN(4096);
+ }
+
+ .text :
+ {
+ *(.data)
+ *(.rodata)
+ . = ALIGN(4096);
+ }
+
+ .bss :
+ {
+ *(.bss)
+ . = ALIGN(4096);
+ }
+
+ end = .; _end = .; __end = .;
+}
\ No newline at end of file