From: Rhett Date: Sun, 1 Jul 2012 23:39:35 +0000 (-0700) Subject: Moved from Google Code to github X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=35f72ac032922022d09bca1c35c79b169ff6666e;p=arcanos.git Moved from Google Code to github --- diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..26ff21e --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,17 @@ +A considerable portion of the initial check-in of ArcanOS is based directly +off the operating systems coursework labs of Dr. Lorenzo Alvisi +(http://userweb.cs.utexas.edu/~lorenzo/), and I owe him a debt of gratitude for +producing and distributing material to help bridge the gap between a simple +"Hello World" bootloader and a functioning kernel. I believe Dr. Alvisi has +released his code under an MIT license, which is GPL compatible. + +Some materials from the initial drop contain header files documented as under +a BSD license which may not be fully GPL-compatible. Since the conflicting +clause under this license is related to advertising of products, I believe +that a hobby project such as ArcanOS will not produce any conflict. I am +endeavoring to locate more GPL-compatible source for these files. + +Concerned parties should contact me at roadriverrail@gmail.com + +Unless explicity specified otherwise, materials in this project are copyright +J. Rhett Aultman (c) 2010 and are released under the terms of the GPL v3. diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..52150b7 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,85 @@ +# +# This makefile system follows the structuring conventions +# recommended by Peter Miller in his excellent paper: +# +# Recursive Make Considered Harmful +# http://aegis.sourceforge.net/auug97.pdf +# +OBJDIR := obj + +TOP = . + +# Cross-compiler jos toolchain +# +# This Makefile will automatically use the cross-compiler toolchain +# installed as 'i386-jos-elf-*', if one exists. If the host tools ('gcc', +# 'objdump', and so forth) compile for a 32-bit x86 ELF target, that will +# be detected as well. If you have the right compiler toolchain installed +# using a different name, set GCCPREFIX explicitly in conf/env.mk + +# try to infer the correct GCCPREFIX +ifndef GCCPREFIX +GCCPREFIX := $(shell if objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \ + then echo ''; \ + else echo "***" 1>&2; \ + echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \ + echo "*** Is the directory with i386-*-elf-gcc in your PATH?" 1>&2; \ + echo "***" 1>&2; exit 1; fi) +endif + +CC := $(GCCPREFIX)gcc -pipe +GCC_LIB := $(shell $(CC) -print-libgcc-file-name) +AS := $(GCCPREFIX)as +AR := $(GCCPREFIX)ar +LD := $(GCCPREFIX)ld +OBJCOPY := $(GCCPREFIX)objcopy +OBJDUMP := $(GCCPREFIX)objdump +NM := $(GCCPREFIX)nm + +# Native commands +NCC := gcc $(CC_VER) -pipe +TAR := gtar +PERL := perl + +# Compiler flags +# -fno-builtin is required to avoid refs to undefined functions in the kernel. +# Only optimize to -O1 to discourage inlining, which complicates backtraces. +CFLAGS := $(CFLAGS) $(DEFS) $(LABDEFS) -O -fno-builtin -I$(TOP) -MD -Wall -Wno-format -Wno-unused -Werror -gstabs -fno-stack-protector + +# Lists that the */Makefrag makefile fragments will add to +OBJDIRS := + +# Make sure that 'all' is the first target +all: + +# Eliminate default suffix rules +.SUFFIXES: + +# Delete target files if there is an error (or make is interrupted) +.DELETE_ON_ERROR: + +# make it so that no intermediate .o files are ever deleted +.PRECIOUS: %.o $(OBJDIR)/boot/%.o $(OBJDIR)/kern/%.o \ + $(OBJDIR)/lib/%.o $(OBJDIR)/fs/%.o $(OBJDIR)/user/%.o + +KERN_CFLAGS := $(CFLAGS) -DARCANOS_KERNEL -gstabs +USER_CFLAGS := $(CFLAGS) -DARCANOS_USER -gstabs + + + + +# Include Makefrags for subdirectories +include kern/Makefrag + + +IMAGES = $(OBJDIR)/kern/bochs.img + +# For deleting the build +clean: + rm -rf $(OBJDIR) + +always: + @: + +.PHONY: all always \ + clean diff --git a/README.md b/README.md deleted file mode 100644 index be3ac9a..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -arcanos -======= - -A hobby/vanity operating system \ No newline at end of file diff --git a/arcanos.kdev4 b/arcanos.kdev4 new file mode 100644 index 0000000..875be81 --- /dev/null +++ b/arcanos.kdev4 @@ -0,0 +1,3 @@ +[Project] +Manager=KDevCustomMakeManager +Name=arcanos diff --git a/boot/pad b/boot/pad new file mode 100644 index 0000000..7a3d28a Binary files /dev/null and b/boot/pad differ diff --git a/boot/post_pad b/boot/post_pad new file mode 100644 index 0000000..1ccbecf Binary files /dev/null and b/boot/post_pad differ diff --git a/boot/stage1 b/boot/stage1 new file mode 100644 index 0000000..b5ed85d Binary files /dev/null and b/boot/stage1 differ diff --git a/boot/stage2 b/boot/stage2 new file mode 100644 index 0000000..58a4819 Binary files /dev/null and b/boot/stage2 differ diff --git a/gpl-3.0.txt b/gpl-3.0.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/gpl-3.0.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/inc/COPYRIGHT b/inc/COPYRIGHT new file mode 100644 index 0000000..a2146cf --- /dev/null +++ b/inc/COPYRIGHT @@ -0,0 +1,121 @@ +The files in this directory are: + +elf.h, memlayout.h, mmu.h, and x86.h are: + + +/* + * Copyright (C) 1997 Massachusetts Institute of Technology + * + * This software is being provided by the copyright holders under the + * following license. By obtaining, using and/or copying this software, + * you agree that you have read, understood, and will comply with the + * following terms and conditions: + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose and without fee or royalty is + * hereby granted, provided that the full text of this NOTICE appears on + * ALL copies of the software and documentation or portions thereof, + * including modifications, that you make. + * + * THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, + * BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR + * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR + * THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY + * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT + * HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR + * DOCUMENTATION. + * + * The name and trademarks of copyright holders may NOT be used in + * advertising or publicity pertaining to the software without specific, + * written prior permission. Title to copyright in this software and any + * associated documentation will at all times remain with copyright + * holders. See the file AUTHORS which should have accompanied this software + * for a list of all copyright holders. + * + * This file may be derived from previously copyrighted software. This + * copyright applies only to those changes made by the copyright + * holders listed in the AUTHORS file. The rest of this file is covered by + * the copyright notices, if any, listed below. + */ + + +stdarg.h is: + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + */ + +types.h is: + +/*- + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.4 (Berkeley) 1/21/94 + */ + diff --git a/inc/console.h b/inc/console.h new file mode 100644 index 0000000..2b49ab7 --- /dev/null +++ b/inc/console.h @@ -0,0 +1,21 @@ +#include + +void blank_screen(); + +void buffer_to_screen(); + +void console_init(); + +void printchar(char c); + +void next_line(); + +void update_cursor(); +int8_t move_to (uint8_t x, uint8_t y); + + +void print_string_helper(char* string); + +void print_string(char* string); + +void print_line(char* string); diff --git a/inc/elf.h b/inc/elf.h new file mode 100644 index 0000000..66add42 --- /dev/null +++ b/inc/elf.h @@ -0,0 +1,65 @@ +#ifndef ARCANOS_INC_ELF_H +#define ARCANOS_INC_ELF_H + +#define ELF_MAGIC 0x464C457FU /* "\x7FELF" in little endian */ + +struct Elf { + uint32_t e_magic; // must equal ELF_MAGIC + uint8_t e_elf[12]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +}; + +struct Proghdr { + uint32_t p_type; + uint32_t p_offset; + uint32_t p_va; + uint32_t p_pa; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +}; + +struct Secthdr { + uint32_t sh_name; + uint32_t sh_type; + uint32_t sh_flags; + uint32_t sh_addr; + uint32_t sh_offset; + uint32_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint32_t sh_addralign; + uint32_t sh_entsize; +}; + +// Values for Proghdr::p_type +#define ELF_PROG_LOAD 1 + +// Flag bits for Proghdr::p_flags +#define ELF_PROG_FLAG_EXEC 1 +#define ELF_PROG_FLAG_WRITE 2 +#define ELF_PROG_FLAG_READ 4 + +// Values for Secthdr::sh_type +#define ELF_SHT_NULL 0 +#define ELF_SHT_PROGBITS 1 +#define ELF_SHT_SYMTAB 2 +#define ELF_SHT_STRTAB 3 + +// Values for Secthdr::sh_name +#define ELF_SHN_UNDEF 0 + +#endif /* !ARCANOS_INC_ELF_H */ diff --git a/inc/idt.h b/inc/idt.h new file mode 100644 index 0000000..8ce5c51 --- /dev/null +++ b/inc/idt.h @@ -0,0 +1,31 @@ +#include +#include + +typedef struct _IDTDescr{ + uint16_t offset_1; // offset bits 0..15 + uint16_t selector; // a code segment selector in GDT or LDT + uint8_t zero; // unused, set to 0 + uint8_t type_attr; // type and attributes, see below + uint16_t offset_2; // offset bits 16..31 +}__attribute__((__packed__)) IDTDescr; + +typedef struct _IDT{ + uint16_t limit; + uint32_t base; +}__attribute__((__packed__)) IDT; + +IDTDescr idt[256]; +IDT idt_struct; +IDT* idtp; +IDT* phys_idtp; + +#define UNUSED_TYPE_ATTR 0x00 +#define INTERRUPT_GATE_TYPE_ATTR 0x8E +#define TRAP_GATE_TYPE_ATTR 0x8F + +#define HIGH_OFFSET(x) ((x >> 16)) +#define LOW_OFFSET(x) ((x & 0x0000FFFF)) + +void reset_idt(); +void set_idt_entry(uint8_t number, void (*handler)(), uint16_t type); +void load_idt(); diff --git a/inc/info.h b/inc/info.h new file mode 100644 index 0000000..727d894 --- /dev/null +++ b/inc/info.h @@ -0,0 +1,8 @@ +#ifndef ARCANOS_INC_INFO_H +#define ARCANOS_INC_INFO_H + +#include + +#define ARCANOS_VERSION "PRE-MAGUS" + +#endif diff --git a/inc/memlayout.h b/inc/memlayout.h new file mode 100644 index 0000000..487a934 --- /dev/null +++ b/inc/memlayout.h @@ -0,0 +1,36 @@ +#ifndef ARCANOS_INC_MEMLAYOUT_H +#define ARCANOS_INC_MEMLAYOUT_H + +#ifndef __ASSEMBLER__ +#include +//#include +#include +#endif /* not __ASSEMBLER__ */ + +/* + * This file contains definitions for memory management in our OS, + * which are relevant to both the kernel and user-mode software. + */ + +// Global descriptor numbers +#define GD_KT 0x08 // kernel text +#define GD_KD 0x10 // kernel data +#define GD_UT 0x18 // user text +#define GD_UD 0x20 // user data +#define GD_TSS 0x28 // Task segment selector + +// All physical memory mapped at this address +#define KERNBASE 0xC0000000 + +#define INITIAL_PDE 0x09D000 + +// At IOPHYSMEM (640K) there is a 384K hole for I/O. From the kernel, +// IOPHYSMEM can be addressed at KERNBASE + IOPHYSMEM. The hole ends +// at physical address EXTPHYSMEM. +#define IOPHYSMEM 0x0A0000 +#define EXTPHYSMEM 0x100000 + +#define KSTACKTOP VPT +#define KSTKSIZE (8*PGSIZE) // size of a kernel stack + +#endif /* !ARCANOS_INC_MEMLAYOUT_H */ diff --git a/inc/memmgr.h b/inc/memmgr.h new file mode 100644 index 0000000..3690700 --- /dev/null +++ b/inc/memmgr.h @@ -0,0 +1,36 @@ +#ifndef __ARCANOS_KERN_MEMMGR_H__ +#define __ARCANOS_KERN_MEMMGR_H__ + +#include + +#define PAGE_PRESENT 0x1 +#define PAGE_RW 0x2 +#define PAGE_USER 0x4 + +#define PAGE_SIZE 4096 + +//4GB / 4kb page size / 1 bit per page +#define PHYS_MEM_MAP_SIZE 131072 + +//Bitmap of memory. +uint8_t phys_mem_map [PHYS_MEM_MAP_SIZE]; + +typedef struct _kmemdesc { + void* data_ptr; + unsigned int size; + struct _kmemdesc* next; +} kmemdesc; + +void init_paging(); + +void frame_allocator_init(multiboot_info_t* mbi, uint32_t kernel_base, uint32_t kernel_end); +void mark_frame(uint32_t base, uint8_t status); +void* get_frame(); +void* get_page(); +void memmgr_init(); +void* memmgr_allocate(unsigned int size); +void memmgr_free(void* ptr); + +void map_page(void* physaddr, void* virtualaddr, unsigned int flags); + +#endif diff --git a/inc/mmu.h b/inc/mmu.h new file mode 100644 index 0000000..62ae3c4 --- /dev/null +++ b/inc/mmu.h @@ -0,0 +1,259 @@ +#ifndef ARCANOS_INC_MMU_H +#define ARCANOS_INC_MMU_H + +/* + * This file contains definitions for the x86 memory management unit (MMU), + * including paging- and segmentation-related data structures and constants, + * the %cr0, %cr4, and %eflags registers, and traps. + */ + +/* + * + * Part 1. Paging data structures and constants. + * + */ + +#ifndef __ASSEMBLER__ + +typedef uint32_t pdentry; +typedef uint32_t ptentry; + +#endif + +// A linear address 'la' has a three-part structure as follows: +// +// +--------10------+-------10-------+---------12----------+ +// | Page Directory | Page Table | Offset within Page | +// | Index | Index | | +// +----------------+----------------+---------------------+ +// \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/ +// \----------- PPN(la) -----------/ +// +// The PDX, PTX, PGOFF, and PPN macros decompose linear addresses as shown. +// To construct a linear address la from PDX(la), PTX(la), and PGOFF(la), +// use PGADDR(PDX(la), PTX(la), PGOFF(la)). + +// page number field of address +#define PPN(la) (((uintptr_t) (la)) >> PTXSHIFT) +#define VPN(la) PPN(la) // used to index into vpt[] + +// page directory index +#define PDX(la) ((((uintptr_t) (la)) >> PDXSHIFT) & 0x3FF) +#define VPD(la) PDX(la) // used to index into vpd[] + +// page table index +#define PTX(la) ((((uintptr_t) (la)) >> PTXSHIFT) & 0x3FF) + +// offset in page +#define PGOFF(la) (((uintptr_t) (la)) & 0xFFF) + +// construct linear address from indexes and offset +#define PGADDR(d, t, o) ((void*) ((d) << PDXSHIFT | (t) << PTXSHIFT | (o))) + +// Page directory and page table constants. +#define NPDENTRIES 1024 // page directory entries per page directory +#define NPTENTRIES 1024 // page table entries per page table + +#define PGSIZE 4096 // bytes mapped by a page +#define PGSHIFT 12 // log2(PGSIZE) + +#define PTSIZE (PGSIZE*NPTENTRIES) // bytes mapped by a page directory entry +#define PTSHIFT 22 // log2(PTSIZE) + +#define PTXSHIFT 12 // offset of PTX in a linear address +#define PDXSHIFT 22 // offset of PDX in a linear address + +// Page table/directory entry flags. +#define PTE_P 0x001 // Present +#define PTE_W 0x002 // Writeable +#define PTE_U 0x004 // User +#define PTE_PWT 0x008 // Write-Through +#define PTE_PCD 0x010 // Cache-Disable +#define PTE_A 0x020 // Accessed +#define PTE_D 0x040 // Dirty +#define PTE_PS 0x080 // Page Size +#define PTE_MBZ 0x180 // Bits must be zero + +// The PTE_AVAIL bits aren't used by the kernel or interpreted by the +// hardware, so user processes are allowed to set them arbitrarily. +#define PTE_AVAIL 0xE00 // Available for software use + +// Only flags in PTE_USER may be used in system calls. +#define PTE_USER (PTE_AVAIL | PTE_P | PTE_W | PTE_U) + +// address in page table entry +#define PTE_ADDR(pte) ((physaddr_t) (pte) & ~0xFFF) + +// Control Register flags +#define CR0_PE 0x00000001 // Protection Enable +#define CR0_MP 0x00000002 // Monitor coProcessor +#define CR0_EM 0x00000004 // Emulation +#define CR0_TS 0x00000008 // Task Switched +#define CR0_ET 0x00000010 // Extension Type +#define CR0_NE 0x00000020 // Numeric Errror +#define CR0_WP 0x00010000 // Write Protect +#define CR0_AM 0x00040000 // Alignment Mask +#define CR0_NW 0x20000000 // Not Writethrough +#define CR0_CD 0x40000000 // Cache Disable +#define CR0_PG 0x80000000 // Paging + +#define CR4_PCE 0x00000100 // Performance counter enable +#define CR4_MCE 0x00000040 // Machine Check Enable +#define CR4_PSE 0x00000010 // Page Size Extensions +#define CR4_DE 0x00000008 // Debugging Extensions +#define CR4_TSD 0x00000004 // Time Stamp Disable +#define CR4_PVI 0x00000002 // Protected-Mode Virtual Interrupts +#define CR4_VME 0x00000001 // V86 Mode Extensions + +// Eflags register +#define FL_CF 0x00000001 // Carry Flag +#define FL_PF 0x00000004 // Parity Flag +#define FL_AF 0x00000010 // Auxiliary carry Flag +#define FL_ZF 0x00000040 // Zero Flag +#define FL_SF 0x00000080 // Sign Flag +#define FL_TF 0x00000100 // Trap Flag +#define FL_IF 0x00000200 // Interrupt Flag +#define FL_DF 0x00000400 // Direction Flag +#define FL_OF 0x00000800 // Overflow Flag +#define FL_IOPL_MASK 0x00003000 // I/O Privilege Level bitmask +#define FL_IOPL_0 0x00000000 // IOPL == 0 +#define FL_IOPL_1 0x00001000 // IOPL == 1 +#define FL_IOPL_2 0x00002000 // IOPL == 2 +#define FL_IOPL_3 0x00003000 // IOPL == 3 +#define FL_NT 0x00004000 // Nested Task +#define FL_RF 0x00010000 // Resume Flag +#define FL_VM 0x00020000 // Virtual 8086 mode +#define FL_AC 0x00040000 // Alignment Check +#define FL_VIF 0x00080000 // Virtual Interrupt Flag +#define FL_VIP 0x00100000 // Virtual Interrupt Pending +#define FL_ID 0x00200000 // ID flag + +// Page fault error codes +#define FEC_PR 0x1 // Page fault caused by protection violation +#define FEC_WR 0x2 // Page fault caused by a write +#define FEC_U 0x4 // Page fault occured while in user mode + + +/* + * + * Part 2. Segmentation data structures and constants. + * + */ + +#ifdef __ASSEMBLER__ + +/* + * Macros to build GDT entries in assembly. + */ +#define SEG_NULL \ + .word 0, 0; \ + .byte 0, 0, 0, 0 +#define SEG(type,base,lim) \ + .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ + .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ + (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) + +#else // not __ASSEMBLER__ + +#include + +// Segment Descriptors +struct Segdesc { + unsigned sd_lim_15_0 : 16; // Low bits of segment limit + unsigned sd_base_15_0 : 16; // Low bits of segment base address + unsigned sd_base_23_16 : 8; // Middle bits of segment base address + unsigned sd_type : 4; // Segment type (see STS_ constants) + unsigned sd_s : 1; // 0 = system, 1 = application + unsigned sd_dpl : 2; // Descriptor Privilege Level + unsigned sd_p : 1; // Present + unsigned sd_lim_19_16 : 4; // High bits of segment limit + unsigned sd_avl : 1; // Unused (available for software use) + unsigned sd_rsv1 : 1; // Reserved + unsigned sd_db : 1; // 0 = 16-bit segment, 1 = 32-bit segment + unsigned sd_g : 1; // Granularity: limit scaled by 4K when set + unsigned sd_base_31_24 : 8; // High bits of segment base address +}; +// Null segment +#define SEG_NULL (struct Segdesc){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +// Segment that is loadable but faults when used +#define SEG_FAULT (struct Segdesc){ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 } +// Normal segment +#define SEG(type, base, lim, dpl) (struct Segdesc) \ +{ ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ + type, 1, dpl, 1, (unsigned) (lim) >> 28, 0, 0, 1, 1, \ + (unsigned) (base) >> 24 } +#define SEG16(type, base, lim, dpl) (struct Segdesc) \ +{ (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ + type, 1, dpl, 1, (unsigned) (lim) >> 16, 0, 0, 1, 0, \ + (unsigned) (base) >> 24 } + +#endif /* !__ASSEMBLER__ */ + +// Application segment type bits +#define STA_X 0x8 // Executable segment +#define STA_E 0x4 // Expand down (non-executable segments) +#define STA_C 0x4 // Conforming code segment (executable only) +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) +#define STA_A 0x1 // Accessed + +// System segment type bits +#define STS_T16A 0x1 // Available 16-bit TSS +#define STS_LDT 0x2 // Local Descriptor Table +#define STS_T16B 0x3 // Busy 16-bit TSS +#define STS_CG16 0x4 // 16-bit Call Gate +#define STS_TG 0x5 // Task Gate / Coum Transmitions +#define STS_IG16 0x6 // 16-bit Interrupt Gate +#define STS_TG16 0x7 // 16-bit Trap Gate +#define STS_T32A 0x9 // Available 32-bit TSS +#define STS_T32B 0xB // Busy 32-bit TSS +#define STS_CG32 0xC // 32-bit Call Gate +#define STS_IG32 0xE // 32-bit Interrupt Gate +#define STS_TG32 0xF // 32-bit Trap Gate + +#ifndef __ASSEMBLER__ + +// Task state segment format (as described by the Pentium architecture book) +struct Taskstate { + uint32_t ts_link; // Old ts selector + uintptr_t ts_esp0; // Stack pointers and segment selectors + uint16_t ts_ss0; // after an increase in privilege level + uint16_t ts_padding1; + uintptr_t ts_esp1; + uint16_t ts_ss1; + uint16_t ts_padding2; + uintptr_t ts_esp2; + uint16_t ts_ss2; + uint16_t ts_padding3; + physaddr_t ts_cr3; // Page directory base + uintptr_t ts_eip; // Saved state from last task switch + uint32_t ts_eflags; + uint32_t ts_eax; // More saved state (registers) + uint32_t ts_ecx; + uint32_t ts_edx; + uint32_t ts_ebx; + uintptr_t ts_esp; + uintptr_t ts_ebp; + uint32_t ts_esi; + uint32_t ts_edi; + uint16_t ts_es; // Even more saved state (segment selectors) + uint16_t ts_padding4; + uint16_t ts_cs; + uint16_t ts_padding5; + uint16_t ts_ss; + uint16_t ts_padding6; + uint16_t ts_ds; + uint16_t ts_padding7; + uint16_t ts_fs; + uint16_t ts_padding8; + uint16_t ts_gs; + uint16_t ts_padding9; + uint16_t ts_ldt; + uint16_t ts_padding10; + uint16_t ts_t; // Trap on task switch + uint16_t ts_iomb; // I/O map base address +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* !ARCANOS_INC_MMU_H */ diff --git a/inc/multiboot.h b/inc/multiboot.h new file mode 100644 index 0000000..a592058 --- /dev/null +++ b/inc/multiboot.h @@ -0,0 +1,225 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009 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 ARCANOS_MULTIBOOT_HEADER +#define ARCANOS_MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The bits in the required part of flags field we don't support. */ +#define MULTIBOOT_UNSUPPORTED 0x0000fffc + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the 'flags' member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the 'flags' member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 + +#ifndef ASM_FILE + +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; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* 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; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint32_t addr_low; + multiboot_uint32_t addr_high; + multiboot_uint32_t len_low; + multiboot_uint32_t len_high; + #define MULTIBOOT_MEMORY_AVAILABLE 1 + #define MULTIBOOT_MEMORY_RESERVED 2 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/inc/pic.h b/inc/pic.h new file mode 100644 index 0000000..4d7dd85 --- /dev/null +++ b/inc/pic.h @@ -0,0 +1,33 @@ + +/** + * Credit where credit is due-- I have to thank the osdev.org community + * for their excellent Wiki, which has given me incredibly useful code + * samples for working with the PIC. + */ + +#define PIC1 0x20 /* IO base address for master PIC */ +#define PIC2 0xA0 /* IO base 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 code */ + +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ + +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +void PIC_remap(int offset1, int offset2); +void PIC_sendEOI(unsigned char irq); +void PIC_clear_masks(); +void PIC_set_mask(uint8_t irq, uint8_t value); + diff --git a/inc/stdarg.h b/inc/stdarg.h new file mode 100644 index 0000000..006da79 --- /dev/null +++ b/inc/stdarg.h @@ -0,0 +1,19 @@ +/* $NetBSD: stdarg.h,v 1.12 1995/12/25 23:15:31 mycroft Exp $ */ + +#ifndef STDARG_H +#define STDARG_H + +typedef char *va_list; + +#define __va_size(type) \ + (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long)) + +#define va_start(ap, last) \ + ((ap) = (va_list)&(last) + __va_size(last)) + +#define va_arg(ap, type) \ + (*(type *)((ap) += __va_size(type), (ap) - __va_size(type))) + +#define va_end(ap) ((void)0) + +#endif /* !STDARG_H */ diff --git a/inc/string.h b/inc/string.h new file mode 100644 index 0000000..56d3302 --- /dev/null +++ b/inc/string.h @@ -0,0 +1,9 @@ +#ifndef ARCANOS_INC_STRING_H +#define ARCANOS_INC_STRING_H + +#include + +int strlen(const char *s); +void * memset(void *dst, int c, size_t len); + +#endif /* not ARCANOS_INC_STRING_H */ diff --git a/inc/stringformat.h b/inc/stringformat.h new file mode 100644 index 0000000..be48b14 --- /dev/null +++ b/inc/stringformat.h @@ -0,0 +1,21 @@ +/* + * stringformat.h + * + * Created on: Aug 30, 2010 + * Author: rhett + */ + +#ifndef STRINGFORMAT_H_ +#define STRINGFORMAT_H_ + +#include + +void reverse(char*); + +void print_int_dec(unsigned int i); +void print_int_hex(unsigned int i); +void print_substring(char* i); +void print_escape_char(char c); + +void _kern_print(const char* fmt_string, ...); +#endif /* STRINGFORMAT_H_ */ diff --git a/inc/types.h b/inc/types.h new file mode 100644 index 0000000..e50fba1 --- /dev/null +++ b/inc/types.h @@ -0,0 +1,72 @@ +#ifndef ARCANOS_INC_TYPES_H +#define ARCANOS_INC_TYPES_H + +#ifndef NULL +#define NULL ((void*) 0) +#endif + +// Represents true-or-false values +typedef int bool; + +// Explicitly-sized versions of integer types +typedef __signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; + +// Pointers and addresses are 32 bits long. +// We use pointer types to represent virtual addresses, +// uintptr_t to represent the numerical values of virtual addresses, +// and physaddr_t to represent physical addresses. +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; +typedef uint32_t physaddr_t; + +// Page numbers are 32 bits long. +typedef uint32_t ppn_t; + +// size_t is used for memory object sizes. +typedef uint32_t size_t; +// ssize_t is a signed version of ssize_t, used in case there might be an +// error return. +typedef int32_t ssize_t; + +// off_t is used for file offsets and lengths. +typedef int32_t off_t; + +// Efficient min and max operations +#define MIN(_a, _b) \ +({ \ + typeof(_a) __a = (_a); \ + typeof(_b) __b = (_b); \ + __a <= __b ? __a : __b; \ +}) +#define MAX(_a, _b) \ +({ \ + typeof(_a) __a = (_a); \ + typeof(_b) __b = (_b); \ + __a >= __b ? __a : __b; \ +}) + +// Rounding operations (efficient when n is a power of 2) +// Round down to the nearest multiple of n +#define ROUNDDOWN(a, n) \ +({ \ + uint32_t __a = (uint32_t) (a); \ + (typeof(a)) (__a - __a % (n)); \ +}) +// Round up to the nearest multiple of n +#define ROUNDUP(a, n) \ +({ \ + uint32_t __n = (uint32_t) (n); \ + (typeof(a)) (ROUNDDOWN((uint32_t) (a) + __n - 1, __n)); \ +}) + +// Return the offset of 'member' relative to the beginning of a struct type +#define offsetof(type, member) ((size_t) (&((type*)0)->member)) + +#endif /* !ARCANOS_INC_TYPES_H */ diff --git a/inc/x86.h b/inc/x86.h new file mode 100644 index 0000000..e6b19ea --- /dev/null +++ b/inc/x86.h @@ -0,0 +1,283 @@ +#ifndef ARCANOS_INC_X86_H +#define ARCANOS_INC_X86_H + +#include + +static __inline void breakpoint(void) __attribute__((always_inline)); +static __inline uint8_t inb(int port) __attribute__((always_inline)); +static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline)); +static __inline uint16_t inw(int port) __attribute__((always_inline)); +static __inline void insw(int port, void *addr, int cnt) __attribute__((always_inline)); +static __inline uint32_t inl(int port) __attribute__((always_inline)); +static __inline void insl(int port, void *addr, int cnt) __attribute__((always_inline)); +static __inline void outb(int port, uint8_t data) __attribute__((always_inline)); +static __inline void outsb(int port, const void *addr, int cnt) __attribute__((always_inline)); +static __inline void outw(int port, uint16_t data) __attribute__((always_inline)); +static __inline void outsw(int port, const void *addr, int cnt) __attribute__((always_inline)); +static __inline void outsl(int port, const void *addr, int cnt) __attribute__((always_inline)); +static __inline void outl(int port, uint32_t data) __attribute__((always_inline)); +static __inline void invlpg(void *addr) __attribute__((always_inline)); +static __inline void lidt(void *p) __attribute__((always_inline)); +static __inline void lldt(uint16_t sel) __attribute__((always_inline)); +static __inline void ltr(uint16_t sel) __attribute__((always_inline)); +static __inline void lcr0(uint32_t val) __attribute__((always_inline)); +static __inline uint32_t rcr0(void) __attribute__((always_inline)); +static __inline uint32_t rcr2(void) __attribute__((always_inline)); +static __inline void lcr3(uint32_t val) __attribute__((always_inline)); +static __inline uint32_t rcr3(void) __attribute__((always_inline)); +static __inline void lcr4(uint32_t val) __attribute__((always_inline)); +static __inline uint32_t rcr4(void) __attribute__((always_inline)); +static __inline void tlbflush(void) __attribute__((always_inline)); +static __inline uint32_t read_eflags(void) __attribute__((always_inline)); +static __inline void write_eflags(uint32_t eflags) __attribute__((always_inline)); +static __inline uint32_t read_ebp(void) __attribute__((always_inline)); +static __inline uint32_t read_esp(void) __attribute__((always_inline)); +static __inline void cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp); +static __inline uint64_t read_tsc(void) __attribute__((always_inline)); +static __inline void io_wait(void) __attribute__((always_inline)); + +static __inline void +breakpoint(void) +{ + __asm __volatile("int3"); +} + +static __inline uint8_t +inb(int port) +{ + uint8_t data; + __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insb(int port, void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\tinsb" : + "=D" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "memory", "cc"); +} + +static __inline uint16_t +inw(int port) +{ + uint16_t data; + __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insw(int port, void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\tinsw" : + "=D" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "memory", "cc"); +} + +static __inline uint32_t +inl(int port) +{ + uint32_t data; + __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insl(int port, void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\tinsl" : + "=D" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "memory", "cc"); +} + +static __inline void +outb(int port, uint8_t data) +{ + __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsb(int port, const void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\toutsb" : + "=S" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "cc"); +} + +static __inline void +outw(int port, uint16_t data) +{ + __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsw(int port, const void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\toutsw" : + "=S" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "cc"); +} + +static __inline void +outsl(int port, const void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\toutsl" : + "=S" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "cc"); +} + +static __inline void +outl(int port, uint32_t data) +{ + __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +invlpg(void *addr) +{ + __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory"); +} + +static __inline void +lidt(void *p) +{ + __asm __volatile("lidt (%0)" : : "r" (p)); +} + +static __inline void +lldt(uint16_t sel) +{ + __asm __volatile("lldt %0" : : "r" (sel)); +} + +static __inline void +ltr(uint16_t sel) +{ + __asm __volatile("ltr %0" : : "r" (sel)); +} + +static __inline void +lcr0(uint32_t val) +{ + __asm __volatile("movl %0,%%cr0" : : "r" (val)); +} + +static __inline uint32_t +rcr0(void) +{ + uint32_t val; + __asm __volatile("movl %%cr0,%0" : "=r" (val)); + return val; +} + +static __inline uint32_t +rcr2(void) +{ + uint32_t val; + __asm __volatile("movl %%cr2,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr3(uint32_t val) +{ + __asm __volatile("movl %0,%%cr3" : : "r" (val)); +} + +static __inline uint32_t +rcr3(void) +{ + uint32_t val; + __asm __volatile("movl %%cr3,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr4(uint32_t val) +{ + __asm __volatile("movl %0,%%cr4" : : "r" (val)); +} + +static __inline uint32_t +rcr4(void) +{ + uint32_t cr4; + __asm __volatile("movl %%cr4,%0" : "=r" (cr4)); + return cr4; +} + +static __inline void +tlbflush(void) +{ + uint32_t cr3; + __asm __volatile("movl %%cr3,%0" : "=r" (cr3)); + __asm __volatile("movl %0,%%cr3" : : "r" (cr3)); +} + +static __inline uint32_t +read_eflags(void) +{ + uint32_t eflags; + __asm __volatile("pushfl; popl %0" : "=r" (eflags)); + return eflags; +} + +static __inline void +write_eflags(uint32_t eflags) +{ + __asm __volatile("pushl %0; popfl" : : "r" (eflags)); +} + +static __inline uint32_t +read_ebp(void) +{ + uint32_t ebp; + __asm __volatile("movl %%ebp,%0" : "=r" (ebp)); + return ebp; +} + +static __inline uint32_t +read_esp(void) +{ + uint32_t esp; + __asm __volatile("movl %%esp,%0" : "=r" (esp)); + return esp; +} + +static __inline void +cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp) +{ + uint32_t eax, ebx, ecx, edx; + asm volatile("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "a" (info)); + if (eaxp) + *eaxp = eax; + if (ebxp) + *ebxp = ebx; + if (ecxp) + *ecxp = ecx; + if (edxp) + *edxp = edx; +} + +static __inline uint64_t +read_tsc(void) +{ + uint64_t tsc; + __asm __volatile("rdtsc" : "=A" (tsc)); + return tsc; +} + +static __inline void io_wait(void) { + asm volatile("outb %%al, $0x80" : : "a"(0)); +} + + +#endif /* !ARCANOS_INC_X86_H */ diff --git a/kern/COPYRIGHT b/kern/COPYRIGHT new file mode 100644 index 0000000..dce201f --- /dev/null +++ b/kern/COPYRIGHT @@ -0,0 +1,41 @@ +Unless otherwise stated, all source is Copyright (c) 2010 J. Rhett Aultman +and under the GPL v3. + +entry.S is derived from the Exokernel, which is: + +/* + * Copyright (C) 1997 Massachusetts Institute of Technology + * + * This software is being provided by the copyright holders under the + * following license. By obtaining, using and/or copying this software, + * you agree that you have read, understood, and will comply with the + * following terms and conditions: + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose and without fee or royalty is + * hereby granted, provided that the full text of this NOTICE appears on + * ALL copies of the software and documentation or portions thereof, + * including modifications, that you make. + * + * THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, + * BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR + * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR + * THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY + * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT + * HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR + * DOCUMENTATION. + * + * The name and trademarks of copyright holders may NOT be used in + * advertising or publicity pertaining to the software without specific, + * written prior permission. Title to copyright in this software and any + * associated documentation will at all times remain with copyright + * holders. See the file AUTHORS which should have accompanied this software + * for a list of all copyright holders. + * + * This file may be derived from previously copyrighted software. This + * copyright applies only to those changes made by the copyright + * holders listed in the AUTHORS file. The rest of this file is covered by + * the copyright notices, if any, listed below. + */ + diff --git a/kern/Makefrag b/kern/Makefrag new file mode 100644 index 0000000..8f17fdb --- /dev/null +++ b/kern/Makefrag @@ -0,0 +1,66 @@ +OBJDIRS += kern + +KERN_LDFLAGS := $(LDFLAGS) -T kern/kernel.ld -nostdlib + +# entry.S must be first, so that it's the first code in the text segment!!! +# +# We also snatch the use of a couple handy source files +# from the lib directory, to avoid gratuitous code duplication. +KERN_SRCFILES := kern/entry.S \ + kern/init.c \ + kern/console.c \ + lib/string.c \ + kern/stringformat.c \ + kern/memmgr.c \ + kern/interrupts/interrupts.S \ + kern/interrupts/interrupt_handlers.c \ + kern/interrupts/idt.c \ + kern/interrupts/pic.c + +# Only build files if they exist. +KERN_SRCFILES := $(wildcard $(KERN_SRCFILES)) + +KERN_BINFILES := + +KERN_OBJFILES := $(patsubst %.c, $(OBJDIR)/%.o, $(KERN_SRCFILES)) +KERN_OBJFILES := $(patsubst %.S, $(OBJDIR)/%.o, $(KERN_OBJFILES)) +KERN_OBJFILES := $(patsubst obj/lib/%, obj/kern/%, $(KERN_OBJFILES)) + +KERN_BINFILES := $(patsubst %, $(OBJDIR)/%, $(KERN_BINFILES)) + +# How to build kernel object files +$(OBJDIR)/kern/%.o: kern/%.c + @echo + cc $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $< + +$(OBJDIR)/kern/%.o: kern/%.S + @echo + as $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $< + +$(OBJDIR)/kern/%.o: kern/interrupts/%.S + @echo + as $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $< + +$(OBJDIR)/kern/%.o: lib/%.c + @echo + cc $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $< + +# How to build the kernel itself +$(OBJDIR)/kern/kernel: $(KERN_OBJFILES) $(KERN_BINFILES) kern/kernel.ld + @echo + ld $@ + $(V)$(LD) -o $@ $(KERN_LDFLAGS) $(KERN_OBJFILES) $(GCC_LIB) -b binary $(KERN_BINFILES) + $(V)$(OBJDUMP) -S $@ > $@.asm + $(V)$(NM) -n $@ > $@.sym + +# How to build the Bochs disk image +$(OBJDIR)/kern/bochs.img: $(OBJDIR)/kern/kernel + @echo + mk $@ + kern/layout_image_file.py + $(V)cat boot/stage1 boot/stage2 boot/pad $(OBJDIR)/kern/kernel boot/post_pad > $(OBJDIR)/kern/bochs.img + +all: $(OBJDIR)/kern/bochs.img + diff --git a/kern/boot.S b/kern/boot.S new file mode 100644 index 0000000..922c0ff --- /dev/null +++ b/kern/boot.S @@ -0,0 +1,30 @@ +.global loader # making entry point visible to linker +.extern kernel_main + +# setting up the Multiboot header - see GRUB docs for details +.set ALIGN, 1<<0 # align loaded modules on page boundaries +.set MEMINFO, 1<<1 # provide memory map +.set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field +.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header +.set CHECKSUM, -(MAGIC + FLAGS) # checksum required + +.align 4 +.long MAGIC +.long FLAGS +.long CHECKSUM + +# reserve initial kernel stack space +.set STACKSIZE, 0x4000 # that is, 16k. +.comm stack, STACKSIZE, 32 # reserve 16k stack on a quadword boundary + +loader: + mov $(stack + STACKSIZE), %esp # set up the stack + push %eax # Multiboot magic number + push %ebx # Multiboot data structure + + call kernel_main # call kernel proper + + cli +hang: + hlt # halt machine should kernel return + jmp hang diff --git a/kern/console.c b/kern/console.c new file mode 100644 index 0000000..752c50a --- /dev/null +++ b/kern/console.c @@ -0,0 +1,116 @@ +#include +#include +#include + +#include + +#define SCREEN_WIDTH 80 +#define SCREEN_HEIGHT 25 +#define X 0 +#define Y 1 + +volatile uint8_t* textmode_base = (volatile uint8_t*)(0xB8000); +uint8_t current_color = (uint8_t)0x2a; +uint8_t current_loc[2] = {0,0}; +char screen_buffer[SCREEN_WIDTH*SCREEN_HEIGHT]; + +void blank_screen() { + int i=0; + for (i=0; i<(SCREEN_WIDTH*SCREEN_HEIGHT*2); i=i+2) { + *(textmode_base+i) = ' '; + *(textmode_base+i+1) = current_color; + screen_buffer[i/2] = ' '; + } + current_loc[X] = 0; + current_loc[Y] = 0; +} + +void buffer_to_screen() { + int i=0; + for (i=0; i<(SCREEN_WIDTH*SCREEN_HEIGHT*2); i=i+2) { + *(textmode_base+i) = screen_buffer[i/2]; + *(textmode_base+i+1) = current_color; + } +} + +void console_init() { + blank_screen(); + update_cursor(); +} + +void printchar(char c) { + unsigned int offset = ((current_loc[Y]*SCREEN_WIDTH)+current_loc[X])*2; + *(textmode_base+offset) = c; + screen_buffer[(current_loc[Y]*SCREEN_WIDTH)+current_loc[X]] = c; + *(textmode_base+offset+1) = current_color; + current_loc[X]++; + if (current_loc[X] >= SCREEN_WIDTH) { + next_line(); + } +} + +void next_line() { + current_loc[X] = 0; + current_loc[Y] = current_loc[Y] + 1; + if (current_loc[Y] == SCREEN_HEIGHT) { + int x=0; + int y=0; + //copy everything in the buffer one line down + move_to(0,0); + for (y=1; y<=SCREEN_HEIGHT; y++) { + for (x=0; x>8)&0xFF)); +} + +int8_t move_to (uint8_t x, uint8_t y) { + if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) { + return -1; + } + current_loc[X] = x; + current_loc[Y] = y; + return 0; +} + + + +void print_string_helper(char* string) { + while (*string != '\0') { + printchar(*string); + string++; + } +} + +void print_string(char* string) { + print_string_helper(string); + update_cursor(); +} + +void print_line(char* string) { + print_string_helper(string); + next_line(); + update_cursor(); +} diff --git a/kern/entry.S b/kern/entry.S new file mode 100644 index 0000000..2532d04 --- /dev/null +++ b/kern/entry.S @@ -0,0 +1,126 @@ +/* See COPYRIGHT for copyright information. */ + +#include +#include + +# Shift Right Logical +#define SRL(val, shamt) (((val) >> (shamt)) & ~(-1 << (32 - (shamt)))) + + +################################################################### +# The kernel (this code) is linked at address ~(KERNBASE + 1 Meg), +# but the bootloader loads it at address ~1 Meg. +# +# RELOC(x) maps a symbol x from its link address to its actual +# location in physical memory (its load address). +################################################################### + +#define RELOC(x) ((x) - KERNBASE) + + +.set CODE_SEL,0x8 # index of code seg within mygdt +.set DATA_SEL,0x10 # index of data seg within mygdt + +#define MULTIBOOT_PAGE_ALIGN (1<<0) +#define MULTIBOOT_MEMORY_INFO (1<<1) +#define MULTIBOOT_HEADER_MAGIC (0x1BADB002) +#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN) +#define CHECKSUM (-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)) + +################################################################### +# entry point +################################################################### + +.text + +# The Multiboot header +.align 4 +.long MULTIBOOT_HEADER_MAGIC +.long MULTIBOOT_HEADER_FLAGS +.long CHECKSUM + +.globl _start +_start: + movw $0x1234,0x472 # warm boot + + # Clear the frame pointer register (EBP) + # so that once we get into debugging C code, + # stack backtraces will be terminated properly. + movl $0x0,%ebp # nuke frame pointer + + # Set the stack pointer + movl $(RELOC(bootstacktop)),%esp + + #preserve the GRUB magic info + push %eax + push %ebx + + movl $(RELOC(init_paging)), %edx + call %edx + + #okay...in theory, paging is ready to go, so enable paging + + mov $INITIAL_PDE, %eax + mov %eax, %cr3 + + mov %cr0, %eax + or $0x80000000, %eax + mov %eax, %cr0 + + #get the info back off the stack before we NEWK it! + pop %ebx + pop %eax + + # Perform a long jump to a symbol the linker has provided. This + # will move the program counter register into the address space + # ArcanOS is linked to. + + ljmp $CODE_SEL,$relocated +relocated: + + # Clear the frame pointer register (EBP) + # so that once we get into debugging C code, + # stack backtraces will be terminated properly. + movl $0x0,%ebp # nuke frame pointer + + # Set the stack pointer + movl $(bootstacktop),%esp + + push %eax #push the multiboot magic number on the stack + push %ebx #push the multipoot pointer on the stack + + # now to C code + call kernel_main + + # Should never get here, but in case we do, just spin. +spin: jmp spin + +################################################################### +# boot stack +################################################################### + .p2align PGSHIFT # force page alignment + .globl bootstack +bootstack: + .space KSTKSIZE + .globl bootstacktop +bootstacktop: + +################################################################### +# setup the GDT +################################################################### + .p2align 2 # force 4 byte alignment +mygdt: + SEG_NULL # null seg + SEG(STA_X|STA_R, -KERNBASE, 0xffffffff) # code seg + SEG(STA_W, -KERNBASE, 0xffffffff) # data seg +mygdtdesc: + .word 0x17 # sizeof(mygdt) - 1 + .long RELOC(mygdt) # address mygdt + +mygdt_flat: + SEG_NULL # null seg + SEG(STA_X|STA_R, 0, 0xffffffff) # code seg + SEG(STA_W, 0, 0xffffffff) # data seg +mygdtdesc_flat: + .word 0x17 # sizeof(mygdt_flat) - 1 + .long RELOC(mygdt_flat) # address mygdt_flat diff --git a/kern/init.c b/kern/init.c new file mode 100644 index 0000000..fb14f92 --- /dev/null +++ b/kern/init.c @@ -0,0 +1,148 @@ +/* See COPYRIGHT for copyright information. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Check if the bit BIT in FLAGS is set. */ +#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit))) + +extern void keyboard_isr(); +void i386_init(multiboot_info_t* mbi); + +void kernel_main( void* mbd, unsigned int magic ) +{ + if ( magic != 0x2BADB002 ) + { + /* Something went not according to specs. Print an error */ + /* message and halt, but do *not* rely on the multiboot */ + /* data structure. */ + _kern_print("BROKEN MULTIBOOT HEADER! Bailing out!"); + while(1); + } + mbd = KERNBASE + mbd; + i386_init((multiboot_info_t*)mbd); +} + +void +i386_init(multiboot_info_t* mbi) +{ + extern char etext[], edata[], end[], kern_textbase[], kern_textend[]; + extern char kern_robase[], kern_roend[]; + extern char kern_stabbase[], kern_stabend[]; + extern char kern_stabstrbase[], kern_stabstrend[]; + extern char kern_database[], kern_dataend[]; + extern char kern_bssbase[], kern_bssend[]; + extern char end[]; + extern char load_start[], load_end[]; + + int i; + int j; + + console_init(); + _kern_print("Arcanos version %s\n", ARCANOS_VERSION); + _kern_print("Kernel mapped to address 0x%x\n", KERNBASE); + + /* Print out the flags. */ + _kern_print("multiboot info address = 0x%x\n", mbi); + _kern_print("flags = 0x%x\n", (unsigned) mbi->flags); + + /* Are mem_* valid? */ + if (CHECK_FLAG (mbi->flags, 0)) + _kern_print("mem_lower = %uKB, mem_upper = %uKB\n", + (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper); + + /* Is boot_device valid? */ + if (CHECK_FLAG (mbi->flags, 1)) + _kern_print("boot_device = 0x%x\n", (unsigned) mbi->boot_device); + + /* Is the command line passed? */ + if (CHECK_FLAG (mbi->flags, 2)) { + _kern_print("cmdline = %s\n", (char *) (mbi->cmdline)); + } + + + /* Are mods_* valid? */ + if (CHECK_FLAG (mbi->flags, 3)) + { + multiboot_module_t *mod; + int i; + + _kern_print("mods_count = %d, mods_addr = 0x%x\n", + (int) mbi->mods_count, (int) (mbi->mods_addr)); + for (i = 0, mod = (multiboot_module_t *) (mbi->mods_addr); + i < mbi->mods_count; + i++, mod++) + _kern_print(" mod_start = 0x%x, mod_end = 0x%x, cmdline = %s\n", + (unsigned) (mod->mod_start), + (unsigned) (mod->mod_end), + (char *) (mod->cmdline)); + } + + + /* Bits 4 and 5 are mutually exclusive! */ + if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5)) + { + _kern_print("Both bits 4 and 5 are set.\n"); + return; + } + + /* Is the symbol table of a.out valid? */ + if (CHECK_FLAG (mbi->flags, 4)) + { + multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym); + + _kern_print("multiboot_aout_symbol_table: tabsize = 0x%0x, " + "strsize = 0x%x, addr = 0x%x\n", + (unsigned) multiboot_aout_sym->tabsize, + (unsigned) multiboot_aout_sym->strsize, + (unsigned) multiboot_aout_sym->addr); + } + + /* Is the section header table of ELF valid? */ + if (CHECK_FLAG (mbi->flags, 5)) + { + multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec); + + _kern_print("multiboot_elf_sec: num = %u, size = 0x%x," + " addr = 0x%x, shndx = 0x%x\n", + (unsigned) multiboot_elf_sec->num, (unsigned) multiboot_elf_sec->size, + (unsigned) (multiboot_elf_sec->addr), (unsigned) multiboot_elf_sec->shndx); + } + + /* Are mmap_* valid? */ + if (CHECK_FLAG (mbi->flags, 6)) + { + multiboot_memory_map_t *mmap; + + frame_allocator_init(mbi, (uint32_t)load_start, (uint32_t)load_end); + } + + //void* init_addr = memmgr_init(end); + //_kern_print("Mem mgr initialized and using address %x\n", init_addr); + asm("cli"); + reset_idt(); + load_idt(); + PIC_clear_masks(); + PIC_remap(32, 40); //PIC1 - 32-39, PIC2 - 40-47; + set_idt_entry(33, keyboard_isr, INTERRUPT_GATE_TYPE_ATTR); + PIC_set_mask(1, 0); + load_idt(); + asm("sti"); //Interrupts are on now, bitches. + _kern_print("Interrupts enabled.\n"); + //I think that it might actually be necessary to forcibly run the + //keyboard ISR to perhaps...process any lingering key presses? + asm("int $33"); + memmgr_init(); + + char* yaay = memmgr_allocate(1024); +//stop here for now + _kern_print("Entering kernel idle loop.\n"); + asm("hlt"); + while (1); +} diff --git a/kern/interrupts/COPYRIGHT b/kern/interrupts/COPYRIGHT new file mode 100644 index 0000000..40c0755 --- /dev/null +++ b/kern/interrupts/COPYRIGHT @@ -0,0 +1,2 @@ +Unless otherwise stated, all source is Copyright (c) 2010 J. Rhett Aultman +and under the GPL v3. diff --git a/kern/interrupts/idt.c b/kern/interrupts/idt.c new file mode 100644 index 0000000..c51b4f6 --- /dev/null +++ b/kern/interrupts/idt.c @@ -0,0 +1,73 @@ +#include +#include +#include + +extern void isr_0(); +extern void isr_1(); +extern void isr_2(); +extern void isr_3(); +extern void isr_4(); +extern void isr_5(); +extern void isr_6(); +extern void isr_7(); +extern void isr_8(); +extern void isr_9(); +extern void isr_10(); +extern void isr_11(); +extern void isr_12(); +extern void isr_13(); +extern void isr_14(); +extern void isr_16(); +extern void isr_17(); +extern void isr_18(); +extern void isr_19(); +extern void isr_30(); + +void reset_idt() { + memset(idt, 0, sizeof(IDTDescr)*256); + //The base of the table must be a linear address (which is + //currently the same as the physical address) + idt_struct.base = (uint32_t)idt-KERNBASE; + idt_struct.limit = 256*(sizeof(IDTDescr)-1); + idtp = &idt_struct; + phys_idtp = (IDT*)(((uint32_t)idtp) - KERNBASE); + _kern_print("IDTP: %x PHYS_IDTP %x\n", ((uint32_t)idtp), ((uint32_t)phys_idtp)); + //Set default exception handlers. There's no compelling reason + //to change them, but kernel code can by making its own + //set_idt_entry calls. + set_idt_entry(0, isr_0, TRAP_GATE_TYPE_ATTR); + set_idt_entry(1,isr_1, TRAP_GATE_TYPE_ATTR); + set_idt_entry(2,isr_2, INTERRUPT_GATE_TYPE_ATTR); + set_idt_entry(3,isr_3, TRAP_GATE_TYPE_ATTR); + set_idt_entry(4,isr_4, TRAP_GATE_TYPE_ATTR); + set_idt_entry(5,isr_5, TRAP_GATE_TYPE_ATTR); + set_idt_entry(6,isr_6, TRAP_GATE_TYPE_ATTR); + set_idt_entry(7,isr_7, TRAP_GATE_TYPE_ATTR); + set_idt_entry(8,isr_8, TRAP_GATE_TYPE_ATTR); + set_idt_entry(9,isr_9, TRAP_GATE_TYPE_ATTR); + set_idt_entry(10,isr_10, TRAP_GATE_TYPE_ATTR); + set_idt_entry(11,isr_11, TRAP_GATE_TYPE_ATTR); + set_idt_entry(12,isr_12, TRAP_GATE_TYPE_ATTR); + set_idt_entry(13,isr_13, TRAP_GATE_TYPE_ATTR); + set_idt_entry(14,isr_14, TRAP_GATE_TYPE_ATTR); + set_idt_entry(16,isr_16, TRAP_GATE_TYPE_ATTR); + set_idt_entry(17,isr_17, TRAP_GATE_TYPE_ATTR); + set_idt_entry(18,isr_18, TRAP_GATE_TYPE_ATTR); + set_idt_entry(19,isr_19, TRAP_GATE_TYPE_ATTR); + set_idt_entry(30,isr_30, TRAP_GATE_TYPE_ATTR); + +} + +void set_idt_entry(uint8_t number, void (*handler)(), uint16_t type) { + uint32_t handler_addr = (uint32_t)handler - KERNBASE; + handler_addr = handler_addr; + idt[number].offset_1 = LOW_OFFSET(handler_addr); + idt[number].offset_2 = HIGH_OFFSET(handler_addr); + idt[number].selector = GD_KT; + idt[number].type_attr = type; + idt[number].zero = 0; +} + +void load_idt() { + asm volatile("LIDT (%0) ": :"p" (phys_idtp)); +} diff --git a/kern/interrupts/interrupt_handlers.c b/kern/interrupts/interrupt_handlers.c new file mode 100644 index 0000000..d9cffaa --- /dev/null +++ b/kern/interrupts/interrupt_handlers.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +char* exception_messages[32] = { +"Divide-by-zero Error", +"Debug", +"Non-maskable Interrupt", +"Breakpoint", +"Overflow", +"Bound Range Exceeded", +"Invalid Opcode", +"Device Not Available", +"Double Fault", +"Coprocessor Segment Overrun", +"Invalid TSS", +"Segment Not Present", +"Stack-Segment Fault", +"General Protection Fault", +"Page Fault", +"Reserved", +"x87 Floating-Point Exception", +"Alignment Check", +"Machine Check", +"SIMD Floating-Point Exception", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Security Exception", +"Reserved" +}; + +/** + * Exceptions to handle: + * +Divide-by-zero Error 0 Fault #DE No +Debug 1 Fault/Trap #DB No +Non-maskable Interrupt 2 Interrupt - No +Breakpoint 3 Trap #BP No +Overflow 4 Trap #OF No +Bound Range Exceeded 5 Fault #BR No +Invalid Opcode 6 Fault #UD No +Device Not Available 7 Fault #NM No +Double Fault 8 Abort #DF Yes +Coprocessor Segment Overrun 9 Fault - No +Invalid TSS 10 Fault #TS Yes +Segment Not Present 11 Fault #NP Yes +Stack-Segment Fault 12 Fault #SS Yes +General Protection Fault 13 Fault #GP Yes +Page Fault 14 Fault #PF Yes +Reserved 15 - - No +x87 Floating-Point Exception 16 Fault #MF No +Alignment Check 17 Fault #AC Yes +Machine Check 18 Abort #MC No +SIMD Floating-Point Exception 19 Fault #XM/#XF No +Reserved 20-29 - - No +Security Exception 30 - #SX No +Reserved 31 - - No +Triple Fault - - - No +*/ + +/* filename : interrupt_handlers.c */ +void _interrupt_handler(uint8_t number) +{ + _kern_print("%s exception. Halting.\n", exception_messages[number]); + asm("hlt"); + while(1); +} + +void _keyboard_interrupt() +{ + uint8_t new_scan_code=0; + new_scan_code = inb(0x60); + + /* Do something with the scancode. + * Remember you only get '''one''' byte of the scancode each time the ISR is invoked. + * (Though most of the times the scancode is only one byte.) + */ + _kern_print("Keyboard scancode 0x%x\n", new_scan_code); + /* Acknowledge the IRQ, pretty much tells the PIC that we can accept >=priority IRQs now. */ + PIC_sendEOI(1); //Keyboard is IRQ 1. +} diff --git a/kern/interrupts/interrupts.S b/kern/interrupts/interrupts.S new file mode 100644 index 0000000..fc5c990 --- /dev/null +++ b/kern/interrupts/interrupts.S @@ -0,0 +1,194 @@ +/* filename : interrupts.S */ + +.globl _load_idt +.extern idtp +.extern _interrupt_handler + +.align 4 + +//Divide-by-zero Error +.globl isr_0 +isr_0: + pushal + push $0 + call _interrupt_handler + popal + iret + +//Debug +.globl isr_1 +isr_1: + pushal + push $1 + call _interrupt_handler + popal + iret + +//Non-maskable Interrupt +.globl isr_2 +isr_2: + pushal + push $2 + call _interrupt_handler + popal + iret + +//Breakpoint +.globl isr_3 +isr_3: + pushal + push $3 + call _interrupt_handler + popal + iret + +//Overflow +.globl isr_4 +isr_4: + pushal + push $4 + call _interrupt_handler + popal + iret + +//Bound Range Exceeded +.globl isr_5 +isr_5: + pushal + push $5 + call _interrupt_handler + popal + iret + +//Invalid Opcode +.globl isr_6 +isr_6: + pushal + push $6 + call _interrupt_handler + popal + iret + +//Device Not Available +.globl isr_7 +isr_7: + pushal + push $7 + call _interrupt_handler + popal + iret + +//Double Fault +.globl isr_8 +isr_8: + pushal + push $8 + call _interrupt_handler + popal + iret + +//Coprocessor Segment Overrun +.globl isr_9 +isr_9: + pushal + push $9 + call _interrupt_handler + popal + iret + +//Invalid TSS +.globl isr_10 +isr_10: + pushal + push $10 + call _interrupt_handler + popal + iret + +//Segment Not Present +.globl isr_11 +isr_11: + pushal + push $11 + call _interrupt_handler + popal + iret + +//Stack-Segment Fault +.globl isr_12 +isr_12: + pushal + push $12 + call _interrupt_handler + popal + iret + +//General Protection Fault +.globl isr_13 +isr_13: + pushal + push $13 + call _interrupt_handler + popal + iret + +//Page Fault +.globl isr_14 +isr_14: + pushal + push $14 + call _interrupt_handler + popal + iret + +//x87 Floating-Point Exception +.globl isr_16 +isr_16: + pushal + push $16 + call _interrupt_handler + popal + iret + +//Alignment Check +.globl isr_17 +isr_17: + pushal + push $17 + call _interrupt_handler + popal + iret + +//Machine Check +.globl isr_18 +isr_18: + pushal + push $18 + call _interrupt_handler + popal + iret + +//SIMD Floating-Point Exception +.globl isr_19 +isr_19: + pushal + push $19 + call _interrupt_handler + popal + iret + +//Security Exception +.globl isr_30 +isr_30: + pushal + push $30 + call _interrupt_handler + popal + iret + +.globl keyboard_isr +keyboard_isr: + pushal + call _keyboard_interrupt + popal + iret diff --git a/kern/interrupts/pic.c b/kern/interrupts/pic.c new file mode 100644 index 0000000..1b30b3c --- /dev/null +++ b/kern/interrupts/pic.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +/** + * Again, a debt of gratitude to osdev.org for this code. + */ + +void PIC_sendEOI(unsigned char irq) +{ + if(irq >= 8) + outb(PIC2_COMMAND,PIC_EOI); + + outb(PIC1_COMMAND,PIC_EOI); +} + +/* +arguments: + offset1 - vector offset for master PIC + vectors on the master become offset1..offset1+7 + offset2 - same for slave PIC: offset2..offset2+7 +*/ +void PIC_remap(int offset1, int offset2) +{ + uint8_t a1, a2; + + a1 = inb(PIC1_DATA); // save masks + a2 = inb(PIC2_DATA); + + outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // starts the initialization sequence + io_wait(); + outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); + io_wait(); + outb(PIC1_DATA, offset1); // define the PIC vectors + io_wait(); + outb(PIC2_DATA, offset2); + io_wait(); + outb(PIC1_DATA, 4); //ICW3: Master takes slave on IRQ2 (4 = 100b -- bitmask for IRQ2) + io_wait(); + outb(PIC2_DATA, 2); //ICW3: Slave sends to master on IRQ2 (2 expressed in binary here) + io_wait(); + + outb(PIC1_DATA, ICW4_8086); + io_wait(); + outb(PIC2_DATA, ICW4_8086); + io_wait(); + + outb(PIC1_DATA, a1); // restore saved masks. + outb(PIC2_DATA, a2); +} + +void PIC_clear_masks() { + outb(PIC1_DATA, 0xFF); + outb(PIC2_DATA, 0xFF); +} + +/* + * Set/clear interrupt mask bits. Must specify by IRQ and value is + * 0 to clear and all else to set. + */ +void PIC_set_mask(uint8_t irq, uint8_t value) { + uint8_t mask_bit = 1; + + uint8_t pic_port; + + if(irq >= 8) { + irq = irq-8; + pic_port = PIC2_DATA; + } else { + pic_port = PIC1_DATA; + } + + uint8_t mask; + mask = inb(pic_port); //get current mask + io_wait(); + mask_bit = mask_bit << irq; + if (value) { + mask = mask | mask_bit; //If value is 1, then set the mask bit + } else { + mask = mask & (~mask_bit); //If value is 0, then clear the mask bit + } + outb(pic_port, mask); //set the new mask + io_wait(); +} diff --git a/kern/kernel.ld b/kern/kernel.ld new file mode 100644 index 0000000..289006e --- /dev/null +++ b/kern/kernel.ld @@ -0,0 +1,84 @@ +/* Simple linker script for the Arcanos kernel. + See the GNU ld 'info' manual ("info ld") to learn the syntax. */ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) + +virt = 0xC0100000; +phys = 0x00100000; +offset = 0xC0000000; + +SECTIONS +{ + .text virt : AT(phys) { + PROVIDE(load_start = phys); + PROVIDE(kern_textbase = .); + *(.text .stub .text.* .gnu.linkonce.t.*) + PROVIDE(kern_textend = .); + } + + PROVIDE(etext = .); + phys = ALIGN(4) - offset; + + .rodata : AT(phys) { + robase = .; + PROVIDE(kern_robase = .); + *(.rodata .rodata.* .gnu.linkonce.r.*) + PROVIDE(kern_roend = .); + + } + + phys = ALIGN(4) - offset; + + /* Include debugging information in kernel memory */ + .stab : AT(phys) { + stabbase = .; + PROVIDE(kern_stabbase = .); + *(.stab); + PROVIDE(kern_stabend = .); + BYTE(0) /* Force the linker to allocate space + for this section */ + } + + phys = ALIGN(1) - offset; + + .stabstr : AT(phys) { + stabstrbase = .; + PROVIDE(kern_stabstrbase = .); + *(.stabstr); + PROVIDE(kern_stabstrend = .); + BYTE(0) /* Force the linker to allocate space + for this section */ + } + + phys = . - offset; + phys = ALIGN(0x1000) - offset; + + /* The data segment */ + .data ALIGN(0x1000) : AT (phys) { + database = .; + PROVIDE(kern_database = .); + *(.data) + PROVIDE(kern_dataend = .); + } + + phys = ALIGN(32) - offset; + + PROVIDE(edata = .); + + .bss : AT (phys) { + bssbase = .; + PROVIDE(kern_bssbase = .); + *(.bss) + PROVIDE(kern_bssend = .); + } + + PROVIDE(end = .); + phys = . - offset; + PROVIDE(load_end = phys); + + /DISCARD/ : { + *(.eh_frame .note.GNU-stack) + } +} diff --git a/kern/layout_image_file.py b/kern/layout_image_file.py new file mode 100755 index 0000000..17f7ec0 --- /dev/null +++ b/kern/layout_image_file.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +from __future__ import division; +import os; +import math; + + +disk_size = 5120000; + +stage1_size = os.path.getsize("boot/stage1"); +stage2_size = os.path.getsize("boot/stage2"); +pad_size = os.path.getsize("boot/pad"); +kernel_size = os.path.getsize("obj/kern/kernel"); + +print "stage1 size: %d" % stage1_size; +print "stage2 size: %d" % stage2_size; +print "pad size: %d" % pad_size; +print "kernel size: %d" % kernel_size; + +post_pad_size = disk_size - stage1_size - stage2_size - pad_size - kernel_size; + +print "will generate a post_pad of size: %d" % post_pad_size; + +dd_cmd = "dd if=/dev/zero of=boot/post_pad bs=%d count=1" % post_pad_size; + +os.system(dd_cmd); + +kernel_start = math.ceil((stage1_size + stage2_size + pad_size)/512); +kernel_len = math.ceil(kernel_size/512); + +print "GRUB load command: kernel %d+%d" % (kernel_start, kernel_len); diff --git a/kern/memmgr.c b/kern/memmgr.c new file mode 100644 index 0000000..c1b3853 --- /dev/null +++ b/kern/memmgr.c @@ -0,0 +1,460 @@ +#include +#include +#include +#include + +#define CELL_SIZE (PAGE_SIZE*sizeof(uint8_t)*8) +#define FRAME_STATUS_FREE 1 +#define FRAME_STATUS_USED 0 +#define CELL_STATUS_USED 0 +#define PT_ENTRIES 1024 +#define HIGHER_HALF_BASE 768 +#define INVALID_FRAME ((void*)0xFFFFFFFF) + +static kmemdesc* free_list_head; +static kmemdesc* alloc_list_head; +static kmemdesc* free_list_tail; +static kmemdesc* alloc_list_tail; + +static uint32_t* pde = (uint32_t*)INITIAL_PDE; + +int mem_available; + +void flush_tlb(); + +/* + * I can't honestly say if this is the dumbest thing I've done or one + * of my more clever tricks. This function is written to sling together + * some page tables for the kernel. The kernel is higher-half (actually + * it's linked at 0xc0100000) but I just didn't want to write this in + * assembly. Well...nothing in here involves a long jump or a far call + * or refers to global variables ("end" is linker-provided), so the + * code should be location-independent! So, we call this from within + * entry.S when we have nothing set up, and it still works! + * + * Probably shouldn't call this from within the kernel proper, though. + */ + +void init_paging() { + extern char end[]; + + int i; + uint32_t* initial_pde = (uint32_t*)INITIAL_PDE; + uint32_t* firstmeg_table = (uint32_t*)(INITIAL_PDE-PAGE_SIZE); + uint32_t* kernel_table = (uint32_t*)(INITIAL_PDE-(PAGE_SIZE*2)); + + //First, clear the tables + for (i=0; i<1024; ++i) { + *initial_pde=0; + *firstmeg_table = 0; + *kernel_table = 0; + } + + //Identity-page the first 4MB + for (i=0; i<1024; i++) { + uint32_t page_base = i*PAGE_SIZE; + page_base = page_base | PAGE_RW | PAGE_PRESENT; + firstmeg_table[i] = page_base; + } + + initial_pde[0] = ((uint32_t)firstmeg_table) | PAGE_RW | PAGE_PRESENT; + + //Now page in the kernel's space. + uint32_t kernel_page_count = (((uint32_t)end) - KERNBASE) / PAGE_SIZE; + if ((((uint32_t)end) - KERNBASE) % PAGE_SIZE > 0) ++kernel_page_count; + + /* NOTE: this should really map in only enough pages to fit the kernel + * but for now, this is mapping the entire lower 4MB to 0xc0000000 + * in addition to the identity paging above. Why? Because GRUB + * is putting the multiboot header struct in low memory but passing + * it a value that appears to be link-address relative (i.e. it's at + * 0xc00300000 or so) and so the area below the kernel must be mapped + * in, too. We're going to change link addresses before MAGUS is + * over, anyway, so for now we're mapping the same 4MB as both identity + * and into the link-address space of the kernel. */ + + for (i=0; i<1024/*kernel_page_count*/; ++i) { + //Load base is 1MB + uint32_t page_base = (i*PAGE_SIZE)/*+(1024*1024)*/; + page_base = page_base | PAGE_RW | PAGE_PRESENT; + //the link address base is not flat higher half but higher half + //plus 1MB + kernel_table[i] = page_base; + } + + initial_pde[768] = ((uint32_t)kernel_table) | PAGE_RW | PAGE_PRESENT; + + return; + +} + +void frame_allocator_init(multiboot_info_t* mbi, uint32_t kernel_base, uint32_t kernel_end) { + + int i; + int frames_allocated = 0; + for(i=0; i<(PHYS_MEM_MAP_SIZE); i++) { + phys_mem_map[i] = 0; + } + + //_kern_print("mmap_addr = 0x%x, mmap_length = 0x%x\n", + // (unsigned) (mbi->mmap_addr), (unsigned) mbi->mmap_length); + + multiboot_memory_map_t* mmap; + for (mmap = (multiboot_memory_map_t *) (mbi->mmap_addr); + (unsigned long) mmap < (mbi->mmap_addr) + mbi->mmap_length; + mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + + mmap->size + sizeof (mmap->size))) + { + //_kern_print(" size = 0x%x, base_addr = 0x%x%x," + // " length = 0x%x%x, type = 0x%x\n", + // (unsigned) mmap->size, + // mmap->addr_high, + // mmap->addr_low, + // mmap->len_high, + // mmap->len_low, + // (unsigned) mmap->type); + + if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) { + //Kindly note here that we will *NOT* be making use of the "high" + //fields here. The memory manager is current capped at 4GB, so + //we will deal only with the lower 32-bits of addresses. + + //The goal here is to flip on the bits for available RAM. After + //that, we will flip OFF the bits for the areas where the kernel + //was loaded and where the initial page tables sit. + + //The frame allocator is very happy to fail to mark partial + //frames as "not available." This is a good, safe starting point + //as it means that the only physical memory allocated out will + //"really be there." + + uint32_t base = mmap->addr_low; + uint32_t len = mmap->len_low; + + //First, advance up to the next page frame boundary. + if ((base % PAGE_SIZE) != 0) { + base = base + (PAGE_SIZE - (base % PAGE_SIZE)); + len = len - (PAGE_SIZE - (base % PAGE_SIZE)); + } + + //As long as there is another frame to allocate, allocate it. + while (!(len> bit) & FRAME_STATUS_FREE) { + break; + } else { + continue; + } + } + + //Once we get here, we know we must have an available frame + //As the mem_map entry was not full and so an empty bit was + //found somewhere. + + //Mark it as taken + mark_frame(((i*CELL_SIZE)+(bit*PAGE_SIZE)), FRAME_STATUS_USED); + + //return the address + uint32_t addr = (i*CELL_SIZE)+(bit*PAGE_SIZE); + return (void*)addr; + } + } + //Looks like everything was taken already + _kern_print("ERROR: Could not locate a frame to allocate\n"); + return (void*)INVALID_FRAME; +} + +void* get_page() { + + void* frame = get_frame(); + if (frame == INVALID_FRAME) { + _kern_print("Did not get a frame for the requested page!\n"); + return 0; + } + + //All page addresses returned from here should be higher-half + int pd_entry; + for (pd_entry = HIGHER_HALF_BASE; pd_entry < PT_ENTRIES; pd_entry++) { + if (pde[pd_entry] == 0) { + //Found a blank spot in the page directory, so we will + //create a table and use it. + uint32_t* new_table = (uint32_t*)get_frame(); + if (new_table == INVALID_FRAME) { + _kern_print("Could not allocate a new page table.\n"); + //TODO: RETURN INITIAL FRAME TO POOL TO PREVENT A LEAK + return 0; + } + //Blank the table + int i; + for (i=0; inext = 0; + free_list_head->size = mem_available; + free_list_head->data_ptr = ((char*)free_list_head)+sizeof(kmemdesc); + free_list_tail = free_list_head; + return; +} + +void* memmgr_allocate(unsigned int size) { + + if (size > (PAGE_SIZE - sizeof(kmemdesc))) { + _kern_print("Alloc of sizes greater than %d not supported!\n", + (PAGE_SIZE - sizeof(kmemdesc))); + return 0; + } + //Sweep the free list to find a fit. + kmemdesc* sweep = 0; + kmemdesc* prev = 0; + + if (free_list_head == 0) return 0; + + sweep = free_list_head; + while (sweep != free_list_tail) { + + //_kern_print("Comparing size %d against %d\n",sweep->size, size); + if (sweep->size == size) { + //_kern_print("Comparing size matched object at %x\n",sweep->data_ptr); + + //Found it. If it's the head, then the free list needs + //a new head. Otherwise, suture it out. + //a head == tail case cannot occur inside this loop + if (sweep == free_list_head) { + if (sweep == free_list_tail) { + free_list_head = 0; + free_list_tail = 0; + } else { + free_list_head = sweep->next; + } + } else { + prev->next = sweep->next; + } + + if (alloc_list_tail == 0) { + alloc_list_head = sweep; + alloc_list_tail = sweep; + } else { + alloc_list_tail->next = sweep; + alloc_list_tail = sweep; + } + return sweep->data_ptr; + } + + prev = sweep; + sweep = sweep->next; + } + + //We are here under the following conditions: + //head == tail == sweep , previous == 0 + //sweep == tail, previous != 0 + + //Before proceeding, see if we need to allocate more memory on + //the end. + if (free_list_tail->size < (size+sizeof(kmemdesc))) { + + kmemdesc* next_page = (kmemdesc*)get_page(); + if (!next_page) { + _kern_print("Could not satisfy: no pages available!\n"); + return 0; + } + + int mem_available = PAGE_SIZE; + mem_available -= sizeof(kmemdesc); + next_page->size = mem_available; + next_page->data_ptr = ((char*)next_page)+sizeof(kmemdesc); + + free_list_tail->next = next_page; + free_list_tail = next_page; + free_list_tail = free_list_head; + } + + sweep = (kmemdesc*)(((char*)free_list_tail)+sizeof(kmemdesc)+size); + sweep->data_ptr = ((char*)sweep) + sizeof(kmemdesc); + mem_available = mem_available - size - sizeof(kmemdesc); + sweep->size = mem_available; + sweep->next = 0; + + //free_list_tail is now a kmemdesc describing the allocated space + free_list_tail->size = size; + + if (alloc_list_tail != 0) { + alloc_list_tail->next = free_list_tail; + alloc_list_tail = free_list_tail; + } else { + alloc_list_head = free_list_tail; + alloc_list_tail = free_list_tail; + } + + //sweep is now set to be the new tail + if (free_list_head == free_list_tail) { + free_list_head = sweep; + free_list_tail = sweep; + } else { + prev->next = sweep; + free_list_tail = sweep; + } + + //having moved the former free list tail to the tail of the + //alloc list, return the alloc list tail data pointer + return alloc_list_tail->data_ptr; +} + +void memmgr_free(void* ptr) { + kmemdesc* sweep = 0; + kmemdesc* prev = 0; + + + if (alloc_list_head == 0) return; + + //First, locate the correct kmemdesc in the free list. Keep + //prev updated in case we need to suture the list. + + sweep = alloc_list_head; + while (sweep != alloc_list_tail) { + if (sweep->data_ptr == ptr) { + //Found it. Break the loop. + break; + } + prev = sweep; + sweep = sweep->next; + } + //Conditions that get us to this point: + //-- head == tail == sweep, prev == NULL, sweep data_ptr not checked + if (alloc_list_head == alloc_list_tail) { + if (sweep->data_ptr == ptr) { + alloc_list_head = 0; + alloc_list_tail = 0; + } else { + //ERROR! The only entry on the free list didn't + //have a data pointer that matched the given pointer + //_kern_print("Couldn't match the one item in the free list\n"); + return; + } + } + //-- head == sweep, prev == null, sweep data_ptr matched + else if (sweep == alloc_list_head) { + alloc_list_head = sweep->next; + } + //-- sweep == tail, prev != null, sweep data ptr not checked + else if (sweep == alloc_list_tail) { + if (sweep->data_ptr == ptr) { + //Matched at the tail of the list + alloc_list_tail = prev; + alloc_list_tail->next = 0; + } else { + //ERROR! Traversed the list without a match! + //_kern_print("Traversed the free list in vain\n"); + return; + } + } + //-- prev != null, sweep data_ptr matched + else { + sweep->next = prev->next; + } + + //At this point, sweep points to a kmemdesc that has been removed + //from the alloc list. We will place it at the head of the free + //list. + if (free_list_head == 0) { + free_list_head = sweep; + free_list_tail = sweep; + } else { + sweep->next = free_list_head; + free_list_head = sweep; + } + //_kern_print("Object at address %x freed\n", sweep->data_ptr); + //_kern_print("Free list head now size %d address %x\n", free_list_head->size, free_list_head->data_ptr); +} + +void flush_tlb() { + //Do the super-heavy full TLB flush. We should use invlpg in the + //future. + asm("movl %cr3, %eax; movl %eax, %cr3;"); +} diff --git a/kern/stringformat.c b/kern/stringformat.c new file mode 100644 index 0000000..2ef677c --- /dev/null +++ b/kern/stringformat.c @@ -0,0 +1,125 @@ +/* + * stringformat.c + * + * Created on: Aug 30, 2010 + * Author: rhett + */ + +#include +#include +#include + +void reverse(char* buffer) { + int buflen = 0; + int begin; + int end; + + begin = 0; + end = strlen(buffer)-1; + + if (end<0) return; + if (end == begin) return; + + while(begin < end) { + char swap; + swap = buffer[begin]; + buffer[begin] = buffer[end]; + buffer[end] = swap; + + begin++; + end--; + } + +} + +void print_int_dec(unsigned int i) { + int radix = 10; + //Buffer size is based on a guess at something larger than + //a maxint val + char buffer [(sizeof(int)*3)+1]; + int c=0; + do { + buffer[c++] = i % radix + '0'; + i /= radix; + } while (i>0); + + buffer[c] = '\0'; + reverse(buffer); + print_string(buffer); +} + +void print_int_hex(unsigned int i) { + int radix = 16; + //Buffer size is based on a guess at something larger than + //a maxint val + char buffer [(sizeof(int)*3)+1]; + int c=0; + do { + int hexit = i%radix; + if (hexit<10) { + buffer[c++] = hexit + '0'; + } else { + hexit = hexit-10; + buffer[c++] = hexit + 'a'; + } + i /= radix; + } while (i>0); + + buffer[c] = '\0'; + reverse(buffer); + print_string(buffer); + +} + +void print_substring(char* c) { + print_string(c); +} + +void print_escape_char(char c) { + switch(c) { + case '\n': + next_line(); + update_cursor(); + break; + default: + printchar(c); + } +} + +void _kern_print(const char* fmt_string, ...) { + int i; + int value; + char* s; + va_list args; + + va_start(args,fmt_string); + + for (i=0; fmt_string[i] != '\0'; i++) { + if (fmt_string[i] == '%') { + i++; + switch (fmt_string[i]) { + case 'd': + case 'u': + value = va_arg(args, int); + print_int_dec(value); + break; + case 's': + s = va_arg(args, char*); + print_substring(s); + break; + case 'x': + value = va_arg(args, int); + print_int_hex(value); + break; + case '%': + print_escape_char(fmt_string[i]); + break; + } + } else { + print_escape_char(fmt_string[i]); + } + } + update_cursor(); + + va_end(args); +} diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 0000000..d3818c8 --- /dev/null +++ b/lib/string.c @@ -0,0 +1,226 @@ +// Basic string routines. Not hardware optimized, but not shabby. + +#include + +int +strlen(const char *s) +{ + int n; + + for (n = 0; *s != '\0'; s++) + n++; + return n; +} + +int +strnlen(const char *s, size_t size) +{ + int n; + + for (n = 0; size > 0 && *s != '\0'; s++, size--) + n++; + return n; +} + +char * +strcpy(char *dst, const char *src) +{ + char *ret; + + ret = dst; + while ((*dst++ = *src++) != '\0') + /* do nothing */; + return ret; +} + +char * +strncpy(char *dst, const char *src, size_t size) { + size_t i; + char *ret; + + ret = dst; + for (i = 0; i < size; i++) { + *dst++ = *src; + // If strlen(src) < size, null-pad 'dst' out to 'size' chars + if (*src != '\0') + src++; + } + return ret; +} + +size_t +strlcpy(char *dst, const char *src, size_t size) +{ + char *dst_in; + + dst_in = dst; + if (size > 0) { + while (--size > 0 && *src != '\0') + *dst++ = *src++; + *dst = '\0'; + } + return dst - dst_in; +} + +int +strcmp(const char *p, const char *q) +{ + while (*p && *p == *q) + p++, q++; + return (int) ((unsigned char) *p - (unsigned char) *q); +} + +int +strncmp(const char *p, const char *q, size_t n) +{ + while (n > 0 && *p && *p == *q) + n--, p++, q++; + if (n == 0) + return 0; + else + return (int) ((unsigned char) *p - (unsigned char) *q); +} + +// Return a pointer to the first occurrence of 'c' in 's', +// or a null pointer if the string has no 'c'. +char * +strchr(const char *s, char c) +{ + for (; *s; s++) + if (*s == c) + return (char *) s; + return 0; +} + +// Return a pointer to the first occurrence of 'c' in 's', +// or a pointer to the string-ending null character if the string has no 'c'. +char * +strfind(const char *s, char c) +{ + for (; *s; s++) + if (*s == c) + break; + return (char *) s; +} + + +void * +memset(void *v, int c, size_t n) +{ + char *p; + int m; + + p = v; + m = n; + while (--m >= 0) + *p++ = c; + + return v; +} + +void * +memcpy(void *dst, const void *src, size_t n) +{ + const char *s; + char *d; + + s = src; + d = dst; + while (n-- > 0) + *d++ = *s++; + + return dst; +} + +void * +memmove(void *dst, const void *src, size_t n) +{ + const char *s; + char *d; + + s = src; + d = dst; + if (s < d && s + n > d) { + s += n; + d += n; + while (n-- > 0) + *--d = *--s; + } else + while (n-- > 0) + *d++ = *s++; + + return dst; +} + +int +memcmp(const void *v1, const void *v2, size_t n) +{ + const uint8_t *s1 = (const uint8_t *) v1; + const uint8_t *s2 = (const uint8_t *) v2; + + while (n-- > 0) { + if (*s1 != *s2) + return (int) *s1 - (int) *s2; + s1++, s2++; + } + + return 0; +} + +void * +memfind(const void *s, int c, size_t n) +{ + const void *ends = (const char *) s + n; + for (; s < ends; s++) + if (*(const unsigned char *) s == (unsigned char) c) + break; + return (void *) s; +} + +long +strtol(const char *s, char **endptr, int base) +{ + int neg = 0; + long val = 0; + + // gobble initial whitespace + while (*s == ' ' || *s == '\t') + s++; + + // plus/minus sign + if (*s == '+') + s++; + else if (*s == '-') + s++, neg = 1; + + // hex or octal base prefix + if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) + s += 2, base = 16; + else if (base == 0 && s[0] == '0') + s++, base = 8; + else if (base == 0) + base = 10; + + // digits + while (1) { + int dig; + + if (*s >= '0' && *s <= '9') + dig = *s - '0'; + else if (*s >= 'a' && *s <= 'z') + dig = *s - 'a' + 10; + else if (*s >= 'A' && *s <= 'Z') + dig = *s - 'A' + 10; + else + break; + if (dig >= base) + break; + s++, val = (val * base) + dig; + // we don't properly detect overflow! + } + + if (endptr) + *endptr = (char *) s; + return (neg ? -val : val); +} +