Commit initial

This commit is contained in:
Valentin Verdier 2020-04-17 17:44:23 +02:00
commit ea623dfa61
54 changed files with 7297 additions and 0 deletions

675
LICENCE Normal file
View File

@ -0,0 +1,675 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 <http://www.gnu.org/licenses/>.
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:
<program> Copyright (C) <year> <name of author>
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
<http://www.gnu.org/licenses/>.
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
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

14
boot/Makefile Normal file
View File

@ -0,0 +1,14 @@
.PHONY: bin clean
all: bin
bin:
make -C bootloader/
make -C kernloader/
-mkdir bin
mv bootloader/bootsect.bin bin/
mv kernloader/NOS-kernldr.bin bin/
clean:
make -C bootloader/ clean
make -C kernloader/ clean
-rm -rf bin/

8
boot/bootloader/Makefile Normal file
View File

@ -0,0 +1,8 @@
.PHONY: clean
all: bootsect.bin
bootsect.bin: bootsect.asm
nasm -f bin -o $@ $^
clean:
-rm -f bootsect.bin

View File

@ -0,0 +1,173 @@
; bootsect.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
; Code placé dans le MBR du disque
; ####################################
; BootLoader principal
; ####################################
; Le code est copié par le BIOS à l'adresse 0x7C00, soit à la base du segment 0x07C0
; 0x0:0x7C00 <=> 0x07C0:0000 0x07C0 x 0x10 = 0x7C00
; adresse physique = segment x 16 + offset
%define BOOT_SEG 0x07C0
%define KERN_LDR_SEG 0x07E0
%define KERN_LDR_LBA_ADDR 1
[BITS 16]
[ORG 0] ; Par rapport au segment 0x07C0
boot:
; On fait pointer les registres de segments sur le segment 0x07C0
; On ne fait rien pour CS car le bios s'en ait déjà occupé
mov ax, BOOT_SEG
mov ds, ax
mov ax, 0x9F00 ; On définit l'adresse de base de la pile à la base du segment 0x9F00, soit à l'adresse 0x9F000
mov ss, ax
mov sp, 0xFFF ; On définit le pointeur de pile à l'offset 0xFFFF ce qui correspond à l'adresse 0x9FFFF
mov [bootdisk], dl ; On sauvegarde le numéro de l'unité de disque utilisée par le BIOS
xor ax, ax ; int 0x13 fonction 0x00
int 0x13
call load_kern_ldr
jmp KERN_LDR_SEG:0x0000 ; On saute vers le code de kernLdr
; Fonction load_kern_ldr
; Charge kernLdr qui commence au 30ème secteur du disque
load_kern_ldr:
push ax
push ebx
push dx
push di
mov ax, 63 ; On charge 63 secteurs
mov dx, KERN_LDR_SEG
xor di, di
mov ebx, KERN_LDR_LBA_ADDR
call build_DAPS
call read_sector
pop di
pop dx
pop ebx
pop ax
ret
; Fonction print
; Params : pointeur sur str -> ds:si
print:
push ax
push bx
.top:
lodsb
cmp al, 0
jz .end
mov ah, 0x0E ; int 0x10 fonction 0x0E
mov bx, 0x07 ; attribut du caractère
int 0x10
jmp .top
.end:
pop bx
pop ax
ret
read_sector:
push ax
push dx
push si
xor ax, ax
add ax, 0 ; On met le flag de retenue à 0
mov si, DAPS
mov ah, 0x42
mov dl, [bootdisk]
int 0x13
jc .error
jmp .no_error
.error:
mov si, error_int13h
call print
call stop
.no_error:
pop si
pop dx
pop ax
ret
; Fonction build_DAPS
; Params: Nombre de secteur -> ax, Adresse LBA -> ebx, destination -> dx:di
build_DAPS:
mov [DAPS + 2], ax ; Nombre de secteurs
mov [DAPS + 4], di ; Offset du segment de destination
mov [DAPS + 6], dx ; Segment de destination
; adresse LBA
mov [DAPS + 8], ebx
xor ax, ax
mov [DAPS + 12], ax
mov [DAPS + 14], ax
ret
; Fonction Error
stop:
.loop:
hlt
jmp .loop
; Variables
; ############################################
DAPS: ; Disk Address Packet Structure
db 16 ; Taille de la structure
db 0 ; Toujours à 0
dw 0 ; Nombre de secteurs à transfèrer
dw 0 ; Offset du segment de buffer
dw 0 ; segment de buffer
dd 0 ; Adresse LBA de début
dd 0 ; Partie haute de l'adresse LBA (pour LBA 48 bits) non utilisée ici
error_int13h: db "BIOS 13H extension error !", 13, 10, 0
boot_disk: db 0
; ############################################
times 446-($-$$) db 144

33
boot/kernloader/Makefile Normal file
View File

@ -0,0 +1,33 @@
.PHONY: clean
CC=gcc
CFLAGS= -m32 -march=i486 -fno-stack-protector -fno-zero-initialized-in-bss
kernldr_obj_core=kernldr_init.o \
kernldr_main.o \
kernldr_print.o \
kernldr_utils.o \
asm_utils.o
kernldr_obj_drivers=drivers/ATA.o
all: NOS-kernldr.bin
NOS-kernldr.bin: kernldr_1 kernldr_2
dd if=kernldr_1 of=$@ bs=512 count=1
dd if=kernldr_2 of=$@ bs=512 seek=1
rm kernldr_1 kernldr_2
kernldr_1: startup.asm
nasm -f bin -o $@ $^
kernldr_2: $(kernldr_obj_core) $(kernldr_obj_drivers)
ld -melf_i386 --oformat=binary --Ttext=8000 --entry=kernldr_init $^ -o $@
clean:
-rm -f NOS-kernldr.bin $(kernldr_obj_core) $(kernldr_obj_drivers)
%.o:%.c
$(CC) $(CFLAGS) -c $^ -o $@
%.o:%.asm
nasm -f elf -o $@ $^

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,150 @@
/* ATA.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "../types.h"
#include "../kernLdr.h"
#include "ATA.h"
int ATA_getDevice(unsigned int ataNumber, unsigned int drive, T_ATA_device* dev) {
ataNumber &= 0x3;
drive &= 0x1;
print("-> Device : ATA %d ", DEFAULT_COLOR, ataNumber);
switch(ataNumber) {
case 0:
dev->ata_port = ATA_0_PORT;
dev->ata_ctrl_port = ATA_0_CTRL_PORT;
break;
case 1:
dev->ata_port = ATA_1_PORT;
dev->ata_ctrl_port = ATA_1_CTRL_PORT;
break;
case 2:
dev->ata_port = ATA_2_PORT;
dev->ata_ctrl_port = ATA_2_CTRL_PORT;
break;
case 3:
dev->ata_port = ATA_3_PORT;
dev->ata_ctrl_port = ATA_3_CTRL_PORT;
break;
}
if(drive) {
print("Slave drive\n", DEFAULT_COLOR);
dev->drive = ATA_SLAVE;
} else {
print("Master drive\n", DEFAULT_COLOR);
dev->drive = ATA_MASTER;
}
/* On vérifie si les ports I/O sont reliés à un contrôleur */
T_byte testByte;
_out(dev->ata_port + 2, 0x45);
_in(dev->ata_port + 2, &testByte);
if(testByte == 0x45) { /* Le contrôleur éxiste */
T_byte a, b, status;
/* On se prépare à utiliser la commande IDENTIFY pour connaitre le type de disque ATA */
_out(dev->ata_port + 6, ATA_CHS_MODE | dev->drive); /* On selectionne le disque */
delay(1000);
_out(dev->ata_port + 2, 0);
_out(dev->ata_port + 3, 0);
_out(dev->ata_port + 4, 0);
_out(dev->ata_port + 5, 0);
_out(dev->ata_port + 7, ATA_CMD_IDENTIFY); /* envoie de la commande */
_in(dev->ata_port + 7, &status);
if(status == 0) { /* Si le status est à 0, il n'y à pas de disque */
print("-> ERROR : Drive doesn't exist !\n", DEFAULT_COLOR);
return 0;
} else { /* Sinon on attend que le disque soit prêt */
while(status & 0x80) {
_in(dev->ata_port + 7, &status);
}
}
/* On récupère les octets de signature */
_in(dev->ata_port + 4, &a);
_in(dev->ata_port + 5, &b);
if((a == 0) && (b == 0)) { /* Disque dur ATA */
while(!(status & 0x08)) { /* On attend que le disque soit prêt pour la lecture des données d'identification */
_in(dev->ata_port + 7, &status);
}
unsigned int i;
T_word trash;
for(i = 0; i < 256; i++) { /* Pas besoin des info d'identification, mais on les transfert pour que le contrôleur termine la commande normalement */
_inw(dev->ata_port, &trash);
}
return 1;
} else {
print("-> ERROR : Drive is not ATA !\n", DEFAULT_COLOR);
}
} else {
print("-> ERROR : Controller doesn't exist !\n", DEFAULT_COLOR);
}
return 0;
}
void ATA_read(T_ATA_device dev, T_dword baseLBA, T_byte sectorCount, void* baddr) {
T_byte* buffer = baddr;
T_byte status = 0;
unsigned int i, j;
T_word word;
_out(dev.ata_port + 1, 0); /* Octet nul */
_out(dev.ata_port + 2, sectorCount);
_out(dev.ata_port + 3, (T_byte) (baseLBA & 0xFF)); /* 8 bits de poids faible de l'adresse LBA */
_out(dev.ata_port + 4, (T_byte) ((baseLBA >> 8) & 0xFF));
_out(dev.ata_port + 5, (T_byte) ((baseLBA >> 16) & 0xFF));
_out(dev.ata_port + 6, ATA_LBA_MODE | dev.drive | ((baseLBA >> 24) & 0x0F));
for(i = 0; i < 4; i++) {
_in(dev.ata_port + 7, &status);
}
_out(dev.ata_port + 7, ATA_CMD_READ);
/* On attend que le contrôleur soit prêt */
for(i = 0; i < sectorCount; i++) {
do {
_in(dev.ata_port + 7, &status);
}while((status & 0x80) || !(status & 0x08));
for(j = 0; j < 256; j++) {
_inw(dev.ata_port, &word);
buffer[(i * 512) + (j * 2)] = (T_byte) (word & 0xFF);
buffer[(i * 512) + (j * 2) + 1] = (T_byte) ((word >> 8) & 0xFF);
}
}
}

View File

@ -0,0 +1,57 @@
/* ATA.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef NOS_ATA_H
#define NOS_ATA_H
#include "../types.h"
#define ATA_LBA_MODE 0xE0
#define ATA_CHS_MODE 0xA0
#define ATA_MASTER 0x00
#define ATA_SLAVE 0x10
#define ATA_0_PORT 0x1F0
#define ATA_1_PORT 0x170
#define ATA_2_PORT 0x1E8
#define ATA_3_PORT 0x168
#define ATA_0_CTRL_PORT 0x3F6
#define ATA_1_CTRL_PORT 0x376
#define ATA_2_CTRL_PORT 0x3E6
#define ATA_3_CTRL_PORT 0x366
#define ATA_CMD_READ 0x20
#define ATA_CMD_IDENTIFY 0xEC
typedef struct {
T_word ata_port;
T_word ata_ctrl_port;
T_byte drive;
} T_ATA_device;
int ata_select_drive(unsigned int, unsigned int, T_ATA_device*);
void ata_read(T_ATA_device, T_dword, T_byte, void*);
#endif

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

77
boot/kernloader/io.asm Normal file
View File

@ -0,0 +1,77 @@
; io_port.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
global _out, _in, _outw, _inw, _outdw, _indw
_out:
push eax
push edx
mov dx, [esp+12]
mov al, [esp+16]
out dx, al
pop edx
pop eax
ret
_in:
push edx
xor eax, eax
mov dx, [esp+8]
in al, dx
pop edx
ret
_outw:
push eax
push edx
mov dx, [esp+12]
mov ax, [esp+16]
out dx, ax
pop edx
pop eax
ret
_inw:
push edx
xor eax, eax
mov dx, [esp+8]
in ax, dx
pop edx
ret
_outdw:
push eax
push edx
mov dx, [esp+12]
mov eax, [esp+16]
out dx, eax
pop edx
pop eax
ret
_indw:
push edx
mov dx, [esp+8]
in eax, dx
pop edx
ret

209
boot/kernloader/kernldr.h Normal file
View File

@ -0,0 +1,209 @@
/* kernLdr.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef NOS_KERNLDR_H
#define NOS_KERNLDR_H
#include <stdarg.h>
#include "types.h"
#include "drivers/ATA.h"
/* Structure de passage d'arguments */
typedef struct {
T_dword low_addr;
T_dword high_addr;
T_dword low_size;
T_dword high_size;
T_dword type;
T_dword unused;
}__attribute__((packed)) T_mmap_entry;
#define BOOT_ARGS_ADDR 0x1000
typedef struct {
T_byte cursor_x;
T_byte cursor_y;
T_byte mmap_entry_count;
T_mmap_entry mmap[30]; /* Taille fixée arbitrairement */
}__attribute__((packed)) T_boot_args;
#define KERNEL_ARGS_ADDR 0x1400
typedef struct {
T_byte cursor_x;
T_byte cursor_x;
T_dword pmem_size;
T_byte mmap_entry_count;
T_dword init_proc_addr;
T_dword init_proc_size;
T_mmap_entry* mmap;
}__attribute__((packed)) T_kernel_args;
/* ############################## */
/* ######### Affichage ########## */
#define VIDEO_ADDR 0xB8000
#define VIDEO_SIZE 0xFA0
#define VIDEO_END_OFFSET 0xB8FA0
#define DEFAULT_COLOR 0x0F
char pos_x;
char pos_y;
int enable_cursor;
void scrollup(int);
void write_char(char, char);
void print(char*, ...);
void clear();
void show_cursor();
void hide_cursor();
void move_cursor(char, char);
/* ############################## */
/* ####### Fonctions I/O ######## */
void _out(T_word, T_byte);
T_byte _in(T_word);
void _outw(T_word, T_word);
T_word _inw(T_word);
void _outdw(T_word, T_dword);
T_dword _indw(T_word);
/* ############################## */
/* ########### Divers ########### */
void memcopy(char*, char*, unsigned int);
int strcmp(char*, char*);
void int_to_str(unsigned int, char*, int);
unsigned int expo(int, int);
void delay(unsigned int);
/* ############################## */
/* ###### Structure MBR et Table de partition */
#define PARTITION_BOOT_SIGN 0x80
#define VFAT32_PARTITION_ID 0x07
typedef struct {
T_byte bootsign;
T_byte chs_start_head;
T_byte chs_start_sector:6;
T_word chs_start_cylinder:10;
T_byte fs_id;
T_byte chs_end_head;
T_byte chs_end_sector:6;
T_word chs_end_cylinder:10;
T_dword lba_start_sector;
T_dword lba_sector_count;
}__attribute__((packed)) T_partition_entry;
#define MBR_BOOT_SIGN 0xAA55
typedef struct {
T_byte bootcode[446];
T_partition_entry pt[4];
T_word bootsign;
}__attribute__((packed)) T_MBR;
/* ########################################## */
/* ###### Fat32 structure ####### */
typedef struct {
T_byte jumpcode[3];
char OEM_identifier[8];
T_word byte_per_sect;
T_byte sect_per_cluster;
T_word reserved_sect_count;
T_byte fat_count;
T_word unused_1;
T_word total_sect_count_16;
T_byte media_desc_type;
T_word unused_2;
T_word sect_per_track;
T_word head_count;
T_dword hidden_sect_lba;
T_dword total_sect_count_32;
T_dword sect_per_fat;
T_word fat_info;
T_word fat_ver;
T_dword rootdir_first_cluster;
T_word fs_info_sect;
T_word dbr_cpy_sect;
T_byte reserved[12];
T_byte bios_disk_id;
T_byte reserved_NT; /* Windows NT flags */
T_byte sign;
T_dword serial_num;
char label[11];
char identifier_str[8];
T_byte bootcode[420];
T_word bootsign;
}__attribute__((packed)) T_FAT32_dbr;
#define FAT32_DIR_ENTRY_SIZE 32
typedef struct {
T_byte entry_num;
char char_part1[10];
T_byte attribute;
T_byte lfn_entry_type;
T_byte checksum;
char char_part2[12];
T_word null;
char char_part3[4];
}__attribute__((packed)) T_FAT32_lfn_entry;
typedef struct {
char filename[8];
char extention[3];
T_byte attribute;
T_byte reserved; /* Windows NT */
T_byte creation_time_1;
T_word creation_time_2;
T_word creation_date;
T_word last_acces;
T_word high_first_cluster;
T_word modif_time;
T_word modif_date;
T_word low_first_cluster;
T_dword file_size;
}__attribute__((packed)) T_FAT32_std_entry;
typedef struct {
T_ATA_device device;
T_FAT32_dbr dbr;
/* Buffer de lecture */
unsigned int loaded_fat_sect;
T_dword fat_sect_buf[128]; /* 512 octets */
T_dword* dir_cluster_buf;
/* Adresses LBA des structures sur le disque */
T_dword LBA_dbr;
T_dword LBA_fat;
T_dword LBA_first_sata_sect; /* cluster 2 */
} T_FAT32_partition;
#endif

View File

@ -0,0 +1,77 @@
; kernLdr_init.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
global kernLdr_init
extern kernLdr_main
kernldr_init:
; On initialise tous les segments de données pour le mode protégé
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; Segment de pile
mov ax, 0x18
mov ss, ax
mov esp, 0xA0000 ; Pile à 0xA0000
push eax
; on vérifie que la ligne a20 est activée
call check_a20_line
cmp eax, 0
je .next ; Si activée, on passe
call enable_a20_line ; Sinon on l'active
.next:
; On appel le fonction principale qui :
; - calcul la taille de la mémoire utilisable à partir de la liste de plage mémoire communiquée par kernldr_1
; - charge la partition FAT32 définit
; - charge KERNEL32 à l'adresse 0x100000, et init à l'adresse 0x28000 depuis le répertoire /boot
; - construit la structure de passage d'argument
call kernldr_main
; On saute vers le kernel
mov esp, 0xA0000
jmp 0x08:0x100000
; Retourne 0xFFFFFFFF si déactivée, 0 si activée
check_a20_line:
mov dword [0x500], 0
mov dword [0x100500], 0xFFFFFFFF
mov eax, [0x500]
ret
enable_a20_line:
push eax
in al, 0x92
test al, 0x02
jnz .end
or al, 0x02
and al, 0xFE
out 0x92, al
.end:
pop eax
ret

View File

@ -0,0 +1,268 @@
/* kernLdr_main.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "types.h"
#include "kernLdr.h"
#include "drivers/ATA.h"
static void detectMemory(T_bootArgs* bargs, T_kernelArgs* kargs)
{
T_dword* test1 = (T_dword*) 0x500;
T_dword* test2 = (T_dword*) 0x100500;
*test1 = 0;
*test2 = 0xFFFFFFFF;
if(*test1 == 0) {
print("-> A20 line enabled\n", DEFAULT_COLOR);
} else {
print("-> A20 line disabled\n", DEFAULT_COLOR);
asm("hlt");
}
unsigned int i;
kargs->phyMemSize = 0;
for(i = 0; i < bargs->memListEntryCount; i++) {
//print("-> (0x%x - 0x%x) type=%d\n", DEFAULT_COLOR, bargs->memMap[i].baseAddr_1, bargs->memMap[i].baseAddr_1 + bargs->memMap[i].size_1, bargs->memMap[i].type);
if(bargs->memMap[i].type == 1) {
kargs->phyMemSize += bargs->memMap[i].size_1;
}
}
print("-> Physical memory size : %d Ko\n", DEFAULT_COLOR, (kargs->phyMemSize / 1024));
}
static int getPartition(unsigned int partNumber, T_ATA_device device, T_FAT32_partition* part)
{
partNumber &= 0x3;
print("-> Partition : %d\n", DEFAULT_COLOR, partNumber);
/* On récupère le MBR */
T_mbr* mbr = (T_mbr*) 0x15000;
ATA_read(device, 0, 1, mbr);
if(mbr->partitionTable[partNumber].fileSytemID == VFAT32_PARTITION_ID) {
part->device = device;
part->LBA_dbr = mbr->partitionTable[partNumber].startingLBA;
// On charge le Dos Boot Record de la partition
ATA_read(part->device, part->LBA_dbr, 1, (void*) &part->dbr);
// On calcul l'adresse de la FAT ainsi que l'adresse du premier cluster
if(part->dbr.fatInfo >> 7) {
unsigned int activeFAT = part->dbr.fatInfo & 0x0F;
part->LBA_fileAllocationTable = part->LBA_dbr + part->dbr.reservedSectors + (activeFAT * part->dbr.sectorsPerFat);
} else {
part->LBA_fileAllocationTable = part->LBA_dbr + part->dbr.reservedSectors;
}
ATA_read(part->device, part->LBA_fileAllocationTable, 1, part->fatSectorBuffer);
part->LBA_firstDataSector = part->LBA_dbr + part->dbr.reservedSectors + (part->dbr.fatNumber * part->dbr.sectorsPerFat);
return 1;
} else {
print("-> ERROR : The partition is not VFAT32 type\n", DEFAULT_COLOR);
return 0;
}
}
static T_dword getFat32ClusterLBA(unsigned int clusterNum, T_FAT32_partition* part) {
return ((clusterNum - 2) * part->dbr.sectorsPerCluster) + part->LBA_firstDataSector;
}
static unsigned int getFat32NextClusterNum(unsigned int clusterNum, T_FAT32_partition* part) {
unsigned int nextCluster;
unsigned int sector = part->LBA_fileAllocationTable + ((clusterNum * 4) / 512);
if(sector != part->loadedFatSector) {
ATA_read(part->device, sector, 1, part->fatSectorBuffer);
part->loadedFatSector = sector;
}
nextCluster = part->fatSectorBuffer[((clusterNum * 4) % 512) / 4];
if(nextCluster >= 0x0FFFFFF8) {
return 0;
} else if(nextCluster == 0x0FFFFFF7) {
print("-> ERROR : A BAD CLUSTER WAS FOUND (PREVIOUS CLUSTER = %d)\n", DEFAULT_COLOR, clusterNum);
asm("hlt");
} else {
return nextCluster;
}
}
static unsigned int loadFile(char *target, T_dword destAddr, T_FAT32_partition* part)
{
print("-> Loading '%s'\n", DEFAULT_COLOR, target);
unsigned int currentCluster = part->dbr.rootDirFirstCluster; /* Numéro d'un cluster du répertoire courant */
T_FAT32_stdEntry* entry = (T_FAT32_stdEntry*) part->dirClusterBuffer; /* Buffer utilisé pour stocker un cluster du répertoire courant */
ATA_read(part->device, getFat32ClusterLBA(currentCluster, part), part->dbr.sectorsPerCluster, entry);
unsigned int i = 0;
while(target[i] != 0) {
char entity[256];
unsigned int j;
char isDirectory = 0, isFile = 0;
for(j = 0; target[i] != 0; i++, j++) {
if(j >= 256) {
print("-> ERROR : INVALID TARGET '%s'\n", DEFAULT_COLOR, target);
return 0;
} else if(target[i] == '/') {
isDirectory = 1;
i++;
break;
} else {
entity[j] = target[i];
}
}
/* On ferme la chaine de caractères */
entity[j] = '\0';
if(!isDirectory) {
isFile = 1;
}
/* Chargement */
if(entity[0] != '\0') {
unsigned int lfnAvailable = 0;
unsigned int stopLoop = 0;
while(currentCluster && (!stopLoop)) {
unsigned int k;
char *entityLFN = (char*) 0x4200;
for(k = 0; k < ((part->dbr.sectorsPerCluster * 512) / FAT32_DIR_ENTRY_SIZE); k++) {
if((entry[k].fileName[0] != 0) && (entry[k].fileName[0] != 0xE5)) { /* Si l'entrée est valide */
if(entry[k].attribute == 0x0F) { /* Si on trouve une entrée LFN */
T_FAT32_lfnEntry* lfnEntry = (T_FAT32_lfnEntry*) &entry[k];
lfnAvailable = 1;
/* On récupère les parties de nom */
unsigned int l;
unsigned int offset = ((lfnEntry->entryNum & 0x3F) - 1) * 13; /* offset de la section du nom dans la chaine finale */
for(l = 0; l < 13; l++) {
if(l < 5) {
entityLFN[offset + l] = lfnEntry->char_part1[l * 2];
} else if(l < 11) {
entityLFN[offset + l] = lfnEntry->char_part2[(l - 5) * 2];
} else if(l < 13) {
entityLFN[offset + l] = lfnEntry->char_part3[(l - 11) * 2];
}
}
} else { /* Sinon c'est une entrée standard */
char *entityNameCmp;
if(lfnAvailable) {
entityNameCmp = entityLFN;
lfnAvailable = 0;
} else {
entityNameCmp = (char*) 0x4400;
unsigned int l, m;
for(l = 0; l < 8 && entry[k].fileName[l] != ' '; l++) {
entityNameCmp[l] = entry[k].fileName[l];
}
entityNameCmp[l] = '.';
for(m = 0; m < 3 && entry[k].extention[m] != ' '; m++, l++) {
entityNameCmp[l] = entry[k].extention[m];
}
entityNameCmp[l] = '\0';
}
if(isDirectory) {
if((strcmp(entity, entityNameCmp)) && (entry[k].attribute & 0x10)) {
currentCluster = ((T_dword) entry[k].firstCluster_high << 16) | entry[k].firstCluster_low;
ATA_read(part->device, getFat32ClusterLBA(currentCluster, part), part->dbr.sectorsPerCluster, part->dirClusterBuffer);
stopLoop = 1;
break;
}
} else if(isFile) {
if((strcmp(entity, entityNameCmp)) && (entry[k].attribute & 0x20)) {
unsigned int cluster = ((T_dword) entry[k].firstCluster_high << 16) | entry[k].firstCluster_low;
unsigned int size = 0;
while(cluster) {
ATA_read(part->device, getFat32ClusterLBA(cluster, part), part->dbr.sectorsPerCluster, (void*) destAddr);
destAddr += (part->dbr.sectorsPerCluster * 512);
cluster = getFat32NextClusterNum(cluster, part);
size += (part->dbr.sectorsPerCluster * 512);
}
return size;
}
}
}
}
}
if(!stopLoop) {
currentCluster = getFat32NextClusterNum(currentCluster, part);
}
}
if(!stopLoop) {
print("-> ERROR : UNABLE TO FIND '%s' FOR '%s'\n", DEFAULT_COLOR, entity, target);
return 0;
}
}
}
}
void kernLdr_main()
{
/* On définit les adresse des structure en mémoire */
T_bootArgs* bootArgs = (T_bootArgs*) BOOT_ARGS_ADDR;
T_kernelArgs* kernelArgs = (T_kernelArgs*) KERNEL_ARGS_ADDR;
/* Position du curseur */
posX = bootArgs->cursor_X;
posY = bootArgs->cursor_Y;
showCursor();
print("Welcome to NutsOS KernelLoader v1.0.0\n", DEFAULT_COLOR);
/* On affiche la memory map */
print("[MEMORY DETECTION]\n", 0x02);
detectMemory(bootArgs, kernelArgs);
T_ATA_device bootDevice;
T_FAT32_partition bootPartition;
bootPartition.loadedFatSector = 0;
bootPartition.dirClusterBuffer = (T_dword*) 0x2000;
print("[FILES LOADING]\n", 0x02);
if(!ATA_getDevice(0, 0, &bootDevice)) {
asm("hlt");
}
if(!getPartition(0, bootDevice, &bootPartition)) {
asm("hlt");
}
if(loadFile("/boot/NOS-kernel32.bin", 0x100000, &bootPartition)) { /* On charge KERNEL32 à la bonne adresse et on passe les arguments */
kernelArgs->initProcessAddr = 0x28000;
kernelArgs->initProcessSize = loadFile("/boot/init", kernelArgs->initProcessAddr, &bootPartition);
if(!kernelArgs->initProcessSize) {
asm("hlt");
} else if(kernelArgs->initProcessSize > 819200) {
print("ERROR : INIT PROCESS IS TOO LARGE\n", DEFAULT_COLOR);
asm("hlt");
} else {
print("[BOOTING]\n", 0x02);
kernelArgs->cursor_X = posX;
kernelArgs->cursor_Y = posY;
kernelArgs->memListEntryCount = bootArgs->memListEntryCount;
kernelArgs->memMap = bootArgs->memMap;
}
} else {
asm("hlt");
}
}

View File

@ -0,0 +1,187 @@
/* kernLdr_print.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "kernLdr.h"
#define DEFAULT_COLOR 0x0F
char color = (char) DEFAULT_COLOR;
void scrollup(int lines) {
char* vid;
char* offset;
for(vid = (char*) VIDEO_ADDR; vid < (char*) VIDEO_END_OFFSET; vid += 2) {
offset = (char*) (vid + lines * 160);
if(offset < (char*) VIDEO_END_OFFSET) {
vid[0] = offset[0];
vid[1] = offset[1];
} else {
vid[0] = 0;
vid[1] = color;
}
}
pos_y -= lines;
if(pos_y < 0) {
pos_y = 0;
}
}
void write_char(char c_ascii) {
char* vid;
vid = (char*) (VIDEO_ADDR + pos_y * 160 + pos_x * 2);
switch(c_ascii) {
case 0:
break;
case 8:
vid[-2] = 0;
vid[-1] = color;
pos_x--;
break;
case 10: // Ligne suivante
pos_x = 0;
pos_y++;
break;
case 13: // Retour debut de ligne
pos_x = 0;
break;
default:
vid[0] = c_ascii;
vid[1] = color;
pos_x++;
break;
}
if(pos_x > 79) {
pos_x = 0;
pos_y++;
}
if(pos_y > 24) {
scrollup(1);
}
if(posX < 0) {
posX = 79;
posY--;
}
if(posY < 0) {
posX = 0;
posY = 0;
}
if(enable_cursor) {
move_cursor(pos_x, pos_y);
}
}
static void print_dec(unsigned int a, char color) {
char str[11];
int_to_str(a, str, 10);
unsigned int i;
for(i = 0; str[i] != 0; i++) {
write_char(str[i]);
}
}
static void print_hex(unsigned int a, char color) {
char str[9];
int_to_str(a, str, 16);
unsigned int i;
for(i = 0; str[i] != 0; i++) {
write_char(str[i]);
}
}
static void print_bin(unsigned int a, char color) {
char str[33];
int_to_str(a, str, 2);
unsigned int i;
for(i = 0; str[i] != 0; i++) {
write_char(str[i]);
}
}
void print(char *str, ...) {
va_list arg;
va_start(arg, str);
while(str[0] != 0) {
if(str[0] == '%') {
if(str[1] == 'd') {
print_dec(va_arg(arg, T_dword), color);
str += 2;
} else if(str[1] == 'x') {
print_hex(va_arg(arg, T_dword), color);
str += 2;
} else if(str[1] == 'b') {
print_bin(va_arg(arg, T_dword), color);
str += 2;
} else if(str[1] == 's') {
print(va_arg(arg, char*), color);
str += 2;
} else if(str[1] == 'C') {
} else {
write_char(*str, color);
str++;
}
} else {
write_char(*str, color);
str++;
}
}
va_end(arg);
}
void clear() {
char* vid;
for(vid = (char*) VIDEO_ADDR; vid <= (char*) VIDEO_END_OFFSET; vid += 2) {
vid[0] = 0;
vid[1] = ;
}
}
void show_cursor() {
enable_cursor = 1;
move_cursor(pos_x, pos_y);
}
void hide_cursor() {
enable_cursor = 0;
move_cursor(-1, -1);
}
void move_cursor(char x, char y) {
T_word c_pos = (T_word) (y * 80 + x);
_out(0x3D4, 0x0F);
_out(0x3D5, (T_byte) cpos);
_out(0x3D4, 0x0E);
_out(0x3D5, (T_byte) (cpos >> 8));
}

View File

@ -0,0 +1,92 @@
/* kernLdr_utils.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "drivers/ATA.h"
#include "kernLdr.h"
void memcopy(char *src, char *dst, unsigned int n) {
unsigned int i;
for(i = 0; i < n; i++) {
dst[i] = src[i];
}
}
int strcmp(char *str1, char *str2) {
int length1 = 0;
int length2 = 0;
int i;
while(str1[length1] != 0) {
length1++;
}
while(str2[length2] != 0) {
length2++;
}
if(length1 == length2) {
for(i = 0; i < length1; i++) {
if(str1[i] != str2[i]) {
return 0;
}
}
} else {
return 0;
}
return 1;
}
void intToStr(T_dword num, char *str, int base) {
const char decimal[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
int i, j, a;
int length;
int tmp = 0;
int counter = 0;
for(i = 0; i < 10; i++) {
if((num / (expo(base, i))) < base) {
length = i;
break;
}
}
j = length;
for(i = 0; i <= length; i++) {
a = num / expo(base, j);
str[counter] = decimal[a - (base * tmp)];
tmp = a;
counter++;
j--;
}
str[counter] = 0;
}
T_dword expo(int x, int y) {
return (y > 0) ? (x * expo(x, y-1)) : 1;
}
void delay(unsigned int n) {
unsigned int i;
for(i = 0; i < n; i++);
}

197
boot/kernloader/startup.asm Normal file
View File

@ -0,0 +1,197 @@
; startup.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
%define ARGS_SEG 0x100
%define KERN_LDR_SEG 0x07E0
%define ARGS_CURSOR_POSX_OFFSET 0
%define ARGS_CURSOR_POSY_OFFSET 1
%define ARGS_MEMMAP_ENTRY_COUNT_OFFSET 2
%define ARGS_MEMMAP_OFFSET 3
[BITS 16]
[ORG 0] ; Par rapport au segment 0x07E0
startup:
mov ax, KERN_LDR_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, 0x500
mov ss, ax
mov sp, 0xFF0
mov si, start_msg
call print
call build_args
; On passe en mode protégé
cli
lgdt [gdtreg]
mov eax, cr0
or eax, 1
mov cr0, eax
; Segment 0x07E0 en mode réel = adresse physique 0x7E00
; Le seconde partie du code de kernLdr est situé 512 octets plus loin
; On saute dans le seconde partie de kernLdr et en même temps on réinitialise le segment de code
jmp 0x08:0x8000
build_args:
push eax
push ebx
push ecx
push edx
push es
push di
mov ax, ARGS_SEG
mov es, ax
mov ah, 3
xor bh, bh
int 0x10 ; On demande la position du curseur
; On passe la position du curseur en argument
mov [es:ARGS_CURSOR_POSX_OFFSET], dl
mov [es:ARGS_CURSOR_POSY_OFFSET], dh
; Memory map initialisation
mov di, ARGS_MEMMAP_OFFSET
mov eax, 0xE820
xor ebx, ebx
mov ecx, 24
mov edx, 0x534D4150
int 0x15
jc error
cmp eax, 0x534D4150
jne error
cmp ebx, 0
je error
xor bp, bp
; récupération des entrées de la Memory Map
.loop:
inc bp
add di, 24
mov eax, 0xE820
mov ecx, 24
int 0x15
jc .end_loop
cmp ebx, 0
jne .loop
.end_loop:
mov ax, bp
mov [es:ARGS_MEMMAP_ENTRY_COUNT_OFFSET], al
pop di
pop es
pop edx
pop ecx
pop ebx
pop eax
ret
; Fonction print
; Params : pointeur sur str -> ds:si
print:
push ax
push bx
.top:
lodsb
cmp al, 0
jz .end
mov ah, 0x0E ; int 0x10 fonction 0x0E
mov bx, 0x07 ; attribut du caractère
int 0x10
jmp .top
.end:
pop bx
pop ax
ret
error:
mov si, error_msg
call print
.loop:
hlt
jmp .loop
; Variables
; #################################
; kernLdrContext:
; - cursorX
; - cursorY
; - biosBootDisk
; - listSize
; - memStructureList
start_msg: db "Starting NutsOS KernelLoader...", 13, 10, 0
error_msg: db "Fatal Error !", 0
gdt_reg:
dw (gdt_end - gdt_start) ; taille de la gdt
dd (KERN_LDR_SEG << 4) + gdt_start ; adresse de base dur 32 bits
gdt_start:
.null_seg: ; descripteur nul
times 8 db 0
.code_seg: ; Segment de code [0x0 - 0xFFFFFFFF]
dw 0xFFFF ; limite0_15
dw 0x0000 ; base0_15
db 0x00 ; base16_23
db 0x9A ; acces
db 0xCF ; Flags, limite16_19
db 0x00 ; base24_31
.data_seg: ; Segment de données [0x0 - 0xFFFFFFFF]
dw 0xFFFF ; limite0_15
dw 0x0000 ; base0_15
db 0x00 ; base16_23
db 0x92 ; acces
db 0xCF ; Flags, limite16_19
db 0x00 ; base24_31
.stack_seg: ; Segment de pile [... - 0x9F000]
dw 0x0000 ; limite0_15, (0x009F + intel vt-x = O_o bug)
dw 0x0000 ; base0_15
db 0x00 ; base16_23
db 0x96 ; acces
db 0xC0 ; Flags, limite16_19
db 0x00 ; base24_31
gdt_end:
; #################################
times 512-($-$$) db 144

31
boot/kernloader/types.h Normal file
View File

@ -0,0 +1,31 @@
/* types.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef NOS_TYPES_H
#define NOS_TYPES_H
typedef unsigned char T_byte;
typedef unsigned short T_word;
typedef unsigned int T_dword;
#endif

39
kernel/Makefile Normal file
View File

@ -0,0 +1,39 @@
.PHONY: clean
.SUFFIXES:
include_dir=include/
CC=gcc
CFLAGS= -m32 -march=i486 -fno-stack-protector -fno-zero-initialized-in-bss -I $(include_dir)
kobj_core=src/main.o \
src/print.o \
src/memory.o \
src/interrupt.o \
src/utils.o \
src/systemCall.o \
src/process.o \
src/ipc.o \
src/scheduler.o \
src/elf_loader.o \
src/signal.o
kobj_asm_x86=src/asm/isr.o \
src/asm/asm_utils.o \
src/asm/io_port.o \
src/asm/sched.o
all: NOS-kernel32.bin
NOS-kernel32.bin: $(kobj_core) $(kobj_asm_x86)
ld -melf_i386 --oformat=binary --Ttext=100000 --entry=main $^ -o $@
%.o: %.asm
nasm -f elf -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c $^ -o $@
clean:
-rm -f $(kobj_core) $(kobj_asm_x86)
-rm -f NOS-kernel32.bin

50
kernel/include/args.h Normal file
View File

@ -0,0 +1,50 @@
/* args.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef ARGS_H
#define ARGS_H
#include "types.h"
/* Strcutres de récupération de contexte */
typedef struct {
T_dword baseAddr_1;
T_dword baseAddr_2;
T_dword size_1;
T_dword size_2;
T_dword type;
T_dword unused;
}__attribute__((packed)) T_memMapEntry;
typedef struct {
T_byte cursor_X;
T_byte cursor_Y;
T_dword phyMemSize;
T_byte memListEntryNumber;
T_dword initProcessAddr;
T_dword initProcessSize;
T_memMapEntry* memMap;
}__attribute__((packed)) T_kernelArgs;
T_kernelArgs* args;
#endif

51
kernel/include/asm_x86.h Normal file
View File

@ -0,0 +1,51 @@
/* asm_x86.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef ASM_X86_H
#define ASM_X86_H
#include "types.h"
#include "memory.h"
#include "interrupt.h"
void _loadGdtR(T_gdt*);
void _loadTaskRegister();
void _loadIdtR(T_idt*);
void _clearInterrupt();
void _startInterrupt();
void _out(T_word, T_byte);
T_byte _in(T_word);
void _outw(T_word, T_word);
T_word _inw(T_word);
void _outdw(T_word, T_dword);
T_dword _indw(T_word);
void _enablePaging();
void _emptyTLB();
void _loadCr3(T_dword);
T_dword _readCr3();
T_dword _readCr2();
T_dword _saveEflags();
T_dword _restoreEflags(T_dword);
T_dword _atomicTestAndSet(unsigned int*);
T_dword _getStackFrameAddr(unsigned int);
#endif

View File

@ -0,0 +1,32 @@
/* elf_loader.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef ELF_LOADER_H
#define ELF_LOADER_H
#include "types.h"
#include "utils.h"
int ELF32_checkFile(void*);
unsigned int ELF32_load(void*, T_list*);
#endif

View File

@ -0,0 +1,99 @@
/* interrupt.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef INTERRUPT_H
#define INTERRUPT_H
#include "types.h"
/* === Configuration du PIC 8259A === */
#define PIC_MASTER_CMD_REG 0x20
#define PIC_MASTER_DATA_REG 0x21
#define PIC_MASTER_IDT_OFFSET 0x20
#define PIC_SLAVE_CMD_REG 0xA0
#define PIC_SLAVE_DATA_REG 0xA1
#define PIC_SLAVE_IDT_OFFSET 0x28
#define PIC_EOI 0x20
void PIC_init();
void PIC_maskIRQ(T_byte);
void PIC_sendEOI();
/* ======================================================================== */
/* ===== Manipulation de l'IDT ===== */
#define IDT_BASE 0x200800
#define INT_DESC_SIZE 8
#define IDT_SIZE 256
#define DIVIDE_BY_0_INT 0
#define NMI_INT 2
#define BREAKPOINT_INT 3
#define OVERFLOW_INT 4
#define INVALID_TSS_INT 10
#define SEG_FAULT_INT 11
#define STACK_SEG_FAULT_INT 12
#define GP_FAULT_INT 13
#define PAGE_FAULT_INT 14
#define TIMER_INT 32
#define KB_INT 33
#define SYS_CALL_INT 64
typedef struct {
T_word offset0_15;
T_word segment;
T_word type;
T_word offset16_31;
}__attribute__((packed)) T_IDT_desc;
typedef struct {
T_word limite;
T_dword base;
}__attribute__((packed)) T_IDT_reg;
void IDT_init();
void IDT_createDesc(T_dword, T_word, T_word, unsigned int);
/* ======================================================================== */
/* Routine d'interruption en assembleur (redirection vers routines en C) */
void _defaultInt();
void _SEG_fault();
void _GP_fault();
void _page_fault();
void _clockInterrupt();
void _syscall();
/* ======================================================================== */
#endif

31
kernel/include/ipc.h Normal file
View File

@ -0,0 +1,31 @@
/* ipc.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef IPC_H
#define IPC_H
#include "types.h"
void IPC_mutexLock(unsigned int*);
void IPC_mutexUnlock(unsigned int*);
#endif

223
kernel/include/memory.h Normal file
View File

@ -0,0 +1,223 @@
/* memory.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef MEMORY_H
#define MEMORY_H
#include "types.h"
/* ###### Main Memory Management ###### */
#define KERNEL_SPACE_SIZE 0x10000000 /* Mémoire potentiellement utilisable par le kernel, adresse virtuelle de fin de l'espace noyau, aligné sur 4 Mo */
/* Configation dynamique */
#define KERNEL_SPACE_PT_COUNT (KERNEL_SPACE_SIZE / (PAGE_PER_PT * PAGE_SIZE))
#define KERNEL_SPACE_PAGE_COUNT (KERNEL_SPACE_PT_COUNT * PAGE_PER_PT)
#define KERNEL_PHY_SPACE_SIZE (KERNEL_PT_ADDR + (KERNEL_SPACE_PT_COUNT * PT_SIZE))
#define KERNEL_PHY_SPACE_PAGE_COUNT (KERNEL_PHY_SPACE_SIZE / PAGE_SIZE)
#define KERNEL_VM_SIZE (KERNEL_SPACE_SIZE - KERNEL_PHY_SPACE_SIZE)
#define KERNEL_VM_PAGE_COUNT (KERNEL_VM_SIZE / PAGE_SIZE)
/* ----------------------- */
/* Configation statique */
#define KERNEL_PD_ADDR 0x303000
#define KERNEL_PT_ADDR 0x304000
#define PD_SIZE 4096
#define PT_SIZE 4096
#define PAGE_SIZE 4096
#define MAX_PT_COUNT 1024
#define MAX_PAGE_COUNT 1048576
#define PAGE_OFFSET_BITS 12
#define PAGE_PER_PT 1024
/* ----------------------- */
/* Special types */
typedef T_dword T_page;
typedef T_Page* T_pageTable;
typedef T_pageTable* T_pageDir;
/* ----------------------- */
#ifdef MEMORY_PRIVATE
T_PageDirectory kpageDir;
T_PageTable kageTable;
unsigned int KernPageTableMutex;
#endif
void kinitSpace();
unsigned int kaddPage(T_Page);
void kremovePage(T_Page);
T_Page kgetPage();
void* kgetPhyAddr(void*);
/* ##################################### */
/* ###### Segment Management ###### */
#define GDT_BASE 0x200000
#define SEG_DESC_SIZE 8
#define SEG_DESC_NUMBER 256
#define MAIN_KERNEL_STACK 0xA0000
#define TSS_BASE 0x201000
struct MemSegDescriptor
{
bits16 limite0_15;
bits16 base0_15;
bits8 base16_23;
bits8 acces;
bits8 limite16_19:4;
bits8 other:4;
bits8 base24_31;
}__attribute__((packed));
struct GdtReg
{
bits16 limite;
bits32 base;
}__attribute__((packed));
struct TaskStateSegment
{
bits16 prevTask;
bits16 reserved_1;
bits32 esp0;
bits16 ss0;
bits16 reserved_2;
bits32 esp1;
bits16 ss1;
bits16 reserved_3;
bits32 esp2;
bits16 ss2;
bits16 reserved_4;
bits32 cr3;
bits32 eip;
bits32 eflags;
bits32 eax;
bits32 ecx;
bits32 edx;
bits32 ebx;
bits32 esp;
bits32 ebp;
bits32 esi;
bits32 edi;
bits16 es;
bits16 reserved_5;
bits16 cs;
bits16 reserved_6;
bits16 ss;
bits16 reserved_7;
bits16 ds;
bits16 reserved_8;
bits16 fs;
bits16 reserved_9;
bits16 gs;
bits16 reserved_10;
bits16 ldtSegSelect;
bits16 reserved_11;
bits16 flagDebug;
bits16 io_map;
}__attribute__((packed));
/* Special types */
typedef struct MemSegDescriptor T_GdtDesc;
typedef struct GdtReg T_GDT;
typedef struct TaskStateSegment T_TSS;
/* ----------------------- */
T_TSS *tss;
void InitGDT();
void CreateSegDescriptor(bits32, bits32, bits8, bits8, unsigned int);
/* ##################################### */
/* ###### Page Management ###### */
#ifdef MEMORY_PRIVATE
#define PHY_PAGE_MAP_ADDR 0x203000
#define PAGE_FREE 0
#define PAGE_USED 1
#define PAGE_NOT_PRESENT 4
bits8 *PageMap;
unsigned int PhyPageMapMutex;
#endif
#define PAGE_FLAG_PRESENT 1
#define PAGE_FLAG_RW 2
#define PAGE_FLAG_USER 4
T_Page GetPhyPage();
void ReleasePhyPage(T_Page);
/* ##################################### */
/* ###### Alloc Management ###### */
#ifdef MEMORY_PRIVATE
#define FREE 0
#define USED 1
unsigned int KERNEL_HEAP_BASE;
unsigned int KERNEL_HEAP_LIMIT;
struct AllocAreaModel {
T_byte state; /* 1:used 0:free */
struct AllocAreaModel *next;
}__attribute__((packed));
unsigned int AllocMutex;
#endif
void* malloc(unsigned int);
void free(void*);
struct AllocAreaModel* EnlargeHeap();
/* ##################################### */
/* ###### Paging Management ###### */
T_PageDirectory CreateTaskPageDirectory();
void DestroyTaskPageDirectory(T_PageDirectory);
unsigned int AddPage(T_Page, bits32);
void RemovePage(T_Page);
unsigned int LinkPhyPage(T_Page, T_Page, bits32);
void UnlinkPhyPage(T_Page);
void* GetPhyAddr(void*);
/* ##################################### */
#endif

58
kernel/include/print.h Normal file
View File

@ -0,0 +1,58 @@
/* print.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef PRINT_H
#define PRINT_H
#include <stdarg.h>
#include "types.h"
#define TEXTCOLOR_BLACK 0x0
#define TEXTCOLOR_DARK_BLUE 0x1
#define TEXTCOLOR_DARK_GREEN 0x2
#define TEXTCOLOR_DARK_CYAN 0x3
#define TEXTCOLOR_DARK_RED 0x4
#define TEXTCOLOR_DARK_MAGENTA 0x5
#define TEXTCOLOR_DARK_BROWN 0x6
#define TEXTCOLOR_DARK_GRAY 0x8
#define TEXTCOLOR_LIGHT_GRAY 0x7
#define TEXTCOLOR_LIGHT_BLUE 0x9
#define TEXTCOLOR_LIGHT_GREEN 0xA
#define TEXTCOLOR_LIGHT_CYAN 0xB
#define TEXTCOLOR_LIGHT_RED 0xC
#define TEXTCOLOR_LIGHT_MAGENTA 0xD
#define TEXTCOLOR_LIGHT_YELLOW 0xE
#define TEXTCOLOR_WHITE 0xF
#define BACK_BLUE 0x1
#define BACK_GREEN 0x2
#define BACK_CYAN 0x3
#define BACK_RED 0x4
#define BACK_MAGENTA 0x5
#define BACK_BROWN 0x6
#define BACK_GRAY 0x7
void printError(char*, ...);
void print(char*, ...);
void printColor(char*, T_byte, ...);
#endif

126
kernel/include/process.h Normal file
View File

@ -0,0 +1,126 @@
/* process.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef PROCESS_H
#define PROCESS_H
#include "types.h"
#include "memory.h"
#include "utils.h"
#include "ipc.h"
#define USER_SPACE_BASE_ADDR (KERNEL_SPACE_SIZE)
#define USER_STACK_ADDR 0xFFBFF000
#define USER_SPACE_END_ADDR 0xFFBFE000
#define PROCESS_STATUS_RUNNING 0
#define PROCESS_STATUS_WAIT_MUTEX 1
#define PROCESS_STATUS_SLEEP 2
#define PROCESS_STATUS_ZOMBIE 3
struct ProcessModel
{
struct ProcessModel* next; /* 0 */
struct ProcessModel* prev; /* 4 */
bits32 reg_EAX; /* 8 */
bits32 reg_EBX; /* 12 */
bits32 reg_ECX; /* 16 */
bits32 reg_EDX; /* 20 */
bits32 reg_ESI; /* 24 */
bits32 reg_EDI; /* 28 */
bits32 reg_EBP; /* 32 */
bits32 reg_ESP; /* 36 */
bits32 reg_EIP; /* 40 */
bits32 reg_EFLAGS; /* 44 */
bits16 reg_CS; /* 48 */
bits16 reg_DS; /* 50 */
bits16 reg_ES; /* 52 */
bits16 reg_FS; /* 54 */
bits16 reg_GS; /* 56 */
bits16 reg_SS; /* 58 */
bits32 reg_CR3; /* 60 */
bits32 kernelStackPtr;
T_PageDirectory pageDir;
T_LinkedList processRegionsList;
unsigned int pid;
struct ProcessModel* parent;
T_LinkedList processChildrenList;
unsigned int signal;
void* signalAction[32];
bits8 status; /* 0:actif 1:wait mutex 2:sleep 3:zombie */
unsigned int* ipcWaitMutex;
unsigned int ipcInSection;
};
typedef struct ProcessModel T_Process;
#ifdef PROCESS_PRIVATE
#define PROCESS_REGION_RO 0
#define PROCESS_REGION_RW 1
#define PROCESS_REGION_HEAP 3
struct ProcessRegion
{
struct ProcessRegion* next;
struct ProcessRegion* prev;
T_Page startPage;
T_Page endPage;
unsigned char type;
};
struct ProcessChild
{
struct ProcessChild* next;
struct ProcessChild* prev;
T_Process* process;
};
unsigned int PidCounter;
#endif
T_LinkedList Processes;
T_Process* CurrentProcess;
T_Process Process_0;
void InitProcessManager();
unsigned int CreateProcess(void*);
/* Fonctions éxécutées par le processus lui meme */
void DestroyProcess();
unsigned int ProcessCreateRegion_RO(T_Page, T_Page*, unsigned int, T_LinkedList*);
unsigned int ProcessCreateRegion_RW(T_Page, unsigned int, T_LinkedList*);
void ProcessRemoveRegion(T_Page, unsigned int, T_LinkedList*);
/* ############################################# */
/* Fonctions d'ordonnancement */
void _LoadContext(T_Process*);
bits32* _SaveContex();
T_Process* SchedulingAlgorithm();
void Schedule();
void ScheduleAtClock();
/* ############################################# */
#endif

40
kernel/include/signal.h Normal file
View File

@ -0,0 +1,40 @@
/* signal.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef SIGNAL_H
#define SIGNAL_H
#include "process.h"
/* Du plus important au moins important */
#define SIGNAL_KILL 0
#define SIGNAL_TERM 1
#define SIGNAL_KCHILD 2
void SendSignal(unsigned int, T_Process*);
void ClearSignal(unsigned int, T_Process*);
unsigned int FetchSignal(unsigned int, T_Process*);
void HandleSignal(unsigned int, T_Process*);
#endif

31
kernel/include/types.h Normal file
View File

@ -0,0 +1,31 @@
/* types.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef TYPES_H
#define TYPES_H
typedef unsigned char T_byte;
typedef unsigned short T_word;
typedef unsigned int T_dword;
#endif

57
kernel/include/utils.h Normal file
View File

@ -0,0 +1,57 @@
/* utils.h - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#pragma once
#ifndef UTILS_H
#define UTILS_H
#include "types.h"
void memcopy(char*, char*, unsigned int);
int strcmp(char*, char*);
void IntToChar(bits32, char*, int);
unsigned int expo(unsigned int, unsigned int);
struct List
{
unsigned int entryCount;
struct ElementModel *firstEntry;
struct ElementModel *lastEntry;
};
typedef struct List T_LinkedList;
struct ElementModel
{
struct ElementModel *next;
struct ElementModel *prev;
}__attribute__((packed));
void LinkedListPushFront(void*, T_LinkedList*);
void LinkedListPopFront(T_LinkedList*);
void LinkedListPushBack(void*, T_LinkedList*);
void LinkedListPopBack(T_LinkedList*);
void LinkedListInsert(void*, void*, void*, T_LinkedList*);
void LinkedListRemove(void*, T_LinkedList*);
void InsertElement(void*, void*, void*);
void RemoveElement(void*);
#endif

77
kernel/src/asm/io.asm Normal file
View File

@ -0,0 +1,77 @@
; io_port.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
global _out, _in, _outw, _inw, _outdw, _indw
_out:
push eax
push edx
mov dx, [esp+12]
mov al, [esp+16]
out dx, al
pop edx
pop eax
ret
_in:
push edx
xor eax, eax
mov dx, [esp+8]
in al, dx
pop edx
ret
_outw:
push eax
push edx
mov dx, [esp+12]
mov ax, [esp+16]
out dx, ax
pop edx
pop eax
ret
_inw:
push edx
xor eax, eax
mov dx, [esp+8]
in ax, dx
pop edx
ret
_outdw:
push eax
push edx
mov dx, [esp+12]
mov eax, [esp+16]
out dx, eax
pop edx
pop eax
ret
_indw:
push edx
mov dx, [esp+8]
in eax, dx
pop edx
ret

94
kernel/src/asm/isr.asm Normal file
View File

@ -0,0 +1,94 @@
; isr.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
extern IsrDefault, IsrGPFault, IsrSegFault, IsrPageFault, IsrClock, IsrKeyboard, ExecSystemCall, PIC_Send_EOI
global _DefaultInterrupt, _SEG_Fault, _GP_Fault, _Page_Fault, _KeyboardInterrupt, _ClockInterrupt, _SystemCall
%macro REGS_SAVE 0
pushad
push ds
push es
push fs
push gs
push ebx
mov bx, 0x10
mov ds, bx
pop ebx
%endmacro
%macro REGS_RESTORE 0
pop gs
pop fs
pop es
pop ds
popad
%endmacro
_DefaultInterrupt:
REGS_SAVE
call IsrDefault
call PIC_Send_EOI
REGS_RESTORE
iret
_SEG_Fault:
REGS_SAVE
call IsrSegFault
REGS_RESTORE
iret
_GP_Fault:
REGS_SAVE
call IsrGPFault
REGS_RESTORE
add esp, 4 ; Pour le décalage créé par le code d'erreur dans la pile
iret
_Page_Fault:
REGS_SAVE
call IsrPageFault
REGS_RESTORE
add esp, 4 ; Pour le décalage créé par le code d'erreur dans la pile
iret
_KeyboardInterrupt:
REGS_SAVE
call IsrKeyboard
call PIC_Send_EOI
REGS_RESTORE
iret
_ClockInterrupt:
REGS_SAVE
call IsrClock
call PIC_Send_EOI
REGS_RESTORE
iret
_SystemCall:
REGS_SAVE
push eax
call ExecSystemCall
pop eax
REGS_RESTORE
iret

88
kernel/src/asm/sched.asm Normal file
View File

@ -0,0 +1,88 @@
; sched.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
global _LoadContext, _SaveContex
_SaveContex:
pushfd
pushad
push dword ds
push dword es
push dword fs
push dword gs
mov eax, [esp + 52] ; On retrouve l'adresse de retour empilée lors de l'appel
push eax ; eip ret
mov eax, esp
add eax, 4
ret
_LoadContext:
mov esi, [esp + 4]
mov ax, [esi + 48] ; cs
cmp ax, 0x08
je .kernMode
.userMode:
mov ax, 0x18
mov ss, ax
mov esp, [esi + 64] ; Kstack_ptr
push dword [esi + 58] ; ss
push dword [esi + 36] ; esp
jmp .next
.kernMode:
mov ax, [esi + 58] ; ss
mov ss, ax
mov esp, [esi + 36] ; esp
.next:
push dword [esi + 44] ; eflags
push dword [esi + 48] ; cs
push dword [esi + 40] ; eip
push dword [esi + 8] ; eax
push dword [esi + 12] ; ebx
push dword [esi + 16] ; ecx
push dword [esi + 20] ; edx
push dword [esi + 24] ; esi
push dword [esi + 28] ; edi
push dword [esi + 32] ; ebp
push dword [esi + 50] ; ds
push dword [esi + 52] ; es
push dword [esi + 54] ; fs
push dword [esi + 56] ; gs
mov eax, [esi + 60]
mov cr3, eax
pop gs
pop fs
pop es
pop ds
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
iret

133
kernel/src/asm/syslib.asm Normal file
View File

@ -0,0 +1,133 @@
; asm_utils.asm - This file is a part of NutsOS
; NutsOS
; Copyright (C) 2013 Free Software Foundation, Inc.
; NutsOS is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 3 of the License, or
; (at your option) any later version.
; NutsOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
; You should have received a copy of the GNU General Public License along
; with NutsOS; If not, see <http://www.gnu.org/licenses/>.
; Valentin Verdier <valentin.verdier03@gmail.com>
[BITS 32]
[SECTION .text]
global _ClearInterrupt, _StartInterrupt, _EnablePaging, _LoadGdtR, _LoadIdtR, _LoadTaskRegister, _EmptyTLB, _LoadCr3, _ReadCr3, _ReadCr2, _SaveEflags, _RestoreEflags, _GetStackFrameAddr, _AtomicTestAndSet
_ClearInterrupt:
cli
ret
_StartInterrupt:
sti
ret
_EnablePaging:
push eax
mov eax, 0x303000
mov cr3, eax
mov eax, cr0
or eax, 0x80000000
mov cr0, eax
pop eax
ret
_LoadGdtR:
mov eax, [esp+4]
lgdt [eax]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ax, 0x18
mov ss, ax
jmp 0x08:.next
.next:
ret
_LoadIdtR:
push eax
mov eax, [esp+8]
lidt [eax]
pop eax
ret
_LoadTaskRegister:
push ax
mov ax, 0x38
ltr ax
pop ax
ret
_EmptyTLB:
push eax
mov eax, cr3
mov cr3, eax
pop eax
ret
_LoadCr3:
push eax
mov eax, [esp+8]
mov cr3, eax
pop eax
ret
_ReadCr3:
mov eax, cr3
ret
_ReadCr2:
mov eax, cr2
ret
_SaveEflags:
pushfd
pop eax
ret
_RestoreEflags:
push eax
mov eax, [esp+8]
push eax
popfd
pop eax
ret
_AtomicTestAndSet:
push ebx
push edx
xor eax, eax
mov edx, 1
mov ebx, [esp + 12]
lock cmpxchg [ebx], edx
pop edx
pop ebx
ret
_GetStackFrameAddr:
push ebx
push ecx
mov ecx, [esp + 12]
mov ebx, ebp
.loopTop:
cmp ecx, 0
je .loopEnd
mov eax, [ebx]
mov ebx, eax
dec ecx
jmp .loopTop
.loopEnd:
mov eax, ebx
pop ecx
pop ebx
ret

222
kernel/src/elf_loader.c Normal file
View File

@ -0,0 +1,222 @@
/* elf_loader.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#define ELF_LOADER_PRIVATE
#include "elf_loader.h"
#include "types.h"
#include "print.h"
#include "utils.h"
#include "memory.h"
#include "process.h"
/* Index dans id[] */
#define ID_MAG_0 0
#define ID_MAG_1 1
#define ID_MAG_2 2
#define ID_MAG_3 3
#define ID_CLASS 4
#define ID_DATA 5
#define ID_VERSION 6
#define ID_PAD 7
/* Classes ELF */
#define ELF_CLASS_NONE 0
#define ELF_CLASS_32 1
#define ELF_CLASS_64 2
/* Encodage des données */
#define ELF_DATA_NONE 0
#define ELF_DATA_LSB 1
#define ELF_DATA_MSB 2
/* Types de fichier ELF */
#define ELF_TYPE_NONE 0
#define ELF_TYPE_RELOC 1
#define ELF_TYPE_EXEC 2
#define ELF_TYPE_DYN 3
#define ELF_TYPE_CORE 4
/* Version */
#define ELF_VERSION_NONE 0
#define ELF_VERSION_CURRENT 1
/* Architectures cible */
#define ELF_ARCH_NONE 0
#define ELF_ARCH_M32 1
#define ELF_ARCH_SPARC 2
#define ELF_ARCH_386 3
#define ELF_ARCH_68K 4
#define ELF_ARCH_88K 5
#define ELF_ARCH_860 7
#define ELF_ARCH_MIPS 8
#define ELF_ARCH_MIPS_RS4_BE 10
/* Structure de l'entête des fichier ELF32 */
typedef struct {
T_byte id[16];
T_word type;
T_word targetArch;
T_dword version;
T_dword entry;
T_dword prgHdrTblOff;
T_dword secHdrTblOff; /* Pas utilisé ici */
T_dword flags; /* Pas utilisé ici */
T_word hdrSize;
T_word prgHdrTblEntrySize;
T_word prgHdrTblEntryCount;
T_word secHdrTblEntrySize; /* Pas utilisé ici */
T_word secHdrTblEntryCount; /* Pas utilisé ici */
T_word strTblIndex; /* Pas utilisé ici */
}__attribute__((packed)) T_ELF32_hdr;
/* Types de segment */
#define ELF_SEG_NULL 0
#define ELF_SEG_LOAD 1
#define ELF_SEG_DYNAMIC 2
#define ELF_SEG_INTERP 3
#define ELF_SEG_NOTE 4
#define ELF_SEG_SHLIB 5
#define ELF_SEG_PHDR 6
/* Permissions R|W|X */
#define ELF_SEG_PERM_READ 4
#define ELF_SEG_PERM_WRITE 2
#define ELF_SEG_PERM_EXEC 1
/* Structure d'une entrée du Program header */
typedef struct {
T_dword type;
T_dword offset;
T_dword vaddr;
T_dword paddr;
T_dword sizeInFile;
T_dword sizeInMem;
T_dword flags;
T_dword align;
}__attribute__((packed)) T_ELF32_prgHdrEntry;
int ELF32_checkFile(void *file)
{
T_ELF32_hdr* elfHdr = file;
if(elfHdr->id[ID_MAG_0] != 0x7F || elfHdr->id[ID_MAG_1] != 'E' || elfHdr->id[ID_MAG_2] != 'L' || elfHdr->id[ID_MAG_3] != 'F') {
print("[ELF Loader] : The file at 0x%x is not ELF type\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->id[ID_CLASS] != ELF_CLASS_32) {
print("[ELF Loader] : The file at 0x%x is not a 32 bits ELF\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->id[ID_DATA] != ELF_DATA_LSB) {
print("[ELF Loader] : The ELF file at 0x%x has a bad encoding\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->type == ELF_TYPE_EXEC) {
print("[ELF Loader] : The ELF file at 0x%x is not executable\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->targetArch == ELF_ARCH_386) {
print("[ELF_Loader] : The ELF file at 0x%x is not a x86 executable\n", DEFAULT_COLOR, file);
return 0;
}
if(elfHdr->entry >= KERNEL_SPACE_SIZE) {
return 1;
} else {
print("[ELF_Loader] : The ELF file at 0x%x has a bad entry point\n", DEFAULT_COLOR, file);
return 0;
}
}
unsigned int ELF32_Load(void *file, T_LinkedList* regionsList)
{
if(ELF32_checkFile(file)) {
T_ELF32_hdr* elfHdr = file;
unsigned int i, sc;
for(i = 0, sc = 0; i < elfHdr->prgHdrTblEntryCount; i++, sc++) {
T_ELF32_prgHdrEntry* prgHdrEntry = file + elfHdr->prgHdrTblOff + i * elfHdr->prgHdrTblEntrySize;
if(prgHdrEntry->type == ELF_SEG_LOAD) {
if(!prgHdrEntry->sizeInMem) {
goto error;
}
T_Page segStartPage = prgHdrEntry->vaddr & 0xFFFFF000;
unsigned int pageCount = prgHdrEntry->sizeInMem & 0xFFFFF000;
if(prgHdrEntry->sizeInMem & 0x00000FFF) {
pageCount++;
}
if((prgHdrEntry->vaddr & 0x00000FFF) >= PAGE_SIZE - (prgHdrEntry->sizeInMem & 0x00000FFF)) {
pageCount++;
}
if(prgHdrEntry->flags == (ELF_SEG_PERM_READ | ELF_SEG_PERM_EXEC)) {
T_Page* pglist = malloc(sizeof(T_Page) * pageCount);
if(!pglist) {
goto error;
}
unsigned int j;
for(j = 0; j < pageCount; j++) {
pglist[j] = ((T_Page) file + prgHdrEntry->offset & 0xFFFFF000) + (j << PAGE_OFFSET_BITS);
}
if(!ProcessCreateRegion_RO(segStartPage, pglist, pageCount, regionsList)) {
free(pglist);
goto error;
}
free(pglist);
} else if(prgHdrEntry->flags == (ELF_SEG_PERM_READ | ELF_SEG_PERM_WRITE)) {
if(!ProcessCreateRegion_RW(segStartPage, pageCount, regionsList)) {
goto error;
}
unsigned int j;
for(j = 0; j < pageCount; j++) {
memcopy((char*) (((unsigned int) file + prgHdrEntry->offset & 0xFFFFF000) + (j << PAGE_OFFSET_BITS)),(char*) (segStartPage + (j << PAGE_OFFSET_BITS)), PAGE_SIZE);
}
}
}
}
return elfHdr->entry;
error:
for(i = 0; i < sc; i++) {
T_ELF32_prgHdrEntry* prgHdrEntry = file + elfHdr->prgHdrTblOff + i * elfHdr->prgHdrTblEntrySize;
if(prgHdrEntry->type == ELF_SEG_LOAD) {
T_Page segStartPage = prgHdrEntry->vaddr & 0xFFFFF000;
unsigned int pageCount;
if(prgHdrEntry->sizeInMem & 0x00000FFF) {
pageCount = (prgHdrEntry->sizeInMem & 0xFFFFF000) + 1;
}
if(prgHdrEntry->align > 0) {
pageCount++;
}
ProcessRemoveRegion(segStartPage, pageCount, regionsList);
}
}
return 0;
} else {
return 0;
}
}

165
kernel/src/interrupt.c Normal file
View File

@ -0,0 +1,165 @@
/* interrupt.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "interrupt.h"
#include "types.h"
#include "asm_x86.h"
#include "print.h"
#include "process.h"
/* ============ Configuration du PIC 8259A ============ */
void PIC_Init()
{
_out(PIC_MASTER_CMD_REG, 0x11);
_out(PIC_SLAVE_CMD_REG, 0x11);
_out(PIC_MASTER_DATA_REG, PIC_MASTER_IDT_OFFSET);
_out(PIC_SLAVE_DATA_REG, PIC_SLAVE_IDT_OFFSET);
_out(PIC_MASTER_DATA_REG, 4);
_out(PIC_SLAVE_DATA_REG, 2);
_out(PIC_MASTER_DATA_REG, 1);
_out(PIC_SLAVE_DATA_REG, 1);
_out(PIC_MASTER_DATA_REG, 0);
_out(PIC_SLAVE_DATA_REG, 0);
}
void PIC_MaskIRQ(bits8 irq)
{
bits8 mask;
if(irq < 8)
{
mask = _in(PIC_MASTER_DATA_REG) & ~(1 << irq);
_out(PIC_MASTER_DATA_REG, mask);
}
else
{
mask = _in(PIC_SLAVE_DATA_REG) & ~(1 << (irq - 8));
_out(PIC_SLAVE_DATA_REG, mask);
}
}
void PIC_Send_EOI()
{
_out(PIC_MASTER_CMD_REG, PIC_EOI);
_out(PIC_SLAVE_CMD_REG, PIC_EOI);
}
/* ===================================================== */
/* ========= Manipulation de l'IDT ========= */
void InitIDT()
{
unsigned int i;
T_IDT IdtR;
PIC_Init();
/* Initialisation de l'IDT */
for(i = 0; i < IDT_SIZE; i++)
{
CreateInterruptDescriptor((bits32) &_DefaultInterrupt, 0x08, 0x8E00, i);
}
/* Configuration de l'IDT */
CreateInterruptDescriptor((bits32) &_SEG_Fault, 0x08, 0x8E00, SEG_FAULT_INT);
CreateInterruptDescriptor((bits32) &_SEG_Fault, 0x08, 0x8E00, STACK_SEG_FAULT_INT);
CreateInterruptDescriptor((bits32) &_GP_Fault, 0x08, 0x8E00, GP_FAULT_INT);
CreateInterruptDescriptor((bits32) &_Page_Fault, 0x08, 0xEF00, PAGE_FAULT_INT);
CreateInterruptDescriptor((bits32) &_ClockInterrupt, 0x08, 0x8E00, TIMER_INT);
CreateInterruptDescriptor((bits32) &_KeyboardInterrupt, 0x08, 0x8E00, KB_INT);
CreateInterruptDescriptor((bits32) &_SystemCall, 0x08, 0xEF00, SYS_CALL_INT);
/* Pointeur sur l'IDT pour lidt */
IdtR.limite = (bits16) (INT_DESC_SIZE * IDT_SIZE);
IdtR.base = IDT_BASE;
_LoadIdtR(&IdtR);
}
void CreateInterruptDescriptor(bits32 offset, bits16 seg, bits16 type, unsigned int desc)
{
T_IdtDesc *idt = (T_IdtDesc*) IDT_BASE;
idt[desc].offset0_15 = (offset & 0xFFFF);
idt[desc].segment = seg;
idt[desc].type = type;
idt[desc].offset16_31 = (offset & 0xFFFF0000) >> 16;
}
/* ===================================================== */
/* ========== Routines d'interruption en C ============ */
void IsrDefault()
{
//print("int\n", 0x47);
return;
}
void IsrGPFault()
{
print("ERROR : X86 GENERAL PROTECTION FAULT\n", 0x47);
_ClearInterrupt();
while(1)
{
asm("hlt");
}
}
void IsrSegFault()
{
print("ERROR : X86 SEGMENTATION FAULT\n", 0x47);
_ClearInterrupt();
while(1)
{
asm("hlt");
}
}
void IsrPageFault()
{
bits32 cr2 = _ReadCr2();
/*if(CurrentProcess)
{
ProcessAddPage(cr2 & 0xFFFFF000);
}
else*/
{
print("ERROR : PAGE FAULT (ADDR = %x)\n", 0x47, cr2);
_ClearInterrupt();
while(1)
{
asm("hlt");
}
}
}
void IsrClock()
{
KBD_LedsControl(7);
ScheduleAtClock();
}
/* ========================================================= */

55
kernel/src/ipc.c Normal file
View File

@ -0,0 +1,55 @@
/* ipc.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "ipc.h"
#include "types.h"
#include "asm_x86.h"
#include "process.h"
void IPC_MutexLock(unsigned int* mutex)
{
if(CurrentProcess)
{
if(_AtomicTestAndSet(mutex))
{
CurrentProcess->ipcWaitMutex = mutex;
CurrentProcess->status = 1;
Schedule();
}
else
{
CurrentProcess->ipcInSection++;
}
}
}
void IPC_MutexUnlock(unsigned int* mutex)
{
if(CurrentProcess)
{
if(CurrentProcess->ipcInSection > 0)
{
*mutex = 0;
CurrentProcess->ipcInSection--;
}
}
}

77
kernel/src/main.c Normal file
View File

@ -0,0 +1,77 @@
/* main.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "args.h"
#include "types.h"
#include "print.h"
#include "interrupt.h"
#include "utils.h"
#include "memory.h"
#include "asm_x86.h"
#include "process.h"
void main()
{
arg = (struct ArgModel*) 0x1400;
CurrentProcess = 0;
print("\nNutsOS Kernel ( NOS-kernel32.bin build 2013-12-01 )\n", 0x6F);
print("[Kernel] useable memory -> %d Ko\n", DEFAULT_COLOR, (arg->phyMemSize / 1024));
if(arg->phyMemSize / 1024 < 10240)
{
print("ERROR : A USEABLE SYSTEM MUST HAVE MORE THAN 10 Mo", 0x47);
asm("hlt");
}
print("[Kernel] initializing memory managment...", DEFAULT_COLOR);
InitGDT();
InitKernelSpace();
_EnablePaging();
print("ok\n", 0x02);
print("[Kernel] setting up interrupts...", DEFAULT_COLOR);
InitIDT();
//setTimerDivid(11932); /* (1193181Hz / div) div = 1193 pour 1KHz, div = 11932 pour 100Hz */
print("ok\n", 0x02);
print("[Kernel] setting up processes scheduler...", DEFAULT_COLOR);
InitProcessManager();
print("ok\n", 0x02);
print("[Kernel] end of initialisation, switch to the god process\n", DEFAULT_COLOR);
CurrentProcess = &Process_0;
tss->ss0 = 0x18;
tss->esp0 = CurrentProcess->kernelStackPtr;
_LoadContext(CurrentProcess);
/*print("[Kernel] detect PCI devices...\n", DEFAULT_COLOR);
PciDetectDevices();
print("done\n", DEFAULT_COLOR);*/
/* Normalement, c'est impossible d'arriver jusque ici */
while(1)
{
asm("hlt");
}
}

790
kernel/src/memory.c Normal file
View File

@ -0,0 +1,790 @@
/* memory.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#define MEMORY_PRIVATE
#include "memory.h"
#include "types.h"
#include "print.h"
#include "args.h"
#include "asm_x86.h"
#include "ipc.h"
/* Initialise les principaux segments utilisés par le kernel */
void InitGDT()
{
T_GDT GdtR;
/* Adresse du TSS en mémoire */
tss = (T_TSS*) TSS_BASE;
/* Configuration du TSS */
tss->flagDebug = 0x00;
tss->io_map = 0x00;
tss->esp0 = MAIN_KERNEL_STACK;
tss->ss0 = 0x18;
/* Configuration de la GDT */
CreateSegDescriptor(0x0, 0x0, 0x0, 0x0, 0); /* Segment nul */
CreateSegDescriptor(0x0, 0xFFFFF, 0x9B, 0x0D, 1); /* Code noyau */
CreateSegDescriptor(0x0, 0xFFFFF, 0x93, 0x0D, 2); /* Données noyau */
CreateSegDescriptor(0x0, 0x0, 0x97, 0x0D, 3); /* Pile noyau */
CreateSegDescriptor(0x0, 0xFFFFF, 0xFF, 0x0D, 4); /* Code user */
CreateSegDescriptor(0x0, 0xFFFFF, 0xF3, 0x0D, 5); /* Données user */
CreateSegDescriptor(0x0, 0x0, 0xF7, 0x0D, 6); /* Pile user */
CreateSegDescriptor((bits32) tss, 0x67, 0xE9, 0x00, 7); /* TSS */
/* Pointeur sur GDT pour lgdt */
GdtR.limite = (bits16) (SEG_DESC_NUMBER * SEG_DESC_SIZE);
GdtR.base = GDT_BASE;
_LoadGdtR(&GdtR);
_LoadTaskRegister();
}
void CreateSegDescriptor(bits32 base, bits32 limite, bits8 acces, bits8 other, unsigned int desc)
{
T_GdtDesc *gdt = (T_GdtDesc*) GDT_BASE;
gdt[desc].limite0_15 = (limite & 0xFFFF);
gdt[desc].base0_15 = (base & 0xFFFF);
gdt[desc].base16_23 = (base & 0xFF0000) >> 16;
gdt[desc].acces = acces;
gdt[desc].limite16_19 = (limite & 0xF0000) >> 16;
gdt[desc].other = (other & 0xF);
gdt[desc].base24_31 = (base & 0xFF000000) >> 24;
}
/* Créé l'espace virtuel linéaire du noyau qui couvre 4 Go */
void InitKernelSpace()
{
bits32 i, j, page, size;
/* === On créé l'espace d'adressage du kernel (espace physique fixe : 7184 Ko, espace virtuel dynamique : 254960 Ko, total : 256 Mo) === */
PageDirectory = (T_PageDirectory) KERNEL_PD_ADDR;
PageTable = (T_PageTable) KERNEL_PT_ADDR;
/* On initialise le PageDirectory du kernel */
for(i = 0; i < MAX_PT_COUNT; i++)
{
if(i < KERNEL_SPACE_PT_COUNT)
{
PageDirectory[i] = KERNEL_PT_ADDR + i * PT_SIZE;
PageDirectory[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
}
else
{
PageDirectory[i] = 0;
}
}
/* On initialise les tables de pages du kernel */
for(i = 0; i < KERNEL_SPACE_PAGE_COUNT; i++)
{
if(i < KERNEL_PHY_SPACE_PAGE_COUNT)
{
PageTable[i] = i * PAGE_SIZE;
PageTable[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
}
else
{
PageTable[i] = 0;
}
}
/* ============================================== */
/* ==== On initialise la table d'état des pages physiques en utilisant la Memory Map ==== */
PageMap = (bits8*) PHY_PAGE_MAP_ADDR;
for(i = 0; i < MAX_PAGE_COUNT; i++) /* Initialisation */
{
PageMap[i] = PAGE_NOT_PRESENT;
}
/* On parcout la Memory Map */
for(i = 0; i < arg->memListEntryNumber; i++)
{
/* On calcul le numéro de la page de base puis la taille en nombre de page */
page = arg->memMap[i].baseAddr_1 / PAGE_SIZE;
size = arg->memMap[i].size_1 / PAGE_SIZE;
if(arg->memMap[i].size_1 % PAGE_SIZE > 0)
{
size++;
}
/* Si la zone mémoire est utilisable */
if(arg->memMap[i].type == 1)
{
/* On parcourt la section de la table d'état correspondant à la zone mémoire */
for(j = page; j < page + size; j++)
{
PageMap[j] = FREE;
}
}
}
/* =============================================================== */
/* ===== Structures d'allocation ===== */
KERNEL_HEAP_BASE = KERNEL_PHY_SPACE_PAGE_COUNT << PAGE_OFFSET_BITS;
if(!KernelAddPage(KERNEL_HEAP_BASE))
{
fatalError("MEGA ERROR OF DEATH !!");
}
KERNEL_HEAP_LIMIT = KERNEL_HEAP_BASE + PAGE_SIZE;
struct AllocAreaModel *firstArea = (struct AllocAreaModel*) KERNEL_HEAP_BASE;
firstArea->state = 0;
firstArea->next = 0;
/* ================================================================= */
PhyPageMapMutex = 0;
KernPageTableMutex = 0;
AllocMutex = 0;
}
unsigned int KernelAddPage(T_Page addr)
{
unsigned int vpage = addr >> PAGE_OFFSET_BITS;
unsigned int ret;
if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT)
{
IPC_MutexLock(&KernPageTableMutex);
if(PageTable[vpage] == 0)
{
PageTable[vpage] = GetPhyPage();
if(PageTable[vpage])
{
PageTable[vpage] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
ret = 1;
}
else
{
ret = 0;
}
}
else
{
print("[KernelAddPage] vaddr = 0x%x is already used\n", 0x47, addr);
ret = 0;
}
IPC_MutexUnlock(&KernPageTableMutex);
}
else
{
print("[KernelAddPage] vaddr = 0x%x isn't in virtual kernel space\n", 0x47, addr);
ret = 0;
}
return ret;
}
void KernelRemovePage(T_Page vaddr)
{
unsigned int vpage = vaddr >> PAGE_OFFSET_BITS;
if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT)
{
IPC_MutexLock(&KernPageTableMutex);
if(PageTable[vpage] != 0)
{
ReleasePhyPage(PageTable[vpage] & 0xFFFFF000);
PageTable[vpage] = 0;
_EmptyTLB();
}
else
{
print("[KernelRemovePage] vaddr = 0x%x is already released\n", 0x47);
}
IPC_MutexUnlock(&KernPageTableMutex);
}
else
{
print("[KernelRemovePage] vaddr = 0x%x isn't in virtual kernel space\n", 0x47);
}
}
T_Page KernelGetPage()
{
unsigned int i;
T_Page ret;
for(i = KERNEL_SPACE_PAGE_COUNT - 1; i >= KERNEL_HEAP_LIMIT >> PAGE_OFFSET_BITS; i--)
{
IPC_MutexLock(&KernPageTableMutex);
if(PageTable[i] == 0)
{
PageTable[i] = GetPhyPage();
if(PageTable[i])
{
PageTable[i] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
ret = i << PAGE_OFFSET_BITS;
}
else
{
ret = 0;
}
IPC_MutexUnlock(&KernPageTableMutex);
break;
}
else
{
ret = 0;
}
IPC_MutexUnlock(&KernPageTableMutex);
}
return ret;
}
void* KernelGetPhyAddr(void *vaddr)
{
unsigned int vpage = (unsigned int) vaddr >> PAGE_OFFSET_BITS;
void *ret;
if(vpage < KERNEL_SPACE_PAGE_COUNT && vpage >= KERNEL_PHY_SPACE_PAGE_COUNT)
{
IPC_MutexLock(&KernPageTableMutex);
if(PageTable[vpage])
{
ret = (void*) (PageTable[vpage] & 0xFFFFF000 | (unsigned int) vaddr & 0x00000FFF);
}
else
{
ret = 0;
}
IPC_MutexUnlock(&KernPageTableMutex);
}
else
{
ret = 0;
}
return ret;
}
T_Page GetPhyPage()
{
unsigned int i;
for(i = KERNEL_PHY_SPACE_PAGE_COUNT; i < MAX_PAGE_COUNT; i++)
{
IPC_MutexLock(&PhyPageMapMutex);
if(PageMap[i] == FREE)
{
PageMap[i] = USED;
IPC_MutexUnlock(&PhyPageMapMutex);
return i << PAGE_OFFSET_BITS;
}
IPC_MutexUnlock(&PhyPageMapMutex);
}
print("[GetPhyPage] no enough physical pages\n", 0x47);
return 0;
}
void ReleasePhyPage(T_Page addr)
{
unsigned int page = addr >> PAGE_OFFSET_BITS;
if(page >= KERNEL_PHY_SPACE_PAGE_COUNT)
{
IPC_MutexLock(&PhyPageMapMutex);
if(PageMap[page] != PAGE_NOT_PRESENT)
{
PageMap[page] = FREE;
}
else
{
print("[ReleasePhyPage] unable to release a not present page\n", 0x47);
}
IPC_MutexUnlock(&PhyPageMapMutex);
}
else
{
print("[ReleasePhyPage] unable to release a kernel physical page\n", 0x47);
}
}
void* malloc(unsigned int size)
{
IPC_MutexLock(&AllocMutex);
struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE;
void *ptr = 0;
start:
while(area != 0)
{
if(((unsigned int) area + sizeof(struct AllocAreaModel) < KERNEL_HEAP_LIMIT))
{
if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT)
{
fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED");
}
if(area->state == FREE)
{
unsigned int areaBase = (unsigned int) area + sizeof(struct AllocAreaModel);
unsigned int areaSize;
if(area->next == 0)
{
areaSize = KERNEL_HEAP_LIMIT - areaBase;
}
else
{
areaSize = (unsigned int) area->next - areaBase;
}
if(areaSize == size)
{
area->state = USED;
ptr = (void*) areaBase;
break;
}
else if(areaSize > size)
{
struct AllocAreaModel *newArea = (struct AllocAreaModel*) (areaBase + size);
if(newArea + sizeof(struct AllocAreaModel) < (struct AllocAreaModel*) KERNEL_HEAP_LIMIT)
{
newArea->state = FREE;
newArea->next = area->next;
area->next = newArea;
}
else
{
area->next = 0;
}
area->state = USED;
ptr = (void*) areaBase;
break;
}
}
}
else
{
fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED");
}
area = area->next;
}
if(!ptr)
{
area = EnlargeHeap();
if(area)
{
goto start;
}
}
/*print("MALLOC -> ", 0x04);
area = KERNEL_HEAP_BASE;
while(area)
{
print("base : 0x%x, next : 0x%x, state : %d\n", 0x04, (unsigned int) area + sizeof(struct AllocAreaModel), area->next, area->state);
area = area->next;
}*/
IPC_MutexUnlock(&AllocMutex);
return ptr;
}
void free(void *addr)
{
IPC_MutexLock(&AllocMutex);
struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE;
while(area != 0)
{
if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT)
{
fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED");
}
if(area->state == USED)
{
unsigned int areaBase = (unsigned int) area + sizeof(struct AllocAreaModel);
if(areaBase == (unsigned int) addr)
{
area->state = FREE;
while(area->next != 0)
{
if(area->next >= (struct AllocAreaModel*) KERNEL_HEAP_LIMIT)
{
fatalError("MEMORY MANAGMENT DATA STRUCTURES ARE DAMAGED");
}
if(area->next->state == FREE)
{
area->next = area->next->next;
}
else
{
break;
}
}
IPC_MutexUnlock(&AllocMutex);
return;
}
}
area = area->next;
}
/*print("FREE -> ", 0x04);
area = KERNEL_HEAP_BASE;
while(area)
{
print("base : 0x%x, next : 0x%x, state : %d\n", 0x04, (unsigned int) area + sizeof(struct AllocAreaModel), area->next, area->state);
area = area->next;
}*/
fatalError("IMPOSSIBLE TO FREE MEMORY");
IPC_MutexUnlock(&AllocMutex);
}
struct AllocAreaModel* EnlargeHeap()
{
if(KernelAddPage(KERNEL_HEAP_LIMIT))
{
struct AllocAreaModel *area = (struct AllocAreaModel*) KERNEL_HEAP_BASE;
while(area->next != 0)
{
area = area->next;
}
struct AllocAreaModel *lastArea = area;
if(area->state == USED)
{
lastArea = (struct AllocAreaModel*) KERNEL_HEAP_LIMIT;
lastArea->next = 0;
lastArea->state = FREE;
area->next = lastArea;
}
KERNEL_HEAP_LIMIT += PAGE_SIZE;
return lastArea;
}
else
{
print("[EnlargeHeap] unable to enlarge kernel heap, no enough kernel pages\n", 0x47);
return 0;
}
}
T_PageDirectory CreateTaskPageDirectory()
{
/* #-----# 0xFFFFFFFF
* |-----| pageDir user
* | |
* | |
* | |
* | |
* | |
* |-----|
* | |
* #-----# espace noyau */
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) KernelGetPage();
if(PageDir)
{
for(i = 0; i < MAX_PT_COUNT; i++) /* Initialisation du répertoire de pages*/
{
PageDir[i] = 0;
}
for(i = 0; i < KERNEL_SPACE_PT_COUNT; i++) /* Construction de la partie noyau */
{
PageDir[i] = PageDirectory[i];
}
/* La table de pages 1023 couvre le PageDir et les table de pages, de 0xFFC00000 à 0xFFFFFFFF */
PageDir[1023] = (T_Page) KernelGetPhyAddr(PageDir);
PageDir[1023] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW;
return PageDir;
}
else
{
return 0;
}
}
void DestroyTaskPageDirectory(T_PageDirectory PageDir)
{
unsigned int i;
for(i = KERNEL_SPACE_PAGE_COUNT; i < MAX_PT_COUNT; i++)
{
if(PageDir[i])
{
ReleasePhyPage(PageDir[i] & 0xFFFFF000);
}
}
KernelRemovePage((T_Page) PageDir);
}
/* Alloue une nouvelle page physique et la fait correspondre à l'adresse virtuelle vaddr */
unsigned int AddPage(T_Page vaddr, bits32 perm)
{
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTableAddr;
T_PageTable PageTableVaddr;
bits32 ptNum = (vaddr & 0xFFC00000) >> 22;
bits32 pgNum = (vaddr & 0x003FF000) >> 12;
/* On regarde si la table de pages est créée */
if(PageDir[ptNum] == 0) /* Si elle n'éxiste pas */
{
/* On créé la table de pages */
PageTableAddr = (T_PageTable) GetPhyPage(); /* Adresse physique, donc inaccessible ici */
if(PageTableAddr)
{
/* On ajoute la table de pages crée dans le répertoire */
PageDir[ptNum] = (T_Page) PageTableAddr;
PageDir[ptNum] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER;
PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On accède à la table de pages depuis l'espace de mappage virtuel */
for(i = 0; i < 1024; i++)
{
PageTableVaddr[i] = 0;
}
PageTableVaddr[pgNum] = GetPhyPage();
if(PageTableVaddr[pgNum])
{
PageTableVaddr[pgNum] |= perm;
return 1;
}
else
{
PageDir[ptNum] = 0;
ReleasePhyPage((T_Page) PageTableAddr);
_EmptyTLB();
return 0;
}
}
else
{
return 0;
}
}
else /* Si elle éxiste */
{
PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On accède à la table de pages depuis l'espace de mappage virtuel */
/* On test pour savoir si la page voulue est déjà présente */
if(PageTableVaddr[pgNum] == 0)
{
/* Si elle ne l'est pas on ajoute à la table de pages la page voulue */
PageTableVaddr[pgNum] = GetPhyPage();
if(PageTableVaddr[pgNum])
{
PageTableVaddr[pgNum] |= perm;
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
}
void RemovePage(T_Page vaddr)
{
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTable;
int empty;
bits32 ptNum = (vaddr & 0xFFC00000) >> 22;
bits32 pgNum = (vaddr & 0x003FF000) >> 12;
if(PageDir[ptNum] != 0)
{
PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE);
if(PageTable[pgNum] != 0)
{
ReleasePhyPage(PageTable[pgNum] & 0xFFFFF000);
PageTable[pgNum] = 0;
for(i = 0; i < PAGE_PER_PT; i++)
{
if(PageTable[i] == 0)
{
empty = 1;
}
else
{
empty = 0;
break;
}
}
if(empty)
{
ReleasePhyPage(PageDir[ptNum] & 0xFFFFF000);
PageDir[ptNum] = 0;
}
_EmptyTLB();
}
}
}
unsigned int LinkPhyPage(T_Page vaddr, T_Page addr, bits32 perm)
{
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTableAddr;
T_PageTable PageTableVaddr;
bits32 ptNum = (vaddr & 0xFFC00000) >> 22;
bits32 pgNum = (vaddr & 0x003FF000) >> 12;
/* On regarde si la table de pages est créée */
if(PageDir[ptNum] == 0) /* Si elle n'éxiste pas */
{
/* On créé la table de pages */
PageTableAddr = (T_PageTable) GetPhyPage(); /* Adresse physique, donc inaccessible ici */
if(PageTableAddr)
{
/* On ajoute la table de pages crée dans le répertoire */
PageDir[ptNum] = (T_Page) PageTableAddr;
PageDir[ptNum] |= PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER;
PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On accède à la table de pages depuis l'espace de mappage virtuel */
for(i = 0; i < 1024; i++)
{
PageTableVaddr[i] = 0;
}
PageTableVaddr[pgNum] = addr & 0xFFFFF000;
PageTableVaddr[pgNum] |= perm;
return 1;
}
else
{
return 0;
}
}
else /* Si elle éxiste */
{
PageTableVaddr = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE); /* On accède à la table de pages depuis l'espace de mappage virtuel */
/* On test pour savoir si la page voulue est déjà présente */
if(PageTableVaddr[pgNum] == 0)
{
/* Si elle ne l'est pas on ajoute à la table de pages la page voulue */
PageTableVaddr[pgNum] = addr & 0xFFFFF000;
PageTableVaddr[pgNum] |= perm;
return 1;
}
else
{
return 0;
}
}
}
void UnlinkPhyPage(T_Page vaddr)
{
unsigned int i;
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTable;
int empty;
bits32 ptNum = (vaddr & 0xFFC00000) >> 22;
bits32 pgNum = (vaddr & 0x003FF000) >> 12;
if(PageDir[ptNum] != 0)
{
PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE);
if(PageTable[pgNum] != 0)
{
PageTable[pgNum] = 0;
for(i = 0; i < PAGE_PER_PT; i++)
{
if(PageTable[i] == 0)
{
empty = 1;
}
else
{
empty = 0;
break;
}
}
if(empty)
{
ReleasePhyPage(PageDir[ptNum] & 0xFFFFF000);
PageDir[ptNum] = 0;
}
_EmptyTLB();
}
}
}
void* GetPhyAddr(void *vaddr)
{
T_PageDirectory PageDir = (T_PageDirectory) 0xFFFFF000;
T_PageTable PageTable;
bits32 ptNum = ((bits32) vaddr & 0xFFC00000) >> 22;
bits32 pgNum = ((bits32) vaddr & 0x003FF000) >> 12;
bits32 offset = (bits32) vaddr & 0x00000FFF; /* Offset par rapport au début de la page */
if(PageDir[ptNum] != 0)
{
PageTable = (T_PageTable) (0xFFC00000 + ptNum * PT_SIZE);
if(PageTable[pgNum] != 0)
{
return (void*) (PageTable[pgNum] & 0xFFFFF000 | offset);
}
}
return 0;
}

129
kernel/src/print.c Normal file
View File

@ -0,0 +1,129 @@
/* print.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "print.h"
#include "types.h"
#include "utils.h"
#include "asm_x86.h"
#include <stdarg.h>
static printArgs(char* str, T_byte color, va_list args) {
}
void fatalError(char *str)
{
print("FATAL ERROR : %s\n", 0x47, str);
_ClearInterrupt();
asm("hlt");
}
void putc(char c) {
}
void print(char *str, char color, ...)
{
va_list arg;
va_start(arg, color);
while(*str != 0)
{
if(*str == '%')
{
if(str[1] == 'd')
{
printDec(va_arg(arg, bits32), color);
str+=2;
}
else if(str[1] == 'x')
{
printHex(va_arg(arg, bits32), color);
str+=2;
}
else if(str[1] == 'b')
{
printBin(va_arg(arg, bits32), color);
str+=2;
}
else if(str[1] == 's')
{
print(va_arg(arg, char*), color);
str+=2;
}
else
{
PutCharVterm('%', color, VirtualTerminal_0);
str++;
}
}
else
{
putcVterm(*str, color, VirtualTerminal_0);
str++;
}
}
va_end(arg);
}
void printDec(bits32 a, char color)
{
char buffer[11];
char *str = buffer;
IntToChar(a, str, 10);
while(*str != 0)
{
PutCharVterm(*str, color, VirtualTerminal_0);
str++;
}
}
void printHex(bits32 a, char color)
{
char buffer[9];
char *str = buffer;
IntToChar(a, str, 16);
while(*str != 0)
{
PutCharVterm(*str, color, VirtualTerminal_0);
str++;
}
}
void printBin(bits32 a, char color)
{
char buffer[33];
char *str = buffer;
IntToChar(a, str, 2);
while(*str != 0)
{
PutCharVterm(*str, color, VirtualTerminal_0);
str++;
}
}

408
kernel/src/process.c Normal file
View File

@ -0,0 +1,408 @@
/* process.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#define PROCESS_PRIVATE
#include "process.h"
#include "types.h"
#include "display.h"
#include "asm_x86.h"
#include "memory.h"
#include "utils.h"
#include "args.h"
#include "elf_loader.h"
void Process_0_Task();
void InitProcessManager()
{
Process_0.pid = 0;
Process_0.reg_EAX = 0x00;
Process_0.reg_EBX = 0x00;
Process_0.reg_ECX = 0x00;
Process_0.reg_EDX = 0x00;
Process_0.reg_ESI = 0x00;
Process_0.reg_EDI = 0x00;
Process_0.reg_EBP = 0x00;
Process_0.reg_ESP = MAIN_KERNEL_STACK;
Process_0.reg_CS = 0x08;
Process_0.reg_DS = 0x10;
Process_0.reg_ES = 0x10;
Process_0.reg_FS = 0x10;
Process_0.reg_GS = 0x10;
Process_0.reg_SS = 0x18;
Process_0.reg_EIP = (bits32) &Process_0_Task;
Process_0.reg_EFLAGS = 0x200;
Process_0.pageDir = (T_PageDirectory) KERNEL_PD_ADDR;
Process_0.reg_CR3 = KERNEL_PD_ADDR;
Process_0.kernelStackPtr = MAIN_KERNEL_STACK;
/* Pas de mode user, donc pas de régions */
Process_0.processRegionsList.firstEntry = 0;
Process_0.processRegionsList.lastEntry = 0;
Process_0.processRegionsList.entryCount = 0;
Process_0.parent = 0; /* Pas de parent */
Process_0.processChildrenList.firstEntry = 0;
Process_0.processChildrenList.lastEntry = 0;
Process_0.processChildrenList.entryCount = 0;
Process_0.signal = 0;
Process_0.status = PROCESS_STATUS_RUNNING;
Process_0.ipcWaitMutex = 0;
Process_0.ipcInSection = 0;
Processes.firstEntry = 0;
Processes.lastEntry = 0;
Processes.entryCount = 0;
LinkedListPushBack(&Process_0, &Processes);
PidCounter = 1;
}
unsigned int CreateProcess(void *file)
{
unsigned int i;
/* On initialise une entrée dans la table des processus */
T_Process* process = malloc(sizeof(T_Process));
struct ProcessChild* child = malloc(sizeof(struct ProcessChild));
if(!process || !child)
{
if(child)
{
free(child);
}
if(process)
{
free(process);
}
print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47);
return 0;
}
process->pid = PidCounter;
process->status = PROCESS_STATUS_RUNNING;
process->ipcWaitMutex = 0;
process->ipcInSection = 0;
process->processRegionsList.firstEntry = 0;
process->processRegionsList.lastEntry = 0;
process->processRegionsList.entryCount = 0;
child->process = process;
process->parent = CurrentProcess;
process->processChildrenList.firstEntry = 0;
process->processChildrenList.lastEntry = 0;
process->processChildrenList.entryCount = 0;
process->signal = 0;
process->reg_EAX = 0x00;
process->reg_EBX = 0x00;
process->reg_ECX = 0x00;
process->reg_EDX = 0x00;
process->reg_ESI = 0x00;
process->reg_EDI = 0x00;
process->reg_EBP = 0x00;
process->reg_ESP = (bits32) USER_STACK_ADDR + PAGE_SIZE;
process->reg_CS = 0x23;
process->reg_DS = 0x2B;
process->reg_ES = 0x2B;
process->reg_FS = 0x2B;
process->reg_GS = 0x2B;
process->reg_SS = 0x33;
process->reg_EFLAGS = 0x200;
/* ======================================================= */
/* On créé le répertoire de pages */
process->pageDir = CreateTaskPageDirectory();
if(!process->pageDir)
{
free(process);
free(child);
print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47);
return 0;
}
process->reg_CR3 = (bits32) KernelGetPhyAddr(process->pageDir);
/* ================================================= */
/* La pile noyau */
process->kernelStackPtr = KernelGetPage();
if(!process->kernelStackPtr)
{
DestroyTaskPageDirectory(process->pageDir);
free(process);
free(child);
print("[CreateProcess] unable to create process, not enough kernel memory\n", 0x47);
return 0;
}
process->kernelStackPtr += PAGE_SIZE;
/* ================================================== */
/* On change d'espace d'adressage */
bits32 cr3 = _ReadCr3();
CurrentProcess->reg_CR3 = process->reg_CR3;
_LoadCr3(process->reg_CR3);
/* On créé la pile utilisateur */
if(!AddPage((T_Page) USER_STACK_ADDR, PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER))
{
CurrentProcess->reg_CR3 = cr3;
_LoadCr3(cr3);
KernelRemovePage(process->kernelStackPtr - PAGE_SIZE);
DestroyTaskPageDirectory(process->pageDir);
free(process);
free(child);
print("[CreateProcess] unable to create process, not enough memory\n", 0x47);
return 0;
}
/* ====================================================== */
process->reg_EIP = ELF32_Load(file, &process->processRegionsList);
if(!process->reg_EIP)
{
RemovePage((T_Page) USER_STACK_ADDR);
CurrentProcess->reg_CR3 = cr3;
_LoadCr3(cr3);
KernelRemovePage(process->kernelStackPtr - PAGE_SIZE);
DestroyTaskPageDirectory(process->pageDir);
free(process);
free(child);
print("[CreateProcess] unable to create process, elf error\n", 0x47);
return 0;
}
/* On restaure l'espace d'adressage */
CurrentProcess->reg_CR3 = cr3;
_LoadCr3(cr3);
/* On met à jour les tables */
PidCounter++;
LinkedListPushBack(child, &CurrentProcess->processChildrenList);
LinkedListPushBack(process, &Processes);
print("[CreateProcess] new process created with PID %d\n", DEFAULT_COLOR, process->pid);
return 1;
}
void DestroyProcess()
{
/*unsigned int i;
for(i = 0; i < ProcessNumber; i++)
{
struct ProcessModel *process = GetEntry(i, &Processes);
if(process == CurrentProcess)
{
unsigned int j;
print("Stopping process with PID %d\n", DEFAULT_COLOR, CurrentProcess->pid);
for(j = 0; j < CurrentProcess->codePageCount; j++)
{
RemovePage((bits32) USER_SPACE_BASE_ADDR + (j * PAGE_SIZE));
}
for(j = 0; j < CurrentProcess->allocatedPageCount; j++)
{
struct ProcessAllocatedPageModel *page = GetEntry(0, &CurrentProcess->allocatedPageList);
RemovePage(page->page_vaddr);
free(page);
RemoveEntry(0, &CurrentProcess->allocatedPageList);
}
RemovePage((bits32) USER_STACK_ADDR);
CurrentProcess->status = PROCESS_STATUS_ZOMBIE;
while(1)
{
asm("hlt");
}
KernelRemovePage(CurrentProcess->kernelStackPtr - PAGE_SIZE);
DestroyTaskPageDirectory(CurrentProcess->pageDir);
free(process);
bits32 eflags = _SaveEflags();
_ClearInterrupt();
RemoveEntry(i, &Processes);
ProcessNumber--;
_RestoreEflags(eflags)
}
}*/
}
void Process_0_Task()
{
print("[God] create Init process with PID 1\n", DEFAULT_COLOR);
CreateProcess((void*) arg->initProcessAddr);
while(1)
{
asm("hlt");
}
}
unsigned int ProcessCreateRegion_RO(T_Page startPage, T_Page* pglist, unsigned int pageCount, T_LinkedList* regionsList)
{
startPage &= 0xFFFFF000;
T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS);
if(!pageCount || startPage < USER_SPACE_BASE_ADDR || startPage >= USER_SPACE_END_ADDR || endPage >= USER_SPACE_END_ADDR)
{
print("[ProcessCreateRegion_RO] invalid region location\n", 0x47);
return 0;
}
struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry;
while(entry)
{
if(endPage > entry->startPage && endPage <= entry->endPage
|| startPage >= entry->startPage && startPage < entry->endPage
|| startPage <= entry->startPage && endPage >= entry->endPage)
{
print("[ProcessCreateRegion_RO] conflict between regions\n", 0x47);
return 0;
}
entry = entry->next;
}
unsigned int i, pc;
for(i = 0, pc = 0; i < pageCount; i++, pc++)
{
if(!LinkPhyPage(startPage + (i << PAGE_OFFSET_BITS), pglist[i] & 0xFFFFF000, PAGE_FLAG_PRESENT | PAGE_FLAG_USER))
{
goto error;
}
}
struct ProcessRegion* region = malloc(sizeof(struct ProcessRegion));
if(region)
{
region->startPage = startPage;
region->endPage = endPage;
region->type = (unsigned char) PROCESS_REGION_RO;
LinkedListPushBack(region, regionsList);
return 1;
}
error:
print("[ProcessCreateRegion_RO] unable to add region\n", 0x47);
for(i = 0; i < pc; i++)
{
UnlinkPhyPage(startPage + (i << PAGE_OFFSET_BITS));
}
return 0;
}
unsigned int ProcessCreateRegion_RW(T_Page startPage, unsigned int pageCount, T_LinkedList* regionsList)
{
startPage &= 0xFFFFF000;
T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS);
if(!pageCount || startPage < USER_SPACE_BASE_ADDR || startPage >= USER_SPACE_END_ADDR || endPage >= USER_SPACE_END_ADDR)
{
print("[ProcessCreateRegion_RW] invalid region location\n", 0x47);
return 0;
}
struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry;
while(entry)
{
if(endPage > entry->startPage && endPage <= entry->endPage
|| startPage >= entry->startPage && startPage < entry->endPage
|| startPage <= entry->startPage && endPage >= entry->endPage)
{
print("[ProcessCreateRegion_RW] conflict between regions\n", 0x47);
return 0;
}
entry = entry->next;
}
unsigned int i, pc;
for(i = 0, pc = 0; i < pageCount; i++, pc++)
{
if(!AddPage(startPage + (i << PAGE_OFFSET_BITS), PAGE_FLAG_PRESENT | PAGE_FLAG_RW | PAGE_FLAG_USER))
{
goto error;
}
}
struct ProcessRegion* region = malloc(sizeof(struct ProcessRegion));
if(region)
{
region->startPage = startPage;
region->endPage = endPage;
region->type = (unsigned char) PROCESS_REGION_RW;
LinkedListPushBack(region, regionsList);
return 1;
}
error:
print("[ProcessCreateRegion_RW] unable to add region\n", 0x47);
for(i = 0; i < pc; i++)
{
RemovePage(startPage + (i << PAGE_OFFSET_BITS));
}
return 0;
}
void ProcessRemoveRegion(T_Page startPage, unsigned int pageCount, T_LinkedList* regionsList)
{
startPage &= 0xFFFFF000;
T_Page endPage = startPage + (pageCount << PAGE_OFFSET_BITS);
struct ProcessRegion* entry = (struct ProcessRegion*) regionsList->firstEntry;
while(entry)
{
if(startPage == entry->startPage && endPage == entry->endPage)
{
unsigned int i;
if(entry->type == PROCESS_REGION_RO)
{
for(i = 0; i < pageCount; i++)
{
UnlinkPhyPage(startPage + (i << PAGE_OFFSET_BITS));
}
LinkedListRemove(entry, regionsList);
free(entry);
break;
}
else if(entry->type == PROCESS_REGION_RW)
{
for(i = 0; i < pageCount; i++)
{
RemovePage(startPage + (i << PAGE_OFFSET_BITS));
}
LinkedListRemove(entry, regionsList);
free(entry);
break;
}
}
entry = entry->next;
}
}

173
kernel/src/scheduler.c Normal file
View File

@ -0,0 +1,173 @@
/* scheduler.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "process.h"
#include "types.h"
#include "asm_x86.h"
#include "interrupt.h"
#include "signal.h"
T_Process* SchedulingAlgorithm()
{
T_Process *process = CurrentProcess;
do
{
if(process->next)
{
process = process->next;
}
else
{
process = (T_Process*) Processes.firstEntry;
}
if(process != CurrentProcess)
{
unsigned int i;
for(i = 0; i < 32; i++)
{
if(FetchSignal(i, process))
{
HandleSignal(i, process);
break;
}
}
if(process->status == PROCESS_STATUS_RUNNING)
{
return process;
}
else if(process->status == PROCESS_STATUS_WAIT_MUTEX) /* Si on attend un mutex */
{
/* On regard son etat */
if(!(*process->ipcWaitMutex))
{
process->status = PROCESS_STATUS_RUNNING;
*process->ipcWaitMutex = 1;
process->ipcWaitMutex = 0;
process->ipcInSection++;
return process;
}
}
/*else if(process->status == PROCESS_STATUS_SLEEP) si le processus est en sommeil
{
On regard si un wakeup à é envoyé
}*/
}
else
{
break;
}
}while(1);
if(Process_0.status == PROCESS_STATUS_RUNNING)
{
return &Process_0;
}
else
{
return CurrentProcess;
}
}
void Schedule()
{
bits32 *context = _SaveContex();
bits32 *curStackFrame = (bits32*) _GetStackFrameAddr(0);
_ClearInterrupt();
CurrentProcess->reg_GS = (bits16) context[0];
CurrentProcess->reg_FS = (bits16) context[1];
CurrentProcess->reg_ES = (bits16) context[2];
CurrentProcess->reg_DS = (bits16) context[3];
CurrentProcess->reg_EDI = context[4];
CurrentProcess->reg_ESI = context[5];
CurrentProcess->reg_EBP = curStackFrame[0]; /* ebp de la fonction précédente */
CurrentProcess->reg_EBX = context[8];
CurrentProcess->reg_EDX = context[9];
CurrentProcess->reg_ECX = context[10];
CurrentProcess->reg_EAX = context[11];
CurrentProcess->reg_EIP = curStackFrame[1]; /* eip de retour */
CurrentProcess->reg_CS = 0x08;
CurrentProcess->reg_EFLAGS = (context[12] | 0x200) & 0xFFFFBFFF;
CurrentProcess->reg_ESP = (bits32) &curStackFrame[2];
CurrentProcess->reg_SS = 0x18;
CurrentProcess = SchedulingAlgorithm();
tss->ss0 = 0x18;
tss->esp0 = CurrentProcess->kernelStackPtr;
_LoadContext(CurrentProcess);
}
void ScheduleAtClock()
{
if(!CurrentProcess && Processes.entryCount > 0)
{
CurrentProcess = (T_Process*) Processes.firstEntry;
}
else if(Processes.entryCount <= 1)
{
return;
}
else if(Processes.entryCount > 1)
{
bits32 *context = (bits32*) (_GetStackFrameAddr(1) + 8);
/* Registre empilés manuellement */
CurrentProcess->reg_GS = (bits16) context[0];
CurrentProcess->reg_FS = (bits16) context[1];
CurrentProcess->reg_ES = (bits16) context[2];
CurrentProcess->reg_DS = (bits16) context[3];
CurrentProcess->reg_EDI = context[4];
CurrentProcess->reg_ESI = context[5];
CurrentProcess->reg_EBP = context[6];
/* ESP context[7] inutile */
CurrentProcess->reg_EBX = context[8];
CurrentProcess->reg_EDX = context[9];
CurrentProcess->reg_ECX = context[10];
CurrentProcess->reg_EAX = context[11];
/* registres empliés automatiquement */
CurrentProcess->reg_EIP = context[12];
CurrentProcess->reg_CS = (bits16) context[13];
CurrentProcess->reg_EFLAGS = (context[14] | 0x200) & 0xFFFFBFFF;
if(CurrentProcess->reg_CS == 0x08)
{
CurrentProcess->reg_ESP = (bits32) &context[15];
CurrentProcess->reg_SS = 0x18;
}
else
{
CurrentProcess->reg_ESP = context[15];
CurrentProcess->reg_SS = (bits16) context[16];
}
CurrentProcess = SchedulingAlgorithm();
}
tss->ss0 = 0x18;
tss->esp0 = CurrentProcess->kernelStackPtr;
PIC_Send_EOI();
_LoadContext(CurrentProcess);
}

79
kernel/src/signal.c Normal file
View File

@ -0,0 +1,79 @@
/* signal.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "signal.h"
#include "process.h"
void SendSignal(unsigned int num, T_Process* process)
{
if(num < 32)
{
process->signal |= (1 << num);
}
}
void ClearSignal(unsigned int num, T_Process* process)
{
if(num < 32)
{
process->signal &= ~(1 << num);
}
}
unsigned int FetchSignal(unsigned int num, T_Process* process)
{
if(num < 32)
{
if(process->signal & (1 << num))
{
return 1;
}
else
{
return 0;
}
}
}
void HandleSignal(unsigned int signal, T_Process* process)
{
switch(signal)
{
case SIGNAL_KILL:
print("Process with PID %d received the signal 0 (KILL)\n", DEFAULT_COLOR, process->pid);
break;
case SIGNAL_TERM:
print("Process with PID %d received the signal 1 (TERM)\n", DEFAULT_COLOR, process->pid);
break;
case SIGNAL_KCHILD:
print("Process with PID %d received the signal 2 (KCHILD)\n", DEFAULT_COLOR, process->pid);
break;
default:
print("Process with PID %d received an unknown signal\n", DEFAULT_COLOR, process->pid);
break;
}
ClearSignal(signal, process);
}

72
kernel/src/systemCall.c Normal file
View File

@ -0,0 +1,72 @@
/* systemCall.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "types.h"
#include "print.h"
#include "process.h"
#include "asm_x86.h"
void ExecSystemCall(int sc_num)
{
bits8 *arg;
int i;
unsigned int a = 1;
switch(sc_num)
{
case 1:
asm("mov %%ebx, %0" :: "m" (arg));
PutCharVterm(*arg, 0x0F, CurrentProcess->vterm);
break;
case 2:
asm("mov %%ebx, %0" :: "m" (arg));
ReadInputVterm(arg, CurrentProcess->vterm);
break;
case 3:
/*asm("mov %%ebx, %0" :: "m" (arg));
if(!CreateProcess(arg, 1))
{
CurrentProcess->status = 2;
Schedule();
}*/
break;
case 4:
DestroyProcess();
case 5:
CurrentProcess->status = 2;
Schedule();
/*while(CurrentProcess->status == 2)
{
asm("hlt");
}*/
break;
default:
print("ERREUR : UNKNOW SYSTEM CALL !\n", 0x47);
_ClearInterrupt();
asm("hlt");
break;
}
return;
}

321
kernel/src/utils.c Normal file
View File

@ -0,0 +1,321 @@
/* utils.c - This file is a part of NutsOS
*
* NutsOS
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* NutsOS is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* NutsOS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with NutsOS; If not, see <http://www.gnu.org/licenses/>.
*
* Valentin Verdier <valentin.verdier03@gmail.com>
*/
#include "utils.h"
#include "types.h"
#include "asm_x86.h"
void memcopy(char *src, char *dst, unsigned int n)
{
unsigned int i;
for(i = 0; i < n; i++)
{
dst[i] = src[i];
}
}
int strcmp(char *str1, char *str2)
{
unsigned int i;
int length1 = 0;
int length2 = 0;
while(str1[length1] != 0)
{
length1++;
}
while(str2[length2] != 0)
{
length2++;
}
if(length1 == length2)
{
for(i = 0; i < length1; i++)
{
if(str1[i] != str2[i])
{
return 0;
}
}
}
else
{
return 0;
}
return 1;
}
void IntToChar(bits32 num, char *str, int base)
{
const char digit[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
int i, j, a;
int length;
int tmp = 0;
int counter = 0;
for(i = 0; i < 10; i++)
{
if(num / expo(base, i) < base)
{
length = i;
break;
}
}
j = length;
for(i = 0; i <= length; i++)
{
a = num / expo(base, j);
str[counter] = digit[a - base * tmp];
tmp = a;
counter++;
j--;
}
str[counter] = 0;
}
unsigned int expo(unsigned int x, unsigned int y)
{
if(y > 0)
{
unsigned int i, res = x;
for(i = 1; i < y; i++)
{
res *= x;
}
return res;
}
else
{
return 1;
}
}
void LinkedListPushFront(void *addr, T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *entry = addr;
if(list->entryCount > 0)
{
InsertElement(0, entry, list->firstEntry);
}
else
{
InsertElement(0, entry, 0);
list->lastEntry = entry;
}
list->firstEntry = entry;
list->entryCount++;
_RestoreEflags(eflags);
}
void LinkedListPopFront(T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *nextEntry = list->firstEntry->next;
if(list->entryCount > 1)
{
RemoveElement(list->firstEntry);
list->firstEntry = nextEntry;
}
else
{
list->firstEntry = 0;
list->lastEntry = 0;
}
list->entryCount--;
_RestoreEflags(eflags);
}
void LinkedListPushBack(void *addr, T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *entry = addr;
if(list->entryCount > 0)
{
InsertElement(list->lastEntry, entry, 0);
}
else
{
InsertElement(0, entry, 0);
list->firstEntry = entry;
}
list->lastEntry = entry;
list->entryCount++;
_RestoreEflags(eflags);
}
void LinkedListPopBack(T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *previousEntry = list->lastEntry->prev;
if(list->entryCount > 1)
{
RemoveElement(list->lastEntry);
list->lastEntry = previousEntry;
}
else
{
list->firstEntry = 0;
list->lastEntry = 0;
}
list->entryCount--;
_RestoreEflags(eflags);
}
void LinkedListInsert(void *prev, void *addr, void *next, T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *previousEntry = prev;
struct ElementModel *entry = addr;
struct ElementModel *nextEntry = next;
if(nextEntry == list->firstEntry)
{
LinkedListPushFront(entry, list);
}
else if(previousEntry == list->lastEntry)
{
LinkedListPushBack(entry, list);
}
else
{
InsertElement(previousEntry, entry, nextEntry);
list->entryCount++;
}
_RestoreEflags(eflags);
}
void LinkedListRemove(void *addr, T_LinkedList *list)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *entry = addr;
if(entry == list->firstEntry)
{
LinkedListPopFront(list);
}
else if(entry == list->lastEntry)
{
LinkedListPopBack(list);
}
else
{
RemoveElement(entry);
list->entryCount--;
}
_RestoreEflags(eflags);
}
void InsertElement(void *prev, void *addr, void *next)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *previousEntry = prev;
struct ElementModel *entry = addr;
struct ElementModel *nextEntry = next;
if(previousEntry)
{
entry->prev = previousEntry;
previousEntry->next = entry;
}
else
{
entry->prev = 0;
}
if(nextEntry)
{
entry->next = nextEntry;
nextEntry->prev = entry;
}
else
{
entry->next = 0;
}
_RestoreEflags(eflags);
}
void RemoveElement(void *addr)
{
bits32 eflags = _SaveEflags();
_ClearInterrupt();
struct ElementModel *entry = addr;
struct ElementModel *previousEntry = entry->prev;
struct ElementModel *nextEntry = entry->next;
if(previousEntry)
{
if(nextEntry)
{
previousEntry->next = nextEntry;
}
else
{
previousEntry->next = 0;
}
}
if(nextEntry)
{
if(previousEntry)
{
nextEntry->prev = previousEntry;
}
else
{
nextEntry->prev = 0;
}
}
_RestoreEflags(eflags);
}

45
test/bochsrc Normal file
View File

@ -0,0 +1,45 @@
config_interface: textconfig
display_library: sdl, options="gui_debug"
romimage: file="/usr/local/share/bochs/BIOS-bochs-latest"
cpu: count=1, ips=4000000, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0
#cpuid: level=6, stepping=3, model=3, family=6, vendor_string="AuthenticAMD", brand_string="AMD Athlon(tm) processor"
#cpuid: mmx=1, apic=xapic, sse=sse2, sse4a=0, misaligned_sse=0, sep=1, movbe=0, adx=0
#cpuid: aes=0, xsave=0, xsaveopt=0, x86_64=0, 1g_pages=0, pcid=0, fsgsbase=0, smep=0
#cpuid: smap=0, mwait=0, vmx=0
memory: host=64, guest=128
vgaromimage: file="/usr/local/share/bochs/VGABIOS-lgpl-latest"
vga: extension=vbe, update_freq=5
boot: disk
floppy_bootsig_check: disabled=0
# no floppya
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0
ata3: enabled=0
ata0-master: type=disk, mode=flat, path="disk.img"
ata0-slave: type=none
ata1-master: type=none
ata1-slave: type=none
pci: enabled=1, chipset=i440fx
debugger_log: -
private_colormap: enabled=0
clock: sync=slowdoown, time0=utc
log: /dev/stdout
debug: action=ignore
info: action=report
error: action=report
panic: action=ask
keyboard: serial_delay=250, paste_delay=100000
keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/sdl-pc-us.map

894
test/bochsrc_model Normal file
View File

@ -0,0 +1,894 @@
# You may now use double quotes around pathnames, in case
# your pathname includes spaces.
#=======================================================================
# CONFIG_INTERFACE
#
# The configuration interface is a series of menus or dialog boxes that
# allows you to change all the settings that control Bochs's behavior.
# Depending on the platform there are up to 3 choices of configuration
# interface: a text mode version called "textconfig" and two graphical versions
# called "win32config" and "wx". The text mode version uses stdin/stdout and
# is always compiled in, unless Bochs is compiled for wx only. The choice
# "win32config" is only available on win32 and it is the default there.
# The choice "wx" is only available when you use "--with-wx" on the configure
# command. If you do not write a config_interface line, Bochs will
# choose a default for you.
#
# NOTE: if you use the "wx" configuration interface, you must also use
# the "wx" display library.
#=======================================================================
config_interface: textconfig
#config_interface: wx
#=======================================================================
# DISPLAY_LIBRARY
#
# The display library is the code that displays the Bochs VGA screen. Bochs
# has a selection of about 10 different display library implementations for
# different platforms. If you run configure with multiple --with-* options,
# the display_library command lets you choose which one you want to run with.
# If you do not write a display_library line, Bochs will choose a default for
# you.
#
# The choices are:
# x use X windows interface, cross platform
# sdl use SDL library, cross platform
# svga use SVGALIB library for Linux, allows graphics without X11
# term text only, uses curses/ncurses library, cross platform
# wx use wxWidgets library, cross platform
# nogui no display at all
#
# NOTE: if you use the "wx" configuration interface, you must also use
# the "wx" display library.
#
# Specific options:
# Some display libraries now support specific option to control their
# behaviour. See the examples below for currently supported options.
#=======================================================================
#display_library: nogui
#display_library: sdl, options="fullscreen" # startup in fullscreen mode
#display_library: term
#display_library: sdl
#display_library: x, options="hideIPS" # disable IPS output in status bar
display_library: sdl, options="gui_debug" # use GTK debugger gui
#=======================================================================
# ROMIMAGE:
# The ROM BIOS controls what the PC does when it first powers on.
# Normally, you can use a precompiled BIOS in the source or binary
# distribution called BIOS-bochs-latest. The ROM BIOS is usually loaded
# starting at address 0xf0000, and it is exactly 64k long. Another option
# is 128k BIOS which is loaded at address 0xe0000.
# You can also use the environment variable $BXSHARE to specify the
# location of the BIOS.
# The usage of external large BIOS images (up to 512k) at memory top is
# now supported, but we still recommend to use the BIOS distributed with
# Bochs. The start address optional, since it can be calculated from image size.
#=======================================================================
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest
#romimage: file=bios/seabios-0.5.1.bin
#romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top
#=======================================================================
# CPU:
# This defines cpu-related parameters inside Bochs:
#
# COUNT:
# Set the number of processors:cores per processor:threads per core
# when Bochs is compiled for SMP emulation.
# Bochs currently supports up to 8 threads running simultaniosly.
# If Bochs is compiled without SMP support, it won't accept values
# different from 1.
#
# QUANTUM:
# Maximum amount of instructions allowed to execute by processor before
# returning control to another cpu. This option exists only in Bochs
# binary compiled with SMP support.
#
# RESET_ON_TRIPLE_FAULT:
# Reset the CPU when triple fault occur (highly recommended) rather than
# PANIC. Remember that if you trying to continue after triple fault the
# simulation will be completely bogus !
#
# MSRS:
# Define path to user CPU Model Specific Registers (MSRs) specification.
# See example in msrs.def.
#
# IGNORE_BAD_MSRS:
# Ignore MSR references that Bochs does not understand; print a warning
# message instead of generating #GP exception. This option is enabled
# by default but will not be avaiable if configurable MSRs are enabled.
#
# IPS:
# Emulated Instructions Per Second. This is the number of IPS that bochs
# is capable of running on your machine. You can recompile Bochs with
# --enable-show-ips option enabled, to find your host's capability.
# Measured IPS value will then be logged into your log file or shown
# in the status bar (if supported by the gui).
#
# IPS is used to calibrate many time-dependent events within the bochs
# simulation. For example, changing IPS affects the frequency of VGA
# updates, the duration of time before a key starts to autorepeat, and
# the measurement of BogoMips and other benchmarks.
#
# Examples:
#
# Bochs Machine/Compiler Mips
# ____________________________________________________________________
# 2.3.7 3.2Ghz Intel Core 2 Q9770 with WinXP/g++ 3.4 50 to 55 Mips
# 2.3.7 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 38 to 43 Mips
# 2.2.6 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 21 to 25 Mips
# 2.2.6 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips
# 2.0.1 1.6Ghz Intel P4 with Win2000/g++ 3.3 5 to 7 Mips
#=======================================================================
cpu: count=1, ips=19000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def"
#=======================================================================
# CPUID:
#
# This defines features and functionality supported by Bochs emulated CPU:
#
# MMX:
# Select MMX instruction set support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5.
#
# SEP:
# Select SYSENTER/SYSEXIT instruction set support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# SSE:
# Select SSE instruction set support.
# Any of NONE/SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2 could be selected.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# XAPIC:
# Select XAPIC extensions support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# AES:
# Select AES instruction set support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# MOVBE:
# Select MOVBE Intel(R) Atom instruction support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# XSAVE:
# Select XSAVE extensions support.
# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6.
#
# 1G_PAGES:
# Enable 1G page size support in long mode.
# This option exists only if Bochs compiled with x86-64 support.
#
# MWAIT_IS_NOP:
# When this option is enabled MWAIT will not put the CPU into a sleep state.
# This option exists only if Bochs compiled with --enable-monitor-mwait.
#
# VENDOR_STRING:
# Set the CPUID vendor string returned by CPUID(0x0). This should be a
# twelve-character ASCII string.
#
# BRAND_STRING:
# Set the CPUID vendor string returned by CPUID(0x80000002 .. 0x80000004).
# This should be at most a forty-eight-character ASCII string.
#
# CPUID_LIMIT_WINNT:
# Determine whether to limit maximum CPUID function to 3. This mode is
# required to workaround WinNT installation and boot issues.
#=======================================================================
cpuid: mmx=1, sep=1, sse=sse4_2, aes=1, movbe=1, xsave=1
#=======================================================================
# MEMORY
# Set the amount of physical memory you want to emulate.
#
# GUEST:
# Set amount of guest physical memory to emulate. The default is 32MB,
# the maximum amount limited only by physical address space limitations.
#
# HOST:
# Set amount of host memory you want to allocate for guest RAM emulation.
# It is possible to allocate less memory than you want to emulate in guest
# system. This will fake guest to see the non-existing memory. Once guest
# system touches new memory block it will be dynamically taken from the
# memory pool. You will be warned (by FATAL PANIC) in case guest already
# used all allocated host memory and wants more.
#
#=======================================================================
memory: guest=64, host=128
#=======================================================================
# OPTROMIMAGE[1-4]:
# You may now load up to 4 optional ROM images. Be sure to use a
# read-only area, typically between C8000 and EFFFF. These optional
# ROM images should not overwrite the rombios (located at
# F0000-FFFFF) and the videobios (located at C0000-C7FFF).
# Those ROM images will be initialized by the bios if they contain
# the right signature (0x55AA) and a valid checksum.
# It can also be a convenient way to upload some arbitrary code/data
# in the simulation, that can be retrieved by the boot loader
#=======================================================================
#optromimage1: file=optionalrom.bin, address=0xd0000
#optromimage2: file=optionalrom.bin, address=0xd1000
#optromimage3: file=optionalrom.bin, address=0xd2000
#optromimage4: file=optionalrom.bin, address=0xd3000
#optramimage1: file=/path/file1.img, address=0x0010000
#optramimage2: file=/path/file2.img, address=0x0020000
#optramimage3: file=/path/file3.img, address=0x0030000
#optramimage4: file=/path/file4.img, address=0x0040000
#=======================================================================
# VGAROMIMAGE
# You now need to load a VGA ROM BIOS into C0000.
#=======================================================================
vgaromimage: file=/usr/local/share/bochs/VGABIOS-lgpl-latest
#vgaromimage: file=/usr/share/vgabios/vgabios.debug.bin
#=======================================================================
# VGA:
# Here you can specify the display extension to be used. With the value
# 'none' you can use standard VGA with no extension. Other supported
# values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support.
#=======================================================================
#vga: extension=cirrus
vga: extension=vbe
#=======================================================================
# FLOPPYA:
# Point this to pathname of floppy image file or device
# This should be of a bootable floppy(image/device) if you're
# booting from 'a' (or 'floppy').
#
# You can set the initial status of the media to 'ejected' or 'inserted'.
# floppya: 2_88=path, status=ejected (2.88M 3.5" media)
# floppya: 1_44=path, status=inserted (1.44M 3.5" media)
# floppya: 1_2=path, status=ejected (1.2M 5.25" media)
# floppya: 720k=path, status=inserted (720K 3.5" media)
# floppya: 360k=path, status=inserted (360K 5.25" media)
# floppya: 320k=path, status=inserted (320K 5.25" media)
# floppya: 180k=path, status=inserted (180K 5.25" media)
# floppya: 160k=path, status=inserted (160K 5.25" media)
# floppya: image=path, status=inserted (guess media type from image size)
# floppya: type=1_44 (1.44M 3.5" floppy drive, no media)
#
# The path should be the name of a disk image file. On Unix, you can use a raw
# device name such as /dev/fd0 on Linux. On win32 platforms, use drive letters
# such as a: or b: as the path. The parameter 'image' works with image files
# only. In that case the size must match one of the supported types.
# The parameter 'type' can be used to enable the floppy drive without media
# and status specified. Usually the drive type is set up based on the media type.
#=======================================================================
#floppya: 1_44=/dev/fd0, status=inserted
#floppya: image=../1.44, status=inserted
#floppya: 1_44=/dev/fd0H1440, status=inserted
#floppya: 1_2=../1_2, status=inserted
#floppya: 1_44=a:, status=inserted
#floppya: 2_88=floppyA.img, status=inserted
#floppya: 1_44=/dev/rfd0a, status=inserted
#=======================================================================
# FLOPPYB:
# See FLOPPYA above for syntax
#=======================================================================
#floppyb: 1_44=b:, status=inserted
#floppyb: 1_44=b.img, status=inserted
#=======================================================================
# ATA0, ATA1, ATA2, ATA3
# ATA controller for hard disks and cdroms
#
# ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number
#
# These options enables up to 4 ata channels. For each channel
# the two base io addresses and the irq must be specified.
#
# ata0 and ata1 are enabled by default with the values shown below
#
# Examples:
# ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
# ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
# ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
# ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9
#=======================================================================
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9
#=======================================================================
# ATA[0-3]-MASTER, ATA[0-3]-SLAVE
#
# This defines the type and characteristics of all attached ata devices:
# type= type of attached device [disk|cdrom]
# mode= only valid for disks [flat|concat|external|dll|sparse|vmware3]
# mode= only valid for disks [undoable|growing|volatile]
# path= path of the image
# cylinders= only valid for disks
# heads= only valid for disks
# spt= only valid for disks
# status= only valid for cdroms [inserted|ejected]
# biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos]
# translation=type of translation of the bios, only for disks [none|lba|large|rechs|auto]
# model= string returned by identify device command
# journal= optional filename of the redolog for undoable and volatile disks
#
# Point this at a hard disk image file, cdrom iso file, or physical cdrom
# device. To create a hard disk image, try running bximage. It will help you
# choose the size and then suggest a line that works with it.
#
# In UNIX it may be possible to use a raw device as a Bochs hard disk,
# but WE DON'T RECOMMEND IT. In Windows there is no easy way.
#
# In windows, the drive letter + colon notation should be used for cdroms.
# Depending on versions of windows and drivers, you may only be able to
# access the "first" cdrom in the system. On MacOSX, use path="drive"
# to access the physical drive.
#
# The path is mandatory for hard disks. Disk geometry autodetection works with
# images created by bximage if CHS is set to 0/0/0 (cylinders are calculated
# using heads=16 and spt=63). For other hard disk images and modes the
# cylinders, heads, and spt are mandatory. In all cases the disk size reported
# from the image must be exactly C*H*S*512.
#
# Default values are:
# mode=flat, biosdetect=auto, translation=auto, model="Generic 1234"
#
# The biosdetect option has currently no effect on the bios
#
# Examples:
# ata0-master: type=disk, mode=flat, path=10M.sample, cylinders=306, heads=4, spt=17
# ata0-slave: type=disk, mode=flat, path=20M.sample, cylinders=615, heads=4, spt=17
# ata1-master: type=disk, mode=flat, path=30M.sample, cylinders=615, heads=6, spt=17
# ata1-slave: type=disk, mode=flat, path=46M.sample, cylinders=940, heads=6, spt=17
# ata2-master: type=disk, mode=flat, path=62M.sample, cylinders=940, heads=8, spt=17
# ata2-slave: type=disk, mode=flat, path=112M.sample, cylinders=900, heads=15, spt=17
# ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63
# ata3-slave: type=cdrom, path=iso.sample, status=inserted
#=======================================================================
#ata0-master: type=disk, mode=flat, path="disk.img"
ata1-slave: type=disk, mode=flat, path="disk.img"
#ata0-slave: type=cdrom, path=/dev/sr0, status=inserted
#ata0-slave: type=cdrom, path=BOOTCD.iso, status=inserted
#=======================================================================
# BOOT:
# This defines the boot sequence. Now you can specify up to 3 boot drives,
# which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM).
# Legacy 'a' and 'c' are also supported.
# Examples:
# boot: floppy
# boot: cdrom, disk
# boot: network, disk
# boot: cdrom, floppy, disk
#=======================================================================
#boot: floppy
boot: disk
#boot: cdrom
#=======================================================================
# CLOCK:
# This defines the parameters of the clock inside Bochs:
#
# SYNC:
# This defines the method how to synchronize the Bochs internal time
# with realtime. With the value 'none' the Bochs time relies on the IPS
# value and no host time synchronization is used. The 'slowdown' method
# sacrifices performance to preserve reproducibility while allowing host
# time correlation. The 'realtime' method sacrifices reproducibility to
# preserve performance and host-time correlation.
# It is possible to enable both synchronization methods.
#
# TIME0:
# Specifies the start (boot) time of the virtual machine. Use a time
# value as returned by the time(2) system call. If no time0 value is
# set or if time0 equal to 1 (special case) or if time0 equal 'local',
# the simulation will be started at the current local host time.
# If time0 equal to 2 (special case) or if time0 equal 'utc',
# the simulation will be started at the current utc time.
#
# Syntax:
# clock: sync=[none|slowdown|realtime|both], time0=[timeValue|local|utc]
#
# Example:
# clock: sync=none, time0=local # Now (localtime)
# clock: sync=slowdown, time0=315529200 # Tue Jan 1 00:00:00 1980
# clock: sync=none, time0=631148400 # Mon Jan 1 00:00:00 1990
# clock: sync=realtime, time0=938581955 # Wed Sep 29 07:12:35 1999
# clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000
# clock: sync=none, time0=1 # Now (localtime)
# clock: sync=none, time0=utc # Now (utc/gmt)
#
# Default value are sync=none, time0=local
#=======================================================================
clock: sync=none, time0=utc
#=======================================================================
# FLOPPY_BOOTSIG_CHECK: disabled=[0|1]
# Enables or disables the 0xaa55 signature check on boot floppies
# Defaults to disabled=0
# Examples:
# floppy_bootsig_check: disabled=0
# floppy_bootsig_check: disabled=1
#=======================================================================
floppy_bootsig_check: disabled=0
#=======================================================================
# LOG:
# Give the path of the log file you'd like Bochs debug and misc. verbiage
# to be written to. If you don't use this option or set the filename to
# '-' the output is written to the console. If you really don't want it,
# make it "/dev/null" (Unix) or "nul" (win32). :^(
#
# Examples:
# log: ./bochs.out
# log: /dev/tty
#=======================================================================
log: /dev/stdout
#log: /dev/null
#log: /tmp/bochsout.txt
#=======================================================================
# LOGPREFIX:
# This handles the format of the string prepended to each log line.
# You may use those special tokens :
# %t : 11 decimal digits timer tick
# %i : 8 hexadecimal digits of cpu current eip (ignored in SMP configuration)
# %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror)
# %d : 5 characters string of the device, between brackets
#
# Default : %t%e%d
# Examples:
# logprefix: %t-%e-@%i-%d
# logprefix: %i%e%d
#=======================================================================
#logprefix: %t%e%d
#=======================================================================
# LOG CONTROLS
#
# Bochs now has four severity levels for event logging.
# panic: cannot proceed. If you choose to continue after a panic,
# don't be surprised if you get strange behavior or crashes.
# error: something went wrong, but it is probably safe to continue the
# simulation.
# info: interesting or useful messages.
# debug: messages useful only when debugging the code. This may
# spit out thousands per second.
#
# For events of each level, you can choose to crash, report, or ignore.
# TODO: allow choice based on the facility: e.g. crash on panics from
# everything except the cdrom, and only report those.
#
# If you are experiencing many panics, it can be helpful to change
# the panic action to report instead of fatal. However, be aware
# that anything executed after a panic is uncharted territory and can
# cause bochs to become unstable. The panic is a "graceful exit," so
# if you disable it you may get a spectacular disaster instead.
#=======================================================================
panic: action=ask
error: action=report
info: action=report
debug: action=ignore
#pass: action=fatal
#=======================================================================
# DEBUGGER_LOG:
# Give the path of the log file you'd like Bochs to log debugger output.
# If you really don't want it, make it /dev/null or '-'. :^(
#
# Examples:
# debugger_log: ./debugger.out
#=======================================================================
#debugger_log: /dev/null
#debugger_log: debugger.out
debugger_log: -
#=======================================================================
# COM1, COM2, COM3, COM4:
# This defines a serial port (UART type 16550A). In the 'term' you can specify
# a device to use as com1. This can be a real serial line, or a pty. To use
# a pty (under X/Unix), create two windows (xterms, usually). One of them will
# run bochs, and the other will act as com1. Find out the tty the com1
# window using the `tty' command, and use that as the `dev' parameter.
# Then do `sleep 1000000' in the com1 window to keep the shell from
# messing with things, and run bochs in the other window. Serial I/O to
# com1 (port 0x3f8) will all go to the other window.
# In socket* and pipe* (win32 only) modes Bochs becomes either socket/named pipe
# client or server. In client mode it connects to an already running server (if
# connection fails Bochs treats com port as not connected). In server mode it
# opens socket/named pipe and waits until a client application connects to it
# before starting simulation. This mode is useful for remote debugging (e.g.
# with gdb's "target remote host:port" command or windbg's command line option
# -k com:pipe,port=\\.\pipe\pipename). Note: 'socket' is a shorthand for
# 'socket-client' and 'pipe' for 'pipe-client'. Socket modes use simple TCP
# communication, pipe modes use duplex byte mode pipes.
# Other serial modes are 'null' (no input/output), 'file' (output to a file
# specified as the 'dev' parameter), 'raw' (use the real serial port - under
# construction for win32), 'mouse' (standard serial mouse - requires
# mouse option setting 'type=serial', 'type=serial_wheel' or 'type=serial_msys').
#
# Examples:
# com1: enabled=1, mode=null
# com1: enabled=1, mode=mouse
# com2: enabled=1, mode=file, dev=serial.out
# com3: enabled=1, mode=raw, dev=com1
# com3: enabled=1, mode=socket-client, dev=localhost:8888
# com3: enabled=1, mode=socket-server, dev=localhost:8888
# com4: enabled=1, mode=pipe-client, dev=\\.\pipe\mypipe
# com4: enabled=1, mode=pipe-server, dev=\\.\pipe\mypipe
#=======================================================================
#com1: enabled=1, mode=term, dev=/dev/ttyS0
#=======================================================================
# PARPORT1, PARPORT2:
# This defines a parallel (printer) port. When turned on and an output file is
# defined the emulated printer port sends characters printed by the guest OS
# into the output file. On some platforms a device filename can be used to
# send the data to the real parallel port (e.g. "/dev/lp0" on Linux, "lpt1" on
# win32 platforms).
#
# Examples:
# parport1: enabled=1, file="parport.out"
# parport2: enabled=1, file="/dev/lp0"
# parport1: enabled=0
#=======================================================================
#parport1: enabled=1, file="/dev/lp0"
#=======================================================================
# SB16:
# This defines the SB16 sound emulation. It can have several of the
# following properties.
# All properties are in the format sb16: property=value
# midi: The filename is where the midi data is sent. This can be a
# device or just a file if you want to record the midi data.
# midimode:
# 0=no data
# 1=output to device (system dependent. midi denotes the device driver)
# 2=SMF file output, including headers
# 3=output the midi data stream to the file (no midi headers and no
# delta times, just command and data bytes)
# wave: This is the device/file where wave output is stored
# wavemode:
# 0=no data
# 1=output to device (system dependent. wave denotes the device driver)
# 2=VOC file output, incl. headers
# 3=output the raw wave stream to the file
# log: The file to write the sb16 emulator messages to.
# loglevel:
# 0=no log
# 1=resource changes, midi program and bank changes
# 2=severe errors
# 3=all errors
# 4=all errors plus all port accesses
# 5=all errors and port accesses plus a lot of extra info
# dmatimer:
# microseconds per second for a DMA cycle. Make it smaller to fix
# non-continuous sound. 750000 is usually a good value. This needs a
# reasonably correct setting for the IPS parameter of the CPU option.
#
# Examples for output devices:
# sb16: midimode=1, midi="", wavemode=1, wave="" # win32
# sb16: midimode=1, midi=alsa:128:0, wavemode=1, wave=alsa # Linux with ALSA
#=======================================================================
#sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=/dev/stdout, dmatimer=600000
#=======================================================================
# VGA_UPDATE_INTERVAL:
# Video memory is scanned for updates and screen updated every so many
# virtual seconds. The default is 50000, about 20Hz. Keep in mind that
# you must tweak the 'cpu: ips=N' directive to be as close to the number
# of emulated instructions-per-second your workstation can do, for this
# to be accurate.
#
# Examples:
# vga_update_interval: 250000
#=======================================================================
#vga_update_interval: 50000
#using for Winstone '98 tests
#vga_update_interval: 40000
#=======================================================================
# KEYBOARD_SERIAL_DELAY:
# Approximate time in microseconds that it takes one character to
# be transfered from the keyboard to controller over the serial path.
# Examples:
# keyboard_serial_delay: 200
#=======================================================================
keyboard_serial_delay: 250
#=======================================================================
# KEYBOARD_PASTE_DELAY:
# Approximate time in microseconds between attempts to paste
# characters to the keyboard controller. This leaves time for the
# guest os to deal with the flow of characters. The ideal setting
# depends on how your operating system processes characters. The
# default of 100000 usec (.1 seconds) was chosen because it works
# consistently in Windows.
#
# If your OS is losing characters during a paste, increase the paste
# delay until it stops losing characters.
#
# Examples:
# keyboard_paste_delay: 100000
#=======================================================================
keyboard_paste_delay: 100000
#=======================================================================
# MOUSE:
# The Bochs gui creates mouse "events" unless the 'enabled' option is
# set to 0. The hardware emulation itself is not disabled by this.
# Unless you have a particular reason for enabling the mouse by default,
# it is recommended that you leave it off. You can also toggle the mouse
# usage at runtime (control key + middle mouse button on X11, SDL,
# wxWidgets and Win32).
# With the mouse type option you can select the type of mouse to emulate.
# The default value is 'ps2'. The other choices are 'imps2' (wheel mouse
# on PS/2), 'serial', 'serial_wheel' and 'serial_msys' (one com port requires
# setting 'mode=mouse'). To connect a mouse to an USB port, see the 'usb_uhci'
# or 'usb_ohci' option (requires PCI and USB support).
#
# Examples:
# mouse: enabled=1
# mouse: enabled=1, type=imps2
# mouse: enabled=1, type=serial
# mouse: enabled=0
#=======================================================================
mouse: enabled=0
#=======================================================================
# private_colormap: Request that the GUI create and use it's own
# non-shared colormap. This colormap will be used
# when in the bochs window. If not enabled, a
# shared colormap scheme may be used. Not implemented
# on all GUI's.
#
# Examples:
# private_colormap: enabled=1
# private_colormap: enabled=0
#=======================================================================
private_colormap: enabled=0
#=======================================================================
# ne2k: NE2000 compatible ethernet adapter
#
# Examples:
# ne2k: ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT
#
# ioaddr, irq: You probably won't need to change ioaddr and irq, unless there
# are IRQ conflicts. These arguments are ignored when assign the ne2k to a
# PCI slot.
#
# mac: The MAC address MUST NOT match the address of any machine on the net.
# Also, the first byte must be an even number (bit 0 set means a multicast
# address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast
# address. For the ethertap module, you must use fe:fd:00:00:00:01. There may
# be other restrictions too. To be safe, just use the b0:c4... address.
#
# ethdev: The ethdev value is the name of the network interface on your host
# platform. On UNIX machines, you can get the name by running ifconfig. On
# Windows machines, you must run niclist to get the name of the ethdev.
# Niclist source code is in misc/niclist.c and it is included in Windows
# binary releases.
#
# script: The script value is optional, and is the name of a script that
# is executed after bochs initialize the network interface. You can use
# this script to configure this network interface, or enable masquerading.
# This is mainly useful for the tun/tap devices that only exist during
# Bochs execution. The network interface name is supplied to the script
# as first parameter
#
# If you don't want to make connections to any physical networks,
# you can use the following 'ethmod's to simulate a virtual network.
# null: All packets are discarded, but logged to a few files.
# arpback: ARP is simulated. Disabled by default.
# vde: Virtual Distributed Ethernet
# vnet: ARP, ICMP-echo(ping), DHCP and read/write TFTP are simulated.
# The virtual host uses 192.168.10.1.
# DHCP assigns 192.168.10.2 to the guest.
# TFTP uses the ethdev value for the root directory and doesn't
# overwrite files.
#
#=======================================================================
# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0
# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0
# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig
# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0
# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl"
# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp"
#=======================================================================
# pnic: Bochs/Etherboot pseudo-NIC
#
# Example:
# pnic: enabled=1, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT
#
# The pseudo-NIC accepts the same syntax (for mac, ethmod, ethdev, script) and
# supports the same networking modules as the NE2000 adapter. In addition to
# this, it must be assigned to a PCI slot.
#=======================================================================
#pnic: enabled=1, mac=b0:c4:20:00:00:00, ethmod=vnet
#=======================================================================
# KEYBOARD_MAPPING:
# This enables a remap of a physical localized keyboard to a
# virtualized us keyboard, as the PC architecture expects.
# If enabled, the keymap file must be specified.
#
# Examples:
# keyboard_mapping: enabled=1, map=gui/keymaps/x11-pc-de.map
#=======================================================================
keyboard_mapping: enabled=1, map=/usr/local/share/bochs/keymaps/sdl-pc-us.map
#=======================================================================
# KEYBOARD_TYPE:
# Type of keyboard return by a "identify keyboard" command to the
# keyboard controler. It must be one of "xt", "at" or "mf".
# Defaults to "mf". It should be ok for almost everybody. A known
# exception is french macs, that do have a "at"-like keyboard.
#
# Examples:
# keyboard_type: mf
#=======================================================================
#keyboard_type: mf
#=======================================================================
# USER_SHORTCUT:
# This defines the keyboard shortcut to be sent when you press the "user"
# button in the headerbar. The shortcut string is a combination of maximum
# 3 key names (listed below) separated with a '-' character.
# Valid key names:
# "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc",
# "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup",
# "plus", "right", "shift", "space", "tab", "up", "win", "print" and "power".
#
# Example:
# user_shortcut: keys=ctrl-alt-del
#=======================================================================
#user_shortcut: keys=ctrl-alt-del
#=======================================================================
# I440FXSUPPORT:
# This option controls the presence of the i440FX PCI chipset. You can
# also specify the devices connected to PCI slots. Up to 5 slots are
# available now. These devices are currently supported: ne2k, pcivga,
# pcidev, pcipnic and usb_ohci. If Bochs is compiled with Cirrus SVGA
# support you'll have the additional choice 'cirrus'.
#
# Example:
# i440fxsupport: enabled=1, slot1=pcivga, slot2=ne2k
#=======================================================================
#i440fxsupport: enabled=1
#=======================================================================
# USB_UHCI:
# This option controls the presence of the USB root hub which is a part
# of the i440FX PCI chipset. With the portX option you can connect devices
# to the hub (currently supported: 'mouse', 'tablet', 'keypad', 'disk', 'cdrom'
# 'hub' and 'printer').
#
# If you connect the mouse or tablet to one of the ports, Bochs forwards the
# mouse movement data to the USB device instead of the selected mouse type.
# When connecting the keypad to one of the ports, Bochs forwards the input of
# the numeric keypad to the USB device instead of the PS/2 keyboard.
#
# To connect a flat image as an USB hardisk you can use the 'disk' device with
# the path to the image separated with a colon (see below). To emulate an USB
# cdrom you can use the 'cdrom' device name and the path to an ISO image or raw
# device name also separated with a colon.
#
# The device name 'hub' connects an external hub with max. 8 ports (default: 4)
# to the root hub. To specify the number of ports you have to add the value
# separated with a colon. Connecting devices to the external hub ports is only
# available in the runtime configuration.
#
# The device 'printer' emulates the HP Deskjet 920C printer. The PCL data is
# sent to a file specified in bochsrc.txt. The current code appends the PCL
# code to the file if the file already existed. It would probably be nice to
# overwrite the file instead, asking user first.
#=======================================================================
#usb_uhci: enabled=1
#usb_uhci: enabled=1, port1=mouse, port2=disk:usbdisk.img
#usb_uhci: enabled=1, port1=hub:7, port2=cdrom:image.iso
#=======================================================================
# USB_OHCI:
# This option controls the presence of the USB OHCI host controller with a
# 2-port hub. The portX option accepts the same device types with the same
# syntax as the UHCI controller (see above). The OHCI HC must be assigned to
# a PCI slot.
#=======================================================================
#usb_ohci: enabled=1
#usb_ohci: enabled=1, port1=printer:usbprinter.bin
#=======================================================================
# CMOSIMAGE:
# This defines image file that can be loaded into the CMOS RAM at startup.
# The rtc_init parameter controls whether initialize the RTC with values stored
# in the image. By default the time0 argument given to the clock option is used.
# With 'rtc_init=image' the image is the source for the initial time.
#
# Example:
# cmosimage: file=cmos.img, rtc_init=image
#=======================================================================
#cmosimage: file=cmos.img, rtc_init=time0
#=======================================================================
# MAGIC_BREAK:
# This enables the "magic breakpoint" feature when using the debugger.
# The useless cpu instruction XCHG BX, BX causes Bochs to enter the
# debugger mode. This might be useful for software development.
#
# Example:
# magic_break: enabled=1
#=======================================================================
#magic_break: enabled=1
#=======================================================================
# PORT_E9_HACK:
# The 0xE9 port doesn't exists in normal ISA architecture. However, we
# define a convention here, to display on the console of the system running
# Bochs anything that is written to it. The idea is to provide debug output
# very early when writing BIOS or OS code for example, without having to
# bother with setting up a serial port or etc. Reading from port 0xE9 will
# will return 0xe9 to let you know if the feature is available.
# Leave this 0 unless you have a reason to use it.
#
# Example:
# port_e9_hack: enabled=1
#=======================================================================
#port_e9_hack: enabled=1
#=======================================================================
# DEBUG_SYMBOLS:
# This loads symbols from the specified file for use in Bochs' internal
# debugger. Symbols are loaded into global context. This is equivalent to
# issuing ldsym debugger command at start up.
#
# Example:
# debug_symbols: file="kernel.sym"
# debug_symbols: file="kernel.sym", offset=0x80000000
#=======================================================================
#debug_symbols: file="kernel.sym"
#=======================================================================
# other stuff
#=======================================================================
#load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log
#load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img
#text_snapshot_check: enabled=1
#print_timestamps: enabled=1
#-------------------------
# PCI host device mapping
#-------------------------
#pcidev: vendor=0x1234, device=0x5678
#=======================================================================
# GDBSTUB:
# Enable GDB stub. See user documentation for details.
# Default value is enabled=0.
#=======================================================================
#gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0
#=======================================================================
# PLUGIN_CTRL:
# Controls the presence of optional plugins without a separate option.
# By default all existing plugins are enabled. These plugins are currently
# supported: 'acpi', 'biosdev', 'extfpuirq', 'gameport', 'iodebug',
# 'pci_ide', 'speaker' and 'unmapped'.
#=======================================================================
#plugin_ctrl: biosdev=0, speaker=0
#=======================================================================
# USER_PLUGIN:
# Load user-defined plugin. This option is available only if Bochs is
# compiled with plugin support. Maximum 8 different plugins are supported.
# See the example in the Bochs sources how to write a plugin device.
#=======================================================================
#user_plugin: name=testdev

19
test/init/Makefile Normal file
View File

@ -0,0 +1,19 @@
.PHONY: clean
CC=gcc
CFLAGS=-m32 -march=i486 -fno-zero-initialized-in-bss
LINKER=ld
LDFLAGS=-melf_i386 -Ttext=10000000 --entry=main
all: init
init: init.o
$(LINKER) $(LDFLAGS) $^ -o $@
%.o: %.c
$(CC) $(CFLAGS) -c $^ -o $@
clean:
-rm -f *.o init

12
test/init/init.c Normal file
View File

@ -0,0 +1,12 @@
void main()
{
char *msg1 = "NutsOS Init program\n";
while(*msg1 != 0)
{
asm("mov $1, %%eax; mov %0, %%ebx; int $0x40" :: "m"(msg1));
msg1++;
}
asm("mov $5, %eax; int $0x40");
}

128
test/ndmt Executable file
View File

@ -0,0 +1,128 @@
#!/usr/bin/python
import os
import subprocess
import time
# Variables globales
selectedDiskPath = ""
selectedMountPoint = ""
mountFlag = False
# Fonction SelectDisk : sélectionne une image disque
def SelectDisk(diskPath):
global selectedDiskPath
global mountFlag
if mountFlag == True:
print("Error : you must umount the current partition before select a new disk")
return -1
if os.path.isfile(diskPath) == True:
selectedDiskPath = diskPath
return 0
else:
print("Error : invalid disk path")
return -2
# Fonction SelectMountPoint : sélectionne un répertoire pour le montage
def SelectMountPoint(dirPath):
global selectedMountPoint
global mountFlag
if mountFlag == True:
print("Error : you must umount the current partition before select a new mount point")
return -1
if os.path.isdir(dirPath) == True:
selectedMountPoint = dirPath
return 0
else:
print("Error : invalid dir path")
return -2
# Fonction MountPart : Monte dans le répertoire sélectionné la partition <partNum> du disque sélectionné
def MountPart(partNum):
global selectedDiskPath
global selectedMountPoint
global mountFlag
if mountFlag == True:
print("Error : a partition is aready mounted")
return -1
if partNum >= 0 and partNum < 4:
uid = str(os.getuid())
gid = str(os.getgid())
off = subprocess.check_output(["tools/readpt", selectedDiskPath, str(partNum), "start_LBA"], stderr=None)
partOffset = str(int(off) * 512)
mountOptions = "loop,rw,offset={0},users,uid={1},gid={2}".format(partOffset, uid, gid)
if subprocess.call(["/usr/bin/sudo", "/bin/mount", "-o", mountOptions, selectedDiskPath, selectedMountPoint], stdin=None, stdout=None, stderr=None) == 0:
time.sleep(1)
print("Partition ", partNum, " mounted")
mountFlag = True
return 0
else:
print("Error : unable to mount partition ", partNum)
return -3
else:
return -2
# Fonction UmountPart : Démonte la partition montée
def UmountPart():
global selectedMountPoint
global mountFlag
if mountFlag == False:
print("Error : no partition mounted")
return -1
if subprocess.call(["/usr/bin/sudo", "/bin/umount", selectedMountPoint], stdin=None, stdout=None, stderr=None) == 0:
time.sleep(1)
print("Umount partition")
mountFlag = False
return 0
else:
print("Error : unable to umount partition")
return -2
# Programme principal
print("\n########################################")
print("### NutsOS Disk Management Tool v1.0 ###")
print("########################################\n")
quit = False
while quit != True:
cmd = input("#> ")
args = cmd.split(sep=' ')
if args[0] == "seldisk":
if len(args) == 2:
SelectDisk(args[1])
else:
print("Command error : seldisk <disk>")
elif args[0] == "selmnt":
if len(args) == 2:
SelectMountPoint(args[1])
else:
print("Command error : selmnt <mountpoint>")
elif args[0] == "mount":
if len(args) == 2:
MountPart(int(args[1]))
else:
print("Command error : mount <partition>")
elif args[0] == "umount":
if len(args) == 1:
UmountPart()
else:
print("Command error : umount")
elif args[0] == "quit":
quit = True
if mountFlag == True:
UmountPart()
else:
print("Command error : unknown command")

84
test/tools/readpt.c Normal file
View File

@ -0,0 +1,84 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdint.h>
#define HD_SECTOR_SIZE 512
#define PARTITION_TABLE_START 0x1BE
#define PARTITION_TABLE_SIZE 64
typedef struct {
uint8_t bootSign;
uint8_t startHead;
uint8_t startSector:6;
uint16_t startCylinder:10;
uint8_t fsID;
uint8_t endHead;
uint8_t endSector:6;
uint16_t endCylinder:10;
uint32_t startLBA;
uint32_t sectorCount;
}__attribute__((packed)) T_PartitionTable;
int main(int argc, char* argv[]) {
if(argc == 4) {
char *diskPath = argv[1];
int partNum = atoi(argv[2]);
char* field = argv[3];
T_PartitionTable pt[4];
if(partNum < 0 || partNum > 3) {
fprintf(stderr, "Invalid partiton number\n");
return -1;
}
int fd = open(diskPath, O_RDONLY, 0664);
if(fd == -1) {
close(fd);
fprintf(stderr, "Error when openning the file <%s>\n", diskPath);
return -2;
}
lseek(fd, PARTITION_TABLE_START, SEEK_SET);
int bytesRead = read(fd, pt, PARTITION_TABLE_SIZE);
if(bytesRead == -1) {
close(fd);
fprintf(stderr, "Error when reading the file <%s>\n", diskPath);
return -3;
}
close(fd);
if(!strcmp(field, "boot_sign"))
printf("%u", pt[partNum].bootSign);
else if(!strcmp(field, "start_head"))
printf("%u", pt[partNum].startHead);
else if(!strcmp(field, "start_sector"))
printf("%u", pt[partNum].startSector);
else if(!strcmp(field, "start_cylinder"))
printf("%u", pt[partNum].startCylinder);
else if(!strcmp(field, "fs_ID"))
printf("%u", pt[partNum].fsID);
else if(!strcmp(field, "end_head"))
printf("%u", pt[partNum].endHead);
else if(!strcmp(field, "end_sector"))
printf("%u", pt[partNum].endSector);
else if(!strcmp(field, "end_cylinder"))
printf("%u", pt[partNum].endCylinder);
else if(!strcmp(field, "start_LBA"))
printf("%u", pt[partNum].startLBA);
else if(!strcmp(field, "sector_count"))
printf("%u", pt[partNum].sectorCount);
else {
perror("Invalid field name\n");
return -4;
}
} else {
fprintf(stderr, "[help] : readpt <disk> <partition> <field>\n");
fprintf(stderr, "Valid field names : boot_sign,start_head,start_sector,start_cylinder,fs_ID,end_head,end_sector,end_cylinder,start_LBA,sectorCount\n");
return -5;
}
return 0;
}

77
test/tools/w_kernLdr.c Normal file
View File

@ -0,0 +1,77 @@
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#define KERNLDR_START_SECTOR 1
#define HD_SECTOR_SIZE 512
int main(int argc, char* argv[])
{
if(argc == 3)
{
char *input = argv[1];
char *output = argv[2];
printf("Copy kernLdr from <%s> to <%s> :\n", input, output);
int inputFile = open(input, O_RDONLY , 0664);
if(inputFile == -1)
{
fprintf(stderr, "Error when openning file <%s>\n", input);
return 1;
}
int outputFile = open(output, O_WRONLY | O_CREAT, 0664);
if(outputFile == -1)
{
fprintf(stderr, "Error when openning file <%s>\n", output);
return 1;
}
lseek(inputFile, 0, SEEK_SET);
lseek(outputFile, HD_SECTOR_SIZE * KERNLDR_START_SECTOR, SEEK_SET);
struct stat info;
fstat(inputFile, &info);
unsigned int kernLdrCodeSize = info.st_size;
if(kernLdrCodeSize >= 32256)
{
perror("Error kernLdr is too large\n");
close(inputFile);
close(outputFile);
return 2;
}
unsigned char *kernLdrCode = malloc(kernLdrCodeSize);
int bytesRead = read(inputFile, kernLdrCode, kernLdrCodeSize);
if(bytesRead == -1)
{
perror("Reading error\n");
free(kernLdrCode);
close(inputFile);
close(outputFile);
return 3;
}
int bytesWrite = write(outputFile, kernLdrCode, kernLdrCodeSize);
if(bytesWrite == -1)
{
perror("Writing error\n");
free(kernLdrCode);
close(inputFile);
close(outputFile);
return 3;
}
free(kernLdrCode);
close(inputFile);
close(outputFile);
printf("done\n");
}
else
{
perror("[help] : w_kernLdr <kernLdr> <disk image>\n");
return 4;
}
return 0;
}

66
test/tools/w_mbr.c Normal file
View File

@ -0,0 +1,66 @@
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#define BOOT_CODE_SIZE 446
int main(int argc, char* argv[])
{
if(argc == 3)
{
char *input = argv[1];
char *output = argv[2];
printf("Copy bootcode from <%s> to <%s> :\n", input, output);
int inputFile = open(input, O_RDONLY , 0664);
if(inputFile == -1)
{
fprintf(stderr, "Error when openning file <%s>\n", input);
close(inputFile);
return 1;
}
int outputFile = open(output, O_WRONLY | O_CREAT, 0664);
if(outputFile == -1)
{
fprintf(stderr, "Error when openning file <%s>\n", output);
close(outputFile);
return 1;
}
lseek(inputFile, 0, SEEK_SET);
lseek(outputFile, 0, SEEK_SET);
unsigned char *bootCode = malloc(BOOT_CODE_SIZE);
int bytesRead = read(inputFile, bootCode, BOOT_CODE_SIZE);
if(bytesRead == -1)
{
perror("Reading error\n");
free(bootCode);
close(inputFile);
close(outputFile);
return 2;
}
int bytesWrite = write(outputFile, bootCode, BOOT_CODE_SIZE);
if(bytesWrite == -1)
{
perror("Writing error\n");
free(bootCode);
close(inputFile);
close(outputFile);
return 2;
}
free(bootCode);
close(inputFile);
close(outputFile);
printf("done\n");
}
else
{
fprintf(stderr, "[help] : w_mbr <boot code> <disk image>\n");
return 3;
}
return 0;
}