From 309a5fb95c6c80def804fca2be227d8f6e4c79e6 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 28 Feb 2023 22:24:32 -0500 Subject: [PATCH 001/147] Create LICENSE.md --- LICENSE.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..a5f9261 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Elaina Claus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From b9850f7ab92e24a0306dc01384f15d783e6a1317 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 10:36:35 -0400 Subject: [PATCH 002/147] Create README.md --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..f197e3a --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# stevia + +This is a hobby project that aims to create a simple and lightweight operating system kernel. It is written in Assembly and C, and uses the GNU toolchain and Bochs emulator. The project features (or is hoping to feature): + +- A boot loader that loads the kernel from a floppy disk image +- A kernel that implements basic functions, such as printing messages, handling interrupts, and managing memory +- A shell that allows user input and execution of commands +- A simple text editor that can create and edit files +- A calculator that can perform arithmetic operations +- (big maybe) micropython or some other language, cross compiling, etc... + +## Installation + +To build and run this project, you need to have the following tools installed: + +- GNU Binutils +- GNU GCC +- GNU Make +- NASM +- Bochs (for testing, project might run on other virtuization/emulation platforms, I target the Pentium 3 Era with this project) + +To build the project, run `make` in the root directory. This will generate a floppy disk image named `stevia.img` that contains the boot loader and the kernel. + +To run the project, run `bochs -f bochsrc.txt` in the root directory. This will launch the Bochs emulator and load the floppy disk image. You should see the boot loader message, followed by the kernel message, and then the shell prompt. + +To exit the emulator, press `Ctrl+C` in the terminal where you launched Bochs. + +## License + +This project is licensed under the MIT License and the GPL-3.0 License. See the [COPYING](^1^) and [LICENSE.md](^2^) files for details. + +Here are possible README.md files for each of your requested files: + +### mbr/mbr.s + +This file contains the code for a Master Boot Record (MBR) that loads the boot loader from a floppy disk image. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] + +### vbr/vbr.s + +This file contains the code for a Volume Boot Record (VBR) that loads the boot loader from a FAT partition on disk. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] + +### stage2/stage2.s + +This file contains the code for a second-stage boot loader that loads additional modules from disk. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] + +### miniboot32/BOOT_386.s + +This file contains the code for a 32-bit boot loader that loads the kernel from a floppy disk image. It is written in Assembly.[^note] + +[^note]: **Note:** Please note that the assembly code is strictly targeting the Pentium 3 Katmai uArch, but it might run elsewhere. Your mileage may vary. From 94a2fb08ca2a50bbecf6dc3b1edcf4d2537d4bfe Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 10:43:01 -0400 Subject: [PATCH 003/147] Delete COPYING Removing GPL-3.0 license. --- COPYING | 674 -------------------------------------------------------- 1 file changed, 674 deletions(-) delete mode 100755 COPYING diff --git a/COPYING b/COPYING deleted file mode 100755 index e8ba5cf..0000000 --- a/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file From 2c55ed5c0467cf3dc5c360200c00e86d0e6ab4bf Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 10:43:54 -0400 Subject: [PATCH 004/147] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index f197e3a..3d275b9 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,7 @@ To exit the emulator, press `Ctrl+C` in the terminal where you launched Bochs. ## License -This project is licensed under the MIT License and the GPL-3.0 License. See the [COPYING](^1^) and [LICENSE.md](^2^) files for details. - -Here are possible README.md files for each of your requested files: +This project is licensed under the MIT License. See the [LICENSE.md](^2^) file for details. ### mbr/mbr.s From 90ced63cbab0b1e800cb97494668d0daa0733f53 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 14:24:35 -0400 Subject: [PATCH 005/147] =?UTF-8?q?small=20changes=20to=20License=20?= =?UTF-8?q?=F0=9F=8F=B3=EF=B8=8F=E2=80=8D=E2=9A=A7=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/config.inc | 2 +- include/entry.inc | 2 +- include/errors.inc | 2 +- include/fat32/bpb.inc | 2 +- include/fat32/fat32_structures.inc | 2 +- include/memory.inc | 2 +- include/partition_table.inc | 2 +- scripts/create-disk.sh | 2 +- src/mbr/mbr.s | 2 +- src/miniboot32/BOOT_386.s | 2 +- src/stage2/stage2.s | 2 +- src/vbr/vbr.s | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/config.inc b/include/config.inc index 802dfce..20c9047 100755 --- a/include/config.inc +++ b/include/config.inc @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/include/entry.inc b/include/entry.inc index 7306599..e9f7213 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/include/errors.inc b/include/errors.inc index 88dd000..6e334bb 100755 --- a/include/errors.inc +++ b/include/errors.inc @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/include/fat32/bpb.inc b/include/fat32/bpb.inc index b16c0e0..6622b72 100755 --- a/include/fat32/bpb.inc +++ b/include/fat32/bpb.inc @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/include/fat32/fat32_structures.inc b/include/fat32/fat32_structures.inc index 29fd9ee..ecc25c3 100755 --- a/include/fat32/fat32_structures.inc +++ b/include/fat32/fat32_structures.inc @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/include/memory.inc b/include/memory.inc index 14f81f1..79094b5 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/include/partition_table.inc b/include/partition_table.inc index cd21bff..4f1723b 100755 --- a/include/partition_table.inc +++ b/include/partition_table.inc @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index a58aabd..93a13f7 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright (C) 2020 Bradley Claus +# Copyright (C) 2023 Elaina Claus # # 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 diff --git a/src/mbr/mbr.s b/src/mbr/mbr.s index a92b386..7f3b9f1 100755 --- a/src/mbr/mbr.s +++ b/src/mbr/mbr.s @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/src/miniboot32/BOOT_386.s b/src/miniboot32/BOOT_386.s index adca632..845735f 100755 --- a/src/miniboot32/BOOT_386.s +++ b/src/miniboot32/BOOT_386.s @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/src/stage2/stage2.s b/src/stage2/stage2.s index f60dc37..7c1e8c2 100755 --- a/src/stage2/stage2.s +++ b/src/stage2/stage2.s @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 diff --git a/src/vbr/vbr.s b/src/vbr/vbr.s index 1cd1bd4..262c1bb 100755 --- a/src/vbr/vbr.s +++ b/src/vbr/vbr.s @@ -1,4 +1,4 @@ -; Copyright (C) 2020 Bradley Claus +; Copyright (C) 2023 Elaina Claus ; ; 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 From 5fdde61dd3bbf370b8cee4b60c1e2aa1e07b3732 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 15:55:45 -0400 Subject: [PATCH 006/147] remove packaged binaries --- bin/.keepdir | 0 bin/bios.bin | Bin 262144 -> 0 bytes bin/vgabios.bin | Bin 38400 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 bin/.keepdir delete mode 100755 bin/bios.bin delete mode 100755 bin/vgabios.bin diff --git a/bin/.keepdir b/bin/.keepdir deleted file mode 100755 index e69de29..0000000 diff --git a/bin/bios.bin b/bin/bios.bin deleted file mode 100755 index 998d724d03ab03c32ff5c5f36284bd49204f0451..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 262144 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 Xc>#Q#Q>W@(LkA2RJRl6D diff --git a/bin/vgabios.bin b/bin/vgabios.bin deleted file mode 100755 index 9ad694a8e24f57eeb2e3c07b5f1c2182a69276d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38400 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 N-Ea*gJHu^R|2GM_MBo4b From ad828ac1f4f6ccd07422932f785b66ad658c87d3 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 15:56:15 -0400 Subject: [PATCH 007/147] use wx interface for config, gui, and debug --- bochsrc.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bochsrc.txt b/bochsrc.txt index 65b5de5..b60b583 100755 --- a/bochsrc.txt +++ b/bochsrc.txt @@ -1,19 +1,19 @@ # configuration file generated by Bochs plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, gameport=true, iodebug=true -config_interface: textconfig -display_library: x -memory: host=32, guest=32 +config_interface: wx +display_library: wx +memory: host=64, guest=64 boot: disk floppy_bootsig_check: disabled=0 # no floppya # no floppyb ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 -ata0-master: type=disk, path="disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto +ata0-master: type=disk, path="./disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto ata0-slave: type=none ata1: enabled=false ata2: enabled=false ata3: enabled=false -pci: enabled=1, chipset=i440fx +pci: enabled=0 vga: extension=vbe, update_freq=5, realtime=1 cpu: count=1:1:1, ips=1000000, quantum=16, model=p3_katmai, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 print_timestamps: enabled=0 @@ -32,7 +32,7 @@ panic: action=ask keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none mouse: type=ps2, enabled=false, toggle=ctrl+mbutton speaker: enabled=true, mode=system -parport1: enabled=true, file=none +parport1: enabled=false parport2: enabled=false com1: enabled=true, mode=null com2: enabled=false From d4dc46d7703f89ac9f137c2f59f9c462b852f8cd Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 16:03:46 -0400 Subject: [PATCH 008/147] MIT license applied to all project files --- LICENSE.md | 2 -- include/config.inc | 27 ++++++++++++++++----------- include/entry.inc | 27 ++++++++++++++++----------- include/errors.inc | 27 ++++++++++++++++----------- include/fat32/bpb.inc | 27 ++++++++++++++++----------- include/fat32/fat32_structures.inc | 27 ++++++++++++++++----------- include/memory.inc | 27 ++++++++++++++++----------- include/partition_table.inc | 28 ++++++++++++++++------------ scripts/create-disk.sh | 27 ++++++++++++++++----------- src/mbr/mbr.s | 27 ++++++++++++++++----------- src/miniboot32/BOOT_386.s | 27 ++++++++++++++++----------- src/stage2/stage2.s | 27 ++++++++++++++++----------- src/vbr/vbr.s | 28 +++++++++++++++++----------- 13 files changed, 193 insertions(+), 135 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index a5f9261..d57b7b2 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,5 +1,3 @@ -MIT License - Copyright (c) 2023 Elaina Claus Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/include/config.inc b/include/config.inc index 20c9047..20e2430 100755 --- a/include/config.inc +++ b/include/config.inc @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. %define SECTOR_SIZE 512 diff --git a/include/entry.inc b/include/entry.inc index e9f7213..f9f566e 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. ; 8KiB from 0x2500 -> 0x500 diff --git a/include/errors.inc b/include/errors.inc index 6e334bb..c3e9e71 100755 --- a/include/errors.inc +++ b/include/errors.inc @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. ; Errors diff --git a/include/fat32/bpb.inc b/include/fat32/bpb.inc index 6622b72..e6ce621 100755 --- a/include/fat32/bpb.inc +++ b/include/fat32/bpb.inc @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. ; BPB Information diff --git a/include/fat32/fat32_structures.inc b/include/fat32/fat32_structures.inc index ecc25c3..959b0e5 100755 --- a/include/fat32/fat32_structures.inc +++ b/include/fat32/fat32_structures.inc @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. ; ## FAT32 Info ## diff --git a/include/memory.inc b/include/memory.inc index 79094b5..4b64ca8 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. ; ## Generic Low mem map (from osdev wiki) ## diff --git a/include/partition_table.inc b/include/partition_table.inc index 4f1723b..5fc7a20 100755 --- a/include/partition_table.inc +++ b/include/partition_table.inc @@ -1,18 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . - +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. ; Partition table entry format ; Off. Size. Description diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index 93a13f7..dfdafe0 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -1,19 +1,24 @@ #!/usr/bin/env bash -# Copyright (C) 2023 Elaina Claus +# Copyright (c) 2023 Elaina Claus # -# 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. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -# 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. +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. # -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. if ! [ $(id -u) = 0 ]; then echo "Script must be run as root!" diff --git a/src/mbr/mbr.s b/src/mbr/mbr.s index 7f3b9f1..1bc1ea2 100755 --- a/src/mbr/mbr.s +++ b/src/mbr/mbr.s @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. [BITS 16] [ORG 0x7A00] diff --git a/src/miniboot32/BOOT_386.s b/src/miniboot32/BOOT_386.s index 845735f..6ab059b 100755 --- a/src/miniboot32/BOOT_386.s +++ b/src/miniboot32/BOOT_386.s @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. [BITS 32] [ORG 0x100000] diff --git a/src/stage2/stage2.s b/src/stage2/stage2.s index 7c1e8c2..04b2268 100755 --- a/src/stage2/stage2.s +++ b/src/stage2/stage2.s @@ -1,17 +1,22 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. [BITS 16] [ORG 0X7E00] diff --git a/src/vbr/vbr.s b/src/vbr/vbr.s index 262c1bb..cb71e81 100755 --- a/src/vbr/vbr.s +++ b/src/vbr/vbr.s @@ -1,17 +1,23 @@ -; Copyright (C) 2023 Elaina Claus +; Copyright (c) 2023 Elaina Claus ; -; 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. +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: ; -; 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. +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. ; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + [BITS 16] [ORG 0x7C00] From d162d5dc4ce09f93bd9c018d28d67f14d2e2b631 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 16:22:13 -0400 Subject: [PATCH 009/147] update readme with more information --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3d275b9..1e91fc4 100644 --- a/README.md +++ b/README.md @@ -31,18 +31,18 @@ This project is licensed under the MIT License. See the [LICENSE.md](^2^) file f ### mbr/mbr.s -This file contains the code for a Master Boot Record (MBR) that loads the boot loader from a floppy disk image. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] +This file contains the code for a Master Boot Record (MBR) that attempts to find an active partition to load. The CPU is assumed to be in 16-bit real mode at this point and the bios has loaded the 1st sector of the disk (512 bytes) to 0x0000:0x7C00. First the mbr code relocates from 0x7C00 to 0x0600 and then jumps to the entry point. the loader attempts to load the first active partition it can find and loads the vbr to 0x7c00 (512 bytes) and then jumps to 0x0000:0x7C00. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] ### vbr/vbr.s -This file contains the code for a Volume Boot Record (VBR) that loads the boot loader from a FAT partition on disk. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] +This file contains the code for a Volume Boot Record (VBR) that loads the stage2 loader code from the booted disk. It reads disk sectors 1-63 into memory to STAGE2_ENTRY(defaults to 0x7E00 in config.inc) this currently allows for stevia to load up to 32KiB of code to perform bootloader duties. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] ### stage2/stage2.s -This file contains the code for a second-stage boot loader that loads additional modules from disk. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] +This file contains the code for a second-stage boot loader that loads additional modules from disk, performs some system sanity checks, and provides a simple boot interface for options/configuration. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] ### miniboot32/BOOT_386.s -This file contains the code for a 32-bit boot loader that loads the kernel from a floppy disk image. It is written in Assembly.[^note] +This file contains the code for a 32-bit binary that can be loaded and ran with stevia as a mini demo. It is written in Assembly.[^note] [^note]: **Note:** Please note that the assembly code is strictly targeting the Pentium 3 Katmai uArch, but it might run elsewhere. Your mileage may vary. From 5916b46a9e43ecc718e8ae86a0056975d225b6f9 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 16:34:39 -0400 Subject: [PATCH 010/147] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 1e91fc4..bb6fedd 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,14 @@ This is a hobby project that aims to create a simple and lightweight operating s - A calculator that can perform arithmetic operations - (big maybe) micropython or some other language, cross compiling, etc... +## Why? +I enjoy bare metal programing and I have an old Dell system with a Pentium 3, I did this mostly to learn how to write a legacy style bootloader (I am also kinda working on a UEFI bootloader/utility as well!) + ## Installation To build and run this project, you need to have the following tools installed: +- A host system running Linux, macOS (should work 🤷‍♀️), or Windows 11 with WSL2/WSLg - GNU Binutils - GNU GCC - GNU Make @@ -25,6 +29,8 @@ To run the project, run `bochs -f bochsrc.txt` in the root directory. This will To exit the emulator, press `Ctrl+C` in the terminal where you launched Bochs. +To run the project on real hardware I use a SD card to IDE interface for my test system which is a ~700Mhz P3 with 256 MB of ram. You will need to write the 'stevia.img' to the disk with 'dd'. On real hardware you may encounter issues that are not accounted for since most of the development happens on bochs, please report any issues you encounter. + ## License This project is licensed under the MIT License. See the [LICENSE.md](^2^) file for details. From 4e9e58c4308da059cc3f1cd3ed7a36a00ea85e43 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 22 Aug 2023 16:45:22 -0400 Subject: [PATCH 011/147] added description for create-disk script --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index bb6fedd..e329ea0 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ This is a hobby project that aims to create a simple and lightweight operating s - (big maybe) micropython or some other language, cross compiling, etc... ## Why? + I enjoy bare metal programing and I have an old Dell system with a Pentium 3, I did this mostly to learn how to write a legacy style bootloader (I am also kinda working on a UEFI bootloader/utility as well!) ## Installation @@ -51,4 +52,34 @@ This file contains the code for a second-stage boot loader that loads additional This file contains the code for a 32-bit binary that can be loaded and ran with stevia as a mini demo. It is written in Assembly.[^note] +### scripts/create-disk.sh + +This script creates a disk image file for stevia. The disk image file can be used to boot stevia on an emulator or a real machine. + +#### Requirements + +- Bash shell +- Root privileges +- dd utility +- sfdisk utility (for Linux) or hdiutil & util-linux utility (for macOS, util-linux is needed for sfdisk because hdiutil only creates hybrid disks on newer versions afaik) +- newfs_msdos utility (for macOS) +- mkfs.vfat utility (for Linux) + +#### Usage + +Run the script as root (or just allow the make script to do its business): + +```bash +sudo ./create_disk_image.sh +``` + +The script will create a disk image file named `disk.img` in the current directory. The disk image file will have the following characteristics: + +- Size: 128 MiB +- Partition table: DOS +- Partition 1: FAT32, bootable, starts at sector 2048, contains the boot32 boot test file (`BOOT_386.bin`) +- Boot code: MBR (`mbr.bin`), VBR (`vbr.bin`), stage2 (sectors 1-63) (`stage2.bin`) + +The script will also copy the necessary files from the `build` directory to the disk image file. If the files are not found, the script will exit with an error. + [^note]: **Note:** Please note that the assembly code is strictly targeting the Pentium 3 Katmai uArch, but it might run elsewhere. Your mileage may vary. From b2857ff9fda1123470483f4372d228ee97ebca45 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 23 Aug 2023 07:35:30 -0400 Subject: [PATCH 012/147] clarify that WSL is supported --- scripts/create-disk.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index dfdafe0..65b8b0f 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -196,6 +196,6 @@ elif [[ "$OSTYPE" == "darwin"* ]]; then fi else # Unknown. - echo "Unknown OS type! Supported build hosts systems are GNU/Linux and macOS." + echo "Unknown OS type! Supported build hosts systems are GNU/Linux (WSL) and macOS." exit 1 fi \ No newline at end of file From 30b71d2e6e4bca37af541675c9e81d0ebc0a21c5 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 23 Aug 2023 10:09:49 -0400 Subject: [PATCH 013/147] updated gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ec50e92..b64f809 100755 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ out/* build/* *.img *.elf -bx_enh_dbg.ini \ No newline at end of file +bx_enh_dbg.ini +stevia-log \ No newline at end of file From b590edd3ffbdaf13401b728f183d01f71e70ff79 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 23 Aug 2023 10:10:13 -0400 Subject: [PATCH 014/147] enable logging and bump to 128MB of memory --- bochsrc.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bochsrc.txt b/bochsrc.txt index b60b583..8ca1a66 100755 --- a/bochsrc.txt +++ b/bochsrc.txt @@ -2,7 +2,7 @@ plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, gameport=true, iodebug=true config_interface: wx display_library: wx -memory: host=64, guest=64 +memory: host=128, guest=128 boot: disk floppy_bootsig_check: disabled=0 # no floppya @@ -23,7 +23,7 @@ port_e9_hack: enabled=0 private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 # no cmosimage -log: - +log: stevia-log logprefix: %t%e%d debug: action=ignore info: action=report From 355ceb49a7f5661ebd360be1f5e1410767062d65 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 23 Aug 2023 10:10:30 -0400 Subject: [PATCH 015/147] changed extention from .s to .nasm --- Makefile | 26 ++++++++++---------- src/mbr/{mbr.s => mbr.nasm} | 0 src/miniboot32/{BOOT_386.s => BOOT_386.nasm} | 0 src/stage2/{stage2.s => stage2.nasm} | 0 src/vbr/{vbr.s => vbr.nasm} | 0 5 files changed, 13 insertions(+), 13 deletions(-) rename src/mbr/{mbr.s => mbr.nasm} (100%) rename src/miniboot32/{BOOT_386.s => BOOT_386.nasm} (100%) rename src/stage2/{stage2.s => stage2.nasm} (100%) rename src/vbr/{vbr.s => vbr.nasm} (100%) diff --git a/Makefile b/Makefile index 80bfaa8..3723efc 100755 --- a/Makefile +++ b/Makefile @@ -2,19 +2,19 @@ iso := 'disk.img' include := './include' -mbr_source_files := $(wildcard src/mbr/*.s) -vbr_source_files := $(wildcard src/vbr/*.s) -stage2_source_files := $(wildcard src/stage2/*.s) -boottest_source_files := $(wildcard src/miniboot32/*.s) +mbr_source_files := $(wildcard src/mbr/*.nasm) +vbr_source_files := $(wildcard src/vbr/*.nasm) +stage2_source_files := $(wildcard src/stage2/*.nasm) +boottest_source_files := $(wildcard src/miniboot32/*.nasm) -mbr_binary_files := $(patsubst src/mbr/%.s, build/%.bin, $(mbr_source_files)) -vbr_binary_files := $(patsubst src/vbr/%.s, build/%.bin, $(vbr_source_files)) -stage2_binary_files := $(patsubst src/stage2/%.s, build/%.bin, $(stage2_source_files)) -boottest_binary_files := $(patsubst src/miniboot32/%.s, build/%.bin, $(boottest_source_files)) +mbr_binary_files := $(patsubst src/mbr/%.nasm, build/%.bin, $(mbr_source_files)) +vbr_binary_files := $(patsubst src/vbr/%.nasm, build/%.bin, $(vbr_source_files)) +stage2_binary_files := $(patsubst src/stage2/%.nasm, build/%.bin, $(stage2_source_files)) +boottest_binary_files := $(patsubst src/miniboot32/%.nasm, build/%.bin, $(boottest_source_files)) build_dir := 'build' -qemu_args := -L ./bin/ -bios bios.bin -cpu pentium3 -m 64 -S -s -monitor stdio -nic none +qemu_args := -L ./bin/ -bios bios.bin -cpu pentium3 -m 128 -S -s -monitor stdio -nic none .PHONY: all mbr vbr stage2 boottest clean run run_bochs iso all: $(iso) $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files) @@ -36,19 +36,19 @@ run_bochs: $(iso) iso: $(iso) @file disk.img -build/%.bin: src/mbr/%.s +build/%.bin: src/mbr/%.nasm @mkdir -p $(shell dirname $@) @nasm -i$(include) -Wall -f bin $< -o $@ -build/%.bin: src/vbr/%.s +build/%.bin: src/vbr/%.nasm @mkdir -p $(shell dirname $@) @nasm -i$(include) -Wall -f bin $< -o $@ -build/%.bin: src/stage2/%.s +build/%.bin: src/stage2/%.nasm @mkdir -p $(shell dirname $@) @nasm -i$(include) -Wall -f bin $< -o $@ -build/%.bin: src/miniboot32/%.s +build/%.bin: src/miniboot32/%.nasm @mkdir -p $(shell dirname $@) @nasm -i$(include) -Wall -f bin $< -o $@ diff --git a/src/mbr/mbr.s b/src/mbr/mbr.nasm similarity index 100% rename from src/mbr/mbr.s rename to src/mbr/mbr.nasm diff --git a/src/miniboot32/BOOT_386.s b/src/miniboot32/BOOT_386.nasm similarity index 100% rename from src/miniboot32/BOOT_386.s rename to src/miniboot32/BOOT_386.nasm diff --git a/src/stage2/stage2.s b/src/stage2/stage2.nasm similarity index 100% rename from src/stage2/stage2.s rename to src/stage2/stage2.nasm diff --git a/src/vbr/vbr.s b/src/vbr/vbr.nasm similarity index 100% rename from src/vbr/vbr.s rename to src/vbr/vbr.nasm From 7fd4a89d96e908a80a5d13fd14b2828ec444ff19 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 27 Jul 2024 09:21:41 -0400 Subject: [PATCH 016/147] Update README.md updated description to more accurately reflect project status --- README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index e329ea0..0fe19d7 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,6 @@ # stevia -This is a hobby project that aims to create a simple and lightweight operating system kernel. It is written in Assembly and C, and uses the GNU toolchain and Bochs emulator. The project features (or is hoping to feature): - -- A boot loader that loads the kernel from a floppy disk image -- A kernel that implements basic functions, such as printing messages, handling interrupts, and managing memory -- A shell that allows user input and execution of commands -- A simple text editor that can create and edit files -- A calculator that can perform arithmetic operations -- (big maybe) micropython or some other language, cross compiling, etc... +This is a hobby project that aims to create a simple and lightweight operating system. It is written in Assembly and C, and uses the GNU toolchain and Bochs emulator. ## Why? From abc79adeb711e14d2d60fec158c16c1bf35be8c1 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 21 Sep 2024 11:45:22 -0400 Subject: [PATCH 017/147] remove reallocation in mbr init also reenable interupts in the init block --- src/mbr/mbr.nasm | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 1bc1ea2..bb9475c 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -34,11 +34,7 @@ init: mov ss, ax ; Set Stack Segment to 0 mov sp, STACK_START - - mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx - mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS) - mov di, MBR_ENTRY ; New MBR Address (our new relocation address) - rep movsw ; copy 512 bytes from 0x0000:7c00 to 0x0000:0600 + sti jmp 0:main nop @@ -49,7 +45,6 @@ init: %include "errors.inc" main: - sti mov [boot_drive], dl ; BIOS passes drive number in DL .check_disk: From 1c27b665b0c27e5e8ddcbbd297af5dd970217494 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 21 Sep 2024 11:46:36 -0400 Subject: [PATCH 018/147] ignore vscode personal configs --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b64f809..32c5bba 100755 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ build/* *.img *.elf bx_enh_dbg.ini -stevia-log \ No newline at end of file +stevia-log +.vscode/ \ No newline at end of file From bdc1fc5bf01c54ea964e86843fa4067380d5caf9 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 21 Sep 2024 12:04:05 -0400 Subject: [PATCH 019/147] added -P option to losetup this fixes an issue that appeared on WSL2 recently(ish) --- scripts/create-disk.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index 65b8b0f..eb56221 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -47,7 +47,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then if [ -e $mbr_file ] && [ -e $vbr_file ]; then # get next loop device and mount it ld=$(losetup -f) - losetup -b 512 $ld disk.img + losetup -P -b 512 $ld disk.img # create a DOS disk, with 1 FAT32 partition that is bootable, part1 starts at sector 2048 sfdisk $ld < scripts/loop_setup.sfdisk From a5702bd92e1d2644e402fe44277882cbeef1f9a3 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 21 Sep 2024 12:32:49 -0400 Subject: [PATCH 020/147] partially revert change, sti is still in init --- src/mbr/mbr.nasm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index bb9475c..c6b57e4 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -34,6 +34,12 @@ init: mov ss, ax ; Set Stack Segment to 0 mov sp, STACK_START + + mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx + mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS) + mov di, MBR_ENTRY ; New MBR Address (our new relocation address) + rep movsw ; copy 512 bytes from 0x0000:7c00 to 0x0000:MBR_ENTRY (7A00 as of writing) + sti jmp 0:main From 96a8103e11898ec47660044c61a4f98e2dde1255 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 21 Sep 2024 13:28:52 -0400 Subject: [PATCH 021/147] added debuging 'errors' also there is special handling for them in error.inc --- include/errors.inc | 26 +++++++++++++++++++------- src/stage2/stage2.nasm | 1 + 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/errors.inc b/include/errors.inc index c3e9e71..a07630e 100755 --- a/include/errors.inc +++ b/include/errors.inc @@ -48,7 +48,7 @@ %define VBR_ERROR_RESERVED_w 'w' %define VBR_ERROR_RESERVED_x 'x' -; 26 errors, 8 in use +; 22 errors, 8 in use %define STAGE2_A20_FAILED 'A' %define STAGE2_SIGNATURE_MISSING 'B' %define STAGE2_MM_E820_NO_SUPPORT 'C' @@ -71,27 +71,39 @@ %define STAGE2_ERROR_RESERVED_T 'T' %define STAGE2_ERROR_RESERVED_U 'U' %define STAGE2_ERROR_RESERVED_V 'V' -%define STAGE2_ERROR_RESERVED_W 'W' -%define STAGE2_ERROR_RESERVED_X 'X' -%define STAGE2_ERROR_RESERVED_Y 'Y' -%define STAGE2_ERROR_RESERVED_Z 'Z' + +; for development only, specific errors should be above. +%define STEVIA_DEBUG_OK 'W' +%define STEVIA_DEBUG_ERR 'X' +%define STEVIA_DEBUG_UNIMPLEMENTED 'Y' +%define STEVIA_DEBUG_HALT 'Z' %macro ERROR 1 + xor ax, ax mov al, %1 jmp error %endmacro ; pass error as ascii character in al, errors a-zA-Z or 0-9 error: - ; color 0x4F is white on red ; fs = 0xb800 => fs:0x0000 = 0xb8000 mov dx, 0xB800 mov fs, dx + mov dx, STEVIA_DEBUG_OK + cmp ax, dx + jge error.debug_err + ; the characters are two bytes in the order of 0xb8000: byte c, byte attribute ; since x86 is le, we store the attribute in the MSB of dx - mov dh, 0x4F + mov dh, 0x4F ; color 0x4F is white text/red background + mov dl, al + mov word [fs:0x0000], dx + jmp error.stop + +.debug_err: + mov dh, 0x5F ; debug case is white text/purple background mov dl, al mov word [fs:0x0000], dx diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 04b2268..dd4dfcf 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -159,6 +159,7 @@ main: ; jump to entry point ; TODO + ERROR STEVIA_DEBUG_HALT hcf: hlt From d42ee1df60491871dd3ceb3bf717114ade46f50e Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 21 Sep 2024 13:45:15 -0400 Subject: [PATCH 022/147] small optimization to error printer saves us 5 bytes of code (15 overall) --- include/errors.inc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/include/errors.inc b/include/errors.inc index a07630e..31f723a 100755 --- a/include/errors.inc +++ b/include/errors.inc @@ -94,19 +94,18 @@ error: mov dx, STEVIA_DEBUG_OK cmp ax, dx jge error.debug_err + mov dh, 0x4F ; color 0x4F is white text/red background + jmp error.print +.debug_err: + mov dh, 0x5F ; debug case is white text/purple background ; the characters are two bytes in the order of 0xb8000: byte c, byte attribute ; since x86 is le, we store the attribute in the MSB of dx - mov dh, 0x4F ; color 0x4F is white text/red background +.print: mov dl, al mov word [fs:0x0000], dx jmp error.stop -.debug_err: - mov dh, 0x5F ; debug case is white text/purple background - mov dl, al - mov word [fs:0x0000], dx - .stop: hlt jmp short error.stop \ No newline at end of file From 6db97e3258c5639987dbb886f88e748320ce4279 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 21 Sep 2024 14:09:52 -0400 Subject: [PATCH 023/147] added bxrc config to launch on windows hosts --- bochsrc.bxrc | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 bochsrc.bxrc diff --git a/bochsrc.bxrc b/bochsrc.bxrc new file mode 100644 index 0000000..52f1435 --- /dev/null +++ b/bochsrc.bxrc @@ -0,0 +1,51 @@ +# configuration file generated by Bochs +plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=false, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false +config_interface: win32config +display_library: win32 +memory: guest=64, host=64, block_size=128 +romimage: file="C:\Program Files\Bochs-2.8\BIOS-bochs-latest", address=0x00000000, options=none, flash_data=none +vgaromimage: file="C:\Program Files\Bochs-2.8\VGABIOS-lgpl-latest" +boot: disk +floppy_bootsig_check: disabled=0 +floppya: type=1_44 +# no floppyb +ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=auto +ata0-slave: type=none +ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata1-master: type=none +ata1-slave: type=none +ata2: enabled=false +ata3: enabled=false +optromimage1: file=none +optromimage2: file=none +optromimage3: file=none +optromimage4: file=none +optramimage1: file=none +optramimage2: file=none +optramimage3: file=none +optramimage4: file=none +pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none +vga: extension=vbe, update_freq=10, realtime=1, ddc=builtin +cpu: count=1, ips=1000000, model=p3_katmai, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +print_timestamps: enabled=0 +port_e9_hack: enabled=false, all_rings=false +private_colormap: enabled=0 +clock: sync=none, time0=local, rtc_sync=0 +# no cmosimage +log: - +logprefix: %t%e%d +debug: action=ignore +info: action=report +error: action=report +panic: action=ask +keyboard: type=mf, serial_delay=150, paste_delay=100000, user_shortcut=none +mouse: type=none, enabled=false, toggle=ctrl+mbutton +sound: waveoutdrv=dummy, waveout=none, waveindrv=dummy, wavein=none, midioutdrv=dummy, midiout=none +speaker: enabled=true, mode=sound, volume=15 +parport1: enabled=true, file=none +parport2: enabled=false +com1: enabled=true, mode=null +com2: enabled=false +com3: enabled=false +com4: enabled=false From 5e4e40f7de7bae0aba6bc05ed52d127804c78096 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 2 Oct 2024 10:13:00 -0400 Subject: [PATCH 024/147] removed ata1 from windows bochsrc --- bochsrc.bxrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bochsrc.bxrc b/bochsrc.bxrc index 52f1435..6de97b7 100644 --- a/bochsrc.bxrc +++ b/bochsrc.bxrc @@ -12,7 +12,7 @@ floppya: type=1_44 ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=auto ata0-slave: type=none -ata1: enabled=true, ioaddr1=0x170, ioaddr2=0x370, irq=15 +ata1: type=none ata1-master: type=none ata1-slave: type=none ata2: enabled=false From 8e595e8eba2fcd439e66b9962bc802e2d0482ceb Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 2 Oct 2024 10:13:45 -0400 Subject: [PATCH 025/147] added some clarification on cdecl16 --- docs/calling_convention_cdecl16.txt | 104 ++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 docs/calling_convention_cdecl16.txt diff --git a/docs/calling_convention_cdecl16.txt b/docs/calling_convention_cdecl16.txt new file mode 100644 index 0000000..24837b5 --- /dev/null +++ b/docs/calling_convention_cdecl16.txt @@ -0,0 +1,104 @@ +__cdecl16near Calling Convention +Purpose: Used for calling near (within the same segment) functions in 16-bit code. +Stack Management: The caller cleans up the stack after the function call. +Parameter Passing: Parameters are pushed onto the stack from right to left. +Return Address: A near return address (16-bit) is pushed onto the stack. +Return Value: The return value is typically placed in the AX register. + +e.g + +; Caller +push param2 +push param1 +call near_func +add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) + +; Callee (near_func) +near_func: + push bp + mov bp, sp + ; Function body + mov sp, bp + pop bp + ret + +__cdecl16far Calling Convention +Purpose: Used for calling far (across different segments) functions in 16-bit code. +Stack Management: The caller cleans up the stack after the function call. +Parameter Passing: Parameters are pushed onto the stack from right to left. +Return Address: A far return address (32-bit, consisting of a segment and an offset) is pushed onto the stack. +Return Value: The return value is typically placed in the AX register. + +e.g + +; Caller +push param2 +push param1 +call far_func +add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) + +; Callee (far_func) +far_func: + push bp + mov bp, sp + ; Function body + mov sp, bp + pop bp + retf ; Far return + +Key Differences +Return Address: __cdecl16near uses a 16-bit return address, while __cdecl16far uses a 32-bit return address (segment:offset). +Function Scope: __cdecl16near is for functions within the same segment, whereas __cdecl16far is for functions that may be in different segments. +Return Instruction: __cdecl16near uses ret, while __cdecl16far uses retf (far return). + + +### REGISTERS ### + +Register Usage in __cdecl16near and __cdecl16far +Caller-Saved Registers (Volatile) +These registers must be saved by the caller if they wish to preserve their values across function calls: + +AX: Accumulator register, often used for return values. +CX: Counter register, commonly used in loops and string operations. +DX: Data register, used for I/O operations and arithmetic. +SI: Source index for string operations. +DI: Destination index for string operations. +Callee-Saved Registers (Non-Volatile) +These registers must be preserved by the callee. If the callee uses these registers, it must save their original values and restore them before returning: + +BP: Base pointer, used for stack frame management. +SP: Stack pointer, although typically managed by the calling convention itself. +BX: Base register, often used for addressing. +SI: Source index, if not used for string operations. +DI: Destination index, if not used for string operations. + +e.g + +; Caller +push param2 +push param1 +call near_func +add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) + +; Callee (near_func) +near_func: + push bp + mov bp, sp + ; Save callee-saved registers if used + push bx + push si + push di + ; Function body + ; Use AX, CX, DX freely + mov ax, [bp+4] ; Access first parameter + mov bx, [bp+6] ; Access second parameter + ; + ; your other code here + ; + ; Restore callee-saved registers + pop di + pop si + pop bx + mov sp, bp + pop bp + ret From 2bbfa0931b6974facb88780a9adf41d6ebb69717 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 2 Oct 2024 10:25:59 -0400 Subject: [PATCH 026/147] moved reservation for bpb to a include --- include/fat32/bpb_reserve_area.inc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 include/fat32/bpb_reserve_area.inc diff --git a/include/fat32/bpb_reserve_area.inc b/include/fat32/bpb_reserve_area.inc new file mode 100644 index 0000000..27e8759 --- /dev/null +++ b/include/fat32/bpb_reserve_area.inc @@ -0,0 +1,29 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +bpb_start: +; fill BPB area with 0x00 since we skip writing this part to disk +; but we need it for the 'jmp short entry; nop' above +times 33 db 0x00 + +ebpb_start: +; fill BPB area with 0x00 since we skip writing this part to disk +; but we need it for the 'jmp short entry; nop' above +times 54 db 0x00 \ No newline at end of file From 7c446ef3b24cb62ec2c6022091ec8df96bb8ef9b Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 2 Oct 2024 10:26:36 -0400 Subject: [PATCH 027/147] load our base headers in the same order as the mbr --- src/vbr/vbr.nasm | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index cb71e81..4025cb1 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -25,17 +25,9 @@ jmp short init nop -bpb_start: -; fill BPB area with 0x00 since we skip writing this part to disk -; but we need it for the 'jmp short entry; nop' above -times 33 db 0x00 - -ebpb_start: -; fill BPB area with 0x00 since we skip writing this part to disk -; but we need it for the 'jmp short entry; nop' above -times 54 db 0x00 - +%include "fat32/bpb_reserve_area.inc" %include "entry.inc" + init: cli ; We do not want to be interrupted @@ -48,25 +40,22 @@ init: mov bp, sp ; base ptr = stack ptr mov bx, VBR_ENTRY ; move BP to the new start of the initial boot sector + sti ; all done with inital setup and relocation, reenable interupts jmp 0:main ; fix up cs:ip just in case and jump to relocated code %include "config.inc" -%include "errors.inc" %include "memory.inc" - %include "partition_table.inc" +%include "errors.inc" %include "fat32/bpb.inc" - - main: - sti ; all done with inital setup and relocation, reenable interupts mov [bsDriveNumber], dl ; BIOS passes drive number in DL mov [partition_offset], si ; save passed partition entry offset -.check_FAT_size: +.check_FAT_size: ; we only support a very specific setup of FAT32 cmp dword [bsSectorHuge], 0 ; SectorsHuge will not be set if FAT12/16 ja main.load_stage2 From 2f6bd2e2d8ea5f72d6302b6ecf8526f91485dce4 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 2 Oct 2024 11:59:34 -0400 Subject: [PATCH 028/147] remove comment about CC, see docs/ --- src/stage2/stage2.nasm | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index dd4dfcf..57cc708 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -24,17 +24,6 @@ jmp short init nop -; Unless noted otherwise, functions will be the standard x86 cdecl used in GCC - -; In cdecl, subroutine arguments are passed on the stack. -; Integer values and memory addresses are returned in the EAX register, -; floating point values in the ST0 x87 register. -; Registers EAX, ECX, and EDX are caller-saved, -; and the rest are callee-saved. -; The x87 floating point registers ST0 to ST7 must be empty (popped or freed) -; when calling a new function, and ST1 to ST7 must be empty on exiting a function. -; ST0 must also be empty when not used for returning a value. - ; boot drive in dl ; active partition offset in si %include "entry.inc" From 054f4320ba71ee6d26d3963de6ebbd5843395d6e Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 2 Oct 2024 12:37:21 -0400 Subject: [PATCH 029/147] =?UTF-8?q?fixing=20how=20the=20stack=20works=20st?= =?UTF-8?q?age1=20=F0=9F=98=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stage2/stage2.nasm | 47 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 57cc708..7d0fd9e 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -72,44 +72,40 @@ main: mov ax, 0xBEEF push ax ; mark top of stack for debuging - push bp - mov bp, sp lea ax, [HelloPrompt_cstr] push ax call PrintString - leave + add sp, 0x2 ; enable A20 gate - push bp - mov bp, sp call EnableA20 + lea ax, [A20_Enabled_cstr] push ax call PrintString - leave + add sp, 0x2 ; get system memory map - push bp - mov bp, sp call GetMemoryMap + lea ax, [MemoryMap_OK_cstr] push ax call PrintString - leave + add sp, 0x2 ; enter unreal mode - push bp - mov bp, sp call EnterUnrealMode + lea ax, [UnrealMode_OK_cstr] push ax call PrintString - leave + add sp, 0x2 + + ; FAT Driver setup push bp mov bp, sp call InitFATDriver - leave ; ; Find first cluster of bootable file @@ -117,29 +113,26 @@ main: push bp mov bp, sp call SearchFATDIR - leave - PUSH_DWORD_EAX ; save return value of function + + PUSH_DWORD_EAX ; save return value of function as a 32-bit value on a 16-bit aligned stack + - push bp - mov bp, sp lea ax, [FileFound_OK_cstr] push ax call PrintString - leave + add sp, 0x2 POP_DWORD_EAX ; return value of SearchFATDIR push bp mov bp, sp PUSH_DWORD_EAX call PrintDWORD - leave + - push bp - mov bp, sp lea ax, [NewLine_cstr] push ax call PrintString - leave + add sp, 0x2 ; TODO @@ -544,11 +537,14 @@ read_disk_raw: ; Prints a C-Style string (null terminated) using BIOS vga teletype call ; void PrintString(char* buf) PrintString: + push bp + mov bp, sp + push si push di push bx - mov di, [bp - 2] ; first arg is char* + mov di, [bp + 2] ; first arg is char* .str_len: xor cx, cx ; ECX = 0 @@ -562,7 +558,7 @@ PrintString: dec cx ; CX contains the length of the string - nul byte at end .print: - mov si, [bp - 2] ; source string + mov si, [bp + 2] ; source string .print_L0: push bp mov bp, sp @@ -582,6 +578,9 @@ PrintString: pop bx pop di pop si + + mov sp, bp + pop bp ret ; Return from procedure ; Prints a single character From 929962eaca1ca2ea27babc0cbe5b246389297e68 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 13:49:44 -0400 Subject: [PATCH 030/147] bunch of changes mostly to do with cdecl16 conformity moved top of stack marker to init SetTextMode and Cursor done before hello msg corrected CC/Stack usage to conform with cdecl16 for PrintString corrected CC/Stack usage to conform with cdecl16 for PrintChar corrected stack usage to conform with cdecl16 for SetTextMode corrected stack usage to conform with cdecl16 for disable_cursor --- src/stage2/stage2.nasm | 88 ++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 7d0fd9e..cb707d7 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -38,28 +38,30 @@ init: mov ss, ax ; Set Stack Segment to 0 mov sp, STACK_START ; Set Stack Pointer + + add sp, 0x4 + mov ax, 0xDEAD + push word ax + mov ax, 0xBEEF + push word ax ; mark top of stack for debuging + mov bp, sp + sti jmp 0:main %include "config.inc" %include "errors.inc" %include "memory.inc" - %include "partition_table.inc" %include "fat32/bpb.inc" %include "fat32/fat32_structures.inc" main: - sti - mov byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8], dl mov word [partition_offset], si - call SetTextMode - call disable_cursor - mov eax, dword [STAGE2_SIG] cmp eax, 0xDEADBEEF je main.signature_present @@ -67,16 +69,16 @@ main: ERROR STAGE2_SIGNATURE_MISSING .signature_present: - mov ax, 0xDEAD - push ax - mov ax, 0xBEEF - push ax ; mark top of stack for debuging + call SetTextMode + call disable_cursor lea ax, [HelloPrompt_cstr] push ax call PrintString add sp, 0x2 + ERROR STEVIA_DEBUG_HALT + ; enable A20 gate call EnableA20 @@ -544,9 +546,8 @@ PrintString: push di push bx - mov di, [bp + 2] ; first arg is char* + mov di, [bp + 4] ; first arg is char* .str_len: - xor cx, cx ; ECX = 0 not cx ; ECX = -1 == 0xFFFF xor ax, ax ; search for al = 0x0 @@ -558,16 +559,12 @@ PrintString: dec cx ; CX contains the length of the string - nul byte at end .print: - mov si, [bp + 2] ; source string + mov si, [bp + 4] ; source string .print_L0: - push bp - mov bp, sp - movzx ax, byte [si] push ax - call PrintCharacter - leave + add sp, 0x2 inc si dec cx @@ -586,11 +583,14 @@ PrintString: ; Prints a single character ; void PrintCharacter(char c); PrintCharacter: + push bp + mov bp, sp + push si push di push bx - - mov ax, [bp-2] ; c +.func_bios: + mov ax, [bp + 4] ; c mov dx, 0x00ff and ax, dx @@ -602,6 +602,9 @@ PrintCharacter: pop bx pop di pop si + + mov sp, bp + pop bp ret ; prints the hex representation of of val_upper:val_lower (4 byte value) @@ -662,6 +665,15 @@ PrintDWORD: ; also clears screen ; void SetTextMode(void) SetTextMode: +.prolog: + push bp + mov bp, sp + + push si + push di + push bx + pushf +.func: xor ah, ah ; Set Video mode BIOS function mov al, 0x02 ; 16 color 80x25 Text mode int 0x10 ; Call video interrupt @@ -670,6 +682,13 @@ SetTextMode: xor al, al ; page 0 int 0x10 ; call video interrupt .endp: + popf + pop bx + pop di + pop si + + mov sp, bp + pop bp ret ; Address Range Descriptor Structure @@ -826,22 +845,31 @@ GetMemoryMap: ; disables blinking text mode cursor disable_cursor: - pushf - push eax - push edx - - mov dx, 0x3D4 +.prolog: + push bp + mov bp, sp + + push si + push di + push bx + pushf +.func: + mov dx, 0x3D4 mov al, 0xA ; low cursor shape register out dx, al inc dx mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape out dx, al - - pop edx - pop eax - popf - ret +.endp: + popf + pop bx + pop di + pop si + + mov sp, bp + pop bp + ret ; ;NT 0x15 Function 2400 - Disable A20 From 00847477651f6d2d63b53ee9cfacafe76d42e894 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 14:46:47 -0400 Subject: [PATCH 031/147] added entry & exit macros --- include/cdecl16.inc | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 include/cdecl16.inc diff --git a/include/cdecl16.inc b/include/cdecl16.inc new file mode 100644 index 0000000..528a2a1 --- /dev/null +++ b/include/cdecl16.inc @@ -0,0 +1,37 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +%macro __CDECL16_ENTRY 0 + push bp + mov bp, sp + + push si + push di + push bx +%endmacro + +%macro __CDECL16_EXIT 0 + pop bx + pop di + pop si + + mov sp, bp + pop bp +%endmacro \ No newline at end of file From c524d8801d6161b60d816111cc954d21bd822631 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 14:51:43 -0400 Subject: [PATCH 032/147] replace prologs and epilogs in cdecl functions so far --- src/stage2/stage2.nasm | 78 ++++++++++-------------------------------- 1 file changed, 19 insertions(+), 59 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index cb707d7..7ebefc0 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -54,6 +54,7 @@ init: %include "errors.inc" %include "memory.inc" %include "partition_table.inc" +%include "cdecl16.inc" %include "fat32/bpb.inc" %include "fat32/fat32_structures.inc" @@ -136,13 +137,6 @@ main: call PrintString add sp, 0x2 - ; TODO - - ; read elf information and place the sections in the file at the correct location - ; TODO - - ; jump to entry point - ; TODO ERROR STEVIA_DEBUG_HALT hcf: @@ -155,7 +149,7 @@ hcf: ; ; ############### - +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 InitFATDriver: push bx @@ -200,6 +194,7 @@ InitFATDriver: pop bx ret +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; load a file to the high memory buffer for the elf parser ; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory ; @@ -326,7 +321,7 @@ SearchFATDIR: pop di ret - +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad @@ -403,6 +398,7 @@ NextCluster: pop si ret +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; uint32_t ClusterToLBA(uint32_t cluster) ClusterToLBA: push si @@ -419,6 +415,7 @@ ClusterToLBA: pop si ret +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) ReadFATCluster: push si @@ -494,6 +491,7 @@ ReadFATCluster: ; bp-6 = offset ; bp-8 = segment ; bp-10 = ret ptr +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 read_disk_raw: push si @@ -539,13 +537,7 @@ read_disk_raw: ; Prints a C-Style string (null terminated) using BIOS vga teletype call ; void PrintString(char* buf) PrintString: - push bp - mov bp, sp - - push si - push di - push bx - + __CDECL16_ENTRY mov di, [bp + 4] ; first arg is char* .str_len: xor cx, cx ; ECX = 0 @@ -572,23 +564,13 @@ PrintString: jcxz PrintString.endp jmp PrintString.print_L0 ; Fetch next character from string .endp: - pop bx - pop di - pop si - - mov sp, bp - pop bp + __CDECL16_EXIT ret ; Return from procedure ; Prints a single character ; void PrintCharacter(char c); PrintCharacter: - push bp - mov bp, sp - - push si - push di - push bx + __CDECL_ENTRY .func_bios: mov ax, [bp + 4] ; c mov dx, 0x00ff @@ -599,14 +581,10 @@ PrintCharacter: int 0x10 ; call video interrupt .endp: - pop bx - pop di - pop si - - mov sp, bp - pop bp + __CDECL16_EXIT ret +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; prints the hex representation of of val_upper:val_lower (4 byte value) ; void PrintDWORD(uint16_t val_upper, uint16_t val_lower); PrintDWORD: @@ -666,12 +644,7 @@ PrintDWORD: ; void SetTextMode(void) SetTextMode: .prolog: - push bp - mov bp, sp - - push si - push di - push bx + __CDECL16_ENTRY pushf .func: xor ah, ah ; Set Video mode BIOS function @@ -683,12 +656,7 @@ SetTextMode: int 0x10 ; call video interrupt .endp: popf - pop bx - pop di - pop si - - mov sp, bp - pop bp + __CDECL16_EXIT ret ; Address Range Descriptor Structure @@ -769,6 +737,7 @@ SetTextMode: ; 1 AddressRangeMemory This run is available RAM usable by the operating system. ; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. ; Other Undefined Undefined - Reserved for future use. +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 GetMemoryMap: push es ; save segment registers @@ -846,12 +815,7 @@ GetMemoryMap: ; disables blinking text mode cursor disable_cursor: .prolog: - push bp - mov bp, sp - - push si - push di - push bx + __CDECL16_ENTRY pushf .func: mov dx, 0x3D4 @@ -863,12 +827,7 @@ disable_cursor: out dx, al .endp: popf - pop bx - pop di - pop si - - mov sp, bp - pop bp + __CDECL16_EXIT ret ; @@ -920,6 +879,7 @@ disable_cursor: ; Bits 4-5 - Manufacturer defined ; Bits 6-7 - 00: HDD activity LED off; any other value is "on" ; +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 EnableA20: push bx push cx @@ -1005,7 +965,7 @@ EnableA20: ret - +; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 EnterUnrealMode: cli ; no interrupts push ds ; save real mode From f691000a3169dae7e16426440b5f594e009d8893 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 15:10:22 -0400 Subject: [PATCH 033/147] cdecl16 for EnableA20 ver.1 --- src/stage2/stage2.nasm | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 7ebefc0..dc45eb5 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -78,8 +78,6 @@ main: call PrintString add sp, 0x2 - ERROR STEVIA_DEBUG_HALT - ; enable A20 gate call EnableA20 @@ -88,6 +86,8 @@ main: call PrintString add sp, 0x2 + ERROR STEVIA_DEBUG_HALT + ; get system memory map call GetMemoryMap @@ -881,17 +881,12 @@ disable_cursor: ; ; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 EnableA20: - push bx - push cx - ; end prolog + __CDECL16_ENTRY - ; checked this way since this will /always/ work -.a20_check: - pushf push ds push es - push di - push si + pushf ; save data and extra segment since we touch them and save flags +.a20_check: cli xor ax, ax @@ -924,13 +919,7 @@ EnableA20: je EnableA20.end_check mov ax, 1 ; return 1 if es:di != ds:si (A20 is enabled) .end_check: - pop si - pop di - pop es - pop ds - popf sti - cmp ax, 1 je EnableA20.endp ; A20 is already enabled @@ -960,9 +949,10 @@ EnableA20: out 0x92, al ; enable A20 jmp EnableA20.a20_check .endp: - pop cx - pop bx - + popf + pop es + pop ds + __CDECL16_EXIT ret ; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 From 46717935a1b2446b4c7897155b86a9de1ca49cd2 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 15:28:44 -0400 Subject: [PATCH 034/147] src/stage2/stage2.nasm:573: warning: label alone on a line without a colon might be in error [-w+label-orphan] --- src/stage2/stage2.nasm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index dc45eb5..a40792e 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -570,7 +570,7 @@ PrintString: ; Prints a single character ; void PrintCharacter(char c); PrintCharacter: - __CDECL_ENTRY + __CDECL16_ENTRY .func_bios: mov ax, [bp + 4] ; c mov dx, 0x00ff From ac6110aa40c0ceebacd1cabbf0ae307ab897d8de Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 16:34:27 -0400 Subject: [PATCH 035/147] cdecl16 work and cleanup in MemoryMap --- src/stage2/stage2.nasm | 125 +++++------------------------------------ 1 file changed, 14 insertions(+), 111 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index a40792e..7406a00 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -658,108 +658,22 @@ SetTextMode: popf __CDECL16_EXIT ret - -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; Input: -; -; EAX Function Code E820h -; EBX Continuation Contains the "continuation value" to get the -; next run of physical memory. This is the -; value returned by a previous call to this -; routine. If this is the first call, EBX -; must contain zero. -; ES:DI Buffer Pointer Pointer to an Address Range Descriptor -; structure which the BIOS is to fill in. -; ECX Buffer Size The length in bytes of the structure passed -; to the BIOS. The BIOS will fill in at most -; ECX bytes of the structure or however much -; of the structure the BIOS implements. The -; minimum size which must be supported by both -; the BIOS and the caller is 20 bytes. Future -; implementations may extend this structure. -; EDX Signature 'SMAP' - Used by the BIOS to verify the -; caller is requesting the system map -; information to be returned in ES:DI. -; -; Output: -; -; CF Carry Flag Non-Carry - indicates no error -; EAX Signature 'SMAP' - Signature to verify correct BIOS -; revision. -; ES:DI Buffer Pointer Returned Address Range Descriptor pointer. -; Same value as on input. -; ECX Buffer Size Number of bytes returned by the BIOS in the -; address range descriptor. The minimum size -; structure returned by the BIOS is 20 bytes. -; EBX Continuation Contains the continuation value to get the -; next address descriptor. The actual -; significance of the continuation value is up -; to the discretion of the BIOS. The caller -; must pass the continuation value unchanged -; as input to the next iteration of the E820 -; call in order to get the next Address Range -; Descriptor. A return value of zero means that -; this is the last descriptor -; -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; -; The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. -; The BaseAddress is the physical address of the start of the range being specified. -; -; The LengthLow and LengthHigh together are the 64 bit Length of this range. -; The Length is the physical contiguous length in bytes of a range being specified. -; -; The Type field describes the usage of the described address range as defined in the table below. - -; Value Pneumonic Description -; 1 AddressRangeMemory This run is available RAM usable by the operating system. -; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. -; Other Undefined Undefined - Reserved for future use. -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 +; See memory.inc for a brief description of E820 mmap function GetMemoryMap: - push es ; save segment registers - - push bx - shr ebx, 16 - push bx ; save ebx on a 16bit stack - - push cx - shr ecx, 16 - push cx ; save ecx on a 16bit stack - ; end prolog + __CDECL16_ENTRY + push es ; save segment register +.func: mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0 - mov eax, 0xE820 ; select 0xE820 function - mov ebx, 0x0000 ; Continuation value + mov eax, 0xE820 ; select 0xE820 function + mov ebx, 0x0000 ; Continuation value mov dx, (BIOSMemoryMap >> 4) mov es, dx - mov di, 0 ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap + mov di, 0 ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap mov ecx, AddressRangeDescStruct_t_size - mov edx, 0x534D4150 ; 'SMAP' magic + mov edx, 0x534D4150 ; 'SMAP' magic int 0x15 jnc GetMemoryMap.no_error @@ -774,14 +688,14 @@ GetMemoryMap: jb GetMemoryMap.nonstandard_e820 cmp ebx, 0 - je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges + je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges - add di, AddressRangeDescStruct_t_size ; increment di to next descriptor - mov edx, eax ; 'SMAP' to edx - mov eax, 0xE820 ; select E820 function + add di, AddressRangeDescStruct_t_size ; increment di to next descriptor + mov edx, eax ; 'SMAP' to edx + mov eax, 0xE820 ; select E820 function int 0x15 - jnc GetMemoryMap.no_error ; carry indicates an error + jnc GetMemoryMap.no_error ; carry indicates an error .other_error: ERROR STAGE2_MM_E820_MISC_ERR @@ -791,19 +705,8 @@ GetMemoryMap: ERROR STAGE2_MM_E820_NO_SMAP .endp: - xor ebx, ebx - xor ecx, ecx - - pop cx - shl ecx, 16 - pop cx - - pop bx - shl ebx, 16 - pop bx - pop es - + __CDECL16_EXIT ret ; ############################## From c8ca94d7baa4dc8603bbfc914c55bc258dda61eb Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 16:43:10 -0400 Subject: [PATCH 036/147] some general cleanup & moving the halt to the next point in main() --- src/stage2/stage2.nasm | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 7406a00..e3b9471 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -86,8 +86,6 @@ main: call PrintString add sp, 0x2 - ERROR STEVIA_DEBUG_HALT - ; get system memory map call GetMemoryMap @@ -96,6 +94,8 @@ main: call PrintString add sp, 0x2 + ERROR STEVIA_DEBUG_HALT + ; enter unreal mode call EnterUnrealMode @@ -527,10 +527,10 @@ read_disk_raw: mov ah, 0x42 mov dl, byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8] int 0x13 - jnc read_disk_raw.endf + jnc read_disk_raw.endp ERROR STAGE2_MBR_DISK_READ_ERROR -.endf: +.endp: pop si ret @@ -549,7 +549,6 @@ PrintString: not cx ; the inverse of a neg number = abs(x) - 1 dec cx ; CX contains the length of the string - nul byte at end - .print: mov si, [bp + 4] ; source string .print_L0: @@ -571,7 +570,7 @@ PrintString: ; void PrintCharacter(char c); PrintCharacter: __CDECL16_ENTRY -.func_bios: +.func: mov ax, [bp + 4] ; c mov dx, 0x00ff and ax, dx @@ -579,7 +578,6 @@ PrintCharacter: mov ah, 0x0E ; INT 0x10, AH=0x0E call mov bx, 0x0007 ; BH = page no. BL =Text attribute 0x07 is lightgrey font on black background int 0x10 ; call video interrupt - .endp: __CDECL16_EXIT ret @@ -658,6 +656,7 @@ SetTextMode: popf __CDECL16_EXIT ret + ; See memory.inc for a brief description of E820 mmap function GetMemoryMap: __CDECL16_ENTRY From 2cfe86efac1a8e8743bc29180386abe0d5a852eb Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 17:41:48 -0400 Subject: [PATCH 037/147] refactored and validated MemoryMap funciton --- src/stage2/stage2.nasm | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index e3b9471..e459476 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -665,26 +665,24 @@ GetMemoryMap: mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0 mov eax, 0xE820 ; select 0xE820 function - mov ebx, 0x0000 ; Continuation value + xor ebx, ebx ; Continuation value, 0 for the first call mov dx, (BIOSMemoryMap >> 4) mov es, dx - mov di, 0 ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap + xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap mov ecx, AddressRangeDescStruct_t_size mov edx, 0x534D4150 ; 'SMAP' magic - +.loop_L1: int 0x15 - jnc GetMemoryMap.no_error - ERROR STAGE2_MM_E820_NO_SUPPORT - -.no_error: - inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] + jc GetMemoryMap.error cmp eax, 0x534D4150 jne GetMemoryMap.no_smap_returned +.no_error: + inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] - cmp ecx, 20 - jb GetMemoryMap.nonstandard_e820 + cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing + jb GetMemoryMap.nonstandard_e820 ; non-standard entry found cmp ebx, 0 je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges @@ -692,17 +690,13 @@ GetMemoryMap: add di, AddressRangeDescStruct_t_size ; increment di to next descriptor mov edx, eax ; 'SMAP' to edx mov eax, 0xE820 ; select E820 function - - int 0x15 - jnc GetMemoryMap.no_error ; carry indicates an error - -.other_error: + jmp GetMemoryMap.loop_L1 +.error: ERROR STAGE2_MM_E820_MISC_ERR .nonstandard_e820: ERROR STAGE2_MM_E820_NONSTANDARD .no_smap_returned: ERROR STAGE2_MM_E820_NO_SMAP - .endp: pop es __CDECL16_EXIT From de5b0ddc5d9a8443b11c9d1d24397b3b611a21d1 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 17:59:29 -0400 Subject: [PATCH 038/147] cdecl16 update for EnterUnrealMode --- src/stage2/stage2.nasm | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index e459476..caa2606 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -94,8 +94,6 @@ main: call PrintString add sp, 0x2 - ERROR STEVIA_DEBUG_HALT - ; enter unreal mode call EnterUnrealMode @@ -104,6 +102,7 @@ main: call PrintString add sp, 0x2 + ERROR STEVIA_DEBUG_HALT ; FAT Driver setup push bp @@ -853,10 +852,10 @@ EnableA20: ; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 EnterUnrealMode: + __CDECL16_ENTRY +.func: cli ; no interrupts - push ds ; save real mode - push bx - + push ds ; save real mode data selector lgdt [unreal_gdt_info] mov eax, cr0 ; switch to pmode @@ -871,10 +870,10 @@ EnterUnrealMode: and al,0xFE ; back to realmode mov cr0, eax ; by toggling bit again - pop bx pop ds ; get back old segment sti .endp: + __CDECL16_EXIT ret ; ############# From 4d05d2ae4cccbca8e865e95806db16b2221744fe Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 18:14:04 -0400 Subject: [PATCH 039/147] move E820 function desc to memory.inc --- include/memory.inc | 79 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/include/memory.inc b/include/memory.inc index 4b64ca8..77deb22 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -110,6 +110,85 @@ struc SteviaInfoStruct_t .EBPBDataPtr resd 1 endstruc +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; Input: +; +; EAX Function Code E820h +; EBX Continuation Contains the "continuation value" to get the +; next run of physical memory. This is the +; value returned by a previous call to this +; routine. If this is the first call, EBX +; must contain zero. +; ES:DI Buffer Pointer Pointer to an Address Range Descriptor +; structure which the BIOS is to fill in. +; ECX Buffer Size The length in bytes of the structure passed +; to the BIOS. The BIOS will fill in at most +; ECX bytes of the structure or however much +; of the structure the BIOS implements. The +; minimum size which must be supported by both +; the BIOS and the caller is 20 bytes. Future +; implementations may extend this structure. +; EDX Signature 'SMAP' - Used by the BIOS to verify the +; caller is requesting the system map +; information to be returned in ES:DI. +; +; Output: +; +; CF Carry Flag Non-Carry - indicates no error +; EAX Signature 'SMAP' - Signature to verify correct BIOS +; revision. +; ES:DI Buffer Pointer Returned Address Range Descriptor pointer. +; Same value as on input. +; ECX Buffer Size Number of bytes returned by the BIOS in the +; address range descriptor. The minimum size +; structure returned by the BIOS is 20 bytes. +; EBX Continuation Contains the continuation value to get the +; next address descriptor. The actual +; significance of the continuation value is up +; to the discretion of the BIOS. The caller +; must pass the continuation value unchanged +; as input to the next iteration of the E820 +; call in order to get the next Address Range +; Descriptor. A return value of zero means that +; this is the last descriptor +; +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; +; The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. +; The BaseAddress is the physical address of the start of the range being specified. +; +; The LengthLow and LengthHigh together are the 64 bit Length of this range. +; The Length is the physical contiguous length in bytes of a range being specified. +; +; The Type field describes the usage of the described address range as defined in the table below. + +; Value Pneumonic Description +; 1 AddressRangeMemory This run is available RAM usable by the operating system. +; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. +; Other Undefined Undefined - Reserved for future use. + ; Address Range Descriptor Structure ; ; Offset in Bytes Name Description From 8157dd301cdf8359b8c34370d37a0be664e44872 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 18:15:18 -0400 Subject: [PATCH 040/147] swap order of entering Unreal mode and getting an E820 also InitFATDriver should be ok to add to the start process again. --- src/stage2/stage2.nasm | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index caa2606..6f5275c 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -86,14 +86,6 @@ main: call PrintString add sp, 0x2 - ; get system memory map - call GetMemoryMap - - lea ax, [MemoryMap_OK_cstr] - push ax - call PrintString - add sp, 0x2 - ; enter unreal mode call EnterUnrealMode @@ -102,13 +94,20 @@ main: call PrintString add sp, 0x2 - ERROR STEVIA_DEBUG_HALT + ; get system memory map + call GetMemoryMap + + lea ax, [MemoryMap_OK_cstr] + push ax + call PrintString + add sp, 0x2 ; FAT Driver setup push bp mov bp, sp call InitFATDriver + ERROR STEVIA_DEBUG_HALT ; ; Find first cluster of bootable file ; @@ -150,8 +149,8 @@ hcf: ; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 InitFATDriver: - push bx - + __CDECL16_ENTRY +.func: xor eax, eax mov dword [fat32_state + FAT32_State_t.active_cluster_32], eax mov dword [fat32_state + FAT32_State_t.active_FAT_cluster_32], eax @@ -190,7 +189,7 @@ InitFATDriver: .error: ERROR STAGE2_FAT32_INIT_ERROR .endp: - pop bx + __CDECL16_EXIT ret ; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 @@ -773,11 +772,8 @@ disable_cursor: ; Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible ; Bits 4-5 - Manufacturer defined ; Bits 6-7 - 00: HDD activity LED off; any other value is "on" -; -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 EnableA20: __CDECL16_ENTRY - push ds push es pushf ; save data and extra segment since we touch them and save flags @@ -850,7 +846,6 @@ EnableA20: __CDECL16_EXIT ret -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 EnterUnrealMode: __CDECL16_ENTRY .func: From 015def8d521a5bc035af6701d38b3a473bea9c2a Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 19:02:47 -0400 Subject: [PATCH 041/147] rough pass on fixing the stack across the board --- src/stage2/stage2.nasm | 158 ++++++++++++----------------------------- 1 file changed, 46 insertions(+), 112 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 6f5275c..822b234 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -103,33 +103,21 @@ main: add sp, 0x2 ; FAT Driver setup - push bp - mov bp, sp call InitFATDriver - ERROR STEVIA_DEBUG_HALT ; ; Find first cluster of bootable file ; - push bp - mov bp, sp call SearchFATDIR - PUSH_DWORD_EAX ; save return value of function as a 32-bit value on a 16-bit aligned stack - lea ax, [FileFound_OK_cstr] push ax call PrintString add sp, 0x2 - POP_DWORD_EAX ; return value of SearchFATDIR - push bp - mov bp, sp - PUSH_DWORD_EAX - call PrintDWORD + call PrintDWORD ; print 32bit value void PrintDWORD(uint32_t dword) - lea ax, [NewLine_cstr] push ax call PrintString @@ -147,7 +135,6 @@ hcf: ; ; ############### -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 InitFATDriver: __CDECL16_ENTRY .func: @@ -192,7 +179,7 @@ InitFATDriver: __CDECL16_EXIT ret -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 +; TODO: needs validation ; load a file to the high memory buffer for the elf parser ; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory ; @@ -204,18 +191,11 @@ InitFATDriver: ; halts/errors if file is not found ; uint32_t SearchFATDIR(uint8_t* SFN); SearchFATDIR: - push di - push si - push bx - + __CDECL16_ENTRY .file_lookup: xor ecx, ecx xor edx, edx .load_first_dir: - push bp - mov bp, sp - ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) - mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32] mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax PUSH_DWORD_EAX @@ -223,9 +203,9 @@ SearchFATDIR: push ax ; offset xor ax, ax push ax ; segment + call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) + add sp, 0x8 - call ReadFATCluster - leave lea si, [dir_buffer] jmp SearchFATDIR.empty_dir_entry @@ -233,13 +213,10 @@ SearchFATDIR: ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad - push bp - mov bp, sp - mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] PUSH_DWORD_EAX call NextCluster - leave + add sp, 0x4 cmp eax, 0x0fff_fff7 jb SearchFATDIR.load_next_dir_next_OK @@ -247,10 +224,6 @@ SearchFATDIR: .load_next_dir_next_OK: ; load 512 bytes of directory entries from data sector - push bp - mov bp, sp - ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) - mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32] PUSH_DWORD_EAX lea ax, [dir_buffer] @@ -258,8 +231,8 @@ SearchFATDIR: xor ax, ax push ax ; segment - call ReadFATCluster - leave + call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) + sub sp, 0x8 lea si, [dir_buffer] .empty_dir_entry: @@ -314,20 +287,15 @@ SearchFATDIR: mov ax, [si + FAT32_SFN_t.cluster_16_low] ; eax == first cluster of file .endp: - pop bx - pop si - pop di + __CDECL16_EXIT ret -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad NextCluster: - push si - push di - push bx - + __CDECL16_ENTRY +.func: MOV_DWORD_EAX 2 mov edx, eax mov si, fat32_nc_data @@ -366,11 +334,7 @@ NextCluster: add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: -; load correct fat - push bp - mov bp, sp -; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) - + ; load correct fat ror eax, 16 push ax ror eax, 16 @@ -382,8 +346,9 @@ NextCluster: xor ax, ax push ax + ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) call read_disk_raw ; read_disk_raw(0, fat_buffer, 31:16 fat_sector, 15:0 fat_sector) - leave + add sp, 0x8 .read_cluster: ; next_cluster = fat_buffer[entry_offset] @@ -391,17 +356,13 @@ NextCluster: mov si, fat_buffer mov eax, dword [bx+si+0] .endp: - pop bx - pop di - pop si + __CDECL16_EXIT ret -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; uint32_t ClusterToLBA(uint32_t cluster) ClusterToLBA: - push si - push di - + __CDECL16_ENTRY +.func: MOV_DWORD_EAX 2 sub eax, 2 movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8] @@ -409,54 +370,36 @@ ClusterToLBA: add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32] ; eax contains the LBA now .endp: - pop di - pop si + __CDECL16_EXIT ret -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) ReadFATCluster: - push si - push di - - ; cluster to LBA - - MOV_DWORD_EAX 2 - - push bp - mov bp, sp - ; uint32_t ClusterToLBA(uint32_t cluster) + __CDECL16_ENTRY +.func: + MOV_DWORD_EAX 8 PUSH_DWORD_EAX - call ClusterToLBA - leave ; eax == LBA + call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster) + add sp, 0x4 ; eax == LBA - mov dx, [bp-8] ; seg + mov dx, [bp + 4] ; seg shl edx, 16 - mov dx, [bp-6] ; offset - - + mov dx, [bp + 6] ; offset ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) - push bp - mov bp, sp - ror eax, 16 push ax ror eax, 16 - push ax + push ax ; uint32 cluster split to two (2) uint16_t's (lower and upper LBA) - push dx + push dx ; uint16_t buf_offset ror edx, 16 - push dx - - ;DEBUG_HCF + push dx ; unit16_t segment call read_disk_raw - leave - + add sp, 0x8 .endp: - pop di - pop si + __CDECL16_EXIT ret ; ############### @@ -489,14 +432,10 @@ ReadFATCluster: ; bp-6 = offset ; bp-8 = segment ; bp-10 = ret ptr -; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 +; TODO: this needs validation read_disk_raw: - push si - - ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); - push bp - mov bp, sp - + __CDECL16_ENTRY +.func: mov ax, 0x10 push ax ; len = 16 bytes xor ax, ax @@ -504,21 +443,21 @@ read_disk_raw: mov ax, lba_packet push ax ; dest = lba_packet address - call kmemset - leave + call kmemset ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); + add sp, 0x6 mov byte [lba_packet + LBAPkt_t.size], 0x10 mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 - mov ax, [bp-2] + mov ax, [bp + 4] shl eax, 16 - mov ax, [bp-4] + mov ax, [bp + 6] mov dword [lba_packet + LBAPkt_t.lower_lba], eax - mov ax, [bp-6] + mov ax, [bp + 8] mov word [lba_packet + LBAPkt_t.offset], ax - mov ax, [bp-8] + mov ax, [bp + 10] mov word [lba_packet + LBAPkt_t.segment], ax mov si, lba_packet @@ -527,9 +466,8 @@ read_disk_raw: int 0x13 jnc read_disk_raw.endp ERROR STAGE2_MBR_DISK_READ_ERROR - .endp: - pop si + __CDECL16_EXIT ret ; Prints a C-Style string (null terminated) using BIOS vga teletype call @@ -584,15 +522,14 @@ PrintCharacter: ; prints the hex representation of of val_upper:val_lower (4 byte value) ; void PrintDWORD(uint16_t val_upper, uint16_t val_lower); PrintDWORD: - push si + __CDECL16_ENTRY +.func: lea si, [IntToHex_table] - - push bx mov ebx, 16 ; base-16 - mov ax, [bp-4] ; val_upper + mov ax, [bp + 6] ; val_upper shl eax, 16 - mov ax, [bp-2] ; val_lower + mov ax, [bp + 2] ; val_lower xor edx, edx xor cx, cx @@ -618,12 +555,10 @@ PrintDWORD: dec cx push cx - push bp - mov bp, sp movzx ax, byte [bx+si+0] ; bx = index into Hex lookup table push ax call PrintCharacter - leave + add sp, 0x2 pop cx @@ -631,8 +566,7 @@ PrintDWORD: jmp PrintDWORD.print_stack .endp: - pop bx - pop si + __CDECL16_EXIT ret ; Sets output to 80x25 16 color text mode via BIOS call From 27c41c8b0a5c1881c3dd3f7f1dc08f2c762dcc84 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 19:33:07 -0400 Subject: [PATCH 042/147] update some of the dword stack macros --- include/memory.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/memory.inc b/include/memory.inc index 77deb22..f9d157e 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -244,9 +244,9 @@ endstruc ; ; first argument == starting offset from bp for lower 16bits %macro MOV_DWORD_EAX 1 - mov ax, [bp-(%1+2)] + mov ax, [bp+(%1+2)] shl eax, 16 - mov ax, [bp-%1] + mov ax, [bp+%1] ; eax contains dword from stack %endmacro From e98cc41403eddbca84959891ba0d599dd2488bec Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 19:52:00 -0400 Subject: [PATCH 043/147] forking kmemset functions to be updated later for mbr/vbr --- include/kmem_func_OLD.inc | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 include/kmem_func_OLD.inc diff --git a/include/kmem_func_OLD.inc b/include/kmem_func_OLD.inc new file mode 100644 index 0000000..e7e7080 --- /dev/null +++ b/include/kmem_func_OLD.inc @@ -0,0 +1,53 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +; uint8_t* kmemset(void* dest, uint8_t val, size_t len); +kmemset: + push di ; function uses di, so save it. + + mov cx, [bp - 2] ; size_t len + mov al, [bp - 4] ; uint8_t val + mov di, [bp - 6] ; void * ptr + + cld + rep stosb +.endf: + mov ax, [bp - 6] ; return pointer to dest + pop di ; restore di + ret + +; uint8_t* kmemset(uint8_t* dest, uint8_t* src, size_t len); +; not overlap safe +kmemcpy: + push di + push si ; di, si are callee save + + mov cx, [bp - 2] ; length + mov si, [bp - 4] ; source + mov di, [bp - 6] ; dest + + cld ; ensure we are incrementing + rep movsb + +.endf: + mov ax, [bp - 6] ; return pointer to dest + pop si + pop di + ret \ No newline at end of file From 89ebe30ad8a60820b810ecac23fc264ea6c95c19 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 19:52:24 -0400 Subject: [PATCH 044/147] forking kmemset functions for stage2 usage --- include/kmem_func.inc | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 include/kmem_func.inc diff --git a/include/kmem_func.inc b/include/kmem_func.inc new file mode 100644 index 0000000..e7e7080 --- /dev/null +++ b/include/kmem_func.inc @@ -0,0 +1,53 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +; uint8_t* kmemset(void* dest, uint8_t val, size_t len); +kmemset: + push di ; function uses di, so save it. + + mov cx, [bp - 2] ; size_t len + mov al, [bp - 4] ; uint8_t val + mov di, [bp - 6] ; void * ptr + + cld + rep stosb +.endf: + mov ax, [bp - 6] ; return pointer to dest + pop di ; restore di + ret + +; uint8_t* kmemset(uint8_t* dest, uint8_t* src, size_t len); +; not overlap safe +kmemcpy: + push di + push si ; di, si are callee save + + mov cx, [bp - 2] ; length + mov si, [bp - 4] ; source + mov di, [bp - 6] ; dest + + cld ; ensure we are incrementing + rep movsb + +.endf: + mov ax, [bp - 6] ; return pointer to dest + pop si + pop di + ret \ No newline at end of file From b96f58792170448e8f9b5a424d98ba26c1c34506 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 19:53:11 -0400 Subject: [PATCH 045/147] add forked functions and remove from memory.inc for kmem* --- include/memory.inc | 37 +------------------------------------ src/mbr/mbr.nasm | 1 + src/stage2/stage2.nasm | 1 + src/vbr/vbr.nasm | 1 + 4 files changed, 4 insertions(+), 36 deletions(-) diff --git a/include/memory.inc b/include/memory.inc index f9d157e..eb8ae11 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -254,39 +254,4 @@ endstruc DEBUG_LOOP: hlt jmp short DEBUG_LOOP -%endmacro - - -; uint8_t* kmemset(void* dest, uint8_t val, size_t len); -kmemset: - push di ; function uses di, so save it. - - mov cx, [bp - 2] ; size_t len - mov al, [bp - 4] ; uint8_t val - mov di, [bp - 6] ; void * ptr - - cld - rep stosb -.endf: - mov ax, [bp - 6] ; return pointer to dest - pop di ; restore di - ret - -; uint8_t* kmemset(uint8_t* dest, uint8_t* src, size_t len); -; not overlap safe -kmemcpy: - push di - push si ; di, si are callee save - - mov cx, [bp - 2] ; length - mov si, [bp - 4] ; source - mov di, [bp - 6] ; dest - - cld ; ensure we are incrementing - rep movsb - -.endf: - mov ax, [bp - 6] ; return pointer to dest - pop si - pop di - ret \ No newline at end of file +%endmacro \ No newline at end of file diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index c6b57e4..268e3f5 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -47,6 +47,7 @@ init: %include "config.inc" %include "memory.inc" +%include "kmem_func_OLD.inc" %include "partition_table.inc" %include "errors.inc" diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 822b234..44684dd 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -53,6 +53,7 @@ init: %include "config.inc" %include "errors.inc" %include "memory.inc" +%include "kmem_func.inc" %include "partition_table.inc" %include "cdecl16.inc" diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 4025cb1..b036ad6 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -46,6 +46,7 @@ init: %include "config.inc" %include "memory.inc" +%include "kmem_func_OLD.inc" %include "partition_table.inc" %include "errors.inc" From 41b9bf5134abd335613fab2f43daa09ae28bd862 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 20:59:25 -0400 Subject: [PATCH 046/147] remove this and add it back to vbr.nasm --- include/fat32/bpb_reserve_area.inc | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 include/fat32/bpb_reserve_area.inc diff --git a/include/fat32/bpb_reserve_area.inc b/include/fat32/bpb_reserve_area.inc deleted file mode 100644 index 27e8759..0000000 --- a/include/fat32/bpb_reserve_area.inc +++ /dev/null @@ -1,29 +0,0 @@ -; Copyright (c) 2024 Elaina Claus -; -; Permission is hereby granted, free of charge, to any person obtaining a copy -; of this software and associated documentation files (the "Software"), to deal -; in the Software without restriction, including without limitation the rights -; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -; copies of the Software, and to permit persons to whom the Software is -; furnished to do so, subject to the following conditions: -; -; The above copyright notice and this permission notice shall be included in all -; copies or substantial portions of the Software. -; -; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -; SOFTWARE. - -bpb_start: -; fill BPB area with 0x00 since we skip writing this part to disk -; but we need it for the 'jmp short entry; nop' above -times 33 db 0x00 - -ebpb_start: -; fill BPB area with 0x00 since we skip writing this part to disk -; but we need it for the 'jmp short entry; nop' above -times 54 db 0x00 \ No newline at end of file From 36b88691403518a5b073ff4fce3b28a0088446ff Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 21:00:02 -0400 Subject: [PATCH 047/147] add bpb and ebpb reserve area back to vbr.nasm --- src/vbr/vbr.nasm | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index b036ad6..661bbea 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -24,8 +24,15 @@ [CPU KATMAI] jmp short init nop +phy_bpb_start: +; fill BPB area with 0x00 since we skip writing this part to disk +; but we need it for the 'jmp short entry; nop' above +times 33 db 0x00 -%include "fat32/bpb_reserve_area.inc" +phy_ebpb_start: +; fill BPB area with 0x00 since we skip writing this part to disk +; but we need it for the 'jmp short entry; nop' above +times 54 db 0x00 %include "entry.inc" init: @@ -103,7 +110,7 @@ main: mov bp, sp mov ax, fat32_bpb_SIZE ; size in byte push ax - mov ax, bpb_start ; start of bpb + mov ax, phy_bpb_start ; start of bpb push ax mov ax, fat32_bpb ; defined in memory.inc, destination push ax @@ -114,7 +121,7 @@ main: mov bp, sp mov ax, fat32_ebpb_SIZE ; 72 bytes of data push ax - mov ax, ebpb_start ; start of ebpb + mov ax, phy_ebpb_start ; start of ebpb push ax mov ax, fat32_ebpb ; defined in memory.inc, destination push ax From 36e3bd968ab8ec2dd513a4c18155ab2cfdb549ba Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 3 Oct 2024 21:00:49 -0400 Subject: [PATCH 048/147] change FAT partition type to 0Ch from 0Bh (W95 FAT32 LBA was CHS/LBA) --- scripts/create-disk.sh | 2 +- scripts/loop_setup.sfdisk | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index eb56221..cbd96f6 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -57,7 +57,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then # get first partition firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}') - mkfs.vfat -v -F32 $firstpart + mkfs.vfat -v -F32 -S 512 $firstpart # copy MBR while preserving partition table dd if=$mbr_file of=$ld bs=1 count=440 diff --git a/scripts/loop_setup.sfdisk b/scripts/loop_setup.sfdisk index d18859f..286180d 100755 --- a/scripts/loop_setup.sfdisk +++ b/scripts/loop_setup.sfdisk @@ -1,4 +1,5 @@ label: dos unit: sectors +sector-size: 512 -start= 2048, type=b, bootable +start= 2048, type=c, bootable From ec1f40c305b9b9bb5ce2058f03fc386074650d52 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 07:57:56 -0400 Subject: [PATCH 049/147] added isoz stage to make a compressed disk image also included a work around for a WSL bug in create-disk.sh --- .gitignore | 1 + Makefile | 15 +++++++++++---- scripts/create-disk.sh | 37 ++++++++++++++++++++++++------------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 32c5bba..9cf867a 100755 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ out/* build/* *.img +*.img.gz *.elf bx_enh_dbg.ini stevia-log diff --git a/Makefile b/Makefile index 3723efc..ead41f7 100755 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -iso := 'disk.img' +iso := '/tmp/disk.img' +isoz := 'disk.img.gz' include := './include' @@ -15,9 +16,9 @@ boottest_binary_files := $(patsubst src/miniboot32/%.nasm, build/%.bin, $(bootte build_dir := 'build' qemu_args := -L ./bin/ -bios bios.bin -cpu pentium3 -m 128 -S -s -monitor stdio -nic none -.PHONY: all mbr vbr stage2 boottest clean run run_bochs iso +.PHONY: all mbr vbr stage2 boottest clean run run_bochs iso isoz -all: $(iso) $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files) +all: $(iso) $(isoz) $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files) mbr: $(mbr_binary_files) vbr: $(vbr_binary_files) stage2: $(stage2_binary_files) @@ -26,6 +27,7 @@ boottest: $(boottest_binary_files) clean: @rm -rvf $(build_dir)/* @rm -rvf $(iso) + @rm -rvf $(isoz) run: $(iso) @sudo qemu-system-i386 $(qemu_args) -hda $(iso) @@ -34,7 +36,10 @@ run_bochs: $(iso) @bochs -q iso: $(iso) - @file disk.img + @file $(iso) + +isoz: $(isoz) + @file $(isoz) build/%.bin: src/mbr/%.nasm @mkdir -p $(shell dirname $@) @@ -56,3 +61,5 @@ $(iso): $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files) $(boottes @echo root access needed to create disk image... @sudo scripts/create-disk.sh +$(isoz): $(iso) + @gzip -9kc $(iso) > $(isoz) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index cbd96f6..cbae495 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -25,21 +25,30 @@ if ! [ $(id -u) = 0 ]; then exit 1 fi +# paths to bootcode mbr_file=build/mbr.bin vbr_file=build/vbr.bin stage2_file=build/stage2.bin boottest_file=build/BOOT_386.bin -mount_point=/tmp/stevia_disk -if ! [ -e disk.img ]; then +# Disk creation options +mount_point=/tmp/stevia_disk +disk_tmp_file=/tmp/disk.img +disk_file_final=./disk.img.gz + +# $disk_sector_size * $disk_size = total bytes, default is 128MiB +disk_size=262144 +disk_sector_size=512 + +if ! [ -e $disk_tmp_file ]; then # create raw disk image with 128MiB of space - dd if=/dev/zero of=disk.img bs=512 count=262144 + dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size sync else echo "Removing old disk image..." - rm -rfv disk.img - dd if=/dev/zero of=disk.img bs=512 count=262144 + rm -rfv $disk_tmp_file + dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size sync fi @@ -47,7 +56,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then if [ -e $mbr_file ] && [ -e $vbr_file ]; then # get next loop device and mount it ld=$(losetup -f) - losetup -P -b 512 $ld disk.img + losetup -P -b 512 $ld $disk_tmp_file # create a DOS disk, with 1 FAT32 partition that is bootable, part1 starts at sector 2048 sfdisk $ld < scripts/loop_setup.sfdisk @@ -55,9 +64,9 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then # partprobe the image partprobe $ld - # get first partition + # get first partition, this is sloppy might need to review this... firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}') - mkfs.vfat -v -F32 -S 512 $firstpart + mkfs.vfat -v -F32 -S $disk_sector_size $firstpart # copy MBR while preserving partition table dd if=$mbr_file of=$ld bs=1 count=440 @@ -73,7 +82,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then dd if=$vbr_file of=$firstpart bs=1 seek=510 skip=510 count=2 #stage2 to sectors 1-64 - dd if=$stage2_file of=$ld bs=512 seek=1 + dd if=$stage2_file of=$ld bs=$disk_sector_size seek=1 # copy boot32 boot test file to disk image if ! [ -e $mount_point ]; then @@ -94,8 +103,10 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then losetup -d $ld # chown to the real user to prevent issues with reading/writing the file later - SUDOUSER=$(logname) - chown --from=root:root ${SUDOUSER}:$(id $SUDOUSER -g) disk.img + # BUG: ${logname}:$(id $(logname -g)) doesn't work right on WSL because of runlevel hacks in WSL + # BUG: https://github.com/microsoft/WSL/issues/1761 + # as a work around I'll just reference LICENSE.md...WHICH SHOULD ALWAYS BE THERE 👀 + chown --from=root:root --reference=LICENSE.md $disk_tmp_file else echo "unable to find MBR/VBR binaries!" @@ -159,7 +170,7 @@ elif [[ "$OSTYPE" == "darwin"* ]]; then dd if=$vbr_file of=/dev/$firstpart bs=1 seek=510 skip=510 count=2 conv=sync #stage2 to sectors 1-64 - dd if=$stage2_file of=$ld_path bs=512 seek=1 conv=sync + dd if=$stage2_file of=$ld_path bs=$disk_sector_size seek=1 conv=sync #sync pending dd stuff sync @@ -189,7 +200,7 @@ elif [[ "$OSTYPE" == "darwin"* ]]; then # chown to the real user to prevent issues with reading/writing the file later SUDOUSER=$(logname) chown ${SUDOUSER}:staff disk.img - + gzip -9kc $disk_tmp_file > $disk_file_final else echo "unable to find MBR/VBR binaries!" exit 2 From d5aa70daf37bc7250007eb6aadfdf256688746c5 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 09:51:44 -0400 Subject: [PATCH 050/147] add macros to prevent __CDECL16 stuff from being defined multiple times --- include/cdecl16.inc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/cdecl16.inc b/include/cdecl16.inc index 528a2a1..b039985 100644 --- a/include/cdecl16.inc +++ b/include/cdecl16.inc @@ -17,7 +17,7 @@ ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. - +%ifnmacro __CDECL16_ENTRY %macro __CDECL16_ENTRY 0 push bp mov bp, sp @@ -26,7 +26,9 @@ push di push bx %endmacro +%endif +%ifnmacro __CDECL16_EXIT %macro __CDECL16_EXIT 0 pop bx pop di @@ -34,4 +36,5 @@ mov sp, bp pop bp -%endmacro \ No newline at end of file +%endmacro +%endif From 4ee766304b4a3153a63ca53a1441ed7d9722f326 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 09:52:24 -0400 Subject: [PATCH 051/147] seperate error code for reading disk in mbr vs vbr vs stage2 --- include/errors.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/errors.inc b/include/errors.inc index 31f723a..82da97d 100755 --- a/include/errors.inc +++ b/include/errors.inc @@ -32,7 +32,7 @@ %define MBR_ERROR_RESERVED_i 'i' %define MBR_ERROR_RESERVED_j 'j' %define MBR_ERROR_RESERVED_k 'k' -%define MBR_ERROR_RESERVED_l 'l' +%define MBR_ERROR_INT13h_EREAD_ERR 'l' ; 12 Error %define VBR_ERROR_WRONG_FAT_SIZE 'm' From 63e6f1fac850b6745d8f59e6f8d41d43d3db2db4 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 09:53:01 -0400 Subject: [PATCH 052/147] kmemset and kmemcpy cdecl16 versions --- include/kmem_func.inc | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/include/kmem_func.inc b/include/kmem_func.inc index e7e7080..e69ca31 100644 --- a/include/kmem_func.inc +++ b/include/kmem_func.inc @@ -17,37 +17,35 @@ ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%include 'cdecl16.inc' -; uint8_t* kmemset(void* dest, uint8_t val, size_t len); +; uint8_t* kmemset(void* dest, uint8_t val, uint8_t len); kmemset: - push di ; function uses di, so save it. - - mov cx, [bp - 2] ; size_t len - mov al, [bp - 4] ; uint8_t val - mov di, [bp - 6] ; void * ptr + __CDECL16_ENTRY + .func: + mov cx, [bp + 8] ; size_t len + mov al, [bp + 6] ; uint8_t val + mov di, [bp + 4] ; void * ptr cld - rep stosb -.endf: - mov ax, [bp - 6] ; return pointer to dest - pop di ; restore di + rep stosb + mov ax, di ; return pointer to dest +.endp: + __CDECL16_EXIT ret -; uint8_t* kmemset(uint8_t* dest, uint8_t* src, size_t len); +; uint8_t* kmemset(uint8_t* dest, uint8_t* src, uint8_t len); ; not overlap safe kmemcpy: - push di - push si ; di, si are callee save - - mov cx, [bp - 2] ; length - mov si, [bp - 4] ; source - mov di, [bp - 6] ; dest + __CDECL16_ENTRY +.func: + mov cx, [bp + 8] ; len + mov si, [bp + 6] ; src + mov di, [bp + 4] ; dest cld ; ensure we are incrementing rep movsb - + mov ax, di ; return pointer to dest .endf: - mov ax, [bp - 6] ; return pointer to dest - pop si - pop di + __CDECL16_EXIT ret \ No newline at end of file From 597132df9fe792417f2d26eeff54f3e2f6e2b63f Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 09:55:19 -0400 Subject: [PATCH 053/147] cdecl16 overhaul for mbr code switch to cdecl kmem* functions refactored read_disk_raw to read_vbr_raw fixed a small issue where the mbr wasn't checking its signature --- src/mbr/mbr.nasm | 62 ++++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 268e3f5..1d14927 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -23,8 +23,8 @@ [CPU KATMAI] jmp short init nop - -%include "entry.inc" +%include "cdecl16.inc" ; include calling convention macros for cdecl16 +%include "entry.inc" ; defines with entry points for various stages & stack init: cli ; We do not want to be interrupted @@ -47,7 +47,7 @@ init: %include "config.inc" %include "memory.inc" -%include "kmem_func_OLD.inc" +%include "kmem_func.inc" %include "partition_table.inc" %include "errors.inc" @@ -56,7 +56,7 @@ main: .check_disk: cmp dl, 0x80 - jae main.find_active + jae main.check_extentions ERROR MBR_ERROR_DISK_T_ERR .check_extentions: @@ -85,9 +85,6 @@ main: ; this gives us an offset from the begining of the partition table mov word [part_offset], ax ; update part_offset .read_data: - push bp - mov bp, sp - ;uint8_t read_disk_raw(size_t count, uint16_t buf_segment, uint16_t buf_offset, ; uint16_t lower_lower_lba, uint16_t upper_lower_lba) mov eax, dword [bx + PartEntry_t.lba_start] @@ -103,11 +100,8 @@ main: xor ax, ax push ax ; segment = 0 - mov ax, 1 - push ax - - call read_disk_raw - leave + call read_vbr_raw + add sp, 0x8 jnc main.goto_vbr ERROR MBR_ERROR_DISK_READ_ERR ; error in LBA read @@ -117,9 +111,6 @@ main: ERROR MBR_ERROR_NO_VBR_SIG ; no signature present .sig_ok: - push bp - mov bp, sp - mov ax, partition_table_SIZE ; 72 bytes of data push ax mov ax, DiskSig ; start of partition table @@ -127,7 +118,7 @@ main: mov ax, partition_table ; defined in memory.inc push ax call kmemcpy ; copy partition table to memory - leave + add sp, 0x6 xor ah, ah ; Set Video mode BIOS function mov al, 0x02 ; 16 color 80x25 Text mode @@ -158,54 +149,41 @@ main: ; ; ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) -; bp-0 = call frame -; bp-2 = upper_lower_lba -; bp-4 = lower_lower_lba -; bp-6 = offset -; bp-8 = segment -; bp-10 = count -; bp-12 = ret ptr -read_disk_raw: - push si - - ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); - push bp - mov bp, sp - +read_vbr_raw: + __CDECL16_ENTRY +.func: mov ax, 0x10 push ax ; len = 16 bytes xor ax, ax push ax ; val = 0 mov ax, lba_packet push ax ; dest = lba_packet address - - call kmemset - leave + call kmemset + add sp, 0x06 mov byte [lba_packet + LBAPkt_t.size], 0x10 - mov word [lba_packet + LBAPkt_t.xfer_size], STAGE2_SECTOR_COUNT + mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 - mov ax, [bp-2] + mov ax, [bp + 10] shl eax, 16 - mov ax, [bp-4] + mov ax, [bp + 8] mov dword [lba_packet + LBAPkt_t.lower_lba], eax - mov ax, [bp-6] + mov ax, [bp + 6] mov word [lba_packet + LBAPkt_t.offset], ax - mov ax, [bp-8] + mov ax, [bp + 4] mov word [lba_packet + LBAPkt_t.segment], ax mov si, lba_packet mov ah, 0x42 mov dl, byte [boot_drive] int 0x13 - jnc read_disk_raw.endf + jnc .endf - mov al, 'B' - jmp error + ERROR MBR_ERROR_INT13h_EREAD_ERR .endf: - pop si + __CDECL16_EXIT ret ; ############# From 30c4f1b82c4e0b6b2ce9d07352c3e8cc8f91cf29 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 09:55:45 -0400 Subject: [PATCH 054/147] move cdecl macros to nearly the top so early functions can use them --- src/stage2/stage2.nasm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 44684dd..e98146c 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -26,6 +26,7 @@ nop ; boot drive in dl ; active partition offset in si +%include "cdecl16.inc" %include "entry.inc" init: cli ; We do not want to be interrupted @@ -55,7 +56,6 @@ init: %include "memory.inc" %include "kmem_func.inc" %include "partition_table.inc" -%include "cdecl16.inc" %include "fat32/bpb.inc" %include "fat32/fat32_structures.inc" From 3f029e6b4c9486df8c92fa248da0ccdde6e08462 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 09:56:41 -0400 Subject: [PATCH 055/147] vbr cdecl overhaul refactored read_disk_raw to read_stage2_raw switched to new kmem functions --- src/vbr/vbr.nasm | 67 +++++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 44 deletions(-) diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 661bbea..aaaeb52 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -33,8 +33,8 @@ phy_ebpb_start: ; fill BPB area with 0x00 since we skip writing this part to disk ; but we need it for the 'jmp short entry; nop' above times 54 db 0x00 +%include "cdecl16.inc" %include "entry.inc" - init: cli ; We do not want to be interrupted @@ -46,14 +46,15 @@ init: mov sp, STACK_START ; Setup stack mov bp, sp ; base ptr = stack ptr - mov bx, VBR_ENTRY ; move BP to the new start of the initial boot sector + mov bx, VBR_ENTRY ; move Bx to the new start of the initial boot sector sti ; all done with inital setup and relocation, reenable interupts jmp 0:main ; fix up cs:ip just in case and jump to relocated code + nop %include "config.inc" %include "memory.inc" -%include "kmem_func_OLD.inc" +%include "kmem_func.inc" %include "partition_table.inc" %include "errors.inc" @@ -71,12 +72,6 @@ main: ; read sectors 1-63 to stage2 entry point .load_stage2: - push bp - mov bp, sp - - ;uint8_t read_disk_raw(size_t count, uint16_t buf_segment, uint16_t buf_offset, - ; uint16_t lower_lower_lba, uint16_t upper_lower_lba) - xor ax, ax push ax ; upper_lower_lba = 0 @@ -91,11 +86,10 @@ main: shr ax, 4 push ax ; segment = 7E0 - mov ax, STAGE2_SECTOR_COUNT - push ax - - call read_disk_raw - leave + ;uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, + ; uint16_t lower_lower_lba, uint16_t upper_lower_lba) + call read_stage2_raw + add sp, 0x8 .check_sig: mov ax, 0x7E0 @@ -106,8 +100,6 @@ main: ERROR VBR_ERROR_NO_SIGNATURE ; no signature present in stage2 .sig_ok: - push bp - mov bp, sp mov ax, fat32_bpb_SIZE ; size in byte push ax mov ax, phy_bpb_start ; start of bpb @@ -115,10 +107,8 @@ main: mov ax, fat32_bpb ; defined in memory.inc, destination push ax call kmemcpy ; copy bpb to memory - leave + add sp, 0x6 - push bp - mov bp, sp mov ax, fat32_ebpb_SIZE ; 72 bytes of data push ax mov ax, phy_ebpb_start ; start of ebpb @@ -126,7 +116,7 @@ main: mov ax, fat32_ebpb ; defined in memory.inc, destination push ax call kmemcpy ; copy ebpb to memory - leave + add sp, 0x6 mov si, [partition_offset] mov dl, [bsDriveNumber] @@ -152,54 +142,43 @@ stop: ; successfully transferred ; ; -; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) -; bp-0 = call frame -; bp-2 = upper_lower_lba -; bp-4 = lower_lower_lba -; bp-6 = offset -; bp-8 = segment -; bp-10 = count -; bp-12 = ret ptr -read_disk_raw: - push si - - ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); - push bp - mov bp, sp - +; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, +; uint16_t lower_lower_lba, uint16_t upper_lower_lba) +read_stage2_raw: + __CDECL16_ENTRY +.func: mov ax, 0x10 push ax ; len = 16 bytes xor ax, ax push ax ; val = 0 mov ax, lba_packet push ax ; dest = lba_packet address - - call kmemset - leave + call kmemset + add sp, 0x06 mov byte [lba_packet + LBAPkt_t.size], 0x10 mov word [lba_packet + LBAPkt_t.xfer_size], STAGE2_SECTOR_COUNT - mov ax, [bp-2] + mov ax, [bp + 10] shl eax, 16 - mov ax, [bp-4] + mov ax, [bp + 8] mov dword [lba_packet + LBAPkt_t.lower_lba], eax - mov ax, [bp-6] + mov ax, [bp + 6] mov word [lba_packet + LBAPkt_t.offset], ax - mov ax, [bp-8] + mov ax, [bp + 4] mov word [lba_packet + LBAPkt_t.segment], ax mov si, lba_packet mov ah, 0x42 mov dl, byte [bsDriveNumber] int 0x13 - jnc read_disk_raw.endf + jnc .endf ERROR VBR_ERROR_DISK_READ_ERR .endf: - pop si + __CDECL16_EXIT ret ; Data From 86fd76e909b4e62973a8bf26904aac2e818fe7da Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 09:57:32 -0400 Subject: [PATCH 056/147] remove old kmem functions --- include/kmem_func_OLD.inc | 53 --------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 include/kmem_func_OLD.inc diff --git a/include/kmem_func_OLD.inc b/include/kmem_func_OLD.inc deleted file mode 100644 index e7e7080..0000000 --- a/include/kmem_func_OLD.inc +++ /dev/null @@ -1,53 +0,0 @@ -; Copyright (c) 2024 Elaina Claus -; -; Permission is hereby granted, free of charge, to any person obtaining a copy -; of this software and associated documentation files (the "Software"), to deal -; in the Software without restriction, including without limitation the rights -; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -; copies of the Software, and to permit persons to whom the Software is -; furnished to do so, subject to the following conditions: -; -; The above copyright notice and this permission notice shall be included in all -; copies or substantial portions of the Software. -; -; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -; SOFTWARE. - -; uint8_t* kmemset(void* dest, uint8_t val, size_t len); -kmemset: - push di ; function uses di, so save it. - - mov cx, [bp - 2] ; size_t len - mov al, [bp - 4] ; uint8_t val - mov di, [bp - 6] ; void * ptr - - cld - rep stosb -.endf: - mov ax, [bp - 6] ; return pointer to dest - pop di ; restore di - ret - -; uint8_t* kmemset(uint8_t* dest, uint8_t* src, size_t len); -; not overlap safe -kmemcpy: - push di - push si ; di, si are callee save - - mov cx, [bp - 2] ; length - mov si, [bp - 4] ; source - mov di, [bp - 6] ; dest - - cld ; ensure we are incrementing - rep movsb - -.endf: - mov ax, [bp - 6] ; return pointer to dest - pop si - pop di - ret \ No newline at end of file From d93236d29862b23da196e7a7a84c2b9632229650 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 11:48:25 -0400 Subject: [PATCH 057/147] some bpb/ebpb tweaks --- src/vbr/vbr.nasm | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index aaaeb52..ebb8b71 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -17,8 +17,6 @@ ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. - - [BITS 16] [ORG 0x7C00] [CPU KATMAI] @@ -28,11 +26,10 @@ phy_bpb_start: ; fill BPB area with 0x00 since we skip writing this part to disk ; but we need it for the 'jmp short entry; nop' above times 33 db 0x00 - phy_ebpb_start: -; fill BPB area with 0x00 since we skip writing this part to disk -; but we need it for the 'jmp short entry; nop' above +; fill eBPB area with 0x00 since we skip writing this part to disk times 54 db 0x00 + %include "cdecl16.inc" %include "entry.inc" init: @@ -102,7 +99,7 @@ main: .sig_ok: mov ax, fat32_bpb_SIZE ; size in byte push ax - mov ax, phy_bpb_start ; start of bpb + mov ax, phy_bpb_start ; start of bpb push ax mov ax, fat32_bpb ; defined in memory.inc, destination push ax @@ -111,7 +108,7 @@ main: mov ax, fat32_ebpb_SIZE ; 72 bytes of data push ax - mov ax, phy_ebpb_start ; start of ebpb + mov ax, phy_ebpb_start ; start of ebpb push ax mov ax, fat32_ebpb ; defined in memory.inc, destination push ax From fdbfd811d5cf31598bfcd281ace2ae15841ffdaf Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 14:26:10 -0400 Subject: [PATCH 058/147] increased disk size and moved bpb/ebpb a bit --- include/memory.inc | 2 +- scripts/create-disk.sh | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/memory.inc b/include/memory.inc index eb8ae11..73d7fcb 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -59,7 +59,7 @@ ; copy of FAT32 EBPB, 54 bytes ;0x306A -%define fat32_ebpb 0x3070 +%define fat32_ebpb 0x30A0 %define fat32_ebpb_SIZE 54 ; FAT32 FSInfo, 512 bytes diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index cbae495..ccfa103 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -37,12 +37,12 @@ mount_point=/tmp/stevia_disk disk_tmp_file=/tmp/disk.img disk_file_final=./disk.img.gz -# $disk_sector_size * $disk_size = total bytes, default is 128MiB -disk_size=262144 +# $disk_sector_size * $disk_size = total bytes, default is 256MiB +disk_size=524288 disk_sector_size=512 if ! [ -e $disk_tmp_file ]; then - # create raw disk image with 128MiB of space + # create raw disk image dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size sync else @@ -66,7 +66,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then # get first partition, this is sloppy might need to review this... firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}') - mkfs.vfat -v -F32 -S $disk_sector_size $firstpart + mkfs.fat -v -F32 $firstpart # copy MBR while preserving partition table dd if=$mbr_file of=$ld bs=1 count=440 From 62f036b645a45cf70a436d1151344dbfada0d633 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 4 Oct 2024 22:17:35 -0400 Subject: [PATCH 059/147] change test kernel stage name also pointed up a bug in memory.inc --- include/memory.inc | 1 + scripts/create-disk.sh | 10 +++++----- src/miniboot32/{BOOT_386.nasm => BOOTi686.nasm} | 0 src/stage2/stage2.nasm | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) rename src/miniboot32/{BOOT_386.nasm => BOOTi686.nasm} (100%) diff --git a/include/memory.inc b/include/memory.inc index 73d7fcb..5ebf4da 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -243,6 +243,7 @@ endstruc ; STACK BOTTOM ; ; first argument == starting offset from bp for lower 16bits +; BUG: needs fixed for cdecl16 %macro MOV_DWORD_EAX 1 mov ax, [bp+(%1+2)] shl eax, 16 diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index ccfa103..994cb22 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -29,7 +29,7 @@ fi mbr_file=build/mbr.bin vbr_file=build/vbr.bin stage2_file=build/stage2.bin -boottest_file=build/BOOT_386.bin +boottest_file=build/BOOTi686.bin # Disk creation options @@ -38,7 +38,7 @@ disk_tmp_file=/tmp/disk.img disk_file_final=./disk.img.gz # $disk_sector_size * $disk_size = total bytes, default is 256MiB -disk_size=524288 +disk_size=(524288 * 2) disk_sector_size=512 if ! [ -e $disk_tmp_file ]; then @@ -66,7 +66,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then # get first partition, this is sloppy might need to review this... firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}') - mkfs.fat -v -F32 $firstpart + mkfs.fat -v -n 'STEVIAFS' $firstpart # copy MBR while preserving partition table dd if=$mbr_file of=$ld bs=1 count=440 @@ -89,9 +89,9 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then mkdir $mount_point fi mount $firstpart $mount_point - + mkdir -p $mount_point/STEVIA if [ -e $boottest_file ]; then - cp -v $boottest_file $mount_point + cp -v $boottest_file $mount_point/STEVIA/BOOTi686.BIN else echo "unable to find boot32.bin!" exit 3 diff --git a/src/miniboot32/BOOT_386.nasm b/src/miniboot32/BOOTi686.nasm similarity index 100% rename from src/miniboot32/BOOT_386.nasm rename to src/miniboot32/BOOTi686.nasm diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index e98146c..94c27c1 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -829,7 +829,7 @@ IntToHex_table: NewLine_cstr: db StrCRLF_NUL BootTarget_str: - db "BOOT_386BIN" + db "BOOTI686BIN" ; ############# ; From e162e268c4652e668e22d548c033ee538c4ed394 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 5 Oct 2024 10:13:18 -0400 Subject: [PATCH 060/147] remove the dword stack macros and just use the 32bit override --- include/memory.inc | 44 ----------------------- src/stage2/stage2.nasm | 82 ++++++++++++++++-------------------------- 2 files changed, 31 insertions(+), 95 deletions(-) diff --git a/include/memory.inc b/include/memory.inc index 5ebf4da..7f0e15b 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -207,50 +207,6 @@ struc AddressRangeDescStruct_t .ExtType resd 1 endstruc -; moves argument into eax then pushes lower 16bits then upper 16 bits of of argument to stack -; eax is clobbered -%macro PUSH_DWORD 1 - mov eax, %1 - push ax - shr eax, 16 - push ax -%endmacro - -; same as PUSH_DWORD except no arguments, pushes EAX directly -%macro PUSH_DWORD_EAX 0 - push ax - shr eax, 16 - push ax -%endmacro - -; pops upper 16bits then lower 16bits into eax -; eax is clobbered -%macro POP_DWORD_EAX 0 - xor eax, eax - pop ax - shl eax, 16 - pop ax -%endmacro - -; moves data on stack referenced by bp to eax -; stack must be organized as follows (tl;dr push lower 16bits first ie. PUSH_DWORD macro) -; MOV_DWORD_EAX 2 -; STACK TOP (0x0) -; upper_uint16 [bp-4] -; lower_uint16 [bp-2] -; --- [bp] --- -; ... -; STACK BOTTOM -; -; first argument == starting offset from bp for lower 16bits -; BUG: needs fixed for cdecl16 -%macro MOV_DWORD_EAX 1 - mov ax, [bp+(%1+2)] - shl eax, 16 - mov ax, [bp+%1] - ; eax contains dword from stack -%endmacro - %macro DEBUG_HCF 0 DEBUG_LOOP: hlt diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 94c27c1..87609ca 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -110,15 +110,17 @@ main: ; Find first cluster of bootable file ; call SearchFATDIR - PUSH_DWORD_EAX ; save return value of function as a 32-bit value on a 16-bit aligned stack + push dword eax lea ax, [FileFound_OK_cstr] push ax call PrintString add sp, 0x2 - call PrintDWORD ; print 32bit value void PrintDWORD(uint32_t dword) - + push dword eax + call PrintDWORD ; void PrintDWORD(uint32_t dword) + add sp, 0x4 + lea ax, [NewLine_cstr] push ax call PrintString @@ -194,12 +196,11 @@ InitFATDriver: SearchFATDIR: __CDECL16_ENTRY .file_lookup: - xor ecx, ecx - xor edx, edx .load_first_dir: mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32] mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax - PUSH_DWORD_EAX + + push dword eax ; cluster lea ax, [dir_buffer] push ax ; offset xor ax, ax @@ -211,12 +212,11 @@ SearchFATDIR: jmp SearchFATDIR.empty_dir_entry .load_next_dir: - ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] - PUSH_DWORD_EAX - call NextCluster + push dword eax + call NextCluster ; uint32_t NextCluster(uint32_t active_cluster); add sp, 0x4 cmp eax, 0x0fff_fff7 @@ -226,12 +226,12 @@ SearchFATDIR: .load_next_dir_next_OK: ; load 512 bytes of directory entries from data sector mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32] - PUSH_DWORD_EAX - lea ax, [dir_buffer] + + push dword eax + lea ax, [dir_buffer] ; cluster push ax ; offset xor ax, ax push ax ; segment - call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) sub sp, 0x8 @@ -297,8 +297,7 @@ SearchFATDIR: NextCluster: __CDECL16_ENTRY .func: - MOV_DWORD_EAX 2 - mov edx, eax + mov dword edx, [bp + 4] mov si, fat32_nc_data .calc_offset: ; fat_offset = active_cluster * 4 @@ -336,19 +335,15 @@ NextCluster: mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: ; load correct fat - ror eax, 16 - push ax - ror eax, 16 - push ax + push dword eax mov ax, fat_buffer push ax xor ax, ax push ax - ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) - call read_disk_raw ; read_disk_raw(0, fat_buffer, 31:16 fat_sector, 15:0 fat_sector) + call read_disk_raw ; read_disk_raw(0, fat_buffer, fat_sector) add sp, 0x8 .read_cluster: @@ -364,7 +359,7 @@ NextCluster: ClusterToLBA: __CDECL16_ENTRY .func: - MOV_DWORD_EAX 2 + mov dword eax, [bp + 4] sub eax, 2 movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8] mul edx @@ -378,26 +373,21 @@ ClusterToLBA: ReadFATCluster: __CDECL16_ENTRY .func: - MOV_DWORD_EAX 8 - PUSH_DWORD_EAX + mov dword eax, [bp + 8] + push dword eax call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster) add sp, 0x4 ; eax == LBA + - mov dx, [bp + 4] ; seg - shl edx, 16 - mov dx, [bp + 6] ; offset - - ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) - ror eax, 16 - push ax - ror eax, 16 - push ax ; uint32 cluster split to two (2) uint16_t's (lower and upper LBA) + push dword eax ;uint32_t lba + mov dx, [bp + 4] ; seg push dx ; uint16_t buf_offset - ror edx, 16 + + mov dx, [bp + 6] ; offset push dx ; unit16_t segment - call read_disk_raw + call read_disk_raw ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) add sp, 0x8 .endp: __CDECL16_EXIT @@ -426,13 +416,7 @@ ReadFATCluster: ; successfully transferred ; ; -; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) -; bp-0 = call frame -; bp-2 = upper_lower_lba -; bp-4 = lower_lower_lba -; bp-6 = offset -; bp-8 = segment -; bp-10 = ret ptr +; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) ; TODO: this needs validation read_disk_raw: __CDECL16_ENTRY @@ -450,15 +434,13 @@ read_disk_raw: mov byte [lba_packet + LBAPkt_t.size], 0x10 mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 - mov ax, [bp + 4] - shl eax, 16 - mov ax, [bp + 6] + mov dword eax, [bp + 8] mov dword [lba_packet + LBAPkt_t.lower_lba], eax - mov ax, [bp + 8] + mov ax, [bp + 6] mov word [lba_packet + LBAPkt_t.offset], ax - mov ax, [bp + 10] + mov ax, [bp + 4] mov word [lba_packet + LBAPkt_t.segment], ax mov si, lba_packet @@ -520,17 +502,15 @@ PrintCharacter: ret ; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 -; prints the hex representation of of val_upper:val_lower (4 byte value) -; void PrintDWORD(uint16_t val_upper, uint16_t val_lower); +; prints the hex representation of of val +; void PrintDWORD(uint32_t val); PrintDWORD: __CDECL16_ENTRY .func: lea si, [IntToHex_table] mov ebx, 16 ; base-16 - mov ax, [bp + 6] ; val_upper - shl eax, 16 - mov ax, [bp + 2] ; val_lower + mov dword eax, [bp + 4] ;val xor edx, edx xor cx, cx From 0a1123c5b5e3d0761333e0cffc74d434eed54511 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 5 Oct 2024 10:14:02 -0400 Subject: [PATCH 061/147] removed extra part probe and added sleep before removing disk also back to putting the test 32bit mode code on the root of the volume --- scripts/create-disk.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index 994cb22..59aa6fd 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -61,12 +61,9 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then # create a DOS disk, with 1 FAT32 partition that is bootable, part1 starts at sector 2048 sfdisk $ld < scripts/loop_setup.sfdisk - # partprobe the image - partprobe $ld - # get first partition, this is sloppy might need to review this... firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}') - mkfs.fat -v -n 'STEVIAFS' $firstpart + mkfs.fat -v -F32 -n 'STEVIAFS' $firstpart # copy MBR while preserving partition table dd if=$mbr_file of=$ld bs=1 count=440 @@ -89,9 +86,9 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then mkdir $mount_point fi mount $firstpart $mount_point - mkdir -p $mount_point/STEVIA + mkdir -p $mount_point if [ -e $boottest_file ]; then - cp -v $boottest_file $mount_point/STEVIA/BOOTi686.BIN + cp -v $boottest_file $mount_point/BOOTI686.BIN else echo "unable to find boot32.bin!" exit 3 @@ -100,6 +97,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then # detach loop device umount $mount_point sync + sleep 1 losetup -d $ld # chown to the real user to prevent issues with reading/writing the file later From a4fa48949c11cc117d6b6d786d22fb5bf3e9eb37 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 5 Oct 2024 12:04:40 -0400 Subject: [PATCH 062/147] Move fat32 and BIOS functions to their own files --- include/BIOS/BIOS_func.inc | 272 ++++++++++++++++ include/fat32/fat32_func_old.inc | 274 ++++++++++++++++ src/stage2/stage2.nasm | 514 +------------------------------ 3 files changed, 551 insertions(+), 509 deletions(-) create mode 100644 include/BIOS/BIOS_func.inc create mode 100644 include/fat32/fat32_func_old.inc diff --git a/include/BIOS/BIOS_func.inc b/include/BIOS/BIOS_func.inc new file mode 100644 index 0000000..64050de --- /dev/null +++ b/include/BIOS/BIOS_func.inc @@ -0,0 +1,272 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +; +;INT 0x15 Function 2400 - Disable A20 +;Returns: +; +; CF = clear if success +; AH = 0 +; CF = set on error +; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported) +; +;INT 0x15 Function 2401 - Enable A20 +;Returns: +; +; CF = clear if success +; AH = 0 +; CF = set on error +; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported) +; +;INT 0x15 Function 2402 - A20 Status +; Returns: +; +; CF = clear if success +; AH = status (01: keyboard controller is in secure mode; 0x86: function not supported) +; AL = current state (00: disabled, 01: enabled) +; CX = set to 0xffff is keyboard controller is no ready in 0xc000 read attempts +; CF = set on error +; +;INT 0x15 Function 2403 - Query A20 support +;Returns: +; +;CF = clear if success +;AH = status (01: keyboard controller is in secure mode; 0x86: function not supported) +;BX = status. +; +;BX contains a bit pattern: +; +; Bit 0 - supported on keyboard controller +; Bit 1 - if supported on bit 1 of I/O port 0x92 +; Bits 2:14 - Reserved +; Bit 15 - 1 if additional data is available. +; +; I/O Port 0x92 infomation: +; +; Bit 0 - Setting to 1 causes a fast reset +; Bit 1 - 0: disable A20; 1: enable A20 +; Bit 2 - Manufacturer defined +; Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible +; Bits 4-5 - Manufacturer defined +; Bits 6-7 - 00: HDD activity LED off; any other value is "on" +EnableA20: + __CDECL16_ENTRY + push ds + push es +.a20_check: + cli + + xor ax, ax + mov es, ax + + not ax ; ax = 0xFFFF + mov ds, ax + + mov di, 0x0500 ; scratch location 1 + mov si, 0x0510 ; scratch location 2 + + mov al, byte [es:di] + push ax ; save whatever is at 0x0000:0500, physical location 0x0500 + + mov al, byte [ds:si] + push ax ; save whatever is at 0xFFFF:0510 [clarification: 0x100500 physical location (0x100500 - 1MB = 0x0500)] + + mov byte [es:di], 0x00 ; zero non-wraped location and write 0xFF to it after (ab)using wrapping + mov byte [ds:si], 0xFF ; if the non-wrapped location is 0xFF, then we wraped and A20 is disabled + + cmp byte [es:di], 0xFF + + pop ax + mov byte [ds:si], al ; restore original contents of scratch location 2 + + pop ax + mov byte [es:di], al ; restore original contents of scratch location 1 + + mov ax, 0 ; return 0 if es:di == ds:si (memory wraps) + je EnableA20.end_check + mov ax, 1 ; return 1 if es:di != ds:si (A20 is enabled) +.end_check: + sti + cmp ax, 1 + je EnableA20.endp ; A20 is already enabled + + mov ax, 0x2403 + int 0x15 + jc EnableA20.do_fallback_a20 ; carry = error...not supported? + cmp ah, 0 + ja EnableA20.do_fallback_a20 ; non-zero return = error as well + + mov al, bl + and al, 0000_0010b + cmp al, 0000_0010b + je EnableA20.do_fast_a20 ; if fast a20 is supported use it + + jmp EnableA20.do_bios_a20 ; else fall back to enabling via BIOS + +.do_fallback_a20: + ERROR STAGE2_A20_FAILED +.do_bios_a20: + mov ax, 0x2401 + int 0x15 + jmp EnableA20.a20_check +.do_fast_a20: + in al, 0x92 ; read from FAST A20 port + or al, 2 ; bit 0 is a fast reset, bit 1 is fast A20 + and al, 0xFE ; make sure bit 0 is 0 + out 0x92, al ; enable A20 + jmp EnableA20.a20_check +.endp: + pop es + pop ds + __CDECL16_EXIT + ret + +; See memory.inc for a brief description of E820 mmap function +GetMemoryMap: + __CDECL16_ENTRY + push es ; save segment register +.func: + mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0 + + mov eax, 0xE820 ; select 0xE820 function + xor ebx, ebx ; Continuation value, 0 for the first call + + mov dx, (BIOSMemoryMap >> 4) + mov es, dx + xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap + + mov ecx, AddressRangeDescStruct_t_size + mov edx, 0x534D4150 ; 'SMAP' magic +.loop_L1: + int 0x15 + jc GetMemoryMap.error + cmp eax, 0x534D4150 + jne GetMemoryMap.no_smap_returned +.no_error: + inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] + + cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing + jb GetMemoryMap.nonstandard_e820 ; non-standard entry found + + cmp ebx, 0 + je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges + + add di, AddressRangeDescStruct_t_size ; increment di to next descriptor + mov edx, eax ; 'SMAP' to edx + mov eax, 0xE820 ; select E820 function + jmp GetMemoryMap.loop_L1 +.error: + ERROR STAGE2_MM_E820_MISC_ERR +.nonstandard_e820: + ERROR STAGE2_MM_E820_NONSTANDARD +.no_smap_returned: + ERROR STAGE2_MM_E820_NO_SMAP +.endp: + pop es + __CDECL16_EXIT + ret + +; Wrapper for AH=0x42 INT13h (Extended Read) +; +; BIOS call details +; AH = 42h +; DL = drive number +; DS:SI -> disk address packet +; +; Return: +; CF clear if successful +; AH = 00h +; CF set on error +; AH = error code +; disk address packet's block count field set to number of blocks +; successfully transferred +; +; +; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) +; TODO: this needs validation +read_disk_raw: + __CDECL16_ENTRY +.func: + mov ax, 0x10 + push ax ; len = 16 bytes + xor ax, ax + push ax ; val = 0 + mov ax, lba_packet + push ax ; dest = lba_packet address + + call kmemset ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); + add sp, 0x6 + + mov byte [lba_packet + LBAPkt_t.size], 0x10 + mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 + + mov dword eax, [bp + 8] + mov dword [lba_packet + LBAPkt_t.lower_lba], eax + + mov ax, [bp + 6] + mov word [lba_packet + LBAPkt_t.offset], ax + + mov ax, [bp + 4] + mov word [lba_packet + LBAPkt_t.segment], ax + + mov si, lba_packet + mov ah, 0x42 + mov dl, byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8] + int 0x13 + jnc read_disk_raw.endp + ERROR STAGE2_MBR_DISK_READ_ERROR +.endp: + __CDECL16_EXIT + ret + +; Sets output to 80x25 16 color text mode via BIOS call +; also clears screen +; void SetTextMode(void) +SetTextMode: +.prolog: + __CDECL16_ENTRY + pushf +.func: + xor ah, ah ; Set Video mode BIOS function + mov al, 0x02 ; 16 color 80x25 Text mode + int 0x10 ; Call video interrupt + + mov ah, 0x05 ; Select active display page BIOS function + xor al, al ; page 0 + int 0x10 ; call video interrupt +.endp: + popf + __CDECL16_EXIT + ret + +; disables blinking text mode cursor +disable_cursor: + __CDECL16_ENTRY +.func: + mov dx, 0x3D4 + mov al, 0xA ; low cursor shape register + out dx, al + + inc dx + mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape + out dx, al +.endp: + __CDECL16_EXIT + ret \ No newline at end of file diff --git a/include/fat32/fat32_func_old.inc b/include/fat32/fat32_func_old.inc new file mode 100644 index 0000000..581d3c0 --- /dev/null +++ b/include/fat32/fat32_func_old.inc @@ -0,0 +1,274 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +InitFATDriver: + __CDECL16_ENTRY +.func: + xor eax, eax + mov dword [fat32_state + FAT32_State_t.active_cluster_32], eax + mov dword [fat32_state + FAT32_State_t.active_FAT_cluster_32], eax + mov dword [fat32_state + FAT32_State_t.first_root_dir_sector_32], eax + mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax + +.calc_active_part: + mov ax, word [partition_offset] + mov bx, partition_table + add bx, ax ; bx points to the partition that was booted from + + mov eax, dword [bx + PartEntry_t.lba_start] + mov dword [fat32_state + FAT32_State_t.active_drive_lba_32], eax + +.calc_first_fat: + movzx eax, word [fat32_bpb + FAT32_bpb_t.reserved_sectors_16] ; first fat from start of partition + add eax, dword [fat32_state + FAT32_State_t.active_drive_lba_32] ; calculate offset from start of drive + + mov dword [fat32_state + FAT32_State_t.first_fat_sector_32], eax +.calc_total_fat: + mov ebx, dword [fat32_ebpb + FAT32_ebpb_t.sectors_per_fat_32] + movzx eax, byte [fat32_bpb + FAT32_bpb_t.fat_count_8] + mul ebx ; result in EDX:EAX, CF set on > 32bit return value + jc InitFATDriver.error ; as a catch for unhandled overflow, just error if value is greater than 32bits + + mov dword [fat32_state + FAT32_State_t.fat_size_32], eax +.calc_first_data: + mov edx, dword [fat32_state + FAT32_State_t.first_fat_sector_32] + add eax, edx + + mov dword [fat32_state + FAT32_State_t.first_data_sector_32], eax +.get_first_root_dir: + ; TODO + + jmp InitFATDriver.endp +.error: + ERROR STAGE2_FAT32_INIT_ERROR +.endp: + __CDECL16_EXIT + ret + +; TODO: needs validation +; load a file to the high memory buffer for the elf parser +; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory +; +; SFN is a 8.3 file name, all uppercase, and padded with spaces +; do not add a null byte to the end of the string +; eg. kernel.bin == "KERNEL BIN" +; +; returns first cluster of file if found +; halts/errors if file is not found +; uint32_t SearchFATDIR(uint8_t* SFN); +SearchFATDIR: + __CDECL16_ENTRY +.file_lookup: + .load_first_dir: + mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32] + mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax + + push dword eax ; cluster + lea ax, [dir_buffer] + push ax ; offset + xor ax, ax + push ax ; segment + call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) + add sp, 0x8 + + lea si, [dir_buffer] + jmp SearchFATDIR.empty_dir_entry + + .load_next_dir: + ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) + ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad + mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] + push dword eax + call NextCluster ; uint32_t NextCluster(uint32_t active_cluster); + add sp, 0x4 + + cmp eax, 0x0fff_fff7 + jb SearchFATDIR.load_next_dir_next_OK + ERROR STAGE2_FAT32_END_OF_CHAIN + + .load_next_dir_next_OK: + ; load 512 bytes of directory entries from data sector + mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32] + + push dword eax + lea ax, [dir_buffer] ; cluster + push ax ; offset + xor ax, ax + push ax ; segment + call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) + sub sp, 0x8 + + lea si, [dir_buffer] + .empty_dir_entry: + ; check for 0x0 in first byte, if true then there are no more files + ; if true we did not find the file, we should error here + cmp byte [si], 0 + jne SearchFATDIR.unused_dir_entry + ERROR STAGE2_FAT32_NO_FILE + + .unused_dir_entry: + ; check for 0xe5 and 0x05 in first byte, if true then this entry is unused, but it is not the last entry. + cmp byte [si], 0xe5 + je SearchFATDIR.next_entry + + cmp byte [si], 0x05 + je SearchFATDIR.next_entry + jmp SearchFATDIR.parse_dir + + .next_entry: + ; increment offset by 32 bytes to read the next entry in this set of dir entries + ; if we are at the end of the buffer, then load the next buffer + add si, 0x20 ; 32 bytes + + lea ax, [dir_buffer] + add ax, 0x1FF ; 512 - 1 bytes + cmp si, ax + jae SearchFATDIR.load_next_dir + jmp SearchFATDIR.empty_dir_entry + + .parse_dir: + .lfn_check: + ; check for ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID (0x0F) in offset 11 + ; TODO: going to skip LFN for now, since all valid volumes will have SFN's + cmp byte [si+11], 0x0F + je SearchFATDIR.next_entry + .sfn_file_name_check: + push si + push di + + mov cx, 0xA ; max of 11 filename length of 11 characters + ; si points to the start of the current directory entry + lea di, [BootTarget_str] ; current memory location (8.3 name is at offset 0) + repe cmpsb ; compare the strings + + pop di + pop si + jne SearchFATDIR.next_entry + + .sfn_entry_found: + mov ax, [si + FAT32_SFN_t.cluster_16_high] + shl eax, 16 + mov ax, [si + FAT32_SFN_t.cluster_16_low] + ; eax == first cluster of file +.endp: + __CDECL16_EXIT + ret + +; uint32_t NextCluster(uint32_t active_cluster); +; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) +; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad +NextCluster: + __CDECL16_ENTRY +.func: + mov dword edx, [bp + 4] + mov si, fat32_nc_data +.calc_offset: +; fat_offset = active_cluster * 4 + mov eax, 4 + mul edx + mov dword [si + FAT32_NextClusterData_t.fat_offset], eax + +.calc_fat_sector: +; fat_sector = first_fat_sector + (fat_offset / sector_size) +; entry_offset = fat_offset % sector_size + mov edx, 0xffff_0000 + and edx, eax + shr edx, 16 + + push si + mov si, fat32_bpb + mov cx, word [si + FAT32_bpb_t.bytes_per_sector_16] + pop si + + div cx ; DX:AX / cx = fat_sector - first_fat_sector in AX + ; DX = remainder (fat_offset mod sector_size) + + mov ecx, 0x0000_ffff + and edx, ecx + mov dword [si + FAT32_NextClusterData_t.entry_offset], edx + + push si + mov si, fat32_state + mov ecx, dword [si + FAT32_State_t.first_fat_sector_32] + pop si + + mov edx, 0x0000ffff + and eax, edx + add eax, ecx ; fat_sector + first_fat_sector + mov dword [si + FAT32_NextClusterData_t.fat_sector], eax +.load_fat_table: + ; load correct fat + push dword eax + + mov ax, fat_buffer + push ax + + xor ax, ax + push ax + ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) + call read_disk_raw ; read_disk_raw(0, fat_buffer, fat_sector) + add sp, 0x8 + +.read_cluster: +; next_cluster = fat_buffer[entry_offset] + mov ebx, dword [si + FAT32_NextClusterData_t.entry_offset] + mov si, fat_buffer + mov eax, dword [bx+si+0] +.endp: + __CDECL16_EXIT + ret + +; uint32_t ClusterToLBA(uint32_t cluster) +ClusterToLBA: + __CDECL16_ENTRY +.func: + mov dword eax, [bp + 4] + sub eax, 2 + movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8] + mul edx + add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32] + ; eax contains the LBA now +.endp: + __CDECL16_EXIT + ret + +; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) +ReadFATCluster: + __CDECL16_ENTRY +.func: + mov dword eax, [bp + 8] + push dword eax + call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster) + add sp, 0x4 ; eax == LBA + + + push dword eax ;uint32_t lba + + mov dx, [bp + 4] ; seg + push dx ; uint16_t buf_offset + + mov dx, [bp + 6] ; offset + push dx ; unit16_t segment + + call read_disk_raw ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) + add sp, 0x8 +.endp: + __CDECL16_EXIT + ret diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 87609ca..e061f9c 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -138,260 +138,7 @@ hcf: ; ; ############### -InitFATDriver: - __CDECL16_ENTRY -.func: - xor eax, eax - mov dword [fat32_state + FAT32_State_t.active_cluster_32], eax - mov dword [fat32_state + FAT32_State_t.active_FAT_cluster_32], eax - mov dword [fat32_state + FAT32_State_t.first_root_dir_sector_32], eax - mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax - -.calc_active_part: - mov ax, word [partition_offset] - mov bx, partition_table - add bx, ax ; bx points to the partition that was booted from - - mov eax, dword [bx + PartEntry_t.lba_start] - mov dword [fat32_state + FAT32_State_t.active_drive_lba_32], eax - -.calc_first_fat: - movzx eax, word [fat32_bpb + FAT32_bpb_t.reserved_sectors_16] ; first fat from start of partition - add eax, dword [fat32_state + FAT32_State_t.active_drive_lba_32] ; calculate offset from start of drive - - mov dword [fat32_state + FAT32_State_t.first_fat_sector_32], eax -.calc_total_fat: - mov ebx, dword [fat32_ebpb + FAT32_ebpb_t.sectors_per_fat_32] - movzx eax, byte [fat32_bpb + FAT32_bpb_t.fat_count_8] - mul ebx ; result in EDX:EAX, CF set on > 32bit return value - jc InitFATDriver.error ; as a catch for unhandled overflow, just error if value is greater than 32bits - - mov dword [fat32_state + FAT32_State_t.fat_size_32], eax -.calc_first_data: - mov edx, dword [fat32_state + FAT32_State_t.first_fat_sector_32] - add eax, edx - - mov dword [fat32_state + FAT32_State_t.first_data_sector_32], eax -.get_first_root_dir: - ; TODO - - jmp InitFATDriver.endp -.error: - ERROR STAGE2_FAT32_INIT_ERROR -.endp: - __CDECL16_EXIT - ret - -; TODO: needs validation -; load a file to the high memory buffer for the elf parser -; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory -; -; SFN is a 8.3 file name, all uppercase, and padded with spaces -; do not add a null byte to the end of the string -; eg. kernel.bin == "KERNEL BIN" -; -; returns first cluster of file if found -; halts/errors if file is not found -; uint32_t SearchFATDIR(uint8_t* SFN); -SearchFATDIR: - __CDECL16_ENTRY -.file_lookup: - .load_first_dir: - mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32] - mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax - - push dword eax ; cluster - lea ax, [dir_buffer] - push ax ; offset - xor ax, ax - push ax ; segment - call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) - add sp, 0x8 - - lea si, [dir_buffer] - jmp SearchFATDIR.empty_dir_entry - - .load_next_dir: - ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) - ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad - mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] - push dword eax - call NextCluster ; uint32_t NextCluster(uint32_t active_cluster); - add sp, 0x4 - - cmp eax, 0x0fff_fff7 - jb SearchFATDIR.load_next_dir_next_OK - ERROR STAGE2_FAT32_END_OF_CHAIN - - .load_next_dir_next_OK: - ; load 512 bytes of directory entries from data sector - mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32] - - push dword eax - lea ax, [dir_buffer] ; cluster - push ax ; offset - xor ax, ax - push ax ; segment - call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) - sub sp, 0x8 - - lea si, [dir_buffer] - .empty_dir_entry: - ; check for 0x0 in first byte, if true then there are no more files - ; if true we did not find the file, we should error here - cmp byte [si], 0 - jne SearchFATDIR.unused_dir_entry - ERROR STAGE2_FAT32_NO_FILE - - .unused_dir_entry: - ; check for 0xe5 and 0x05 in first byte, if true then this entry is unused, but it is not the last entry. - cmp byte [si], 0xe5 - je SearchFATDIR.next_entry - - cmp byte [si], 0x05 - je SearchFATDIR.next_entry - jmp SearchFATDIR.parse_dir - - .next_entry: - ; increment offset by 32 bytes to read the next entry in this set of dir entries - ; if we are at the end of the buffer, then load the next buffer - add si, 0x20 ; 32 bytes - - lea ax, [dir_buffer] - add ax, 0x1FF ; 512 - 1 bytes - cmp si, ax - jae SearchFATDIR.load_next_dir - jmp SearchFATDIR.empty_dir_entry - - .parse_dir: - .lfn_check: - ; check for ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID (0x0F) in offset 11 - ; TODO: going to skip LFN for now, since all valid volumes will have SFN's - cmp byte [si+11], 0x0F - je SearchFATDIR.next_entry - .sfn_file_name_check: - push si - push di - - mov cx, 0xA ; max of 11 filename length of 11 characters - ; si points to the start of the current directory entry - lea di, [BootTarget_str] ; current memory location (8.3 name is at offset 0) - repe cmpsb ; compare the strings - - pop di - pop si - jne SearchFATDIR.next_entry - - .sfn_entry_found: - mov ax, [si + FAT32_SFN_t.cluster_16_high] - shl eax, 16 - mov ax, [si + FAT32_SFN_t.cluster_16_low] - ; eax == first cluster of file -.endp: - __CDECL16_EXIT - ret - -; uint32_t NextCluster(uint32_t active_cluster); -; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) -; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad -NextCluster: - __CDECL16_ENTRY -.func: - mov dword edx, [bp + 4] - mov si, fat32_nc_data -.calc_offset: -; fat_offset = active_cluster * 4 - mov eax, 4 - mul edx - mov dword [si + FAT32_NextClusterData_t.fat_offset], eax - -.calc_fat_sector: -; fat_sector = first_fat_sector + (fat_offset / sector_size) -; entry_offset = fat_offset % sector_size - mov edx, 0xffff_0000 - and edx, eax - shr edx, 16 - - push si - mov si, fat32_bpb - mov cx, word [si + FAT32_bpb_t.bytes_per_sector_16] - pop si - - div cx ; DX:AX / cx = fat_sector - first_fat_sector in AX - ; DX = remainder (fat_offset mod sector_size) - - mov ecx, 0x0000_ffff - and edx, ecx - mov dword [si + FAT32_NextClusterData_t.entry_offset], edx - - push si - mov si, fat32_state - mov ecx, dword [si + FAT32_State_t.first_fat_sector_32] - pop si - - mov edx, 0x0000ffff - and eax, edx - add eax, ecx ; fat_sector + first_fat_sector - mov dword [si + FAT32_NextClusterData_t.fat_sector], eax -.load_fat_table: - ; load correct fat - push dword eax - - mov ax, fat_buffer - push ax - - xor ax, ax - push ax - ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) - call read_disk_raw ; read_disk_raw(0, fat_buffer, fat_sector) - add sp, 0x8 - -.read_cluster: -; next_cluster = fat_buffer[entry_offset] - mov ebx, dword [si + FAT32_NextClusterData_t.entry_offset] - mov si, fat_buffer - mov eax, dword [bx+si+0] -.endp: - __CDECL16_EXIT - ret - -; uint32_t ClusterToLBA(uint32_t cluster) -ClusterToLBA: - __CDECL16_ENTRY -.func: - mov dword eax, [bp + 4] - sub eax, 2 - movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8] - mul edx - add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32] - ; eax contains the LBA now -.endp: - __CDECL16_EXIT - ret - -; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) -ReadFATCluster: - __CDECL16_ENTRY -.func: - mov dword eax, [bp + 8] - push dword eax - call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster) - add sp, 0x4 ; eax == LBA - - - push dword eax ;uint32_t lba - - mov dx, [bp + 4] ; seg - push dx ; uint16_t buf_offset - - mov dx, [bp + 6] ; offset - push dx ; unit16_t segment - - call read_disk_raw ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) - add sp, 0x8 -.endp: - __CDECL16_EXIT - ret +%include 'fat32/fat32_func_old.inc' ; ############### ; @@ -399,59 +146,13 @@ ReadFATCluster: ; ; ############### +%include 'BIOS/BIOS_func.inc' -; Wrapper for AH=0x42 INT13h (Extended Read) +; ############################## ; -; BIOS call details -; AH = 42h -; DL = drive number -; DS:SI -> disk address packet +; SYSTEM CONFIGURATION FUNCTIONS ; -; Return: -; CF clear if successful -; AH = 00h -; CF set on error -; AH = error code -; disk address packet's block count field set to number of blocks -; successfully transferred -; -; -; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) -; TODO: this needs validation -read_disk_raw: - __CDECL16_ENTRY -.func: - mov ax, 0x10 - push ax ; len = 16 bytes - xor ax, ax - push ax ; val = 0 - mov ax, lba_packet - push ax ; dest = lba_packet address - - call kmemset ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); - add sp, 0x6 - - mov byte [lba_packet + LBAPkt_t.size], 0x10 - mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 - - mov dword eax, [bp + 8] - mov dword [lba_packet + LBAPkt_t.lower_lba], eax - - mov ax, [bp + 6] - mov word [lba_packet + LBAPkt_t.offset], ax - - mov ax, [bp + 4] - mov word [lba_packet + LBAPkt_t.segment], ax - - mov si, lba_packet - mov ah, 0x42 - mov dl, byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8] - int 0x13 - jnc read_disk_raw.endp - ERROR STAGE2_MBR_DISK_READ_ERROR -.endp: - __CDECL16_EXIT - ret +; ############################## ; Prints a C-Style string (null terminated) using BIOS vga teletype call ; void PrintString(char* buf) @@ -550,217 +251,12 @@ PrintDWORD: __CDECL16_EXIT ret -; Sets output to 80x25 16 color text mode via BIOS call -; also clears screen -; void SetTextMode(void) -SetTextMode: -.prolog: - __CDECL16_ENTRY - pushf -.func: - xor ah, ah ; Set Video mode BIOS function - mov al, 0x02 ; 16 color 80x25 Text mode - int 0x10 ; Call video interrupt - - mov ah, 0x05 ; Select active display page BIOS function - xor al, al ; page 0 - int 0x10 ; call video interrupt -.endp: - popf - __CDECL16_EXIT - ret - -; See memory.inc for a brief description of E820 mmap function -GetMemoryMap: - __CDECL16_ENTRY - push es ; save segment register -.func: - mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0 - - mov eax, 0xE820 ; select 0xE820 function - xor ebx, ebx ; Continuation value, 0 for the first call - - mov dx, (BIOSMemoryMap >> 4) - mov es, dx - xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap - - mov ecx, AddressRangeDescStruct_t_size - mov edx, 0x534D4150 ; 'SMAP' magic -.loop_L1: - int 0x15 - jc GetMemoryMap.error - cmp eax, 0x534D4150 - jne GetMemoryMap.no_smap_returned -.no_error: - inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] - - cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing - jb GetMemoryMap.nonstandard_e820 ; non-standard entry found - - cmp ebx, 0 - je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges - - add di, AddressRangeDescStruct_t_size ; increment di to next descriptor - mov edx, eax ; 'SMAP' to edx - mov eax, 0xE820 ; select E820 function - jmp GetMemoryMap.loop_L1 -.error: - ERROR STAGE2_MM_E820_MISC_ERR -.nonstandard_e820: - ERROR STAGE2_MM_E820_NONSTANDARD -.no_smap_returned: - ERROR STAGE2_MM_E820_NO_SMAP -.endp: - pop es - __CDECL16_EXIT - ret - ; ############################## ; ; SYSTEM CONFIGURATION FUNCTIONS ; ; ############################## -; disables blinking text mode cursor -disable_cursor: -.prolog: - __CDECL16_ENTRY - pushf -.func: - mov dx, 0x3D4 - mov al, 0xA ; low cursor shape register - out dx, al - - inc dx - mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape - out dx, al -.endp: - popf - __CDECL16_EXIT - ret - -; -;NT 0x15 Function 2400 - Disable A20 -;Returns: -; -; CF = clear if success -; AH = 0 -; CF = set on error -; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported) -; -;INT 0x15 Function 2401 - Enable A20 -;Returns: -; -; CF = clear if success -; AH = 0 -; CF = set on error -; AH = status (01=keyboard controller is in secure mode, 0x86=function not supported) -; -;INT 0x15 Function 2402 - A20 Status -; Returns: -; -; CF = clear if success -; AH = status (01: keyboard controller is in secure mode; 0x86: function not supported) -; AL = current state (00: disabled, 01: enabled) -; CX = set to 0xffff is keyboard controller is no ready in 0xc000 read attempts -; CF = set on error -; -;INT 0x15 Function 2403 - Query A20 support -;Returns: -; -;CF = clear if success -;AH = status (01: keyboard controller is in secure mode; 0x86: function not supported) -;BX = status. -; -;BX contains a bit pattern: -; -; Bit 0 - supported on keyboard controller -; Bit 1 - if supported on bit 1 of I/O port 0x92 -; Bits 2:14 - Reserved -; Bit 15 - 1 if additional data is available. -; -; I/O Port 0x92 infomation: -; -; Bit 0 - Setting to 1 causes a fast reset -; Bit 1 - 0: disable A20; 1: enable A20 -; Bit 2 - Manufacturer defined -; Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible -; Bits 4-5 - Manufacturer defined -; Bits 6-7 - 00: HDD activity LED off; any other value is "on" -EnableA20: - __CDECL16_ENTRY - push ds - push es - pushf ; save data and extra segment since we touch them and save flags -.a20_check: - cli - - xor ax, ax - mov es, ax - - not ax ; ax = 0xFFFF - mov ds, ax - - mov di, 0x0500 ; scratch location 1 - mov si, 0x0510 ; scratch location 2 - - mov al, byte [es:di] - push ax ; save whatever is at 0x0000:0500, physical location 0x0500 - - mov al, byte [ds:si] - push ax ; save whatever is at 0xFFFF:0510 [clarification: 0x100500 physical location (0x100500 - 1MB = 0x0500)] - - mov byte [es:di], 0x00 ; zero non-wraped location and write 0xFF to it after (ab)using wrapping - mov byte [ds:si], 0xFF ; if the non-wrapped location is 0xFF, then we wraped and A20 is disabled - - cmp byte [es:di], 0xFF - - pop ax - mov byte [ds:si], al ; restore original contents of scratch location 2 - - pop ax - mov byte [es:di], al ; restore original contents of scratch location 1 - - mov ax, 0 ; return 0 if es:di == ds:si (memory wraps) - je EnableA20.end_check - mov ax, 1 ; return 1 if es:di != ds:si (A20 is enabled) -.end_check: - sti - cmp ax, 1 - je EnableA20.endp ; A20 is already enabled - - mov ax, 0x2403 - int 0x15 - jc EnableA20.do_fallback_a20 ; carry = error...not supported? - cmp ah, 0 - ja EnableA20.do_fallback_a20 ; non-zero return = error as well - - mov al, bl - and al, 0000_0010b - cmp al, 0000_0010b - je EnableA20.do_fast_a20 ; if fast a20 is supported use it - - jmp EnableA20.do_bios_a20 ; else fall back to enabling via BIOS - -.do_fallback_a20: - ERROR STAGE2_A20_FAILED -.do_bios_a20: - mov ax, 0x2401 - int 0x15 - jmp EnableA20.a20_check -.do_fast_a20: - in al, 0x92 ; read from FAST A20 port - or al, 2 ; bit 0 is a fast reset, bit 1 is fast A20 - and al, 0xFE ; make sure bit 0 is 0 - out 0x92, al ; enable A20 - jmp EnableA20.a20_check -.endp: - popf - pop es - pop ds - __CDECL16_EXIT - ret - EnterUnrealMode: __CDECL16_ENTRY .func: From d6af15a7a673513857b6d12d9173b64288d22b5d Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 5 Oct 2024 12:16:31 -0400 Subject: [PATCH 063/147] typo fix --- include/fat32/fat32_func_old.inc | 1 - 1 file changed, 1 deletion(-) diff --git a/include/fat32/fat32_func_old.inc b/include/fat32/fat32_func_old.inc index 581d3c0..33175ed 100644 --- a/include/fat32/fat32_func_old.inc +++ b/include/fat32/fat32_func_old.inc @@ -63,7 +63,6 @@ InitFATDriver: ret ; TODO: needs validation -; load a file to the high memory buffer for the elf parser ; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory ; ; SFN is a 8.3 file name, all uppercase, and padded with spaces From 5440a1ae61cdba182494c53988efa21129b76b6f Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 5 Oct 2024 13:35:39 -0400 Subject: [PATCH 064/147] more modularization and updating date in MIT licence header --- include/BIOS/BIOS_sys.inc | 24 +++ include/BIOS/func/E820_memory_map.inc | 161 ++++++++++++++++++ .../{BIOS_func.inc => func/a20enable.inc} | 133 --------------- include/BIOS/func/ext_read.inc | 90 ++++++++++ include/BIOS/func/video.inc | 54 ++++++ include/config.inc | 2 +- include/entry.inc | 10 +- include/{errors.inc => error_codes.inc} | 36 +--- include/fat32/bpb.inc | 2 +- include/memory.inc | 99 +---------- include/partition_table.inc | 21 +-- include/util/error_func.inc | 50 ++++++ src/mbr/mbr.nasm | 2 +- src/stage2/stage2.nasm | 6 +- src/vbr/vbr.nasm | 2 +- 15 files changed, 395 insertions(+), 297 deletions(-) create mode 100644 include/BIOS/BIOS_sys.inc create mode 100644 include/BIOS/func/E820_memory_map.inc rename include/BIOS/{BIOS_func.inc => func/a20enable.inc} (55%) create mode 100644 include/BIOS/func/ext_read.inc create mode 100644 include/BIOS/func/video.inc rename include/{errors.inc => error_codes.inc} (80%) create mode 100644 include/util/error_func.inc diff --git a/include/BIOS/BIOS_sys.inc b/include/BIOS/BIOS_sys.inc new file mode 100644 index 0000000..c453986 --- /dev/null +++ b/include/BIOS/BIOS_sys.inc @@ -0,0 +1,24 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +%include 'BIOS/func/a20enable.inc' +%include 'BIOS/func/E820_memory_map.inc' +%include 'BIOS/func/ext_read.inc' +%include 'BIOS/func/video.inc' \ No newline at end of file diff --git a/include/BIOS/func/E820_memory_map.inc b/include/BIOS/func/E820_memory_map.inc new file mode 100644 index 0000000..9cd9231 --- /dev/null +++ b/include/BIOS/func/E820_memory_map.inc @@ -0,0 +1,161 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + + +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; Input: +; +; EAX Function Code E820h +; EBX Continuation Contains the "continuation value" to get the +; next run of physical memory. This is the +; value returned by a previous call to this +; routine. If this is the first call, EBX +; must contain zero. +; ES:DI Buffer Pointer Pointer to an Address Range Descriptor +; structure which the BIOS is to fill in. +; ECX Buffer Size The length in bytes of the structure passed +; to the BIOS. The BIOS will fill in at most +; ECX bytes of the structure or however much +; of the structure the BIOS implements. The +; minimum size which must be supported by both +; the BIOS and the caller is 20 bytes. Future +; implementations may extend this structure. +; EDX Signature 'SMAP' - Used by the BIOS to verify the +; caller is requesting the system map +; information to be returned in ES:DI. +; +; Output: +; +; CF Carry Flag Non-Carry - indicates no error +; EAX Signature 'SMAP' - Signature to verify correct BIOS +; revision. +; ES:DI Buffer Pointer Returned Address Range Descriptor pointer. +; Same value as on input. +; ECX Buffer Size Number of bytes returned by the BIOS in the +; address range descriptor. The minimum size +; structure returned by the BIOS is 20 bytes. +; EBX Continuation Contains the continuation value to get the +; next address descriptor. The actual +; significance of the continuation value is up +; to the discretion of the BIOS. The caller +; must pass the continuation value unchanged +; as input to the next iteration of the E820 +; call in order to get the next Address Range +; Descriptor. A return value of zero means that +; this is the last descriptor +; +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; +; The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. +; The BaseAddress is the physical address of the start of the range being specified. +; +; The LengthLow and LengthHigh together are the 64 bit Length of this range. +; The Length is the physical contiguous length in bytes of a range being specified. +; +; The Type field describes the usage of the described address range as defined in the table below. + +; Value Pneumonic Description +; 1 AddressRangeMemory This run is available RAM usable by the operating system. +; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. +; Other Undefined Undefined - Reserved for future use. + +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow u32 - Low 32 Bits of Base Address +; 4 BaseAddrHigh u32 - High 32 Bits of Base Address +; 8 LengthLow u32 - Low 32 Bits of Length in Bytes +; 12 LengthHigh u32 - High 32 Bits of Length in Bytes +; 16 Type u32 - Address type of this range. +; 20 ExtType u32 - ACPI 3.0 extended type +struc AddressRangeDescStruct_t + .BaseAddrLow resd 1 + .BaseAddrHigh resd 1 + .LengthLow resd 1 + .LengthHigh resd 1 + .Type resd 1 + .ExtType resd 1 +endstruc + +GetMemoryMap: + __CDECL16_ENTRY + push es ; save segment register +.func: + mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0 + + mov eax, 0xE820 ; select 0xE820 function + xor ebx, ebx ; Continuation value, 0 for the first call + + mov dx, (BIOSMemoryMap >> 4) + mov es, dx + xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap + + mov ecx, AddressRangeDescStruct_t_size + mov edx, 0x534D4150 ; 'SMAP' magic +.loop_L1: + int 0x15 + jc GetMemoryMap.error + cmp eax, 0x534D4150 + jne GetMemoryMap.no_smap_returned +.no_error: + inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] + + cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing + jb GetMemoryMap.nonstandard_e820 ; non-standard entry found + + cmp ebx, 0 + je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges + + add di, AddressRangeDescStruct_t_size ; increment di to next descriptor + mov edx, eax ; 'SMAP' to edx + mov eax, 0xE820 ; select E820 function + jmp GetMemoryMap.loop_L1 +.error: + ERROR STAGE2_MM_E820_MISC_ERR +.nonstandard_e820: + ERROR STAGE2_MM_E820_NONSTANDARD +.no_smap_returned: + ERROR STAGE2_MM_E820_NO_SMAP +.endp: + pop es + __CDECL16_EXIT + ret \ No newline at end of file diff --git a/include/BIOS/BIOS_func.inc b/include/BIOS/func/a20enable.inc similarity index 55% rename from include/BIOS/BIOS_func.inc rename to include/BIOS/func/a20enable.inc index 64050de..0b18bf5 100644 --- a/include/BIOS/BIOS_func.inc +++ b/include/BIOS/func/a20enable.inc @@ -135,138 +135,5 @@ EnableA20: .endp: pop es pop ds - __CDECL16_EXIT - ret - -; See memory.inc for a brief description of E820 mmap function -GetMemoryMap: - __CDECL16_ENTRY - push es ; save segment register -.func: - mov dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries], 0 - - mov eax, 0xE820 ; select 0xE820 function - xor ebx, ebx ; Continuation value, 0 for the first call - - mov dx, (BIOSMemoryMap >> 4) - mov es, dx - xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap - - mov ecx, AddressRangeDescStruct_t_size - mov edx, 0x534D4150 ; 'SMAP' magic -.loop_L1: - int 0x15 - jc GetMemoryMap.error - cmp eax, 0x534D4150 - jne GetMemoryMap.no_smap_returned -.no_error: - inc dword [SteviaInfo + SteviaInfoStruct_t.MemoryMapEntries] - - cmp ecx, 20 ; TODO: maybe this could be handled better than just panicing - jb GetMemoryMap.nonstandard_e820 ; non-standard entry found - - cmp ebx, 0 - je GetMemoryMap.endp ; 0 in ebx means we have reached the end of memory ranges - - add di, AddressRangeDescStruct_t_size ; increment di to next descriptor - mov edx, eax ; 'SMAP' to edx - mov eax, 0xE820 ; select E820 function - jmp GetMemoryMap.loop_L1 -.error: - ERROR STAGE2_MM_E820_MISC_ERR -.nonstandard_e820: - ERROR STAGE2_MM_E820_NONSTANDARD -.no_smap_returned: - ERROR STAGE2_MM_E820_NO_SMAP -.endp: - pop es - __CDECL16_EXIT - ret - -; Wrapper for AH=0x42 INT13h (Extended Read) -; -; BIOS call details -; AH = 42h -; DL = drive number -; DS:SI -> disk address packet -; -; Return: -; CF clear if successful -; AH = 00h -; CF set on error -; AH = error code -; disk address packet's block count field set to number of blocks -; successfully transferred -; -; -; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) -; TODO: this needs validation -read_disk_raw: - __CDECL16_ENTRY -.func: - mov ax, 0x10 - push ax ; len = 16 bytes - xor ax, ax - push ax ; val = 0 - mov ax, lba_packet - push ax ; dest = lba_packet address - - call kmemset ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); - add sp, 0x6 - - mov byte [lba_packet + LBAPkt_t.size], 0x10 - mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 - - mov dword eax, [bp + 8] - mov dword [lba_packet + LBAPkt_t.lower_lba], eax - - mov ax, [bp + 6] - mov word [lba_packet + LBAPkt_t.offset], ax - - mov ax, [bp + 4] - mov word [lba_packet + LBAPkt_t.segment], ax - - mov si, lba_packet - mov ah, 0x42 - mov dl, byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8] - int 0x13 - jnc read_disk_raw.endp - ERROR STAGE2_MBR_DISK_READ_ERROR -.endp: - __CDECL16_EXIT - ret - -; Sets output to 80x25 16 color text mode via BIOS call -; also clears screen -; void SetTextMode(void) -SetTextMode: -.prolog: - __CDECL16_ENTRY - pushf -.func: - xor ah, ah ; Set Video mode BIOS function - mov al, 0x02 ; 16 color 80x25 Text mode - int 0x10 ; Call video interrupt - - mov ah, 0x05 ; Select active display page BIOS function - xor al, al ; page 0 - int 0x10 ; call video interrupt -.endp: - popf - __CDECL16_EXIT - ret - -; disables blinking text mode cursor -disable_cursor: - __CDECL16_ENTRY -.func: - mov dx, 0x3D4 - mov al, 0xA ; low cursor shape register - out dx, al - - inc dx - mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape - out dx, al -.endp: __CDECL16_EXIT ret \ No newline at end of file diff --git a/include/BIOS/func/ext_read.inc b/include/BIOS/func/ext_read.inc new file mode 100644 index 0000000..6e137ce --- /dev/null +++ b/include/BIOS/func/ext_read.inc @@ -0,0 +1,90 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +;Offset Size Description +; 0 1 size of packet (16 bytes) +; 1 1 always 0 +; 2 2 number of sectors to transfer (max 127 on some BIOSes) +; 4 4 transfer buffer (0xFFFF:0xFFFF) +; 8 4 lower 32-bits of starting 48-bit LBA +; 12 4 upper 32-bits of starting 48-bit LBA +; needs to be aligned to a uint32_t +struc LBAPkt_t + .size resb 1 + .res0 resb 1 + .xfer_size resw 1 + .offset resw 1 + .segment resw 1 + .lower_lba resd 1 + .upper_lba resd 1 +endstruc + +; Wrapper for AH=0x42 INT13h (Extended Read) +; +; BIOS call details +; AH = 42h +; DL = drive number +; DS:SI -> disk address packet +; +; Return: +; CF clear if successful +; AH = 00h +; CF set on error +; AH = error code +; disk address packet's block count field set to number of blocks +; successfully transferred +; +; +; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) +; TODO: this needs validation +read_disk_raw: + __CDECL16_ENTRY +.func: + mov ax, 0x10 + push ax ; len = 16 bytes + xor ax, ax + push ax ; val = 0 + mov ax, lba_packet + push ax ; dest = lba_packet address + + call kmemset ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); + add sp, 0x6 + + mov byte [lba_packet + LBAPkt_t.size], 0x10 + mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 + + mov dword eax, [bp + 8] + mov dword [lba_packet + LBAPkt_t.lower_lba], eax + + mov ax, [bp + 6] + mov word [lba_packet + LBAPkt_t.offset], ax + + mov ax, [bp + 4] + mov word [lba_packet + LBAPkt_t.segment], ax + + mov si, lba_packet + mov ah, 0x42 + mov dl, byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8] + int 0x13 + jnc read_disk_raw.endp + ERROR STAGE2_MBR_DISK_READ_ERROR +.endp: + __CDECL16_EXIT + ret \ No newline at end of file diff --git a/include/BIOS/func/video.inc b/include/BIOS/func/video.inc new file mode 100644 index 0000000..5a5e78e --- /dev/null +++ b/include/BIOS/func/video.inc @@ -0,0 +1,54 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +; Sets output to 80x25 16 color text mode via BIOS call +; also clears screen +; void SetTextMode(void) +SetTextMode: +.prolog: + __CDECL16_ENTRY + pushf +.func: + xor ah, ah ; Set Video mode BIOS function + mov al, 0x02 ; 16 color 80x25 Text mode + int 0x10 ; Call video interrupt + + mov ah, 0x05 ; Select active display page BIOS function + xor al, al ; page 0 + int 0x10 ; call video interrupt +.endp: + popf + __CDECL16_EXIT + ret + +; disables blinking text mode cursor +disable_cursor: + __CDECL16_ENTRY +.func: + mov dx, 0x3D4 + mov al, 0xA ; low cursor shape register + out dx, al + + inc dx + mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape + out dx, al +.endp: + __CDECL16_EXIT + ret \ No newline at end of file diff --git a/include/config.inc b/include/config.inc index 20e2430..3a780f6 100755 --- a/include/config.inc +++ b/include/config.inc @@ -1,4 +1,4 @@ -; Copyright (c) 2023 Elaina Claus +; Copyright (c) 2024 Elaina Claus ; ; Permission is hereby granted, free of charge, to any person obtaining a copy ; of this software and associated documentation files (the "Software"), to deal diff --git a/include/entry.inc b/include/entry.inc index f9f566e..f295305 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -1,4 +1,4 @@ -; Copyright (c) 2023 Elaina Claus +; Copyright (c) 2024 Elaina Claus ; ; Permission is hereby granted, free of charge, to any person obtaining a copy ; of this software and associated documentation files (the "Software"), to deal @@ -20,7 +20,7 @@ ; 8KiB from 0x2500 -> 0x500 -%define STACK_START 0x2500 -%define MBR_ENTRY 0x7A00 -%define VBR_ENTRY 0x7C00 -%define STAGE2_ENTRY 0x7E00 \ No newline at end of file +%define EARLY_STACK_START 0x2500 +%define MBR_ENTRY 0x7A00 +%define VBR_ENTRY 0x7C00 +%define STAGE2_ENTRY 0x7E00 \ No newline at end of file diff --git a/include/errors.inc b/include/error_codes.inc similarity index 80% rename from include/errors.inc rename to include/error_codes.inc index 82da97d..bc1999c 100755 --- a/include/errors.inc +++ b/include/error_codes.inc @@ -1,4 +1,4 @@ -; Copyright (c) 2023 Elaina Claus +; Copyright (c) 2024 Elaina Claus ; ; Permission is hereby granted, free of charge, to any person obtaining a copy ; of this software and associated documentation files (the "Software"), to deal @@ -76,36 +76,4 @@ %define STEVIA_DEBUG_OK 'W' %define STEVIA_DEBUG_ERR 'X' %define STEVIA_DEBUG_UNIMPLEMENTED 'Y' -%define STEVIA_DEBUG_HALT 'Z' - - -%macro ERROR 1 - xor ax, ax - mov al, %1 - jmp error -%endmacro - -; pass error as ascii character in al, errors a-zA-Z or 0-9 -error: - ; fs = 0xb800 => fs:0x0000 = 0xb8000 - mov dx, 0xB800 - mov fs, dx - - mov dx, STEVIA_DEBUG_OK - cmp ax, dx - jge error.debug_err - mov dh, 0x4F ; color 0x4F is white text/red background - jmp error.print -.debug_err: - mov dh, 0x5F ; debug case is white text/purple background - - ; the characters are two bytes in the order of 0xb8000: byte c, byte attribute - ; since x86 is le, we store the attribute in the MSB of dx -.print: - mov dl, al - mov word [fs:0x0000], dx - jmp error.stop - -.stop: - hlt - jmp short error.stop \ No newline at end of file +%define STEVIA_DEBUG_HALT 'Z' \ No newline at end of file diff --git a/include/fat32/bpb.inc b/include/fat32/bpb.inc index e6ce621..8200b34 100755 --- a/include/fat32/bpb.inc +++ b/include/fat32/bpb.inc @@ -1,4 +1,4 @@ -; Copyright (c) 2023 Elaina Claus +; Copyright (c) 2024 Elaina Claus ; ; Permission is hereby granted, free of charge, to any person obtaining a copy ; of this software and associated documentation files (the "Software"), to deal diff --git a/include/memory.inc b/include/memory.inc index 7f0e15b..68e1305 100755 --- a/include/memory.inc +++ b/include/memory.inc @@ -1,4 +1,4 @@ -; Copyright (c) 2023 Elaina Claus +; Copyright (c) 2024 Elaina Claus ; ; Permission is hereby granted, free of charge, to any person obtaining a copy ; of this software and associated documentation files (the "Software"), to deal @@ -110,103 +110,6 @@ struc SteviaInfoStruct_t .EBPBDataPtr resd 1 endstruc -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; Input: -; -; EAX Function Code E820h -; EBX Continuation Contains the "continuation value" to get the -; next run of physical memory. This is the -; value returned by a previous call to this -; routine. If this is the first call, EBX -; must contain zero. -; ES:DI Buffer Pointer Pointer to an Address Range Descriptor -; structure which the BIOS is to fill in. -; ECX Buffer Size The length in bytes of the structure passed -; to the BIOS. The BIOS will fill in at most -; ECX bytes of the structure or however much -; of the structure the BIOS implements. The -; minimum size which must be supported by both -; the BIOS and the caller is 20 bytes. Future -; implementations may extend this structure. -; EDX Signature 'SMAP' - Used by the BIOS to verify the -; caller is requesting the system map -; information to be returned in ES:DI. -; -; Output: -; -; CF Carry Flag Non-Carry - indicates no error -; EAX Signature 'SMAP' - Signature to verify correct BIOS -; revision. -; ES:DI Buffer Pointer Returned Address Range Descriptor pointer. -; Same value as on input. -; ECX Buffer Size Number of bytes returned by the BIOS in the -; address range descriptor. The minimum size -; structure returned by the BIOS is 20 bytes. -; EBX Continuation Contains the continuation value to get the -; next address descriptor. The actual -; significance of the continuation value is up -; to the discretion of the BIOS. The caller -; must pass the continuation value unchanged -; as input to the next iteration of the E820 -; call in order to get the next Address Range -; Descriptor. A return value of zero means that -; this is the last descriptor -; -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; -; The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. -; The BaseAddress is the physical address of the start of the range being specified. -; -; The LengthLow and LengthHigh together are the 64 bit Length of this range. -; The Length is the physical contiguous length in bytes of a range being specified. -; -; The Type field describes the usage of the described address range as defined in the table below. - -; Value Pneumonic Description -; 1 AddressRangeMemory This run is available RAM usable by the operating system. -; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. -; Other Undefined Undefined - Reserved for future use. - -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow u32 - Low 32 Bits of Base Address -; 4 BaseAddrHigh u32 - High 32 Bits of Base Address -; 8 LengthLow u32 - Low 32 Bits of Length in Bytes -; 12 LengthHigh u32 - High 32 Bits of Length in Bytes -; 16 Type u32 - Address type of this range. -; 20 ExtType u32 - ACPI 3.0 extended type -struc AddressRangeDescStruct_t - .BaseAddrLow resd 1 - .BaseAddrHigh resd 1 - .LengthLow resd 1 - .LengthHigh resd 1 - .Type resd 1 - .ExtType resd 1 -endstruc - %macro DEBUG_HCF 0 DEBUG_LOOP: hlt diff --git a/include/partition_table.inc b/include/partition_table.inc index 5fc7a20..7f149fa 100755 --- a/include/partition_table.inc +++ b/include/partition_table.inc @@ -1,4 +1,4 @@ -; Copyright (c) 2023 Elaina Claus +; Copyright (c) 2024 Elaina Claus ; ; Permission is hereby granted, free of charge, to any person obtaining a copy ; of this software and associated documentation files (the "Software"), to deal @@ -41,23 +41,4 @@ struc PartTable_t .partition2 resb 16 .partition3 resb 16 .partition4 resb 16 -endstruc - - -;Offset Size Description -; 0 1 size of packet (16 bytes) -; 1 1 always 0 -; 2 2 number of sectors to transfer (max 127 on some BIOSes) -; 4 4 transfer buffer (0xFFFF:0xFFFF) -; 8 4 lower 32-bits of starting 48-bit LBA -; 12 4 upper 32-bits of starting 48-bit LBA -; needs to be aligned to a uint32_t -struc LBAPkt_t - .size resb 1 - .res0 resb 1 - .xfer_size resw 1 - .offset resw 1 - .segment resw 1 - .lower_lba resd 1 - .upper_lba resd 1 endstruc \ No newline at end of file diff --git a/include/util/error_func.inc b/include/util/error_func.inc new file mode 100644 index 0000000..cbd238a --- /dev/null +++ b/include/util/error_func.inc @@ -0,0 +1,50 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +%macro ERROR 1 + xor ax, ax + mov al, %1 + jmp error +%endmacro + +; pass error as ascii character in al, errors a-zA-Z or 0-9 +error: + ; fs = 0xb800 => fs:0x0000 = 0xb8000 + mov dx, 0xB800 + mov fs, dx + + mov dx, STEVIA_DEBUG_OK + cmp ax, dx + jge error.debug_err + mov dh, 0x4F ; color 0x4F is white text/red background + jmp error.print +.debug_err: + mov dh, 0x5F ; debug case is white text/purple background + + ; the characters are two bytes in the order of 0xb8000: byte c, byte attribute + ; since x86 is le, we store the attribute in the MSB of dx +.print: + mov dl, al + mov word [fs:0x0000], dx + jmp error.stop + +.stop: + hlt + jmp short error.stop \ No newline at end of file diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 1d14927..f65a202 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -33,7 +33,7 @@ init: mov es, ax ; * mov ss, ax ; Set Stack Segment to 0 - mov sp, STACK_START + mov sp, EARLY_STACK_START mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index e061f9c..5fad4a8 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -38,7 +38,7 @@ init: mov gs, ax ; * mov ss, ax ; Set Stack Segment to 0 - mov sp, STACK_START ; Set Stack Pointer + mov sp, EARLY_STACK_START ; Set Stack Pointer add sp, 0x4 mov ax, 0xDEAD @@ -52,7 +52,7 @@ init: jmp 0:main %include "config.inc" -%include "errors.inc" +%include "error_codes.inc" %include "memory.inc" %include "kmem_func.inc" %include "partition_table.inc" @@ -146,7 +146,7 @@ hcf: ; ; ############### -%include 'BIOS/BIOS_func.inc' +%include 'BIOS/BIOS_sys.inc' ; ############################## ; diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index ebb8b71..37759ca 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -40,7 +40,7 @@ init: mov es, ax ; * mov ss, ax ; Set Stack Segment to 0 - mov sp, STACK_START ; Setup stack + mov sp, EARLY_STACK_START ; Setup stack mov bp, sp ; base ptr = stack ptr mov bx, VBR_ENTRY ; move Bx to the new start of the initial boot sector From 8f95c8f26709585f24ca19373a07bb0d12f1eb28 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 5 Oct 2024 18:55:00 -0400 Subject: [PATCH 065/147] tons more work on modularizing the code --- bochsrc.bxrc | 2 +- include/BIOS/func/E820_memory_map.inc | 7 +- include/BIOS/func/a20enable.inc | 7 +- include/BIOS/func/ext_read.inc | 44 +++-- include/BIOS/func/video.inc | 8 +- include/cdecl16.inc | 3 +- include/config.inc | 6 +- include/entry.inc | 6 +- include/error_codes.inc | 6 +- include/fat32/{bpb.inc => bpb_offset_bx.inc} | 6 +- include/fat32/fat32_structures.inc | 4 +- .../{fat32_func_old.inc => fat32_sys.inc} | 76 ++++++-- include/kmem_func.inc | 13 +- include/{memory.inc => mem.inc} | 21 +- include/partition_table.inc | 7 +- include/util/error_func.inc | 15 +- src/mbr/mbr.nasm | 179 +++++++----------- src/stage2/stage2.nasm | 73 ++++--- src/vbr/vbr.nasm | 173 +++++++---------- 19 files changed, 360 insertions(+), 296 deletions(-) rename include/fat32/{bpb.inc => bpb_offset_bx.inc} (98%) rename include/fat32/{fat32_func_old.inc => fat32_sys.inc} (82%) rename include/{memory.inc => mem.inc} (93%) diff --git a/bochsrc.bxrc b/bochsrc.bxrc index 6de97b7..34c323d 100644 --- a/bochsrc.bxrc +++ b/bochsrc.bxrc @@ -10,7 +10,7 @@ floppy_bootsig_check: disabled=0 floppya: type=1_44 # no floppyb ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 -ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=auto +ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=lba ata0-slave: type=none ata1: type=none ata1-master: type=none diff --git a/include/BIOS/func/E820_memory_map.inc b/include/BIOS/func/E820_memory_map.inc index 9cd9231..3447a47 100644 --- a/include/BIOS/func/E820_memory_map.inc +++ b/include/BIOS/func/E820_memory_map.inc @@ -18,6 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_E820MEMORY_MAP ; Address Range Descriptor Structure ; @@ -116,6 +117,7 @@ struc AddressRangeDescStruct_t .ExtType resd 1 endstruc +ALIGN 4, db 0x90 GetMemoryMap: __CDECL16_ENTRY push es ; save segment register @@ -158,4 +160,7 @@ GetMemoryMap: .endp: pop es __CDECL16_EXIT - ret \ No newline at end of file + ret + +%endif +%define __INC_E820MEMORY_MAP \ No newline at end of file diff --git a/include/BIOS/func/a20enable.inc b/include/BIOS/func/a20enable.inc index 0b18bf5..cde9a18 100644 --- a/include/BIOS/func/a20enable.inc +++ b/include/BIOS/func/a20enable.inc @@ -18,6 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_A20ENABLE ; ;INT 0x15 Function 2400 - Disable A20 ;Returns: @@ -66,6 +67,7 @@ ; Bit 3 - power on password bytes (CMOS bytes 0x38-0x3f or 0x36-0x3f). 0: accessible, 1: inaccessible ; Bits 4-5 - Manufacturer defined ; Bits 6-7 - 00: HDD activity LED off; any other value is "on" +ALIGN 4, db 0x90 EnableA20: __CDECL16_ENTRY push ds @@ -136,4 +138,7 @@ EnableA20: pop es pop ds __CDECL16_EXIT - ret \ No newline at end of file + ret + +%endif +%define __INC_A20ENABLE \ No newline at end of file diff --git a/include/BIOS/func/ext_read.inc b/include/BIOS/func/ext_read.inc index 6e137ce..a107c94 100644 --- a/include/BIOS/func/ext_read.inc +++ b/include/BIOS/func/ext_read.inc @@ -18,6 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_EXT_READ ;Offset Size Description ; 0 1 size of packet (16 bytes) ; 1 1 always 0 @@ -52,25 +53,28 @@ endstruc ; successfully transferred ; ; -; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) -; TODO: this needs validation +; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, +; uint32_t lba, +; uint16_t count, uint16_t drive_num) +ALIGN 4, db 0x90 read_disk_raw: __CDECL16_ENTRY -.func: +.func: mov ax, 0x10 push ax ; len = 16 bytes xor ax, ax push ax ; val = 0 mov ax, lba_packet push ax ; dest = lba_packet address - - call kmemset ; uint8_t* kmemset(void* dest, uint8_t val, size_t len); - add sp, 0x6 + call kmemset + add sp, 0x06 mov byte [lba_packet + LBAPkt_t.size], 0x10 - mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 - mov dword eax, [bp + 8] + mov ax, [bp + 12] + mov word [lba_packet + LBAPkt_t.xfer_size], ax + + mov eax, [bp + 8] mov dword [lba_packet + LBAPkt_t.lower_lba], eax mov ax, [bp + 6] @@ -81,10 +85,26 @@ read_disk_raw: mov si, lba_packet mov ah, 0x42 - mov dl, byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8] + + ;BUG: still working on getting this passed down correctly, going to hard set it for now. + movzx dx, byte [bp + 14] + and dx, 0x00ff + ;xor dl, dl + ;mov dl, 0x80 + int 0x13 - jnc read_disk_raw.endp + jnc .endf + + %ifdef __STEVIA_MBR + ERROR MBR_ERROR_DISK_READ_ERR + %elifsef __STEVIA_VBR + ERROR VBR_ERROR_DISK_READ_ERR + %else ERROR STAGE2_MBR_DISK_READ_ERROR -.endp: + %endif +.endf: __CDECL16_EXIT - ret \ No newline at end of file + ret + +%endif +%define __INC_EXT_READ \ No newline at end of file diff --git a/include/BIOS/func/video.inc b/include/BIOS/func/video.inc index 5a5e78e..33b0a6e 100644 --- a/include/BIOS/func/video.inc +++ b/include/BIOS/func/video.inc @@ -18,9 +18,11 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_VIDEO ; Sets output to 80x25 16 color text mode via BIOS call ; also clears screen ; void SetTextMode(void) +ALIGN 4, db 0x90 SetTextMode: .prolog: __CDECL16_ENTRY @@ -39,6 +41,7 @@ SetTextMode: ret ; disables blinking text mode cursor +ALIGN 4, db 0x90 disable_cursor: __CDECL16_ENTRY .func: @@ -51,4 +54,7 @@ disable_cursor: out dx, al .endp: __CDECL16_EXIT - ret \ No newline at end of file + ret + +%endif +%define __INC_VIDEO \ No newline at end of file diff --git a/include/cdecl16.inc b/include/cdecl16.inc index b039985..13bdc50 100644 --- a/include/cdecl16.inc +++ b/include/cdecl16.inc @@ -21,6 +21,7 @@ %macro __CDECL16_ENTRY 0 push bp mov bp, sp + sub sp, 0x20 push si push di @@ -37,4 +38,4 @@ mov sp, bp pop bp %endmacro -%endif +%endif \ No newline at end of file diff --git a/include/config.inc b/include/config.inc index 3a780f6..db74252 100755 --- a/include/config.inc +++ b/include/config.inc @@ -18,8 +18,12 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_STEVIA_CONFIG %define SECTOR_SIZE 512 %define STAGE2_SECTOR_COUNT 0x40 ; 32 KiB -%define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT) \ No newline at end of file +%define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT) + +%endif +%define __INC_STEVIA_CONFIG \ No newline at end of file diff --git a/include/entry.inc b/include/entry.inc index f295305..fa5e710 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -18,9 +18,13 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_ENTRY ; 8KiB from 0x2500 -> 0x500 %define EARLY_STACK_START 0x2500 %define MBR_ENTRY 0x7A00 %define VBR_ENTRY 0x7C00 -%define STAGE2_ENTRY 0x7E00 \ No newline at end of file +%define STAGE2_ENTRY 0x7E00 + +%endif +%define __INC_ENTRY \ No newline at end of file diff --git a/include/error_codes.inc b/include/error_codes.inc index bc1999c..d1eb182 100755 --- a/include/error_codes.inc +++ b/include/error_codes.inc @@ -18,6 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_ERROR_CODES ; Errors ; 12 Errors, 5 in use @@ -76,4 +77,7 @@ %define STEVIA_DEBUG_OK 'W' %define STEVIA_DEBUG_ERR 'X' %define STEVIA_DEBUG_UNIMPLEMENTED 'Y' -%define STEVIA_DEBUG_HALT 'Z' \ No newline at end of file +%define STEVIA_DEBUG_HALT 'Z' + +%endif +%define __INC_ERROR_CODES \ No newline at end of file diff --git a/include/fat32/bpb.inc b/include/fat32/bpb_offset_bx.inc similarity index 98% rename from include/fat32/bpb.inc rename to include/fat32/bpb_offset_bx.inc index 8200b34..e807556 100755 --- a/include/fat32/bpb.inc +++ b/include/fat32/bpb_offset_bx.inc @@ -18,6 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_BPD_OFFSET_BX ; BPB Information ; Off. Hex Off. Size Description @@ -88,4 +89,7 @@ %define bsVolumeSerial bx+0x43 %define bsVolumeLabel bx+0x47 %define bsSystemIdent bx+0x52 -;-- End EBPB \ No newline at end of file +;-- End EBPB + +%endif +%define __INC_BPD_OFFSET_BX \ No newline at end of file diff --git a/include/fat32/fat32_structures.inc b/include/fat32/fat32_structures.inc index 959b0e5..0bba2a5 100755 --- a/include/fat32/fat32_structures.inc +++ b/include/fat32/fat32_structures.inc @@ -18,6 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_FAT32_STRUCT ; ## FAT32 Info ## ; total_sectors = bsSectorsHuge @@ -230,4 +231,5 @@ endstruc ; LFN == RO | HIDDEN | SYSTEM | VOLID == 0x0F %define FAT32_ATTR_LFN 0x0F - +%endif +%define __INC_FAT32_STRUCT \ No newline at end of file diff --git a/include/fat32/fat32_func_old.inc b/include/fat32/fat32_sys.inc similarity index 82% rename from include/fat32/fat32_func_old.inc rename to include/fat32/fat32_sys.inc index 33175ed..3de49ab 100644 --- a/include/fat32/fat32_func_old.inc +++ b/include/fat32/fat32_sys.inc @@ -18,6 +18,13 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_FAT32_SYS + +%include "partition_table.inc" +%include "fat32/bpb_offset_bx.inc" +%include "fat32/fat32_structures.inc" + +ALIGN 4, db 0x90 InitFATDriver: __CDECL16_ENTRY .func: @@ -28,9 +35,14 @@ InitFATDriver: mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax .calc_active_part: - mov ax, word [partition_offset] - mov bx, partition_table - add bx, ax ; bx points to the partition that was booted from + mov bx, [partition_offset_ptr] + mov ax, [bx + 0] + mov bx, ax + mov ax, [bx + 0] + + mov dx, partition_table + add dx, ax ; dx points to the partition that was booted from + mov bx, dx ; set bx, should point at our partition mov eax, dword [bx + PartEntry_t.lba_start] mov dword [fat32_state + FAT32_State_t.active_drive_lba_32], eax @@ -72,6 +84,7 @@ InitFATDriver: ; returns first cluster of file if found ; halts/errors if file is not found ; uint32_t SearchFATDIR(uint8_t* SFN); +ALIGN 4, db 0x90 SearchFATDIR: __CDECL16_ENTRY .file_lookup: @@ -173,9 +186,16 @@ SearchFATDIR: ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad +ALIGN 4, db 0x90 NextCluster: __CDECL16_ENTRY .func: + mov bx, [boot_drive_ptr] + mov ax, [bx + 0] + mov bx, ax + movzx ax, byte [bx + 0] ; 67h override would probably work but this is the 16bit way to do it + mov byte [bp - 2], al ; save boot drive as a local for easy access + mov dword edx, [bp + 4] mov si, fat32_nc_data .calc_offset: @@ -213,7 +233,14 @@ NextCluster: add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: - ; load correct fat + movzx ax, [bp - 2] + push ax + + mov ax, 0x1 + push ax + + ; load correct fat + mov eax, dword [si + FAT32_NextClusterData_t.fat_sector] push dword eax mov ax, fat_buffer @@ -221,10 +248,11 @@ NextCluster: xor ax, ax push ax - ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) - call read_disk_raw ; read_disk_raw(0, fat_buffer, fat_sector) - add sp, 0x8 - + call read_disk_raw + add sp, 0xC + ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, +; uint32_t lba, +; uint16_t count, uint16_t drive_num) .read_cluster: ; next_cluster = fat_buffer[entry_offset] mov ebx, dword [si + FAT32_NextClusterData_t.entry_offset] @@ -235,6 +263,7 @@ NextCluster: ret ; uint32_t ClusterToLBA(uint32_t cluster) +ALIGN 4, db 0x90 ClusterToLBA: __CDECL16_ENTRY .func: @@ -249,25 +278,42 @@ ClusterToLBA: ret ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) +ALIGN 4, db 0x90 ReadFATCluster: __CDECL16_ENTRY .func: + mov bx, [boot_drive_ptr] + mov ax, [bx + 0] + mov bx, ax + movzx ax, byte [bx + 0] ; 67h override would probably work but this is the 16bit way to do it + mov byte [bp - 2], al ; save boot drive as a local for easy access + mov dword eax, [bp + 8] push dword eax call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster) add sp, 0x4 ; eax == LBA - push dword eax ;uint32_t lba + movzx ax, [bp - 2] + push ax - mov dx, [bp + 4] ; seg - push dx ; uint16_t buf_offset + mov ax, 0x1 + push ax - mov dx, [bp + 6] ; offset - push dx ; unit16_t segment + ; load correct fat + mov eax, dword [si + FAT32_NextClusterData_t.fat_sector] + push dword eax - call read_disk_raw ; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint32_t lba) - add sp, 0x8 + mov ax, fat_buffer + push ax + + xor ax, ax + push ax + call read_disk_raw + add sp, 0xC .endp: __CDECL16_EXIT ret + +%endif +%define __INC_FAT32_SYS \ No newline at end of file diff --git a/include/kmem_func.inc b/include/kmem_func.inc index e69ca31..93f544d 100644 --- a/include/kmem_func.inc +++ b/include/kmem_func.inc @@ -17,15 +17,18 @@ ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. + +%ifndef __INC_KMEM_FUNC %include 'cdecl16.inc' -; uint8_t* kmemset(void* dest, uint8_t val, uint8_t len); +; uint8_t* kmemset_byte(void* dst, uint8_t val, uint16_t len); +ALIGN 4, db 0x90 kmemset: __CDECL16_ENTRY .func: mov cx, [bp + 8] ; size_t len mov al, [bp + 6] ; uint8_t val - mov di, [bp + 4] ; void * ptr + mov di, [bp + 4] ; void * dst cld rep stosb @@ -36,6 +39,7 @@ kmemset: ; uint8_t* kmemset(uint8_t* dest, uint8_t* src, uint8_t len); ; not overlap safe +ALIGN 4, db 0x90 kmemcpy: __CDECL16_ENTRY .func: @@ -48,4 +52,7 @@ kmemcpy: mov ax, di ; return pointer to dest .endf: __CDECL16_EXIT - ret \ No newline at end of file + ret + +%endif +%define __INC_KMEM_FUNC \ No newline at end of file diff --git a/include/memory.inc b/include/mem.inc similarity index 93% rename from include/memory.inc rename to include/mem.inc index 68e1305..ca8ac77 100755 --- a/include/memory.inc +++ b/include/mem.inc @@ -18,6 +18,8 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_MEM + ; ## Generic Low mem map (from osdev wiki) ## ; start end size type description @@ -54,12 +56,12 @@ ; copy of FAT32 BPB, 33 bytes (+1 to the next value to align to uint16_t) ;0x3048 -%define fat32_bpb 0x3050 -%define fat32_bpb_SIZE 33 +%define fat32_bpb 0x304A +%define fat32_bpb_SIZE 36 ; copy of FAT32 EBPB, 54 bytes ;0x306A -%define fat32_ebpb 0x30A0 +%define fat32_ebpb 0x306E %define fat32_ebpb_SIZE 54 ; FAT32 FSInfo, 512 bytes @@ -69,18 +71,18 @@ ; some stored state for the fat32 driver ;0x32A2 -%define fat32_state 0x32B0 +%define fat32_state 0x34B0 %define fat32_state_SIZE 32 ; next free space is 0x32D0 -%define fat32_nc_data 0x32D0 +%define fat32_nc_data 0x35D0 %define fat32_nc_data_size 16 ; lba_packet for raw_disk_read %define lba_packet 0x4000 %define BIOSMemoryMap 0x4200 -%define SteviaInfo 0x4400 +%define SteviaInfo 0x5200 ; High memory addresses for loading kernel (for use with unreal mode and 32bit override) @@ -110,8 +112,5 @@ struc SteviaInfoStruct_t .EBPBDataPtr resd 1 endstruc -%macro DEBUG_HCF 0 - DEBUG_LOOP: - hlt - jmp short DEBUG_LOOP -%endmacro \ No newline at end of file +%endif +%define __INC_MEM \ No newline at end of file diff --git a/include/partition_table.inc b/include/partition_table.inc index 7f149fa..ddd9ab6 100755 --- a/include/partition_table.inc +++ b/include/partition_table.inc @@ -18,6 +18,8 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_PART_TABLE + ; Partition table entry format ; Off. Size. Description ;0x00 1 Drive attributes (bit 7 set = active or bootable) @@ -41,4 +43,7 @@ struc PartTable_t .partition2 resb 16 .partition3 resb 16 .partition4 resb 16 -endstruc \ No newline at end of file +endstruc + +%endif +%define __INC_PART_TABLE \ No newline at end of file diff --git a/include/util/error_func.inc b/include/util/error_func.inc index cbd238a..d2a4901 100644 --- a/include/util/error_func.inc +++ b/include/util/error_func.inc @@ -18,13 +18,23 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. +%ifndef __INC_ERROR_FUNC + %macro ERROR 1 xor ax, ax mov al, %1 jmp error %endmacro +%macro DEBUG_HCF 0 + DEBUG_LOOP: + cli + hlt + jmp short DEBUG_LOOP +%endmacro + ; pass error as ascii character in al, errors a-zA-Z or 0-9 +ALIGN 4, db 0x90 error: ; fs = 0xb800 => fs:0x0000 = 0xb8000 mov dx, 0xB800 @@ -47,4 +57,7 @@ error: .stop: hlt - jmp short error.stop \ No newline at end of file + jmp short error.stop + +%endif +%define __INC_ERROR_FUNC \ No newline at end of file diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index f65a202..e4450a8 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -23,17 +23,37 @@ [CPU KATMAI] jmp short init nop -%include "cdecl16.inc" ; include calling convention macros for cdecl16 -%include "entry.inc" ; defines with entry points for various stages & stack -init: - cli ; We do not want to be interrupted - xor ax, ax ; 0 AX - mov ds, ax ; Set segment registers to 0 - mov es, ax ; * - - mov ss, ax ; Set Stack Segment to 0 - mov sp, EARLY_STACK_START +; ############### +; +; Headers/Includes/Definitions +; +; ############### + +%define __STEVIA_MBR + +%include "cdecl16.inc" +%include "entry.inc" +%include "config.inc" +%include "mem.inc" +%include "error_codes.inc" +%include "partition_table.inc" + +; ############### +; End Section +; ############### + +ALIGN 4, db 0x90 +init: + cli ; We do not want to be interrupted + + xor ax, ax ; 0 AX + mov ds, ax ; Set segment registers to 0 + + mov ss, ax ; Set Stack Segment to 0 + mov sp, EARLY_STACK_START ; Setup stack + mov bp, sp ; base ptr = stack ptr + sub sp, 0x20 ; local varible space mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS) @@ -43,16 +63,28 @@ init: sti jmp 0:main - nop -%include "config.inc" -%include "memory.inc" +; ############### +; +; Extra/Shared Functions +; +; ############### + %include "kmem_func.inc" -%include "partition_table.inc" -%include "errors.inc" +%include "util/error_func.inc" +; ############### +; End Section +; ############### + +; +; bp - 2 : uint8_t boot_drive +; bp - 4 : uint16_t part_offset +; + +ALIGN 4, db 0x90 main: - mov [boot_drive], dl ; BIOS passes drive number in DL + mov byte [bp - 2], dl ; BIOS passes drive number in DL .check_disk: cmp dl, 0x80 @@ -62,7 +94,7 @@ main: .check_extentions: xor ax, ax mov bx, 0x55AA - mov dl, byte [boot_drive] + mov dl, byte [bp - 2] int 0x13 jnc main.find_active ERROR MBR_ERROR_NO_INT32E ; no extended function support @@ -83,25 +115,30 @@ main: mov ax, bx sub ax, DiskSig ; leaves us with the offset relative from start of table ; this gives us an offset from the begining of the partition table - mov word [part_offset], ax ; update part_offset + mov word [bp - 4], ax ; update part_offset .read_data: - ;uint8_t read_disk_raw(size_t count, uint16_t buf_segment, uint16_t buf_offset, - ; uint16_t lower_lower_lba, uint16_t upper_lower_lba) - mov eax, dword [bx + PartEntry_t.lba_start] - ror eax, 16 - push ax + movzx ax, byte [bp - 2] + push ax ; drive_num - ror eax, 16 - push ax + mov ax, 0x1 + push ax ; count - mov ax, VBR_ENTRY - push ax + mov dword eax, dword [bx + PartEntry_t.lba_start] + push dword eax ; lba xor ax, ax - push ax ; segment = 0 + push ax ; offset = 0 + + mov ax, VBR_ENTRY + shr ax, 4 + push ax ; segment = 7C0 + + ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, + ; uint32_t lba, + ; uint16_t count, uint16_t drive_num) + call read_disk_raw + add sp, 0xC - call read_vbr_raw - add sp, 0x8 jnc main.goto_vbr ERROR MBR_ERROR_DISK_READ_ERR ; error in LBA read @@ -120,86 +157,16 @@ main: call kmemcpy ; copy partition table to memory add sp, 0x6 - xor ah, ah ; Set Video mode BIOS function - mov al, 0x02 ; 16 color 80x25 Text mode - int 0x10 ; Call video interrupt - - mov ah, 0x05 ; Select active display page BIOS function - xor al, al ; page 0 - int 0x10 ; call video interrupt - - mov si, word [part_offset] - mov dl, byte [boot_drive] + mov si, word [bp - 4] + mov dl, byte [bp - 2] jmp 0:0x7C00 -; Wrapper for AH=0x42 INT13h (Extended Read) +; ############### ; -; BIOS call details -; AH = 42h -; DL = drive number -; DS:SI -> disk address packet +; BIOS Functions ; -; Return: -; CF clear if successful -; AH = 00h -; CF set on error -; AH = error code -; disk address packet's block count field set to number of blocks -; successfully transferred -; -; -; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, uint16_t lower_lower_lba, uint16_t upper_lower_lba) -read_vbr_raw: - __CDECL16_ENTRY -.func: - mov ax, 0x10 - push ax ; len = 16 bytes - xor ax, ax - push ax ; val = 0 - mov ax, lba_packet - push ax ; dest = lba_packet address - call kmemset - add sp, 0x06 - - mov byte [lba_packet + LBAPkt_t.size], 0x10 - mov word [lba_packet + LBAPkt_t.xfer_size], 0x0001 - - mov ax, [bp + 10] - shl eax, 16 - mov ax, [bp + 8] - mov dword [lba_packet + LBAPkt_t.lower_lba], eax - - mov ax, [bp + 6] - mov word [lba_packet + LBAPkt_t.offset], ax - - mov ax, [bp + 4] - mov word [lba_packet + LBAPkt_t.segment], ax - - mov si, lba_packet - mov ah, 0x42 - mov dl, byte [boot_drive] - int 0x13 - jnc .endf - - ERROR MBR_ERROR_INT13h_EREAD_ERR -.endf: - __CDECL16_EXIT - ret - -; ############# -; -; Locals -; -; ############# - -boot_drive: - db 0x00 -mbr_reserved1: - db 0x00 - -; OFFSET from BEGINING of partition table, ie. DiskSig (-6 from PartEntry1) -part_offset: - dw 0x0000 +; ############### +%include 'BIOS/func/ext_read.inc' %assign bytes_remaining (440 - ($ - $$)) %warning MBR has bytes_remaining bytes remaining for code (MAX: 440 bytes) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 5fad4a8..f014125 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -23,11 +23,27 @@ [CPU KATMAI] jmp short init nop - ; boot drive in dl ; active partition offset in si + +; ############### +; +; Headers/Includes/Definitions +; +; ############### +%define __STEVIA_STAGE2 + + %include "cdecl16.inc" %include "entry.inc" +%include "config.inc" +%include "mem.inc" +%include "error_codes.inc" + +; ############### +; End Section +; ############### +ALIGN 4, db 0x90 init: cli ; We do not want to be interrupted @@ -37,32 +53,36 @@ init: mov fs, ax ; * mov gs, ax ; * - mov ss, ax ; Set Stack Segment to 0 + mov ss, ax ; Set Stack Segment to 0 mov sp, EARLY_STACK_START ; Set Stack Pointer - - add sp, 0x4 - mov ax, 0xDEAD - push word ax - mov ax, 0xBEEF - push word ax ; mark top of stack for debuging - mov bp, sp + sub sp, 0x20 ; 32 bytes for local varibles + sti jmp 0:main -%include "config.inc" -%include "error_codes.inc" -%include "memory.inc" -%include "kmem_func.inc" -%include "partition_table.inc" -%include "fat32/bpb.inc" -%include "fat32/fat32_structures.inc" +; ############### +; +; Extra/Shared Functions +; +; ############### + +%include "kmem_func.inc" +%include "util/error_func.inc" + +; ############### +; End Section +; ############### main: - mov byte [fat32_ebpb + FAT32_ebpb_t.drive_number_8], dl - mov word [partition_offset], si + lea ax, [bp - 2] + mov [boot_drive_ptr], ax + lea ax, [bp - 4] + mov [partition_offset_ptr], ax + mov byte [bp - 2], dl ; boot_drive (probably 0x80) + mov word [bp - 4], si ; partition_offset mov eax, dword [STAGE2_SIG] cmp eax, 0xDEADBEEF @@ -138,7 +158,7 @@ hcf: ; ; ############### -%include 'fat32/fat32_func_old.inc' +%include 'fat32/fat32_sys.inc' ; ############### ; @@ -306,18 +326,13 @@ NewLine_cstr: db StrCRLF_NUL BootTarget_str: db "BOOTI686BIN" - -; ############# -; -; Locals -; -; ############# - -partition_offset: +boot_drive_ptr: + db 0x00 +stage2_resb_1: + db 0x00 +partition_offset_ptr: dw 0x0000 - - ; GDT documentation below: ; ; Pr: Present bit. This must be 1 for all valid selectors. diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 37759ca..2ffdd30 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -30,36 +30,59 @@ phy_ebpb_start: ; fill eBPB area with 0x00 since we skip writing this part to disk times 54 db 0x00 +; ############### +; +; Headers/Includes/Definitions +; +; ############### +%define __STEVIA_VBR + + %include "cdecl16.inc" %include "entry.inc" +%include "config.inc" +%include "mem.inc" +%include "error_codes.inc" +%include "fat32/bpb_offset_bx.inc" + +; ############### +; End Section +; ############### + +ALIGN 4, db 0x90 init: cli ; We do not want to be interrupted xor ax, ax ; 0 AX mov ds, ax ; Set segment registers to 0 - mov es, ax ; * mov ss, ax ; Set Stack Segment to 0 - mov sp, EARLY_STACK_START ; Setup stack + mov sp, EARLY_STACK_START ; Setup stack mov bp, sp ; base ptr = stack ptr + sub sp, 0x20 ; local varible space mov bx, VBR_ENTRY ; move Bx to the new start of the initial boot sector sti ; all done with inital setup and relocation, reenable interupts jmp 0:main ; fix up cs:ip just in case and jump to relocated code - nop -%include "config.inc" -%include "memory.inc" +; ############### +; +; Extra/Shared Functions +; +; ############### + %include "kmem_func.inc" -%include "partition_table.inc" -%include "errors.inc" +%include "util/error_func.inc" -%include "fat32/bpb.inc" +; ############### +; End Section +; ############### +ALIGN 4, db 0x90 main: - mov [bsDriveNumber], dl ; BIOS passes drive number in DL - mov [partition_offset], si ; save passed partition entry offset + mov byte [bp - 2], dl ; boot_drive + mov [bp - 4], si ; part_offset .check_FAT_size: ; we only support a very specific setup of FAT32 cmp dword [bsSectorHuge], 0 ; SectorsHuge will not be set if FAT12/16 @@ -69,24 +92,39 @@ main: ; read sectors 1-63 to stage2 entry point .load_stage2: - xor ax, ax - push ax ; upper_lower_lba = 0 + mov ax, (fat32_bpb_SIZE + fat32_ebpb_SIZE) ; size in byte + push ax + mov ax, (phy_bpb_start - 0x3) ; start of bpb - 0x3 for the jump short main at the start + push ax + mov ax, fat32_bpb ; defined in memory.inc, destination + push ax + call kmemcpy ; copy bpb to memory + add sp, 0x6 - mov ax , 1 - push ax ; lower_lower_lba = 1 + mov bx, fat32_bpb ; bx now points to aligned memory structure + + movzx ax, byte [bp - 2] + push ax ; drive_num + + mov ax, STAGE2_SECTOR_COUNT + push ax ; count + + mov dword eax, 0x1 + push dword eax ; lba xor ax, ax - push ax ; offset = 0 + push ax ; offset = 0 - ; 07E0:0 + ; 07E0:0 = 0x00007e00 mov ax, STAGE2_ENTRY shr ax, 4 - push ax ; segment = 7E0 + push ax ; segment = 7E0 - ;uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, - ; uint16_t lower_lower_lba, uint16_t upper_lower_lba) - call read_stage2_raw - add sp, 0x8 + ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, + ; uint32_t lba, + ; uint16_t count, uint16_t drive_num) + call read_disk_raw + add sp, 0xC .check_sig: mov ax, 0x7E0 @@ -97,97 +135,16 @@ main: ERROR VBR_ERROR_NO_SIGNATURE ; no signature present in stage2 .sig_ok: - mov ax, fat32_bpb_SIZE ; size in byte - push ax - mov ax, phy_bpb_start ; start of bpb - push ax - mov ax, fat32_bpb ; defined in memory.inc, destination - push ax - call kmemcpy ; copy bpb to memory - add sp, 0x6 - - mov ax, fat32_ebpb_SIZE ; 72 bytes of data - push ax - mov ax, phy_ebpb_start ; start of ebpb - push ax - mov ax, fat32_ebpb ; defined in memory.inc, destination - push ax - call kmemcpy ; copy ebpb to memory - add sp, 0x6 - - mov si, [partition_offset] - mov dl, [bsDriveNumber] + mov si, [bp - 4] + mov dx, [bp - 2] jmp 0:0x7E00 -stop: - hlt - jmp short stop - -; Wrapper for AH=0x42 INT13h (Extended Read) +; ############### ; -; BIOS call details -; AH = 42h -; DL = drive number -; DS:SI -> disk address packet +; Required BIOS functions ; -; Return: -; CF clear if successful -; AH = 00h -; CF set on error -; AH = error code -; disk address packet's block count field set to number of blocks -; successfully transferred -; -; -; uint8_t read_disk_raw(uint16_t buf_segment, uint16_t buf_offset, -; uint16_t lower_lower_lba, uint16_t upper_lower_lba) -read_stage2_raw: - __CDECL16_ENTRY -.func: - mov ax, 0x10 - push ax ; len = 16 bytes - xor ax, ax - push ax ; val = 0 - mov ax, lba_packet - push ax ; dest = lba_packet address - call kmemset - add sp, 0x06 - - mov byte [lba_packet + LBAPkt_t.size], 0x10 - mov word [lba_packet + LBAPkt_t.xfer_size], STAGE2_SECTOR_COUNT - - mov ax, [bp + 10] - shl eax, 16 - mov ax, [bp + 8] - mov dword [lba_packet + LBAPkt_t.lower_lba], eax - - mov ax, [bp + 6] - mov word [lba_packet + LBAPkt_t.offset], ax - - mov ax, [bp + 4] - mov word [lba_packet + LBAPkt_t.segment], ax - - mov si, lba_packet - mov ah, 0x42 - mov dl, byte [bsDriveNumber] - int 0x13 - jnc .endf - - ERROR VBR_ERROR_DISK_READ_ERR -.endf: - __CDECL16_EXIT - ret -; Data - -; ############# -; -; Locals -; -; ############# - -; offset from the begining of sector 0 to the active partition. -partition_offset: - dw 0x0000 +; ############### +%include 'BIOS/func/ext_read.inc' %assign bytes_remaining (420 - ($ - $$)) %warning VBR has bytes_remaining bytes remaining for code (MAX: 420 bytes) From 145e9fbaa9cafae895f958f55936334ac0dcff12 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 5 Oct 2024 20:14:00 -0400 Subject: [PATCH 066/147] =?UTF-8?q?fixed=20read=5Fdisk=5Fraw=20in=20ReadFA?= =?UTF-8?q?TCluster=20boot=5Fdrive=20and=20partition=5Foffset=20are=20glob?= =?UTF-8?q?al=20pointers=20now=20removed=20an=20extra=20error=20from=20mbr?= =?UTF-8?q?=20disk=20read=20and=20some=20general=20formating=20and=20clean?= =?UTF-8?q?up=20=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/BIOS/func/ext_read.inc | 2 +- include/fat32/fat32_sys.inc | 13 +++---------- src/mbr/mbr.nasm | 10 +++++----- src/stage2/stage2.nasm | 11 ++++++----- src/vbr/vbr.nasm | 13 ++++--------- 5 files changed, 19 insertions(+), 30 deletions(-) diff --git a/include/BIOS/func/ext_read.inc b/include/BIOS/func/ext_read.inc index a107c94..42d1cdc 100644 --- a/include/BIOS/func/ext_read.inc +++ b/include/BIOS/func/ext_read.inc @@ -97,7 +97,7 @@ read_disk_raw: %ifdef __STEVIA_MBR ERROR MBR_ERROR_DISK_READ_ERR - %elifsef __STEVIA_VBR + %elifdef __STEVIA_VBR ERROR VBR_ERROR_DISK_READ_ERR %else ERROR STAGE2_MBR_DISK_READ_ERROR diff --git a/include/fat32/fat32_sys.inc b/include/fat32/fat32_sys.inc index 3de49ab..60f155a 100644 --- a/include/fat32/fat32_sys.inc +++ b/include/fat32/fat32_sys.inc @@ -36,9 +36,7 @@ InitFATDriver: .calc_active_part: mov bx, [partition_offset_ptr] - mov ax, [bx + 0] - mov bx, ax - mov ax, [bx + 0] + mov ax, [bx + 0] mov dx, partition_table add dx, ax ; dx points to the partition that was booted from @@ -66,7 +64,6 @@ InitFATDriver: mov dword [fat32_state + FAT32_State_t.first_data_sector_32], eax .get_first_root_dir: ; TODO - jmp InitFATDriver.endp .error: ERROR STAGE2_FAT32_INIT_ERROR @@ -74,7 +71,6 @@ InitFATDriver: __CDECL16_EXIT ret -; TODO: needs validation ; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory ; ; SFN is a 8.3 file name, all uppercase, and padded with spaces @@ -284,15 +280,13 @@ ReadFATCluster: .func: mov bx, [boot_drive_ptr] mov ax, [bx + 0] - mov bx, ax - movzx ax, byte [bx + 0] ; 67h override would probably work but this is the 16bit way to do it mov byte [bp - 2], al ; save boot drive as a local for easy access mov dword eax, [bp + 8] push dword eax call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster) add sp, 0x4 ; eax == LBA - + mov dword [bp - 6], eax movzx ax, [bp - 2] push ax @@ -300,8 +294,7 @@ ReadFATCluster: mov ax, 0x1 push ax - ; load correct fat - mov eax, dword [si + FAT32_NextClusterData_t.fat_sector] + mov eax, dword [bp + 6] push dword eax mov ax, fat_buffer diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index e4450a8..b1ad23d 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -138,15 +138,10 @@ main: ; uint16_t count, uint16_t drive_num) call read_disk_raw add sp, 0xC - - - jnc main.goto_vbr - ERROR MBR_ERROR_DISK_READ_ERR ; error in LBA read .goto_vbr: cmp word [VBR_ENTRY + 0x1FE], 0xAA55 je main.sig_ok ERROR MBR_ERROR_NO_VBR_SIG ; no signature present - .sig_ok: mov ax, partition_table_SIZE ; 72 bytes of data push ax @@ -166,8 +161,13 @@ main: ; BIOS Functions ; ; ############### + %include 'BIOS/func/ext_read.inc' +; ############### +; End Section +; ############### + %assign bytes_remaining (440 - ($ - $$)) %warning MBR has bytes_remaining bytes remaining for code (MAX: 440 bytes) times ((512 - 72) - ($ - $$)) nop ; Fill the rest of sector with nop diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index f014125..d6d11bd 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -23,16 +23,14 @@ [CPU KATMAI] jmp short init nop -; boot drive in dl -; active partition offset in si ; ############### ; ; Headers/Includes/Definitions ; ; ############### -%define __STEVIA_STAGE2 +%define __STEVIA_STAGE2 %include "cdecl16.inc" %include "entry.inc" @@ -43,6 +41,7 @@ nop ; ############### ; End Section ; ############### + ALIGN 4, db 0x90 init: cli ; We do not want to be interrupted @@ -62,7 +61,6 @@ init: jmp 0:main - ; ############### ; ; Extra/Shared Functions @@ -76,6 +74,10 @@ init: ; End Section ; ############### +; +; bp - 2 : uint8_t boot_drive +; bp - 4 : uint16_t part_offset +; main: lea ax, [bp - 2] mov [boot_drive_ptr], ax @@ -147,7 +149,6 @@ main: add sp, 0x2 ERROR STEVIA_DEBUG_HALT - hcf: hlt jmp short hcf diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 2ffdd30..4c46864 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -37,7 +37,6 @@ times 54 db 0x00 ; ############### %define __STEVIA_VBR - %include "cdecl16.inc" %include "entry.inc" %include "config.inc" @@ -81,17 +80,14 @@ init: ALIGN 4, db 0x90 main: - mov byte [bp - 2], dl ; boot_drive + mov byte [bp - 2], dl ; boot_drive mov [bp - 4], si ; part_offset .check_FAT_size: ; we only support a very specific setup of FAT32 cmp dword [bsSectorHuge], 0 ; SectorsHuge will not be set if FAT12/16 ja main.load_stage2 - ERROR VBR_ERROR_WRONG_FAT_SIZE - -; read sectors 1-63 to stage2 entry point -.load_stage2: +.load_stage2: ; read sectors 1-63 to stage2 entry point mov ax, (fat32_bpb_SIZE + fat32_ebpb_SIZE) ; size in byte push ax mov ax, (phy_bpb_start - 0x3) ; start of bpb - 0x3 for the jump short main at the start @@ -140,10 +136,9 @@ main: jmp 0:0x7E00 ; ############### -; -; Required BIOS functions -; +; Required BIOS function(s) ; ############### + %include 'BIOS/func/ext_read.inc' %assign bytes_remaining (420 - ($ - $$)) From f33ecbcea2123a8612befd7369e2baeef54098a0 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 6 Oct 2024 15:37:19 -0400 Subject: [PATCH 067/147] make the Linux bochs run more inline with the Windows one --- bochsrc.txt | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/bochsrc.txt b/bochsrc.txt index 8ca1a66..10ea176 100755 --- a/bochsrc.txt +++ b/bochsrc.txt @@ -1,38 +1,49 @@ # configuration file generated by Bochs -plugin_ctrl: unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, gameport=true, iodebug=true -config_interface: wx -display_library: wx -memory: host=128, guest=128 +plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=false, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false +config_interface: textconfig +display_library: sdl2 +memory: guest=64, host=64, block_size=128 +romimage: file="/usr/share/bochs/BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none +vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" boot: disk floppy_bootsig_check: disabled=0 -# no floppya +floppya: type=1_44 # no floppyb ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 -ata0-master: type=disk, path="./disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Generic 1234", biosdetect=auto, translation=auto +ata0-master: type=disk, path="./disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=lba ata0-slave: type=none ata1: enabled=false +ata1-master: type=none +ata1-slave: type=none ata2: enabled=false ata3: enabled=false -pci: enabled=0 -vga: extension=vbe, update_freq=5, realtime=1 -cpu: count=1:1:1, ips=1000000, quantum=16, model=p3_katmai, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +optromimage1: file=none +optromimage2: file=none +optromimage3: file=none +optromimage4: file=none +optramimage1: file=none +optramimage2: file=none +optramimage3: file=none +optramimage4: file=none +pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none +vga: extension=vbe, update_freq=10, realtime=1, ddc=builtin +cpu: count=1, ips=1000000, model=p3_katmai, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 print_timestamps: enabled=0 -debugger_log: - -magic_break: enabled=0 -port_e9_hack: enabled=0 +port_e9_hack: enabled=false, all_rings=false private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 # no cmosimage -log: stevia-log +log: - logprefix: %t%e%d debug: action=ignore info: action=report error: action=report panic: action=ask -keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none -mouse: type=ps2, enabled=false, toggle=ctrl+mbutton -speaker: enabled=true, mode=system -parport1: enabled=false +keyboard: type=mf, serial_delay=150, paste_delay=100000, user_shortcut=none +mouse: type=none, enabled=false, toggle=ctrl+mbutton +sound: waveoutdrv=dummy, waveout=none, waveindrv=dummy, wavein=none, midioutdrv=dummy, midiout=none +speaker: enabled=true, mode=sound, volume=15 +parport1: enabled=true, file=none parport2: enabled=false com1: enabled=true, mode=null com2: enabled=false From e41b597056076d06c55a718cfa23675e7f882ae3 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 6 Oct 2024 18:50:32 -0400 Subject: [PATCH 068/147] surpress some of the relocation warnings for mbr, vbr & stage2 --- src/mbr/mbr.nasm | 1 + src/stage2/stage2.nasm | 2 ++ src/vbr/vbr.nasm | 1 + 3 files changed, 4 insertions(+) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index b1ad23d..973d1ca 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -21,6 +21,7 @@ [BITS 16] [ORG 0x7A00] [CPU KATMAI] +[WARNING -reloc-abs-word] jmp short init nop diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index d6d11bd..337b2de 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -21,6 +21,8 @@ [BITS 16] [ORG 0X7E00] [CPU KATMAI] +[WARNING -reloc-abs-word] +[WARNING -reloc-abs-dword] jmp short init nop diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 4c46864..ba804da 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -20,6 +20,7 @@ [BITS 16] [ORG 0x7C00] [CPU KATMAI] +[WARNING -reloc-abs-word] jmp short init nop phy_bpb_start: From 213ea112096a73405ba3e14450a883454b101c0e Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 6 Oct 2024 18:52:20 -0400 Subject: [PATCH 069/147] cutting out everything from miniboot this file has always just been a place holder to get some code to load from the disk I wanted to cut out all the extra stuff in it just to simplify things down. --- src/miniboot32/BOOTi686.nasm | 516 ++--------------------------------- 1 file changed, 28 insertions(+), 488 deletions(-) diff --git a/src/miniboot32/BOOTi686.nasm b/src/miniboot32/BOOTi686.nasm index 6ab059b..8f4c603 100755 --- a/src/miniboot32/BOOTi686.nasm +++ b/src/miniboot32/BOOTi686.nasm @@ -21,131 +21,30 @@ [BITS 32] [ORG 0x100000] [CPU KATMAI] - -jmp short start32 +jmp short init32 nop -; Unless noted otherwise, functions will be the standard x86 cdecl used in GCC - -; In cdecl, subroutine arguments are passed on the stack. -; Integer values and memory addresses are returned in the EAX register, -; floating point values in the ST0 x87 register. -; Registers EAX, ECX, and EDX are caller-saved, -; and the rest are callee-saved. -; The x87 floating point registers ST0 to ST7 must be empty (popped or freed) -; when calling a new function, and ST1 to ST7 must be empty on exiting a function. -; ST0 must also be empty when not used for returning a value. -; -; EXAMPLE: to call uint8_t* kmemset(uint8_t* dest, uint8_t val, uint8_t size); -; => kmemset(*((char*) 0xb8000), 'F', (80*25)) -; -; push ebp ; save old call frame pointer -; mov ebp, esp ; new call frame pointer -; push 0x000007D0 ; push args RTL, EBP - 4 -; push 'F' ; * EBP - 8 -; push 0x000b8000 ; * EBP - 12 -; call kmemset ; call function, this also places a return pointer on stack -; add esp, 12 ; remove call arguments from stack frame -; mov esp, ebp ; restore stack frame pointer (callee saves EBP) -; pop ebp ; restore call frame pointer -; -; - -; 33 bytes BPB + 26 Byte EBPB -struc BPBStruct - .OemName resb 8 - .BytesPerSect resw 1 - .SecsPerClust resb 1 - .ResSectors resw 1 - .FATs resb 1 - .RootDirEnts resw 1 - .Sectors resw 1 - .Media resb 1 - .SectPerFAT resw 1 - .SectPerTrack resw 1 - .Heads resw 1 - .Hidden resd 1 - .SectorHuge resd 1 - ; begin EBPB - .DriveNumber resb 1 - .NTReserved resb 1 - .Signature resb 1 - .VolumeID resd 1 - .VolumeLabel resb 11 - .SysIdent resb 8 -endstruc - -; 12 bytes -struc FSInfoStruct - .first_root_dir_sector resw 1 - .last_root_dir_sector resw 1 - .root_dir_len resw 1 - .first_data_sector resw 1 - .active_cluster resw 1 - .active_FAT_cluster resw 1 -endstruc - -; 20 bytes -struc KInfoStruct - .load_address resd 1 - .file_len resd 1 - .file_name resb 8 - .file_ext resb 3 - .reserved1 resb 1 -endstruc - -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow u32 - Low 32 Bits of Base Address -; 4 BaseAddrHigh u32 - High 32 Bits of Base Address -; 8 LengthLow u32 - Low 32 Bits of Length in Bytes -; 12 LengthHigh u32 - High 32 Bits of Length in Bytes -; 16 Type u32 - Address type of this range. -; 20 ExtType u32 - ACPI 3.0 extended type -struc AddressRangeDescStruct - .BaseAddrLow resd 1 - .BaseAddrHigh resd 1 - .LengthLow resd 1 - .LengthHigh resd 1 - .Type resd 1 - .ExtType resd 1 -endstruc - -; 20 bytes, passed to loaded kernel -struc CBootInfoStruct - .MemoryMapPtr resd 1 - .MemoryMapEntries resd 1 - .BPBDataPtr resd 1 - .FSInfoPtr resd 1 - .KInfoPtr resd 1 -endstruc - ;;; ; Errors ; 0 = unused -; 1 = No CPUID support on this platform (VM or some very old hardware?) -; 2 = magic signature not found at end of file -; 3 = Unexpected/unhandled artithmetic overflow/carry +; E = General Error +; S = magic signature not found at end of file +; O = OK ;;; %define MAX_BYTES (1024 * 8) - %define VGA_BUF 0xb8000 -;black BG/Green FG -%define TTY_COLOR 0x0200 -;black BG/Red FG -%define TTY_ERR_CLR 0x0400 -;subtract 1 for max array values -%define VGA_MAX_Y 25 -%define VGA_MAX_X 80 ; VGA memory is row-major => offset = (row * MAX_Colums) + colum ; macro array is counted from 0,0 = 1,1 => 79,24 is the last usable space in a page %define VGA_OFFSET(x,y) (((y*VGA_MAX_X) + x)*2) +;subtract 1 for max array values +%define VGA_MAX_Y 25 +%define VGA_MAX_X 80 -start32: - mov ax, 0x10 +ALIGN 16, db 0 +init32: + mov ax, 0x10 ; 0x10 selector segment mov ds, ax mov es, ax mov fs, ax @@ -154,394 +53,35 @@ start32: mov esp, stack_top mov ebp, esp -; debugger hack because gdb doesn't like to switch register sizes -; issue a set $eax = 1 to continue -%ifdef DEBUG_HACK - mov eax, 0 -.gdb_hack: - test eax, eax - jz start32.gdb_hack -%endif - mov eax, dword [BOOT_SIG] cmp eax, 0xA0B0C0D0 - jz start32.signature_present - - mov al, "2" - call error - + jz .signature_present + mov dl, "S" + jmp .result .signature_present: - call check_cpuid - - push ebp - mov ebp, esp - lea eax, [welcome_cstr] - push eax - call vga_puts - leave - - push ebp - mov ebp, esp - lea eax, [version_cstr] - push eax - call vga_puts - leave - - push ebp - mov ebp, esp - lea eax, [datetime_cstr] - push eax - call vga_puts - leave - - mov eax, VGA_BUF - add eax, VGA_OFFSET(78, 24) - mov dword [eax], 0x2f4b2f4f - hlt - -; Early error printer. Prints 'ERR: X' where X is an error code in al -error: + mov dl, "O" +.result: mov eax, VGA_BUF add eax, VGA_OFFSET(73, 24) + + mov dword [eax], 0x1f451f52 + add eax, 0x4 + mov dword [eax], 0x1f3e1f53 + add eax, 0x4 + ; RES> in white-on-blue - mov dword [eax], 0x4f524f45 - add eax, 0x2 - mov dword [eax], 0x4f3a4f52 - add eax, 0x2 - mov dword [eax], 0x4f204f20 - add eax, 0x2 - mov byte [eax], al + mov ecx, 0x1f201f20 + and cl, dl ; 0x1f201f(dl) + ror ecx, 16 ; 0x1f(dl)1f20 = ' (dl)' + mov dword [eax], ecx ; should be a space and contents of dl +.endp: hlt - -check_cpuid: - ; flip cpuid id bit (bit 21) to check for cpuid support - - ; copy flags to eax via stack - pushfd - pop eax - - mov ecx, eax ; copy to ecx for compare - - xor eax, 1 << 21 ; xor eax with the 21st bit set - - push eax ; push new flags and pop to flags register - popfd - - pushfd - pop eax - - cmp eax, ecx ; can we change the bit? - je .no_cpuid - ret -.no_cpuid: - mov al, "1" - call error - -; int vga_puts(char* str) -; -; INPUT: -; str: C-Sytle string -; -; OUTPUT: -; EAX = characters printed -; -vga_puts: - ; prolog, EBP = SFP (Stack frame pointer), [EBP-4] = char* str - push edi - push esi - push ebx - -.get_str_len: - mov edi, [ebp - 4] - - xor ecx, ecx ; ECX = 0 - not ecx ; ECX = -1 == 0xFFFFFFFF - xor eax, eax ; search for al = 0x0 - cld - repne scasb ; deincrement ecx while searching for al - not ecx ; the inverse of a neg number = abs(x) - 1 - dec ecx ; ECX contains the length of the string - nul byte at end - - - mov edi, VGA_BUF ; load dest index with VGA buffer + calculated offset - mov esi, [ebp -4] ; load source index with src string - - ; ECX = string length - ; ESI = source string to print - ; EDI = destination in the VGA buffer -.print_char: - cmp ecx, 0x0 - jle vga_puts.endf - - cmp byte [vga_buf_pos_x], 80 - je vga_puts.end_of_line - - cmp byte [vga_buf_pos_y], 25 - je vga_puts.scroll_up - - cmp byte [esi], 0x20 - jl vga_puts.special_character_switch - - push ebp - mov ebp, esp - - xor eax, eax - mov al, [vga_buf_pos_y] - push eax ; vga_pos_y - - xor eax, eax - mov al, [vga_buf_pos_x] - push eax ; vga_pos_x - - ; uint16_t vga_calc_offset(uint8_t vga_pos_x, uint8_t vga_pos_y) - call vga_calc_offset - leave - - xor bx, bx - mov bl, byte [esi] - or bx, TTY_COLOR ; create VGA character - - mov [edi+eax], bx - inc esi - inc byte [vga_buf_pos_x] - - - dec ecx - jmp vga_puts.print_char ; loop until ECX == 0 - -.end_of_line: - ; advance to next row - inc byte [vga_buf_pos_y] - mov byte [vga_buf_pos_x], 0 - jmp vga_puts.print_char -.scroll_up: - ; after 25 rows, move to next page (either swap pages [memcpy] or erase page 0) - mov byte [vga_buf_pos_x], 0 - mov byte [vga_buf_pos_y], 0 - - push ebp - mov ebp, esp - - mov eax, 0x7D0 - push eax ; 1 VGA page = 0x7D0 elements - - xor eax, eax - push eax ; we want to blank the page with 0x0000 - - mov eax, VGA_BUF - push eax ; load vga buffer base (0xb8000) - - ; uint16_t* kmemset_word(void* dest, uint16_t val, size_t len); - call kmemset_byte - leave - - jmp vga_puts.print_char - -.special_character_switch: - - cmp byte[esi], 0xA - je vga_puts.handle_LF - - cmp byte[esi], 0xD - je vga_puts.handle_CR - -; Default case -.special_character_endp: - dec ecx - inc esi - - jmp vga_puts.print_char - -.handle_LF: - ; advance to next row - inc byte [vga_buf_pos_y] - jmp vga_puts.special_character_endp - -.handle_CR: - mov byte [vga_buf_pos_x], 0 - jmp vga_puts.special_character_endp - - -.endf: - pop ebx - pop esi - pop edi - - ret - -; short vga_get_xy(void) -; -; INPUT: -; -; OUTPUT: -; EAX = xy_pos -; > x = xy_pos && 0xFF00 -; y = xy_pos && 0x00FF -; 2 MSB of EAX are 0. -; -vga_get_xy: -.endf: - ret - -; void vga_set_xy(short xy_pos) -; xy_pos is a byte packed word (16bit value), MSB is x, LSB is y -; => x = xy_pos && 0xFF00 -; y = xy_pos && 0x00FF -; -; INPUT: -; xy_pos -; -; OUTPUT: -; NONE -; -vga_set_xy: -.endf: - ret - -; uint16_t vga_calc_offset(uint8_t vga_pos_x, uint8_t vga_pos_y) -; VGA_OFFSET(x,y) == (((y*VGA_MAX_X) + x)*2) -vga_calc_offset: - xor eax, eax - xor edx, edx - - mov edx, [ebp-4] - mov ax, VGA_MAX_X - mul dx ; DX:AX contains (y*VGA_MAX_X) - jc vga_calc_offset.artithmetic_error - - mov edx, [ebp-8] - add ax, dx - jc vga_calc_offset.artithmetic_error - - mov dx, 0x02 - mul dx ; DX:AX contains (y*VGA_MAX_X) + x) * 2 - jnc vga_calc_offset.endf - -.artithmetic_error: - mov al, '3' - call error - -.endf: - ; (e)AX contains the offset - ret - -; uint32_t* kmemset(void* dest, uint32_t val, size_t len); -kmemset_dword: - push edi ; function uses edi, so save it. - ; [ebp] = previous call frame - mov ecx, [ebp - 4] ; size_t len - - mov eax, [ebp - 8] ; uint32_t val - - mov edi, [ebp - 12] ; void * ptr - ; [ebp - 16] = return adress - ; [ebp - 20] = saved EDI - rep stosd -.endf: - mov eax, [ebp - 12] ; return pointer to dest - pop edi ; restore edi - ret - -; uint16_t* kmemset(void* dest, uint16_t val, size_t len); -kmemset_word: - push edi ; function uses edi, so save it. - ; [ebp] = previous call frame - mov ecx, [ebp - 4] ; size_t len - - mov ax, [ebp - 8] ; uint16_t val - - mov edi, [ebp - 12] ; void * ptr - ; [ebp - 16] = return adress - ; [ebp - 20] = saved EDI - rep stosw -.endf: - mov eax, [ebp - 12] ; return pointer to dest - pop edi ; restore edi - ret - -; uint8_t* kmemset(void* dest, uint8_t val, size_t len); -kmemset_byte: - push edi ; function uses edi, so save it. - ; [ebp] = previous call frame - mov ecx, [ebp - 4] ; size_t len - - mov al, [ebp - 8] ; uint8_t val - - mov edi, [ebp - 12] ; void * ptr - ; [ebp - 16] = return adress - ; [ebp - 20] = saved EDI - rep stosb -.endf: - mov eax, [ebp - 12] ; return pointer to dest - pop edi ; restore edi - ret - -; uint32_t* kmemset(uint32_t* dest, uint32_t* src, size_t len); -kmemcpy_dword: - push edi - push esi ; edi, esi are callee save - - mov edi, [ebp-12] ; dest - mov esi, [ebp-8] ; source - mov ecx, [ebp-4] ; length - - cld ; ensure we are incrementing - rep movsd - -.endf: - mov eax, [ebp-12] ; return pointer to dest - pop esi - pop edi - ret - -; uint16_t* kmemset(uint16_t* dest, uint16_t* src, size_t len); -kmemcpy_word: - push edi - push esi ; edi, esi are callee save - - mov edi, [ebp-12] ; dest - mov esi, [ebp-8] ; source - mov ecx, [ebp-4] ; length - - cld ; ensure we are incrementing - rep movsw - -.endf: - mov eax, [ebp-12] ; return pointer to dest - pop esi - pop edi - ret - -; uint8_t* kmemset(uint8_t* dest, uint8_t* src, size_t len); -; not overlap safe -kmemcpy_byte: - push edi - push esi ; edi, esi are callee save - - mov edi, [ebp-12] ; dest - mov esi, [ebp-8] ; source - mov ecx, [ebp-4] ; length - - cld ; ensure we are incrementing - rep movsb - -.endf: - mov eax, [ebp-12] ; return pointer to dest - pop esi - pop edi - ret - -; Static Values -vga_buf_pos_x: - db 0x00 -vga_buf_pos_y: - db 0x00 + jmp .endp - $$ ; Strings +ALIGN 16, db 0 %define StrCRLF_NUL 0Dh, 0Ah, 00h -welcome_cstr: - db 'CBoot Stage3', StrCRLF_NUL version_cstr: db 'CBoot v0.0.3 ', 'NASM - ', __NASM_VER__, StrCRLF_NUL datetime_cstr: From 2bbdaddb68f51a14f6707065fe80d2befe46fd89 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 6 Oct 2024 21:46:32 -0400 Subject: [PATCH 070/147] jmp imm32 vs jmp rel8 (5 bytes vs 2 bytes) --- src/miniboot32/BOOTi686.nasm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/miniboot32/BOOTi686.nasm b/src/miniboot32/BOOTi686.nasm index 8f4c603..b7ad838 100755 --- a/src/miniboot32/BOOTi686.nasm +++ b/src/miniboot32/BOOTi686.nasm @@ -21,7 +21,7 @@ [BITS 32] [ORG 0x100000] [CPU KATMAI] -jmp short init32 +jmp short (init32 - $$) ; PI jump nop ;;; From 4218a08658b0969a63577795768f12a3d1e61104 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Mon, 7 Oct 2024 20:39:39 -0400 Subject: [PATCH 071/147] force the first jump to init in all stages to be the rel8 version --- src/mbr/mbr.nasm | 6 +++--- src/stage2/stage2.nasm | 7 ++++--- src/vbr/vbr.nasm | 9 ++++++--- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 973d1ca..de84aae 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -22,7 +22,9 @@ [ORG 0x7A00] [CPU KATMAI] [WARNING -reloc-abs-word] -jmp short init +%define __STEVIA_MBR + +jmp short (init - $$) nop ; ############### @@ -31,8 +33,6 @@ nop ; ; ############### -%define __STEVIA_MBR - %include "cdecl16.inc" %include "entry.inc" %include "config.inc" diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 337b2de..b4750d7 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -23,7 +23,10 @@ [CPU KATMAI] [WARNING -reloc-abs-word] [WARNING -reloc-abs-dword] -jmp short init +%define __STEVIA_STAGE2 + +__STAGE2_ENTRY: +jmp short (init - $$) nop ; ############### @@ -32,8 +35,6 @@ nop ; ; ############### -%define __STEVIA_STAGE2 - %include "cdecl16.inc" %include "entry.inc" %include "config.inc" diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index ba804da..9018af1 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -21,8 +21,12 @@ [ORG 0x7C00] [CPU KATMAI] [WARNING -reloc-abs-word] -jmp short init -nop +%define __STEVIA_VBR + +__ENTRY: + jmp short (init_thunk - $$) + nop + phy_bpb_start: ; fill BPB area with 0x00 since we skip writing this part to disk ; but we need it for the 'jmp short entry; nop' above @@ -36,7 +40,6 @@ times 54 db 0x00 ; Headers/Includes/Definitions ; ; ############### -%define __STEVIA_VBR %include "cdecl16.inc" %include "entry.inc" From 8301fc20a80b1816aecdfc9c1e55e4c1ea3ee98b Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Mon, 7 Oct 2024 20:41:15 -0400 Subject: [PATCH 072/147] renamed files to show code vs defs files that actually include code should be in .nasm files defines/macros/non-code should be in .inc files --- include/BIOS/{BIOS_sys.inc => BIOS_SYS.inc} | 8 ++++---- .../func/{E820_memory_map.inc => E820_memory_map.nasm} | 0 include/BIOS/func/{a20enable.inc => a20enable.nasm} | 0 include/BIOS/func/{ext_read.inc => ext_read.nasm} | 0 include/BIOS/func/{video.inc => video.nasm} | 0 include/fat32/{fat32_sys.inc => FAT32_SYS.inc} | 0 include/util/{error_func.inc => error_func.nasm} | 0 include/{kmem_func.inc => util/kmem_func.nasm} | 0 8 files changed, 4 insertions(+), 4 deletions(-) rename include/BIOS/{BIOS_sys.inc => BIOS_SYS.inc} (88%) rename include/BIOS/func/{E820_memory_map.inc => E820_memory_map.nasm} (100%) rename include/BIOS/func/{a20enable.inc => a20enable.nasm} (100%) rename include/BIOS/func/{ext_read.inc => ext_read.nasm} (100%) rename include/BIOS/func/{video.inc => video.nasm} (100%) rename include/fat32/{fat32_sys.inc => FAT32_SYS.inc} (100%) rename include/util/{error_func.inc => error_func.nasm} (100%) rename include/{kmem_func.inc => util/kmem_func.nasm} (100%) diff --git a/include/BIOS/BIOS_sys.inc b/include/BIOS/BIOS_SYS.inc similarity index 88% rename from include/BIOS/BIOS_sys.inc rename to include/BIOS/BIOS_SYS.inc index c453986..88a4842 100644 --- a/include/BIOS/BIOS_sys.inc +++ b/include/BIOS/BIOS_SYS.inc @@ -18,7 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. -%include 'BIOS/func/a20enable.inc' -%include 'BIOS/func/E820_memory_map.inc' -%include 'BIOS/func/ext_read.inc' -%include 'BIOS/func/video.inc' \ No newline at end of file +%include 'BIOS/func/a20enable.nasm' +%include 'BIOS/func/E820_memory_map.nasm' +%include 'BIOS/func/ext_read.nasm' +%include 'BIOS/func/video.nasm' \ No newline at end of file diff --git a/include/BIOS/func/E820_memory_map.inc b/include/BIOS/func/E820_memory_map.nasm similarity index 100% rename from include/BIOS/func/E820_memory_map.inc rename to include/BIOS/func/E820_memory_map.nasm diff --git a/include/BIOS/func/a20enable.inc b/include/BIOS/func/a20enable.nasm similarity index 100% rename from include/BIOS/func/a20enable.inc rename to include/BIOS/func/a20enable.nasm diff --git a/include/BIOS/func/ext_read.inc b/include/BIOS/func/ext_read.nasm similarity index 100% rename from include/BIOS/func/ext_read.inc rename to include/BIOS/func/ext_read.nasm diff --git a/include/BIOS/func/video.inc b/include/BIOS/func/video.nasm similarity index 100% rename from include/BIOS/func/video.inc rename to include/BIOS/func/video.nasm diff --git a/include/fat32/fat32_sys.inc b/include/fat32/FAT32_SYS.inc similarity index 100% rename from include/fat32/fat32_sys.inc rename to include/fat32/FAT32_SYS.inc diff --git a/include/util/error_func.inc b/include/util/error_func.nasm similarity index 100% rename from include/util/error_func.inc rename to include/util/error_func.nasm diff --git a/include/kmem_func.inc b/include/util/kmem_func.nasm similarity index 100% rename from include/kmem_func.inc rename to include/util/kmem_func.nasm From 586f3f0106ec416c132a22202b4708de0bed01c5 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 8 Oct 2024 08:53:30 -0400 Subject: [PATCH 073/147] converted error handler to a 16bit far jump optimized the early error printer a bit to save some bytes removed DEBUG_HCF macro --- include/util/error_func.nasm | 41 ++++++++++++------------------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/include/util/error_func.nasm b/include/util/error_func.nasm index d2a4901..1f9281d 100644 --- a/include/util/error_func.nasm +++ b/include/util/error_func.nasm @@ -21,16 +21,10 @@ %ifndef __INC_ERROR_FUNC %macro ERROR 1 - xor ax, ax - mov al, %1 - jmp error -%endmacro - -%macro DEBUG_HCF 0 - DEBUG_LOOP: - cli - hlt - jmp short DEBUG_LOOP + mov al, %1 ; al = 1 byte error code mapped to ascii values + db 0xEA ; jmp far imm16:imm16 + dw error ; error_far_seg + dw 0x0000 ; error_far_ptr %endmacro ; pass error as ascii character in al, errors a-zA-Z or 0-9 @@ -38,26 +32,19 @@ ALIGN 4, db 0x90 error: ; fs = 0xb800 => fs:0x0000 = 0xb8000 mov dx, 0xB800 - mov fs, dx + mov fs, dx ; F segment to 0xB800 = video memory - mov dx, STEVIA_DEBUG_OK - cmp ax, dx - jge error.debug_err - mov dh, 0x4F ; color 0x4F is white text/red background - jmp error.print -.debug_err: - mov dh, 0x5F ; debug case is white text/purple background - - ; the characters are two bytes in the order of 0xb8000: byte c, byte attribute - ; since x86 is le, we store the attribute in the MSB of dx + cmp al, STEVIA_DEBUG_OK + jge short .debug ; the 'letter >= W' (W, X, Y, Z) are used as special debug codes + mov ah, 0x4F ; color 0x4F is white text/red background + jmp short .print +.debug: + mov ah, 0x5F ; debug case is white text/purple background .print: - mov dl, al - mov word [fs:0x0000], dx - jmp error.stop - -.stop: + mov word [fs:0x0000], ax +.halt: hlt - jmp short error.stop + jmp short .halt %endif %define __INC_ERROR_FUNC \ No newline at end of file From 6ae68d1a19784752227c38753ac683f2026f30d2 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 8 Oct 2024 08:55:17 -0400 Subject: [PATCH 074/147] ensure 2 byte jmp rel8 thunk to init surpress reloc abs warnings corrected include paths/filenames --- src/mbr/mbr.nasm | 10 ++++++---- src/stage2/stage2.nasm | 14 ++++++++------ src/vbr/vbr.nasm | 13 +++++++------ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index de84aae..d02d405 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -21,7 +21,9 @@ [BITS 16] [ORG 0x7A00] [CPU KATMAI] -[WARNING -reloc-abs-word] +[WARNING -reloc-abs-byte] +[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings. + %define __STEVIA_MBR jmp short (init - $$) @@ -71,8 +73,8 @@ init: ; ; ############### -%include "kmem_func.inc" -%include "util/error_func.inc" +%include "util/kmem_func.nasm" +%include "util/error_func.nasm" ; ############### ; End Section @@ -163,7 +165,7 @@ main: ; ; ############### -%include 'BIOS/func/ext_read.inc' +%include 'BIOS/func/ext_read.nasm' ; ############### ; End Section diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index b4750d7..717279a 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -21,8 +21,10 @@ [BITS 16] [ORG 0X7E00] [CPU KATMAI] +[WARNING -reloc-abs-byte] [WARNING -reloc-abs-word] -[WARNING -reloc-abs-dword] +[WARNING -reloc-abs-dword] ; Yes, we use absolute addresses. surpress these warnings. + %define __STEVIA_STAGE2 __STAGE2_ENTRY: @@ -70,8 +72,8 @@ init: ; ; ############### -%include "kmem_func.inc" -%include "util/error_func.inc" +%include "util/kmem_func.nasm" +%include "util/error_func.nasm" ; ############### ; End Section @@ -154,7 +156,7 @@ main: ERROR STEVIA_DEBUG_HALT hcf: hlt - jmp short hcf + jmp short (hcf - $$) ; ############### ; @@ -162,7 +164,7 @@ hcf: ; ; ############### -%include 'fat32/fat32_sys.inc' +%include 'fat32/FAT32_SYS.inc' ; ############### ; @@ -170,7 +172,7 @@ hcf: ; ; ############### -%include 'BIOS/BIOS_sys.inc' +%include 'BIOS/BIOS_SYS.inc' ; ############################## ; diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 9018af1..c630f6f 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -20,13 +20,14 @@ [BITS 16] [ORG 0x7C00] [CPU KATMAI] -[WARNING -reloc-abs-word] +[WARNING -reloc-abs-byte] +[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings. %define __STEVIA_VBR __ENTRY: - jmp short (init_thunk - $$) + jmp short (init - $$) nop - + phy_bpb_start: ; fill BPB area with 0x00 since we skip writing this part to disk ; but we need it for the 'jmp short entry; nop' above @@ -75,8 +76,8 @@ init: ; ; ############### -%include "kmem_func.inc" -%include "util/error_func.inc" +%include "util/kmem_func.nasm" +%include "util/error_func.nasm" ; ############### ; End Section @@ -143,7 +144,7 @@ main: ; Required BIOS function(s) ; ############### -%include 'BIOS/func/ext_read.inc' +%include 'BIOS/func/ext_read.nasm' %assign bytes_remaining (420 - ($ - $$)) %warning VBR has bytes_remaining bytes remaining for code (MAX: 420 bytes) From 5ab7e704551586a701287811a15e5674cccfce7f Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 8 Oct 2024 09:08:47 -0400 Subject: [PATCH 075/147] Update README.md --- README.md | 120 +++++++++++++++++++++++++----------------------------- 1 file changed, 56 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 0fe19d7..27979a5 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,70 @@ -# stevia +# Stevia Bootloader -This is a hobby project that aims to create a simple and lightweight operating system. It is written in Assembly and C, and uses the GNU toolchain and Bochs emulator. +Stevia is a lightweight, hobby bootloader written in Assembly and C, designed for educational purposes. It targets x86 (Pentium III era) and aims to be simple, approachable, and understandable, focusing on minimalism and core functionality. -## Why? +## Features -I enjoy bare metal programing and I have an old Dell system with a Pentium 3, I did this mostly to learn how to write a legacy style bootloader (I am also kinda working on a UEFI bootloader/utility as well!) +### Currently Implemented + +- **Stage 1 Bootloader**: Loads from the Master Boot Record (MBR) and prepares the system for Stage 2. +- **Stage 2 Bootloader**: Loads the kernel into memory and passes control. +- **Basic Filesystem Support**: Initial filesystem recognition (details depend on implemented filesystem support). +- **Memory Map Parsing**: Detects available memory regions via BIOS interrupts. +- **GDT Initialization**: Sets up the Global Descriptor Table for protected mode. + +### In Progress + +- **Interrupt Descriptor Table (IDT) Setup**: Setting up basic interrupt handling. +- **Basic Keyboard Input**: Initial support for capturing keystrokes. + +### Planned Features + +- **Task Scheduling**: Basic round-robin task switching. +- **Filesystem Expansion**: Support for additional filesystems. +- **More Robust Driver Support**: Additional hardware drivers, such as for storage devices. ## Installation -To build and run this project, you need to have the following tools installed: +### Prerequisites -- A host system running Linux, macOS (should work 🤷‍♀️), or Windows 11 with WSL2/WSLg -- GNU Binutils -- GNU GCC -- GNU Make -- NASM -- Bochs (for testing, project might run on other virtuization/emulation platforms, I target the Pentium 3 Era with this project) +To build and run Stevia, you will need the following tools installed on your system: -To build the project, run `make` in the root directory. This will generate a floppy disk image named `stevia.img` that contains the boot loader and the kernel. +- **Assembler**: NASM for assembling bootloader components. +- **C Compiler**: GCC (cross-compiler recommended). +- **Emulator**: Bochs or QEMU for testing. +- **GNU Make**: For building the project. +- **Utilities**: + - **dd**: For creating raw disk images. + - **losetup** (Linux only): For associating loop devices with disk images. + - **sfdisk**: For creating DOS disk partitions. + - **mkfs.fat**: For formatting partitions as FAT32. + - **hdiutil** (macOS only): For attaching disk images. + - **newfs\_msdos** (macOS only): For formatting FAT32 partitions. -To run the project, run `bochs -f bochsrc.txt` in the root directory. This will launch the Bochs emulator and load the floppy disk image. You should see the boot loader message, followed by the kernel message, and then the shell prompt. +### Building and Running -To exit the emulator, press `Ctrl+C` in the terminal where you launched Bochs. +1. **Clone the repository**: + ```sh + git clone https://github.com/Nivirx/stevia.git + cd stevia + ``` +2. **Build the bootloader and create a bootable disk image**: + ```sh + sudo make + ``` +3. **Run using Bochs**: + ```sh + bochs -f bochsrc.txt + ``` -To run the project on real hardware I use a SD card to IDE interface for my test system which is a ~700Mhz P3 with 256 MB of ram. You will need to write the 'stevia.img' to the disk with 'dd'. On real hardware you may encounter issues that are not accounted for since most of the development happens on bochs, please report any issues you encounter. +## Project Goals + +Stevia is intended to be a learning tool for those interested in low-level programming, focusing on understanding the basics of how a computer starts up and manages early system resources. Contributions and forks are welcome, especially from those interested in expanding the functionality. + +## Contributing + +We welcome contributions! Feel free to open issues for bugs or feature requests, and submit pull requests for any improvements. Please ensure that your code follows the existing style and includes appropriate comments. ## License -This project is licensed under the MIT License. See the [LICENSE.md](^2^) file for details. - -### mbr/mbr.s - -This file contains the code for a Master Boot Record (MBR) that attempts to find an active partition to load. The CPU is assumed to be in 16-bit real mode at this point and the bios has loaded the 1st sector of the disk (512 bytes) to 0x0000:0x7C00. First the mbr code relocates from 0x7C00 to 0x0600 and then jumps to the entry point. the loader attempts to load the first active partition it can find and loads the vbr to 0x7c00 (512 bytes) and then jumps to 0x0000:0x7C00. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] - -### vbr/vbr.s - -This file contains the code for a Volume Boot Record (VBR) that loads the stage2 loader code from the booted disk. It reads disk sectors 1-63 into memory to STAGE2_ENTRY(defaults to 0x7E00 in config.inc) this currently allows for stevia to load up to 32KiB of code to perform bootloader duties. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] - -### stage2/stage2.s - -This file contains the code for a second-stage boot loader that loads additional modules from disk, performs some system sanity checks, and provides a simple boot interface for options/configuration. It is written in Assembly and uses BIOS interrupts to read sectors from disk.[^note] - -### miniboot32/BOOT_386.s - -This file contains the code for a 32-bit binary that can be loaded and ran with stevia as a mini demo. It is written in Assembly.[^note] - -### scripts/create-disk.sh - -This script creates a disk image file for stevia. The disk image file can be used to boot stevia on an emulator or a real machine. - -#### Requirements - -- Bash shell -- Root privileges -- dd utility -- sfdisk utility (for Linux) or hdiutil & util-linux utility (for macOS, util-linux is needed for sfdisk because hdiutil only creates hybrid disks on newer versions afaik) -- newfs_msdos utility (for macOS) -- mkfs.vfat utility (for Linux) - -#### Usage - -Run the script as root (or just allow the make script to do its business): - -```bash -sudo ./create_disk_image.sh -``` - -The script will create a disk image file named `disk.img` in the current directory. The disk image file will have the following characteristics: - -- Size: 128 MiB -- Partition table: DOS -- Partition 1: FAT32, bootable, starts at sector 2048, contains the boot32 boot test file (`BOOT_386.bin`) -- Boot code: MBR (`mbr.bin`), VBR (`vbr.bin`), stage2 (sectors 1-63) (`stage2.bin`) - -The script will also copy the necessary files from the `build` directory to the disk image file. If the files are not found, the script will exit with an error. - -[^note]: **Note:** Please note that the assembly code is strictly targeting the Pentium 3 Katmai uArch, but it might run elsewhere. Your mileage may vary. +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details. From 00daf92df584959fa7ed6178b28999323880707e Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 8 Oct 2024 20:22:21 -0400 Subject: [PATCH 076/147] unreal gdt now has 2 selectors 1 code, 1 data ss, and e/f/g segments are loaded to the same flat 4gb segment moved gdt notes to documentation --- docs/gdt.txt | 61 +++++++++++++++++ src/stage2/stage2.nasm | 152 ++++++++++++++++++----------------------- 2 files changed, 129 insertions(+), 84 deletions(-) create mode 100644 docs/gdt.txt diff --git a/docs/gdt.txt b/docs/gdt.txt new file mode 100644 index 0000000..d3da195 --- /dev/null +++ b/docs/gdt.txt @@ -0,0 +1,61 @@ +GDT documentation below: + + Pr: Present bit. This must be 1 for all valid selectors. + + Privl: Privilege, 2 bits. Contains the ring level, + 0 = highest (kernel), 3 = lowest (user applications). + + S: Descriptor type. This bit should be set for code or data segments + and should be cleared for system segments (eg. a Task State Segment) + + Ex: Executable bit. If 1 code in this segment can be executed + ie. a code selector. If 0 it is a data selector. + + DC: Direction bit/Conforming bit. + Direction bit for data selectors: Tells the direction. + 0 the segment grows up. 1 the segment grows down, ie. the offset has to be greater than the limit. + + Conforming bit for code selectors: + If 1 code in this segment can be executed from an equal or lower privilege level. + For example, code in ring 3 can far-jump to conforming code in a ring 2 segment. + The privl-bits represent the highest privilege level that is allowed to execute the segment. + For example, code in ring 0 cannot far-jump to a conforming code segment with privl==0x2 + while code in ring 2 and 3 can. Note that the privilege level remains the same + ie. a far-jump form ring 3 to a privl==2-segment remains in ring 3 after the jump. + + If 0 code in this segment can only be executed from the ring set in privl. + + RW: Readable bit/Writable bit. + Readable bit for code selectors: Whether read access for this segment is allowed. Write access is never allowed for code segments. + Writable bit for data selectors: Whether write access for this segment is allowed. Read access is always allowed for data segments. + + Ac: Accessed bit. Just set to 0. The CPU sets this to 1 when the segment is accessed. + + Gr: Granularity bit. If 0 the limit is in 1 B blocks (byte granularity), if 1 the limit is in 4 KiB blocks (page granularity). + + Sz: Size bit. If 0 the selector defines 16 bit protected mode. If 1 it defines 32 bit protected mode. + You can have both 16 bit and 32 bit selectors at once. + + AvL: Availible to software bit, the CPU does not use this field and software can read/write to it + + D/B bit: The default operand-size bit is found in code-segment and data-segment descriptors but not in system-segment descriptors. Setting + this bit to 1 indicates a 32-bit default operand size, and clearing it indicates a 16-bit default size. + + E bit: Expand down bit: Setting this bit to 1 identifies the data segment as expand-down. + In expand-down segments, the segment limit defines the lower segment boundary while the base is the upper boundary + + A GDT entry is 8 bytes and is constructed as follows: + First DWORD + 0-15 Limit 0:15 First 16 bits in the segment limiter + 16-31 Base 0:15 First 16 bits in the base address + + 2nd DWORD + + 0:7 Base 16:23 Bits 16-23 in the base address + 8:12 S/Type Segment type and attributes, S = bit 12, Type = 8:11, Type is either [1, DC, RW, Ac] or [0, E, RW, Ac] + 13:14 Privl 0 = Highest privilege (OS), 3 = Lowest privilege (User applications) + 15 Pr Set to 1 if segment is present + 16:19 Limit 16:19 Bits 16-19 in the segment limiter + 20:22 Attributes Different attributes, depending on the segment type + 23 Gr Used together with the limiter, to determine the size of the segment + 24:31 Base 24:31 The last 24-31 bits in the base address \ No newline at end of file diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 717279a..4e069d4 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -287,22 +287,50 @@ EnterUnrealMode: __CDECL16_ENTRY .func: cli ; no interrupts - push ds ; save real mode data selector + push ds ; save real mode data/stack selectors + push es + push fs + push gs + push ss + + push cs ; save real mode code selector lgdt [unreal_gdt_info] - mov eax, cr0 ; switch to pmode + mov eax, cr0 ; switch to pmode or al,1 ; set pmode bit - mov cr0, eax - - jmp $+2 ; clear instruction cache - - mov bx, 0x08 ; select descriptor 1 - mov ds, bx ; 8h = 1000b + mov cr0, eax + jmp $+2 + ;jmp far 0x0008:EnterUnrealMode.load_cs + db 0xEA ; jmp far imm16:imm16 + dw EnterUnrealMode.load_cs ; error_far_ptr + dw 0x0008 ; error_far_seg +.load_cs: + mov bx, 0x10 ; select descriptor 2 + mov ds, bx ; 10h = 0001_0000b + + mov ss, bx + mov es, bx + mov fs, bx + mov gs, bx ; other data/stack to desc. 2 + and al,0xFE ; back to realmode - mov cr0, eax ; by toggling bit again + mov cr0, eax ; by toggling bit again + jmp $+2 - pop ds ; get back old segment + pop ax ; save cs to ax to setup far jump + mov word [ds:__UNREAL_SEGMENT], ax + ;jmp far 0x0008:EnterUnrealMode.unload_cs + db 0xEA ; jmp far imm16:imm16 + dw EnterUnrealMode.unload_cs ; error_far_ptr +__UNREAL_SEGMENT: + dw 0x0000 ; error_far_seg +EnterUnrealMode.unload_cs: + pop ss + pop gs + pop fs + pop es + pop ds ; get back old segments sti .endp: __CDECL16_EXIT @@ -339,71 +367,7 @@ stage2_resb_1: partition_offset_ptr: dw 0x0000 -; GDT documentation below: -; -; Pr: Present bit. This must be 1 for all valid selectors. -; -; Privl: Privilege, 2 bits. Contains the ring level, -; 0 = highest (kernel), 3 = lowest (user applications). -; -; S: Descriptor type. This bit should be set for code or data segments -; and should be cleared for system segments (eg. a Task State Segment) -; -; Ex: Executable bit. If 1 code in this segment can be executed -; ie. a code selector. If 0 it is a data selector. -; -; DC: Direction bit/Conforming bit. -; Direction bit for data selectors: Tells the direction. -; 0 the segment grows up. 1 the segment grows down, ie. the offset has to be greater than the limit. -; -; Conforming bit for code selectors: -; If 1 code in this segment can be executed from an equal or lower privilege level. -; For example, code in ring 3 can far-jump to conforming code in a ring 2 segment. -; The privl-bits represent the highest privilege level that is allowed to execute the segment. -; For example, code in ring 0 cannot far-jump to a conforming code segment with privl==0x2 -; while code in ring 2 and 3 can. Note that the privilege level remains the same -; ie. a far-jump form ring 3 to a privl==2-segment remains in ring 3 after the jump. -; -; If 0 code in this segment can only be executed from the ring set in privl. -; -; RW: Readable bit/Writable bit. -; Readable bit for code selectors: Whether read access for this segment is allowed. Write access is never allowed for code segments. -; Writable bit for data selectors: Whether write access for this segment is allowed. Read access is always allowed for data segments. -; -; Ac: Accessed bit. Just set to 0. The CPU sets this to 1 when the segment is accessed. -; -; Gr: Granularity bit. If 0 the limit is in 1 B blocks (byte granularity), if 1 the limit is in 4 KiB blocks (page granularity). -; -; Sz: Size bit. If 0 the selector defines 16 bit protected mode. If 1 it defines 32 bit protected mode. -; You can have both 16 bit and 32 bit selectors at once. -; -; AvL: Availible to software bit, the CPU does not use this field and software can read/write to it -; -; D/B bit: The default operand-size bit is found in code-segment and data-segment descriptors but not in system-segment descriptors. Setting -; this bit to 1 indicates a 32-bit default operand size, and clearing it indicates a 16-bit default size. -; -; E bit: Expand down bit: Setting this bit to 1 identifies the data segment as expand-down. -; In expand-down segments, the segment limit defines the lower segment boundary while the base is the upper boundary -; -; A GDT entry is 8 bytes and is constructed as follows: -; First DWORD -; 0-15 Limit 0:15 First 16 bits in the segment limiter -; 16-31 Base 0:15 First 16 bits in the base address -; -; 2nd DWORD -; -; 0:7 Base 16:23 Bits 16-23 in the base address -; 8:12 S/Type Segment type and attributes, S = bit 12, Type = 8:11, Type is either [1, DC, RW, Ac] or [0, E, RW, Ac] -; 13:14 Privl 0 = Highest privilege (OS), 3 = Lowest privilege (User applications) -; 15 Pr Set to 1 if segment is present -; 16:19 Limit 16:19 Bits 16-19 in the segment limiter -; 20:22 Attributes Different attributes, depending on the segment type -; 23 Gr Used together with the limiter, to determine the size of the segment -; 24:31 Base 24:31 The last 24-31 bits in the base address -; -; -; - +; see docs/gdt.txt for a quick refresher on GDT ALIGN 4, db 0 unreal_gdt_info: unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1 @@ -413,11 +377,17 @@ unreal_gdt_start: ; entry 0 dq 0 ; first entry is null - ; entry 1 (4 GiB flat data map) - ; first dword + ; entry 1 (4 GiB flat code map) + dw 0xFFFF ; Segment Limit 15:0 (Same large limit as data segment) + dw 0x0000 ; Base Address 15:0 + db 0x00 ; Base Address 23:16 + db 1001_1010b ; Access Byte: 1001_1010b for executable code + db 1000_1111b ; Flags and Segment Limit 19:16 (Same as data segment) + db 0x00 ; Base Address 31:24 + + ; entry 2 (4 GiB flat data map) dw 0xFFFF ; 0:15 limit dw 0x0000 ; 0:15 base - ; second dword db 0x00 ; 16:23 base db 1001_0010b ; bit 0:4 = S/Type, [1, DC, RW, Ac] or [0, E, RW, Ac] ; bit 5:6 = Privl @@ -441,7 +411,7 @@ unreal_gdt_start: ; Pr = 1, segment is present ; AVL = 0, ignore this field ; D/B bit = 0, 16bit code/stack - ; Gr = 1, multiply limit by 4096 + ; Gr = 1, multiply limit by 4096 unreal_gdt_end: ALIGN 4, db 0 @@ -453,18 +423,32 @@ gdt32_info: gdt32_start: dq 0 .gdt32_code: + dw 0xFFFF ; code segment (RX) + dw 0x0000 + db 0x00 + db 1001_1000b ; Access: readable, executable + db 1100_1111b ; 4KB granularity, 32-bit + db 0x00 + .gdt32_data: ; data segment (RW) dw 0xFFFF dw 0x0000 db 0x00 - db 1001_1000b - db 1100_1111b + db 1001_0010b ; Access: readable, writable + db 1100_1111b ; 4KB granularity, 32-bit db 0x00 - .gdt32_data: + .gdt32_stack: ; Stack segment (RW) dw 0xFFFF dw 0x0000 db 0x00 - db 1001_0010b - db 1100_1111b + db 1001_0010b ; Access: readable, writable + db 1100_1111b ; 4KB granularity, 32-bit + db 0x00 + .gdt32_ro_data: ; Read-only data segment (RO) + dw 0xFFFF + dw 0x0000 + db 0x00 + db 1001_0000b ; Access: readable, not writable + db 1100_1111b ; 4KB granularity, 32-bit db 0x00 gdt32_end: From 75c046f9cd8ae207ff34e7929f774af6809726b4 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 8 Oct 2024 20:23:16 -0400 Subject: [PATCH 077/147] use gs for vesa framebuffer (was fs) --- include/util/error_func.nasm | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/include/util/error_func.nasm b/include/util/error_func.nasm index 1f9281d..6c2aa92 100644 --- a/include/util/error_func.nasm +++ b/include/util/error_func.nasm @@ -30,10 +30,6 @@ ; pass error as ascii character in al, errors a-zA-Z or 0-9 ALIGN 4, db 0x90 error: - ; fs = 0xb800 => fs:0x0000 = 0xb8000 - mov dx, 0xB800 - mov fs, dx ; F segment to 0xB800 = video memory - cmp al, STEVIA_DEBUG_OK jge short .debug ; the 'letter >= W' (W, X, Y, Z) are used as special debug codes mov ah, 0x4F ; color 0x4F is white text/red background @@ -41,8 +37,11 @@ error: .debug: mov ah, 0x5F ; debug case is white text/purple background .print: - mov word [fs:0x0000], ax + mov dx, 0xB800 + mov gs, dx + mov word [gs:0x0000], ax ; 0xB8000 = video memory .halt: + cli hlt jmp short .halt From d684d4f11f59e62a2c850f4d725d51c582063ba7 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 11:31:38 -0400 Subject: [PATCH 078/147] more error handling for dd writes --- scripts/create-disk.sh | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index 59aa6fd..0310811 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -66,20 +66,39 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then mkfs.fat -v -F32 -n 'STEVIAFS' $firstpart # copy MBR while preserving partition table - dd if=$mbr_file of=$ld bs=1 count=440 + if ! dd if=$mbr_file of=$ld bs=1 count=440; then + echo "Failed to write MBR to disk. (part 1)" >&2 + exit 1 + fi + # copy MBR 0xAA55 - dd if=$mbr_file of=$ld bs=1 seek=510 skip=510 count=2 + if ! dd if=$mbr_file of=$ld bs=1 seek=510 skip=510 count=2; then + echo "Failed to write MBR to disk. (part 2)" >&2 + exit 1 + fi # copy VBR to partition 1 while preserving partition information # copy jmp short entry; nop - dd if=$vbr_file of=$firstpart bs=1 count=3 + if ! dd if=$vbr_file of=$firstpart bs=1 count=3; then + echo "Failed to write VBR to disk. (part 1)" >&2 + exit 1 + fi # copy bootcode - dd if=$vbr_file of=$firstpart bs=1 seek=90 skip=90 count=420 + if ! dd if=$vbr_file of=$firstpart bs=1 seek=90 skip=90 count=420; then + echo "Failed to write VBR to disk. (part 2)" >&2 + exit 1 + fi # copy 0xAA55 - dd if=$vbr_file of=$firstpart bs=1 seek=510 skip=510 count=2 + if ! dd if=$vbr_file of=$firstpart bs=1 seek=510 skip=510 count=2; then + echo "Failed to write VBR to disk. (part 3)" >&2 + exit 1 + fi #stage2 to sectors 1-64 - dd if=$stage2_file of=$ld bs=$disk_sector_size seek=1 + if ! dd if=$stage2_file of=$ld bs=$disk_sector_size seek=1; then + echo "Failed to write Stage2 to disk." >&2 + exit 1 + fi # copy boot32 boot test file to disk image if ! [ -e $mount_point ]; then From a3a768adf4c1eeda96740c36b3627f966c7266af Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 11:44:04 -0400 Subject: [PATCH 079/147] more error handling in detecting disk image creation will need ported to macOS sometime --- scripts/create-disk.sh | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index 0310811..2d1928b 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -21,7 +21,7 @@ # SOFTWARE. if ! [ $(id -u) = 0 ]; then - echo "Script must be run as root!" + echo "Script must be run as root!" >&2 exit 1 fi @@ -43,12 +43,18 @@ disk_sector_size=512 if ! [ -e $disk_tmp_file ]; then # create raw disk image - dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size + if ! dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size; then + echo "Failed creating blank disk image." >&2 + exit 1 + fi sync else echo "Removing old disk image..." rm -rfv $disk_tmp_file - dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size + if ! dd if=/dev/zero of=$disk_tmp_file bs=$disk_sector_size count=$disk_size; then + echo "Failed creating blank disk image." >&2 + exit 1 + fi sync fi @@ -105,12 +111,19 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then mkdir $mount_point fi mount $firstpart $mount_point - mkdir -p $mount_point + + # ensure mountpoint is actually a mountpoint + if ! mountpoint -q $mount_point; then + echo "Failed to mount partition at $mount_point." >&2 + exit 1 + fi + + # copy kernel to filesystem if [ -e $boottest_file ]; then cp -v $boottest_file $mount_point/BOOTI686.BIN else - echo "unable to find boot32.bin!" - exit 3 + echo "Failed to write $boottest_file to disk image" >&2 + exit 1 fi # detach loop device @@ -126,8 +139,8 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then chown --from=root:root --reference=LICENSE.md $disk_tmp_file else - echo "unable to find MBR/VBR binaries!" - exit 2 + echo "unable to find MBR/VBR binaries!" >&2 + exit 1 fi # requires util-linux from homebrew elif [[ "$OSTYPE" == "darwin"* ]]; then From aff631f3db2c1ed847070dba016ec0c114cde423 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 12:04:44 -0400 Subject: [PATCH 080/147] force 1-1 logical to physical sectors copy our VBR code to backup VBR --- scripts/create-disk.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index 2d1928b..3d97aa5 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -69,7 +69,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then # get first partition, this is sloppy might need to review this... firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}') - mkfs.fat -v -F32 -n 'STEVIAFS' $firstpart + mkfs.fat -v -F32 -s 1 -n 'STEVIAFS' $firstpart # copy MBR while preserving partition table if ! dd if=$mbr_file of=$ld bs=1 count=440; then @@ -100,6 +100,12 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then exit 1 fi + # write backup VBR + if ! dd if=$firstpart of=$firstpart bs=$disk_sector_size count=1 seek=6; then + echo "Failed to copy VBR (sector 1) to backup VBR." >&2 + exit 1 + fi + #stage2 to sectors 1-64 if ! dd if=$stage2_file of=$ld bs=$disk_sector_size seek=1; then echo "Failed to write Stage2 to disk." >&2 From 0aae0616fdeb6ccd9071bc5c08b00c03db672b72 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 12:08:09 -0400 Subject: [PATCH 081/147] more comments to seperate setups --- scripts/create-disk.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index 3d97aa5..f1aba13 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -71,6 +71,10 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then firstpart=$(lsblk -ilp -o NAME $ld | tr '\n' ' ' | awk '{print $3}') mkfs.fat -v -F32 -s 1 -n 'STEVIAFS' $firstpart + # + # MBR setup + # + # copy MBR while preserving partition table if ! dd if=$mbr_file of=$ld bs=1 count=440; then echo "Failed to write MBR to disk. (part 1)" >&2 @@ -83,6 +87,10 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then exit 1 fi + # + # VBR Setup & backup VBR + # + # copy VBR to partition 1 while preserving partition information # copy jmp short entry; nop if ! dd if=$vbr_file of=$firstpart bs=1 count=3; then @@ -106,6 +114,11 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then exit 1 fi + + # + # Stage2 Setup + # + #stage2 to sectors 1-64 if ! dd if=$stage2_file of=$ld bs=$disk_sector_size seek=1; then echo "Failed to write Stage2 to disk." >&2 @@ -132,6 +145,10 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then exit 1 fi + # + # Final Cleanup + # + # detach loop device umount $mount_point sync From 056551fdd1f54d146dffaa8ec0bdf9b72ab22720 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 12:16:01 -0400 Subject: [PATCH 082/147] rename file to BOOT.BIN K.I.S.S. --- scripts/create-disk.sh | 2 +- src/stage2/stage2.nasm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/create-disk.sh b/scripts/create-disk.sh index f1aba13..b16eb71 100755 --- a/scripts/create-disk.sh +++ b/scripts/create-disk.sh @@ -139,7 +139,7 @@ if [[ "$OSTYPE" == "linux-gnu"* ]]; then # copy kernel to filesystem if [ -e $boottest_file ]; then - cp -v $boottest_file $mount_point/BOOTI686.BIN + cp -v $boottest_file $mount_point/BOOT.BIN else echo "Failed to write $boottest_file to disk image" >&2 exit 1 diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 4e069d4..e755639 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -359,7 +359,7 @@ IntToHex_table: NewLine_cstr: db StrCRLF_NUL BootTarget_str: - db "BOOTI686BIN" + db "BOOT BIN" boot_drive_ptr: db 0x00 stage2_resb_1: From 07197b0d5b3a1aadd78f761a231745dfe9668017 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 12:59:36 -0400 Subject: [PATCH 083/147] reduce proceedure local storage to 16 bytes --- include/cdecl16.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cdecl16.inc b/include/cdecl16.inc index 13bdc50..81477e8 100644 --- a/include/cdecl16.inc +++ b/include/cdecl16.inc @@ -21,7 +21,7 @@ %macro __CDECL16_ENTRY 0 push bp mov bp, sp - sub sp, 0x20 + sub sp, 0x10 push si push di From 4af0637c7ff61f1a9fb96ea4f2822ce45a008ec7 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 13:00:45 -0400 Subject: [PATCH 084/147] use kmemset to 0 out fat32_state in InitFATDriver --- include/fat32/FAT32_SYS.inc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 60f155a..70d91ac 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -28,11 +28,14 @@ ALIGN 4, db 0x90 InitFATDriver: __CDECL16_ENTRY .func: - xor eax, eax - mov dword [fat32_state + FAT32_State_t.active_cluster_32], eax - mov dword [fat32_state + FAT32_State_t.active_FAT_cluster_32], eax - mov dword [fat32_state + FAT32_State_t.first_root_dir_sector_32], eax - mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax + mov ax, fat32_state_SIZE + push ax ; length of fat32_state structure + xor ax, ax + push ax ; init fat32_state with zero + mov ax, fat32_state + push ax ; address of structure + call kmemset + sub sp, 0x6 .calc_active_part: mov bx, [partition_offset_ptr] From 802d47fbf78643c241b98f1ad6be07e2a4cb3970 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 13:09:17 -0400 Subject: [PATCH 085/147] fix passing stage2 wrong data for boot drive --- src/stage2/stage2.nasm | 4 +--- src/vbr/vbr.nasm | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index e755639..fb59ec1 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -361,9 +361,7 @@ NewLine_cstr: BootTarget_str: db "BOOT BIN" boot_drive_ptr: - db 0x00 -stage2_resb_1: - db 0x00 + dw 0x0000 partition_offset_ptr: dw 0x0000 diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index c630f6f..95101a3 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -136,8 +136,8 @@ main: ERROR VBR_ERROR_NO_SIGNATURE ; no signature present in stage2 .sig_ok: - mov si, [bp - 4] - mov dx, [bp - 2] + mov si, word [bp - 4] + mov dl, byte [bp - 2] jmp 0:0x7E00 ; ############### From 71f13fd6b5cbb9c99f76703cbe653feb575c821d Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 14:25:01 -0400 Subject: [PATCH 086/147] somewhat of a cludge, but added a macro to save all caller saved regs --- include/cdecl16.inc | 16 ++++++++++++++++ include/fat32/FAT32_SYS.inc | 24 +++++++++++++++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/include/cdecl16.inc b/include/cdecl16.inc index 81477e8..60583ad 100644 --- a/include/cdecl16.inc +++ b/include/cdecl16.inc @@ -38,4 +38,20 @@ mov sp, bp pop bp %endmacro +%endif + +%ifnmacro __CDECL16_CALLER_SAVE +%macro __CDECL16_CALLER_SAVE 0 + push ax + push cx + push dx +%endmacro +%endif + +%ifnmacro __CDECL16_CALLER_RESTORE +%macro __CDECL16_CALLER_RESTORE 0 + pop dx + pop cx + pop ax +%endmacro %endif \ No newline at end of file diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 70d91ac..902d887 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -91,6 +91,8 @@ SearchFATDIR: mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32] mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax + __CDECL16_CALLER_SAVE + push dword eax ; cluster lea ax, [dir_buffer] push ax ; offset @@ -99,16 +101,20 @@ SearchFATDIR: call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) add sp, 0x8 + __CDECL16_CALLER_RESTORE + lea si, [dir_buffer] jmp SearchFATDIR.empty_dir_entry .load_next_dir: ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad + __CDECL16_CALLER_SAVE mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] push dword eax call NextCluster ; uint32_t NextCluster(uint32_t active_cluster); add sp, 0x4 + __CDECL16_CALLER_RESTORE cmp eax, 0x0fff_fff7 jb SearchFATDIR.load_next_dir_next_OK @@ -116,15 +122,18 @@ SearchFATDIR: .load_next_dir_next_OK: ; load 512 bytes of directory entries from data sector + __CDECL16_CALLER_SAVE mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32] + push dword eax ; cluster - push dword eax - lea ax, [dir_buffer] ; cluster + lea ax, [dir_buffer] push ax ; offset + xor ax, ax push ax ; segment call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) sub sp, 0x8 + __CDECL16_CALLER_RESTORE lea si, [dir_buffer] .empty_dir_entry: @@ -181,7 +190,7 @@ SearchFATDIR: .endp: __CDECL16_EXIT ret - +; BUG: this function needs review ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad @@ -232,6 +241,7 @@ NextCluster: add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: + __CDECL16_CALLER_SAVE movzx ax, [bp - 2] push ax @@ -249,6 +259,7 @@ NextCluster: push ax call read_disk_raw add sp, 0xC + __CDECL16_CALLER_RESTORE ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint32_t lba, ; uint16_t count, uint16_t drive_num) @@ -281,6 +292,7 @@ ALIGN 4, db 0x90 ReadFATCluster: __CDECL16_ENTRY .func: + __CDECL16_CALLER_SAVE mov bx, [boot_drive_ptr] mov ax, [bx + 0] mov byte [bp - 2], al ; save boot drive as a local for easy access @@ -290,7 +302,9 @@ ReadFATCluster: call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster) add sp, 0x4 ; eax == LBA mov dword [bp - 6], eax + __CDECL16_CALLER_RESTORE + __CDECL16_CALLER_SAVE movzx ax, [bp - 2] push ax @@ -305,8 +319,12 @@ ReadFATCluster: xor ax, ax push ax +; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, +; uint32_t lba, +; uint16_t count, uint16_t drive_num) call read_disk_raw add sp, 0xC + __CDECL16_CALLER_RESTORE .endp: __CDECL16_EXIT ret From 095822fa27e64a31e908cd59ba9987e791465aef Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 15:55:24 -0400 Subject: [PATCH 087/147] inlined ClusterToLBA removed caller save kludge for now init first_root_dir_sector from ebpb data --- include/fat32/FAT32_SYS.inc | 63 +++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 902d887..5a0144c 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -66,7 +66,10 @@ InitFATDriver: mov dword [fat32_state + FAT32_State_t.first_data_sector_32], eax .get_first_root_dir: - ; TODO + mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32] + mov dword [fat32_state + FAT32_State_t.first_root_dir_sector_32], eax ; this only works when 1 cluster = 1 sector + mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax + jmp InitFATDriver.endp .error: ERROR STAGE2_FAT32_INIT_ERROR @@ -88,11 +91,7 @@ SearchFATDIR: __CDECL16_ENTRY .file_lookup: .load_first_dir: - mov eax, [fat32_ebpb + FAT32_ebpb_t.root_dir_cluster_32] - mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax - - __CDECL16_CALLER_SAVE - + mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] push dword eax ; cluster lea ax, [dir_buffer] push ax ; offset @@ -101,20 +100,17 @@ SearchFATDIR: call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) add sp, 0x8 - __CDECL16_CALLER_RESTORE - lea si, [dir_buffer] jmp SearchFATDIR.empty_dir_entry .load_next_dir: ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad - __CDECL16_CALLER_SAVE + mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] push dword eax call NextCluster ; uint32_t NextCluster(uint32_t active_cluster); add sp, 0x4 - __CDECL16_CALLER_RESTORE cmp eax, 0x0fff_fff7 jb SearchFATDIR.load_next_dir_next_OK @@ -122,7 +118,6 @@ SearchFATDIR: .load_next_dir_next_OK: ; load 512 bytes of directory entries from data sector - __CDECL16_CALLER_SAVE mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32] push dword eax ; cluster @@ -133,7 +128,6 @@ SearchFATDIR: push ax ; segment call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) sub sp, 0x8 - __CDECL16_CALLER_RESTORE lea si, [dir_buffer] .empty_dir_entry: @@ -191,6 +185,8 @@ SearchFATDIR: __CDECL16_EXIT ret ; BUG: this function needs review +; +; bp - 2 - byte boot_drive ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad @@ -199,12 +195,12 @@ NextCluster: __CDECL16_ENTRY .func: mov bx, [boot_drive_ptr] - mov ax, [bx + 0] - mov bx, ax - movzx ax, byte [bx + 0] ; 67h override would probably work but this is the 16bit way to do it - mov byte [bp - 2], al ; save boot drive as a local for easy access + movzx ax, byte [bx + 0] + mov byte [bp - 2], al ; save boot drive as a local for easy access + ;movzx ax, byte [bx + 0] ; 67h override would probably work but this is the 16bit way to do it + ;mov byte [bp - 2], al ; save boot drive as a local for easy access - mov dword edx, [bp + 4] + mov edx, dword [bp + 4] mov si, fat32_nc_data .calc_offset: ; fat_offset = active_cluster * 4 @@ -241,7 +237,6 @@ NextCluster: add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: - __CDECL16_CALLER_SAVE movzx ax, [bp - 2] push ax @@ -259,7 +254,6 @@ NextCluster: push ax call read_disk_raw add sp, 0xC - __CDECL16_CALLER_RESTORE ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint32_t lba, ; uint16_t count, uint16_t drive_num) @@ -287,44 +281,45 @@ ClusterToLBA: __CDECL16_EXIT ret +; bp - 6 - dword lba +; bp - 2 - byte boot_drive ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) ALIGN 4, db 0x90 ReadFATCluster: __CDECL16_ENTRY -.func: - __CDECL16_CALLER_SAVE +.func: mov bx, [boot_drive_ptr] - mov ax, [bx + 0] + movzx ax, byte [bx + 0] mov byte [bp - 2], al ; save boot drive as a local for easy access mov dword eax, [bp + 8] - push dword eax - call ClusterToLBA ; uint32_t ClusterToLBA(uint32_t cluster) - add sp, 0x4 ; eax == LBA - mov dword [bp - 6], eax - __CDECL16_CALLER_RESTORE + ; inline ClusterToLBA + sub eax, 2 + movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8] + mul edx + add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32] + ; eax contains the LBA now + mov dword [bp - 6], eax ; save lba - __CDECL16_CALLER_SAVE - movzx ax, [bp - 2] + movzx ax, byte [bp - 2] ; drive_num = boot_drive push ax - mov ax, 0x1 + mov ax, 0x1 ; count = 1 push ax - mov eax, dword [bp + 6] + mov eax, dword [bp - 6] ; lba = ClusterToLBA return value push dword eax - mov ax, fat_buffer + mov ax, fat_buffer ; offset = fat_buffer (in mem.inc) push ax - xor ax, ax + xor ax, ax ; segment = 0x0000, our buffer is in the first 64 KiB push ax ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint32_t lba, ; uint16_t count, uint16_t drive_num) call read_disk_raw add sp, 0xC - __CDECL16_CALLER_RESTORE .endp: __CDECL16_EXIT ret From 086cf9d8ea96b22493cdd0e8a87aedf322b06fec Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 16:52:57 -0400 Subject: [PATCH 088/147] correct src size in op --- include/fat32/FAT32_SYS.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 5a0144c..9c8d01b 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -237,7 +237,7 @@ NextCluster: add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: - movzx ax, [bp - 2] + movzx ax, byte [bp - 2] push ax mov ax, 0x1 From 208729ed01a4075a209bbab5497dc46f0b4d2800 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 17:20:53 -0400 Subject: [PATCH 089/147] split e820 bios call documentation to its own file under docs/ --- docs/e820_usage.txt | 78 +++++++++++++++++++++++++ include/BIOS/func/E820_memory_map.nasm | 79 -------------------------- 2 files changed, 78 insertions(+), 79 deletions(-) create mode 100644 docs/e820_usage.txt diff --git a/docs/e820_usage.txt b/docs/e820_usage.txt new file mode 100644 index 0000000..200bf83 --- /dev/null +++ b/docs/e820_usage.txt @@ -0,0 +1,78 @@ +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; Input: +; +; EAX Function Code E820h +; EBX Continuation Contains the "continuation value" to get the +; next run of physical memory. This is the +; value returned by a previous call to this +; routine. If this is the first call, EBX +; must contain zero. +; ES:DI Buffer Pointer Pointer to an Address Range Descriptor +; structure which the BIOS is to fill in. +; ECX Buffer Size The length in bytes of the structure passed +; to the BIOS. The BIOS will fill in at most +; ECX bytes of the structure or however much +; of the structure the BIOS implements. The +; minimum size which must be supported by both +; the BIOS and the caller is 20 bytes. Future +; implementations may extend this structure. +; EDX Signature 'SMAP' - Used by the BIOS to verify the +; caller is requesting the system map +; information to be returned in ES:DI. +; +; Output: +; +; CF Carry Flag Non-Carry - indicates no error +; EAX Signature 'SMAP' - Signature to verify correct BIOS +; revision. +; ES:DI Buffer Pointer Returned Address Range Descriptor pointer. +; Same value as on input. +; ECX Buffer Size Number of bytes returned by the BIOS in the +; address range descriptor. The minimum size +; structure returned by the BIOS is 20 bytes. +; EBX Continuation Contains the continuation value to get the +; next address descriptor. The actual +; significance of the continuation value is up +; to the discretion of the BIOS. The caller +; must pass the continuation value unchanged +; as input to the next iteration of the E820 +; call in order to get the next Address Range +; Descriptor. A return value of zero means that +; this is the last descriptor +; +; Address Range Descriptor Structure +; +; Offset in Bytes Name Description +; 0 BaseAddrLow Low 32 Bits of Base Address +; 4 BaseAddrHigh High 32 Bits of Base Address +; 8 LengthLow Low 32 Bits of Length in Bytes +; 12 LengthHigh High 32 Bits of Length in Bytes +; 16 Type Address type of this range. +; +; The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. +; The BaseAddress is the physical address of the start of the range being specified. +; +; The LengthLow and LengthHigh together are the 64 bit Length of this range. +; The Length is the physical contiguous length in bytes of a range being specified. +; +; The Type field describes the usage of the described address range as defined in the table below. + +; Value Pneumonic Description +; 1 AddressRangeMemory This run is available RAM usable by the operating system. +; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. +; Other Undefined Undefined - Reserved for future use. \ No newline at end of file diff --git a/include/BIOS/func/E820_memory_map.nasm b/include/BIOS/func/E820_memory_map.nasm index 3447a47..6752bf3 100644 --- a/include/BIOS/func/E820_memory_map.nasm +++ b/include/BIOS/func/E820_memory_map.nasm @@ -20,85 +20,6 @@ %ifndef __INC_E820MEMORY_MAP -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; Input: -; -; EAX Function Code E820h -; EBX Continuation Contains the "continuation value" to get the -; next run of physical memory. This is the -; value returned by a previous call to this -; routine. If this is the first call, EBX -; must contain zero. -; ES:DI Buffer Pointer Pointer to an Address Range Descriptor -; structure which the BIOS is to fill in. -; ECX Buffer Size The length in bytes of the structure passed -; to the BIOS. The BIOS will fill in at most -; ECX bytes of the structure or however much -; of the structure the BIOS implements. The -; minimum size which must be supported by both -; the BIOS and the caller is 20 bytes. Future -; implementations may extend this structure. -; EDX Signature 'SMAP' - Used by the BIOS to verify the -; caller is requesting the system map -; information to be returned in ES:DI. -; -; Output: -; -; CF Carry Flag Non-Carry - indicates no error -; EAX Signature 'SMAP' - Signature to verify correct BIOS -; revision. -; ES:DI Buffer Pointer Returned Address Range Descriptor pointer. -; Same value as on input. -; ECX Buffer Size Number of bytes returned by the BIOS in the -; address range descriptor. The minimum size -; structure returned by the BIOS is 20 bytes. -; EBX Continuation Contains the continuation value to get the -; next address descriptor. The actual -; significance of the continuation value is up -; to the discretion of the BIOS. The caller -; must pass the continuation value unchanged -; as input to the next iteration of the E820 -; call in order to get the next Address Range -; Descriptor. A return value of zero means that -; this is the last descriptor -; -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; -; The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. -; The BaseAddress is the physical address of the start of the range being specified. -; -; The LengthLow and LengthHigh together are the 64 bit Length of this range. -; The Length is the physical contiguous length in bytes of a range being specified. -; -; The Type field describes the usage of the described address range as defined in the table below. - -; Value Pneumonic Description -; 1 AddressRangeMemory This run is available RAM usable by the operating system. -; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. -; Other Undefined Undefined - Reserved for future use. - ; Address Range Descriptor Structure ; ; Offset in Bytes Name Description From e5fb1b41eb218058618966a299d433517b364a2a Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 19:03:27 -0400 Subject: [PATCH 090/147] added bochs debug wrappers --- include/util/bochs_magic.inc | 65 ++++++++++++++++++++++++++++++++++++ src/mbr/mbr.nasm | 1 + src/vbr/vbr.nasm | 1 + 3 files changed, 67 insertions(+) create mode 100644 include/util/bochs_magic.inc diff --git a/include/util/bochs_magic.inc b/include/util/bochs_magic.inc new file mode 100644 index 0000000..55b23fd --- /dev/null +++ b/include/util/bochs_magic.inc @@ -0,0 +1,65 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +%ifndef __INC_BOCHS_DEBUG_MAGIC + +; +; port_e9_hack: enabled=1 needs to be set in bochsrc.txt/bxrc +; +%ifnmacro __BOCHS_PRINTC + %macro __BOCHS_PRINTC 1 + mov al, %1 + out 0xe9, byte al + %endmacro +%endif + +; +; port_e9_hack: enabled=1 needs to be set in bochsrc.txt/bxrc +; +%ifnmacro __BOCHS_BREAK + %macro __BOCHS_BREAK 0 + push ax + mov ax, 0x8A00 + out 0x8A00, word ax + pop ax + %endmacro +%endif + +; +; magic_break: enabled=1 needs to be set in bochsrc.txt/bxrc +; +%ifnmacro __BOCHS_MAGIC_DEBUG + %macro __BOCHS_MAGIC_DEBUG 0 + xchg bx, bx + %endmacro +%endif + +%ifnmacro PRINT_FUNC_LABEL + %macro PRINT_FUNC_LABEL 1 + %define label %1 + %assign addr label + %ifnctx __OUTPUT__ + __OUTPUT__ "Entry point for '%1' = %d", addr + %endif + %endmacro +%endif + +%define __INC_BOCHS_DEBUG_MAGIC +%endif \ No newline at end of file diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index d02d405..4afe7a5 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -35,6 +35,7 @@ nop ; ; ############### +%include "util/bochs_magic.inc" %include "cdecl16.inc" %include "entry.inc" %include "config.inc" diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 95101a3..377ba3c 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -42,6 +42,7 @@ times 54 db 0x00 ; ; ############### +%include "util/bochs_magic.inc" %include "cdecl16.inc" %include "entry.inc" %include "config.inc" From 48cd0f742d60059ebfc5d02eb7b66f1a439b93c1 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 19:05:15 -0400 Subject: [PATCH 091/147] added macros to define cstr and str aligned all the entry points for proceedures to 4 bytes added a PrintString wraper macro --- src/stage2/stage2.nasm | 125 +++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 56 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index fb59ec1..998699b 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -37,6 +37,7 @@ nop ; ; ############### +%include "util/bochs_magic.inc" %include "cdecl16.inc" %include "entry.inc" %include "config.inc" @@ -82,78 +83,53 @@ init: ; ; bp - 2 : uint8_t boot_drive ; bp - 4 : uint16_t part_offset -; +ALIGN 4, db 0x90 main: lea ax, [bp - 2] mov [boot_drive_ptr], ax lea ax, [bp - 4] - mov [partition_offset_ptr], ax + mov [partition_offset_ptr], ax ; setup pointers to boot_drive and partition offset on stack + mov byte [bp - 2], dl ; boot_drive (probably 0x80) mov word [bp - 4], si ; partition_offset mov eax, dword [STAGE2_SIG] cmp eax, 0xDEADBEEF je main.signature_present - ERROR STAGE2_SIGNATURE_MISSING .signature_present: call SetTextMode call disable_cursor - - lea ax, [HelloPrompt_cstr] - push ax - call PrintString - add sp, 0x2 - + __PRINT_CSTR HelloPrompt + ; enable A20 gate call EnableA20 - - lea ax, [A20_Enabled_cstr] - push ax - call PrintString - add sp, 0x2 + __PRINT_CSTR A20_Enabled ; enter unreal mode call EnterUnrealMode - - lea ax, [UnrealMode_OK_cstr] - push ax - call PrintString - add sp, 0x2 + __PRINT_CSTR UnrealMode_OK ; get system memory map call GetMemoryMap - - lea ax, [MemoryMap_OK_cstr] - push ax - call PrintString - add sp, 0x2 + __PRINT_CSTR MemoryMap_OK ; FAT Driver setup call InitFATDriver + __PRINT_CSTR InitFATSYS_OK ; ; Find first cluster of bootable file ; call SearchFATDIR push dword eax - - lea ax, [FileFound_OK_cstr] - push ax - call PrintString - add sp, 0x2 - + __PRINT_CSTR FileFound_OK push dword eax call PrintDWORD ; void PrintDWORD(uint32_t dword) add sp, 0x4 - - lea ax, [NewLine_cstr] - push ax - call PrintString - add sp, 0x2 + __PRINT_CSTR NewLine - ERROR STEVIA_DEBUG_HALT hcf: hlt jmp short (hcf - $$) @@ -164,6 +140,11 @@ hcf: ; ; ############### +boot_drive_ptr: + dw 0x0000 +partition_offset_ptr: + dw 0x0000 + %include 'fat32/FAT32_SYS.inc' ; ############### @@ -180,8 +161,18 @@ hcf: ; ; ############################## +%ifnmacro __PRINT_CSTR + %macro __PRINT_CSTR 1 + lea ax, [%1_cstr] + push ax + call PrintString + add sp, 0x2 + %endmacro +%endif + ; Prints a C-Style string (null terminated) using BIOS vga teletype call ; void PrintString(char* buf) +ALIGN 4, db 0x90 PrintString: __CDECL16_ENTRY mov di, [bp + 4] ; first arg is char* @@ -214,6 +205,7 @@ PrintString: ; Prints a single character ; void PrintCharacter(char c); +ALIGN 4, db 0x90 PrintCharacter: __CDECL16_ENTRY .func: @@ -231,6 +223,7 @@ PrintCharacter: ; TODO: fix the prolog, epilog and stack usage to confirm with cdecl16 ; prints the hex representation of of val ; void PrintDWORD(uint32_t val); +ALIGN 4, db 0x90 PrintDWORD: __CDECL16_ENTRY .func: @@ -282,7 +275,7 @@ PrintDWORD: ; SYSTEM CONFIGURATION FUNCTIONS ; ; ############################## - +ALIGN 4, db 0x90 EnterUnrealMode: __CDECL16_ENTRY .func: @@ -342,28 +335,39 @@ EnterUnrealMode.unload_cs: ; ; ############# -%define StrCRLF_NUL 0Dh, 0Ah, 00h +%macro define_str 2 + ALIGN 4 + %1_str: + db %2 + %define str_length %strlen(%2) ; string + %1_str_len: + dd str_len +%endmacro -HelloPrompt_cstr: - db 'Stevia Stage2', StrCRLF_NUL -A20_Enabled_cstr: - db 'A20 Enabled OK', StrCRLF_NUL -MemoryMap_OK_cstr: - db 'Memory map OK', StrCRLF_NUL -UnrealMode_OK_cstr: - db 'Unreal mode OK', StrCRLF_NUL -FileFound_OK_cstr: - db 'Found SFN entry for bootable binary, first cluster -> ', 00h +; TODO: technically this is a cstr but it splices a return and newline on the end +; TODO: this probably should be seperated out and the printing functionality should +; TODO: place that newline and return +%macro define_cstr 2 +%define CRLF_NUL 0Dh, 0Ah, 00h + ALIGN 4 + %1_cstr: + db %2, StrCRLF_NUL +%endmacro + +define_cstr HelloPrompt, "Hello from Stevia Stage2!" +define_cstr A20_Enabled_OK, "A20 Enabled OK" +define_cstr MemoryMap_OK, "Memory map OK" +define_cstr UnrealMode_OK, "Unreal mode OK" +define_cstr FileFound_OK, "Found SFN entry for bootable binary, first cluster -> " +define_cstr InitFATSYS_OK, "FAT32 Driver Init..." +define_cstr NewLine, "" + + +define_str BootTarget, "BOOT BIN" + +ALIGN 4 IntToHex_table: db '0123456789ABCDEF' -NewLine_cstr: - db StrCRLF_NUL -BootTarget_str: - db "BOOT BIN" -boot_drive_ptr: - dw 0x0000 -partition_offset_ptr: - dw 0x0000 ; see docs/gdt.txt for a quick refresher on GDT ALIGN 4, db 0 @@ -450,6 +454,15 @@ gdt32_start: db 0x00 gdt32_end: +ALIGN 8 +version_magic: + db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h + +ALIGN 8 +datetime_magic: + db 'Assembled - ', __DATE__, ' ', __TIME__, 00h + + %assign bytes_remaining ((MAX_STAGE2_BYTES - 4) - ($ - $$)) %warning STAGE2 has bytes_remaining bytes remaining for code (MAX: MAX_STAGE2_BYTES) From 075e51c8bcbf4b50a11d0402bd59c1f938a948cb Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 19:31:31 -0400 Subject: [PATCH 092/147] move macro definition super early fix a few mistakes in macro defs --- src/stage2/stage2.nasm | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 998699b..ae61946 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -44,6 +44,13 @@ nop %include "mem.inc" %include "error_codes.inc" +%macro print_string 1 + mov ax, %1 + push ax + call PrintString + add sp, 0x2 +%endmacro + ; ############### ; End Section ; ############### @@ -101,34 +108,34 @@ main: .signature_present: call SetTextMode call disable_cursor - __PRINT_CSTR HelloPrompt + print_string HelloPrompt_cstr ; enable A20 gate call EnableA20 - __PRINT_CSTR A20_Enabled + print_string A20_Enabled_OK_cstr ; enter unreal mode call EnterUnrealMode - __PRINT_CSTR UnrealMode_OK + print_string UnrealMode_OK_cstr ; get system memory map call GetMemoryMap - __PRINT_CSTR MemoryMap_OK + print_string MemoryMap_OK_cstr ; FAT Driver setup call InitFATDriver - __PRINT_CSTR InitFATSYS_OK + print_string InitFATSYS_OK_cstr ; ; Find first cluster of bootable file ; call SearchFATDIR push dword eax - __PRINT_CSTR FileFound_OK + print_string FileFound_OK_cstr push dword eax call PrintDWORD ; void PrintDWORD(uint32_t dword) add sp, 0x4 - __PRINT_CSTR NewLine + print_string NewLine_cstr hcf: hlt @@ -161,15 +168,6 @@ partition_offset_ptr: ; ; ############################## -%ifnmacro __PRINT_CSTR - %macro __PRINT_CSTR 1 - lea ax, [%1_cstr] - push ax - call PrintString - add sp, 0x2 - %endmacro -%endif - ; Prints a C-Style string (null terminated) using BIOS vga teletype call ; void PrintString(char* buf) ALIGN 4, db 0x90 @@ -339,7 +337,7 @@ EnterUnrealMode.unload_cs: ALIGN 4 %1_str: db %2 - %define str_length %strlen(%2) ; string + %define str_len %strlen(%2) ; string %1_str_len: dd str_len %endmacro @@ -351,7 +349,7 @@ EnterUnrealMode.unload_cs: %define CRLF_NUL 0Dh, 0Ah, 00h ALIGN 4 %1_cstr: - db %2, StrCRLF_NUL + db %2, CRLF_NUL %endmacro define_cstr HelloPrompt, "Hello from Stevia Stage2!" From 59678149e0701030a79a2e4827ade48b1e11728a Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 21:49:15 -0400 Subject: [PATCH 093/147] added debug config for bochs --- bochsrc.dbg.txt | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 bochsrc.dbg.txt diff --git a/bochsrc.dbg.txt b/bochsrc.dbg.txt new file mode 100755 index 0000000..7b35bac --- /dev/null +++ b/bochsrc.dbg.txt @@ -0,0 +1,53 @@ +# configuration file generated by Bochs +plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=false, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false +config_interface: textconfig +display_library: sdl2, options=gui_debug +memory: guest=64, host=64, block_size=128 +romimage: file="/usr/share/bochs/BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none +vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" +boot: disk +floppy_bootsig_check: disabled=0 +floppya: type=1_44 +# no floppyb +ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +ata0-master: type=disk, path="./disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=auto +ata0-slave: type=none +ata1: enabled=false +ata1-master: type=none +ata1-slave: type=none +ata2: enabled=false +ata3: enabled=false +optromimage1: file=none +optromimage2: file=none +optromimage3: file=none +optromimage4: file=none +optramimage1: file=none +optramimage2: file=none +optramimage3: file=none +optramimage4: file=none +pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, slot5=none +vga: extension=vbe, update_freq=10, realtime=1, ddc=builtin +cpu: count=1, ips=1000000, model=p3_katmai, reset_on_triple_fault=0, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 +print_timestamps: enabled=0 +private_colormap: enabled=0 +clock: sync=none, time0=local, rtc_sync=0 +# no cmosimage +log: stevia-log +#logcontrol: disk=1, rombios=1, pci=0, cpu=0, keyboard=0, io=0 +logprefix: %t%e%d +debug: action=ignore +info: action=report +error: action=report +panic: action=ask +keyboard: type=mf, serial_delay=150, paste_delay=100000, user_shortcut=none +mouse: type=none, enabled=false, toggle=ctrl+mbutton +sound: waveoutdrv=dummy, waveout=none, waveindrv=dummy, wavein=none, midioutdrv=dummy, midiout=none +speaker: enabled=true, mode=sound, volume=15 +parport1: enabled=true, file=none +parport2: enabled=false +com1: enabled=true, mode=null +com2: enabled=false +com3: enabled=false +com4: enabled=false +magic_break: enabled=1 +port_e9_hack: enabled=1, all_rings=false From 60aaf5cdd925e9920d71851e2e69a496ce578c1c Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Fri, 11 Oct 2024 21:51:07 -0400 Subject: [PATCH 094/147] move far jump setup in EnterUnrealMode to right after we save CS --- src/stage2/stage2.nasm | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index ae61946..1f119f4 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -284,33 +284,33 @@ EnterUnrealMode: push gs push ss - push cs ; save real mode code selector - lgdt [unreal_gdt_info] + push cs ; save real mode code selector + pop ax ; save cs to ax to setup far jump + mov word [ds:__UNREAL_SEGMENT], ax - mov eax, cr0 ; switch to pmode - or al,1 ; set pmode bit - mov cr0, eax - jmp $+2 + lgdt [unreal_gdt_info] + mov eax, cr0 + or al,1 ; set pmode bit + mov cr0, eax ; switch to pmode + jmp $+2 ; clear instruction cache ;jmp far 0x0008:EnterUnrealMode.load_cs db 0xEA ; jmp far imm16:imm16 dw EnterUnrealMode.load_cs ; error_far_ptr dw 0x0008 ; error_far_seg .load_cs: - mov bx, 0x10 ; select descriptor 2 - mov ds, bx ; 10h = 0001_0000b + mov bx, 0x10 ; select descriptor 2 + mov ds, bx ; 10h = 0001_0000b mov ss, bx mov es, bx mov fs, bx - mov gs, bx ; other data/stack to desc. 2 + mov gs, bx ; other data/stack to index 2 (off 0x10) - and al,0xFE ; back to realmode - mov cr0, eax ; by toggling bit again - jmp $+2 + and al,0xFE ; toggle bit 1 of cr0 + mov cr0, eax ; back to realmode + jmp $+2 ; clear instruction cache again - pop ax ; save cs to ax to setup far jump - mov word [ds:__UNREAL_SEGMENT], ax ;jmp far 0x0008:EnterUnrealMode.unload_cs db 0xEA ; jmp far imm16:imm16 dw EnterUnrealMode.unload_cs ; error_far_ptr From 2581e50c8b0da9bad2983e6830964046ffd65cd0 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 11:27:20 -0400 Subject: [PATCH 095/147] ignore nasm symbol map files --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9cf867a..92682b7 100755 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ build/* *.elf bx_enh_dbg.ini stevia-log -.vscode/ \ No newline at end of file +.vscode/ +*.map \ No newline at end of file From e648fd0de6f82f0a516e1f97d4841b838ab23a41 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 11:27:55 -0400 Subject: [PATCH 096/147] remove PRINT_FUNC macro...this isn't it chief --- include/util/bochs_magic.inc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/util/bochs_magic.inc b/include/util/bochs_magic.inc index 55b23fd..fa236fc 100644 --- a/include/util/bochs_magic.inc +++ b/include/util/bochs_magic.inc @@ -51,15 +51,5 @@ %endmacro %endif -%ifnmacro PRINT_FUNC_LABEL - %macro PRINT_FUNC_LABEL 1 - %define label %1 - %assign addr label - %ifnctx __OUTPUT__ - __OUTPUT__ "Entry point for '%1' = %d", addr - %endif - %endmacro -%endif - %define __INC_BOCHS_DEBUG_MAGIC %endif \ No newline at end of file From cd048933ec7c5e77af6df2b1abc23cdad784f53f Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 11:28:25 -0400 Subject: [PATCH 097/147] output symbol maps to ease debuging --- src/mbr/mbr.nasm | 2 +- src/vbr/vbr.nasm | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 4afe7a5..cfec883 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -23,7 +23,7 @@ [CPU KATMAI] [WARNING -reloc-abs-byte] [WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings. - +[map all mbr.map] %define __STEVIA_MBR jmp short (init - $$) diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 377ba3c..009f7ae 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -21,7 +21,8 @@ [ORG 0x7C00] [CPU KATMAI] [WARNING -reloc-abs-byte] -[WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings. +[WARNING -reloc-abs-word] +[map all vbr.map] ; Yes, we use absolute addresses. surpress these warnings. %define __STEVIA_VBR __ENTRY: From 65e5a83eb49e62c02c122f55fdb3eae5b58006a5 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 11:29:20 -0400 Subject: [PATCH 098/147] stage2 is now a multisection binary file also preparing to move memory globals to bss section. --- src/stage2/stage2.nasm | 44 ++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 1f119f4..ca7484b 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -21,15 +21,13 @@ [BITS 16] [ORG 0X7E00] [CPU KATMAI] +[map all stage2.map] [WARNING -reloc-abs-byte] [WARNING -reloc-abs-word] [WARNING -reloc-abs-dword] ; Yes, we use absolute addresses. surpress these warnings. - %define __STEVIA_STAGE2 -__STAGE2_ENTRY: -jmp short (init - $$) -nop + ; ############### ; @@ -51,9 +49,11 @@ nop add sp, 0x2 %endmacro -; ############### -; End Section -; ############### +section .text +org 0x7E00 +begin_text: +jmp short (init - $$) +nop ALIGN 4, db 0x90 init: @@ -83,11 +83,6 @@ init: %include "util/kmem_func.nasm" %include "util/error_func.nasm" -; ############### -; End Section -; ############### - -; ; bp - 2 : uint8_t boot_drive ; bp - 4 : uint16_t part_offset ALIGN 4, db 0x90 @@ -326,7 +321,11 @@ EnterUnrealMode.unload_cs: .endp: __CDECL16_EXIT ret +end_text: +section .data follows=.text +align 512 +begin_data: ; ############# ; ; Strings @@ -459,11 +458,22 @@ version_magic: ALIGN 8 datetime_magic: db 'Assembled - ', __DATE__, ' ', __TIME__, 00h - +end_data: %assign bytes_remaining ((MAX_STAGE2_BYTES - 4) - ($ - $$)) -%warning STAGE2 has bytes_remaining bytes remaining for code (MAX: MAX_STAGE2_BYTES) +%warning STAGE2 has bytes_remaining bytes remaining for code/data (MAX: MAX_STAGE2_BYTES) -; this is here to make the stage2 bigger than 1 sector for testing -times ((MAX_STAGE2_BYTES - 4) - ($ - $$)) db 0x00 -STAGE2_SIG: dd 0xDEADBEEF \ No newline at end of file +; section start location needs to be a 'critical expression' +; i.e resolvable at build time, we are setting 0x7E00 as the offset since +section .sign start=((MAX_STAGE2_BYTES - 512) + 0x7E00) +times ( (512 - 4) - ($ -$$)) db 0x90 ; nop +STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 + +section .bss follows=.sign +align 512 +begin_bss: +buffer1 resb 512 +buffer2 resb 512 +buffer3 resb 512 +buffer4 resb 512 +end_bss: \ No newline at end of file From a523e17d27a3a5c56c24f7d17d02bb05e0fc06ec Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 12:55:29 -0400 Subject: [PATCH 099/147] moved stuff that is only referenced in Stage2 to stage2 bss --- include/mem.inc | 28 ++++------------------------ src/stage2/stage2.nasm | 24 ++++++++++++++++++++---- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/include/mem.inc b/include/mem.inc index ca8ac77..0ac49da 100755 --- a/include/mem.inc +++ b/include/mem.inc @@ -43,13 +43,6 @@ ; 0x0000000100000000 ??? ??? (whatever exists) RAM -- free for use (PAE/64bit)/More Extended memory ; ???????????????? ??? ??? Potentially usable for memory mapped PCI devices in modern hardware (but typically not, due to backward compatibility) -; 0x2700 -> 0x28FF -%define disk_buffer 0x2700 -; 0x2900 -> 0x2AFF -%define fat_buffer 0x2900 -; 0x2B00 -> 0x2CFF -%define dir_buffer 0x2B00 - ; copy of partition table, 72 bytes %define partition_table 0x3000 %define partition_table_SIZE 72 @@ -64,15 +57,6 @@ %define fat32_ebpb 0x306E %define fat32_ebpb_SIZE 54 -; FAT32 FSInfo, 512 bytes -;0x30A2 -%define fat32_fsinfo 0x30B0 -%define fat32_fsinfo_SIZE 512 - -; some stored state for the fat32 driver -;0x32A2 -%define fat32_state 0x34B0 -%define fat32_state_SIZE 32 ; next free space is 0x32D0 %define fat32_nc_data 0x35D0 @@ -81,14 +65,6 @@ ; lba_packet for raw_disk_read %define lba_packet 0x4000 -%define BIOSMemoryMap 0x4200 -%define SteviaInfo 0x5200 - - -; High memory addresses for loading kernel (for use with unreal mode and 32bit override) - -; file load buffer at 16MB -%define HMEM_load_buffer 0x1000000 ;PhysicalAddress = Segment * 16 + Offset @@ -104,6 +80,10 @@ ; Segement = linear >> 4 (top 16 bits) ; offset = linear & 0x0F (low 4 bits) +struc EarlyBootStruct_t + .lba_packet_offset resw 1 +endstruc + ; 20 bytes, passed to loaded kernel struc SteviaInfoStruct_t .MemoryMapPtr resd 1 diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index ca7484b..8d4df81 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -472,8 +472,24 @@ STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage section .bss follows=.sign align 512 begin_bss: -buffer1 resb 512 -buffer2 resb 512 -buffer3 resb 512 -buffer4 resb 512 + +disk_buffer resb 512 + +fat_buffer resb 512 + +dir_buffer resb 512 + +fat_fsinfo resb 512 + +fat32_state resb FAT32_State_t_size + +%define BIOSMemoryMap_SIZE 4096 +BIOSMemoryMap resb 4096 + +SteviaInfo resd 4 + +align 16 +stack_bottom: + stack resb 4096 +stack_top: end_bss: \ No newline at end of file From 31c45051e6b6b6576f49e2e9ff71caa7ded44550 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 12:57:56 -0400 Subject: [PATCH 100/147] minor cleanup related to memory refactor --- src/mbr/mbr.nasm | 23 ++--------------------- src/vbr/vbr.nasm | 16 +++++++++------- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index cfec883..efb5e84 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -25,14 +25,11 @@ [WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings. [map all mbr.map] %define __STEVIA_MBR - jmp short (init - $$) nop ; ############### -; ; Headers/Includes/Definitions -; ; ############### %include "util/bochs_magic.inc" @@ -43,11 +40,7 @@ nop %include "error_codes.inc" %include "partition_table.inc" -; ############### -; End Section -; ############### - -ALIGN 4, db 0x90 +ALIGN 4 init: cli ; We do not want to be interrupted @@ -69,23 +62,15 @@ init: jmp 0:main ; ############### -; ; Extra/Shared Functions -; ; ############### %include "util/kmem_func.nasm" %include "util/error_func.nasm" -; ############### -; End Section -; ############### - ; ; bp - 2 : uint8_t boot_drive ; bp - 4 : uint16_t part_offset -; - ALIGN 4, db 0x90 main: mov byte [bp - 2], dl ; BIOS passes drive number in DL @@ -158,7 +143,7 @@ main: mov si, word [bp - 4] mov dl, byte [bp - 2] - jmp 0:0x7C00 + jmp word 0x0000:0x7C00 ; ############### ; @@ -168,10 +153,6 @@ main: %include 'BIOS/func/ext_read.nasm' -; ############### -; End Section -; ############### - %assign bytes_remaining (440 - ($ - $$)) %warning MBR has bytes_remaining bytes remaining for code (MAX: 440 bytes) times ((512 - 72) - ($ - $$)) nop ; Fill the rest of sector with nop diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 009f7ae..c68a37b 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -24,7 +24,7 @@ [WARNING -reloc-abs-word] [map all vbr.map] ; Yes, we use absolute addresses. surpress these warnings. %define __STEVIA_VBR - +section .text __ENTRY: jmp short (init - $$) nop @@ -51,11 +51,8 @@ times 54 db 0x00 %include "error_codes.inc" %include "fat32/bpb_offset_bx.inc" -; ############### -; End Section -; ############### -ALIGN 4, db 0x90 +ALIGN 4 init: cli ; We do not want to be interrupted @@ -85,6 +82,9 @@ init: ; End Section ; ############### +; +; byte boot_drive @ bp - 2 +; word part_offset @ bp - 4 ALIGN 4, db 0x90 main: mov byte [bp - 2], dl ; boot_drive @@ -101,7 +101,7 @@ main: push ax mov ax, fat32_bpb ; defined in memory.inc, destination push ax - call kmemcpy ; copy bpb to memory + call kmemcpy ; copy bpb & ebpb to memory add sp, 0x6 mov bx, fat32_bpb ; bx now points to aligned memory structure @@ -130,6 +130,8 @@ main: add sp, 0xC .check_sig: + ; BUG: this is hard coded to check @ ((0x7E0 << 4) + 0x7FFC)...i.e (STAGE2_ENTRY + (STAGE2_MAX_BYTES - 4)) + ; this should be removed or done properly mov ax, 0x7E0 mov fs, ax cmp dword [fs:0x7FFC], 0xDEADBEEF @@ -140,7 +142,7 @@ main: .sig_ok: mov si, word [bp - 4] mov dl, byte [bp - 2] - jmp 0:0x7E00 + jmp word 0x0000:0x7E00 ; ############### ; Required BIOS function(s) From 3fbfcbef53452e972111d9f541aeb8b62c163501 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 12:58:16 -0400 Subject: [PATCH 101/147] BIOSMemoryMap is a location in bss now, use lea --- include/BIOS/func/E820_memory_map.nasm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/BIOS/func/E820_memory_map.nasm b/include/BIOS/func/E820_memory_map.nasm index 6752bf3..abc944a 100644 --- a/include/BIOS/func/E820_memory_map.nasm +++ b/include/BIOS/func/E820_memory_map.nasm @@ -48,7 +48,8 @@ GetMemoryMap: mov eax, 0xE820 ; select 0xE820 function xor ebx, ebx ; Continuation value, 0 for the first call - mov dx, (BIOSMemoryMap >> 4) + lea dx, [BIOSMemoryMap] + shr dx, 4 mov es, dx xor di, di ; (BIOSMemoryMap >> 4):0 makes di an index into BIOSMemoryMap From bd80f48b1b5f89daafed5e980d25d5614040c4c3 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 12:58:32 -0400 Subject: [PATCH 102/147] use NASM defined size value from structure macro --- include/fat32/FAT32_SYS.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 9c8d01b..9f00869 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -28,7 +28,7 @@ ALIGN 4, db 0x90 InitFATDriver: __CDECL16_ENTRY .func: - mov ax, fat32_state_SIZE + mov ax, FAT32_State_t_size push ax ; length of fat32_state structure xor ax, ax push ax ; init fat32_state with zero From 9656a9465bf2e9c3aaa677059dda78c98a223858 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 14:48:26 -0400 Subject: [PATCH 103/147] first version of kmemcpy5/kmemset4 --- include/util/kmemcpy5_func.nasm | 53 +++++++++++++++++++++++++++++++++ include/util/kmemset4_func.nasm | 47 +++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 include/util/kmemcpy5_func.nasm create mode 100644 include/util/kmemset4_func.nasm diff --git a/include/util/kmemcpy5_func.nasm b/include/util/kmemcpy5_func.nasm new file mode 100644 index 0000000..81a6b64 --- /dev/null +++ b/include/util/kmemcpy5_func.nasm @@ -0,0 +1,53 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +%ifndef __INC_KMEMCPY5_FUNC +%include 'cdecl16.inc' + +; uint8_t* kmemset(word dest_segment, word dest, word src_segment, word src, byte len); +; not overlap safe, only for +ALIGN 4, db 0x90 +kmemcpy5: + __CDECL16_ENTRY + push ds + push es +.setup_segments + mov ax, [bp + 4] + mov ds, ax ; destination segment + + mov ax, [ bp + 8] + mov es, ax ; source segment +.func: + mov cx, [bp + 12] ; len + mov si, [bp + 10] ; src + mov di, [bp + 6] ; dest + + cld ; ensure we are incrementing + rep movsb ; move ds:si -> es:di + mov ax, di ; return pointer to dest +.restore_segments: + pop es + pop ds +.endf: + __CDECL16_EXIT + ret + +%define __INC_KMEMCPY5_FUNC +%endif \ No newline at end of file diff --git a/include/util/kmemset4_func.nasm b/include/util/kmemset4_func.nasm new file mode 100644 index 0000000..9f0a734 --- /dev/null +++ b/include/util/kmemset4_func.nasm @@ -0,0 +1,47 @@ +; Copyright (c) 2024 Elaina Claus +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in all +; copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. + +%ifndef __INC_KMEMSET4_FUNC +%include 'cdecl16.inc' + +; word kmemset_byte(word segment, word dst, byte val, word len); +ALIGN 4, db 0x90 +kmemset4: + __CDECL16_ENTRY +.setup_segment: + push es + mov ax, [bp + 4] + mov es, ax + .func: + mov cx, [bp + 10] ; size_t len + mov al, [bp + 8] ; uint8_t val + mov di, [bp + 6] ; word dst + + cld + rep stosb ; move al -> es:di + mov ax, di ; return pointer to dest +.restore_segments: + pop es +.endf: + __CDECL16_EXIT + ret + +%endif +%define __INC_KMEMSET4_FUNC \ No newline at end of file From 73b42c66fd7246ee286237caf39c1989e9a8ecd6 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 15:38:24 -0400 Subject: [PATCH 104/147] renamed mem.inc and removed unused items --- include/{mem.inc => early_mem.inc} | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) rename include/{mem.inc => early_mem.inc} (88%) diff --git a/include/mem.inc b/include/early_mem.inc similarity index 88% rename from include/mem.inc rename to include/early_mem.inc index 0ac49da..d2b3ea2 100755 --- a/include/mem.inc +++ b/include/early_mem.inc @@ -18,7 +18,7 @@ ; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ; SOFTWARE. -%ifndef __INC_MEM +%ifndef __INC_EARLY_MEM ; ## Generic Low mem map (from osdev wiki) ## @@ -60,13 +60,11 @@ ; next free space is 0x32D0 %define fat32_nc_data 0x35D0 -%define fat32_nc_data_size 16 +%define fat32_nc_data_SIZE 16 ; lba_packet for raw_disk_read %define lba_packet 0x4000 - - ;PhysicalAddress = Segment * 16 + Offset %define SEG_TO_LINEAR(s,o) ((s << 4) + o) @@ -76,21 +74,5 @@ ; Seg = (physical - offset) / 16 %define LINEAR_TO_SEGMENT(p,o) ((p - o) >> 4) -; create normalized linear addres from seg:off (16:4) -; Segement = linear >> 4 (top 16 bits) -; offset = linear & 0x0F (low 4 bits) - -struc EarlyBootStruct_t - .lba_packet_offset resw 1 -endstruc - -; 20 bytes, passed to loaded kernel -struc SteviaInfoStruct_t - .MemoryMapPtr resd 1 - .MemoryMapEntries resd 1 - .BPBDataPtr resd 1 - .EBPBDataPtr resd 1 -endstruc - %endif -%define __INC_MEM \ No newline at end of file +%define __INC_EARLY_MEM \ No newline at end of file From 276fe7057297c0ee08234c02ef4857d0e4956472 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 15:38:47 -0400 Subject: [PATCH 105/147] use early_mem.inc --- src/mbr/mbr.nasm | 4 ++-- src/vbr/vbr.nasm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index efb5e84..410f9a0 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -36,7 +36,7 @@ nop %include "cdecl16.inc" %include "entry.inc" %include "config.inc" -%include "mem.inc" +%include "early_mem.inc" %include "error_codes.inc" %include "partition_table.inc" @@ -136,7 +136,7 @@ main: push ax mov ax, DiskSig ; start of partition table push ax - mov ax, partition_table ; defined in memory.inc + mov ax, partition_table ; defined in early_mem.inc push ax call kmemcpy ; copy partition table to memory add sp, 0x6 diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index c68a37b..3bc198b 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -47,7 +47,7 @@ times 54 db 0x00 %include "cdecl16.inc" %include "entry.inc" %include "config.inc" -%include "mem.inc" +%include "early_mem.inc" %include "error_codes.inc" %include "fat32/bpb_offset_bx.inc" From 1d84f526908c59badc2a4a8b3dd5be579f8e75ae Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 15:39:04 -0400 Subject: [PATCH 106/147] definition corrections in part table stuff --- include/partition_table.inc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/partition_table.inc b/include/partition_table.inc index ddd9ab6..abd895a 100755 --- a/include/partition_table.inc +++ b/include/partition_table.inc @@ -34,15 +34,15 @@ struc PartEntry_t .chs_start resb 3 .part_type resb 1 .chs_end resb 3 - .lba_start resb 4 - .lba_length resb 4 + .lba_start resd 1 + .lba_length resd 1 endstruc struc PartTable_t - .partition1 resb 16 - .partition2 resb 16 - .partition3 resb 16 - .partition4 resb 16 + .partition1 resb PartEntry_t_size + .partition2 resb PartEntry_t_size + .partition3 resb PartEntry_t_size + .partition4 resb PartEntry_t_size endstruc %endif From 54b7a81648c41e4963b0725894729bbc0f7d9783 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 15:39:16 -0400 Subject: [PATCH 107/147] correct typo --- include/util/kmemcpy5_func.nasm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/util/kmemcpy5_func.nasm b/include/util/kmemcpy5_func.nasm index 81a6b64..d3c698e 100644 --- a/include/util/kmemcpy5_func.nasm +++ b/include/util/kmemcpy5_func.nasm @@ -28,7 +28,7 @@ kmemcpy5: __CDECL16_ENTRY push ds push es -.setup_segments +.setup_segments: mov ax, [bp + 4] mov ds, ax ; destination segment @@ -48,6 +48,6 @@ kmemcpy5: .endf: __CDECL16_EXIT ret - + %define __INC_KMEMCPY5_FUNC %endif \ No newline at end of file From f535840572d2c1cfb7425e84b97751f65e99a07b Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 15:41:39 -0400 Subject: [PATCH 108/147] big step...and also its completely broken right now we are going to use 0x07E0 as our base segment so we have a bit more memory to work with until we are fully in 32bit protected mode. this commit is broken but is just one step towards a working release. --- src/stage2/stage2.nasm | 96 +++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 8d4df81..ba29d1c 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -19,7 +19,7 @@ ; SOFTWARE. [BITS 16] -[ORG 0X7E00] +[ORG 0x0000] [CPU KATMAI] [map all stage2.map] [WARNING -reloc-abs-byte] @@ -27,19 +27,15 @@ [WARNING -reloc-abs-dword] ; Yes, we use absolute addresses. surpress these warnings. %define __STEVIA_STAGE2 - - ; ############### -; ; Headers/Includes/Definitions -; ; ############### %include "util/bochs_magic.inc" %include "cdecl16.inc" %include "entry.inc" %include "config.inc" -%include "mem.inc" +%include "early_mem.inc" %include "error_codes.inc" %macro print_string 1 @@ -50,39 +46,72 @@ %endmacro section .text -org 0x7E00 +org 0x0000 + begin_text: jmp short (init - $$) nop ALIGN 4, db 0x90 init: - cli ; We do not want to be interrupted + cli ; We do not want to be interrupted - xor ax, ax ; 0 AX - mov ds, ax ; Set segment registers to 0 - mov es, ax ; * - mov fs, ax ; * - mov gs, ax ; * + mov ax, 0x07E0 ; 0x07E0 i.e 0x7E00 >> 4 in AX + mov ds, ax ; Set segment registers to 0 + mov es, ax ; * + mov fs, ax ; * + mov gs, ax ; * - mov ss, ax ; Set Stack Segment to 0 - mov sp, EARLY_STACK_START ; Set Stack Pointer + mov ss, ax ; Set Stack Segment to 0x07E0 + mov sp, stack_top ; Set Stack Pointer mov bp, sp sub sp, 0x20 ; 32 bytes for local varibles sti - jmp 0:main + jmp word 0x07E0:main ; ############### -; -; Extra/Shared Functions -; +; Functions ; ############### %include "util/kmem_func.nasm" +%include "util/kmemcpy5_func.nasm" +%include "util/kmemset4_func.nasm" %include "util/error_func.nasm" +; ############### +; FAT32 Driver +; ############### + +boot_drive_ptr: + dw 0x0000 +partition_offset_ptr: + dw 0x0000 + +%include 'fat32/FAT32_SYS.inc' + +; ############### +; BIOS functions +; ############### + +%include 'BIOS/BIOS_SYS.inc' + +; structures + +struc SteviaInfoStruct_t + .MemoryMapPtr resd 1 + .MemoryMapEntries resd 1 +endstruc + +struc EarlyBootStruct_t + .lba_packet resb LBAPkt_t_size + .partition_table resb partition_table_SIZE + .fat32_bpb resb fat32_bpb_SIZE + .fat32_ebpb resb fat32_ebpb_SIZE + .fat32_nc_data resb fat32_nc_data_SIZE +endstruc + ; bp - 2 : uint8_t boot_drive ; bp - 4 : uint16_t part_offset ALIGN 4, db 0x90 @@ -136,27 +165,6 @@ hcf: hlt jmp short (hcf - $$) -; ############### -; -; FAT32 Driver -; -; ############### - -boot_drive_ptr: - dw 0x0000 -partition_offset_ptr: - dw 0x0000 - -%include 'fat32/FAT32_SYS.inc' - -; ############### -; -; BIOS functions -; -; ############### - -%include 'BIOS/BIOS_SYS.inc' - ; ############################## ; ; SYSTEM CONFIGURATION FUNCTIONS @@ -465,7 +473,7 @@ end_data: ; section start location needs to be a 'critical expression' ; i.e resolvable at build time, we are setting 0x7E00 as the offset since -section .sign start=((MAX_STAGE2_BYTES - 512) + 0x7E00) +section .sign start=(MAX_STAGE2_BYTES - 512) times ( (512 - 4) - ($ -$$)) db 0x90 ; nop STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 @@ -481,15 +489,15 @@ dir_buffer resb 512 fat_fsinfo resb 512 -fat32_state resb FAT32_State_t_size - %define BIOSMemoryMap_SIZE 4096 BIOSMemoryMap resb 4096 SteviaInfo resd 4 +fat32_state resb FAT32_State_t_size align 16 stack_bottom: - stack resb 4096 + stack resb 8192 stack_top: +stage2_main_redzone resb 32 end_bss: \ No newline at end of file From 2fa03c31d70bad2b69a09d716c639a3298175008 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 20:25:04 -0400 Subject: [PATCH 109/147] partially roll back changing the segment to 0x07E0 --- include/util/error_func.nasm | 4 +- src/stage2/stage2.nasm | 114 +++++++++++++++-------------------- 2 files changed, 51 insertions(+), 67 deletions(-) diff --git a/include/util/error_func.nasm b/include/util/error_func.nasm index 6c2aa92..5682266 100644 --- a/include/util/error_func.nasm +++ b/include/util/error_func.nasm @@ -22,9 +22,7 @@ %macro ERROR 1 mov al, %1 ; al = 1 byte error code mapped to ascii values - db 0xEA ; jmp far imm16:imm16 - dw error ; error_far_seg - dw 0x0000 ; error_far_ptr + jmp error %endmacro ; pass error as ascii character in al, errors a-zA-Z or 0-9 diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index ba29d1c..78b4980 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -19,13 +19,14 @@ ; SOFTWARE. [BITS 16] -[ORG 0x0000] +[ORG 0x7E00] [CPU KATMAI] [map all stage2.map] [WARNING -reloc-abs-byte] [WARNING -reloc-abs-word] [WARNING -reloc-abs-dword] ; Yes, we use absolute addresses. surpress these warnings. %define __STEVIA_STAGE2 +%define __STAGE2_SEGMENT 0x0000 ; ############### ; Headers/Includes/Definitions @@ -46,7 +47,7 @@ %endmacro section .text -org 0x0000 +org 0x7E00 begin_text: jmp short (init - $$) @@ -56,20 +57,21 @@ ALIGN 4, db 0x90 init: cli ; We do not want to be interrupted - mov ax, 0x07E0 ; 0x07E0 i.e 0x7E00 >> 4 in AX + mov ax, __STAGE2_SEGMENT ; configured segment mov ds, ax ; Set segment registers to 0 mov es, ax ; * mov fs, ax ; * mov gs, ax ; * - mov ss, ax ; Set Stack Segment to 0x07E0 + mov ss, ax ; Set Stack Segment to data segment mov sp, stack_top ; Set Stack Pointer + mov bp, sp sub sp, 0x20 ; 32 bytes for local varibles sti - jmp word 0x07E0:main + jmp word __STAGE2_SEGMENT:main ; ############### ; Functions @@ -126,10 +128,12 @@ main: mov eax, dword [STAGE2_SIG] cmp eax, 0xDEADBEEF - je main.signature_present + je main.bss_init ERROR STAGE2_SIGNATURE_MISSING -.signature_present: +.bss_init: + nop ; placeholder +.stage2_main: call SetTextMode call disable_cursor print_string HelloPrompt_cstr @@ -288,14 +292,19 @@ EnterUnrealMode: push ss push cs ; save real mode code selector + xor ax, ax ; pop ax ; save cs to ax to setup far jump - mov word [ds:__UNREAL_SEGMENT], ax + mov word [__UNREAL_SEGMENT], ax + + shl eax, 4 + add eax, unreal_gdt_start ; ax contains the physical address of gdt table + mov dword [unreal_gdt_ptr], eax ; update gdt ptr in unreal_gdt_info + + lgdt [dword ((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; calculate linear address for lgdt to consume - lgdt [unreal_gdt_info] mov eax, cr0 or al,1 ; set pmode bit mov cr0, eax ; switch to pmode - jmp $+2 ; clear instruction cache ;jmp far 0x0008:EnterUnrealMode.load_cs db 0xEA ; jmp far imm16:imm16 @@ -310,9 +319,8 @@ EnterUnrealMode: mov fs, bx mov gs, bx ; other data/stack to index 2 (off 0x10) - and al,0xFE ; toggle bit 1 of cr0 - mov cr0, eax ; back to realmode - jmp $+2 ; clear instruction cache again + and al,0xFE ; toggle bit 1 of cr0 + mov cr0, eax ; back to realmode ;jmp far 0x0008:EnterUnrealMode.unload_cs db 0xEA ; jmp far imm16:imm16 @@ -375,58 +383,36 @@ IntToHex_table: db '0123456789ABCDEF' ; see docs/gdt.txt for a quick refresher on GDT -ALIGN 4, db 0 +ALIGN 16, db 0 unreal_gdt_info: unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1 - unreal_gdt_ptr: dd unreal_gdt_start + unreal_gdt_ptr: dd ((__STAGE2_SEGMENT << 4) + unreal_gdt_start) unreal_gdt_start: - ; entry 0 + ; entry 0 (null descriptor) dq 0 ; first entry is null - ; entry 1 (4 GiB flat code map) - dw 0xFFFF ; Segment Limit 15:0 (Same large limit as data segment) + ; entry 1 (16-bit code segment with 4 GiB flat mapping) + dw 0xFFFF ; Segment Limit 15:0 dw 0x0000 ; Base Address 15:0 - db 0x00 ; Base Address 23:16 - db 1001_1010b ; Access Byte: 1001_1010b for executable code - db 1000_1111b ; Flags and Segment Limit 19:16 (Same as data segment) - db 0x00 ; Base Address 31:24 + db 0000_0000b ; Base Address 23:16 + db 1001_1010b ; Access Byte: executable, readable, present + db 0000_1111b ; Flags: 16-bit, Granularity = 4KiB + db 0000_0000b ; Base Address 31:24 - ; entry 2 (4 GiB flat data map) - dw 0xFFFF ; 0:15 limit - dw 0x0000 ; 0:15 base - db 0x00 ; 16:23 base - db 1001_0010b ; bit 0:4 = S/Type, [1, DC, RW, Ac] or [0, E, RW, Ac] - ; bit 5:6 = Privl - ; bit 7 = Present - - db 1000_1111b ; bit 0:3 = 16:19 of Limit - ; bit 4 = Availible to software bit - ; bit 5 = Reserved (?) - ; bit 6 = D/B bit, depending on if this is code/data 1 = 32 bit operands or stack size - ; bit 7 = Granularity bit. 1 = multiply limit by 4096 - db 0x00 ; base 24:31 - ; at the end of the day... - ; base = 0x00000000 - ; limit = 0xFFFFF - ; Accessed = 0, ignore this field - ; RW = 1, data is Read/Write - ; E = 0, Expand up, valid data is from base -> limit, if 1 valid data is from (limit + 1) -> base - ; C/D = 0, Segment is a data segment - ; S = 1, Segment is a system segment - ; Privl = 00b, Ring0 segment - ; Pr = 1, segment is present - ; AVL = 0, ignore this field - ; D/B bit = 0, 16bit code/stack - ; Gr = 1, multiply limit by 4096 + ; entry 2 (16-bit data segment with 4 GiB flat mapping) + dw 0xFFFF ; Segment Limit 15:0 + dw 0x0000 ; Base Address 15:0 + db 0000_0000b ; Base Address 23:16 + db 1001_0010b ; Access Byte: readable, writable, present + db 0000_1111b ; Flags: 16-bit, Granularity = 4KiB + db 0000_0000b ; Base Address 31:24 unreal_gdt_end: -ALIGN 4, db 0 +ALIGN 16, db 0 gdt32_info: gdt32_size: dw (gdt32_end - gdt32_start) - 1 - gdt32_ptr: dd gdt32_start - -; check above for detailed information + gdt32_ptr: dd ((__STAGE2_SEGMENT << 4) + gdt32_start) gdt32_start: dq 0 .gdt32_code: @@ -473,14 +459,22 @@ end_data: ; section start location needs to be a 'critical expression' ; i.e resolvable at build time, we are setting 0x7E00 as the offset since -section .sign start=(MAX_STAGE2_BYTES - 512) -times ( (512 - 4) - ($ -$$)) db 0x90 ; nop -STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 +section .sign start=((MAX_STAGE2_BYTES - 512) + 0x7E00) +times ((512 - 4) - ($ -$$) ) db 0x90 ; nop +STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 section .bss follows=.sign align 512 begin_bss: +stack_bottom: + stack resb 4096 +stack_top: +stage2_main_redzone resb 32 +SteviaInfo resd 4 +fat32_state resb FAT32_State_t_size + +align 512 disk_buffer resb 512 fat_buffer resb 512 @@ -492,12 +486,4 @@ fat_fsinfo resb 512 %define BIOSMemoryMap_SIZE 4096 BIOSMemoryMap resb 4096 -SteviaInfo resd 4 -fat32_state resb FAT32_State_t_size - -align 16 -stack_bottom: - stack resb 8192 -stack_top: -stage2_main_redzone resb 32 end_bss: \ No newline at end of file From d1f8ec4a9e4c023ef92b22adfc99bcfa6b875f72 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 21:21:43 -0400 Subject: [PATCH 110/147] follow standard proceedure and reallocate the mbr to 0x600 --- include/entry.inc | 2 +- src/mbr/mbr.nasm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/entry.inc b/include/entry.inc index fa5e710..b21aa8d 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -22,7 +22,7 @@ ; 8KiB from 0x2500 -> 0x500 %define EARLY_STACK_START 0x2500 -%define MBR_ENTRY 0x7A00 +%define MBR_ENTRY 0x0600 %define VBR_ENTRY 0x7C00 %define STAGE2_ENTRY 0x7E00 diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 410f9a0..9cbd24c 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -19,7 +19,7 @@ ; SOFTWARE. [BITS 16] -[ORG 0x7A00] +[ORG 0x0600] [CPU KATMAI] [WARNING -reloc-abs-byte] [WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings. From 3d3bcc6ea51dd741c6142ea10a7d25a7eb2eeb07 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 22:13:12 -0400 Subject: [PATCH 111/147] reduced stage2 to 24KiB --- include/config.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config.inc b/include/config.inc index db74252..ea4bbd7 100755 --- a/include/config.inc +++ b/include/config.inc @@ -21,7 +21,7 @@ %ifndef __INC_STEVIA_CONFIG %define SECTOR_SIZE 512 -%define STAGE2_SECTOR_COUNT 0x40 +%define STAGE2_SECTOR_COUNT 0x30 ; 32 KiB %define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT) From bd40d6d3247128a7c27ac7c691b575cd28e7fcf9 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 22:14:47 -0400 Subject: [PATCH 112/147] relocate code sections to end up with stage2 starting at 0x500 --- include/entry.inc | 4 ++-- src/mbr/mbr.nasm | 27 ++++++++++++++------------- src/stage2/stage2.nasm | 29 +++++++++++++++++++---------- src/vbr/vbr.nasm | 18 +++++++----------- 4 files changed, 42 insertions(+), 36 deletions(-) diff --git a/include/entry.inc b/include/entry.inc index b21aa8d..0d276ee 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -21,10 +21,10 @@ %ifndef __INC_ENTRY ; 8KiB from 0x2500 -> 0x500 -%define EARLY_STACK_START 0x2500 +%define EARLY_STACK_START 0xFFFF %define MBR_ENTRY 0x0600 %define VBR_ENTRY 0x7C00 -%define STAGE2_ENTRY 0x7E00 +%define STAGE2_ENTRY 0x0500 %endif %define __INC_ENTRY \ No newline at end of file diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 9cbd24c..a382ba6 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -42,16 +42,18 @@ nop ALIGN 4 init: - cli ; We do not want to be interrupted + cli ; We do not want to be interrupted - xor ax, ax ; 0 AX - mov ds, ax ; Set segment registers to 0 - - mov ss, ax ; Set Stack Segment to 0 - mov sp, EARLY_STACK_START ; Setup stack - mov bp, sp ; base ptr = stack ptr - sub sp, 0x20 ; local varible space + xor ax, ax ; 0 AX + mov ds, ax ; Set segment registers to 0 + mov es, ax + + mov ss, ax ; Set Stack Segment to 0 + mov sp, EARLY_STACK_START ; Setup stack + mov bp, sp ; base ptr = stack ptr + sub sp, 0x10 ; local varible space + xor cx, cx mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS) mov di, MBR_ENTRY ; New MBR Address (our new relocation address) @@ -115,12 +117,11 @@ main: mov dword eax, dword [bx + PartEntry_t.lba_start] push dword eax ; lba - xor ax, ax - push ax ; offset = 0 - mov ax, VBR_ENTRY - shr ax, 4 - push ax ; segment = 7C0 + push ax ; offset = 0x7c00 + + xor ax, ax + push ax ; segment = 0 ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint32_t lba, diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 78b4980..08536e4 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -19,7 +19,7 @@ ; SOFTWARE. [BITS 16] -[ORG 0x7E00] +[ORG 0x0500] ; IF YOU CHANGE ORG CHANGE THE SIGN OFFSET AT THE END [CPU KATMAI] [map all stage2.map] [WARNING -reloc-abs-byte] @@ -47,7 +47,7 @@ %endmacro section .text -org 0x7E00 +org 0x0500 begin_text: jmp short (init - $$) @@ -57,6 +57,18 @@ ALIGN 4, db 0x90 init: cli ; We do not want to be interrupted + mov cx, (end_bss - begin_bss) ; count = bss length + + mov ax, begin_bss + shr ax, 4 + mov es, ax ; es = begining of bss section + + xor ax, ax + mov di, ax ; dst = 0 + + cld + rep stosb ; zero bss section + mov ax, __STAGE2_SEGMENT ; configured segment mov ds, ax ; Set segment registers to 0 mov es, ax ; * @@ -128,11 +140,8 @@ main: mov eax, dword [STAGE2_SIG] cmp eax, 0xDEADBEEF - je main.bss_init + je main.stage2_main ERROR STAGE2_SIGNATURE_MISSING - -.bss_init: - nop ; placeholder .stage2_main: call SetTextMode call disable_cursor @@ -396,8 +405,9 @@ unreal_gdt_start: dw 0xFFFF ; Segment Limit 15:0 dw 0x0000 ; Base Address 15:0 db 0000_0000b ; Base Address 23:16 + db 1001_1010b ; Access Byte: executable, readable, present - db 0000_1111b ; Flags: 16-bit, Granularity = 4KiB + db 1000_1111b ; 24:20 G/DB/L/AVL & SegLimit 19:16 db 0000_0000b ; Base Address 31:24 ; entry 2 (16-bit data segment with 4 GiB flat mapping) @@ -405,7 +415,7 @@ unreal_gdt_start: dw 0x0000 ; Base Address 15:0 db 0000_0000b ; Base Address 23:16 db 1001_0010b ; Access Byte: readable, writable, present - db 0000_1111b ; Flags: 16-bit, Granularity = 4KiB + db 1000_1111b ; Flags: 16-bit, Granularity = 4KiB db 0000_0000b ; Base Address 31:24 unreal_gdt_end: @@ -459,7 +469,7 @@ end_data: ; section start location needs to be a 'critical expression' ; i.e resolvable at build time, we are setting 0x7E00 as the offset since -section .sign start=((MAX_STAGE2_BYTES - 512) + 0x7E00) +section .sign start=((MAX_STAGE2_BYTES - 512) + 0x0500) times ((512 - 4) - ($ -$$) ) db 0x90 ; nop STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 @@ -474,7 +484,6 @@ stage2_main_redzone resb 32 SteviaInfo resd 4 fat32_state resb FAT32_State_t_size -align 512 disk_buffer resb 512 fat_buffer resb 512 diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 3bc198b..50e312f 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -115,13 +115,12 @@ main: mov dword eax, 0x1 push dword eax ; lba - xor ax, ax - push ax ; offset = 0 - ; 07E0:0 = 0x00007e00 mov ax, STAGE2_ENTRY - shr ax, 4 - push ax ; segment = 7E0 + push ax ; offset + + xor ax, ax + push ax ; segment = 0 ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint32_t lba, @@ -130,11 +129,8 @@ main: add sp, 0xC .check_sig: - ; BUG: this is hard coded to check @ ((0x7E0 << 4) + 0x7FFC)...i.e (STAGE2_ENTRY + (STAGE2_MAX_BYTES - 4)) - ; this should be removed or done properly - mov ax, 0x7E0 - mov fs, ax - cmp dword [fs:0x7FFC], 0xDEADBEEF + mov eax, dword [(MAX_STAGE2_BYTES - 4) + 0x500] + cmp eax, 0xDEADBEEF je main.sig_ok ERROR VBR_ERROR_NO_SIGNATURE ; no signature present in stage2 @@ -142,7 +138,7 @@ main: .sig_ok: mov si, word [bp - 4] mov dl, byte [bp - 2] - jmp word 0x0000:0x7E00 + jmp word 0x0000:STAGE2_ENTRY ; ############### ; Required BIOS function(s) From 0983ec3fd557977dc84adb844cb3f00ffe2d6f86 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sat, 12 Oct 2024 22:16:17 -0400 Subject: [PATCH 113/147] remove map files as well --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index ead41f7..baf15ff 100755 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ stage2: $(stage2_binary_files) boottest: $(boottest_binary_files) clean: + @rm -rvf *.map @rm -rvf $(build_dir)/* @rm -rvf $(iso) @rm -rvf $(isoz) From a62f3de26fb3778b04627ec0e7a72e6eb273bca3 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 13:22:01 -0400 Subject: [PATCH 114/147] unreal gdt tweaks & fixes --- src/stage2/stage2.nasm | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 08536e4..3cfb951 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -396,27 +396,23 @@ ALIGN 16, db 0 unreal_gdt_info: unreal_gdt_size: dw (unreal_gdt_end - unreal_gdt_start) - 1 unreal_gdt_ptr: dd ((__STAGE2_SEGMENT << 4) + unreal_gdt_start) - unreal_gdt_start: ; entry 0 (null descriptor) dq 0 ; first entry is null ; entry 1 (16-bit code segment with 4 GiB flat mapping) - dw 0xFFFF ; Segment Limit 15:0 - dw 0x0000 ; Base Address 15:0 - db 0000_0000b ; Base Address 23:16 - - db 1001_1010b ; Access Byte: executable, readable, present - db 1000_1111b ; 24:20 G/DB/L/AVL & SegLimit 19:16 + dq 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0 + db 0x00 ; Base Address 23:16 + db 1001_1010b ; Access Byte: Present, ring0, S = 1, executable (1), non-conforming, readable, Accessed + db 1000_1111b ; Flags: GR = 4KiB, attr = , Granularity = 4KiB & 16:19 of limit db 0000_0000b ; Base Address 31:24 ; entry 2 (16-bit data segment with 4 GiB flat mapping) - dw 0xFFFF ; Segment Limit 15:0 - dw 0x0000 ; Base Address 15:0 - db 0000_0000b ; Base Address 23:16 - db 1001_0010b ; Access Byte: readable, writable, present - db 1000_1111b ; Flags: 16-bit, Granularity = 4KiB - db 0000_0000b ; Base Address 31:24 + dq 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0 + db 0x00 ; Base Address(23:16) + db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present + db 1000_1111b ; Flags: GR = 4KiB, attr = <16-bit/?/?>, Granularity = 4KiB & 16:19 of limit + db 0000_0000b ; Base Address(31:24) unreal_gdt_end: ALIGN 16, db 0 From c9191444963ce4d0cbafba0113f41e08daec5762 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 14:50:49 -0400 Subject: [PATCH 115/147] turns out huge unreal mode isn't supported in bochs huge unreal mode is 4GiB code in 16bit mode + 4GiB data we will just use the regular big flat model instead (64KiB code/4GiB data) --- src/stage2/stage2.nasm | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 3cfb951..29e2f02 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -305,15 +305,12 @@ EnterUnrealMode: pop ax ; save cs to ax to setup far jump mov word [__UNREAL_SEGMENT], ax - shl eax, 4 - add eax, unreal_gdt_start ; ax contains the physical address of gdt table - mov dword [unreal_gdt_ptr], eax ; update gdt ptr in unreal_gdt_info - - lgdt [dword ((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; calculate linear address for lgdt to consume + lgdt [((__STAGE2_SEGMENT << 4) + unreal_gdt_info)] ; load unreal gdt mov eax, cr0 or al,1 ; set pmode bit mov cr0, eax ; switch to pmode + jmp short $+2 ;jmp far 0x0008:EnterUnrealMode.load_cs db 0xEA ; jmp far imm16:imm16 @@ -330,7 +327,8 @@ EnterUnrealMode: and al,0xFE ; toggle bit 1 of cr0 mov cr0, eax ; back to realmode - + jmp short $+2 + ;jmp far 0x0008:EnterUnrealMode.unload_cs db 0xEA ; jmp far imm16:imm16 dw EnterUnrealMode.unload_cs ; error_far_ptr @@ -400,19 +398,19 @@ unreal_gdt_start: ; entry 0 (null descriptor) dq 0 ; first entry is null - ; entry 1 (16-bit code segment with 4 GiB flat mapping) - dq 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0 + ; entry 1 (16bit code 64KiB limit) + dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0 db 0x00 ; Base Address 23:16 db 1001_1010b ; Access Byte: Present, ring0, S = 1, executable (1), non-conforming, readable, Accessed - db 1000_1111b ; Flags: GR = 4KiB, attr = , Granularity = 4KiB & 16:19 of limit - db 0000_0000b ; Base Address 31:24 + db 0000_0000b ; Flags: GR = 4KiB, attr = , Granularity = 4KiB & 16:19 of limit + db 0x00 ; Base Address 31:24 - ; entry 2 (16-bit data segment with 4 GiB flat mapping) - dq 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0 + ; entry 2 (16bit data segment with 4 GiB flat mapping) + dd 0x0000FFFF ; Base Address(15:0) 31:16, Segment Limit(15:0) 15:0 db 0x00 ; Base Address(23:16) db 1001_0010b ; Access Byte: Present, ring0, S = 1, data (0), non-confirming, writable, present db 1000_1111b ; Flags: GR = 4KiB, attr = <16-bit/?/?>, Granularity = 4KiB & 16:19 of limit - db 0000_0000b ; Base Address(31:24) + db 0x00 ; Base Address(31:24) unreal_gdt_end: ALIGN 16, db 0 From 832141efb48fcade55cc561159fa6695e134522d Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 16:36:11 -0400 Subject: [PATCH 116/147] bss convertion for mbr stage --- src/mbr/mbr.nasm | 62 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index a382ba6..7745791 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -36,22 +36,39 @@ nop %include "cdecl16.inc" %include "entry.inc" %include "config.inc" -%include "early_mem.inc" %include "error_codes.inc" %include "partition_table.inc" +%include "fat32/fat32_structures.inc" ALIGN 4 init: cli ; We do not want to be interrupted - - xor ax, ax ; 0 AX - mov ds, ax ; Set segment registers to 0 + xor ax, ax + mov ds, ax ; Set segment registers to 0x0000 mov es, ax - + mov fs, ax + mov gs, ax + + ; + ; Zero BSS section + ; + mov cx, (end_bss - begin_bss) ; count = bss length + + mov ax, begin_bss + shr ax, 4 + mov es, ax ; es = begining of bss section + + xor ax, ax + mov di, ax ; dst = 0 + + cld + rep stosb ; zero bss section + + xor ax, ax mov ss, ax ; Set Stack Segment to 0 - mov sp, EARLY_STACK_START ; Setup stack + mov sp, stack_top ; Setup stack mov bp, sp ; base ptr = stack ptr - sub sp, 0x10 ; local varible space + sub sp, 0x10 ; local varible space xor cx, cx mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx @@ -133,13 +150,13 @@ main: je main.sig_ok ERROR MBR_ERROR_NO_VBR_SIG ; no signature present .sig_ok: - mov ax, partition_table_SIZE ; 72 bytes of data + mov ax, PartTable_t_size push ax mov ax, DiskSig ; start of partition table push ax - mov ax, partition_table ; defined in early_mem.inc + mov ax, partition_table push ax - call kmemcpy ; copy partition table to memory + call kmemcpy ; copy partition table to bss add sp, 0x6 mov si, word [bp - 4] @@ -174,4 +191,27 @@ PartEntry3: PartEntry4: times 16 db 0x00 BootSig: - dw 0xAA55 ; Add boot signature at the end of bootloader \ No newline at end of file + dw 0xAA55 ; Add boot signature at the end of bootloader +; this should mark the 512 byte mark...if not, something has gone wrong. +section .bss follows=.text +begin_bss: + +align 16, resb 1 +partition_table resb PartTable_t_size + +align 16, resb 1 +fat32_bpb resb FAT32_bpb_t_size +fat32_ebpb resb FAT32_ebpb_t_size + +align 16, resb 1 +fat32_nc_data resb 16 + +align 16, resb 1 +lba_packet resb LBAPkt_t_size + +align 512, resb 1 +stack_bottom resb 1024 ; 1Kib stack early on + +stack_top: +mbr_redzone resb 32 +end_bss: \ No newline at end of file From 4faffbf7feed18312e1ae0b01a9ca5ce01dc8302 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 16:36:55 -0400 Subject: [PATCH 117/147] remove defs for memory locations (moving to bss) --- include/early_mem.inc | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/include/early_mem.inc b/include/early_mem.inc index d2b3ea2..bce18d9 100755 --- a/include/early_mem.inc +++ b/include/early_mem.inc @@ -43,28 +43,6 @@ ; 0x0000000100000000 ??? ??? (whatever exists) RAM -- free for use (PAE/64bit)/More Extended memory ; ???????????????? ??? ??? Potentially usable for memory mapped PCI devices in modern hardware (but typically not, due to backward compatibility) -; copy of partition table, 72 bytes -%define partition_table 0x3000 -%define partition_table_SIZE 72 - -; copy of FAT32 BPB, 33 bytes (+1 to the next value to align to uint16_t) -;0x3048 -%define fat32_bpb 0x304A -%define fat32_bpb_SIZE 36 - -; copy of FAT32 EBPB, 54 bytes -;0x306A -%define fat32_ebpb 0x306E -%define fat32_ebpb_SIZE 54 - - -; next free space is 0x32D0 -%define fat32_nc_data 0x35D0 -%define fat32_nc_data_SIZE 16 - -; lba_packet for raw_disk_read -%define lba_packet 0x4000 - ;PhysicalAddress = Segment * 16 + Offset %define SEG_TO_LINEAR(s,o) ((s << 4) + o) From 7f06d47f32b73789663bd7087cd13fb4b5e57f74 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 16:37:29 -0400 Subject: [PATCH 118/147] add reserved space for jmp short init at the start, technically this is part of the bpb anyways --- include/fat32/fat32_structures.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fat32/fat32_structures.inc b/include/fat32/fat32_structures.inc index 0bba2a5..7fb0289 100755 --- a/include/fat32/fat32_structures.inc +++ b/include/fat32/fat32_structures.inc @@ -63,6 +63,7 @@ ; resulting in a value which does not fit in the Number of Sectors entry at 0x13. struc FAT32_bpb_t + .reserved_init resb 3 .ident_8 resb 8 .bytes_per_sector_16 resb 2 .sectors_per_cluster_8 resb 1 From 29db27925fe4fa63ac167a0357b6a939db159703 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 16:37:52 -0400 Subject: [PATCH 119/147] initial work on a macro to call read_disk_raw --- include/BIOS/func/ext_read.nasm | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/BIOS/func/ext_read.nasm b/include/BIOS/func/ext_read.nasm index 42d1cdc..826729a 100644 --- a/include/BIOS/func/ext_read.nasm +++ b/include/BIOS/func/ext_read.nasm @@ -36,6 +36,29 @@ struc LBAPkt_t .lower_lba resd 1 .upper_lba resd 1 endstruc +; call_read_disk_raw +%macro call_read_disk_raw 5 + movzx ax, %5 + push ax ; drive_num + + movzx ax, %4 + push ax ; count + + movzx dword eax, %3 + push dword eax ; lba + + movzx ax, %2 + push ax ; offset + + movzx ax, %1 + push ax ; segment = 0 + + ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, + ; uint32_t lba, + ; uint16_t count, uint16_t drive_num) + call read_disk_raw + add sp, 0xC +%endmacro ; Wrapper for AH=0x42 INT13h (Extended Read) ; From dd1a74bff03b202a4bb01e2b8817f088e1b56565 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 16:41:39 -0400 Subject: [PATCH 120/147] pass location of partition_table structure to vbr --- src/mbr/mbr.nasm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 7745791..ba036de 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -161,6 +161,7 @@ main: mov si, word [bp - 4] mov dl, byte [bp - 2] + mov bx, partition_table jmp word 0x0000:0x7C00 ; ############### From 9d33469e32d4578b5d760a3cce23b96a8b18a550 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 17:52:09 -0400 Subject: [PATCH 121/147] fixed bss init in mbr --- src/mbr/mbr.nasm | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index ba036de..02f61e4 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -51,20 +51,13 @@ init: ; ; Zero BSS section - ; - mov cx, (end_bss - begin_bss) ; count = bss length - + mov cx, (end_bss - begin_bss) ; count = bss length mov ax, begin_bss - shr ax, 4 - mov es, ax ; es = begining of bss section - + mov di, ax ; es:di is dest xor ax, ax - mov di, ax ; dst = 0 - cld rep stosb ; zero bss section - xor ax, ax mov ss, ax ; Set Stack Segment to 0 mov sp, stack_top ; Setup stack mov bp, sp ; base ptr = stack ptr From e3a646675fdb7372500ffd065fb233eece4ec24d Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 17:52:28 -0400 Subject: [PATCH 122/147] bss for vbr stage --- src/vbr/vbr.nasm | 115 +++++++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 39 deletions(-) diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 50e312f..f17c041 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -29,7 +29,6 @@ __ENTRY: jmp short (init - $$) nop -phy_bpb_start: ; fill BPB area with 0x00 since we skip writing this part to disk ; but we need it for the 'jmp short entry; nop' above times 33 db 0x00 @@ -49,30 +48,41 @@ times 54 db 0x00 %include "config.inc" %include "early_mem.inc" %include "error_codes.inc" +%include "partition_table.inc" +%include "fat32/fat32_structures.inc" %include "fat32/bpb_offset_bx.inc" - - +; +; dl = boot_drive +; si = part_offset +; bx = partition_table location from mbr ALIGN 4 init: - cli ; We do not want to be interrupted + cli ; We do not want to be interrupted + xor ax, ax + mov ds, ax ; Set segment registers to 0x0000 + mov es, ax - xor ax, ax ; 0 AX - mov ds, ax ; Set segment registers to 0 + ; zero bss section + mov cx, (end_bss - begin_bss) ; count = bss length + mov ax, begin_bss + mov di, ax ; es:di is dest + xor ax, ax + cld + rep stosb - mov ss, ax ; Set Stack Segment to 0 - mov sp, EARLY_STACK_START ; Setup stack - mov bp, sp ; base ptr = stack ptr - sub sp, 0x20 ; local varible space + xor ax, ax + mov ss, ax ; Set Stack Segment to 0 + mov sp, stack_top ; Setup stack + mov bp, sp ; base ptr = stack ptr + sub sp, 0x10 ; local varible space - mov bx, VBR_ENTRY ; move Bx to the new start of the initial boot sector - sti ; all done with inital setup and relocation, reenable interupts + mov cx, bx ; mov partition_table locaiton to cx + sti ; all done with inital setup and relocation, reenable interupts - jmp 0:main ; fix up cs:ip just in case and jump to relocated code + jmp 0:main ; fix up cs:ip just in case and jump to relocated code ; ############### -; ; Extra/Shared Functions -; ; ############### %include "util/kmem_func.nasm" @@ -85,27 +95,38 @@ init: ; ; byte boot_drive @ bp - 2 ; word part_offset @ bp - 4 +; ptr partition_table ALIGN 4, db 0x90 main: - mov byte [bp - 2], dl ; boot_drive - mov [bp - 4], si ; part_offset + mov byte [bp - 2], dl ; boot_drive + mov word [bp - 4], si ; part_offset + mov word [bp - 6], cx ; partition_table -.check_FAT_size: ; we only support a very specific setup of FAT32 - cmp dword [bsSectorHuge], 0 ; SectorsHuge will not be set if FAT12/16 - ja main.load_stage2 - ERROR VBR_ERROR_WRONG_FAT_SIZE -.load_stage2: ; read sectors 1-63 to stage2 entry point - mov ax, (fat32_bpb_SIZE + fat32_ebpb_SIZE) ; size in byte +.load_fs_data: + mov ax, PartTable_t_size push ax - mov ax, (phy_bpb_start - 0x3) ; start of bpb - 0x3 for the jump short main at the start + mov ax, [bp - 6] ; ptr partition_table + mov ax, partition_table push ax - mov ax, fat32_bpb ; defined in memory.inc, destination + call kmemcpy ; copy partition table data + add sp, 0x6 + + mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte + push ax + mov ax, __ENTRY + push ax + mov ax, fat32_bpb ; push ax call kmemcpy ; copy bpb & ebpb to memory add sp, 0x6 mov bx, fat32_bpb ; bx now points to aligned memory structure - +.check_FAT_size: ; we only support a very specific setup of FAT32 + cmp dword [bsSectorHuge], 0 ; SectorsHuge will not be set if FAT12/16 + ja main.load_stage2 + ERROR VBR_ERROR_WRONG_FAT_SIZE +.load_stage2: + ; read sectors 1-(MAX_STAGE2_BYTES / 512) to stage2 entry point movzx ax, byte [bp - 2] push ax ; drive_num @@ -115,7 +136,6 @@ main: mov dword eax, 0x1 push dword eax ; lba - mov ax, STAGE2_ENTRY push ax ; offset @@ -127,17 +147,11 @@ main: ; uint16_t count, uint16_t drive_num) call read_disk_raw add sp, 0xC - -.check_sig: - mov eax, dword [(MAX_STAGE2_BYTES - 4) + 0x500] - cmp eax, 0xDEADBEEF - je main.sig_ok - - ERROR VBR_ERROR_NO_SIGNATURE ; no signature present in stage2 - -.sig_ok: - mov si, word [bp - 4] - mov dl, byte [bp - 2] +.enter_stage2: + mov dl, byte [bp - 2] ; boot_drive + mov si, word [bp - 4] ; part_offset + mov bx, partition_table + mov dx, fat32_bpb jmp word 0x0000:STAGE2_ENTRY ; ############### @@ -152,4 +166,27 @@ main: times (510 - ($ - $$)) nop ; Fill the rest of sector with nop BootSig: - dw 0xAA55 ; Add boot signature at the end of bootloader \ No newline at end of file + dw 0xAA55 ; Add boot signature at the end of bootloader + +section .bss follows=.text +begin_bss: + +align 16, resb 1 +partition_table resb PartTable_t_size + +align 16, resb 1 +fat32_bpb resb FAT32_bpb_t_size +fat32_ebpb resb FAT32_ebpb_t_size + +align 16, resb 1 +fat32_nc_data resb 16 + +align 16, resb 1 +lba_packet resb LBAPkt_t_size + +align 512, resb 1 +stack_bottom resb 1024 ; 1Kib stack early on + +stack_top: +vbr_redzone resb 32 +end_bss: \ No newline at end of file From e4b9c5d77f7195268d60b50d8fea3ffacb60b853 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 17:54:06 -0400 Subject: [PATCH 123/147] added partition_table and fat32_bpb params to stage2 also the partition table and fat32_bpb and passed/copied from the mbr/vbr now --- src/stage2/stage2.nasm | 99 +++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 21 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 29e2f02..fb4e88a 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -53,10 +53,17 @@ begin_text: jmp short (init - $$) nop +; dl = byte boot_drive +; si = word part_offset (active partition offset) +; bx = ptr PartTable_t partition_table +; dx = ptr FAT32_bpb_t fat32_bpb ALIGN 4, db 0x90 init: cli ; We do not want to be interrupted + ; + ; Zero BSS section + ; mov cx, (end_bss - begin_bss) ; count = bss length mov ax, begin_bss @@ -68,9 +75,10 @@ init: cld rep stosb ; zero bss section + ; done zeroing BSS - mov ax, __STAGE2_SEGMENT ; configured segment - mov ds, ax ; Set segment registers to 0 + mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment + mov ds, ax ; * mov es, ax ; * mov fs, ax ; * mov gs, ax ; * @@ -119,30 +127,50 @@ struc SteviaInfoStruct_t endstruc struc EarlyBootStruct_t - .lba_packet resb LBAPkt_t_size - .partition_table resb partition_table_SIZE - .fat32_bpb resb fat32_bpb_SIZE - .fat32_ebpb resb fat32_ebpb_SIZE - .fat32_nc_data resb fat32_nc_data_SIZE + .partition_table resb PartTable_t_size + .fat32_bpb resb FAT32_bpb_t_size + .fat32_ebpb resb FAT32_ebpb_t_size endstruc -; bp - 2 : uint8_t boot_drive -; bp - 4 : uint16_t part_offset +; bp - 2 : byte boot_drive +; bp - 4 : word part_offset +; bp - 6 : ptr PartTable_t partition_table +; bp - 8 : ptr FAT32_bpb_t fat32_bpb ALIGN 4, db 0x90 main: lea ax, [bp - 2] mov [boot_drive_ptr], ax + lea ax, [bp - 4] mov [partition_offset_ptr], ax ; setup pointers to boot_drive and partition offset on stack mov byte [bp - 2], dl ; boot_drive (probably 0x80) mov word [bp - 4], si ; partition_offset - + mov word [bp - 6], bx ; partition_table + mov word [bp - 8], dx ; fat32_bpb +.check_sig: mov eax, dword [STAGE2_SIG] cmp eax, 0xDEADBEEF je main.stage2_main ERROR STAGE2_SIGNATURE_MISSING .stage2_main: + mov ax, PartTable_t_size + push ax + mov ax, [bp - 6] ; ptr partition_table + mov ax, partition_table + push ax + call kmemcpy ; copy partition table data + add sp, 0x6 + + mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte + push ax + mov ax, [bp - 8] ; start of bpb - 0x3 for the jump short main at the start + push ax + mov ax, fat32_bpb ; defined in memory.inc, destination + push ax + call kmemcpy ; copy bpb & ebpb to memory + add sp, 0x6 + call SetTextMode call disable_cursor print_string HelloPrompt_cstr @@ -163,6 +191,7 @@ main: call InitFATDriver print_string InitFATSYS_OK_cstr + ERROR STEVIA_DEBUG_HALT ; ; Find first cluster of bootable file ; @@ -468,25 +497,53 @@ times ((512 - 4) - ($ -$$) ) db 0x90 ; nop STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 section .bss follows=.sign -align 512 +align 512, resb 1 begin_bss: stack_bottom: - stack resb 4096 + resb 4096 stack_top: -stage2_main_redzone resb 32 +stage2_main_redzone: + resb 32 -SteviaInfo resd 4 -fat32_state resb FAT32_State_t_size +align 16, resb 1 +partition_table resb PartTable_t_size -disk_buffer resb 512 +align 16, resb 1 +fat32_bpb resb FAT32_bpb_t_size +fat32_ebpb resb FAT32_ebpb_t_size -fat_buffer resb 512 +align 16, resb 1 +fat32_nc_data resb 16 -dir_buffer resb 512 +align 16, resb 1 +lba_packet resb LBAPkt_t_size -fat_fsinfo resb 512 +align 16, resb 1 +SteviaInfo: + resd 4 +align 16, resb 1 +fat32_state: + resb FAT32_State_t_size -%define BIOSMemoryMap_SIZE 4096 -BIOSMemoryMap resb 4096 +align 16, resb 1 +mbr_sector_data: + resb 512 +vbr_sector_data: + resb 512 + +align 16, resb 1 +disk_buffer: + resb 512 +fat_buffer: + resb 512 +dir_buffer: + resb 512 +fat_fsinfo: + resb 512 + +align 16, resb 1 +%define BIOSMemoryMap_SIZE 2048 +BIOSMemoryMap: + resb 2048 end_bss: \ No newline at end of file From 8537d6cd5ed619bfd1b5f2328a212bac7ba36eb9 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 20:51:16 -0400 Subject: [PATCH 124/147] use bx addressing in read_disk_raw --- include/BIOS/func/ext_read.nasm | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/include/BIOS/func/ext_read.nasm b/include/BIOS/func/ext_read.nasm index 826729a..ce0e5fb 100644 --- a/include/BIOS/func/ext_read.nasm +++ b/include/BIOS/func/ext_read.nasm @@ -83,37 +83,33 @@ ALIGN 4, db 0x90 read_disk_raw: __CDECL16_ENTRY .func: - mov ax, 0x10 - push ax ; len = 16 bytes + mov ax, LBAPkt_t_size + push ax ; len xor ax, ax - push ax ; val = 0 + push ax ; val = 0 mov ax, lba_packet - push ax ; dest = lba_packet address + mov bx, ax + push ax ; dest = lba_packet address call kmemset add sp, 0x06 - mov byte [lba_packet + LBAPkt_t.size], 0x10 + mov byte [bx + LBAPkt_t.size], 0x10 mov ax, [bp + 12] - mov word [lba_packet + LBAPkt_t.xfer_size], ax + mov word [bx + LBAPkt_t.xfer_size], ax mov eax, [bp + 8] - mov dword [lba_packet + LBAPkt_t.lower_lba], eax + mov dword [bx + LBAPkt_t.lower_lba], eax mov ax, [bp + 6] - mov word [lba_packet + LBAPkt_t.offset], ax + mov word [bx + LBAPkt_t.offset], ax mov ax, [bp + 4] - mov word [lba_packet + LBAPkt_t.segment], ax + mov word [bx + LBAPkt_t.segment], ax - mov si, lba_packet - mov ah, 0x42 - - ;BUG: still working on getting this passed down correctly, going to hard set it for now. - movzx dx, byte [bp + 14] - and dx, 0x00ff - ;xor dl, dl - ;mov dl, 0x80 + mov si, bx ; ds:si LBAPkt_t + mov ah, 0x42 ; call # + mov dl, byte [bp + 14] ; drive # int 0x13 jnc .endf From f32745a7e3e8d68767750dfa757571bd9fdd7d90 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 20:51:34 -0400 Subject: [PATCH 125/147] enable magic in the normal bochsrc.txt --- bochsrc.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bochsrc.txt b/bochsrc.txt index 10ea176..d65599c 100755 --- a/bochsrc.txt +++ b/bochsrc.txt @@ -49,3 +49,5 @@ com1: enabled=true, mode=null com2: enabled=false com3: enabled=false com4: enabled=false +magic_break: enabled=1 +port_e9_hack: enabled=1, all_rings=false \ No newline at end of file From ad2d37c63ba70c403ab1265725631685ab6587dc Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 13 Oct 2024 20:53:13 -0400 Subject: [PATCH 126/147] use bochs magic breakpoints in the error printer makes it easier to get a good state to do some investigating before reseting. --- include/util/bochs_magic.inc | 3 ++- include/util/error_func.nasm | 5 +++++ src/stage2/stage2.nasm | 42 ++++++++++++++++++++---------------- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/include/util/bochs_magic.inc b/include/util/bochs_magic.inc index fa236fc..bc59c80 100644 --- a/include/util/bochs_magic.inc +++ b/include/util/bochs_magic.inc @@ -20,7 +20,8 @@ %ifndef __INC_BOCHS_DEBUG_MAGIC -; +; for things like the error printer, opperate differently when we are targeting a dev (bochs) build +%define __STEVIA_DEV_DEBUG ; port_e9_hack: enabled=1 needs to be set in bochsrc.txt/bxrc ; %ifnmacro __BOCHS_PRINTC diff --git a/include/util/error_func.nasm b/include/util/error_func.nasm index 5682266..271cf97 100644 --- a/include/util/error_func.nasm +++ b/include/util/error_func.nasm @@ -22,7 +22,12 @@ %macro ERROR 1 mov al, %1 ; al = 1 byte error code mapped to ascii values + %ifdef __STEVIA_DEV_DEBUG + __BOCHS_MAGIC_DEBUG + %endif jmp error + + %endmacro ; pass error as ascii character in al, errors a-zA-Z or 0-9 diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index fb4e88a..994530d 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -86,11 +86,13 @@ init: mov ss, ax ; Set Stack Segment to data segment mov sp, stack_top ; Set Stack Pointer + mov ax, init + push ax ; simulate a return value to the begining of the stage2 loader + + push bp mov bp, sp sub sp, 0x20 ; 32 bytes for local varibles - sti - jmp word __STAGE2_SEGMENT:main ; ############### @@ -106,11 +108,6 @@ init: ; FAT32 Driver ; ############### -boot_drive_ptr: - dw 0x0000 -partition_offset_ptr: - dw 0x0000 - %include 'fat32/FAT32_SYS.inc' ; ############### @@ -191,7 +188,6 @@ main: call InitFATDriver print_string InitFATSYS_OK_cstr - ERROR STEVIA_DEBUG_HALT ; ; Find first cluster of bootable file ; @@ -201,11 +197,9 @@ main: push dword eax call PrintDWORD ; void PrintDWORD(uint32_t dword) add sp, 0x4 - print_string NewLine_cstr - + print_string NewLine_cstr hcf: - hlt - jmp short (hcf - $$) + ERROR STEVIA_DEBUG_OK ; ############################## ; @@ -505,6 +499,10 @@ stack_top: stage2_main_redzone: resb 32 +; +; structures +; + align 16, resb 1 partition_table resb PartTable_t_size @@ -518,19 +516,25 @@ fat32_nc_data resb 16 align 16, resb 1 lba_packet resb LBAPkt_t_size -align 16, resb 1 -SteviaInfo: - resd 4 align 16, resb 1 fat32_state: resb FAT32_State_t_size align 16, resb 1 -mbr_sector_data: - resb 512 -vbr_sector_data: - resb 512 +SteviaInfo: + resd 4 +; +; locals +; +boot_drive_ptr: + resw 1 +partition_offset_ptr: + resw 1 + +; +; large continuous allocations +; align 16, resb 1 disk_buffer: resb 512 From 933cccb88e7a52ef9bfcc176e7533ac31fbf33c2 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Mon, 14 Oct 2024 10:44:44 -0400 Subject: [PATCH 127/147] replace text documentation with markdown --- docs/Stevia Notes.md | 230 ++++++++++++++++++++++++++++ docs/calling_convention_cdecl16.txt | 104 ------------- docs/e820_usage.txt | 78 ---------- docs/examples.txt | 35 ----- docs/gdt.txt | 61 -------- include/early_mem.inc | 23 --- 6 files changed, 230 insertions(+), 301 deletions(-) create mode 100644 docs/Stevia Notes.md delete mode 100644 docs/calling_convention_cdecl16.txt delete mode 100644 docs/e820_usage.txt delete mode 100755 docs/examples.txt delete mode 100644 docs/gdt.txt diff --git a/docs/Stevia Notes.md b/docs/Stevia Notes.md new file mode 100644 index 0000000..14aa37e --- /dev/null +++ b/docs/Stevia Notes.md @@ -0,0 +1,230 @@ +# **Bootloader Documentation** + +## **1. Calling Conventions** + +### __cdecl16near Calling Convention + +- **Purpose**: For calling near (within the same segment) functions in 16-bit code. +- **Stack Management**: Caller cleans up the stack after the function call. +- **Parameter Passing**: Parameters are pushed onto the stack from right to left. +- **Return Address**: A near return address (16-bit) is pushed onto the stack. +- **Return Value**: Placed in the AX register. + +Example: + +```assembly +; Caller +push param2 +push param1 +call near_func +add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) + +; Callee (near_func) +near_func: + push bp + mov bp, sp + ; Function body + mov sp, bp + pop bp + ret +``` + +### __cdecl16far Calling Convention + +- **Purpose**: For calling far (across different segments) functions in 16-bit code. +- **Stack Management**: Caller cleans up the stack after the function call. +- **Parameter Passing**: Parameters are pushed onto the stack from right to left. +- **Return Address**: A far return address (32-bit, consisting of a segment and an offset) is pushed onto the stack. +- **Return Value**: Placed in the AX register. + +Example: + +```assembly +; Caller +push param2 +push param1 +call far_func +add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) + +; Callee (far_func) +far_func: + push bp + mov bp, sp + ; Function body + mov sp, bp + pop bp + retf ; Far return +``` + +### **Key Differences** + +- **Return Address**: `__cdecl16near` uses a 16-bit return address; `__cdecl16far` uses a 32-bit return address (segment:offset). +- **Function Scope**: `__cdecl16near` is for functions within the same segment; `__cdecl16far` is for functions that may be in different segments. +- **Return Instruction**: `__cdecl16near` uses `ret`; `__cdecl16far` uses `retf` (far return). + +### **Register Usage** + +#### Caller-Saved (Volatile) Registers + +- **AX**: Accumulator, often used for return values. +- **CX**: Counter register. +- **DX**: Data register, used for I/O operations. +- **SI/DI**: String operation indexes. + +#### Callee-Saved (Non-Volatile) Registers + +- **BP**: Base pointer, used for stack frame management. +- **SP**: Stack pointer. +- **BX**: Base register. + +Example: + +```assembly +; Caller +push param2 +push param1 +call near_func +add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) + +; Callee (near_func) +near_func: + push bp + mov bp, sp + ; Save callee-saved registers if used + push bx + push si + push di + ; Function body + ; Use AX, CX, DX freely + ; Restore callee-saved registers + pop di + pop si + pop bx + mov sp, bp + pop bp + ret +``` + +## **2. E820 Memory Map Usage** + +### **Address Range Descriptor Structure** + +| Offset | Name | Description | +|--------|---------------|---------------------------------------| +| 0 | BaseAddrLow | Low 32 bits of base address | +| 4 | BaseAddrHigh | High 32 bits of base address | +| 8 | LengthLow | Low 32 bits of length in bytes | +| 12 | LengthHigh | High 32 bits of length in bytes | +| 16 | Type | Address type of this range | + +### **E820 Function Call** + +#### Input + +- **EAX**: Function code `E820h`. +- **EBX**: Continuation value for physical memory retrieval (0 for the first call). +- **ES:DI**: Buffer pointer to an Address Range Descriptor structure. +- **ECX**: Buffer size (minimum size 20 bytes). +- **EDX**: Signature ('SMAP'). + +#### Output + +- **CF**: Carry flag (indicates success/failure). +- **EAX**: Signature ('SMAP'). +- **ECX**: Buffer size (number of bytes returned). +- **EBX**: Continuation value for subsequent E820 calls. + +### **Address Type Values** + +| Value | Pneumonic | Description | +|-------|----------------------|-----------------------------------------------------------| +| 1 | AddressRangeMemory | Available RAM usable by the operating system. | +| 2 | AddressRangeReserved | Reserved by the system, unusable by the operating system. | + +## **3. Example Calculations** + +### **Partition Offset** + +- Partition 1 offset = LBA 0x800 = 0x100000 +- `bsSectorSize = 512` + +### **First FAT Sector** + +- `first_fat_sector = bsResSector = 32 => (32*512) = 0x4000` +- `first_fat_sector = 0x100000 + 0x4000 = 0x104000` + +### **Total FAT Sectors** + +- `total_fat_sectors = fat_sectors * number_of_FATs = 2001 * 2 = 4002` +- `total_fat_size = total_fat_sectors * bsSectorSize = 0x1F4400` + +### **First Data Sector** + +- `first_data_sector = FatStartSector + FatAreaSize = 0x104000 + 0x1F4400 = 0x2F8400` + +### **FAT Table Look Up** + +```c +if the cluster we got from the table entry was cluster 354 +fat_sector = 354 / 128 = 2 +fat_entry = 354 mod 128 = 98 + +so we load the 3rd (indexed from 0) fat table sector and read the 98th entry + +``` + +Example: + +```c + +fat_table_offset = (first_fat_sector + 2) * 512 +fat_table = *(fat_table_offset) +disk_read(fat_table[98]) +``` + +## **4. Global Descriptor Table (GDT)** + +### **Segment Attributes** + +- **Pr**: Present bit (must be 1 for valid selectors). +- **Privl**: Privilege level (0 = kernel, 3 = user). +- **S**: Descriptor type (set for code/data segments, cleared for system segments). +- **Ex**: Executable bit (set if segment contains code). +- **DC**: Direction/Conforming bit (for data or code segments). +- **RW**: Readable/Writable (depends on segment type). + +### **Granularity (Gr)** + +- **Gr**: Granularity bit (0 = byte granularity, 1 = 4 KiB blocks). +- **Sz**: Size bit (0 = 16-bit mode, 1 = 32-bit mode). + +### **GDT Entry Construction** + +Each GDT entry is 8 bytes: + +- First DWORD: Limit (0:15), Base (0:15) +- Second DWORD: Base (16:31), Attributes (8:12) + +## **5. Memory Layout Example** + +### **Low Memory (First MiB)** + +| Start | End | Size | Type | Description | +|-------------|-------------|-----------------|-----------------------|----------------------------------| +| 0x00000000 | 0x000003FF | 1 KiB | RAM (partially unusable) | Real Mode IVT (Interrupt Vector Table) | +| 0x00000400 | 0x000004FF | 256 bytes | RAM (partially unusable) | BDA (BIOS data area) | +| 0x00000500 | 0x00007BFF | almost 30 KiB | RAM - free for use | Conventional memory | +| 0x00007C00 | 0x00007DFF | 512 bytes | RAM (partially unusable) | OS BootSector | +| 0x00007E00 | 0x0007FFFF | 480.5 KiB | RAM - free for use | Conventional memory | +| 0x00080000 | 0x0009FFFF | 128 KiB | RAM (partially unusable) | EBDA (Extended BIOS Data Area) | +| 0x000A0000 | 0x000FFFFF | 384 KiB | various (unusable) | Video memory, ROM Area | + +### **Extended Memory (Above 1 MiB)** + +| Start | End | Size | Description | +|-------------|-------------|-----------------|------------------------| +| 0x00100000 | 0x00EFFFFF | 14 MiB | RAM - free for use | +| 0x00F00000 | 0x00FFFFFF | 1 MiB | Possible memory-mapped hardware (ISA) | +| 0x01000000 | ? | ? | More extended memory | +| 0xC0000000 | 0xFFFFFFFF | 1 GiB | Memory mapped PCI devices, BIOS, etc. | +| 0x0000000100000000 | ? | ? | RAM - usable in PAE/64-bit mode | diff --git a/docs/calling_convention_cdecl16.txt b/docs/calling_convention_cdecl16.txt deleted file mode 100644 index 24837b5..0000000 --- a/docs/calling_convention_cdecl16.txt +++ /dev/null @@ -1,104 +0,0 @@ -__cdecl16near Calling Convention -Purpose: Used for calling near (within the same segment) functions in 16-bit code. -Stack Management: The caller cleans up the stack after the function call. -Parameter Passing: Parameters are pushed onto the stack from right to left. -Return Address: A near return address (16-bit) is pushed onto the stack. -Return Value: The return value is typically placed in the AX register. - -e.g - -; Caller -push param2 -push param1 -call near_func -add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) - -; Callee (near_func) -near_func: - push bp - mov bp, sp - ; Function body - mov sp, bp - pop bp - ret - -__cdecl16far Calling Convention -Purpose: Used for calling far (across different segments) functions in 16-bit code. -Stack Management: The caller cleans up the stack after the function call. -Parameter Passing: Parameters are pushed onto the stack from right to left. -Return Address: A far return address (32-bit, consisting of a segment and an offset) is pushed onto the stack. -Return Value: The return value is typically placed in the AX register. - -e.g - -; Caller -push param2 -push param1 -call far_func -add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) - -; Callee (far_func) -far_func: - push bp - mov bp, sp - ; Function body - mov sp, bp - pop bp - retf ; Far return - -Key Differences -Return Address: __cdecl16near uses a 16-bit return address, while __cdecl16far uses a 32-bit return address (segment:offset). -Function Scope: __cdecl16near is for functions within the same segment, whereas __cdecl16far is for functions that may be in different segments. -Return Instruction: __cdecl16near uses ret, while __cdecl16far uses retf (far return). - - -### REGISTERS ### - -Register Usage in __cdecl16near and __cdecl16far -Caller-Saved Registers (Volatile) -These registers must be saved by the caller if they wish to preserve their values across function calls: - -AX: Accumulator register, often used for return values. -CX: Counter register, commonly used in loops and string operations. -DX: Data register, used for I/O operations and arithmetic. -SI: Source index for string operations. -DI: Destination index for string operations. -Callee-Saved Registers (Non-Volatile) -These registers must be preserved by the callee. If the callee uses these registers, it must save their original values and restore them before returning: - -BP: Base pointer, used for stack frame management. -SP: Stack pointer, although typically managed by the calling convention itself. -BX: Base register, often used for addressing. -SI: Source index, if not used for string operations. -DI: Destination index, if not used for string operations. - -e.g - -; Caller -push param2 -push param1 -call near_func -add sp, 4 ; Clean up the stack (2 parameters * 2 bytes each) - -; Callee (near_func) -near_func: - push bp - mov bp, sp - ; Save callee-saved registers if used - push bx - push si - push di - ; Function body - ; Use AX, CX, DX freely - mov ax, [bp+4] ; Access first parameter - mov bx, [bp+6] ; Access second parameter - ; - ; your other code here - ; - ; Restore callee-saved registers - pop di - pop si - pop bx - mov sp, bp - pop bp - ret diff --git a/docs/e820_usage.txt b/docs/e820_usage.txt deleted file mode 100644 index 200bf83..0000000 --- a/docs/e820_usage.txt +++ /dev/null @@ -1,78 +0,0 @@ -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; Input: -; -; EAX Function Code E820h -; EBX Continuation Contains the "continuation value" to get the -; next run of physical memory. This is the -; value returned by a previous call to this -; routine. If this is the first call, EBX -; must contain zero. -; ES:DI Buffer Pointer Pointer to an Address Range Descriptor -; structure which the BIOS is to fill in. -; ECX Buffer Size The length in bytes of the structure passed -; to the BIOS. The BIOS will fill in at most -; ECX bytes of the structure or however much -; of the structure the BIOS implements. The -; minimum size which must be supported by both -; the BIOS and the caller is 20 bytes. Future -; implementations may extend this structure. -; EDX Signature 'SMAP' - Used by the BIOS to verify the -; caller is requesting the system map -; information to be returned in ES:DI. -; -; Output: -; -; CF Carry Flag Non-Carry - indicates no error -; EAX Signature 'SMAP' - Signature to verify correct BIOS -; revision. -; ES:DI Buffer Pointer Returned Address Range Descriptor pointer. -; Same value as on input. -; ECX Buffer Size Number of bytes returned by the BIOS in the -; address range descriptor. The minimum size -; structure returned by the BIOS is 20 bytes. -; EBX Continuation Contains the continuation value to get the -; next address descriptor. The actual -; significance of the continuation value is up -; to the discretion of the BIOS. The caller -; must pass the continuation value unchanged -; as input to the next iteration of the E820 -; call in order to get the next Address Range -; Descriptor. A return value of zero means that -; this is the last descriptor -; -; Address Range Descriptor Structure -; -; Offset in Bytes Name Description -; 0 BaseAddrLow Low 32 Bits of Base Address -; 4 BaseAddrHigh High 32 Bits of Base Address -; 8 LengthLow Low 32 Bits of Length in Bytes -; 12 LengthHigh High 32 Bits of Length in Bytes -; 16 Type Address type of this range. -; -; The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. -; The BaseAddress is the physical address of the start of the range being specified. -; -; The LengthLow and LengthHigh together are the 64 bit Length of this range. -; The Length is the physical contiguous length in bytes of a range being specified. -; -; The Type field describes the usage of the described address range as defined in the table below. - -; Value Pneumonic Description -; 1 AddressRangeMemory This run is available RAM usable by the operating system. -; 2 AddressRangeReserved This run of addresses is in use or reserved by the system, and must not be used by the operating system. -; Other Undefined Undefined - Reserved for future use. \ No newline at end of file diff --git a/docs/examples.txt b/docs/examples.txt deleted file mode 100755 index 21f9ceb..0000000 --- a/docs/examples.txt +++ /dev/null @@ -1,35 +0,0 @@ -Partition 1 offset = LBA 0x800 - = 0x100000 -bsSectorSize = 512 - -first_fat_sector = bsResSector - = 32 => (32*512) = 0x4000 - = 0x100000 + 0x4000 - = 0x104000 - -total_fat_sectors = fat_sectors * number_of_FATs - = 2001 * 2 - = 4002 - -total_fat_size = total_fat_sectors * bsSectorSize - = 0x1F4400 - -first_data_sector = FatStartSector + FatAreaSize - = 0x104000 + 0x1F4400 - = 0x2F8400 - -FAT table look up - - if the cluster we got from the table entry was cluster 354 - fat_sector = 354 / 128 - = 2 - fat_entry = 354 mod 128 - = 98 - - so we load the 3rd (indexed from 0) fat table sector and read the 98th entry - for the cluster chain. - - // bad fake code below - fat_table_offset = (first_fat_sector + 2) * 512 - fat_table = *(fat_table_offset) - disk_read(fat_table[98]) diff --git a/docs/gdt.txt b/docs/gdt.txt deleted file mode 100644 index d3da195..0000000 --- a/docs/gdt.txt +++ /dev/null @@ -1,61 +0,0 @@ -GDT documentation below: - - Pr: Present bit. This must be 1 for all valid selectors. - - Privl: Privilege, 2 bits. Contains the ring level, - 0 = highest (kernel), 3 = lowest (user applications). - - S: Descriptor type. This bit should be set for code or data segments - and should be cleared for system segments (eg. a Task State Segment) - - Ex: Executable bit. If 1 code in this segment can be executed - ie. a code selector. If 0 it is a data selector. - - DC: Direction bit/Conforming bit. - Direction bit for data selectors: Tells the direction. - 0 the segment grows up. 1 the segment grows down, ie. the offset has to be greater than the limit. - - Conforming bit for code selectors: - If 1 code in this segment can be executed from an equal or lower privilege level. - For example, code in ring 3 can far-jump to conforming code in a ring 2 segment. - The privl-bits represent the highest privilege level that is allowed to execute the segment. - For example, code in ring 0 cannot far-jump to a conforming code segment with privl==0x2 - while code in ring 2 and 3 can. Note that the privilege level remains the same - ie. a far-jump form ring 3 to a privl==2-segment remains in ring 3 after the jump. - - If 0 code in this segment can only be executed from the ring set in privl. - - RW: Readable bit/Writable bit. - Readable bit for code selectors: Whether read access for this segment is allowed. Write access is never allowed for code segments. - Writable bit for data selectors: Whether write access for this segment is allowed. Read access is always allowed for data segments. - - Ac: Accessed bit. Just set to 0. The CPU sets this to 1 when the segment is accessed. - - Gr: Granularity bit. If 0 the limit is in 1 B blocks (byte granularity), if 1 the limit is in 4 KiB blocks (page granularity). - - Sz: Size bit. If 0 the selector defines 16 bit protected mode. If 1 it defines 32 bit protected mode. - You can have both 16 bit and 32 bit selectors at once. - - AvL: Availible to software bit, the CPU does not use this field and software can read/write to it - - D/B bit: The default operand-size bit is found in code-segment and data-segment descriptors but not in system-segment descriptors. Setting - this bit to 1 indicates a 32-bit default operand size, and clearing it indicates a 16-bit default size. - - E bit: Expand down bit: Setting this bit to 1 identifies the data segment as expand-down. - In expand-down segments, the segment limit defines the lower segment boundary while the base is the upper boundary - - A GDT entry is 8 bytes and is constructed as follows: - First DWORD - 0-15 Limit 0:15 First 16 bits in the segment limiter - 16-31 Base 0:15 First 16 bits in the base address - - 2nd DWORD - - 0:7 Base 16:23 Bits 16-23 in the base address - 8:12 S/Type Segment type and attributes, S = bit 12, Type = 8:11, Type is either [1, DC, RW, Ac] or [0, E, RW, Ac] - 13:14 Privl 0 = Highest privilege (OS), 3 = Lowest privilege (User applications) - 15 Pr Set to 1 if segment is present - 16:19 Limit 16:19 Bits 16-19 in the segment limiter - 20:22 Attributes Different attributes, depending on the segment type - 23 Gr Used together with the limiter, to determine the size of the segment - 24:31 Base 24:31 The last 24-31 bits in the base address \ No newline at end of file diff --git a/include/early_mem.inc b/include/early_mem.inc index bce18d9..a705b2f 100755 --- a/include/early_mem.inc +++ b/include/early_mem.inc @@ -20,29 +20,6 @@ %ifndef __INC_EARLY_MEM - -; ## Generic Low mem map (from osdev wiki) ## -; start end size type description -; Low Memory (the first MiB) -; 0x00000000 0x000003FF 1 KiB RAM - partially unusable Real Mode IVT (Interrupt Vector Table) -; 0x00000400 0x000004FF 256 bytes RAM - partially unusable BDA (BIOS data area) -; 0x00000500 0x00007BFF almost 30 KiB RAM - free for use Conventional memory -; 0x00007C00 0x00007DFF 512 bytes RAM - partially unusable OS BootSector -; 0x00007E00 0x0007FFFF 480.5 KiB RAM - free for use Conventional memory -; 0x00080000 0x0009FFFF 128 KiB RAM - partially unusable EBDA (Extended BIOS Data Area) -; 0x000A0000 0x000FFFFF 384 KiB various (unusable) Video memory, ROM Area - -; ## A rough overview of high mem ## -; Idealy this needs to be probed with the E820 functions -; # Start # End # size # description -; -; 0x00100000 0x00EFFFFF 0x00E00000 (14 MiB) RAM -- free for use (if it exists) Extended memory -; 0x00F00000 0x00FFFFFF 0x00100000 (1 MiB) Possible memory mapped hardware ISA Memory Hole 15-16MB -; 0x01000000 ???????? ??? (whatever exists) RAM -- free for use More Extended memory -; 0xC0000000 (sometimes) 0xFFFFFFFF 0x40000000 (1 GiB) Memory mapped PCI devices, PnP NVRAM?, IO APIC/s, local APIC/s, BIOS, ... -; 0x0000000100000000 ??? ??? (whatever exists) RAM -- free for use (PAE/64bit)/More Extended memory -; ???????????????? ??? ??? Potentially usable for memory mapped PCI devices in modern hardware (but typically not, due to backward compatibility) - ;PhysicalAddress = Segment * 16 + Offset %define SEG_TO_LINEAR(s,o) ((s << 4) + o) From a5296bb4380730b342b730e87440d37bd66f5b16 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Mon, 14 Oct 2024 13:18:41 -0400 Subject: [PATCH 128/147] correct drive_num argument on read_disk_raw --- include/BIOS/func/ext_read.nasm | 8 ++++---- include/fat32/FAT32_SYS.inc | 25 ++++++++++++------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/include/BIOS/func/ext_read.nasm b/include/BIOS/func/ext_read.nasm index ce0e5fb..73d2d9c 100644 --- a/include/BIOS/func/ext_read.nasm +++ b/include/BIOS/func/ext_read.nasm @@ -78,7 +78,7 @@ endstruc ; ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, ; uint32_t lba, -; uint16_t count, uint16_t drive_num) +; uint16_t count, uint8_t drive_num) ALIGN 4, db 0x90 read_disk_raw: __CDECL16_ENTRY @@ -88,12 +88,12 @@ read_disk_raw: xor ax, ax push ax ; val = 0 mov ax, lba_packet - mov bx, ax push ax ; dest = lba_packet address call kmemset add sp, 0x06 - mov byte [bx + LBAPkt_t.size], 0x10 + mov bx, lba_packet + mov byte [bx + LBAPkt_t.size], LBAPkt_t_size mov ax, [bp + 12] mov word [bx + LBAPkt_t.xfer_size], ax @@ -104,7 +104,7 @@ read_disk_raw: mov ax, [bp + 6] mov word [bx + LBAPkt_t.offset], ax - mov ax, [bp + 4] + movzx ax, byte [bp + 4] mov word [bx + LBAPkt_t.segment], ax mov si, bx ; ds:si LBAPkt_t diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 9f00869..07bc21c 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -39,7 +39,7 @@ InitFATDriver: .calc_active_part: mov bx, [partition_offset_ptr] - mov ax, [bx + 0] + mov ax, word [ds:bx] mov dx, partition_table add dx, ax ; dx points to the partition that was booted from @@ -93,14 +93,14 @@ SearchFATDIR: .load_first_dir: mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] push dword eax ; cluster - lea ax, [dir_buffer] + mov ax, dir_buffer push ax ; offset xor ax, ax push ax ; segment call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) add sp, 0x8 - lea si, [dir_buffer] + mov si, dir_buffer jmp SearchFATDIR.empty_dir_entry .load_next_dir: @@ -121,7 +121,7 @@ SearchFATDIR: mov eax, [fat32_state + FAT32_State_t.active_dir_cluster_32] push dword eax ; cluster - lea ax, [dir_buffer] + mov ax, dir_buffer push ax ; offset xor ax, ax @@ -129,7 +129,7 @@ SearchFATDIR: call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) sub sp, 0x8 - lea si, [dir_buffer] + mov si, dir_buffer .empty_dir_entry: ; check for 0x0 in first byte, if true then there are no more files ; if true we did not find the file, we should error here @@ -151,7 +151,7 @@ SearchFATDIR: ; if we are at the end of the buffer, then load the next buffer add si, 0x20 ; 32 bytes - lea ax, [dir_buffer] + mov ax, dir_buffer add ax, 0x1FF ; 512 - 1 bytes cmp si, ax jae SearchFATDIR.load_next_dir @@ -169,7 +169,7 @@ SearchFATDIR: mov cx, 0xA ; max of 11 filename length of 11 characters ; si points to the start of the current directory entry - lea di, [BootTarget_str] ; current memory location (8.3 name is at offset 0) + mov di, BootTarget_str ; current memory location (8.3 name is at offset 0) repe cmpsb ; compare the strings pop di @@ -195,10 +195,8 @@ NextCluster: __CDECL16_ENTRY .func: mov bx, [boot_drive_ptr] - movzx ax, byte [bx + 0] - mov byte [bp - 2], al ; save boot drive as a local for easy access - ;movzx ax, byte [bx + 0] ; 67h override would probably work but this is the 16bit way to do it - ;mov byte [bp - 2], al ; save boot drive as a local for easy access + movzx ax, byte [ds:bx] + mov byte [bp - 2], al ; save boot drive as a local for easy access mov edx, dword [bp + 4] mov si, fat32_nc_data @@ -237,6 +235,7 @@ NextCluster: add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: + __BOCHS_MAGIC_DEBUG movzx ax, byte [bp - 2] push ax @@ -287,9 +286,9 @@ ClusterToLBA: ALIGN 4, db 0x90 ReadFATCluster: __CDECL16_ENTRY -.func: +.func: mov bx, [boot_drive_ptr] - movzx ax, byte [bx + 0] + movzx ax, byte [ds:bx] mov byte [bp - 2], al ; save boot drive as a local for easy access mov dword eax, [bp + 8] From 36fcb5faf071917d11d7480d4b17cd2fafea6e0d Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Mon, 14 Oct 2024 17:58:30 -0400 Subject: [PATCH 129/147] 16 KiB stage2 --- include/config.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config.inc b/include/config.inc index ea4bbd7..2a6786f 100755 --- a/include/config.inc +++ b/include/config.inc @@ -21,8 +21,8 @@ %ifndef __INC_STEVIA_CONFIG %define SECTOR_SIZE 512 -%define STAGE2_SECTOR_COUNT 0x30 -; 32 KiB +%define STAGE2_SECTOR_COUNT 0x20 +; 16 KiB %define MAX_STAGE2_BYTES (SECTOR_SIZE * STAGE2_SECTOR_COUNT) %endif From 0f04e682df7c75888c9ead9727d237b38a3e6c03 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Mon, 14 Oct 2024 17:58:43 -0400 Subject: [PATCH 130/147] change entry points (again) --- include/entry.inc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/entry.inc b/include/entry.inc index 0d276ee..81488cb 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -20,11 +20,9 @@ %ifndef __INC_ENTRY -; 8KiB from 0x2500 -> 0x500 -%define EARLY_STACK_START 0xFFFF -%define MBR_ENTRY 0x0600 +%define MBR_ENTRY 0x8C00 %define VBR_ENTRY 0x7C00 -%define STAGE2_ENTRY 0x0500 +%define STAGE2_ENTRY 0x0600 %endif %define __INC_ENTRY \ No newline at end of file From fd7754bc60c745389997e2536ace046ac4217afc Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 12:50:51 -0400 Subject: [PATCH 131/147] I guess wx work again on Debian Trixie? --- bochsrc.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bochsrc.txt b/bochsrc.txt index d65599c..a69b80d 100755 --- a/bochsrc.txt +++ b/bochsrc.txt @@ -1,7 +1,7 @@ # configuration file generated by Bochs plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=false, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false config_interface: textconfig -display_library: sdl2 +display_library: wx memory: guest=64, host=64, block_size=128 romimage: file="/usr/share/bochs/BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none vgaromimage: file="/usr/share/bochs/VGABIOS-lgpl-latest" @@ -50,4 +50,4 @@ com2: enabled=false com3: enabled=false com4: enabled=false magic_break: enabled=1 -port_e9_hack: enabled=1, all_rings=false \ No newline at end of file +port_e9_hack: enabled=1, all_rings=false From 41db11cc64a84d88fe8a92107f17f459263ac711 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 12:51:02 -0400 Subject: [PATCH 132/147] ha ha ha, again! --- include/entry.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/entry.inc b/include/entry.inc index 81488cb..ce5d637 100755 --- a/include/entry.inc +++ b/include/entry.inc @@ -22,7 +22,7 @@ %define MBR_ENTRY 0x8C00 %define VBR_ENTRY 0x7C00 -%define STAGE2_ENTRY 0x0600 +%define STAGE2_ENTRY 0x0500 %endif %define __INC_ENTRY \ No newline at end of file From f81f3589873fd2f83a4f70982f1b92a20300d87b Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 12:51:34 -0400 Subject: [PATCH 133/147] include disk signature and reserved bytes in part table struct --- include/partition_table.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/partition_table.inc b/include/partition_table.inc index abd895a..dec6ca1 100755 --- a/include/partition_table.inc +++ b/include/partition_table.inc @@ -39,6 +39,8 @@ struc PartEntry_t endstruc struc PartTable_t + .signature resb 4 + .reserved resb 2 .partition1 resb PartEntry_t_size .partition2 resb PartEntry_t_size .partition3 resb PartEntry_t_size From 1ce3f67263e3ab2bc47e11b155616be00eb3e686 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 12:53:22 -0400 Subject: [PATCH 134/147] reduced stack size in mbr stage removed some unused data in bss reordered how/when in init we set sp/bp and zero bss we now push the top of the stack pointer/bp at the top of the stack, which makes the stack frame more 'normal' also use movsb instead of movsw --- src/mbr/mbr.nasm | 49 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index 02f61e4..b6d0680 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -19,7 +19,7 @@ ; SOFTWARE. [BITS 16] -[ORG 0x0600] +[ORG 0x8C00] [CPU KATMAI] [WARNING -reloc-abs-byte] [WARNING -reloc-abs-word] ; Yes, we use absolute addresses. surpress these warnings. @@ -49,7 +49,10 @@ init: mov fs, ax mov gs, ax - ; + mov ss, ax ; Set Stack Segment to 0 + mov sp, end_bss ; Setup stack + mov bp, sp ; base ptr = stack ptr + ; Zero BSS section mov cx, (end_bss - begin_bss) ; count = bss length mov ax, begin_bss @@ -58,16 +61,14 @@ init: cld rep stosb ; zero bss section - mov ss, ax ; Set Stack Segment to 0 - mov sp, stack_top ; Setup stack - mov bp, sp ; base ptr = stack ptr - sub sp, 0x10 ; local varible space + sub sp, 0x20 ; local varible space + push bp ; setup top of stack frame xor cx, cx - mov ch, 0x01 ; 256 WORDs in MBR (512 bytes), 0x0100 in cx + mov ch, 0x02 ; 0x0200 in cx mov si, 0x7C00 ; Current MBR Address (loaded here by BIOS) mov di, MBR_ENTRY ; New MBR Address (our new relocation address) - rep movsw ; copy 512 bytes from 0x0000:7c00 to 0x0000:MBR_ENTRY (7A00 as of writing) + rep movsb ; copy 512 bytes from 0x0000:7c00 to 0x0000:MBR_ENTRY (7A00 as of writing) sti @@ -88,14 +89,16 @@ main: mov byte [bp - 2], dl ; BIOS passes drive number in DL .check_disk: - cmp dl, 0x80 + cmp byte [bp - 2], 0x80 jae main.check_extentions + ERROR MBR_ERROR_DISK_T_ERR .check_extentions: xor ax, ax + mov ah, 0x41 mov bx, 0x55AA - mov dl, byte [bp - 2] + mov dl, 0x80 int 0x13 jnc main.find_active ERROR MBR_ERROR_NO_INT32E ; no extended function support @@ -107,9 +110,9 @@ main: mov al, byte [bx + PartEntry_t.attributes] test al, 0x80 ; 0x80 == 1000_0000b jnz main.active_found - add bx, 0x10 ; add 16 bytes to offset loop main.find_active_L0 + ERROR MBR_ERROR_NO_NO_BOOT_PART .active_found: @@ -151,11 +154,12 @@ main: push ax call kmemcpy ; copy partition table to bss add sp, 0x6 - + mov si, word [bp - 4] mov dl, byte [bp - 2] mov bx, partition_table - jmp word 0x0000:0x7C00 + __BOCHS_MAGIC_DEBUG + jmp word 0x0000:VBR_ENTRY ; ############### ; @@ -171,11 +175,8 @@ times ((512 - 72) - ($ - $$)) nop ; Fill the rest of sector with nop DiskSig: times 4 db 0x00 -Reserved1: - db 0x00 -Reserved2: - db 0x00 - +Reserved: + dw 0x0000 PartEntry1: times 16 db 0x00 PartEntry2: @@ -186,26 +187,18 @@ PartEntry4: times 16 db 0x00 BootSig: dw 0xAA55 ; Add boot signature at the end of bootloader -; this should mark the 512 byte mark...if not, something has gone wrong. + section .bss follows=.text begin_bss: align 16, resb 1 partition_table resb PartTable_t_size -align 16, resb 1 -fat32_bpb resb FAT32_bpb_t_size -fat32_ebpb resb FAT32_ebpb_t_size - -align 16, resb 1 -fat32_nc_data resb 16 - align 16, resb 1 lba_packet resb LBAPkt_t_size align 512, resb 1 -stack_bottom resb 1024 ; 1Kib stack early on - +stack_bottom resb 512 ; 512 byte stack early on stack_top: mbr_redzone resb 32 end_bss: \ No newline at end of file From 2b9d0d99468e3f51d5cd815d8fe622b26f6a887f Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 12:56:12 -0400 Subject: [PATCH 135/147] moved stack to end of bss & reduced size for now. removed redzone label reordered sp/bp setup and bss zeroing in init: fixed kmemcpy call stack usage --- src/stage2/stage2.nasm | 62 ++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 994530d..f0c29d8 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -47,8 +47,6 @@ %endmacro section .text -org 0x0500 - begin_text: jmp short (init - $$) nop @@ -59,39 +57,36 @@ nop ; dx = ptr FAT32_bpb_t fat32_bpb ALIGN 4, db 0x90 init: + __BOCHS_MAGIC_DEBUG cli ; We do not want to be interrupted - ; + mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment, excep es + mov ds, ax ; * + mov fs, ax ; * + mov gs, ax ; * + mov ss, ax + ; Zero BSS section - ; mov cx, (end_bss - begin_bss) ; count = bss length mov ax, begin_bss shr ax, 4 - mov es, ax ; es = begining of bss section - - xor ax, ax - mov di, ax ; dst = 0 + mov es, ax ; es = begining of bss section, remember to restore ES later + xor ax, ax ; val = 0 + mov di, ax ; dst = 0 (start of segment) cld - rep stosb ; zero bss section - ; done zeroing BSS + rep stosb - mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment - mov ds, ax ; * - mov es, ax ; * - mov fs, ax ; * - mov gs, ax ; * + mov ax, __STAGE2_SEGMENT + mov es, ax + ; done zeroing bss section - mov ss, ax ; Set Stack Segment to data segment - mov sp, stack_top ; Set Stack Pointer - - mov ax, init - push ax ; simulate a return value to the begining of the stage2 loader - - push bp + mov sp, stack_top mov bp, sp - sub sp, 0x20 ; 32 bytes for local varibles + sub sp, 0x20 + push bp ; setup a somewhat normal stack frame, minus a ret ptr + sti jmp word __STAGE2_SEGMENT:main @@ -154,14 +149,15 @@ main: mov ax, PartTable_t_size push ax mov ax, [bp - 6] ; ptr partition_table + push ax mov ax, partition_table push ax call kmemcpy ; copy partition table data add sp, 0x6 - + mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte push ax - mov ax, [bp - 8] ; start of bpb - 0x3 for the jump short main at the start + mov ax, [bp - 8] push ax mov ax, fat32_bpb ; defined in memory.inc, destination push ax @@ -196,7 +192,6 @@ main: print_string FileFound_OK_cstr push dword eax call PrintDWORD ; void PrintDWORD(uint32_t dword) - add sp, 0x4 print_string NewLine_cstr hcf: ERROR STEVIA_DEBUG_OK @@ -297,7 +292,7 @@ PrintDWORD: push ax call PrintCharacter add sp, 0x2 - + pop cx jcxz PrintDWORD.endp @@ -491,17 +486,8 @@ times ((512 - 4) - ($ -$$) ) db 0x90 ; nop STAGE2_SIG: dd 0xDEADBEEF ; Signature to mark the end of the stage2 section .bss follows=.sign -align 512, resb 1 begin_bss: -stack_bottom: - resb 4096 -stack_top: -stage2_main_redzone: - resb 32 - -; ; structures -; align 16, resb 1 partition_table resb PartTable_t_size @@ -550,4 +536,8 @@ align 16, resb 1 BIOSMemoryMap: resb 2048 +align 512, resb 1 +stack_bottom: + resb 1024 +stack_top: end_bss: \ No newline at end of file From 8e2ca06406cb570b03d197cdcb07d6e4181a2975 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 12:57:54 -0400 Subject: [PATCH 136/147] removed bpb_offset_bx dep reworked init: process 512 byte stack...should be more than enough for the vbr --- src/vbr/vbr.nasm | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index f17c041..7f1ceab 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -50,7 +50,6 @@ times 54 db 0x00 %include "error_codes.inc" %include "partition_table.inc" %include "fat32/fat32_structures.inc" -%include "fat32/bpb_offset_bx.inc" ; ; dl = boot_drive ; si = part_offset @@ -61,6 +60,12 @@ init: xor ax, ax mov ds, ax ; Set segment registers to 0x0000 mov es, ax + mov fs, ax + mov gs, ax + + mov ss, ax ; Set Stack Segment to 0 + mov sp, end_bss ; Setup stack + mov bp, sp ; base ptr = stack ptr ; zero bss section mov cx, (end_bss - begin_bss) ; count = bss length @@ -68,15 +73,11 @@ init: mov di, ax ; es:di is dest xor ax, ax cld - rep stosb + rep stosb + + sub sp, 0x20 ; local varible space + push bp - xor ax, ax - mov ss, ax ; Set Stack Segment to 0 - mov sp, stack_top ; Setup stack - mov bp, sp ; base ptr = stack ptr - sub sp, 0x10 ; local varible space - - mov cx, bx ; mov partition_table locaiton to cx sti ; all done with inital setup and relocation, reenable interupts jmp 0:main ; fix up cs:ip just in case and jump to relocated code @@ -100,18 +101,19 @@ ALIGN 4, db 0x90 main: mov byte [bp - 2], dl ; boot_drive mov word [bp - 4], si ; part_offset - mov word [bp - 6], cx ; partition_table + mov word [bp - 6], bx ; partition_table .load_fs_data: - mov ax, PartTable_t_size + mov ax, PartTable_t_size ; count= + push ax + mov ax, [bp - 6] ; src= ptr partition_table push ax - mov ax, [bp - 6] ; ptr partition_table - mov ax, partition_table + mov ax, partition_table ; dst= push ax call kmemcpy ; copy partition table data add sp, 0x6 - - mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte + + mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte, should be 90 bytes push ax mov ax, __ENTRY push ax @@ -120,9 +122,9 @@ main: call kmemcpy ; copy bpb & ebpb to memory add sp, 0x6 - mov bx, fat32_bpb ; bx now points to aligned memory structure .check_FAT_size: ; we only support a very specific setup of FAT32 - cmp dword [bsSectorHuge], 0 ; SectorsHuge will not be set if FAT12/16 + mov bx, fat32_bpb + cmp dword [bx + FAT32_bpb_t.sector_count_32], 0 ; SectorsHuge will not be set if FAT12/16 ja main.load_stage2 ERROR VBR_ERROR_WRONG_FAT_SIZE .load_stage2: @@ -185,8 +187,7 @@ align 16, resb 1 lba_packet resb LBAPkt_t_size align 512, resb 1 -stack_bottom resb 1024 ; 1Kib stack early on - +stack_bottom resb 512 ; 512b stack early on stack_top: vbr_redzone resb 32 end_bss: \ No newline at end of file From 47a47051b2057615d811bd6479077bdd883e9f3c Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 13:31:32 -0400 Subject: [PATCH 137/147] turn off magic debug in mbr/vbr stages --- src/mbr/mbr.nasm | 3 ++- src/vbr/vbr.nasm | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mbr/mbr.nasm b/src/mbr/mbr.nasm index b6d0680..0ae7a8a 100755 --- a/src/mbr/mbr.nasm +++ b/src/mbr/mbr.nasm @@ -40,6 +40,8 @@ nop %include "partition_table.inc" %include "fat32/fat32_structures.inc" +%undef __STEVIA_DEV_DEBUG + ALIGN 4 init: cli ; We do not want to be interrupted @@ -158,7 +160,6 @@ main: mov si, word [bp - 4] mov dl, byte [bp - 2] mov bx, partition_table - __BOCHS_MAGIC_DEBUG jmp word 0x0000:VBR_ENTRY ; ############### diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 7f1ceab..729cc1e 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -50,7 +50,9 @@ times 54 db 0x00 %include "error_codes.inc" %include "partition_table.inc" %include "fat32/fat32_structures.inc" -; + +%undef __STEVIA_DEV_DEBUG + ; dl = boot_drive ; si = part_offset ; bx = partition_table location from mbr From 6731e03e3837a6191d2cc9b6abf13e4a0bc93fc8 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 13:31:51 -0400 Subject: [PATCH 138/147] magic debug before touching anything in error printer --- include/util/error_func.nasm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/util/error_func.nasm b/include/util/error_func.nasm index 271cf97..e289cb5 100644 --- a/include/util/error_func.nasm +++ b/include/util/error_func.nasm @@ -21,13 +21,11 @@ %ifndef __INC_ERROR_FUNC %macro ERROR 1 - mov al, %1 ; al = 1 byte error code mapped to ascii values %ifdef __STEVIA_DEV_DEBUG __BOCHS_MAGIC_DEBUG %endif + mov al, %1 ; al = 1 byte error code mapped to ascii values jmp error - - %endmacro ; pass error as ascii character in al, errors a-zA-Z or 0-9 From e65220fece3ab6b36f7fd674ea653216197c0db8 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 13:32:36 -0400 Subject: [PATCH 139/147] correct size of operand in PrintDWORD added some magic debug points for stuff that isn't working as well. --- src/stage2/stage2.nasm | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index f0c29d8..16a9af4 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -180,19 +180,26 @@ main: call GetMemoryMap print_string MemoryMap_OK_cstr + __BOCHS_MAGIC_DEBUG ; FAT Driver setup call InitFATDriver print_string InitFATSYS_OK_cstr ; ; Find first cluster of bootable file - ; + __BOCHS_MAGIC_DEBUG call SearchFATDIR - push dword eax + push dword eax ; save first cluster of bootable file + print_string FileFound_OK_cstr - push dword eax + + pop dword eax + push dword eax ; print Cluster of boot file call PrintDWORD ; void PrintDWORD(uint32_t dword) - print_string NewLine_cstr + print_string NewLine_cstr + + ; TODO: using first cluster information, start loading the kernel to memory + ; TODO: going to need an elf parser, some unreal mode file buffer functions to move the data hcf: ERROR STEVIA_DEBUG_OK @@ -262,7 +269,7 @@ PrintDWORD: lea si, [IntToHex_table] mov ebx, 16 ; base-16 - mov dword eax, [bp + 4] ;val + mov eax, dword [bp + 4] ;val xor edx, edx xor cx, cx @@ -292,7 +299,7 @@ PrintDWORD: push ax call PrintCharacter add sp, 0x2 - + pop cx jcxz PrintDWORD.endp From 915ac4c8aee94ef2ab5ece67506151e75ba93b08 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 18:28:06 -0400 Subject: [PATCH 140/147] align to 16 byte bounds and add git info to build --- Makefile | 19 ++++++++++++------- src/stage2/stage2.nasm | 24 +++++++++++++++--------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index baf15ff..43b4d39 100755 --- a/Makefile +++ b/Makefile @@ -1,6 +1,3 @@ -iso := '/tmp/disk.img' -isoz := 'disk.img.gz' - include := './include' mbr_source_files := $(wildcard src/mbr/*.nasm) @@ -15,6 +12,14 @@ boottest_binary_files := $(patsubst src/miniboot32/%.nasm, build/%.bin, $(bootte build_dir := 'build' +# Get current Git version (tag) and hash +GIT_VERSION := $(shell git describe --tags) +GIT_HASH := $(shell git rev-parse HEAD) +GIT_NASM_DEFINES := -D __GIT_VER__='"$(GIT_VERSION)"' -D __GIT_HASH__='"$(GIT_HASH)"' + +iso := '/tmp/disk.img' +isoz := 'disk.img.gz' + qemu_args := -L ./bin/ -bios bios.bin -cpu pentium3 -m 128 -S -s -monitor stdio -nic none .PHONY: all mbr vbr stage2 boottest clean run run_bochs iso isoz @@ -44,19 +49,19 @@ isoz: $(isoz) build/%.bin: src/mbr/%.nasm @mkdir -p $(shell dirname $@) - @nasm -i$(include) -Wall -f bin $< -o $@ + @nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@ build/%.bin: src/vbr/%.nasm @mkdir -p $(shell dirname $@) - @nasm -i$(include) -Wall -f bin $< -o $@ + @nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@ build/%.bin: src/stage2/%.nasm @mkdir -p $(shell dirname $@) - @nasm -i$(include) -Wall -f bin $< -o $@ + @nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@ build/%.bin: src/miniboot32/%.nasm @mkdir -p $(shell dirname $@) - @nasm -i$(include) -Wall -f bin $< -o $@ + @nasm -i$(include) -Wall -f bin $(GIT_NASM_DEFINES) $< -o $@ $(iso): $(mbr_binary_files) $(vbr_binary_files) $(stage2_binary_files) $(boottest_binary_files) @echo root access needed to create disk image... diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 16a9af4..a2f60cd 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -180,14 +180,12 @@ main: call GetMemoryMap print_string MemoryMap_OK_cstr - __BOCHS_MAGIC_DEBUG ; FAT Driver setup call InitFATDriver print_string InitFATSYS_OK_cstr ; ; Find first cluster of bootable file - __BOCHS_MAGIC_DEBUG call SearchFATDIR push dword eax ; save first cluster of bootable file @@ -381,7 +379,7 @@ begin_data: ; ############# %macro define_str 2 - ALIGN 4 + ALIGN 16 %1_str: db %2 %define str_len %strlen(%2) ; string @@ -394,7 +392,7 @@ begin_data: ; TODO: place that newline and return %macro define_cstr 2 %define CRLF_NUL 0Dh, 0Ah, 00h - ALIGN 4 + ALIGN 16 %1_cstr: db %2, CRLF_NUL %endmacro @@ -410,7 +408,7 @@ define_cstr NewLine, "" define_str BootTarget, "BOOT BIN" -ALIGN 4 +ALIGN 16 IntToHex_table: db '0123456789ABCDEF' @@ -474,13 +472,21 @@ gdt32_start: db 0x00 gdt32_end: -ALIGN 8 -version_magic: +ALIGN 8,db 0x00 +BUILD_NASM_VER: db "Stevia Stage2 built with NASM - ", __NASM_VER__, 00h -ALIGN 8 -datetime_magic: +ALIGN 8,db 0x00 +BUILD_DATETIME: db 'Assembled - ', __DATE__, ' ', __TIME__, 00h + +ALIGN 8,db 0x00 +BUILD_GIT_VER: + db __GIT_VER__, 00h + +ALIGN 8,db 0x00 +BUILD_GIT_HASH: + db __GIT_HASH__, 00h end_data: %assign bytes_remaining ((MAX_STAGE2_BYTES - 4) - ($ - $$)) From e085cbbab72df91571b715d49b68c8a7d32420a9 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 18:33:57 -0400 Subject: [PATCH 141/147] remove jmp short init at the start of stage2 also correct total size output as combined .data + .text --- src/stage2/stage2.nasm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index a2f60cd..e87a9cb 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -48,9 +48,6 @@ section .text begin_text: -jmp short (init - $$) -nop - ; dl = byte boot_drive ; si = word part_offset (active partition offset) ; bx = ptr PartTable_t partition_table @@ -489,7 +486,7 @@ BUILD_GIT_HASH: db __GIT_HASH__, 00h end_data: -%assign bytes_remaining ((MAX_STAGE2_BYTES - 4) - ($ - $$)) +%assign bytes_remaining ((MAX_STAGE2_BYTES - 4) - (($ - $$) + (end_text - begin_text))) %warning STAGE2 has bytes_remaining bytes remaining for code/data (MAX: MAX_STAGE2_BYTES) ; section start location needs to be a 'critical expression' From f1842d0cbc40cf6b3f9ae9ce4ec3b45936b79bc1 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 20:01:24 -0400 Subject: [PATCH 142/147] remove some redundant reloads of si use xchg to swap si/di instead of the stack uninline ClusterToLBA call --- include/fat32/FAT32_SYS.inc | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 07bc21c..86c7255 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -128,8 +128,6 @@ SearchFATDIR: push ax ; segment call ReadFATCluster ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) sub sp, 0x8 - - mov si, dir_buffer .empty_dir_entry: ; check for 0x0 in first byte, if true then there are no more files ; if true we did not find the file, we should error here @@ -199,7 +197,8 @@ NextCluster: mov byte [bp - 2], al ; save boot drive as a local for easy access mov edx, dword [bp + 4] - mov si, fat32_nc_data + mov si, fat32_nc_data ; instead of push/pop and moving the data back + mov di, fat32_bpb ; load si & di then use xchg .calc_offset: ; fat_offset = active_cluster * 4 mov eax, 4 @@ -213,10 +212,9 @@ NextCluster: and edx, eax shr edx, 16 - push si - mov si, fat32_bpb + xchg si, di ; switch to fat32_bpb in si mov cx, word [si + FAT32_bpb_t.bytes_per_sector_16] - pop si + xchg si, di div cx ; DX:AX / cx = fat_sector - first_fat_sector in AX ; DX = remainder (fat_offset mod sector_size) @@ -225,17 +223,15 @@ NextCluster: and edx, ecx mov dword [si + FAT32_NextClusterData_t.entry_offset], edx - push si - mov si, fat32_state + xchg si, di ; switch to fat32_bpb in si mov ecx, dword [si + FAT32_State_t.first_fat_sector_32] - pop si + xchg si, di mov edx, 0x0000ffff and eax, edx add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: - __BOCHS_MAGIC_DEBUG movzx ax, byte [bp - 2] push ax @@ -280,7 +276,6 @@ ClusterToLBA: __CDECL16_EXIT ret -; bp - 6 - dword lba ; bp - 2 - byte boot_drive ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) ALIGN 4, db 0x90 @@ -291,23 +286,18 @@ ReadFATCluster: movzx ax, byte [ds:bx] mov byte [bp - 2], al ; save boot drive as a local for easy access - mov dword eax, [bp + 8] - ; inline ClusterToLBA - sub eax, 2 - movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8] - mul edx - add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32] - ; eax contains the LBA now - mov dword [bp - 6], eax ; save lba - movzx ax, byte [bp - 2] ; drive_num = boot_drive push ax mov ax, 0x1 ; count = 1 push ax - mov eax, dword [bp - 6] ; lba = ClusterToLBA return value + mov eax, dword [bp + 8] push dword eax + call ClusterToLBA + add sp, 0x4 + ; eax contains the LBA now + push dword eax ; save lba mov ax, fat_buffer ; offset = fat_buffer (in mem.inc) push ax From 38bcd93cedfa8daa56a90c36c5515f797197034a Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Tue, 15 Oct 2024 20:37:49 -0400 Subject: [PATCH 143/147] some debuging text for fat32 stuff --- include/fat32/FAT32_SYS.inc | 13 ++++++++++--- src/stage2/stage2.nasm | 6 +++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 86c7255..979d939 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -90,6 +90,8 @@ ALIGN 4, db 0x90 SearchFATDIR: __CDECL16_ENTRY .file_lookup: + print_string SearchFATDIR_INFO_cstr + .load_first_dir: mov eax, dword [fat32_state + FAT32_State_t.active_dir_cluster_32] push dword eax ; cluster @@ -156,6 +158,7 @@ SearchFATDIR: jmp SearchFATDIR.empty_dir_entry .parse_dir: + print_string MaybeFound_Boot_INFO_cstr .lfn_check: ; check for ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID (0x0F) in offset 11 ; TODO: going to skip LFN for now, since all valid volumes will have SFN's @@ -182,8 +185,8 @@ SearchFATDIR: .endp: __CDECL16_EXIT ret + ; BUG: this function needs review -; ; bp - 2 - byte boot_drive ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) @@ -192,6 +195,8 @@ ALIGN 4, db 0x90 NextCluster: __CDECL16_ENTRY .func: + print_string NextFATCluster_INFO_cstr + mov bx, [boot_drive_ptr] movzx ax, byte [ds:bx] mov byte [bp - 2], al ; save boot drive as a local for easy access @@ -202,8 +207,8 @@ NextCluster: .calc_offset: ; fat_offset = active_cluster * 4 mov eax, 4 - mul edx - mov dword [si + FAT32_NextClusterData_t.fat_offset], eax + mul edx ; BUG: should check for carry here + mov dword [si + FAT32_NextClusterData_t.fat_offset], eax ; move lower 32 bits to fat offset .calc_fat_sector: ; fat_sector = first_fat_sector + (fat_offset / sector_size) @@ -282,6 +287,8 @@ ALIGN 4, db 0x90 ReadFATCluster: __CDECL16_ENTRY .func: + print_string ReadFATCluster_INFO_cstr + mov bx, [boot_drive_ptr] movzx ax, byte [ds:bx] mov byte [bp - 2], al ; save boot drive as a local for easy access diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index e87a9cb..998073d 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -400,8 +400,12 @@ define_cstr MemoryMap_OK, "Memory map OK" define_cstr UnrealMode_OK, "Unreal mode OK" define_cstr FileFound_OK, "Found SFN entry for bootable binary, first cluster -> " define_cstr InitFATSYS_OK, "FAT32 Driver Init..." -define_cstr NewLine, "" +define_cstr SearchFATDIR_INFO, "Searching FAT DIR for bootable file..." +define_cstr NextFATCluster_INFO, "Attempting to find next FAT cluster..." +define_cstr ReadFATCluster_INFO, "Attempting to load next FAT" +define_cstr MaybeFound_Boot_INFO, "Maybe found a file...checking..." +define_cstr NewLine, "" define_str BootTarget, "BOOT BIN" From a8301915479c0495aa89440859ff28dede41296a Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Wed, 16 Oct 2024 11:58:57 -0400 Subject: [PATCH 144/147] added carry and divz checks across the fat32 code also use the pointers we have in bss to our saved data --- include/error_codes.inc | 6 ++--- include/fat32/FAT32_SYS.inc | 46 ++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/include/error_codes.inc b/include/error_codes.inc index d1eb182..2eb86f2 100755 --- a/include/error_codes.inc +++ b/include/error_codes.inc @@ -60,9 +60,9 @@ %define STAGE2_FAT32_INIT_ERROR 'H' %define STAGE2_FAT32_NO_FILE 'I' %define STAGE2_FAT32_END_OF_CHAIN 'J' -%define STAGE2_ERROR_RESERVED_K 'K' -%define STAGE2_ERROR_RESERVED_L 'L' -%define STAGE2_ERROR_RESERVED_M 'M' +%define STAGE2_FAT32_NCLUS_CFDIVZ 'K' +%define STAGE2_FAT32_CLS2LBA_CF 'L' +%define STAGE2_FAT32_INIT_CF 'M' %define STAGE2_ERROR_RESERVED_N 'N' %define STAGE2_ERROR_RESERVED_O 'O' %define STAGE2_ERROR_RESERVED_P 'P' diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index 979d939..b4f25d9 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -70,12 +70,11 @@ InitFATDriver: mov dword [fat32_state + FAT32_State_t.first_root_dir_sector_32], eax ; this only works when 1 cluster = 1 sector mov dword [fat32_state + FAT32_State_t.active_dir_cluster_32], eax - jmp InitFATDriver.endp -.error: - ERROR STAGE2_FAT32_INIT_ERROR .endp: __CDECL16_EXIT ret +.error: + ERROR STAGE2_FAT32_INIT_CF ; this involves using the low memory buffer for the bios call and moving the file sector by sector to high memory ; @@ -115,6 +114,7 @@ SearchFATDIR: add sp, 0x4 cmp eax, 0x0fff_fff7 + je SearchFATDIR.bad_cluster jb SearchFATDIR.load_next_dir_next_OK ERROR STAGE2_FAT32_END_OF_CHAIN @@ -187,7 +187,6 @@ SearchFATDIR: ret ; BUG: this function needs review -; bp - 2 - byte boot_drive ; uint32_t NextCluster(uint32_t active_cluster); ; if eax >= 0x0FFFFFF8 then there are no more clusters (end of chain) ; if eax == 0x0FFFFFF7 then this is a cluster that is marked as bad @@ -196,18 +195,14 @@ NextCluster: __CDECL16_ENTRY .func: print_string NextFATCluster_INFO_cstr - - mov bx, [boot_drive_ptr] - movzx ax, byte [ds:bx] - mov byte [bp - 2], al ; save boot drive as a local for easy access - mov edx, dword [bp + 4] mov si, fat32_nc_data ; instead of push/pop and moving the data back mov di, fat32_bpb ; load si & di then use xchg .calc_offset: ; fat_offset = active_cluster * 4 mov eax, 4 - mul edx ; BUG: should check for carry here + mul edx + jc NextCluster.error_cfdivz mov dword [si + FAT32_NextClusterData_t.fat_offset], eax ; move lower 32 bits to fat offset .calc_fat_sector: @@ -221,6 +216,8 @@ NextCluster: mov cx, word [si + FAT32_bpb_t.bytes_per_sector_16] xchg si, di + cmp edx, 0 + je NextCluster.error_cfdivz div cx ; DX:AX / cx = fat_sector - first_fat_sector in AX ; DX = remainder (fat_offset mod sector_size) @@ -237,7 +234,8 @@ NextCluster: add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: - movzx ax, byte [bp - 2] + mov bx, word [boot_drive_ptr] + movzx ax, byte [ds:bx] push ax mov ax, 0x1 @@ -252,6 +250,20 @@ NextCluster: xor ax, ax push ax + ; BUG: something about this function causes this BIOS call to come back wrong + ; somehow the drive number is being read in wrong, but I can't find evidence of it being modified or writen + ; to memory incorrectly. + ; 00007109574i[BIOS ] Booting from 0000:7c00 + ; 00007123227i[CPU0 ] [7123227] Stopped on MAGIC BREAKPOINT + ; (0) Magic breakpoint + ; Next at t=7123227 + ; (0) [0x000000000502] 0000:0502 (unk. ctxt): cli ; fa + ; c + ; 00007252963i[BIOS ] int13_diskette: unsupported AH=42 + ; 00007253071i[CPU0 ] [7253071] Stopped on MAGIC BREAKPOINT + ; (0) Magic breakpoint + ; Next at t=7253071 + ; (0) [0x00000000095c] 0000:095c (unk. ctxt): mov al, 0x47 ; b047 call read_disk_raw add sp, 0xC ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset, @@ -265,6 +277,8 @@ NextCluster: .endp: __CDECL16_EXIT ret +.error_cfdivz: + ERROR STAGE2_FAT32_NCLUS_CFDIVZ ; uint32_t ClusterToLBA(uint32_t cluster) ALIGN 4, db 0x90 @@ -275,11 +289,14 @@ ClusterToLBA: sub eax, 2 movzx edx, byte [fat32_bpb + FAT32_bpb_t.sectors_per_cluster_8] mul edx + jc ClusterToLBA.error add eax, dword [fat32_state + FAT32_State_t.first_data_sector_32] ; eax contains the LBA now .endp: __CDECL16_EXIT ret +.error: + ERROR STAGE2_FAT32_CLS2LBA_CF ; bp - 2 - byte boot_drive ; uint8_t ReadFATCluster(uint16_t seg, uint16_t offset, uint32_t cluster) @@ -289,11 +306,8 @@ ReadFATCluster: .func: print_string ReadFATCluster_INFO_cstr - mov bx, [boot_drive_ptr] + mov bx, word [boot_drive_ptr] movzx ax, byte [ds:bx] - mov byte [bp - 2], al ; save boot drive as a local for easy access - - movzx ax, byte [bp - 2] ; drive_num = boot_drive push ax mov ax, 0x1 ; count = 1 @@ -304,7 +318,7 @@ ReadFATCluster: call ClusterToLBA add sp, 0x4 ; eax contains the LBA now - push dword eax ; save lba + push dword eax ; lba = ClusterToLBA(..) mov ax, fat_buffer ; offset = fat_buffer (in mem.inc) push ax From 2c5e5ccbeed2f2e59b13cc4cf487c0b90a15096d Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 19 Dec 2024 13:13:46 -0500 Subject: [PATCH 145/147] might have fixed some of the boot_drive issues with ext_read --- bochsrc.bxrc | 23 +++++++------ include/fat32/FAT32_SYS.inc | 13 ++++--- src/stage2/stage2.nasm | 68 +++++++++++++++++++------------------ src/vbr/vbr.nasm | 8 ++--- 4 files changed, 57 insertions(+), 55 deletions(-) diff --git a/bochsrc.bxrc b/bochsrc.bxrc index 34c323d..6bd34d5 100644 --- a/bochsrc.bxrc +++ b/bochsrc.bxrc @@ -1,20 +1,18 @@ # configuration file generated by Bochs -plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=false, es1370=false, gameport=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false +plugin_ctrl: voodoo=false, unmapped=true, biosdev=true, speaker=true, extfpuirq=true, parallel=true, serial=true, busmouse=false, e1000=false, es1370=false, gameport=true, iodebug=true, ne2k=false, sb16=false, usb_uhci=false, usb_ohci=false, usb_ehci=false, usb_xhci=false config_interface: win32config display_library: win32 memory: guest=64, host=64, block_size=128 -romimage: file="C:\Program Files\Bochs-2.8\BIOS-bochs-latest", address=0x00000000, options=none, flash_data=none +romimage: file="C:\Program Files\Bochs-2.8\BIOS-bochs-legacy", address=0x00000000, options=none, flash_data=none vgaromimage: file="C:\Program Files\Bochs-2.8\VGABIOS-lgpl-latest" boot: disk -floppy_bootsig_check: disabled=0 +floppy_bootsig_check: disabled=1 floppya: type=1_44 # no floppyb ata0: enabled=true, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 -ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=0, spt=0, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=lba +ata0-master: type=disk, path=".\disk.img", mode=flat, cylinders=0, heads=16, spt=63, sect_size=512, model="Stevia Disk", biosdetect=auto, translation=auto ata0-slave: type=none -ata1: type=none -ata1-master: type=none -ata1-slave: type=none +ata1: enabled=false ata2: enabled=false ata3: enabled=false optromimage1: file=none @@ -29,7 +27,10 @@ pci: enabled=1, chipset=i440fx, slot1=none, slot2=none, slot3=none, slot4=none, vga: extension=vbe, update_freq=10, realtime=1, ddc=builtin cpu: count=1, ips=1000000, model=p3_katmai, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 print_timestamps: enabled=0 -port_e9_hack: enabled=false, all_rings=false +debugger_log: - +magic_break: enabled=1 +port_e9_hack: enabled=true, all_rings=false +iodebug: all_rings=0 private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 # no cmosimage @@ -43,9 +44,9 @@ keyboard: type=mf, serial_delay=150, paste_delay=100000, user_shortcut=none mouse: type=none, enabled=false, toggle=ctrl+mbutton sound: waveoutdrv=dummy, waveout=none, waveindrv=dummy, wavein=none, midioutdrv=dummy, midiout=none speaker: enabled=true, mode=sound, volume=15 -parport1: enabled=true, file=none +parport1: enabled=false parport2: enabled=false -com1: enabled=true, mode=null +com1: enabled=false com2: enabled=false com3: enabled=false -com4: enabled=false +com4: enabled=false \ No newline at end of file diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index b4f25d9..e6b8355 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -38,8 +38,7 @@ InitFATDriver: sub sp, 0x6 .calc_active_part: - mov bx, [partition_offset_ptr] - mov ax, word [ds:bx] + mov ax, word partition_offset mov dx, partition_table add dx, ax ; dx points to the partition that was booted from @@ -114,7 +113,7 @@ SearchFATDIR: add sp, 0x4 cmp eax, 0x0fff_fff7 - je SearchFATDIR.bad_cluster + ;je SearchFATDIR.bad_cluster ; TODO: Implement Bad cluster checks jb SearchFATDIR.load_next_dir_next_OK ERROR STAGE2_FAT32_END_OF_CHAIN @@ -234,8 +233,8 @@ NextCluster: add eax, ecx ; fat_sector + first_fat_sector mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: - mov bx, word [boot_drive_ptr] - movzx ax, byte [ds:bx] + xor ax, ax + mov al, boot_drive push ax mov ax, 0x1 @@ -306,8 +305,8 @@ ReadFATCluster: .func: print_string ReadFATCluster_INFO_cstr - mov bx, word [boot_drive_ptr] - movzx ax, byte [ds:bx] + xor ax, ax + mov al, boot_drive push ax mov ax, 0x1 ; count = 1 diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 998073d..834958f 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -49,14 +49,18 @@ section .text begin_text: ; dl = byte boot_drive -; si = word part_offset (active partition offset) -; bx = ptr PartTable_t partition_table -; dx = ptr FAT32_bpb_t fat32_bpb +; ax = word part_offset (active partition offset) +; si = ptr PartTable_t partition_table +; di = ptr FAT32_bpb_t fat32_bpb ALIGN 4, db 0x90 init: - __BOCHS_MAGIC_DEBUG cli ; We do not want to be interrupted + mov [vbr_part_table_ptr], bx ; pointer to partition_table + mov [vbr_fat32_bpb_ptr], dx ; pointer to fat32_bpb + mov [boot_drive], dl ; copy boot_drive to globals + mov [partition_offset], ax ; copy partition_offset to globals + mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment, excep es mov ds, ax ; * mov fs, ax ; * @@ -81,7 +85,7 @@ init: mov sp, stack_top mov bp, sp - sub sp, 0x20 + sub sp, 0x10 push bp ; setup a somewhat normal stack frame, minus a ret ptr sti @@ -121,22 +125,9 @@ struc EarlyBootStruct_t .fat32_ebpb resb FAT32_ebpb_t_size endstruc -; bp - 2 : byte boot_drive -; bp - 4 : word part_offset -; bp - 6 : ptr PartTable_t partition_table -; bp - 8 : ptr FAT32_bpb_t fat32_bpb ALIGN 4, db 0x90 main: - lea ax, [bp - 2] - mov [boot_drive_ptr], ax - - lea ax, [bp - 4] - mov [partition_offset_ptr], ax ; setup pointers to boot_drive and partition offset on stack - - mov byte [bp - 2], dl ; boot_drive (probably 0x80) - mov word [bp - 4], si ; partition_offset - mov word [bp - 6], bx ; partition_table - mov word [bp - 8], dx ; fat32_bpb + __BOCHS_MAGIC_DEBUG .check_sig: mov eax, dword [STAGE2_SIG] cmp eax, 0xDEADBEEF @@ -145,20 +136,20 @@ main: .stage2_main: mov ax, PartTable_t_size push ax - mov ax, [bp - 6] ; ptr partition_table + mov ax, word [vbr_part_table_ptr] ; ptr partition_table push ax mov ax, partition_table push ax - call kmemcpy ; copy partition table data + call kmemcpy ; copy partition table data add sp, 0x6 mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte push ax - mov ax, [bp - 8] + mov ax, word [vbr_fat32_bpb_ptr] push ax - mov ax, fat32_bpb ; defined in memory.inc, destination + mov ax, fat32_bpb ; defined in memory.inc, destination push ax - call kmemcpy ; copy bpb & ebpb to memory + call kmemcpy ; copy bpb & ebpb to memory add sp, 0x6 call SetTextMode @@ -503,33 +494,44 @@ section .bss follows=.sign begin_bss: ; structures -align 16, resb 1 +align 8, resb 1 partition_table resb PartTable_t_size -align 16, resb 1 +align 8, resb 1 fat32_bpb resb FAT32_bpb_t_size fat32_ebpb resb FAT32_ebpb_t_size -align 16, resb 1 +align 8, resb 1 fat32_nc_data resb 16 -align 16, resb 1 +align 8, resb 1 lba_packet resb LBAPkt_t_size -align 16, resb 1 +align 8, resb 1 fat32_state: resb FAT32_State_t_size -align 16, resb 1 +align 8, resb 1 SteviaInfo: resd 4 ; -; locals +; globals ; -boot_drive_ptr: +align 8, resb 1 +boot_drive: + resb 1 + +align 8, resb 1 +partition_offset: resw 1 -partition_offset_ptr: + +align 8, resb 1 +vbr_fat32_bpb_ptr: + resw 1 + +align 8, resb 1 +vbr_part_table_ptr: resw 1 ; diff --git a/src/vbr/vbr.nasm b/src/vbr/vbr.nasm index 729cc1e..d204995 100755 --- a/src/vbr/vbr.nasm +++ b/src/vbr/vbr.nasm @@ -152,10 +152,10 @@ main: call read_disk_raw add sp, 0xC .enter_stage2: - mov dl, byte [bp - 2] ; boot_drive - mov si, word [bp - 4] ; part_offset - mov bx, partition_table - mov dx, fat32_bpb + mov dl, byte [bp - 2] ; byte boot_drive + mov ax, word [bp - 4] ; word part_offset + mov si, partition_table ; ptr partition_table + mov di, fat32_bpb ; ptr fat32_bpb jmp word 0x0000:STAGE2_ENTRY ; ############### From 2a6792ae017b3e38a50e2b8e6f95036362e24253 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 19 Dec 2024 15:18:28 -0500 Subject: [PATCH 146/147] moved varibles passed from vbr to .data section this is to work around having to save them without .bss ready --- include/fat32/FAT32_SYS.inc | 4 +-- src/stage2/stage2.nasm | 67 ++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index e6b8355..d7920a9 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -234,7 +234,7 @@ NextCluster: mov dword [si + FAT32_NextClusterData_t.fat_sector], eax .load_fat_table: xor ax, ax - mov al, boot_drive + mov al, byte [boot_drive] push ax mov ax, 0x1 @@ -306,7 +306,7 @@ ReadFATCluster: print_string ReadFATCluster_INFO_cstr xor ax, ax - mov al, boot_drive + mov al, byte [boot_drive] push ax mov ax, 0x1 ; count = 1 diff --git a/src/stage2/stage2.nasm b/src/stage2/stage2.nasm index 834958f..89e55ce 100755 --- a/src/stage2/stage2.nasm +++ b/src/stage2/stage2.nasm @@ -56,12 +56,13 @@ ALIGN 4, db 0x90 init: cli ; We do not want to be interrupted - mov [vbr_part_table_ptr], bx ; pointer to partition_table - mov [vbr_fat32_bpb_ptr], dx ; pointer to fat32_bpb + ; these 4 are stored in the .data section and are effectivly const types + mov [vbr_part_table_ptr], si ; pointer to partition_table + mov [vbr_fat32_bpb_ptr], di ; pointer to fat32_bpb mov [boot_drive], dl ; copy boot_drive to globals mov [partition_offset], ax ; copy partition_offset to globals - mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment, excep es + mov ax, __STAGE2_SEGMENT ; set all our segments to the configured segment, except es mov ds, ax ; * mov fs, ax ; * mov gs, ax ; * @@ -135,19 +136,19 @@ main: ERROR STAGE2_SIGNATURE_MISSING .stage2_main: mov ax, PartTable_t_size + push ax ; len = PartTable_t_size + mov ax, word [vbr_part_table_ptr] ; src = ptr to vbr partition_table push ax - mov ax, word [vbr_part_table_ptr] ; ptr partition_table + mov ax, partition_table ; dst push ax - mov ax, partition_table - push ax - call kmemcpy ; copy partition table data + call kmemcpy ; copy partition table data to .data section in stage2 add sp, 0x6 - mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; size in byte + mov ax, (FAT32_bpb_t_size + FAT32_ebpb_t_size) ; len push ax - mov ax, word [vbr_fat32_bpb_ptr] + mov ax, word [vbr_fat32_bpb_ptr] ; src push ax - mov ax, fat32_bpb ; defined in memory.inc, destination + mov ax, fat32_bpb ; dst push ax call kmemcpy ; copy bpb & ebpb to memory add sp, 0x6 @@ -160,14 +161,14 @@ main: call EnableA20 print_string A20_Enabled_OK_cstr - ; enter unreal mode - call EnterUnrealMode - print_string UnrealMode_OK_cstr - ; get system memory map call GetMemoryMap print_string MemoryMap_OK_cstr + ; enter unreal mode + call EnterUnrealMode + print_string UnrealMode_OK_cstr + ; FAT Driver setup call InitFATDriver print_string InitFATSYS_OK_cstr @@ -400,6 +401,26 @@ define_cstr NewLine, "" define_str BootTarget, "BOOT BIN" +; +; pre-bss init globals (generally const...but there are exceptions) +; + +align 8, db 0x00 +boot_drive: + db 0x00 + +align 8, db 0x00 +partition_offset: + dw 0x0000 + +align 8, db 0x00 +vbr_fat32_bpb_ptr: + dw 0x0000 + +align 8, db 0x00 +vbr_part_table_ptr: + dw 0x0000 + ALIGN 16 IntToHex_table: db '0123456789ABCDEF' @@ -514,25 +535,9 @@ fat32_state: align 8, resb 1 SteviaInfo: resd 4 - ; -; globals +; post-bss init globals ; -align 8, resb 1 -boot_drive: - resb 1 - -align 8, resb 1 -partition_offset: - resw 1 - -align 8, resb 1 -vbr_fat32_bpb_ptr: - resw 1 - -align 8, resb 1 -vbr_part_table_ptr: - resw 1 ; ; large continuous allocations From 578e9934d8224a7dab4d10ef937fdc0e75aa0c24 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Thu, 19 Dec 2024 18:59:34 -0500 Subject: [PATCH 147/147] more bug catching after changing the location of data also cleanup comment from previous bug --- include/fat32/FAT32_SYS.inc | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/include/fat32/FAT32_SYS.inc b/include/fat32/FAT32_SYS.inc index d7920a9..e50af1f 100644 --- a/include/fat32/FAT32_SYS.inc +++ b/include/fat32/FAT32_SYS.inc @@ -38,7 +38,7 @@ InitFATDriver: sub sp, 0x6 .calc_active_part: - mov ax, word partition_offset + mov ax, word [partition_offset] mov dx, partition_table add dx, ax ; dx points to the partition that was booted from @@ -249,20 +249,6 @@ NextCluster: xor ax, ax push ax - ; BUG: something about this function causes this BIOS call to come back wrong - ; somehow the drive number is being read in wrong, but I can't find evidence of it being modified or writen - ; to memory incorrectly. - ; 00007109574i[BIOS ] Booting from 0000:7c00 - ; 00007123227i[CPU0 ] [7123227] Stopped on MAGIC BREAKPOINT - ; (0) Magic breakpoint - ; Next at t=7123227 - ; (0) [0x000000000502] 0000:0502 (unk. ctxt): cli ; fa - ; c - ; 00007252963i[BIOS ] int13_diskette: unsupported AH=42 - ; 00007253071i[CPU0 ] [7253071] Stopped on MAGIC BREAKPOINT - ; (0) Magic breakpoint - ; Next at t=7253071 - ; (0) [0x00000000095c] 0000:095c (unk. ctxt): mov al, 0x47 ; b047 call read_disk_raw add sp, 0xC ; uint8_t read_stage2_raw(uint16_t buf_segment, uint16_t buf_offset,